diff options
author | Dan Williams <dan.j.williams@intel.com> | 2012-06-22 02:25:27 -0400 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2012-07-20 03:58:45 -0400 |
commit | e4a9c3732cea3e3c8c704aad86636090ffe6b25f (patch) | |
tree | faea8e91b3d917dcdb4c89adbb021ac737a6cb35 | |
parent | 3b661a92e869ebe2358de8f4b3230ad84f7fce51 (diff) |
[SCSI] libata, libsas: introduce sched_eh and end_eh port ops
When managing shost->host_eh_scheduled libata assumes that there is a
1:1 shost-to-ata_port relationship. libsas creates a 1:N relationship
so it needs to manage host_eh_scheduled cumulatively at the host level.
The sched_eh and end_eh port port ops allow libsas to track when domain
devices enter/leave the "eh-pending" state under ha->lock (previously
named ha->state_lock, but it is no longer just a lock for ha->state
changes).
Since host_eh_scheduled indicates eh without backing commands pinning
the device it can be deallocated at any time. Move the taking of the
domain_device reference under the port_lock to guarantee that the
ata_port stays around for the duration of eh.
Reviewed-by: Jacek Danecki <jacek.danecki@intel.com>
Acked-by: Jeff Garzik <jgarzik@redhat.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
-rw-r--r-- | drivers/ata/libata-core.c | 4 | ||||
-rw-r--r-- | drivers/ata/libata-eh.c | 57 | ||||
-rw-r--r-- | drivers/scsi/libsas/sas_ata.c | 38 | ||||
-rw-r--r-- | drivers/scsi/libsas/sas_discover.c | 6 | ||||
-rw-r--r-- | drivers/scsi/libsas/sas_event.c | 12 | ||||
-rw-r--r-- | drivers/scsi/libsas/sas_init.c | 14 | ||||
-rw-r--r-- | drivers/scsi/libsas/sas_scsi_host.c | 27 | ||||
-rw-r--r-- | include/linux/libata.h | 4 | ||||
-rw-r--r-- | include/scsi/libsas.h | 4 | ||||
-rw-r--r-- | include/scsi/sas_ata.h | 5 |
10 files changed, 134 insertions, 37 deletions
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index cece3a4d11ea..3fe1202c61ce 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c | |||
@@ -80,6 +80,8 @@ const struct ata_port_operations ata_base_port_ops = { | |||
80 | .prereset = ata_std_prereset, | 80 | .prereset = ata_std_prereset, |
81 | .postreset = ata_std_postreset, | 81 | .postreset = ata_std_postreset, |
82 | .error_handler = ata_std_error_handler, | 82 | .error_handler = ata_std_error_handler, |
83 | .sched_eh = ata_std_sched_eh, | ||
84 | .end_eh = ata_std_end_eh, | ||
83 | }; | 85 | }; |
84 | 86 | ||
85 | const struct ata_port_operations sata_port_ops = { | 87 | const struct ata_port_operations sata_port_ops = { |
@@ -6642,6 +6644,8 @@ struct ata_port_operations ata_dummy_port_ops = { | |||
6642 | .qc_prep = ata_noop_qc_prep, | 6644 | .qc_prep = ata_noop_qc_prep, |
6643 | .qc_issue = ata_dummy_qc_issue, | 6645 | .qc_issue = ata_dummy_qc_issue, |
6644 | .error_handler = ata_dummy_error_handler, | 6646 | .error_handler = ata_dummy_error_handler, |
6647 | .sched_eh = ata_std_sched_eh, | ||
6648 | .end_eh = ata_std_end_eh, | ||
6645 | }; | 6649 | }; |
6646 | 6650 | ||
6647 | const struct ata_port_info ata_dummy_port_info = { | 6651 | const struct ata_port_info ata_dummy_port_info = { |
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 6d53cf9b3b6e..77fc80640e26 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c | |||
@@ -793,12 +793,12 @@ void ata_scsi_port_error_handler(struct Scsi_Host *host, struct ata_port *ap) | |||
793 | ata_for_each_link(link, ap, HOST_FIRST) | 793 | ata_for_each_link(link, ap, HOST_FIRST) |
794 | memset(&link->eh_info, 0, sizeof(link->eh_info)); | 794 | memset(&link->eh_info, 0, sizeof(link->eh_info)); |
795 | 795 | ||
796 | /* Clear host_eh_scheduled while holding ap->lock such | 796 | /* end eh (clear host_eh_scheduled) while holding |
797 | * that if exception occurs after this point but | 797 | * ap->lock such that if exception occurs after this |
798 | * before EH completion, SCSI midlayer will | 798 | * point but before EH completion, SCSI midlayer will |
799 | * re-initiate EH. | 799 | * re-initiate EH. |
800 | */ | 800 | */ |
801 | host->host_eh_scheduled = 0; | 801 | ap->ops->end_eh(ap); |
802 | 802 | ||
803 | spin_unlock_irqrestore(ap->lock, flags); | 803 | spin_unlock_irqrestore(ap->lock, flags); |
804 | ata_eh_release(ap); | 804 | ata_eh_release(ap); |
@@ -986,16 +986,13 @@ void ata_qc_schedule_eh(struct ata_queued_cmd *qc) | |||
986 | } | 986 | } |
987 | 987 | ||
988 | /** | 988 | /** |
989 | * ata_port_schedule_eh - schedule error handling without a qc | 989 | * ata_std_sched_eh - non-libsas ata_ports issue eh with this common routine |
990 | * @ap: ATA port to schedule EH for | 990 | * @ap: ATA port to schedule EH for |
991 | * | ||
992 | * Schedule error handling for @ap. EH will kick in as soon as | ||
993 | * all commands are drained. | ||
994 | * | 991 | * |
995 | * LOCKING: | 992 | * LOCKING: inherited from ata_port_schedule_eh |
996 | * spin_lock_irqsave(host lock) | 993 | * spin_lock_irqsave(host lock) |
997 | */ | 994 | */ |
998 | void ata_port_schedule_eh(struct ata_port *ap) | 995 | void ata_std_sched_eh(struct ata_port *ap) |
999 | { | 996 | { |
1000 | WARN_ON(!ap->ops->error_handler); | 997 | WARN_ON(!ap->ops->error_handler); |
1001 | 998 | ||
@@ -1007,6 +1004,44 @@ void ata_port_schedule_eh(struct ata_port *ap) | |||
1007 | 1004 | ||
1008 | DPRINTK("port EH scheduled\n"); | 1005 | DPRINTK("port EH scheduled\n"); |
1009 | } | 1006 | } |
1007 | EXPORT_SYMBOL_GPL(ata_std_sched_eh); | ||
1008 | |||
1009 | /** | ||
1010 | * ata_std_end_eh - non-libsas ata_ports complete eh with this common routine | ||
1011 | * @ap: ATA port to end EH for | ||
1012 | * | ||
1013 | * In the libata object model there is a 1:1 mapping of ata_port to | ||
1014 | * shost, so host fields can be directly manipulated under ap->lock, in | ||
1015 | * the libsas case we need to hold a lock at the ha->level to coordinate | ||
1016 | * these events. | ||
1017 | * | ||
1018 | * LOCKING: | ||
1019 | * spin_lock_irqsave(host lock) | ||
1020 | */ | ||
1021 | void ata_std_end_eh(struct ata_port *ap) | ||
1022 | { | ||
1023 | struct Scsi_Host *host = ap->scsi_host; | ||
1024 | |||
1025 | host->host_eh_scheduled = 0; | ||
1026 | } | ||
1027 | EXPORT_SYMBOL(ata_std_end_eh); | ||
1028 | |||
1029 | |||
1030 | /** | ||
1031 | * ata_port_schedule_eh - schedule error handling without a qc | ||
1032 | * @ap: ATA port to schedule EH for | ||
1033 | * | ||
1034 | * Schedule error handling for @ap. EH will kick in as soon as | ||
1035 | * all commands are drained. | ||
1036 | * | ||
1037 | * LOCKING: | ||
1038 | * spin_lock_irqsave(host lock) | ||
1039 | */ | ||
1040 | void ata_port_schedule_eh(struct ata_port *ap) | ||
1041 | { | ||
1042 | /* see: ata_std_sched_eh, unless you know better */ | ||
1043 | ap->ops->sched_eh(ap); | ||
1044 | } | ||
1010 | 1045 | ||
1011 | static int ata_do_link_abort(struct ata_port *ap, struct ata_link *link) | 1046 | static int ata_do_link_abort(struct ata_port *ap, struct ata_link *link) |
1012 | { | 1047 | { |
diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c index d109cc3a17b6..b035acf18730 100644 --- a/drivers/scsi/libsas/sas_ata.c +++ b/drivers/scsi/libsas/sas_ata.c | |||
@@ -523,6 +523,31 @@ static void sas_ata_set_dmamode(struct ata_port *ap, struct ata_device *ata_dev) | |||
523 | i->dft->lldd_ata_set_dmamode(dev); | 523 | i->dft->lldd_ata_set_dmamode(dev); |
524 | } | 524 | } |
525 | 525 | ||
526 | static void sas_ata_sched_eh(struct ata_port *ap) | ||
527 | { | ||
528 | struct domain_device *dev = ap->private_data; | ||
529 | struct sas_ha_struct *ha = dev->port->ha; | ||
530 | unsigned long flags; | ||
531 | |||
532 | spin_lock_irqsave(&ha->lock, flags); | ||
533 | if (!test_and_set_bit(SAS_DEV_EH_PENDING, &dev->state)) | ||
534 | ha->eh_active++; | ||
535 | ata_std_sched_eh(ap); | ||
536 | spin_unlock_irqrestore(&ha->lock, flags); | ||
537 | } | ||
538 | |||
539 | void sas_ata_end_eh(struct ata_port *ap) | ||
540 | { | ||
541 | struct domain_device *dev = ap->private_data; | ||
542 | struct sas_ha_struct *ha = dev->port->ha; | ||
543 | unsigned long flags; | ||
544 | |||
545 | spin_lock_irqsave(&ha->lock, flags); | ||
546 | if (test_and_clear_bit(SAS_DEV_EH_PENDING, &dev->state)) | ||
547 | ha->eh_active--; | ||
548 | spin_unlock_irqrestore(&ha->lock, flags); | ||
549 | } | ||
550 | |||
526 | static struct ata_port_operations sas_sata_ops = { | 551 | static struct ata_port_operations sas_sata_ops = { |
527 | .prereset = ata_std_prereset, | 552 | .prereset = ata_std_prereset, |
528 | .hardreset = sas_ata_hard_reset, | 553 | .hardreset = sas_ata_hard_reset, |
@@ -536,6 +561,8 @@ static struct ata_port_operations sas_sata_ops = { | |||
536 | .port_start = ata_sas_port_start, | 561 | .port_start = ata_sas_port_start, |
537 | .port_stop = ata_sas_port_stop, | 562 | .port_stop = ata_sas_port_stop, |
538 | .set_dmamode = sas_ata_set_dmamode, | 563 | .set_dmamode = sas_ata_set_dmamode, |
564 | .sched_eh = sas_ata_sched_eh, | ||
565 | .end_eh = sas_ata_end_eh, | ||
539 | }; | 566 | }; |
540 | 567 | ||
541 | static struct ata_port_info sata_port_info = { | 568 | static struct ata_port_info sata_port_info = { |
@@ -708,10 +735,6 @@ static void async_sas_ata_eh(void *data, async_cookie_t cookie) | |||
708 | struct ata_port *ap = dev->sata_dev.ap; | 735 | struct ata_port *ap = dev->sata_dev.ap; |
709 | struct sas_ha_struct *ha = dev->port->ha; | 736 | struct sas_ha_struct *ha = dev->port->ha; |
710 | 737 | ||
711 | /* hold a reference over eh since we may be racing with final | ||
712 | * remove once all commands are completed | ||
713 | */ | ||
714 | kref_get(&dev->kref); | ||
715 | sas_ata_printk(KERN_DEBUG, dev, "dev error handler\n"); | 738 | sas_ata_printk(KERN_DEBUG, dev, "dev error handler\n"); |
716 | ata_scsi_port_error_handler(ha->core.shost, ap); | 739 | ata_scsi_port_error_handler(ha->core.shost, ap); |
717 | sas_put_device(dev); | 740 | sas_put_device(dev); |
@@ -742,6 +765,13 @@ void sas_ata_strategy_handler(struct Scsi_Host *shost) | |||
742 | list_for_each_entry(dev, &port->dev_list, dev_list_node) { | 765 | list_for_each_entry(dev, &port->dev_list, dev_list_node) { |
743 | if (!dev_is_sata(dev)) | 766 | if (!dev_is_sata(dev)) |
744 | continue; | 767 | continue; |
768 | |||
769 | /* hold a reference over eh since we may be | ||
770 | * racing with final remove once all commands | ||
771 | * are completed | ||
772 | */ | ||
773 | kref_get(&dev->kref); | ||
774 | |||
745 | async_schedule_domain(async_sas_ata_eh, dev, &async); | 775 | async_schedule_domain(async_sas_ata_eh, dev, &async); |
746 | } | 776 | } |
747 | spin_unlock(&port->dev_list_lock); | 777 | spin_unlock(&port->dev_list_lock); |
diff --git a/drivers/scsi/libsas/sas_discover.c b/drivers/scsi/libsas/sas_discover.c index 629a0865b130..ff497ac76cb4 100644 --- a/drivers/scsi/libsas/sas_discover.c +++ b/drivers/scsi/libsas/sas_discover.c | |||
@@ -294,6 +294,8 @@ static void sas_unregister_common_dev(struct asd_sas_port *port, struct domain_d | |||
294 | 294 | ||
295 | spin_lock_irq(&port->dev_list_lock); | 295 | spin_lock_irq(&port->dev_list_lock); |
296 | list_del_init(&dev->dev_list_node); | 296 | list_del_init(&dev->dev_list_node); |
297 | if (dev_is_sata(dev)) | ||
298 | sas_ata_end_eh(dev->sata_dev.ap); | ||
297 | spin_unlock_irq(&port->dev_list_lock); | 299 | spin_unlock_irq(&port->dev_list_lock); |
298 | 300 | ||
299 | sas_put_device(dev); | 301 | sas_put_device(dev); |
@@ -488,9 +490,9 @@ static void sas_chain_event(int event, unsigned long *pending, | |||
488 | if (!test_and_set_bit(event, pending)) { | 490 | if (!test_and_set_bit(event, pending)) { |
489 | unsigned long flags; | 491 | unsigned long flags; |
490 | 492 | ||
491 | spin_lock_irqsave(&ha->state_lock, flags); | 493 | spin_lock_irqsave(&ha->lock, flags); |
492 | sas_chain_work(ha, sw); | 494 | sas_chain_work(ha, sw); |
493 | spin_unlock_irqrestore(&ha->state_lock, flags); | 495 | spin_unlock_irqrestore(&ha->lock, flags); |
494 | } | 496 | } |
495 | } | 497 | } |
496 | 498 | ||
diff --git a/drivers/scsi/libsas/sas_event.c b/drivers/scsi/libsas/sas_event.c index 4e4292d210c1..789c4d8bb7a7 100644 --- a/drivers/scsi/libsas/sas_event.c +++ b/drivers/scsi/libsas/sas_event.c | |||
@@ -47,9 +47,9 @@ static void sas_queue_event(int event, unsigned long *pending, | |||
47 | if (!test_and_set_bit(event, pending)) { | 47 | if (!test_and_set_bit(event, pending)) { |
48 | unsigned long flags; | 48 | unsigned long flags; |
49 | 49 | ||
50 | spin_lock_irqsave(&ha->state_lock, flags); | 50 | spin_lock_irqsave(&ha->lock, flags); |
51 | sas_queue_work(ha, work); | 51 | sas_queue_work(ha, work); |
52 | spin_unlock_irqrestore(&ha->state_lock, flags); | 52 | spin_unlock_irqrestore(&ha->lock, flags); |
53 | } | 53 | } |
54 | } | 54 | } |
55 | 55 | ||
@@ -61,18 +61,18 @@ void __sas_drain_work(struct sas_ha_struct *ha) | |||
61 | 61 | ||
62 | set_bit(SAS_HA_DRAINING, &ha->state); | 62 | set_bit(SAS_HA_DRAINING, &ha->state); |
63 | /* flush submitters */ | 63 | /* flush submitters */ |
64 | spin_lock_irq(&ha->state_lock); | 64 | spin_lock_irq(&ha->lock); |
65 | spin_unlock_irq(&ha->state_lock); | 65 | spin_unlock_irq(&ha->lock); |
66 | 66 | ||
67 | drain_workqueue(wq); | 67 | drain_workqueue(wq); |
68 | 68 | ||
69 | spin_lock_irq(&ha->state_lock); | 69 | spin_lock_irq(&ha->lock); |
70 | clear_bit(SAS_HA_DRAINING, &ha->state); | 70 | clear_bit(SAS_HA_DRAINING, &ha->state); |
71 | list_for_each_entry_safe(sw, _sw, &ha->defer_q, drain_node) { | 71 | list_for_each_entry_safe(sw, _sw, &ha->defer_q, drain_node) { |
72 | list_del_init(&sw->drain_node); | 72 | list_del_init(&sw->drain_node); |
73 | sas_queue_work(ha, sw); | 73 | sas_queue_work(ha, sw); |
74 | } | 74 | } |
75 | spin_unlock_irq(&ha->state_lock); | 75 | spin_unlock_irq(&ha->lock); |
76 | } | 76 | } |
77 | 77 | ||
78 | int sas_drain_work(struct sas_ha_struct *ha) | 78 | int sas_drain_work(struct sas_ha_struct *ha) |
diff --git a/drivers/scsi/libsas/sas_init.c b/drivers/scsi/libsas/sas_init.c index 10cb5ae30977..6909fefa32c5 100644 --- a/drivers/scsi/libsas/sas_init.c +++ b/drivers/scsi/libsas/sas_init.c | |||
@@ -114,7 +114,7 @@ int sas_register_ha(struct sas_ha_struct *sas_ha) | |||
114 | sas_ha->lldd_queue_size = 128; /* Sanity */ | 114 | sas_ha->lldd_queue_size = 128; /* Sanity */ |
115 | 115 | ||
116 | set_bit(SAS_HA_REGISTERED, &sas_ha->state); | 116 | set_bit(SAS_HA_REGISTERED, &sas_ha->state); |
117 | spin_lock_init(&sas_ha->state_lock); | 117 | spin_lock_init(&sas_ha->lock); |
118 | mutex_init(&sas_ha->drain_mutex); | 118 | mutex_init(&sas_ha->drain_mutex); |
119 | INIT_LIST_HEAD(&sas_ha->defer_q); | 119 | INIT_LIST_HEAD(&sas_ha->defer_q); |
120 | 120 | ||
@@ -163,9 +163,9 @@ int sas_unregister_ha(struct sas_ha_struct *sas_ha) | |||
163 | * events to be queued, and flush any in-progress drainers | 163 | * events to be queued, and flush any in-progress drainers |
164 | */ | 164 | */ |
165 | mutex_lock(&sas_ha->drain_mutex); | 165 | mutex_lock(&sas_ha->drain_mutex); |
166 | spin_lock_irq(&sas_ha->state_lock); | 166 | spin_lock_irq(&sas_ha->lock); |
167 | clear_bit(SAS_HA_REGISTERED, &sas_ha->state); | 167 | clear_bit(SAS_HA_REGISTERED, &sas_ha->state); |
168 | spin_unlock_irq(&sas_ha->state_lock); | 168 | spin_unlock_irq(&sas_ha->lock); |
169 | __sas_drain_work(sas_ha); | 169 | __sas_drain_work(sas_ha); |
170 | mutex_unlock(&sas_ha->drain_mutex); | 170 | mutex_unlock(&sas_ha->drain_mutex); |
171 | 171 | ||
@@ -411,9 +411,9 @@ static int queue_phy_reset(struct sas_phy *phy, int hard_reset) | |||
411 | d->reset_result = 0; | 411 | d->reset_result = 0; |
412 | d->hard_reset = hard_reset; | 412 | d->hard_reset = hard_reset; |
413 | 413 | ||
414 | spin_lock_irq(&ha->state_lock); | 414 | spin_lock_irq(&ha->lock); |
415 | sas_queue_work(ha, &d->reset_work); | 415 | sas_queue_work(ha, &d->reset_work); |
416 | spin_unlock_irq(&ha->state_lock); | 416 | spin_unlock_irq(&ha->lock); |
417 | 417 | ||
418 | rc = sas_drain_work(ha); | 418 | rc = sas_drain_work(ha); |
419 | if (rc == 0) | 419 | if (rc == 0) |
@@ -438,9 +438,9 @@ static int queue_phy_enable(struct sas_phy *phy, int enable) | |||
438 | d->enable_result = 0; | 438 | d->enable_result = 0; |
439 | d->enable = enable; | 439 | d->enable = enable; |
440 | 440 | ||
441 | spin_lock_irq(&ha->state_lock); | 441 | spin_lock_irq(&ha->lock); |
442 | sas_queue_work(ha, &d->enable_work); | 442 | sas_queue_work(ha, &d->enable_work); |
443 | spin_unlock_irq(&ha->state_lock); | 443 | spin_unlock_irq(&ha->lock); |
444 | 444 | ||
445 | rc = sas_drain_work(ha); | 445 | rc = sas_drain_work(ha); |
446 | if (rc == 0) | 446 | if (rc == 0) |
diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c index f0b9b7bf1882..a09da44e282b 100644 --- a/drivers/scsi/libsas/sas_scsi_host.c +++ b/drivers/scsi/libsas/sas_scsi_host.c | |||
@@ -667,16 +667,20 @@ static void sas_eh_handle_sas_errors(struct Scsi_Host *shost, struct list_head * | |||
667 | goto out; | 667 | goto out; |
668 | } | 668 | } |
669 | 669 | ||
670 | |||
670 | void sas_scsi_recover_host(struct Scsi_Host *shost) | 671 | void sas_scsi_recover_host(struct Scsi_Host *shost) |
671 | { | 672 | { |
672 | struct sas_ha_struct *ha = SHOST_TO_SAS_HA(shost); | 673 | struct sas_ha_struct *ha = SHOST_TO_SAS_HA(shost); |
673 | unsigned long flags; | ||
674 | LIST_HEAD(eh_work_q); | 674 | LIST_HEAD(eh_work_q); |
675 | int tries = 0; | ||
676 | bool retry; | ||
675 | 677 | ||
676 | spin_lock_irqsave(shost->host_lock, flags); | 678 | retry: |
679 | tries++; | ||
680 | retry = true; | ||
681 | spin_lock_irq(shost->host_lock); | ||
677 | list_splice_init(&shost->eh_cmd_q, &eh_work_q); | 682 | list_splice_init(&shost->eh_cmd_q, &eh_work_q); |
678 | shost->host_eh_scheduled = 0; | 683 | spin_unlock_irq(shost->host_lock); |
679 | spin_unlock_irqrestore(shost->host_lock, flags); | ||
680 | 684 | ||
681 | SAS_DPRINTK("Enter %s busy: %d failed: %d\n", | 685 | SAS_DPRINTK("Enter %s busy: %d failed: %d\n", |
682 | __func__, shost->host_busy, shost->host_failed); | 686 | __func__, shost->host_busy, shost->host_failed); |
@@ -710,8 +714,19 @@ out: | |||
710 | 714 | ||
711 | scsi_eh_flush_done_q(&ha->eh_done_q); | 715 | scsi_eh_flush_done_q(&ha->eh_done_q); |
712 | 716 | ||
713 | SAS_DPRINTK("--- Exit %s: busy: %d failed: %d\n", | 717 | /* check if any new eh work was scheduled during the last run */ |
714 | __func__, shost->host_busy, shost->host_failed); | 718 | spin_lock_irq(&ha->lock); |
719 | if (ha->eh_active == 0) { | ||
720 | shost->host_eh_scheduled = 0; | ||
721 | retry = false; | ||
722 | } | ||
723 | spin_unlock_irq(&ha->lock); | ||
724 | |||
725 | if (retry) | ||
726 | goto retry; | ||
727 | |||
728 | SAS_DPRINTK("--- Exit %s: busy: %d failed: %d tries: %d\n", | ||
729 | __func__, shost->host_busy, shost->host_failed, tries); | ||
715 | } | 730 | } |
716 | 731 | ||
717 | enum blk_eh_timer_return sas_scsi_timed_out(struct scsi_cmnd *cmd) | 732 | enum blk_eh_timer_return sas_scsi_timed_out(struct scsi_cmnd *cmd) |
diff --git a/include/linux/libata.h b/include/linux/libata.h index 6e887c742a27..53da442f892d 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h | |||
@@ -846,6 +846,8 @@ struct ata_port_operations { | |||
846 | void (*error_handler)(struct ata_port *ap); | 846 | void (*error_handler)(struct ata_port *ap); |
847 | void (*lost_interrupt)(struct ata_port *ap); | 847 | void (*lost_interrupt)(struct ata_port *ap); |
848 | void (*post_internal_cmd)(struct ata_queued_cmd *qc); | 848 | void (*post_internal_cmd)(struct ata_queued_cmd *qc); |
849 | void (*sched_eh)(struct ata_port *ap); | ||
850 | void (*end_eh)(struct ata_port *ap); | ||
849 | 851 | ||
850 | /* | 852 | /* |
851 | * Optional features | 853 | * Optional features |
@@ -1167,6 +1169,8 @@ extern void ata_do_eh(struct ata_port *ap, ata_prereset_fn_t prereset, | |||
1167 | ata_reset_fn_t softreset, ata_reset_fn_t hardreset, | 1169 | ata_reset_fn_t softreset, ata_reset_fn_t hardreset, |
1168 | ata_postreset_fn_t postreset); | 1170 | ata_postreset_fn_t postreset); |
1169 | extern void ata_std_error_handler(struct ata_port *ap); | 1171 | extern void ata_std_error_handler(struct ata_port *ap); |
1172 | extern void ata_std_sched_eh(struct ata_port *ap); | ||
1173 | extern void ata_std_end_eh(struct ata_port *ap); | ||
1170 | extern int ata_link_nr_enabled(struct ata_link *link); | 1174 | extern int ata_link_nr_enabled(struct ata_link *link); |
1171 | 1175 | ||
1172 | /* | 1176 | /* |
diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h index 10ce74f589c5..814d8cb592ad 100644 --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h | |||
@@ -179,6 +179,7 @@ struct sata_device { | |||
179 | enum { | 179 | enum { |
180 | SAS_DEV_GONE, | 180 | SAS_DEV_GONE, |
181 | SAS_DEV_DESTROY, | 181 | SAS_DEV_DESTROY, |
182 | SAS_DEV_EH_PENDING, | ||
182 | }; | 183 | }; |
183 | 184 | ||
184 | struct domain_device { | 185 | struct domain_device { |
@@ -386,7 +387,8 @@ struct sas_ha_struct { | |||
386 | struct list_head defer_q; /* work queued while draining */ | 387 | struct list_head defer_q; /* work queued while draining */ |
387 | struct mutex drain_mutex; | 388 | struct mutex drain_mutex; |
388 | unsigned long state; | 389 | unsigned long state; |
389 | spinlock_t state_lock; | 390 | spinlock_t lock; |
391 | int eh_active; | ||
390 | 392 | ||
391 | struct mutex disco_mutex; | 393 | struct mutex disco_mutex; |
392 | 394 | ||
diff --git a/include/scsi/sas_ata.h b/include/scsi/sas_ata.h index 77670e823ed8..2dfbdaa0b34a 100644 --- a/include/scsi/sas_ata.h +++ b/include/scsi/sas_ata.h | |||
@@ -45,6 +45,7 @@ void sas_ata_eh(struct Scsi_Host *shost, struct list_head *work_q, | |||
45 | void sas_ata_schedule_reset(struct domain_device *dev); | 45 | void sas_ata_schedule_reset(struct domain_device *dev); |
46 | void sas_ata_wait_eh(struct domain_device *dev); | 46 | void sas_ata_wait_eh(struct domain_device *dev); |
47 | void sas_probe_sata(struct asd_sas_port *port); | 47 | void sas_probe_sata(struct asd_sas_port *port); |
48 | void sas_ata_end_eh(struct ata_port *ap); | ||
48 | #else | 49 | #else |
49 | 50 | ||
50 | 51 | ||
@@ -85,6 +86,10 @@ static inline int sas_get_ata_info(struct domain_device *dev, struct ex_phy *phy | |||
85 | { | 86 | { |
86 | return 0; | 87 | return 0; |
87 | } | 88 | } |
89 | |||
90 | static inline void sas_ata_end_eh(struct ata_port *ap) | ||
91 | { | ||
92 | } | ||
88 | #endif | 93 | #endif |
89 | 94 | ||
90 | #endif /* _SAS_ATA_H_ */ | 95 | #endif /* _SAS_ATA_H_ */ |