diff options
Diffstat (limited to 'drivers/scsi/libsas')
-rw-r--r-- | drivers/scsi/libsas/sas_scsi_host.c | 37 |
1 files changed, 36 insertions, 1 deletions
diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c index f90c332474c8..d0c04ebeb8b0 100644 --- a/drivers/scsi/libsas/sas_scsi_host.c +++ b/drivers/scsi/libsas/sas_scsi_host.c | |||
@@ -389,6 +389,19 @@ static int sas_recover_I_T(struct domain_device *dev) | |||
389 | return res; | 389 | return res; |
390 | } | 390 | } |
391 | 391 | ||
392 | static int eh_reset_phy_helper(struct sas_phy *phy) | ||
393 | { | ||
394 | int tmf_resp; | ||
395 | |||
396 | tmf_resp = sas_phy_reset(phy, 1); | ||
397 | if (tmf_resp) | ||
398 | SAS_DPRINTK("Hard reset of phy %d failed 0x%x\n", | ||
399 | phy->identify.phy_identifier, | ||
400 | tmf_resp); | ||
401 | |||
402 | return tmf_resp; | ||
403 | } | ||
404 | |||
392 | void sas_scsi_recover_host(struct Scsi_Host *shost) | 405 | void sas_scsi_recover_host(struct Scsi_Host *shost) |
393 | { | 406 | { |
394 | struct sas_ha_struct *ha = SHOST_TO_SAS_HA(shost); | 407 | struct sas_ha_struct *ha = SHOST_TO_SAS_HA(shost); |
@@ -396,8 +409,9 @@ void sas_scsi_recover_host(struct Scsi_Host *shost) | |||
396 | LIST_HEAD(error_q); | 409 | LIST_HEAD(error_q); |
397 | struct scsi_cmnd *cmd, *n; | 410 | struct scsi_cmnd *cmd, *n; |
398 | enum task_disposition res = TASK_IS_DONE; | 411 | enum task_disposition res = TASK_IS_DONE; |
399 | int tmf_resp; | 412 | int tmf_resp, need_reset; |
400 | struct sas_internal *i = to_sas_internal(shost->transportt); | 413 | struct sas_internal *i = to_sas_internal(shost->transportt); |
414 | struct sas_phy *task_sas_phy = NULL; | ||
401 | 415 | ||
402 | spin_lock_irqsave(shost->host_lock, flags); | 416 | spin_lock_irqsave(shost->host_lock, flags); |
403 | list_splice_init(&shost->eh_cmd_q, &error_q); | 417 | list_splice_init(&shost->eh_cmd_q, &error_q); |
@@ -418,6 +432,13 @@ Again: | |||
418 | SAS_DPRINTK("%s: taskless cmd?!\n", __FUNCTION__); | 432 | SAS_DPRINTK("%s: taskless cmd?!\n", __FUNCTION__); |
419 | continue; | 433 | continue; |
420 | } | 434 | } |
435 | |||
436 | spin_lock_irqsave(&task->task_state_lock, flags); | ||
437 | need_reset = task->task_state_flags & SAS_TASK_NEED_DEV_RESET; | ||
438 | if (need_reset) | ||
439 | task_sas_phy = task->dev->port->phy; | ||
440 | spin_unlock_irqrestore(&task->task_state_lock, flags); | ||
441 | |||
421 | SAS_DPRINTK("trying to find task 0x%p\n", task); | 442 | SAS_DPRINTK("trying to find task 0x%p\n", task); |
422 | res = sas_scsi_find_task(task); | 443 | res = sas_scsi_find_task(task); |
423 | 444 | ||
@@ -428,11 +449,15 @@ Again: | |||
428 | SAS_DPRINTK("%s: task 0x%p is done\n", __FUNCTION__, | 449 | SAS_DPRINTK("%s: task 0x%p is done\n", __FUNCTION__, |
429 | task); | 450 | task); |
430 | task->task_done(task); | 451 | task->task_done(task); |
452 | if (need_reset) | ||
453 | eh_reset_phy_helper(task_sas_phy); | ||
431 | continue; | 454 | continue; |
432 | case TASK_IS_ABORTED: | 455 | case TASK_IS_ABORTED: |
433 | SAS_DPRINTK("%s: task 0x%p is aborted\n", | 456 | SAS_DPRINTK("%s: task 0x%p is aborted\n", |
434 | __FUNCTION__, task); | 457 | __FUNCTION__, task); |
435 | task->task_done(task); | 458 | task->task_done(task); |
459 | if (need_reset) | ||
460 | eh_reset_phy_helper(task_sas_phy); | ||
436 | continue; | 461 | continue; |
437 | case TASK_IS_AT_LU: | 462 | case TASK_IS_AT_LU: |
438 | SAS_DPRINTK("task 0x%p is at LU: lu recover\n", task); | 463 | SAS_DPRINTK("task 0x%p is at LU: lu recover\n", task); |
@@ -443,6 +468,8 @@ Again: | |||
443 | SAS_ADDR(task->dev), | 468 | SAS_ADDR(task->dev), |
444 | cmd->device->lun); | 469 | cmd->device->lun); |
445 | task->task_done(task); | 470 | task->task_done(task); |
471 | if (need_reset) | ||
472 | eh_reset_phy_helper(task_sas_phy); | ||
446 | sas_scsi_clear_queue_lu(&error_q, cmd); | 473 | sas_scsi_clear_queue_lu(&error_q, cmd); |
447 | goto Again; | 474 | goto Again; |
448 | } | 475 | } |
@@ -455,6 +482,8 @@ Again: | |||
455 | SAS_DPRINTK("I_T %016llx recovered\n", | 482 | SAS_DPRINTK("I_T %016llx recovered\n", |
456 | SAS_ADDR(task->dev->sas_addr)); | 483 | SAS_ADDR(task->dev->sas_addr)); |
457 | task->task_done(task); | 484 | task->task_done(task); |
485 | if (need_reset) | ||
486 | eh_reset_phy_helper(task_sas_phy); | ||
458 | sas_scsi_clear_queue_I_T(&error_q, task->dev); | 487 | sas_scsi_clear_queue_I_T(&error_q, task->dev); |
459 | goto Again; | 488 | goto Again; |
460 | } | 489 | } |
@@ -468,6 +497,8 @@ Again: | |||
468 | SAS_DPRINTK("clear nexus port:%d " | 497 | SAS_DPRINTK("clear nexus port:%d " |
469 | "succeeded\n", port->id); | 498 | "succeeded\n", port->id); |
470 | task->task_done(task); | 499 | task->task_done(task); |
500 | if (need_reset) | ||
501 | eh_reset_phy_helper(task_sas_phy); | ||
471 | sas_scsi_clear_queue_port(&error_q, | 502 | sas_scsi_clear_queue_port(&error_q, |
472 | port); | 503 | port); |
473 | goto Again; | 504 | goto Again; |
@@ -480,6 +511,8 @@ Again: | |||
480 | SAS_DPRINTK("clear nexus ha " | 511 | SAS_DPRINTK("clear nexus ha " |
481 | "succeeded\n"); | 512 | "succeeded\n"); |
482 | task->task_done(task); | 513 | task->task_done(task); |
514 | if (need_reset) | ||
515 | eh_reset_phy_helper(task_sas_phy); | ||
483 | goto out; | 516 | goto out; |
484 | } | 517 | } |
485 | } | 518 | } |
@@ -493,6 +526,8 @@ Again: | |||
493 | cmd->device->lun); | 526 | cmd->device->lun); |
494 | 527 | ||
495 | task->task_done(task); | 528 | task->task_done(task); |
529 | if (need_reset) | ||
530 | eh_reset_phy_helper(task_sas_phy); | ||
496 | goto clear_q; | 531 | goto clear_q; |
497 | } | 532 | } |
498 | } | 533 | } |