diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/scsi/ibmvscsi/ibmvfc.c | 69 |
1 files changed, 52 insertions, 17 deletions
diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c index e65262070749..1221b760f49e 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc.c +++ b/drivers/scsi/ibmvscsi/ibmvfc.c | |||
@@ -2383,24 +2383,30 @@ out: | |||
2383 | * @cmd: scsi command to abort | 2383 | * @cmd: scsi command to abort |
2384 | * | 2384 | * |
2385 | * Returns: | 2385 | * Returns: |
2386 | * SUCCESS / FAILED | 2386 | * SUCCESS / FAST_IO_FAIL / FAILED |
2387 | **/ | 2387 | **/ |
2388 | static int ibmvfc_eh_abort_handler(struct scsi_cmnd *cmd) | 2388 | static int ibmvfc_eh_abort_handler(struct scsi_cmnd *cmd) |
2389 | { | 2389 | { |
2390 | struct scsi_device *sdev = cmd->device; | 2390 | struct scsi_device *sdev = cmd->device; |
2391 | struct ibmvfc_host *vhost = shost_priv(sdev->host); | 2391 | struct ibmvfc_host *vhost = shost_priv(sdev->host); |
2392 | int cancel_rc, abort_rc; | 2392 | int cancel_rc, block_rc, abort_rc = 0; |
2393 | int rc = FAILED; | 2393 | int rc = FAILED; |
2394 | 2394 | ||
2395 | ENTER; | 2395 | ENTER; |
2396 | fc_block_scsi_eh(cmd); | 2396 | block_rc = fc_block_scsi_eh(cmd); |
2397 | ibmvfc_wait_while_resetting(vhost); | 2397 | ibmvfc_wait_while_resetting(vhost); |
2398 | cancel_rc = ibmvfc_cancel_all(sdev, IBMVFC_TMF_ABORT_TASK_SET); | 2398 | if (block_rc != FAST_IO_FAIL) { |
2399 | abort_rc = ibmvfc_abort_task_set(sdev); | 2399 | cancel_rc = ibmvfc_cancel_all(sdev, IBMVFC_TMF_ABORT_TASK_SET); |
2400 | abort_rc = ibmvfc_abort_task_set(sdev); | ||
2401 | } else | ||
2402 | cancel_rc = ibmvfc_cancel_all(sdev, 0); | ||
2400 | 2403 | ||
2401 | if (!cancel_rc && !abort_rc) | 2404 | if (!cancel_rc && !abort_rc) |
2402 | rc = ibmvfc_wait_for_ops(vhost, sdev, ibmvfc_match_lun); | 2405 | rc = ibmvfc_wait_for_ops(vhost, sdev, ibmvfc_match_lun); |
2403 | 2406 | ||
2407 | if (block_rc == FAST_IO_FAIL && rc != FAILED) | ||
2408 | rc = FAST_IO_FAIL; | ||
2409 | |||
2404 | LEAVE; | 2410 | LEAVE; |
2405 | return rc; | 2411 | return rc; |
2406 | } | 2412 | } |
@@ -2410,29 +2416,47 @@ static int ibmvfc_eh_abort_handler(struct scsi_cmnd *cmd) | |||
2410 | * @cmd: scsi command struct | 2416 | * @cmd: scsi command struct |
2411 | * | 2417 | * |
2412 | * Returns: | 2418 | * Returns: |
2413 | * SUCCESS / FAILED | 2419 | * SUCCESS / FAST_IO_FAIL / FAILED |
2414 | **/ | 2420 | **/ |
2415 | static int ibmvfc_eh_device_reset_handler(struct scsi_cmnd *cmd) | 2421 | static int ibmvfc_eh_device_reset_handler(struct scsi_cmnd *cmd) |
2416 | { | 2422 | { |
2417 | struct scsi_device *sdev = cmd->device; | 2423 | struct scsi_device *sdev = cmd->device; |
2418 | struct ibmvfc_host *vhost = shost_priv(sdev->host); | 2424 | struct ibmvfc_host *vhost = shost_priv(sdev->host); |
2419 | int cancel_rc, reset_rc; | 2425 | int cancel_rc, block_rc, reset_rc = 0; |
2420 | int rc = FAILED; | 2426 | int rc = FAILED; |
2421 | 2427 | ||
2422 | ENTER; | 2428 | ENTER; |
2423 | fc_block_scsi_eh(cmd); | 2429 | block_rc = fc_block_scsi_eh(cmd); |
2424 | ibmvfc_wait_while_resetting(vhost); | 2430 | ibmvfc_wait_while_resetting(vhost); |
2425 | cancel_rc = ibmvfc_cancel_all(sdev, IBMVFC_TMF_LUN_RESET); | 2431 | if (block_rc != FAST_IO_FAIL) { |
2426 | reset_rc = ibmvfc_reset_device(sdev, IBMVFC_LUN_RESET, "LUN"); | 2432 | cancel_rc = ibmvfc_cancel_all(sdev, IBMVFC_TMF_LUN_RESET); |
2433 | reset_rc = ibmvfc_reset_device(sdev, IBMVFC_LUN_RESET, "LUN"); | ||
2434 | } else | ||
2435 | cancel_rc = ibmvfc_cancel_all(sdev, 0); | ||
2427 | 2436 | ||
2428 | if (!cancel_rc && !reset_rc) | 2437 | if (!cancel_rc && !reset_rc) |
2429 | rc = ibmvfc_wait_for_ops(vhost, sdev, ibmvfc_match_lun); | 2438 | rc = ibmvfc_wait_for_ops(vhost, sdev, ibmvfc_match_lun); |
2430 | 2439 | ||
2440 | if (block_rc == FAST_IO_FAIL && rc != FAILED) | ||
2441 | rc = FAST_IO_FAIL; | ||
2442 | |||
2431 | LEAVE; | 2443 | LEAVE; |
2432 | return rc; | 2444 | return rc; |
2433 | } | 2445 | } |
2434 | 2446 | ||
2435 | /** | 2447 | /** |
2448 | * ibmvfc_dev_cancel_all_noreset - Device iterated cancel all function | ||
2449 | * @sdev: scsi device struct | ||
2450 | * @data: return code | ||
2451 | * | ||
2452 | **/ | ||
2453 | static void ibmvfc_dev_cancel_all_noreset(struct scsi_device *sdev, void *data) | ||
2454 | { | ||
2455 | unsigned long *rc = data; | ||
2456 | *rc |= ibmvfc_cancel_all(sdev, 0); | ||
2457 | } | ||
2458 | |||
2459 | /** | ||
2436 | * ibmvfc_dev_cancel_all_reset - Device iterated cancel all function | 2460 | * ibmvfc_dev_cancel_all_reset - Device iterated cancel all function |
2437 | * @sdev: scsi device struct | 2461 | * @sdev: scsi device struct |
2438 | * @data: return code | 2462 | * @data: return code |
@@ -2449,26 +2473,33 @@ static void ibmvfc_dev_cancel_all_reset(struct scsi_device *sdev, void *data) | |||
2449 | * @cmd: scsi command struct | 2473 | * @cmd: scsi command struct |
2450 | * | 2474 | * |
2451 | * Returns: | 2475 | * Returns: |
2452 | * SUCCESS / FAILED | 2476 | * SUCCESS / FAST_IO_FAIL / FAILED |
2453 | **/ | 2477 | **/ |
2454 | static int ibmvfc_eh_target_reset_handler(struct scsi_cmnd *cmd) | 2478 | static int ibmvfc_eh_target_reset_handler(struct scsi_cmnd *cmd) |
2455 | { | 2479 | { |
2456 | struct scsi_device *sdev = cmd->device; | 2480 | struct scsi_device *sdev = cmd->device; |
2457 | struct ibmvfc_host *vhost = shost_priv(sdev->host); | 2481 | struct ibmvfc_host *vhost = shost_priv(sdev->host); |
2458 | struct scsi_target *starget = scsi_target(sdev); | 2482 | struct scsi_target *starget = scsi_target(sdev); |
2459 | int reset_rc; | 2483 | int block_rc; |
2484 | int reset_rc = 0; | ||
2460 | int rc = FAILED; | 2485 | int rc = FAILED; |
2461 | unsigned long cancel_rc = 0; | 2486 | unsigned long cancel_rc = 0; |
2462 | 2487 | ||
2463 | ENTER; | 2488 | ENTER; |
2464 | fc_block_scsi_eh(cmd); | 2489 | block_rc = fc_block_scsi_eh(cmd); |
2465 | ibmvfc_wait_while_resetting(vhost); | 2490 | ibmvfc_wait_while_resetting(vhost); |
2466 | starget_for_each_device(starget, &cancel_rc, ibmvfc_dev_cancel_all_reset); | 2491 | if (block_rc != FAST_IO_FAIL) { |
2467 | reset_rc = ibmvfc_reset_device(sdev, IBMVFC_TARGET_RESET, "target"); | 2492 | starget_for_each_device(starget, &cancel_rc, ibmvfc_dev_cancel_all_reset); |
2493 | reset_rc = ibmvfc_reset_device(sdev, IBMVFC_TARGET_RESET, "target"); | ||
2494 | } else | ||
2495 | starget_for_each_device(starget, &cancel_rc, ibmvfc_dev_cancel_all_noreset); | ||
2468 | 2496 | ||
2469 | if (!cancel_rc && !reset_rc) | 2497 | if (!cancel_rc && !reset_rc) |
2470 | rc = ibmvfc_wait_for_ops(vhost, starget, ibmvfc_match_target); | 2498 | rc = ibmvfc_wait_for_ops(vhost, starget, ibmvfc_match_target); |
2471 | 2499 | ||
2500 | if (block_rc == FAST_IO_FAIL && rc != FAILED) | ||
2501 | rc = FAST_IO_FAIL; | ||
2502 | |||
2472 | LEAVE; | 2503 | LEAVE; |
2473 | return rc; | 2504 | return rc; |
2474 | } | 2505 | } |
@@ -2480,12 +2511,16 @@ static int ibmvfc_eh_target_reset_handler(struct scsi_cmnd *cmd) | |||
2480 | **/ | 2511 | **/ |
2481 | static int ibmvfc_eh_host_reset_handler(struct scsi_cmnd *cmd) | 2512 | static int ibmvfc_eh_host_reset_handler(struct scsi_cmnd *cmd) |
2482 | { | 2513 | { |
2483 | int rc; | 2514 | int rc, block_rc; |
2484 | struct ibmvfc_host *vhost = shost_priv(cmd->device->host); | 2515 | struct ibmvfc_host *vhost = shost_priv(cmd->device->host); |
2485 | 2516 | ||
2486 | fc_block_scsi_eh(cmd); | 2517 | block_rc = fc_block_scsi_eh(cmd); |
2487 | dev_err(vhost->dev, "Resetting connection due to error recovery\n"); | 2518 | dev_err(vhost->dev, "Resetting connection due to error recovery\n"); |
2488 | rc = ibmvfc_issue_fc_host_lip(vhost->host); | 2519 | rc = ibmvfc_issue_fc_host_lip(vhost->host); |
2520 | |||
2521 | if (block_rc == FAST_IO_FAIL) | ||
2522 | return FAST_IO_FAIL; | ||
2523 | |||
2489 | return rc ? FAILED : SUCCESS; | 2524 | return rc ? FAILED : SUCCESS; |
2490 | } | 2525 | } |
2491 | 2526 | ||