aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorBrian King <brking@linux.vnet.ibm.com>2013-04-12 09:25:16 -0400
committerJames Bottomley <JBottomley@Parallels.com>2013-05-02 14:55:14 -0400
commit93631b4aac7cac29a1ba9c0b849bf527b7e07028 (patch)
tree9e5f151601c817883c9e53964828cbf485717e11 /drivers/scsi
parentf8804b7239b27baca1ab44344318acb8fd55f9ae (diff)
[SCSI] ibmvfc: Support FAST_IO_FAIL in EH handlers
Adds support for receiving FAST_IO_FAIL from fc_block_scsi_eh when in error recovery. This fixes cases of devices being taken offline when they are no longer accessible on the fabric, preventing them from coming back online when the fabric recovers. Signed-off-by: Brian King <brking@linux.vnet.ibm.com> Acked-by: Robert Jennings <rcj@linux.vnet.ibm.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/ibmvscsi/ibmvfc.c69
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 **/
2388static int ibmvfc_eh_abort_handler(struct scsi_cmnd *cmd) 2388static 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 **/
2415static int ibmvfc_eh_device_reset_handler(struct scsi_cmnd *cmd) 2421static 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 **/
2453static 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 **/
2454static int ibmvfc_eh_target_reset_handler(struct scsi_cmnd *cmd) 2478static 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 **/
2481static int ibmvfc_eh_host_reset_handler(struct scsi_cmnd *cmd) 2512static 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