aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan Williams <dan.j.williams@intel.com>2012-06-22 02:25:27 -0400
committerJames Bottomley <JBottomley@Parallels.com>2012-07-20 03:58:45 -0400
commite4a9c3732cea3e3c8c704aad86636090ffe6b25f (patch)
treefaea8e91b3d917dcdb4c89adbb021ac737a6cb35
parent3b661a92e869ebe2358de8f4b3230ad84f7fce51 (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.c4
-rw-r--r--drivers/ata/libata-eh.c57
-rw-r--r--drivers/scsi/libsas/sas_ata.c38
-rw-r--r--drivers/scsi/libsas/sas_discover.c6
-rw-r--r--drivers/scsi/libsas/sas_event.c12
-rw-r--r--drivers/scsi/libsas/sas_init.c14
-rw-r--r--drivers/scsi/libsas/sas_scsi_host.c27
-rw-r--r--include/linux/libata.h4
-rw-r--r--include/scsi/libsas.h4
-rw-r--r--include/scsi/sas_ata.h5
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
85const struct ata_port_operations sata_port_ops = { 87const 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
6647const struct ata_port_info ata_dummy_port_info = { 6651const 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 */
998void ata_port_schedule_eh(struct ata_port *ap) 995void 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}
1007EXPORT_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 */
1021void 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}
1027EXPORT_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 */
1040void 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
1011static int ata_do_link_abort(struct ata_port *ap, struct ata_link *link) 1046static 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
526static 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
539void 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
526static struct ata_port_operations sas_sata_ops = { 551static 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
541static struct ata_port_info sata_port_info = { 568static 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
78int sas_drain_work(struct sas_ha_struct *ha) 78int 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
670void sas_scsi_recover_host(struct Scsi_Host *shost) 671void 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); 678retry:
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
717enum blk_eh_timer_return sas_scsi_timed_out(struct scsi_cmnd *cmd) 732enum 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);
1169extern void ata_std_error_handler(struct ata_port *ap); 1171extern void ata_std_error_handler(struct ata_port *ap);
1172extern void ata_std_sched_eh(struct ata_port *ap);
1173extern void ata_std_end_eh(struct ata_port *ap);
1170extern int ata_link_nr_enabled(struct ata_link *link); 1174extern 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 {
179enum { 179enum {
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
184struct domain_device { 185struct 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,
45void sas_ata_schedule_reset(struct domain_device *dev); 45void sas_ata_schedule_reset(struct domain_device *dev);
46void sas_ata_wait_eh(struct domain_device *dev); 46void sas_ata_wait_eh(struct domain_device *dev);
47void sas_probe_sata(struct asd_sas_port *port); 47void sas_probe_sata(struct asd_sas_port *port);
48void 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
90static 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_ */