ibmvfc: Support FAST_IO_FAIL in EH handlers (bug#812224).
[opensuse:kernel-source.git] / patches.drivers / ibmvfc-Support-FAST_IO_FAIL-in-EH-handlers.patch
1 From: Brian King <brking@linux.vnet.ibm.com>
2 Date: Thu, 25 Apr 2013 08:24:41 +0200
3 Subject: ibmvfc: Support FAST_IO_FAIL in EH handlers
4 References: bug#812224
5 Patch-Mainline: posted to linux-scsi
6
7 Adds support for receiving FAST_IO_FAIL from fc_block_scsi_eh
8 when in error recovery. This fixes cases of devices being
9 taken offline when they are no longer accessible on the fabric,
10 preventing them from coming back online when the fabric recovers.
11
12 Signed-off-by: Brian King <brking@linux.vnet.ibm.com>
13 Acked-by: Hannes Reinecke <hare@suse.de>
14 ---
15  drivers/scsi/ibmvscsi/ibmvfc.c | 87 ++++++++++++++++++++++++++++--------------
16  1 file changed, 58 insertions(+), 29 deletions(-)
17
18 diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c
19 index 7bcb183..6e4977f 100644
20 --- a/drivers/scsi/ibmvscsi/ibmvfc.c
21 +++ b/drivers/scsi/ibmvscsi/ibmvfc.c
22 @@ -2383,26 +2383,30 @@ out:
23   * @cmd:       scsi command to abort
24   *
25   * Returns:
26 - *     SUCCESS / FAILED
27 + *     SUCCESS / FAST_IO_FAIL / FAILED
28   **/
29  static int ibmvfc_eh_abort_handler(struct scsi_cmnd *cmd)
30  {
31         struct scsi_device *sdev = cmd->device;
32         struct ibmvfc_host *vhost = shost_priv(sdev->host);
33 -       int cancel_rc, abort_rc;
34 -       int rc;
35 +       int cancel_rc, block_rc, abort_rc = 0;
36 +       int rc = FAILED;
37  
38         ENTER;
39 -       rc = fc_block_scsi_eh(cmd);
40 -       if (rc != SUCCESS)
41 -               goto out;
42 +       block_rc = fc_block_scsi_eh(cmd);
43         ibmvfc_wait_while_resetting(vhost);
44 -       cancel_rc = ibmvfc_cancel_all(sdev, IBMVFC_TMF_ABORT_TASK_SET);
45 -       abort_rc = ibmvfc_abort_task_set(sdev);
46 +       if (block_rc != FAST_IO_FAIL) {
47 +               cancel_rc = ibmvfc_cancel_all(sdev, IBMVFC_TMF_ABORT_TASK_SET);
48 +               abort_rc = ibmvfc_abort_task_set(sdev);
49 +       } else
50 +               cancel_rc = ibmvfc_cancel_all(sdev, 0);
51  
52         if (!cancel_rc && !abort_rc)
53                 rc = ibmvfc_wait_for_ops(vhost, sdev, ibmvfc_match_lun);
54 -out:
55 +
56 +       if (block_rc == FAST_IO_FAIL && rc != FAILED)
57 +               rc = FAST_IO_FAIL;
58 +
59         LEAVE;
60         return rc;
61  }
62 @@ -2412,31 +2416,47 @@ out:
63   * @cmd:       scsi command struct
64   *
65   * Returns:
66 - *     SUCCESS / FAILED
67 + *     SUCCESS / FAST_IO_FAIL / FAILED
68   **/
69  static int ibmvfc_eh_device_reset_handler(struct scsi_cmnd *cmd)
70  {
71         struct scsi_device *sdev = cmd->device;
72         struct ibmvfc_host *vhost = shost_priv(sdev->host);
73 -       int cancel_rc, reset_rc;
74 -       int rc;
75 +       int cancel_rc, block_rc, reset_rc = 0;
76 +       int rc = FAILED;
77  
78         ENTER;
79 -       rc = fc_block_scsi_eh(cmd);
80 -       if (rc != SUCCESS)
81 -               goto out;
82 +       block_rc = fc_block_scsi_eh(cmd);
83         ibmvfc_wait_while_resetting(vhost);
84 -       cancel_rc = ibmvfc_cancel_all(sdev, IBMVFC_TMF_LUN_RESET);
85 -       reset_rc = ibmvfc_reset_device(sdev, IBMVFC_LUN_RESET, "LUN");
86 +       if (block_rc != FAST_IO_FAIL) {
87 +               cancel_rc = ibmvfc_cancel_all(sdev, IBMVFC_TMF_LUN_RESET);
88 +               reset_rc = ibmvfc_reset_device(sdev, IBMVFC_LUN_RESET, "LUN");
89 +       } else
90 +               cancel_rc = ibmvfc_cancel_all(sdev, 0);
91  
92         if (!cancel_rc && !reset_rc)
93                 rc = ibmvfc_wait_for_ops(vhost, sdev, ibmvfc_match_lun);
94 -out:
95 +
96 +       if (block_rc == FAST_IO_FAIL && rc != FAILED)
97 +               rc = FAST_IO_FAIL;
98 +
99         LEAVE;
100         return rc;
101  }
102  
103  /**
104 + * ibmvfc_dev_cancel_all_noreset - Device iterated cancel all function
105 + * @sdev:      scsi device struct
106 + * @data:      return code
107 + *
108 + **/
109 +static void ibmvfc_dev_cancel_all_noreset(struct scsi_device *sdev, void *data)
110 +{
111 +       unsigned long *rc = data;
112 +       *rc |= ibmvfc_cancel_all(sdev, 0);
113 +}
114 +
115 +/**
116   * ibmvfc_dev_cancel_all_reset - Device iterated cancel all function
117   * @sdev:      scsi device struct
118   * @data:      return code
119 @@ -2453,28 +2473,33 @@ static void ibmvfc_dev_cancel_all_reset(struct scsi_device *sdev, void *data)
120   * @cmd:       scsi command struct
121   *
122   * Returns:
123 - *     SUCCESS / FAILED
124 + *     SUCCESS / FAST_IO_FAIL / FAILED
125   **/
126  static int ibmvfc_eh_target_reset_handler(struct scsi_cmnd *cmd)
127  {
128         struct scsi_device *sdev = cmd->device;
129         struct ibmvfc_host *vhost = shost_priv(sdev->host);
130         struct scsi_target *starget = scsi_target(sdev);
131 -       int reset_rc;
132 -       int rc;
133 +       int block_rc;
134 +       int reset_rc = 0;
135 +       int rc = FAILED;
136         unsigned long cancel_rc = 0;
137  
138         ENTER;
139 -       rc = fc_block_scsi_eh(cmd);
140 -       if (rc != SUCCESS)
141 -               goto out;
142 +       block_rc = fc_block_scsi_eh(cmd);
143         ibmvfc_wait_while_resetting(vhost);
144 -       starget_for_each_device(starget, &cancel_rc, ibmvfc_dev_cancel_all_reset);
145 -       reset_rc = ibmvfc_reset_device(sdev, IBMVFC_TARGET_RESET, "target");
146 +       if (block_rc != FAST_IO_FAIL) {
147 +               starget_for_each_device(starget, &cancel_rc, ibmvfc_dev_cancel_all_reset);
148 +               reset_rc = ibmvfc_reset_device(sdev, IBMVFC_TARGET_RESET, "target");
149 +       } else
150 +               starget_for_each_device(starget, &cancel_rc, ibmvfc_dev_cancel_all_noreset);
151  
152         if (!cancel_rc && !reset_rc)
153                 rc = ibmvfc_wait_for_ops(vhost, starget, ibmvfc_match_target);
154 -out:
155 +
156 +       if (block_rc == FAST_IO_FAIL && rc != FAILED)
157 +               rc = FAST_IO_FAIL;
158 +
159         LEAVE;
160         return rc;
161  }
162 @@ -2486,12 +2511,16 @@ out:
163   **/
164  static int ibmvfc_eh_host_reset_handler(struct scsi_cmnd *cmd)
165  {
166 -       int rc;
167 +       int rc, block_rc;
168         struct ibmvfc_host *vhost = shost_priv(cmd->device->host);
169  
170 -       fc_block_scsi_eh(cmd);
171 +       block_rc = fc_block_scsi_eh(cmd);
172         dev_err(vhost->dev, "Resetting connection due to error recovery\n");
173         rc = ibmvfc_issue_fc_host_lip(vhost->host);
174 +
175 +       if (block_rc == FAST_IO_FAIL)
176 +               return FAST_IO_FAIL;
177 +
178         return rc ? FAILED : SUCCESS;
179  }
180  
181 -- 
182 1.7.12.4
183