diff options
Diffstat (limited to 'drivers/scsi/libsas/sas_scsi_host.c')
-rw-r--r-- | drivers/scsi/libsas/sas_scsi_host.c | 34 |
1 files changed, 15 insertions, 19 deletions
diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c index 704ea06a6e50..1f8241563c6c 100644 --- a/drivers/scsi/libsas/sas_scsi_host.c +++ b/drivers/scsi/libsas/sas_scsi_host.c | |||
@@ -434,7 +434,7 @@ static int sas_recover_I_T(struct domain_device *dev) | |||
434 | } | 434 | } |
435 | 435 | ||
436 | /* Find the sas_phy that's attached to this device */ | 436 | /* Find the sas_phy that's attached to this device */ |
437 | static struct sas_phy *find_local_sas_phy(struct domain_device *dev) | 437 | struct sas_phy *sas_find_local_phy(struct domain_device *dev) |
438 | { | 438 | { |
439 | struct domain_device *pdev = dev->parent; | 439 | struct domain_device *pdev = dev->parent; |
440 | struct ex_phy *exphy = NULL; | 440 | struct ex_phy *exphy = NULL; |
@@ -456,6 +456,7 @@ static struct sas_phy *find_local_sas_phy(struct domain_device *dev) | |||
456 | BUG_ON(!exphy); | 456 | BUG_ON(!exphy); |
457 | return exphy->phy; | 457 | return exphy->phy; |
458 | } | 458 | } |
459 | EXPORT_SYMBOL_GPL(sas_find_local_phy); | ||
459 | 460 | ||
460 | /* Attempt to send a LUN reset message to a device */ | 461 | /* Attempt to send a LUN reset message to a device */ |
461 | int sas_eh_device_reset_handler(struct scsi_cmnd *cmd) | 462 | int sas_eh_device_reset_handler(struct scsi_cmnd *cmd) |
@@ -482,7 +483,7 @@ int sas_eh_device_reset_handler(struct scsi_cmnd *cmd) | |||
482 | int sas_eh_bus_reset_handler(struct scsi_cmnd *cmd) | 483 | int sas_eh_bus_reset_handler(struct scsi_cmnd *cmd) |
483 | { | 484 | { |
484 | struct domain_device *dev = cmd_to_domain_dev(cmd); | 485 | struct domain_device *dev = cmd_to_domain_dev(cmd); |
485 | struct sas_phy *phy = find_local_sas_phy(dev); | 486 | struct sas_phy *phy = sas_find_local_phy(dev); |
486 | int res; | 487 | int res; |
487 | 488 | ||
488 | res = sas_phy_reset(phy, 1); | 489 | res = sas_phy_reset(phy, 1); |
@@ -497,10 +498,10 @@ int sas_eh_bus_reset_handler(struct scsi_cmnd *cmd) | |||
497 | } | 498 | } |
498 | 499 | ||
499 | /* Try to reset a device */ | 500 | /* Try to reset a device */ |
500 | static int try_to_reset_cmd_device(struct Scsi_Host *shost, | 501 | static int try_to_reset_cmd_device(struct scsi_cmnd *cmd) |
501 | struct scsi_cmnd *cmd) | ||
502 | { | 502 | { |
503 | int res; | 503 | int res; |
504 | struct Scsi_Host *shost = cmd->device->host; | ||
504 | 505 | ||
505 | if (!shost->hostt->eh_device_reset_handler) | 506 | if (!shost->hostt->eh_device_reset_handler) |
506 | goto try_bus_reset; | 507 | goto try_bus_reset; |
@@ -540,6 +541,12 @@ Again: | |||
540 | need_reset = task->task_state_flags & SAS_TASK_NEED_DEV_RESET; | 541 | need_reset = task->task_state_flags & SAS_TASK_NEED_DEV_RESET; |
541 | spin_unlock_irqrestore(&task->task_state_lock, flags); | 542 | spin_unlock_irqrestore(&task->task_state_lock, flags); |
542 | 543 | ||
544 | if (need_reset) { | ||
545 | SAS_DPRINTK("%s: task 0x%p requests reset\n", | ||
546 | __FUNCTION__, task); | ||
547 | goto reset; | ||
548 | } | ||
549 | |||
543 | SAS_DPRINTK("trying to find task 0x%p\n", task); | 550 | SAS_DPRINTK("trying to find task 0x%p\n", task); |
544 | res = sas_scsi_find_task(task); | 551 | res = sas_scsi_find_task(task); |
545 | 552 | ||
@@ -550,18 +557,15 @@ Again: | |||
550 | SAS_DPRINTK("%s: task 0x%p is done\n", __FUNCTION__, | 557 | SAS_DPRINTK("%s: task 0x%p is done\n", __FUNCTION__, |
551 | task); | 558 | task); |
552 | sas_eh_finish_cmd(cmd); | 559 | sas_eh_finish_cmd(cmd); |
553 | if (need_reset) | ||
554 | try_to_reset_cmd_device(shost, cmd); | ||
555 | continue; | 560 | continue; |
556 | case TASK_IS_ABORTED: | 561 | case TASK_IS_ABORTED: |
557 | SAS_DPRINTK("%s: task 0x%p is aborted\n", | 562 | SAS_DPRINTK("%s: task 0x%p is aborted\n", |
558 | __FUNCTION__, task); | 563 | __FUNCTION__, task); |
559 | sas_eh_finish_cmd(cmd); | 564 | sas_eh_finish_cmd(cmd); |
560 | if (need_reset) | ||
561 | try_to_reset_cmd_device(shost, cmd); | ||
562 | continue; | 565 | continue; |
563 | case TASK_IS_AT_LU: | 566 | case TASK_IS_AT_LU: |
564 | SAS_DPRINTK("task 0x%p is at LU: lu recover\n", task); | 567 | SAS_DPRINTK("task 0x%p is at LU: lu recover\n", task); |
568 | reset: | ||
565 | tmf_resp = sas_recover_lu(task->dev, cmd); | 569 | tmf_resp = sas_recover_lu(task->dev, cmd); |
566 | if (tmf_resp == TMF_RESP_FUNC_COMPLETE) { | 570 | if (tmf_resp == TMF_RESP_FUNC_COMPLETE) { |
567 | SAS_DPRINTK("dev %016llx LU %x is " | 571 | SAS_DPRINTK("dev %016llx LU %x is " |
@@ -569,8 +573,6 @@ Again: | |||
569 | SAS_ADDR(task->dev), | 573 | SAS_ADDR(task->dev), |
570 | cmd->device->lun); | 574 | cmd->device->lun); |
571 | sas_eh_finish_cmd(cmd); | 575 | sas_eh_finish_cmd(cmd); |
572 | if (need_reset) | ||
573 | try_to_reset_cmd_device(shost, cmd); | ||
574 | sas_scsi_clear_queue_lu(work_q, cmd); | 576 | sas_scsi_clear_queue_lu(work_q, cmd); |
575 | goto Again; | 577 | goto Again; |
576 | } | 578 | } |
@@ -581,15 +583,15 @@ Again: | |||
581 | task); | 583 | task); |
582 | tmf_resp = sas_recover_I_T(task->dev); | 584 | tmf_resp = sas_recover_I_T(task->dev); |
583 | if (tmf_resp == TMF_RESP_FUNC_COMPLETE) { | 585 | if (tmf_resp == TMF_RESP_FUNC_COMPLETE) { |
586 | struct domain_device *dev = task->dev; | ||
584 | SAS_DPRINTK("I_T %016llx recovered\n", | 587 | SAS_DPRINTK("I_T %016llx recovered\n", |
585 | SAS_ADDR(task->dev->sas_addr)); | 588 | SAS_ADDR(task->dev->sas_addr)); |
586 | sas_eh_finish_cmd(cmd); | 589 | sas_eh_finish_cmd(cmd); |
587 | if (need_reset) | 590 | sas_scsi_clear_queue_I_T(work_q, dev); |
588 | try_to_reset_cmd_device(shost, cmd); | ||
589 | sas_scsi_clear_queue_I_T(work_q, task->dev); | ||
590 | goto Again; | 591 | goto Again; |
591 | } | 592 | } |
592 | /* Hammer time :-) */ | 593 | /* Hammer time :-) */ |
594 | try_to_reset_cmd_device(cmd); | ||
593 | if (i->dft->lldd_clear_nexus_port) { | 595 | if (i->dft->lldd_clear_nexus_port) { |
594 | struct asd_sas_port *port = task->dev->port; | 596 | struct asd_sas_port *port = task->dev->port; |
595 | SAS_DPRINTK("clearing nexus for port:%d\n", | 597 | SAS_DPRINTK("clearing nexus for port:%d\n", |
@@ -599,8 +601,6 @@ Again: | |||
599 | SAS_DPRINTK("clear nexus port:%d " | 601 | SAS_DPRINTK("clear nexus port:%d " |
600 | "succeeded\n", port->id); | 602 | "succeeded\n", port->id); |
601 | sas_eh_finish_cmd(cmd); | 603 | sas_eh_finish_cmd(cmd); |
602 | if (need_reset) | ||
603 | try_to_reset_cmd_device(shost, cmd); | ||
604 | sas_scsi_clear_queue_port(work_q, | 604 | sas_scsi_clear_queue_port(work_q, |
605 | port); | 605 | port); |
606 | goto Again; | 606 | goto Again; |
@@ -613,8 +613,6 @@ Again: | |||
613 | SAS_DPRINTK("clear nexus ha " | 613 | SAS_DPRINTK("clear nexus ha " |
614 | "succeeded\n"); | 614 | "succeeded\n"); |
615 | sas_eh_finish_cmd(cmd); | 615 | sas_eh_finish_cmd(cmd); |
616 | if (need_reset) | ||
617 | try_to_reset_cmd_device(shost, cmd); | ||
618 | goto clear_q; | 616 | goto clear_q; |
619 | } | 617 | } |
620 | } | 618 | } |
@@ -628,8 +626,6 @@ Again: | |||
628 | cmd->device->lun); | 626 | cmd->device->lun); |
629 | 627 | ||
630 | sas_eh_finish_cmd(cmd); | 628 | sas_eh_finish_cmd(cmd); |
631 | if (need_reset) | ||
632 | try_to_reset_cmd_device(shost, cmd); | ||
633 | goto clear_q; | 629 | goto clear_q; |
634 | } | 630 | } |
635 | } | 631 | } |