aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorDan Williams <dan.j.williams@intel.com>2012-01-18 23:47:01 -0500
committerJames Bottomley <JBottomley@Parallels.com>2012-02-29 16:35:41 -0500
commit9508a66f898d46e726a318469312b45e0b1d078b (patch)
treee6b61e6c2a7dc8b40fdc0fe34901ff3db4af47a9 /drivers
parent92625f9bff3853951cc75f5bc084ee67c1317d2f (diff)
[SCSI] libsas: async ata scanning
libsas ata error handling is already async but this does not help the scan case. Move initial link recovery out from under host->scan_mutex, and delay synchronization with eh until after all port probe/recovery work has been queued. Device ordering is maintained with scan order by still calling sas_rphy_add() in order of domain discovery. Since we now scan the domain list when invoking libata-eh we need to be careful to check for fully initialized ata ports. Acked-by: Jack Wang <jack_wang@usish.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>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/ata/libata-core.c34
-rw-r--r--drivers/ata/libata-scsi.c13
-rw-r--r--drivers/ata/libata.h1
-rw-r--r--drivers/scsi/aic94xx/aic94xx_init.c1
-rw-r--r--drivers/scsi/isci/init.c1
-rw-r--r--drivers/scsi/libsas/sas_ata.c74
-rw-r--r--drivers/scsi/libsas/sas_discover.c22
-rw-r--r--drivers/scsi/libsas/sas_internal.h9
-rw-r--r--drivers/scsi/libsas/sas_scsi_host.c18
-rw-r--r--drivers/scsi/mvsas/mv_init.c1
-rw-r--r--drivers/scsi/pm8001/pm8001_init.c1
11 files changed, 115 insertions, 60 deletions
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index c06e0ec11556..e0bda9ff89cd 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -5936,29 +5936,31 @@ void ata_host_init(struct ata_host *host, struct device *dev,
5936 host->ops = ops; 5936 host->ops = ops;
5937} 5937}
5938 5938
5939int ata_port_probe(struct ata_port *ap) 5939void __ata_port_probe(struct ata_port *ap)
5940{ 5940{
5941 int rc = 0; 5941 struct ata_eh_info *ehi = &ap->link.eh_info;
5942 unsigned long flags;
5942 5943
5943 /* probe */ 5944 /* kick EH for boot probing */
5944 if (ap->ops->error_handler) { 5945 spin_lock_irqsave(ap->lock, flags);
5945 struct ata_eh_info *ehi = &ap->link.eh_info;
5946 unsigned long flags;
5947 5946
5948 /* kick EH for boot probing */ 5947 ehi->probe_mask |= ATA_ALL_DEVICES;
5949 spin_lock_irqsave(ap->lock, flags); 5948 ehi->action |= ATA_EH_RESET;
5949 ehi->flags |= ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET;
5950 5950
5951 ehi->probe_mask |= ATA_ALL_DEVICES; 5951 ap->pflags &= ~ATA_PFLAG_INITIALIZING;
5952 ehi->action |= ATA_EH_RESET; 5952 ap->pflags |= ATA_PFLAG_LOADING;
5953 ehi->flags |= ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET; 5953 ata_port_schedule_eh(ap);
5954 5954
5955 ap->pflags &= ~ATA_PFLAG_INITIALIZING; 5955 spin_unlock_irqrestore(ap->lock, flags);
5956 ap->pflags |= ATA_PFLAG_LOADING; 5956}
5957 ata_port_schedule_eh(ap);
5958 5957
5959 spin_unlock_irqrestore(ap->lock, flags); 5958int ata_port_probe(struct ata_port *ap)
5959{
5960 int rc = 0;
5960 5961
5961 /* wait for EH to finish */ 5962 if (ap->ops->error_handler) {
5963 __ata_port_probe(ap);
5962 ata_port_wait_eh(ap); 5964 ata_port_wait_eh(ap);
5963 } else { 5965 } else {
5964 DPRINTK("ata%u: bus probe begin\n", ap->print_id); 5966 DPRINTK("ata%u: bus probe begin\n", ap->print_id);
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index 508a60bfe5c1..1ee00c8b5b04 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -3838,6 +3838,19 @@ void ata_sas_port_stop(struct ata_port *ap)
3838} 3838}
3839EXPORT_SYMBOL_GPL(ata_sas_port_stop); 3839EXPORT_SYMBOL_GPL(ata_sas_port_stop);
3840 3840
3841int ata_sas_async_port_init(struct ata_port *ap)
3842{
3843 int rc = ap->ops->port_start(ap);
3844
3845 if (!rc) {
3846 ap->print_id = ata_print_id++;
3847 __ata_port_probe(ap);
3848 }
3849
3850 return rc;
3851}
3852EXPORT_SYMBOL_GPL(ata_sas_async_port_init);
3853
3841/** 3854/**
3842 * ata_sas_port_init - Initialize a SATA device 3855 * ata_sas_port_init - Initialize a SATA device
3843 * @ap: SATA port to initialize 3856 * @ap: SATA port to initialize
diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h
index 1fab235ee516..2e26fcaf635b 100644
--- a/drivers/ata/libata.h
+++ b/drivers/ata/libata.h
@@ -105,6 +105,7 @@ extern int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg);
105extern struct ata_port *ata_port_alloc(struct ata_host *host); 105extern struct ata_port *ata_port_alloc(struct ata_host *host);
106extern const char *sata_spd_string(unsigned int spd); 106extern const char *sata_spd_string(unsigned int spd);
107extern int ata_port_probe(struct ata_port *ap); 107extern int ata_port_probe(struct ata_port *ap);
108extern void __ata_port_probe(struct ata_port *ap);
108 109
109/* libata-acpi.c */ 110/* libata-acpi.c */
110#ifdef CONFIG_ATA_ACPI 111#ifdef CONFIG_ATA_ACPI
diff --git a/drivers/scsi/aic94xx/aic94xx_init.c b/drivers/scsi/aic94xx/aic94xx_init.c
index eea988a04f92..ff80552ead84 100644
--- a/drivers/scsi/aic94xx/aic94xx_init.c
+++ b/drivers/scsi/aic94xx/aic94xx_init.c
@@ -81,7 +81,6 @@ static struct scsi_host_template aic94xx_sht = {
81 .use_clustering = ENABLE_CLUSTERING, 81 .use_clustering = ENABLE_CLUSTERING,
82 .eh_device_reset_handler = sas_eh_device_reset_handler, 82 .eh_device_reset_handler = sas_eh_device_reset_handler,
83 .eh_bus_reset_handler = sas_eh_bus_reset_handler, 83 .eh_bus_reset_handler = sas_eh_bus_reset_handler,
84 .slave_alloc = sas_slave_alloc,
85 .target_destroy = sas_target_destroy, 84 .target_destroy = sas_target_destroy,
86 .ioctl = sas_ioctl, 85 .ioctl = sas_ioctl,
87}; 86};
diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c
index c3fe39bcacd5..c9af456e7dfe 100644
--- a/drivers/scsi/isci/init.c
+++ b/drivers/scsi/isci/init.c
@@ -165,7 +165,6 @@ static struct scsi_host_template isci_sht = {
165 .sg_tablesize = SG_ALL, 165 .sg_tablesize = SG_ALL,
166 .max_sectors = SCSI_DEFAULT_MAX_SECTORS, 166 .max_sectors = SCSI_DEFAULT_MAX_SECTORS,
167 .use_clustering = ENABLE_CLUSTERING, 167 .use_clustering = ENABLE_CLUSTERING,
168 .slave_alloc = sas_slave_alloc,
169 .target_destroy = sas_target_destroy, 168 .target_destroy = sas_target_destroy,
170 .ioctl = sas_ioctl, 169 .ioctl = sas_ioctl,
171 .shost_attrs = isci_host_attrs, 170 .shost_attrs = isci_host_attrs,
diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c
index a9ec1643ee93..eb8b77c86169 100644
--- a/drivers/scsi/libsas/sas_ata.c
+++ b/drivers/scsi/libsas/sas_ata.c
@@ -585,11 +585,10 @@ static struct ata_port_info sata_port_info = {
585 .port_ops = &sas_sata_ops 585 .port_ops = &sas_sata_ops
586}; 586};
587 587
588int sas_ata_init_host_and_port(struct domain_device *found_dev, 588int sas_ata_init_host_and_port(struct domain_device *found_dev)
589 struct scsi_target *starget)
590{ 589{
591 struct Scsi_Host *shost = dev_to_shost(&starget->dev); 590 struct sas_ha_struct *ha = found_dev->port->ha;
592 struct sas_ha_struct *ha = SHOST_TO_SAS_HA(shost); 591 struct Scsi_Host *shost = ha->core.shost;
593 struct ata_port *ap; 592 struct ata_port *ap;
594 593
595 ata_host_init(&found_dev->sata_dev.ata_host, 594 ata_host_init(&found_dev->sata_dev.ata_host,
@@ -607,6 +606,8 @@ int sas_ata_init_host_and_port(struct domain_device *found_dev,
607 ap->private_data = found_dev; 606 ap->private_data = found_dev;
608 ap->cbl = ATA_CBL_SATA; 607 ap->cbl = ATA_CBL_SATA;
609 ap->scsi_host = shost; 608 ap->scsi_host = shost;
609 /* publish initialized ata port */
610 smp_wmb();
610 found_dev->sata_dev.ap = ap; 611 found_dev->sata_dev.ap = ap;
611 612
612 return 0; 613 return 0;
@@ -683,6 +684,38 @@ static void sas_get_ata_command_set(struct domain_device *dev)
683 dev->sata_dev.command_set = ATAPI_COMMAND_SET; 684 dev->sata_dev.command_set = ATAPI_COMMAND_SET;
684} 685}
685 686
687void sas_probe_sata(struct asd_sas_port *port)
688{
689 struct domain_device *dev, *n;
690 int err;
691
692 mutex_lock(&port->ha->disco_mutex);
693 list_for_each_entry_safe(dev, n, &port->disco_list, disco_list_node) {
694 if (!dev_is_sata(dev))
695 continue;
696
697 err = sas_ata_init_host_and_port(dev);
698 if (err)
699 sas_fail_probe(dev, __func__, err);
700 else
701 ata_sas_async_port_init(dev->sata_dev.ap);
702 }
703 mutex_unlock(&port->ha->disco_mutex);
704
705 list_for_each_entry_safe(dev, n, &port->disco_list, disco_list_node) {
706 if (!dev_is_sata(dev))
707 continue;
708
709 sas_ata_wait_eh(dev);
710
711 /* if libata could not bring the link up, don't surface
712 * the device
713 */
714 if (ata_dev_disabled(sas_to_ata_dev(dev)))
715 sas_fail_probe(dev, __func__, -ENODEV);
716 }
717}
718
686/** 719/**
687 * sas_discover_sata -- discover an STP/SATA domain device 720 * sas_discover_sata -- discover an STP/SATA domain device
688 * @dev: pointer to struct domain_device of interest 721 * @dev: pointer to struct domain_device of interest
@@ -724,11 +757,23 @@ static void async_sas_ata_eh(void *data, async_cookie_t cookie)
724 sas_put_device(dev); 757 sas_put_device(dev);
725} 758}
726 759
760static bool sas_ata_dev_eh_valid(struct domain_device *dev)
761{
762 struct ata_port *ap;
763
764 if (!dev_is_sata(dev))
765 return false;
766 ap = dev->sata_dev.ap;
767 /* consume fully initialized ata ports */
768 smp_rmb();
769 return !!ap;
770}
771
727void sas_ata_strategy_handler(struct Scsi_Host *shost) 772void sas_ata_strategy_handler(struct Scsi_Host *shost)
728{ 773{
729 struct scsi_device *sdev;
730 struct sas_ha_struct *sas_ha = SHOST_TO_SAS_HA(shost); 774 struct sas_ha_struct *sas_ha = SHOST_TO_SAS_HA(shost);
731 LIST_HEAD(async); 775 LIST_HEAD(async);
776 int i;
732 777
733 /* it's ok to defer revalidation events during ata eh, these 778 /* it's ok to defer revalidation events during ata eh, these
734 * disks are in one of three states: 779 * disks are in one of three states:
@@ -740,14 +785,21 @@ void sas_ata_strategy_handler(struct Scsi_Host *shost)
740 */ 785 */
741 sas_disable_revalidation(sas_ha); 786 sas_disable_revalidation(sas_ha);
742 787
743 shost_for_each_device(sdev, shost) { 788 spin_lock_irq(&sas_ha->phy_port_lock);
744 struct domain_device *ddev = sdev_to_domain_dev(sdev); 789 for (i = 0; i < sas_ha->num_phys; i++) {
745 790 struct asd_sas_port *port = sas_ha->sas_port[i];
746 if (!dev_is_sata(ddev)) 791 struct domain_device *dev;
747 continue;
748 792
749 async_schedule_domain(async_sas_ata_eh, ddev, &async); 793 spin_lock(&port->dev_list_lock);
794 list_for_each_entry(dev, &port->dev_list, dev_list_node) {
795 if (!sas_ata_dev_eh_valid(dev))
796 continue;
797 async_schedule_domain(async_sas_ata_eh, dev, &async);
798 }
799 spin_unlock(&port->dev_list_lock);
750 } 800 }
801 spin_unlock_irq(&sas_ha->phy_port_lock);
802
751 async_synchronize_full_domain(&async); 803 async_synchronize_full_domain(&async);
752 804
753 sas_enable_revalidation(sas_ha); 805 sas_enable_revalidation(sas_ha);
diff --git a/drivers/scsi/libsas/sas_discover.c b/drivers/scsi/libsas/sas_discover.c
index 18fa364aa00f..0d58a8beaa3d 100644
--- a/drivers/scsi/libsas/sas_discover.c
+++ b/drivers/scsi/libsas/sas_discover.c
@@ -207,22 +207,22 @@ static void sas_probe_devices(struct work_struct *work)
207 207
208 clear_bit(DISCE_PROBE, &port->disc.pending); 208 clear_bit(DISCE_PROBE, &port->disc.pending);
209 209
210 list_for_each_entry_safe(dev, n, &port->disco_list, disco_list_node) { 210 /* devices must be domain members before link recovery and probe */
211 int err; 211 list_for_each_entry(dev, &port->disco_list, disco_list_node) {
212
213 spin_lock_irq(&port->dev_list_lock); 212 spin_lock_irq(&port->dev_list_lock);
214 list_add_tail(&dev->dev_list_node, &port->dev_list); 213 list_add_tail(&dev->dev_list_node, &port->dev_list);
215 spin_unlock_irq(&port->dev_list_lock); 214 spin_unlock_irq(&port->dev_list_lock);
215 }
216 216
217 err = sas_rphy_add(dev->rphy); 217 sas_probe_sata(port);
218 218
219 if (err) { 219 list_for_each_entry_safe(dev, n, &port->disco_list, disco_list_node) {
220 SAS_DPRINTK("%s: for %s device %16llx returned %d\n", 220 int err;
221 __func__, dev->parent ? "exp-attached" : 221
222 "direct-attached", 222 err = sas_rphy_add(dev->rphy);
223 SAS_ADDR(dev->sas_addr), err); 223 if (err)
224 sas_unregister_dev(port, dev); 224 sas_fail_probe(dev, __func__, err);
225 } else 225 else
226 list_del_init(&dev->disco_list_node); 226 list_del_init(&dev->disco_list_node);
227 } 227 }
228} 228}
diff --git a/drivers/scsi/libsas/sas_internal.h b/drivers/scsi/libsas/sas_internal.h
index e028d7a44202..d0d9bf10f79c 100644
--- a/drivers/scsi/libsas/sas_internal.h
+++ b/drivers/scsi/libsas/sas_internal.h
@@ -113,6 +113,15 @@ static inline int sas_smp_host_handler(struct Scsi_Host *shost,
113} 113}
114#endif 114#endif
115 115
116static inline void sas_fail_probe(struct domain_device *dev, const char *func, int err)
117{
118 SAS_DPRINTK("%s: for %s device %16llx returned %d\n",
119 func, dev->parent ? "exp-attached" :
120 "direct-attached",
121 SAS_ADDR(dev->sas_addr), err);
122 sas_unregister_dev(dev->port, dev);
123}
124
116static inline void sas_fill_in_rphy(struct domain_device *dev, 125static inline void sas_fill_in_rphy(struct domain_device *dev,
117 struct sas_rphy *rphy) 126 struct sas_rphy *rphy)
118{ 127{
diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c
index e58ca50517d5..3701ff7e7267 100644
--- a/drivers/scsi/libsas/sas_scsi_host.c
+++ b/drivers/scsi/libsas/sas_scsi_host.c
@@ -762,17 +762,10 @@ int sas_target_alloc(struct scsi_target *starget)
762{ 762{
763 struct sas_rphy *rphy = dev_to_rphy(starget->dev.parent); 763 struct sas_rphy *rphy = dev_to_rphy(starget->dev.parent);
764 struct domain_device *found_dev = sas_find_dev_by_rphy(rphy); 764 struct domain_device *found_dev = sas_find_dev_by_rphy(rphy);
765 int res;
766 765
767 if (!found_dev) 766 if (!found_dev)
768 return -ENODEV; 767 return -ENODEV;
769 768
770 if (dev_is_sata(found_dev)) {
771 res = sas_ata_init_host_and_port(found_dev, starget);
772 if (res)
773 return res;
774 }
775
776 kref_get(&found_dev->kref); 769 kref_get(&found_dev->kref);
777 starget->hostdata = found_dev; 770 starget->hostdata = found_dev;
778 return 0; 771 return 0;
@@ -1012,16 +1005,6 @@ void sas_task_abort(struct sas_task *task)
1012 } 1005 }
1013} 1006}
1014 1007
1015int sas_slave_alloc(struct scsi_device *scsi_dev)
1016{
1017 struct domain_device *dev = sdev_to_domain_dev(scsi_dev);
1018
1019 if (dev_is_sata(dev))
1020 return ata_sas_port_init(dev->sata_dev.ap);
1021
1022 return 0;
1023}
1024
1025void sas_target_destroy(struct scsi_target *starget) 1008void sas_target_destroy(struct scsi_target *starget)
1026{ 1009{
1027 struct domain_device *found_dev = starget->hostdata; 1010 struct domain_device *found_dev = starget->hostdata;
@@ -1082,6 +1065,5 @@ EXPORT_SYMBOL_GPL(sas_task_abort);
1082EXPORT_SYMBOL_GPL(sas_phy_reset); 1065EXPORT_SYMBOL_GPL(sas_phy_reset);
1083EXPORT_SYMBOL_GPL(sas_eh_device_reset_handler); 1066EXPORT_SYMBOL_GPL(sas_eh_device_reset_handler);
1084EXPORT_SYMBOL_GPL(sas_eh_bus_reset_handler); 1067EXPORT_SYMBOL_GPL(sas_eh_bus_reset_handler);
1085EXPORT_SYMBOL_GPL(sas_slave_alloc);
1086EXPORT_SYMBOL_GPL(sas_target_destroy); 1068EXPORT_SYMBOL_GPL(sas_target_destroy);
1087EXPORT_SYMBOL_GPL(sas_ioctl); 1069EXPORT_SYMBOL_GPL(sas_ioctl);
diff --git a/drivers/scsi/mvsas/mv_init.c b/drivers/scsi/mvsas/mv_init.c
index d45878b31254..cc59dff3810b 100644
--- a/drivers/scsi/mvsas/mv_init.c
+++ b/drivers/scsi/mvsas/mv_init.c
@@ -73,7 +73,6 @@ static struct scsi_host_template mvs_sht = {
73 .use_clustering = ENABLE_CLUSTERING, 73 .use_clustering = ENABLE_CLUSTERING,
74 .eh_device_reset_handler = sas_eh_device_reset_handler, 74 .eh_device_reset_handler = sas_eh_device_reset_handler,
75 .eh_bus_reset_handler = sas_eh_bus_reset_handler, 75 .eh_bus_reset_handler = sas_eh_bus_reset_handler,
76 .slave_alloc = sas_slave_alloc,
77 .target_destroy = sas_target_destroy, 76 .target_destroy = sas_target_destroy,
78 .ioctl = sas_ioctl, 77 .ioctl = sas_ioctl,
79 .shost_attrs = mvst_host_attrs, 78 .shost_attrs = mvst_host_attrs,
diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c
index bd165ea61919..36efaa7c3a54 100644
--- a/drivers/scsi/pm8001/pm8001_init.c
+++ b/drivers/scsi/pm8001/pm8001_init.c
@@ -75,7 +75,6 @@ static struct scsi_host_template pm8001_sht = {
75 .use_clustering = ENABLE_CLUSTERING, 75 .use_clustering = ENABLE_CLUSTERING,
76 .eh_device_reset_handler = sas_eh_device_reset_handler, 76 .eh_device_reset_handler = sas_eh_device_reset_handler,
77 .eh_bus_reset_handler = sas_eh_bus_reset_handler, 77 .eh_bus_reset_handler = sas_eh_bus_reset_handler,
78 .slave_alloc = sas_slave_alloc,
79 .target_destroy = sas_target_destroy, 78 .target_destroy = sas_target_destroy,
80 .ioctl = sas_ioctl, 79 .ioctl = sas_ioctl,
81 .shost_attrs = pm8001_host_attrs, 80 .shost_attrs = pm8001_host_attrs,