aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/libsas/sas_ata.c55
-rw-r--r--drivers/scsi/libsas/sas_discover.c63
-rw-r--r--drivers/scsi/libsas/sas_event.c26
-rw-r--r--drivers/scsi/libsas/sas_expander.c5
-rw-r--r--drivers/scsi/libsas/sas_init.c2
-rw-r--r--drivers/scsi/libsas/sas_internal.h3
-rw-r--r--drivers/scsi/libsas/sas_port.c2
-rw-r--r--drivers/scsi/scsi_transport_sas.c18
8 files changed, 158 insertions, 16 deletions
diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c
index 2fc5a3961ca6..4b6365c6410f 100644
--- a/drivers/scsi/libsas/sas_ata.c
+++ b/drivers/scsi/libsas/sas_ata.c
@@ -758,6 +758,35 @@ static int sas_discover_sata_pm(struct domain_device *dev)
758 return -ENODEV; 758 return -ENODEV;
759} 759}
760 760
761void sas_probe_sata(struct work_struct *work)
762{
763 struct domain_device *dev, *n;
764 struct sas_discovery_event *ev =
765 container_of(work, struct sas_discovery_event, work);
766 struct asd_sas_port *port = ev->port;
767
768 clear_bit(DISCE_PROBE, &port->disc.pending);
769
770 list_for_each_entry_safe(dev, n, &port->disco_list, disco_list_node) {
771 int err;
772
773 spin_lock_irq(&port->dev_list_lock);
774 list_add_tail(&dev->dev_list_node, &port->dev_list);
775 spin_unlock_irq(&port->dev_list_lock);
776
777 err = sas_rphy_add(dev->rphy);
778
779 if (err) {
780 SAS_DPRINTK("%s: for %s device %16llx returned %d\n",
781 __func__, dev->parent ? "exp-attached" :
782 "direct-attached",
783 SAS_ADDR(dev->sas_addr), err);
784 sas_unregister_dev(port, dev);
785 } else
786 list_del_init(&dev->disco_list_node);
787 }
788}
789
761/** 790/**
762 * sas_discover_sata -- discover an STP/SATA domain device 791 * sas_discover_sata -- discover an STP/SATA domain device
763 * @dev: pointer to struct domain_device of interest 792 * @dev: pointer to struct domain_device of interest
@@ -794,10 +823,15 @@ int sas_discover_sata(struct domain_device *dev)
794 break; 823 break;
795 } 824 }
796 sas_notify_lldd_dev_gone(dev); 825 sas_notify_lldd_dev_gone(dev);
797 if (!res) { 826
798 sas_notify_lldd_dev_found(dev); 827 if (res)
799 res = sas_rphy_add(dev->rphy); 828 return res;
800 } 829
830 res = sas_notify_lldd_dev_found(dev);
831 if (res)
832 return res;
833
834 sas_discover_event(dev->port, DISCE_PROBE);
801 835
802 return res; 836 return res;
803} 837}
@@ -805,6 +839,17 @@ int sas_discover_sata(struct domain_device *dev)
805void sas_ata_strategy_handler(struct Scsi_Host *shost) 839void sas_ata_strategy_handler(struct Scsi_Host *shost)
806{ 840{
807 struct scsi_device *sdev; 841 struct scsi_device *sdev;
842 struct sas_ha_struct *sas_ha = SHOST_TO_SAS_HA(shost);
843
844 /* it's ok to defer revalidation events during ata eh, these
845 * disks are in one of three states:
846 * 1/ present for initial domain discovery, and these
847 * resets will cause bcn flutters
848 * 2/ hot removed, we'll discover that after eh fails
849 * 3/ hot added after initial discovery, lost the race, and need
850 * to catch the next train.
851 */
852 sas_disable_revalidation(sas_ha);
808 853
809 shost_for_each_device(sdev, shost) { 854 shost_for_each_device(sdev, shost) {
810 struct domain_device *ddev = sdev_to_domain_dev(sdev); 855 struct domain_device *ddev = sdev_to_domain_dev(sdev);
@@ -816,6 +861,8 @@ void sas_ata_strategy_handler(struct Scsi_Host *shost)
816 ata_port_printk(ap, KERN_DEBUG, "sas eh calling libata port error handler"); 861 ata_port_printk(ap, KERN_DEBUG, "sas eh calling libata port error handler");
817 ata_scsi_port_error_handler(shost, ap); 862 ata_scsi_port_error_handler(shost, ap);
818 } 863 }
864
865 sas_enable_revalidation(sas_ha);
819} 866}
820 867
821int sas_ata_timed_out(struct scsi_cmnd *cmd, struct sas_task *task, 868int sas_ata_timed_out(struct scsi_cmnd *cmd, struct sas_task *task,
diff --git a/drivers/scsi/libsas/sas_discover.c b/drivers/scsi/libsas/sas_discover.c
index 32e011766046..7e8fdcb202b7 100644
--- a/drivers/scsi/libsas/sas_discover.c
+++ b/drivers/scsi/libsas/sas_discover.c
@@ -148,9 +148,14 @@ static int sas_get_port_device(struct asd_sas_port *port)
148 port->disc.max_level = 0; 148 port->disc.max_level = 0;
149 149
150 dev->rphy = rphy; 150 dev->rphy = rphy;
151 spin_lock_irq(&port->dev_list_lock); 151
152 list_add_tail(&dev->dev_list_node, &port->dev_list); 152 if (dev_is_sata(dev))
153 spin_unlock_irq(&port->dev_list_lock); 153 list_add_tail(&dev->disco_list_node, &port->disco_list);
154 else {
155 spin_lock_irq(&port->dev_list_lock);
156 list_add_tail(&dev->dev_list_node, &port->dev_list);
157 spin_unlock_irq(&port->dev_list_lock);
158 }
154 159
155 return 0; 160 return 0;
156} 161}
@@ -255,14 +260,43 @@ static void sas_unregister_common_dev(struct asd_sas_port *port, struct domain_d
255 sas_put_device(dev); 260 sas_put_device(dev);
256} 261}
257 262
258void sas_unregister_dev(struct asd_sas_port *port, struct domain_device *dev) 263static void sas_destruct_devices(struct work_struct *work)
259{ 264{
260 if (dev->rphy) { 265 struct domain_device *dev, *n;
266 struct sas_discovery_event *ev =
267 container_of(work, struct sas_discovery_event, work);
268 struct asd_sas_port *port = ev->port;
269
270 clear_bit(DISCE_DESTRUCT, &port->disc.pending);
271
272 list_for_each_entry_safe(dev, n, &port->destroy_list, disco_list_node) {
273 list_del_init(&dev->disco_list_node);
274
261 sas_remove_children(&dev->rphy->dev); 275 sas_remove_children(&dev->rphy->dev);
262 sas_rphy_delete(dev->rphy); 276 sas_rphy_delete(dev->rphy);
263 dev->rphy = NULL; 277 dev->rphy = NULL;
278 sas_unregister_common_dev(port, dev);
279
280 sas_put_device(dev);
281 }
282}
283
284void sas_unregister_dev(struct asd_sas_port *port, struct domain_device *dev)
285{
286 if (!test_bit(SAS_DEV_DESTROY, &dev->state) &&
287 !list_empty(&dev->disco_list_node)) {
288 /* this rphy never saw sas_rphy_add */
289 list_del_init(&dev->disco_list_node);
290 sas_rphy_free(dev->rphy);
291 dev->rphy = NULL;
292 sas_unregister_common_dev(port, dev);
293 }
294
295 if (dev->rphy && !test_and_set_bit(SAS_DEV_DESTROY, &dev->state)) {
296 sas_rphy_unlink(dev->rphy);
297 list_move_tail(&dev->disco_list_node, &port->destroy_list);
298 sas_discover_event(dev->port, DISCE_DESTRUCT);
264 } 299 }
265 sas_unregister_common_dev(port, dev);
266} 300}
267 301
268void sas_unregister_domain_devices(struct asd_sas_port *port) 302void sas_unregister_domain_devices(struct asd_sas_port *port)
@@ -271,6 +305,8 @@ void sas_unregister_domain_devices(struct asd_sas_port *port)
271 305
272 list_for_each_entry_safe_reverse(dev, n, &port->dev_list, dev_list_node) 306 list_for_each_entry_safe_reverse(dev, n, &port->dev_list, dev_list_node)
273 sas_unregister_dev(port, dev); 307 sas_unregister_dev(port, dev);
308 list_for_each_entry_safe(dev, n, &port->disco_list, disco_list_node)
309 sas_unregister_dev(port, dev);
274 310
275 port->port->rphy = NULL; 311 port->port->rphy = NULL;
276 312
@@ -335,6 +371,7 @@ static void sas_discover_domain(struct work_struct *work)
335 sas_rphy_free(dev->rphy); 371 sas_rphy_free(dev->rphy);
336 dev->rphy = NULL; 372 dev->rphy = NULL;
337 373
374 list_del_init(&dev->disco_list_node);
338 spin_lock_irq(&port->dev_list_lock); 375 spin_lock_irq(&port->dev_list_lock);
339 list_del_init(&dev->dev_list_node); 376 list_del_init(&dev->dev_list_node);
340 spin_unlock_irq(&port->dev_list_lock); 377 spin_unlock_irq(&port->dev_list_lock);
@@ -353,16 +390,28 @@ static void sas_revalidate_domain(struct work_struct *work)
353 struct sas_discovery_event *ev = 390 struct sas_discovery_event *ev =
354 container_of(work, struct sas_discovery_event, work); 391 container_of(work, struct sas_discovery_event, work);
355 struct asd_sas_port *port = ev->port; 392 struct asd_sas_port *port = ev->port;
393 struct sas_ha_struct *ha = port->ha;
394
395 /* prevent revalidation from finding sata links in recovery */
396 mutex_lock(&ha->disco_mutex);
397 if (test_bit(SAS_HA_ATA_EH_ACTIVE, &ha->state)) {
398 SAS_DPRINTK("REVALIDATION DEFERRED on port %d, pid:%d\n",
399 port->id, task_pid_nr(current));
400 goto out;
401 }
356 402
357 clear_bit(DISCE_REVALIDATE_DOMAIN, &port->disc.pending); 403 clear_bit(DISCE_REVALIDATE_DOMAIN, &port->disc.pending);
358 404
359 SAS_DPRINTK("REVALIDATING DOMAIN on port %d, pid:%d\n", port->id, 405 SAS_DPRINTK("REVALIDATING DOMAIN on port %d, pid:%d\n", port->id,
360 task_pid_nr(current)); 406 task_pid_nr(current));
407
361 if (port->port_dev) 408 if (port->port_dev)
362 res = sas_ex_revalidate_domain(port->port_dev); 409 res = sas_ex_revalidate_domain(port->port_dev);
363 410
364 SAS_DPRINTK("done REVALIDATING DOMAIN on port %d, pid:%d, res 0x%x\n", 411 SAS_DPRINTK("done REVALIDATING DOMAIN on port %d, pid:%d, res 0x%x\n",
365 port->id, task_pid_nr(current), res); 412 port->id, task_pid_nr(current), res);
413 out:
414 mutex_unlock(&ha->disco_mutex);
366} 415}
367 416
368/* ---------- Events ---------- */ 417/* ---------- Events ---------- */
@@ -414,6 +463,8 @@ void sas_init_disc(struct sas_discovery *disc, struct asd_sas_port *port)
414 static const work_func_t sas_event_fns[DISC_NUM_EVENTS] = { 463 static const work_func_t sas_event_fns[DISC_NUM_EVENTS] = {
415 [DISCE_DISCOVER_DOMAIN] = sas_discover_domain, 464 [DISCE_DISCOVER_DOMAIN] = sas_discover_domain,
416 [DISCE_REVALIDATE_DOMAIN] = sas_revalidate_domain, 465 [DISCE_REVALIDATE_DOMAIN] = sas_revalidate_domain,
466 [DISCE_PROBE] = sas_probe_sata,
467 [DISCE_DESTRUCT] = sas_destruct_devices,
417 }; 468 };
418 469
419 disc->pending = 0; 470 disc->pending = 0;
diff --git a/drivers/scsi/libsas/sas_event.c b/drivers/scsi/libsas/sas_event.c
index e5035aa4c2a6..933d757499b5 100644
--- a/drivers/scsi/libsas/sas_event.c
+++ b/drivers/scsi/libsas/sas_event.c
@@ -81,6 +81,32 @@ int sas_drain_work(struct sas_ha_struct *ha)
81} 81}
82EXPORT_SYMBOL_GPL(sas_drain_work); 82EXPORT_SYMBOL_GPL(sas_drain_work);
83 83
84void sas_disable_revalidation(struct sas_ha_struct *ha)
85{
86 mutex_lock(&ha->disco_mutex);
87 set_bit(SAS_HA_ATA_EH_ACTIVE, &ha->state);
88 mutex_unlock(&ha->disco_mutex);
89}
90
91void sas_enable_revalidation(struct sas_ha_struct *ha)
92{
93 int i;
94
95 mutex_lock(&ha->disco_mutex);
96 clear_bit(SAS_HA_ATA_EH_ACTIVE, &ha->state);
97 for (i = 0; i < ha->num_phys; i++) {
98 struct asd_sas_port *port = ha->sas_port[i];
99 const int ev = DISCE_REVALIDATE_DOMAIN;
100 struct sas_discovery *d = &port->disc;
101
102 if (!test_and_clear_bit(ev, &d->pending))
103 continue;
104
105 sas_queue_event(ev, &d->pending, &d->disc_work[ev].work, ha);
106 }
107 mutex_unlock(&ha->disco_mutex);
108}
109
84static void notify_ha_event(struct sas_ha_struct *sas_ha, enum ha_event event) 110static void notify_ha_event(struct sas_ha_struct *sas_ha, enum ha_event event)
85{ 111{
86 BUG_ON(event >= HA_NUM_EVENTS); 112 BUG_ON(event >= HA_NUM_EVENTS);
diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c
index f33d0c9911c4..e45b259dac4c 100644
--- a/drivers/scsi/libsas/sas_expander.c
+++ b/drivers/scsi/libsas/sas_expander.c
@@ -704,9 +704,7 @@ static struct domain_device *sas_ex_discover_end_dev(
704 704
705 child->rphy = rphy; 705 child->rphy = rphy;
706 706
707 spin_lock_irq(&parent->port->dev_list_lock); 707 list_add_tail(&child->disco_list_node, &parent->port->disco_list);
708 list_add_tail(&child->dev_list_node, &parent->port->dev_list);
709 spin_unlock_irq(&parent->port->dev_list_lock);
710 708
711 res = sas_discover_sata(child); 709 res = sas_discover_sata(child);
712 if (res) { 710 if (res) {
@@ -756,6 +754,7 @@ static struct domain_device *sas_ex_discover_end_dev(
756 sas_rphy_free(child->rphy); 754 sas_rphy_free(child->rphy);
757 child->rphy = NULL; 755 child->rphy = NULL;
758 756
757 list_del(&child->disco_list_node);
759 spin_lock_irq(&parent->port->dev_list_lock); 758 spin_lock_irq(&parent->port->dev_list_lock);
760 list_del(&child->dev_list_node); 759 list_del(&child->dev_list_node);
761 spin_unlock_irq(&parent->port->dev_list_lock); 760 spin_unlock_irq(&parent->port->dev_list_lock);
diff --git a/drivers/scsi/libsas/sas_init.c b/drivers/scsi/libsas/sas_init.c
index 572b943d7603..52cd11d76664 100644
--- a/drivers/scsi/libsas/sas_init.c
+++ b/drivers/scsi/libsas/sas_init.c
@@ -104,6 +104,7 @@ int sas_register_ha(struct sas_ha_struct *sas_ha)
104{ 104{
105 int error = 0; 105 int error = 0;
106 106
107 mutex_init(&sas_ha->disco_mutex);
107 spin_lock_init(&sas_ha->phy_port_lock); 108 spin_lock_init(&sas_ha->phy_port_lock);
108 sas_hash_addr(sas_ha->hashed_sas_addr, sas_ha->sas_addr); 109 sas_hash_addr(sas_ha->hashed_sas_addr, sas_ha->sas_addr);
109 110
@@ -168,6 +169,7 @@ int sas_unregister_ha(struct sas_ha_struct *sas_ha)
168 sas_drain_work(sas_ha); 169 sas_drain_work(sas_ha);
169 170
170 sas_unregister_ports(sas_ha); 171 sas_unregister_ports(sas_ha);
172 sas_drain_work(sas_ha);
171 173
172 if (sas_ha->lldd_max_execute_num > 1) { 174 if (sas_ha->lldd_max_execute_num > 1) {
173 sas_shutdown_queue(sas_ha); 175 sas_shutdown_queue(sas_ha);
diff --git a/drivers/scsi/libsas/sas_internal.h b/drivers/scsi/libsas/sas_internal.h
index 948ea64cc2eb..ebe9b81ddef5 100644
--- a/drivers/scsi/libsas/sas_internal.h
+++ b/drivers/scsi/libsas/sas_internal.h
@@ -56,6 +56,8 @@ enum blk_eh_timer_return sas_scsi_timed_out(struct scsi_cmnd *);
56int sas_init_queue(struct sas_ha_struct *sas_ha); 56int sas_init_queue(struct sas_ha_struct *sas_ha);
57int sas_init_events(struct sas_ha_struct *sas_ha); 57int sas_init_events(struct sas_ha_struct *sas_ha);
58void sas_shutdown_queue(struct sas_ha_struct *sas_ha); 58void sas_shutdown_queue(struct sas_ha_struct *sas_ha);
59void sas_disable_revalidation(struct sas_ha_struct *ha);
60void sas_enable_revalidation(struct sas_ha_struct *ha);
59 61
60void sas_deform_port(struct asd_sas_phy *phy, int gone); 62void sas_deform_port(struct asd_sas_phy *phy, int gone);
61 63
@@ -138,6 +140,7 @@ static inline struct domain_device *sas_alloc_device(void)
138 if (dev) { 140 if (dev) {
139 INIT_LIST_HEAD(&dev->siblings); 141 INIT_LIST_HEAD(&dev->siblings);
140 INIT_LIST_HEAD(&dev->dev_list_node); 142 INIT_LIST_HEAD(&dev->dev_list_node);
143 INIT_LIST_HEAD(&dev->disco_list_node);
141 kref_init(&dev->kref); 144 kref_init(&dev->kref);
142 } 145 }
143 return dev; 146 return dev;
diff --git a/drivers/scsi/libsas/sas_port.c b/drivers/scsi/libsas/sas_port.c
index d88e55f9732b..2980bde4e34a 100644
--- a/drivers/scsi/libsas/sas_port.c
+++ b/drivers/scsi/libsas/sas_port.c
@@ -277,6 +277,8 @@ static void sas_init_port(struct asd_sas_port *port,
277 memset(port, 0, sizeof(*port)); 277 memset(port, 0, sizeof(*port));
278 port->id = i; 278 port->id = i;
279 INIT_LIST_HEAD(&port->dev_list); 279 INIT_LIST_HEAD(&port->dev_list);
280 INIT_LIST_HEAD(&port->disco_list);
281 INIT_LIST_HEAD(&port->destroy_list);
280 spin_lock_init(&port->phy_list_lock); 282 spin_lock_init(&port->phy_list_lock);
281 INIT_LIST_HEAD(&port->phy_list); 283 INIT_LIST_HEAD(&port->phy_list);
282 port->ha = sas_ha; 284 port->ha = sas_ha;
diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c
index 9d9330ae4213..9421bae8af1a 100644
--- a/drivers/scsi/scsi_transport_sas.c
+++ b/drivers/scsi/scsi_transport_sas.c
@@ -1603,6 +1603,20 @@ sas_rphy_delete(struct sas_rphy *rphy)
1603EXPORT_SYMBOL(sas_rphy_delete); 1603EXPORT_SYMBOL(sas_rphy_delete);
1604 1604
1605/** 1605/**
1606 * sas_rphy_unlink - unlink SAS remote PHY
1607 * @rphy: SAS remote phy to unlink from its parent port
1608 *
1609 * Removes port reference to an rphy
1610 */
1611void sas_rphy_unlink(struct sas_rphy *rphy)
1612{
1613 struct sas_port *parent = dev_to_sas_port(rphy->dev.parent);
1614
1615 parent->rphy = NULL;
1616}
1617EXPORT_SYMBOL(sas_rphy_unlink);
1618
1619/**
1606 * sas_rphy_remove - remove SAS remote PHY 1620 * sas_rphy_remove - remove SAS remote PHY
1607 * @rphy: SAS remote phy to remove 1621 * @rphy: SAS remote phy to remove
1608 * 1622 *
@@ -1612,7 +1626,6 @@ void
1612sas_rphy_remove(struct sas_rphy *rphy) 1626sas_rphy_remove(struct sas_rphy *rphy)
1613{ 1627{
1614 struct device *dev = &rphy->dev; 1628 struct device *dev = &rphy->dev;
1615 struct sas_port *parent = dev_to_sas_port(dev->parent);
1616 1629
1617 switch (rphy->identify.device_type) { 1630 switch (rphy->identify.device_type) {
1618 case SAS_END_DEVICE: 1631 case SAS_END_DEVICE:
@@ -1626,10 +1639,9 @@ sas_rphy_remove(struct sas_rphy *rphy)
1626 break; 1639 break;
1627 } 1640 }
1628 1641
1642 sas_rphy_unlink(rphy);
1629 transport_remove_device(dev); 1643 transport_remove_device(dev);
1630 device_del(dev); 1644 device_del(dev);
1631
1632 parent->rphy = NULL;
1633} 1645}
1634EXPORT_SYMBOL(sas_rphy_remove); 1646EXPORT_SYMBOL(sas_rphy_remove);
1635 1647