diff options
author | Brian King <brking@linux.vnet.ibm.com> | 2010-08-05 17:38:34 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2010-08-06 13:26:36 -0400 |
commit | d2fab5cf3979c55f802c96616daf96e9e8de1c80 (patch) | |
tree | 84f395993608c7bdc75c81ebf98746d2099e3cb3 /drivers/scsi/ibmvscsi/ibmvfc.c | |
parent | d5da3040d798df4bbb62579b97f8b6b83749da22 (diff) |
[SCSI] ibmvfc: Fix terminate_rport_io
The ibmvfc driver was incorrectly obtaining a scsi_target pointer
from an fc_rport. The way it is coded ensures that ibmvfc's
terminate_rport_io handler does absolutely nothing. Fix this up
to iterate through affected devices differently, sending cancel
and abort task set as appropriate. Without this patch,
fast_io_fail_tmo is broken for ibmvfc.
Signed-off-by: Brian King <brking@linux.vnet.ibm.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi/ibmvscsi/ibmvfc.c')
-rw-r--r-- | drivers/scsi/ibmvscsi/ibmvfc.c | 372 |
1 files changed, 203 insertions, 169 deletions
diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c index a13db5908426..9f75a6d519a2 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc.c +++ b/drivers/scsi/ibmvscsi/ibmvfc.c | |||
@@ -2039,95 +2039,108 @@ static int ibmvfc_reset_device(struct scsi_device *sdev, int type, char *desc) | |||
2039 | } | 2039 | } |
2040 | 2040 | ||
2041 | /** | 2041 | /** |
2042 | * ibmvfc_abort_task_set - Abort outstanding commands to the device | 2042 | * ibmvfc_match_rport - Match function for specified remote port |
2043 | * @sdev: scsi device to abort commands | 2043 | * @evt: ibmvfc event struct |
2044 | * | 2044 | * @device: device to match (rport) |
2045 | * This sends an Abort Task Set to the VIOS for the specified device. This does | ||
2046 | * NOT send any cancel to the VIOS. That must be done separately. | ||
2047 | * | 2045 | * |
2048 | * Returns: | 2046 | * Returns: |
2049 | * 0 on success / other on failure | 2047 | * 1 if event matches rport / 0 if event does not match rport |
2050 | **/ | 2048 | **/ |
2051 | static int ibmvfc_abort_task_set(struct scsi_device *sdev) | 2049 | static int ibmvfc_match_rport(struct ibmvfc_event *evt, void *rport) |
2052 | { | 2050 | { |
2053 | struct ibmvfc_host *vhost = shost_priv(sdev->host); | 2051 | struct fc_rport *cmd_rport; |
2054 | struct fc_rport *rport = starget_to_rport(scsi_target(sdev)); | ||
2055 | struct ibmvfc_cmd *tmf; | ||
2056 | struct ibmvfc_event *evt, *found_evt; | ||
2057 | union ibmvfc_iu rsp_iu; | ||
2058 | struct ibmvfc_fcp_rsp *fc_rsp = &rsp_iu.cmd.rsp; | ||
2059 | int rsp_rc = -EBUSY; | ||
2060 | unsigned long flags; | ||
2061 | int rsp_code = 0; | ||
2062 | 2052 | ||
2063 | spin_lock_irqsave(vhost->host->host_lock, flags); | 2053 | if (evt->cmnd) { |
2064 | found_evt = NULL; | 2054 | cmd_rport = starget_to_rport(scsi_target(evt->cmnd->device)); |
2065 | list_for_each_entry(evt, &vhost->sent, queue) { | 2055 | if (cmd_rport == rport) |
2066 | if (evt->cmnd && evt->cmnd->device == sdev) { | 2056 | return 1; |
2067 | found_evt = evt; | ||
2068 | break; | ||
2069 | } | ||
2070 | } | ||
2071 | |||
2072 | if (!found_evt) { | ||
2073 | if (vhost->log_level > IBMVFC_DEFAULT_LOG_LEVEL) | ||
2074 | sdev_printk(KERN_INFO, sdev, "No events found to abort\n"); | ||
2075 | spin_unlock_irqrestore(vhost->host->host_lock, flags); | ||
2076 | return 0; | ||
2077 | } | ||
2078 | |||
2079 | if (vhost->state == IBMVFC_ACTIVE) { | ||
2080 | evt = ibmvfc_get_event(vhost); | ||
2081 | ibmvfc_init_event(evt, ibmvfc_sync_completion, IBMVFC_CMD_FORMAT); | ||
2082 | |||
2083 | tmf = &evt->iu.cmd; | ||
2084 | memset(tmf, 0, sizeof(*tmf)); | ||
2085 | tmf->resp.va = (u64)evt->crq.ioba + offsetof(struct ibmvfc_cmd, rsp); | ||
2086 | tmf->resp.len = sizeof(tmf->rsp); | ||
2087 | tmf->frame_type = IBMVFC_SCSI_FCP_TYPE; | ||
2088 | tmf->payload_len = sizeof(tmf->iu); | ||
2089 | tmf->resp_len = sizeof(tmf->rsp); | ||
2090 | tmf->cancel_key = (unsigned long)sdev->hostdata; | ||
2091 | tmf->tgt_scsi_id = rport->port_id; | ||
2092 | int_to_scsilun(sdev->lun, &tmf->iu.lun); | ||
2093 | tmf->flags = (IBMVFC_NO_MEM_DESC | IBMVFC_TMF); | ||
2094 | tmf->iu.tmf_flags = IBMVFC_ABORT_TASK_SET; | ||
2095 | evt->sync_iu = &rsp_iu; | ||
2096 | |||
2097 | init_completion(&evt->comp); | ||
2098 | rsp_rc = ibmvfc_send_event(evt, vhost, default_timeout); | ||
2099 | } | 2057 | } |
2058 | return 0; | ||
2059 | } | ||
2100 | 2060 | ||
2101 | spin_unlock_irqrestore(vhost->host->host_lock, flags); | 2061 | /** |
2062 | * ibmvfc_match_target - Match function for specified target | ||
2063 | * @evt: ibmvfc event struct | ||
2064 | * @device: device to match (starget) | ||
2065 | * | ||
2066 | * Returns: | ||
2067 | * 1 if event matches starget / 0 if event does not match starget | ||
2068 | **/ | ||
2069 | static int ibmvfc_match_target(struct ibmvfc_event *evt, void *device) | ||
2070 | { | ||
2071 | if (evt->cmnd && scsi_target(evt->cmnd->device) == device) | ||
2072 | return 1; | ||
2073 | return 0; | ||
2074 | } | ||
2102 | 2075 | ||
2103 | if (rsp_rc != 0) { | 2076 | /** |
2104 | sdev_printk(KERN_ERR, sdev, "Failed to send abort. rc=%d\n", rsp_rc); | 2077 | * ibmvfc_match_lun - Match function for specified LUN |
2105 | return -EIO; | 2078 | * @evt: ibmvfc event struct |
2106 | } | 2079 | * @device: device to match (sdev) |
2080 | * | ||
2081 | * Returns: | ||
2082 | * 1 if event matches sdev / 0 if event does not match sdev | ||
2083 | **/ | ||
2084 | static int ibmvfc_match_lun(struct ibmvfc_event *evt, void *device) | ||
2085 | { | ||
2086 | if (evt->cmnd && evt->cmnd->device == device) | ||
2087 | return 1; | ||
2088 | return 0; | ||
2089 | } | ||
2107 | 2090 | ||
2108 | sdev_printk(KERN_INFO, sdev, "Aborting outstanding commands\n"); | 2091 | /** |
2109 | wait_for_completion(&evt->comp); | 2092 | * ibmvfc_wait_for_ops - Wait for ops to complete |
2093 | * @vhost: ibmvfc host struct | ||
2094 | * @device: device to match (starget or sdev) | ||
2095 | * @match: match function | ||
2096 | * | ||
2097 | * Returns: | ||
2098 | * SUCCESS / FAILED | ||
2099 | **/ | ||
2100 | static int ibmvfc_wait_for_ops(struct ibmvfc_host *vhost, void *device, | ||
2101 | int (*match) (struct ibmvfc_event *, void *)) | ||
2102 | { | ||
2103 | struct ibmvfc_event *evt; | ||
2104 | DECLARE_COMPLETION_ONSTACK(comp); | ||
2105 | int wait; | ||
2106 | unsigned long flags; | ||
2107 | signed long timeout = IBMVFC_ABORT_WAIT_TIMEOUT * HZ; | ||
2110 | 2108 | ||
2111 | if (rsp_iu.cmd.status) | 2109 | ENTER; |
2112 | rsp_code = ibmvfc_get_err_result(&rsp_iu.cmd); | 2110 | do { |
2111 | wait = 0; | ||
2112 | spin_lock_irqsave(vhost->host->host_lock, flags); | ||
2113 | list_for_each_entry(evt, &vhost->sent, queue) { | ||
2114 | if (match(evt, device)) { | ||
2115 | evt->eh_comp = ∁ | ||
2116 | wait++; | ||
2117 | } | ||
2118 | } | ||
2119 | spin_unlock_irqrestore(vhost->host->host_lock, flags); | ||
2113 | 2120 | ||
2114 | if (rsp_code) { | 2121 | if (wait) { |
2115 | if (fc_rsp->flags & FCP_RSP_LEN_VALID) | 2122 | timeout = wait_for_completion_timeout(&comp, timeout); |
2116 | rsp_code = fc_rsp->data.info.rsp_code; | ||
2117 | 2123 | ||
2118 | sdev_printk(KERN_ERR, sdev, "Abort failed: %s (%x:%x) " | 2124 | if (!timeout) { |
2119 | "flags: %x fcp_rsp: %x, scsi_status: %x\n", | 2125 | wait = 0; |
2120 | ibmvfc_get_cmd_error(rsp_iu.cmd.status, rsp_iu.cmd.error), | 2126 | spin_lock_irqsave(vhost->host->host_lock, flags); |
2121 | rsp_iu.cmd.status, rsp_iu.cmd.error, fc_rsp->flags, rsp_code, | 2127 | list_for_each_entry(evt, &vhost->sent, queue) { |
2122 | fc_rsp->scsi_status); | 2128 | if (match(evt, device)) { |
2123 | rsp_rc = -EIO; | 2129 | evt->eh_comp = NULL; |
2124 | } else | 2130 | wait++; |
2125 | sdev_printk(KERN_INFO, sdev, "Abort successful\n"); | 2131 | } |
2132 | } | ||
2133 | spin_unlock_irqrestore(vhost->host->host_lock, flags); | ||
2134 | if (wait) | ||
2135 | dev_err(vhost->dev, "Timed out waiting for aborted commands\n"); | ||
2136 | LEAVE; | ||
2137 | return wait ? FAILED : SUCCESS; | ||
2138 | } | ||
2139 | } | ||
2140 | } while (wait); | ||
2126 | 2141 | ||
2127 | spin_lock_irqsave(vhost->host->host_lock, flags); | 2142 | LEAVE; |
2128 | ibmvfc_free_event(evt); | 2143 | return SUCCESS; |
2129 | spin_unlock_irqrestore(vhost->host->host_lock, flags); | ||
2130 | return rsp_rc; | ||
2131 | } | 2144 | } |
2132 | 2145 | ||
2133 | /** | 2146 | /** |
@@ -2215,88 +2228,130 @@ static int ibmvfc_cancel_all(struct scsi_device *sdev, int type) | |||
2215 | } | 2228 | } |
2216 | 2229 | ||
2217 | /** | 2230 | /** |
2218 | * ibmvfc_match_target - Match function for specified target | 2231 | * ibmvfc_match_key - Match function for specified cancel key |
2219 | * @evt: ibmvfc event struct | 2232 | * @evt: ibmvfc event struct |
2220 | * @device: device to match (starget) | 2233 | * @key: cancel key to match |
2221 | * | 2234 | * |
2222 | * Returns: | 2235 | * Returns: |
2223 | * 1 if event matches starget / 0 if event does not match starget | 2236 | * 1 if event matches key / 0 if event does not match key |
2224 | **/ | 2237 | **/ |
2225 | static int ibmvfc_match_target(struct ibmvfc_event *evt, void *device) | 2238 | static int ibmvfc_match_key(struct ibmvfc_event *evt, void *key) |
2226 | { | 2239 | { |
2227 | if (evt->cmnd && scsi_target(evt->cmnd->device) == device) | 2240 | unsigned long cancel_key = (unsigned long)key; |
2228 | return 1; | ||
2229 | return 0; | ||
2230 | } | ||
2231 | 2241 | ||
2232 | /** | 2242 | if (evt->crq.format == IBMVFC_CMD_FORMAT && |
2233 | * ibmvfc_match_lun - Match function for specified LUN | 2243 | evt->iu.cmd.cancel_key == cancel_key) |
2234 | * @evt: ibmvfc event struct | ||
2235 | * @device: device to match (sdev) | ||
2236 | * | ||
2237 | * Returns: | ||
2238 | * 1 if event matches sdev / 0 if event does not match sdev | ||
2239 | **/ | ||
2240 | static int ibmvfc_match_lun(struct ibmvfc_event *evt, void *device) | ||
2241 | { | ||
2242 | if (evt->cmnd && evt->cmnd->device == device) | ||
2243 | return 1; | 2244 | return 1; |
2244 | return 0; | 2245 | return 0; |
2245 | } | 2246 | } |
2246 | 2247 | ||
2247 | /** | 2248 | /** |
2248 | * ibmvfc_wait_for_ops - Wait for ops to complete | 2249 | * ibmvfc_abort_task_set - Abort outstanding commands to the device |
2249 | * @vhost: ibmvfc host struct | 2250 | * @sdev: scsi device to abort commands |
2250 | * @device: device to match (starget or sdev) | 2251 | * |
2251 | * @match: match function | 2252 | * This sends an Abort Task Set to the VIOS for the specified device. This does |
2253 | * NOT send any cancel to the VIOS. That must be done separately. | ||
2252 | * | 2254 | * |
2253 | * Returns: | 2255 | * Returns: |
2254 | * SUCCESS / FAILED | 2256 | * 0 on success / other on failure |
2255 | **/ | 2257 | **/ |
2256 | static int ibmvfc_wait_for_ops(struct ibmvfc_host *vhost, void *device, | 2258 | static int ibmvfc_abort_task_set(struct scsi_device *sdev) |
2257 | int (*match) (struct ibmvfc_event *, void *)) | ||
2258 | { | 2259 | { |
2259 | struct ibmvfc_event *evt; | 2260 | struct ibmvfc_host *vhost = shost_priv(sdev->host); |
2260 | DECLARE_COMPLETION_ONSTACK(comp); | 2261 | struct fc_rport *rport = starget_to_rport(scsi_target(sdev)); |
2261 | int wait; | 2262 | struct ibmvfc_cmd *tmf; |
2262 | unsigned long flags; | 2263 | struct ibmvfc_event *evt, *found_evt; |
2263 | signed long timeout = IBMVFC_ABORT_WAIT_TIMEOUT * HZ; | 2264 | union ibmvfc_iu rsp_iu; |
2265 | struct ibmvfc_fcp_rsp *fc_rsp = &rsp_iu.cmd.rsp; | ||
2266 | int rc, rsp_rc = -EBUSY; | ||
2267 | unsigned long flags, timeout = IBMVFC_ABORT_TIMEOUT; | ||
2268 | int rsp_code = 0; | ||
2264 | 2269 | ||
2265 | ENTER; | 2270 | spin_lock_irqsave(vhost->host->host_lock, flags); |
2266 | do { | 2271 | found_evt = NULL; |
2267 | wait = 0; | 2272 | list_for_each_entry(evt, &vhost->sent, queue) { |
2268 | spin_lock_irqsave(vhost->host->host_lock, flags); | 2273 | if (evt->cmnd && evt->cmnd->device == sdev) { |
2269 | list_for_each_entry(evt, &vhost->sent, queue) { | 2274 | found_evt = evt; |
2270 | if (match(evt, device)) { | 2275 | break; |
2271 | evt->eh_comp = ∁ | ||
2272 | wait++; | ||
2273 | } | ||
2274 | } | 2276 | } |
2277 | } | ||
2278 | |||
2279 | if (!found_evt) { | ||
2280 | if (vhost->log_level > IBMVFC_DEFAULT_LOG_LEVEL) | ||
2281 | sdev_printk(KERN_INFO, sdev, "No events found to abort\n"); | ||
2275 | spin_unlock_irqrestore(vhost->host->host_lock, flags); | 2282 | spin_unlock_irqrestore(vhost->host->host_lock, flags); |
2283 | return 0; | ||
2284 | } | ||
2276 | 2285 | ||
2277 | if (wait) { | 2286 | if (vhost->state == IBMVFC_ACTIVE) { |
2278 | timeout = wait_for_completion_timeout(&comp, timeout); | 2287 | evt = ibmvfc_get_event(vhost); |
2288 | ibmvfc_init_event(evt, ibmvfc_sync_completion, IBMVFC_CMD_FORMAT); | ||
2279 | 2289 | ||
2280 | if (!timeout) { | 2290 | tmf = &evt->iu.cmd; |
2281 | wait = 0; | 2291 | memset(tmf, 0, sizeof(*tmf)); |
2282 | spin_lock_irqsave(vhost->host->host_lock, flags); | 2292 | tmf->resp.va = (u64)evt->crq.ioba + offsetof(struct ibmvfc_cmd, rsp); |
2283 | list_for_each_entry(evt, &vhost->sent, queue) { | 2293 | tmf->resp.len = sizeof(tmf->rsp); |
2284 | if (match(evt, device)) { | 2294 | tmf->frame_type = IBMVFC_SCSI_FCP_TYPE; |
2285 | evt->eh_comp = NULL; | 2295 | tmf->payload_len = sizeof(tmf->iu); |
2286 | wait++; | 2296 | tmf->resp_len = sizeof(tmf->rsp); |
2287 | } | 2297 | tmf->cancel_key = (unsigned long)sdev->hostdata; |
2288 | } | 2298 | tmf->tgt_scsi_id = rport->port_id; |
2289 | spin_unlock_irqrestore(vhost->host->host_lock, flags); | 2299 | int_to_scsilun(sdev->lun, &tmf->iu.lun); |
2290 | if (wait) | 2300 | tmf->flags = (IBMVFC_NO_MEM_DESC | IBMVFC_TMF); |
2291 | dev_err(vhost->dev, "Timed out waiting for aborted commands\n"); | 2301 | tmf->iu.tmf_flags = IBMVFC_ABORT_TASK_SET; |
2292 | LEAVE; | 2302 | evt->sync_iu = &rsp_iu; |
2293 | return wait ? FAILED : SUCCESS; | 2303 | |
2294 | } | 2304 | init_completion(&evt->comp); |
2305 | rsp_rc = ibmvfc_send_event(evt, vhost, default_timeout); | ||
2306 | } | ||
2307 | |||
2308 | spin_unlock_irqrestore(vhost->host->host_lock, flags); | ||
2309 | |||
2310 | if (rsp_rc != 0) { | ||
2311 | sdev_printk(KERN_ERR, sdev, "Failed to send abort. rc=%d\n", rsp_rc); | ||
2312 | return -EIO; | ||
2313 | } | ||
2314 | |||
2315 | sdev_printk(KERN_INFO, sdev, "Aborting outstanding commands\n"); | ||
2316 | timeout = wait_for_completion_timeout(&evt->comp, timeout); | ||
2317 | |||
2318 | if (!timeout) { | ||
2319 | rc = ibmvfc_cancel_all(sdev, IBMVFC_TMF_ABORT_TASK_SET); | ||
2320 | if (!rc) { | ||
2321 | rc = ibmvfc_wait_for_ops(vhost, sdev->hostdata, ibmvfc_match_key); | ||
2322 | if (rc == SUCCESS) | ||
2323 | rc = 0; | ||
2295 | } | 2324 | } |
2296 | } while (wait); | ||
2297 | 2325 | ||
2298 | LEAVE; | 2326 | if (rc) { |
2299 | return SUCCESS; | 2327 | sdev_printk(KERN_INFO, sdev, "Cancel failed, resetting host\n"); |
2328 | ibmvfc_reset_host(vhost); | ||
2329 | rsp_rc = 0; | ||
2330 | goto out; | ||
2331 | } | ||
2332 | } | ||
2333 | |||
2334 | if (rsp_iu.cmd.status) | ||
2335 | rsp_code = ibmvfc_get_err_result(&rsp_iu.cmd); | ||
2336 | |||
2337 | if (rsp_code) { | ||
2338 | if (fc_rsp->flags & FCP_RSP_LEN_VALID) | ||
2339 | rsp_code = fc_rsp->data.info.rsp_code; | ||
2340 | |||
2341 | sdev_printk(KERN_ERR, sdev, "Abort failed: %s (%x:%x) " | ||
2342 | "flags: %x fcp_rsp: %x, scsi_status: %x\n", | ||
2343 | ibmvfc_get_cmd_error(rsp_iu.cmd.status, rsp_iu.cmd.error), | ||
2344 | rsp_iu.cmd.status, rsp_iu.cmd.error, fc_rsp->flags, rsp_code, | ||
2345 | fc_rsp->scsi_status); | ||
2346 | rsp_rc = -EIO; | ||
2347 | } else | ||
2348 | sdev_printk(KERN_INFO, sdev, "Abort successful\n"); | ||
2349 | |||
2350 | out: | ||
2351 | spin_lock_irqsave(vhost->host->host_lock, flags); | ||
2352 | ibmvfc_free_event(evt); | ||
2353 | spin_unlock_irqrestore(vhost->host->host_lock, flags); | ||
2354 | return rsp_rc; | ||
2300 | } | 2355 | } |
2301 | 2356 | ||
2302 | /** | 2357 | /** |
@@ -2354,18 +2409,6 @@ static int ibmvfc_eh_device_reset_handler(struct scsi_cmnd *cmd) | |||
2354 | } | 2409 | } |
2355 | 2410 | ||
2356 | /** | 2411 | /** |
2357 | * ibmvfc_dev_cancel_all_abts - Device iterated cancel all function | ||
2358 | * @sdev: scsi device struct | ||
2359 | * @data: return code | ||
2360 | * | ||
2361 | **/ | ||
2362 | static void ibmvfc_dev_cancel_all_abts(struct scsi_device *sdev, void *data) | ||
2363 | { | ||
2364 | unsigned long *rc = data; | ||
2365 | *rc |= ibmvfc_cancel_all(sdev, IBMVFC_TMF_ABORT_TASK_SET); | ||
2366 | } | ||
2367 | |||
2368 | /** | ||
2369 | * ibmvfc_dev_cancel_all_reset - Device iterated cancel all function | 2412 | * ibmvfc_dev_cancel_all_reset - Device iterated cancel all function |
2370 | * @sdev: scsi device struct | 2413 | * @sdev: scsi device struct |
2371 | * @data: return code | 2414 | * @data: return code |
@@ -2378,18 +2421,6 @@ static void ibmvfc_dev_cancel_all_reset(struct scsi_device *sdev, void *data) | |||
2378 | } | 2421 | } |
2379 | 2422 | ||
2380 | /** | 2423 | /** |
2381 | * ibmvfc_dev_abort_all - Device iterated abort task set function | ||
2382 | * @sdev: scsi device struct | ||
2383 | * @data: return code | ||
2384 | * | ||
2385 | **/ | ||
2386 | static void ibmvfc_dev_abort_all(struct scsi_device *sdev, void *data) | ||
2387 | { | ||
2388 | unsigned long *rc = data; | ||
2389 | *rc |= ibmvfc_abort_task_set(sdev); | ||
2390 | } | ||
2391 | |||
2392 | /** | ||
2393 | * ibmvfc_eh_target_reset_handler - Reset the target | 2424 | * ibmvfc_eh_target_reset_handler - Reset the target |
2394 | * @cmd: scsi command struct | 2425 | * @cmd: scsi command struct |
2395 | * | 2426 | * |
@@ -2443,19 +2474,22 @@ static int ibmvfc_eh_host_reset_handler(struct scsi_cmnd *cmd) | |||
2443 | **/ | 2474 | **/ |
2444 | static void ibmvfc_terminate_rport_io(struct fc_rport *rport) | 2475 | static void ibmvfc_terminate_rport_io(struct fc_rport *rport) |
2445 | { | 2476 | { |
2446 | struct scsi_target *starget = to_scsi_target(&rport->dev); | 2477 | struct Scsi_Host *shost = rport_to_shost(rport); |
2447 | struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); | ||
2448 | struct ibmvfc_host *vhost = shost_priv(shost); | 2478 | struct ibmvfc_host *vhost = shost_priv(shost); |
2449 | unsigned long cancel_rc = 0; | 2479 | struct fc_rport *dev_rport; |
2450 | unsigned long abort_rc = 0; | 2480 | struct scsi_device *sdev; |
2451 | int rc = FAILED; | 2481 | unsigned long rc; |
2452 | 2482 | ||
2453 | ENTER; | 2483 | ENTER; |
2454 | starget_for_each_device(starget, &cancel_rc, ibmvfc_dev_cancel_all_abts); | 2484 | shost_for_each_device(sdev, shost) { |
2455 | starget_for_each_device(starget, &abort_rc, ibmvfc_dev_abort_all); | 2485 | dev_rport = starget_to_rport(scsi_target(sdev)); |
2486 | if (dev_rport != rport) | ||
2487 | continue; | ||
2488 | ibmvfc_cancel_all(sdev, IBMVFC_TMF_ABORT_TASK_SET); | ||
2489 | ibmvfc_abort_task_set(sdev); | ||
2490 | } | ||
2456 | 2491 | ||
2457 | if (!cancel_rc && !abort_rc) | 2492 | rc = ibmvfc_wait_for_ops(vhost, rport, ibmvfc_match_rport); |
2458 | rc = ibmvfc_wait_for_ops(vhost, starget, ibmvfc_match_target); | ||
2459 | 2493 | ||
2460 | if (rc == FAILED) | 2494 | if (rc == FAILED) |
2461 | ibmvfc_issue_fc_host_lip(shost); | 2495 | ibmvfc_issue_fc_host_lip(shost); |