diff options
Diffstat (limited to 'drivers/scsi/ibmvscsi/ibmvfc.c')
-rw-r--r-- | drivers/scsi/ibmvscsi/ibmvfc.c | 380 |
1 files changed, 211 insertions, 169 deletions
diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c index bd96cecaa619..9f75a6d519a2 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc.c +++ b/drivers/scsi/ibmvscsi/ibmvfc.c | |||
@@ -433,6 +433,9 @@ static void ibmvfc_set_tgt_action(struct ibmvfc_target *tgt, | |||
433 | { | 433 | { |
434 | switch (tgt->action) { | 434 | switch (tgt->action) { |
435 | case IBMVFC_TGT_ACTION_DEL_RPORT: | 435 | case IBMVFC_TGT_ACTION_DEL_RPORT: |
436 | if (action == IBMVFC_TGT_ACTION_DELETED_RPORT) | ||
437 | tgt->action = action; | ||
438 | case IBMVFC_TGT_ACTION_DELETED_RPORT: | ||
436 | break; | 439 | break; |
437 | default: | 440 | default: |
438 | if (action == IBMVFC_TGT_ACTION_DEL_RPORT) | 441 | if (action == IBMVFC_TGT_ACTION_DEL_RPORT) |
@@ -2036,95 +2039,108 @@ static int ibmvfc_reset_device(struct scsi_device *sdev, int type, char *desc) | |||
2036 | } | 2039 | } |
2037 | 2040 | ||
2038 | /** | 2041 | /** |
2039 | * ibmvfc_abort_task_set - Abort outstanding commands to the device | 2042 | * ibmvfc_match_rport - Match function for specified remote port |
2040 | * @sdev: scsi device to abort commands | 2043 | * @evt: ibmvfc event struct |
2041 | * | 2044 | * @device: device to match (rport) |
2042 | * This sends an Abort Task Set to the VIOS for the specified device. This does | ||
2043 | * NOT send any cancel to the VIOS. That must be done separately. | ||
2044 | * | 2045 | * |
2045 | * Returns: | 2046 | * Returns: |
2046 | * 0 on success / other on failure | 2047 | * 1 if event matches rport / 0 if event does not match rport |
2047 | **/ | 2048 | **/ |
2048 | static int ibmvfc_abort_task_set(struct scsi_device *sdev) | 2049 | static int ibmvfc_match_rport(struct ibmvfc_event *evt, void *rport) |
2049 | { | 2050 | { |
2050 | struct ibmvfc_host *vhost = shost_priv(sdev->host); | 2051 | struct fc_rport *cmd_rport; |
2051 | struct fc_rport *rport = starget_to_rport(scsi_target(sdev)); | ||
2052 | struct ibmvfc_cmd *tmf; | ||
2053 | struct ibmvfc_event *evt, *found_evt; | ||
2054 | union ibmvfc_iu rsp_iu; | ||
2055 | struct ibmvfc_fcp_rsp *fc_rsp = &rsp_iu.cmd.rsp; | ||
2056 | int rsp_rc = -EBUSY; | ||
2057 | unsigned long flags; | ||
2058 | int rsp_code = 0; | ||
2059 | 2052 | ||
2060 | spin_lock_irqsave(vhost->host->host_lock, flags); | 2053 | if (evt->cmnd) { |
2061 | found_evt = NULL; | 2054 | cmd_rport = starget_to_rport(scsi_target(evt->cmnd->device)); |
2062 | list_for_each_entry(evt, &vhost->sent, queue) { | 2055 | if (cmd_rport == rport) |
2063 | if (evt->cmnd && evt->cmnd->device == sdev) { | 2056 | return 1; |
2064 | found_evt = evt; | ||
2065 | break; | ||
2066 | } | ||
2067 | } | ||
2068 | |||
2069 | if (!found_evt) { | ||
2070 | if (vhost->log_level > IBMVFC_DEFAULT_LOG_LEVEL) | ||
2071 | sdev_printk(KERN_INFO, sdev, "No events found to abort\n"); | ||
2072 | spin_unlock_irqrestore(vhost->host->host_lock, flags); | ||
2073 | return 0; | ||
2074 | } | ||
2075 | |||
2076 | if (vhost->state == IBMVFC_ACTIVE) { | ||
2077 | evt = ibmvfc_get_event(vhost); | ||
2078 | ibmvfc_init_event(evt, ibmvfc_sync_completion, IBMVFC_CMD_FORMAT); | ||
2079 | |||
2080 | tmf = &evt->iu.cmd; | ||
2081 | memset(tmf, 0, sizeof(*tmf)); | ||
2082 | tmf->resp.va = (u64)evt->crq.ioba + offsetof(struct ibmvfc_cmd, rsp); | ||
2083 | tmf->resp.len = sizeof(tmf->rsp); | ||
2084 | tmf->frame_type = IBMVFC_SCSI_FCP_TYPE; | ||
2085 | tmf->payload_len = sizeof(tmf->iu); | ||
2086 | tmf->resp_len = sizeof(tmf->rsp); | ||
2087 | tmf->cancel_key = (unsigned long)sdev->hostdata; | ||
2088 | tmf->tgt_scsi_id = rport->port_id; | ||
2089 | int_to_scsilun(sdev->lun, &tmf->iu.lun); | ||
2090 | tmf->flags = (IBMVFC_NO_MEM_DESC | IBMVFC_TMF); | ||
2091 | tmf->iu.tmf_flags = IBMVFC_ABORT_TASK_SET; | ||
2092 | evt->sync_iu = &rsp_iu; | ||
2093 | |||
2094 | init_completion(&evt->comp); | ||
2095 | rsp_rc = ibmvfc_send_event(evt, vhost, default_timeout); | ||
2096 | } | 2057 | } |
2058 | return 0; | ||
2059 | } | ||
2097 | 2060 | ||
2098 | 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 | } | ||
2099 | 2075 | ||
2100 | if (rsp_rc != 0) { | 2076 | /** |
2101 | sdev_printk(KERN_ERR, sdev, "Failed to send abort. rc=%d\n", rsp_rc); | 2077 | * ibmvfc_match_lun - Match function for specified LUN |
2102 | return -EIO; | 2078 | * @evt: ibmvfc event struct |
2103 | } | 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 | } | ||
2104 | 2090 | ||
2105 | sdev_printk(KERN_INFO, sdev, "Aborting outstanding commands\n"); | 2091 | /** |
2106 | 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; | ||
2107 | 2108 | ||
2108 | if (rsp_iu.cmd.status) | 2109 | ENTER; |
2109 | 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); | ||
2110 | 2120 | ||
2111 | if (rsp_code) { | 2121 | if (wait) { |
2112 | if (fc_rsp->flags & FCP_RSP_LEN_VALID) | 2122 | timeout = wait_for_completion_timeout(&comp, timeout); |
2113 | rsp_code = fc_rsp->data.info.rsp_code; | ||
2114 | 2123 | ||
2115 | sdev_printk(KERN_ERR, sdev, "Abort failed: %s (%x:%x) " | 2124 | if (!timeout) { |
2116 | "flags: %x fcp_rsp: %x, scsi_status: %x\n", | 2125 | wait = 0; |
2117 | ibmvfc_get_cmd_error(rsp_iu.cmd.status, rsp_iu.cmd.error), | 2126 | spin_lock_irqsave(vhost->host->host_lock, flags); |
2118 | rsp_iu.cmd.status, rsp_iu.cmd.error, fc_rsp->flags, rsp_code, | 2127 | list_for_each_entry(evt, &vhost->sent, queue) { |
2119 | fc_rsp->scsi_status); | 2128 | if (match(evt, device)) { |
2120 | rsp_rc = -EIO; | 2129 | evt->eh_comp = NULL; |
2121 | } else | 2130 | wait++; |
2122 | 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); | ||
2123 | 2141 | ||
2124 | spin_lock_irqsave(vhost->host->host_lock, flags); | 2142 | LEAVE; |
2125 | ibmvfc_free_event(evt); | 2143 | return SUCCESS; |
2126 | spin_unlock_irqrestore(vhost->host->host_lock, flags); | ||
2127 | return rsp_rc; | ||
2128 | } | 2144 | } |
2129 | 2145 | ||
2130 | /** | 2146 | /** |
@@ -2212,88 +2228,130 @@ static int ibmvfc_cancel_all(struct scsi_device *sdev, int type) | |||
2212 | } | 2228 | } |
2213 | 2229 | ||
2214 | /** | 2230 | /** |
2215 | * ibmvfc_match_target - Match function for specified target | 2231 | * ibmvfc_match_key - Match function for specified cancel key |
2216 | * @evt: ibmvfc event struct | 2232 | * @evt: ibmvfc event struct |
2217 | * @device: device to match (starget) | 2233 | * @key: cancel key to match |
2218 | * | 2234 | * |
2219 | * Returns: | 2235 | * Returns: |
2220 | * 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 |
2221 | **/ | 2237 | **/ |
2222 | static int ibmvfc_match_target(struct ibmvfc_event *evt, void *device) | 2238 | static int ibmvfc_match_key(struct ibmvfc_event *evt, void *key) |
2223 | { | 2239 | { |
2224 | if (evt->cmnd && scsi_target(evt->cmnd->device) == device) | 2240 | unsigned long cancel_key = (unsigned long)key; |
2225 | return 1; | ||
2226 | return 0; | ||
2227 | } | ||
2228 | 2241 | ||
2229 | /** | 2242 | if (evt->crq.format == IBMVFC_CMD_FORMAT && |
2230 | * ibmvfc_match_lun - Match function for specified LUN | 2243 | evt->iu.cmd.cancel_key == cancel_key) |
2231 | * @evt: ibmvfc event struct | ||
2232 | * @device: device to match (sdev) | ||
2233 | * | ||
2234 | * Returns: | ||
2235 | * 1 if event matches sdev / 0 if event does not match sdev | ||
2236 | **/ | ||
2237 | static int ibmvfc_match_lun(struct ibmvfc_event *evt, void *device) | ||
2238 | { | ||
2239 | if (evt->cmnd && evt->cmnd->device == device) | ||
2240 | return 1; | 2244 | return 1; |
2241 | return 0; | 2245 | return 0; |
2242 | } | 2246 | } |
2243 | 2247 | ||
2244 | /** | 2248 | /** |
2245 | * ibmvfc_wait_for_ops - Wait for ops to complete | 2249 | * ibmvfc_abort_task_set - Abort outstanding commands to the device |
2246 | * @vhost: ibmvfc host struct | 2250 | * @sdev: scsi device to abort commands |
2247 | * @device: device to match (starget or sdev) | 2251 | * |
2248 | * @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. | ||
2249 | * | 2254 | * |
2250 | * Returns: | 2255 | * Returns: |
2251 | * SUCCESS / FAILED | 2256 | * 0 on success / other on failure |
2252 | **/ | 2257 | **/ |
2253 | static int ibmvfc_wait_for_ops(struct ibmvfc_host *vhost, void *device, | 2258 | static int ibmvfc_abort_task_set(struct scsi_device *sdev) |
2254 | int (*match) (struct ibmvfc_event *, void *)) | ||
2255 | { | 2259 | { |
2256 | struct ibmvfc_event *evt; | 2260 | struct ibmvfc_host *vhost = shost_priv(sdev->host); |
2257 | DECLARE_COMPLETION_ONSTACK(comp); | 2261 | struct fc_rport *rport = starget_to_rport(scsi_target(sdev)); |
2258 | int wait; | 2262 | struct ibmvfc_cmd *tmf; |
2259 | unsigned long flags; | 2263 | struct ibmvfc_event *evt, *found_evt; |
2260 | 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; | ||
2261 | 2269 | ||
2262 | ENTER; | 2270 | spin_lock_irqsave(vhost->host->host_lock, flags); |
2263 | do { | 2271 | found_evt = NULL; |
2264 | wait = 0; | 2272 | list_for_each_entry(evt, &vhost->sent, queue) { |
2265 | spin_lock_irqsave(vhost->host->host_lock, flags); | 2273 | if (evt->cmnd && evt->cmnd->device == sdev) { |
2266 | list_for_each_entry(evt, &vhost->sent, queue) { | 2274 | found_evt = evt; |
2267 | if (match(evt, device)) { | 2275 | break; |
2268 | evt->eh_comp = ∁ | ||
2269 | wait++; | ||
2270 | } | ||
2271 | } | 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"); | ||
2272 | spin_unlock_irqrestore(vhost->host->host_lock, flags); | 2282 | spin_unlock_irqrestore(vhost->host->host_lock, flags); |
2283 | return 0; | ||
2284 | } | ||
2273 | 2285 | ||
2274 | if (wait) { | 2286 | if (vhost->state == IBMVFC_ACTIVE) { |
2275 | timeout = wait_for_completion_timeout(&comp, timeout); | 2287 | evt = ibmvfc_get_event(vhost); |
2288 | ibmvfc_init_event(evt, ibmvfc_sync_completion, IBMVFC_CMD_FORMAT); | ||
2276 | 2289 | ||
2277 | if (!timeout) { | 2290 | tmf = &evt->iu.cmd; |
2278 | wait = 0; | 2291 | memset(tmf, 0, sizeof(*tmf)); |
2279 | spin_lock_irqsave(vhost->host->host_lock, flags); | 2292 | tmf->resp.va = (u64)evt->crq.ioba + offsetof(struct ibmvfc_cmd, rsp); |
2280 | list_for_each_entry(evt, &vhost->sent, queue) { | 2293 | tmf->resp.len = sizeof(tmf->rsp); |
2281 | if (match(evt, device)) { | 2294 | tmf->frame_type = IBMVFC_SCSI_FCP_TYPE; |
2282 | evt->eh_comp = NULL; | 2295 | tmf->payload_len = sizeof(tmf->iu); |
2283 | wait++; | 2296 | tmf->resp_len = sizeof(tmf->rsp); |
2284 | } | 2297 | tmf->cancel_key = (unsigned long)sdev->hostdata; |
2285 | } | 2298 | tmf->tgt_scsi_id = rport->port_id; |
2286 | spin_unlock_irqrestore(vhost->host->host_lock, flags); | 2299 | int_to_scsilun(sdev->lun, &tmf->iu.lun); |
2287 | if (wait) | 2300 | tmf->flags = (IBMVFC_NO_MEM_DESC | IBMVFC_TMF); |
2288 | dev_err(vhost->dev, "Timed out waiting for aborted commands\n"); | 2301 | tmf->iu.tmf_flags = IBMVFC_ABORT_TASK_SET; |
2289 | LEAVE; | 2302 | evt->sync_iu = &rsp_iu; |
2290 | return wait ? FAILED : SUCCESS; | 2303 | |
2291 | } | 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; | ||
2292 | } | 2324 | } |
2293 | } while (wait); | ||
2294 | 2325 | ||
2295 | LEAVE; | 2326 | if (rc) { |
2296 | 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; | ||
2297 | } | 2355 | } |
2298 | 2356 | ||
2299 | /** | 2357 | /** |
@@ -2351,18 +2409,6 @@ static int ibmvfc_eh_device_reset_handler(struct scsi_cmnd *cmd) | |||
2351 | } | 2409 | } |
2352 | 2410 | ||
2353 | /** | 2411 | /** |
2354 | * ibmvfc_dev_cancel_all_abts - Device iterated cancel all function | ||
2355 | * @sdev: scsi device struct | ||
2356 | * @data: return code | ||
2357 | * | ||
2358 | **/ | ||
2359 | static void ibmvfc_dev_cancel_all_abts(struct scsi_device *sdev, void *data) | ||
2360 | { | ||
2361 | unsigned long *rc = data; | ||
2362 | *rc |= ibmvfc_cancel_all(sdev, IBMVFC_TMF_ABORT_TASK_SET); | ||
2363 | } | ||
2364 | |||
2365 | /** | ||
2366 | * ibmvfc_dev_cancel_all_reset - Device iterated cancel all function | 2412 | * ibmvfc_dev_cancel_all_reset - Device iterated cancel all function |
2367 | * @sdev: scsi device struct | 2413 | * @sdev: scsi device struct |
2368 | * @data: return code | 2414 | * @data: return code |
@@ -2375,18 +2421,6 @@ static void ibmvfc_dev_cancel_all_reset(struct scsi_device *sdev, void *data) | |||
2375 | } | 2421 | } |
2376 | 2422 | ||
2377 | /** | 2423 | /** |
2378 | * ibmvfc_dev_abort_all - Device iterated abort task set function | ||
2379 | * @sdev: scsi device struct | ||
2380 | * @data: return code | ||
2381 | * | ||
2382 | **/ | ||
2383 | static void ibmvfc_dev_abort_all(struct scsi_device *sdev, void *data) | ||
2384 | { | ||
2385 | unsigned long *rc = data; | ||
2386 | *rc |= ibmvfc_abort_task_set(sdev); | ||
2387 | } | ||
2388 | |||
2389 | /** | ||
2390 | * ibmvfc_eh_target_reset_handler - Reset the target | 2424 | * ibmvfc_eh_target_reset_handler - Reset the target |
2391 | * @cmd: scsi command struct | 2425 | * @cmd: scsi command struct |
2392 | * | 2426 | * |
@@ -2440,19 +2474,22 @@ static int ibmvfc_eh_host_reset_handler(struct scsi_cmnd *cmd) | |||
2440 | **/ | 2474 | **/ |
2441 | static void ibmvfc_terminate_rport_io(struct fc_rport *rport) | 2475 | static void ibmvfc_terminate_rport_io(struct fc_rport *rport) |
2442 | { | 2476 | { |
2443 | struct scsi_target *starget = to_scsi_target(&rport->dev); | 2477 | struct Scsi_Host *shost = rport_to_shost(rport); |
2444 | struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); | ||
2445 | struct ibmvfc_host *vhost = shost_priv(shost); | 2478 | struct ibmvfc_host *vhost = shost_priv(shost); |
2446 | unsigned long cancel_rc = 0; | 2479 | struct fc_rport *dev_rport; |
2447 | unsigned long abort_rc = 0; | 2480 | struct scsi_device *sdev; |
2448 | int rc = FAILED; | 2481 | unsigned long rc; |
2449 | 2482 | ||
2450 | ENTER; | 2483 | ENTER; |
2451 | starget_for_each_device(starget, &cancel_rc, ibmvfc_dev_cancel_all_abts); | 2484 | shost_for_each_device(sdev, shost) { |
2452 | 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 | } | ||
2453 | 2491 | ||
2454 | if (!cancel_rc && !abort_rc) | 2492 | rc = ibmvfc_wait_for_ops(vhost, rport, ibmvfc_match_rport); |
2455 | rc = ibmvfc_wait_for_ops(vhost, starget, ibmvfc_match_target); | ||
2456 | 2493 | ||
2457 | if (rc == FAILED) | 2494 | if (rc == FAILED) |
2458 | ibmvfc_issue_fc_host_lip(shost); | 2495 | ibmvfc_issue_fc_host_lip(shost); |
@@ -4193,11 +4230,15 @@ static void ibmvfc_tgt_add_rport(struct ibmvfc_target *tgt) | |||
4193 | if (rport && tgt->action == IBMVFC_TGT_ACTION_DEL_RPORT) { | 4230 | if (rport && tgt->action == IBMVFC_TGT_ACTION_DEL_RPORT) { |
4194 | tgt_dbg(tgt, "Deleting rport\n"); | 4231 | tgt_dbg(tgt, "Deleting rport\n"); |
4195 | list_del(&tgt->queue); | 4232 | list_del(&tgt->queue); |
4233 | ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DELETED_RPORT); | ||
4196 | spin_unlock_irqrestore(vhost->host->host_lock, flags); | 4234 | spin_unlock_irqrestore(vhost->host->host_lock, flags); |
4197 | fc_remote_port_delete(rport); | 4235 | fc_remote_port_delete(rport); |
4198 | del_timer_sync(&tgt->timer); | 4236 | del_timer_sync(&tgt->timer); |
4199 | kref_put(&tgt->kref, ibmvfc_release_tgt); | 4237 | kref_put(&tgt->kref, ibmvfc_release_tgt); |
4200 | return; | 4238 | return; |
4239 | } else if (rport && tgt->action == IBMVFC_TGT_ACTION_DELETED_RPORT) { | ||
4240 | spin_unlock_irqrestore(vhost->host->host_lock, flags); | ||
4241 | return; | ||
4201 | } | 4242 | } |
4202 | 4243 | ||
4203 | if (rport) { | 4244 | if (rport) { |
@@ -4297,6 +4338,7 @@ static void ibmvfc_do_work(struct ibmvfc_host *vhost) | |||
4297 | rport = tgt->rport; | 4338 | rport = tgt->rport; |
4298 | tgt->rport = NULL; | 4339 | tgt->rport = NULL; |
4299 | list_del(&tgt->queue); | 4340 | list_del(&tgt->queue); |
4341 | ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DELETED_RPORT); | ||
4300 | spin_unlock_irqrestore(vhost->host->host_lock, flags); | 4342 | spin_unlock_irqrestore(vhost->host->host_lock, flags); |
4301 | if (rport) | 4343 | if (rport) |
4302 | fc_remote_port_delete(rport); | 4344 | fc_remote_port_delete(rport); |