aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/libsas/sas_discover.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/libsas/sas_discover.c')
-rw-r--r--drivers/scsi/libsas/sas_discover.c61
1 files changed, 35 insertions, 26 deletions
diff --git a/drivers/scsi/libsas/sas_discover.c b/drivers/scsi/libsas/sas_discover.c
index 364679675602..629a0865b130 100644
--- a/drivers/scsi/libsas/sas_discover.c
+++ b/drivers/scsi/libsas/sas_discover.c
@@ -72,6 +72,7 @@ static int sas_get_port_device(struct asd_sas_port *port)
72 struct asd_sas_phy *phy; 72 struct asd_sas_phy *phy;
73 struct sas_rphy *rphy; 73 struct sas_rphy *rphy;
74 struct domain_device *dev; 74 struct domain_device *dev;
75 int rc = -ENODEV;
75 76
76 dev = sas_alloc_device(); 77 dev = sas_alloc_device();
77 if (!dev) 78 if (!dev)
@@ -110,9 +111,16 @@ static int sas_get_port_device(struct asd_sas_port *port)
110 111
111 sas_init_dev(dev); 112 sas_init_dev(dev);
112 113
114 dev->port = port;
113 switch (dev->dev_type) { 115 switch (dev->dev_type) {
114 case SAS_END_DEV:
115 case SATA_DEV: 116 case SATA_DEV:
117 rc = sas_ata_init(dev);
118 if (rc) {
119 rphy = NULL;
120 break;
121 }
122 /* fall through */
123 case SAS_END_DEV:
116 rphy = sas_end_device_alloc(port->port); 124 rphy = sas_end_device_alloc(port->port);
117 break; 125 break;
118 case EDGE_DEV: 126 case EDGE_DEV:
@@ -131,19 +139,14 @@ static int sas_get_port_device(struct asd_sas_port *port)
131 139
132 if (!rphy) { 140 if (!rphy) {
133 sas_put_device(dev); 141 sas_put_device(dev);
134 return -ENODEV; 142 return rc;
135 } 143 }
136 144
137 spin_lock_irq(&port->phy_list_lock);
138 list_for_each_entry(phy, &port->phy_list, port_phy_el)
139 sas_phy_set_target(phy, dev);
140 spin_unlock_irq(&port->phy_list_lock);
141 rphy->identify.phy_identifier = phy->phy->identify.phy_identifier; 145 rphy->identify.phy_identifier = phy->phy->identify.phy_identifier;
142 memcpy(dev->sas_addr, port->attached_sas_addr, SAS_ADDR_SIZE); 146 memcpy(dev->sas_addr, port->attached_sas_addr, SAS_ADDR_SIZE);
143 sas_fill_in_rphy(dev, rphy); 147 sas_fill_in_rphy(dev, rphy);
144 sas_hash_addr(dev->hashed_sas_addr, dev->sas_addr); 148 sas_hash_addr(dev->hashed_sas_addr, dev->sas_addr);
145 port->port_dev = dev; 149 port->port_dev = dev;
146 dev->port = port;
147 dev->linkrate = port->linkrate; 150 dev->linkrate = port->linkrate;
148 dev->min_linkrate = port->linkrate; 151 dev->min_linkrate = port->linkrate;
149 dev->max_linkrate = port->linkrate; 152 dev->max_linkrate = port->linkrate;
@@ -155,6 +158,7 @@ static int sas_get_port_device(struct asd_sas_port *port)
155 sas_device_set_phy(dev, port->port); 158 sas_device_set_phy(dev, port->port);
156 159
157 dev->rphy = rphy; 160 dev->rphy = rphy;
161 get_device(&dev->rphy->dev);
158 162
159 if (dev_is_sata(dev) || dev->dev_type == SAS_END_DEV) 163 if (dev_is_sata(dev) || dev->dev_type == SAS_END_DEV)
160 list_add_tail(&dev->disco_list_node, &port->disco_list); 164 list_add_tail(&dev->disco_list_node, &port->disco_list);
@@ -164,6 +168,11 @@ static int sas_get_port_device(struct asd_sas_port *port)
164 spin_unlock_irq(&port->dev_list_lock); 168 spin_unlock_irq(&port->dev_list_lock);
165 } 169 }
166 170
171 spin_lock_irq(&port->phy_list_lock);
172 list_for_each_entry(phy, &port->phy_list, port_phy_el)
173 sas_phy_set_target(phy, dev);
174 spin_unlock_irq(&port->phy_list_lock);
175
167 return 0; 176 return 0;
168} 177}
169 178
@@ -205,8 +214,7 @@ void sas_notify_lldd_dev_gone(struct domain_device *dev)
205static void sas_probe_devices(struct work_struct *work) 214static void sas_probe_devices(struct work_struct *work)
206{ 215{
207 struct domain_device *dev, *n; 216 struct domain_device *dev, *n;
208 struct sas_discovery_event *ev = 217 struct sas_discovery_event *ev = to_sas_discovery_event(work);
209 container_of(work, struct sas_discovery_event, work);
210 struct asd_sas_port *port = ev->port; 218 struct asd_sas_port *port = ev->port;
211 219
212 clear_bit(DISCE_PROBE, &port->disc.pending); 220 clear_bit(DISCE_PROBE, &port->disc.pending);
@@ -255,6 +263,9 @@ void sas_free_device(struct kref *kref)
255{ 263{
256 struct domain_device *dev = container_of(kref, typeof(*dev), kref); 264 struct domain_device *dev = container_of(kref, typeof(*dev), kref);
257 265
266 put_device(&dev->rphy->dev);
267 dev->rphy = NULL;
268
258 if (dev->parent) 269 if (dev->parent)
259 sas_put_device(dev->parent); 270 sas_put_device(dev->parent);
260 271
@@ -291,8 +302,7 @@ static void sas_unregister_common_dev(struct asd_sas_port *port, struct domain_d
291static void sas_destruct_devices(struct work_struct *work) 302static void sas_destruct_devices(struct work_struct *work)
292{ 303{
293 struct domain_device *dev, *n; 304 struct domain_device *dev, *n;
294 struct sas_discovery_event *ev = 305 struct sas_discovery_event *ev = to_sas_discovery_event(work);
295 container_of(work, struct sas_discovery_event, work);
296 struct asd_sas_port *port = ev->port; 306 struct asd_sas_port *port = ev->port;
297 307
298 clear_bit(DISCE_DESTRUCT, &port->disc.pending); 308 clear_bit(DISCE_DESTRUCT, &port->disc.pending);
@@ -302,7 +312,6 @@ static void sas_destruct_devices(struct work_struct *work)
302 312
303 sas_remove_children(&dev->rphy->dev); 313 sas_remove_children(&dev->rphy->dev);
304 sas_rphy_delete(dev->rphy); 314 sas_rphy_delete(dev->rphy);
305 dev->rphy = NULL;
306 sas_unregister_common_dev(port, dev); 315 sas_unregister_common_dev(port, dev);
307 } 316 }
308} 317}
@@ -314,11 +323,11 @@ void sas_unregister_dev(struct asd_sas_port *port, struct domain_device *dev)
314 /* this rphy never saw sas_rphy_add */ 323 /* this rphy never saw sas_rphy_add */
315 list_del_init(&dev->disco_list_node); 324 list_del_init(&dev->disco_list_node);
316 sas_rphy_free(dev->rphy); 325 sas_rphy_free(dev->rphy);
317 dev->rphy = NULL;
318 sas_unregister_common_dev(port, dev); 326 sas_unregister_common_dev(port, dev);
327 return;
319 } 328 }
320 329
321 if (dev->rphy && !test_and_set_bit(SAS_DEV_DESTROY, &dev->state)) { 330 if (!test_and_set_bit(SAS_DEV_DESTROY, &dev->state)) {
322 sas_rphy_unlink(dev->rphy); 331 sas_rphy_unlink(dev->rphy);
323 list_move_tail(&dev->disco_list_node, &port->destroy_list); 332 list_move_tail(&dev->disco_list_node, &port->destroy_list);
324 sas_discover_event(dev->port, DISCE_DESTRUCT); 333 sas_discover_event(dev->port, DISCE_DESTRUCT);
@@ -377,8 +386,7 @@ static void sas_discover_domain(struct work_struct *work)
377{ 386{
378 struct domain_device *dev; 387 struct domain_device *dev;
379 int error = 0; 388 int error = 0;
380 struct sas_discovery_event *ev = 389 struct sas_discovery_event *ev = to_sas_discovery_event(work);
381 container_of(work, struct sas_discovery_event, work);
382 struct asd_sas_port *port = ev->port; 390 struct asd_sas_port *port = ev->port;
383 391
384 clear_bit(DISCE_DISCOVER_DOMAIN, &port->disc.pending); 392 clear_bit(DISCE_DISCOVER_DOMAIN, &port->disc.pending);
@@ -419,8 +427,6 @@ static void sas_discover_domain(struct work_struct *work)
419 427
420 if (error) { 428 if (error) {
421 sas_rphy_free(dev->rphy); 429 sas_rphy_free(dev->rphy);
422 dev->rphy = NULL;
423
424 list_del_init(&dev->disco_list_node); 430 list_del_init(&dev->disco_list_node);
425 spin_lock_irq(&port->dev_list_lock); 431 spin_lock_irq(&port->dev_list_lock);
426 list_del_init(&dev->dev_list_node); 432 list_del_init(&dev->dev_list_node);
@@ -437,8 +443,7 @@ static void sas_discover_domain(struct work_struct *work)
437static void sas_revalidate_domain(struct work_struct *work) 443static void sas_revalidate_domain(struct work_struct *work)
438{ 444{
439 int res = 0; 445 int res = 0;
440 struct sas_discovery_event *ev = 446 struct sas_discovery_event *ev = to_sas_discovery_event(work);
441 container_of(work, struct sas_discovery_event, work);
442 struct asd_sas_port *port = ev->port; 447 struct asd_sas_port *port = ev->port;
443 struct sas_ha_struct *ha = port->ha; 448 struct sas_ha_struct *ha = port->ha;
444 449
@@ -466,21 +471,25 @@ static void sas_revalidate_domain(struct work_struct *work)
466 471
467/* ---------- Events ---------- */ 472/* ---------- Events ---------- */
468 473
469static void sas_chain_work(struct sas_ha_struct *ha, struct work_struct *work) 474static void sas_chain_work(struct sas_ha_struct *ha, struct sas_work *sw)
470{ 475{
471 /* chained work is not subject to SA_HA_DRAINING or SAS_HA_REGISTERED */ 476 /* chained work is not subject to SA_HA_DRAINING or
472 scsi_queue_work(ha->core.shost, work); 477 * SAS_HA_REGISTERED, because it is either submitted in the
478 * workqueue, or known to be submitted from a context that is
479 * not racing against draining
480 */
481 scsi_queue_work(ha->core.shost, &sw->work);
473} 482}
474 483
475static void sas_chain_event(int event, unsigned long *pending, 484static void sas_chain_event(int event, unsigned long *pending,
476 struct work_struct *work, 485 struct sas_work *sw,
477 struct sas_ha_struct *ha) 486 struct sas_ha_struct *ha)
478{ 487{
479 if (!test_and_set_bit(event, pending)) { 488 if (!test_and_set_bit(event, pending)) {
480 unsigned long flags; 489 unsigned long flags;
481 490
482 spin_lock_irqsave(&ha->state_lock, flags); 491 spin_lock_irqsave(&ha->state_lock, flags);
483 sas_chain_work(ha, work); 492 sas_chain_work(ha, sw);
484 spin_unlock_irqrestore(&ha->state_lock, flags); 493 spin_unlock_irqrestore(&ha->state_lock, flags);
485 } 494 }
486} 495}
@@ -519,7 +528,7 @@ void sas_init_disc(struct sas_discovery *disc, struct asd_sas_port *port)
519 528
520 disc->pending = 0; 529 disc->pending = 0;
521 for (i = 0; i < DISC_NUM_EVENTS; i++) { 530 for (i = 0; i < DISC_NUM_EVENTS; i++) {
522 INIT_WORK(&disc->disc_work[i].work, sas_event_fns[i]); 531 INIT_SAS_WORK(&disc->disc_work[i].work, sas_event_fns[i]);
523 disc->disc_work[i].port = port; 532 disc->disc_work[i].port = port;
524 } 533 }
525} 534}