aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/libsas/sas_ata.c1
-rw-r--r--drivers/scsi/libsas/sas_discover.c32
-rw-r--r--drivers/scsi/libsas/sas_expander.c8
-rw-r--r--drivers/scsi/libsas/sas_internal.h1
-rw-r--r--drivers/scsi/libsas/sas_port.c3
-rw-r--r--include/scsi/libsas.h3
-rw-r--r--include/scsi/scsi_transport_sas.h1
7 files changed, 27 insertions, 22 deletions
diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c
index 70be4425ae0b..2b3637b40dde 100644
--- a/drivers/scsi/libsas/sas_ata.c
+++ b/drivers/scsi/libsas/sas_ata.c
@@ -730,7 +730,6 @@ int sas_discover_sata(struct domain_device *dev)
730 if (res) 730 if (res)
731 return res; 731 return res;
732 732
733 sas_discover_event(dev->port, DISCE_PROBE);
734 return 0; 733 return 0;
735} 734}
736 735
diff --git a/drivers/scsi/libsas/sas_discover.c b/drivers/scsi/libsas/sas_discover.c
index 14f714d05767..e4fd078e4175 100644
--- a/drivers/scsi/libsas/sas_discover.c
+++ b/drivers/scsi/libsas/sas_discover.c
@@ -212,13 +212,9 @@ void sas_notify_lldd_dev_gone(struct domain_device *dev)
212 } 212 }
213} 213}
214 214
215static void sas_probe_devices(struct work_struct *work) 215static void sas_probe_devices(struct asd_sas_port *port)
216{ 216{
217 struct domain_device *dev, *n; 217 struct domain_device *dev, *n;
218 struct sas_discovery_event *ev = to_sas_discovery_event(work);
219 struct asd_sas_port *port = ev->port;
220
221 clear_bit(DISCE_PROBE, &port->disc.pending);
222 218
223 /* devices must be domain members before link recovery and probe */ 219 /* devices must be domain members before link recovery and probe */
224 list_for_each_entry(dev, &port->disco_list, disco_list_node) { 220 list_for_each_entry(dev, &port->disco_list, disco_list_node) {
@@ -294,7 +290,6 @@ int sas_discover_end_dev(struct domain_device *dev)
294 res = sas_notify_lldd_dev_found(dev); 290 res = sas_notify_lldd_dev_found(dev);
295 if (res) 291 if (res)
296 return res; 292 return res;
297 sas_discover_event(dev->port, DISCE_PROBE);
298 293
299 return 0; 294 return 0;
300} 295}
@@ -353,13 +348,9 @@ static void sas_unregister_common_dev(struct asd_sas_port *port, struct domain_d
353 sas_put_device(dev); 348 sas_put_device(dev);
354} 349}
355 350
356static void sas_destruct_devices(struct work_struct *work) 351void sas_destruct_devices(struct asd_sas_port *port)
357{ 352{
358 struct domain_device *dev, *n; 353 struct domain_device *dev, *n;
359 struct sas_discovery_event *ev = to_sas_discovery_event(work);
360 struct asd_sas_port *port = ev->port;
361
362 clear_bit(DISCE_DESTRUCT, &port->disc.pending);
363 354
364 list_for_each_entry_safe(dev, n, &port->destroy_list, disco_list_node) { 355 list_for_each_entry_safe(dev, n, &port->destroy_list, disco_list_node) {
365 list_del_init(&dev->disco_list_node); 356 list_del_init(&dev->disco_list_node);
@@ -370,6 +361,16 @@ static void sas_destruct_devices(struct work_struct *work)
370 } 361 }
371} 362}
372 363
364static void sas_destruct_ports(struct asd_sas_port *port)
365{
366 struct sas_port *sas_port, *p;
367
368 list_for_each_entry_safe(sas_port, p, &port->sas_port_del_list, del_list) {
369 list_del_init(&sas_port->del_list);
370 sas_port_delete(sas_port);
371 }
372}
373
373void sas_unregister_dev(struct asd_sas_port *port, struct domain_device *dev) 374void sas_unregister_dev(struct asd_sas_port *port, struct domain_device *dev)
374{ 375{
375 if (!test_bit(SAS_DEV_DESTROY, &dev->state) && 376 if (!test_bit(SAS_DEV_DESTROY, &dev->state) &&
@@ -384,7 +385,6 @@ void sas_unregister_dev(struct asd_sas_port *port, struct domain_device *dev)
384 if (!test_and_set_bit(SAS_DEV_DESTROY, &dev->state)) { 385 if (!test_and_set_bit(SAS_DEV_DESTROY, &dev->state)) {
385 sas_rphy_unlink(dev->rphy); 386 sas_rphy_unlink(dev->rphy);
386 list_move_tail(&dev->disco_list_node, &port->destroy_list); 387 list_move_tail(&dev->disco_list_node, &port->destroy_list);
387 sas_discover_event(dev->port, DISCE_DESTRUCT);
388 } 388 }
389} 389}
390 390
@@ -490,6 +490,8 @@ static void sas_discover_domain(struct work_struct *work)
490 port->port_dev = NULL; 490 port->port_dev = NULL;
491 } 491 }
492 492
493 sas_probe_devices(port);
494
493 SAS_DPRINTK("DONE DISCOVERY on port %d, pid:%d, result:%d\n", port->id, 495 SAS_DPRINTK("DONE DISCOVERY on port %d, pid:%d, result:%d\n", port->id,
494 task_pid_nr(current), error); 496 task_pid_nr(current), error);
495} 497}
@@ -523,6 +525,10 @@ static void sas_revalidate_domain(struct work_struct *work)
523 port->id, task_pid_nr(current), res); 525 port->id, task_pid_nr(current), res);
524 out: 526 out:
525 mutex_unlock(&ha->disco_mutex); 527 mutex_unlock(&ha->disco_mutex);
528
529 sas_destruct_devices(port);
530 sas_destruct_ports(port);
531 sas_probe_devices(port);
526} 532}
527 533
528/* ---------- Events ---------- */ 534/* ---------- Events ---------- */
@@ -578,10 +584,8 @@ void sas_init_disc(struct sas_discovery *disc, struct asd_sas_port *port)
578 static const work_func_t sas_event_fns[DISC_NUM_EVENTS] = { 584 static const work_func_t sas_event_fns[DISC_NUM_EVENTS] = {
579 [DISCE_DISCOVER_DOMAIN] = sas_discover_domain, 585 [DISCE_DISCOVER_DOMAIN] = sas_discover_domain,
580 [DISCE_REVALIDATE_DOMAIN] = sas_revalidate_domain, 586 [DISCE_REVALIDATE_DOMAIN] = sas_revalidate_domain,
581 [DISCE_PROBE] = sas_probe_devices,
582 [DISCE_SUSPEND] = sas_suspend_devices, 587 [DISCE_SUSPEND] = sas_suspend_devices,
583 [DISCE_RESUME] = sas_resume_devices, 588 [DISCE_RESUME] = sas_resume_devices,
584 [DISCE_DESTRUCT] = sas_destruct_devices,
585 }; 589 };
586 590
587 disc->pending = 0; 591 disc->pending = 0;
diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c
index a8a57b0593e3..7444d40e261c 100644
--- a/drivers/scsi/libsas/sas_expander.c
+++ b/drivers/scsi/libsas/sas_expander.c
@@ -1916,7 +1916,8 @@ static void sas_unregister_devs_sas_addr(struct domain_device *parent,
1916 sas_port_delete_phy(phy->port, phy->phy); 1916 sas_port_delete_phy(phy->port, phy->phy);
1917 sas_device_set_phy(found, phy->port); 1917 sas_device_set_phy(found, phy->port);
1918 if (phy->port->num_phys == 0) 1918 if (phy->port->num_phys == 0)
1919 sas_port_delete(phy->port); 1919 list_add_tail(&phy->port->del_list,
1920 &parent->port->sas_port_del_list);
1920 phy->port = NULL; 1921 phy->port = NULL;
1921 } 1922 }
1922} 1923}
@@ -2124,7 +2125,7 @@ int sas_ex_revalidate_domain(struct domain_device *port_dev)
2124 struct domain_device *dev = NULL; 2125 struct domain_device *dev = NULL;
2125 2126
2126 res = sas_find_bcast_dev(port_dev, &dev); 2127 res = sas_find_bcast_dev(port_dev, &dev);
2127 while (res == 0 && dev) { 2128 if (res == 0 && dev) {
2128 struct expander_device *ex = &dev->ex_dev; 2129 struct expander_device *ex = &dev->ex_dev;
2129 int i = 0, phy_id; 2130 int i = 0, phy_id;
2130 2131
@@ -2136,9 +2137,6 @@ int sas_ex_revalidate_domain(struct domain_device *port_dev)
2136 res = sas_rediscover(dev, phy_id); 2137 res = sas_rediscover(dev, phy_id);
2137 i = phy_id + 1; 2138 i = phy_id + 1;
2138 } while (i < ex->num_phys); 2139 } while (i < ex->num_phys);
2139
2140 dev = NULL;
2141 res = sas_find_bcast_dev(port_dev, &dev);
2142 } 2140 }
2143 return res; 2141 return res;
2144} 2142}
diff --git a/drivers/scsi/libsas/sas_internal.h b/drivers/scsi/libsas/sas_internal.h
index d8826a747690..50e12d662ffe 100644
--- a/drivers/scsi/libsas/sas_internal.h
+++ b/drivers/scsi/libsas/sas_internal.h
@@ -101,6 +101,7 @@ int sas_try_ata_reset(struct asd_sas_phy *phy);
101void sas_hae_reset(struct work_struct *work); 101void sas_hae_reset(struct work_struct *work);
102 102
103void sas_free_device(struct kref *kref); 103void sas_free_device(struct kref *kref);
104void sas_destruct_devices(struct asd_sas_port *port);
104 105
105extern const work_func_t sas_phy_event_fns[PHY_NUM_EVENTS]; 106extern const work_func_t sas_phy_event_fns[PHY_NUM_EVENTS];
106extern const work_func_t sas_port_event_fns[PORT_NUM_EVENTS]; 107extern const work_func_t sas_port_event_fns[PORT_NUM_EVENTS];
diff --git a/drivers/scsi/libsas/sas_port.c b/drivers/scsi/libsas/sas_port.c
index 64722f42b256..f07e55d3aa73 100644
--- a/drivers/scsi/libsas/sas_port.c
+++ b/drivers/scsi/libsas/sas_port.c
@@ -66,6 +66,7 @@ static void sas_resume_port(struct asd_sas_phy *phy)
66 rc = sas_notify_lldd_dev_found(dev); 66 rc = sas_notify_lldd_dev_found(dev);
67 if (rc) { 67 if (rc) {
68 sas_unregister_dev(port, dev); 68 sas_unregister_dev(port, dev);
69 sas_destruct_devices(port);
69 continue; 70 continue;
70 } 71 }
71 72
@@ -220,6 +221,7 @@ void sas_deform_port(struct asd_sas_phy *phy, int gone)
220 221
221 if (port->num_phys == 1) { 222 if (port->num_phys == 1) {
222 sas_unregister_domain_devices(port, gone); 223 sas_unregister_domain_devices(port, gone);
224 sas_destruct_devices(port);
223 sas_port_delete(port->port); 225 sas_port_delete(port->port);
224 port->port = NULL; 226 port->port = NULL;
225 } else { 227 } else {
@@ -317,6 +319,7 @@ static void sas_init_port(struct asd_sas_port *port,
317 INIT_LIST_HEAD(&port->dev_list); 319 INIT_LIST_HEAD(&port->dev_list);
318 INIT_LIST_HEAD(&port->disco_list); 320 INIT_LIST_HEAD(&port->disco_list);
319 INIT_LIST_HEAD(&port->destroy_list); 321 INIT_LIST_HEAD(&port->destroy_list);
322 INIT_LIST_HEAD(&port->sas_port_del_list);
320 spin_lock_init(&port->phy_list_lock); 323 spin_lock_init(&port->phy_list_lock);
321 INIT_LIST_HEAD(&port->phy_list); 324 INIT_LIST_HEAD(&port->phy_list);
322 port->ha = sas_ha; 325 port->ha = sas_ha;
diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h
index 6255bb5ed1e4..1cab6f7af425 100644
--- a/include/scsi/libsas.h
+++ b/include/scsi/libsas.h
@@ -82,10 +82,8 @@ enum phy_event {
82enum discover_event { 82enum discover_event {
83 DISCE_DISCOVER_DOMAIN = 0U, 83 DISCE_DISCOVER_DOMAIN = 0U,
84 DISCE_REVALIDATE_DOMAIN, 84 DISCE_REVALIDATE_DOMAIN,
85 DISCE_PROBE,
86 DISCE_SUSPEND, 85 DISCE_SUSPEND,
87 DISCE_RESUME, 86 DISCE_RESUME,
88 DISCE_DESTRUCT,
89 DISC_NUM_EVENTS, 87 DISC_NUM_EVENTS,
90}; 88};
91 89
@@ -262,6 +260,7 @@ struct asd_sas_port {
262 struct list_head dev_list; 260 struct list_head dev_list;
263 struct list_head disco_list; 261 struct list_head disco_list;
264 struct list_head destroy_list; 262 struct list_head destroy_list;
263 struct list_head sas_port_del_list;
265 enum sas_linkrate linkrate; 264 enum sas_linkrate linkrate;
266 265
267 struct sas_work work; 266 struct sas_work work;
diff --git a/include/scsi/scsi_transport_sas.h b/include/scsi/scsi_transport_sas.h
index 62895b405933..05ec927a3c72 100644
--- a/include/scsi/scsi_transport_sas.h
+++ b/include/scsi/scsi_transport_sas.h
@@ -156,6 +156,7 @@ struct sas_port {
156 156
157 struct mutex phy_list_mutex; 157 struct mutex phy_list_mutex;
158 struct list_head phy_list; 158 struct list_head phy_list;
159 struct list_head del_list; /* libsas only */
159}; 160};
160 161
161#define dev_to_sas_port(d) \ 162#define dev_to_sas_port(d) \