aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/libsas/sas_discover.c
diff options
context:
space:
mode:
authorJonathan Herman <hermanjl@cs.unc.edu>2013-01-17 16:15:55 -0500
committerJonathan Herman <hermanjl@cs.unc.edu>2013-01-17 16:15:55 -0500
commit8dea78da5cee153b8af9c07a2745f6c55057fe12 (patch)
treea8f4d49d63b1ecc92f2fddceba0655b2472c5bd9 /drivers/scsi/libsas/sas_discover.c
parent406089d01562f1e2bf9f089fd7637009ebaad589 (diff)
Patched in Tegra support.
Diffstat (limited to 'drivers/scsi/libsas/sas_discover.c')
-rw-r--r--drivers/scsi/libsas/sas_discover.c356
1 files changed, 77 insertions, 279 deletions
diff --git a/drivers/scsi/libsas/sas_discover.c b/drivers/scsi/libsas/sas_discover.c
index a0c3003e0c7..f5831930df9 100644
--- a/drivers/scsi/libsas/sas_discover.c
+++ b/drivers/scsi/libsas/sas_discover.c
@@ -24,32 +24,35 @@
24 24
25#include <linux/scatterlist.h> 25#include <linux/scatterlist.h>
26#include <linux/slab.h> 26#include <linux/slab.h>
27#include <linux/async.h>
28#include <scsi/scsi_host.h> 27#include <scsi/scsi_host.h>
29#include <scsi/scsi_eh.h> 28#include <scsi/scsi_eh.h>
30#include "sas_internal.h" 29#include "sas_internal.h"
31 30
32#include <scsi/scsi_transport.h> 31#include <scsi/scsi_transport.h>
33#include <scsi/scsi_transport_sas.h> 32#include <scsi/scsi_transport_sas.h>
34#include <scsi/sas_ata.h>
35#include "../scsi_sas_internal.h" 33#include "../scsi_sas_internal.h"
36 34
37/* ---------- Basic task processing for discovery purposes ---------- */ 35/* ---------- Basic task processing for discovery purposes ---------- */
38 36
39void sas_init_dev(struct domain_device *dev) 37void sas_init_dev(struct domain_device *dev)
40{ 38{
41 switch (dev->dev_type) { 39 INIT_LIST_HEAD(&dev->siblings);
42 case SAS_END_DEV: 40 INIT_LIST_HEAD(&dev->dev_list_node);
43 INIT_LIST_HEAD(&dev->ssp_dev.eh_list_node); 41 switch (dev->dev_type) {
44 break; 42 case SAS_END_DEV:
45 case EDGE_DEV: 43 break;
46 case FANOUT_DEV: 44 case EDGE_DEV:
47 INIT_LIST_HEAD(&dev->ex_dev.children); 45 case FANOUT_DEV:
48 mutex_init(&dev->ex_dev.cmd_mutex); 46 INIT_LIST_HEAD(&dev->ex_dev.children);
49 break; 47 break;
50 default: 48 case SATA_DEV:
51 break; 49 case SATA_PM:
52 } 50 case SATA_PM_PORT:
51 INIT_LIST_HEAD(&dev->sata_dev.children);
52 break;
53 default:
54 break;
55 }
53} 56}
54 57
55/* ---------- Domain device discovery ---------- */ 58/* ---------- Domain device discovery ---------- */
@@ -65,19 +68,19 @@ void sas_init_dev(struct domain_device *dev)
65 */ 68 */
66static int sas_get_port_device(struct asd_sas_port *port) 69static int sas_get_port_device(struct asd_sas_port *port)
67{ 70{
71 unsigned long flags;
68 struct asd_sas_phy *phy; 72 struct asd_sas_phy *phy;
69 struct sas_rphy *rphy; 73 struct sas_rphy *rphy;
70 struct domain_device *dev; 74 struct domain_device *dev;
71 int rc = -ENODEV;
72 75
73 dev = sas_alloc_device(); 76 dev = kzalloc(sizeof(*dev), GFP_KERNEL);
74 if (!dev) 77 if (!dev)
75 return -ENOMEM; 78 return -ENOMEM;
76 79
77 spin_lock_irq(&port->phy_list_lock); 80 spin_lock_irqsave(&port->phy_list_lock, flags);
78 if (list_empty(&port->phy_list)) { 81 if (list_empty(&port->phy_list)) {
79 spin_unlock_irq(&port->phy_list_lock); 82 spin_unlock_irqrestore(&port->phy_list_lock, flags);
80 sas_put_device(dev); 83 kfree(dev);
81 return -ENODEV; 84 return -ENODEV;
82 } 85 }
83 phy = container_of(port->phy_list.next, struct asd_sas_phy, port_phy_el); 86 phy = container_of(port->phy_list.next, struct asd_sas_phy, port_phy_el);
@@ -85,7 +88,7 @@ static int sas_get_port_device(struct asd_sas_port *port)
85 memcpy(dev->frame_rcvd, phy->frame_rcvd, min(sizeof(dev->frame_rcvd), 88 memcpy(dev->frame_rcvd, phy->frame_rcvd, min(sizeof(dev->frame_rcvd),
86 (size_t)phy->frame_rcvd_size)); 89 (size_t)phy->frame_rcvd_size));
87 spin_unlock(&phy->frame_rcvd_lock); 90 spin_unlock(&phy->frame_rcvd_lock);
88 spin_unlock_irq(&port->phy_list_lock); 91 spin_unlock_irqrestore(&port->phy_list_lock, flags);
89 92
90 if (dev->frame_rcvd[0] == 0x34 && port->oob_mode == SATA_OOB_MODE) { 93 if (dev->frame_rcvd[0] == 0x34 && port->oob_mode == SATA_OOB_MODE) {
91 struct dev_to_host_fis *fis = 94 struct dev_to_host_fis *fis =
@@ -107,16 +110,9 @@ static int sas_get_port_device(struct asd_sas_port *port)
107 110
108 sas_init_dev(dev); 111 sas_init_dev(dev);
109 112
110 dev->port = port;
111 switch (dev->dev_type) { 113 switch (dev->dev_type) {
112 case SATA_DEV:
113 rc = sas_ata_init(dev);
114 if (rc) {
115 rphy = NULL;
116 break;
117 }
118 /* fall through */
119 case SAS_END_DEV: 114 case SAS_END_DEV:
115 case SATA_DEV:
120 rphy = sas_end_device_alloc(port->port); 116 rphy = sas_end_device_alloc(port->port);
121 break; 117 break;
122 case EDGE_DEV: 118 case EDGE_DEV:
@@ -134,15 +130,15 @@ static int sas_get_port_device(struct asd_sas_port *port)
134 } 130 }
135 131
136 if (!rphy) { 132 if (!rphy) {
137 sas_put_device(dev); 133 kfree(dev);
138 return rc; 134 return -ENODEV;
139 } 135 }
140
141 rphy->identify.phy_identifier = phy->phy->identify.phy_identifier; 136 rphy->identify.phy_identifier = phy->phy->identify.phy_identifier;
142 memcpy(dev->sas_addr, port->attached_sas_addr, SAS_ADDR_SIZE); 137 memcpy(dev->sas_addr, port->attached_sas_addr, SAS_ADDR_SIZE);
143 sas_fill_in_rphy(dev, rphy); 138 sas_fill_in_rphy(dev, rphy);
144 sas_hash_addr(dev->hashed_sas_addr, dev->sas_addr); 139 sas_hash_addr(dev->hashed_sas_addr, dev->sas_addr);
145 port->port_dev = dev; 140 port->port_dev = dev;
141 dev->port = port;
146 dev->linkrate = port->linkrate; 142 dev->linkrate = port->linkrate;
147 dev->min_linkrate = port->linkrate; 143 dev->min_linkrate = port->linkrate;
148 dev->max_linkrate = port->linkrate; 144 dev->max_linkrate = port->linkrate;
@@ -151,23 +147,11 @@ static int sas_get_port_device(struct asd_sas_port *port)
151 memset(port->disc.eeds_a, 0, SAS_ADDR_SIZE); 147 memset(port->disc.eeds_a, 0, SAS_ADDR_SIZE);
152 memset(port->disc.eeds_b, 0, SAS_ADDR_SIZE); 148 memset(port->disc.eeds_b, 0, SAS_ADDR_SIZE);
153 port->disc.max_level = 0; 149 port->disc.max_level = 0;
154 sas_device_set_phy(dev, port->port);
155 150
156 dev->rphy = rphy; 151 dev->rphy = rphy;
157 get_device(&dev->rphy->dev); 152 spin_lock_irq(&port->dev_list_lock);
158 153 list_add_tail(&dev->dev_list_node, &port->dev_list);
159 if (dev_is_sata(dev) || dev->dev_type == SAS_END_DEV) 154 spin_unlock_irq(&port->dev_list_lock);
160 list_add_tail(&dev->disco_list_node, &port->disco_list);
161 else {
162 spin_lock_irq(&port->dev_list_lock);
163 list_add_tail(&dev->dev_list_node, &port->dev_list);
164 spin_unlock_irq(&port->dev_list_lock);
165 }
166
167 spin_lock_irq(&port->phy_list_lock);
168 list_for_each_entry(phy, &port->phy_list, port_phy_el)
169 sas_phy_set_target(phy, dev);
170 spin_unlock_irq(&port->phy_list_lock);
171 155
172 return 0; 156 return 0;
173} 157}
@@ -181,18 +165,15 @@ int sas_notify_lldd_dev_found(struct domain_device *dev)
181 struct Scsi_Host *shost = sas_ha->core.shost; 165 struct Scsi_Host *shost = sas_ha->core.shost;
182 struct sas_internal *i = to_sas_internal(shost->transportt); 166 struct sas_internal *i = to_sas_internal(shost->transportt);
183 167
184 if (!i->dft->lldd_dev_found) 168 if (i->dft->lldd_dev_found) {
185 return 0; 169 res = i->dft->lldd_dev_found(dev);
186 170 if (res) {
187 res = i->dft->lldd_dev_found(dev); 171 printk("sas: driver on pcidev %s cannot handle "
188 if (res) { 172 "device %llx, error:%d\n",
189 printk("sas: driver on pcidev %s cannot handle " 173 dev_name(sas_ha->dev),
190 "device %llx, error:%d\n", 174 SAS_ADDR(dev->sas_addr), res);
191 dev_name(sas_ha->dev), 175 }
192 SAS_ADDR(dev->sas_addr), res);
193 } 176 }
194 set_bit(SAS_DEV_FOUND, &dev->state);
195 kref_get(&dev->kref);
196 return res; 177 return res;
197} 178}
198 179
@@ -203,83 +184,12 @@ void sas_notify_lldd_dev_gone(struct domain_device *dev)
203 struct Scsi_Host *shost = sas_ha->core.shost; 184 struct Scsi_Host *shost = sas_ha->core.shost;
204 struct sas_internal *i = to_sas_internal(shost->transportt); 185 struct sas_internal *i = to_sas_internal(shost->transportt);
205 186
206 if (!i->dft->lldd_dev_gone) 187 if (i->dft->lldd_dev_gone)
207 return;
208
209 if (test_and_clear_bit(SAS_DEV_FOUND, &dev->state)) {
210 i->dft->lldd_dev_gone(dev); 188 i->dft->lldd_dev_gone(dev);
211 sas_put_device(dev);
212 }
213} 189}
214 190
215static void sas_probe_devices(struct work_struct *work) 191/* ---------- Common/dispatchers ---------- */
216{
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
223 /* devices must be domain members before link recovery and probe */
224 list_for_each_entry(dev, &port->disco_list, disco_list_node) {
225 spin_lock_irq(&port->dev_list_lock);
226 list_add_tail(&dev->dev_list_node, &port->dev_list);
227 spin_unlock_irq(&port->dev_list_lock);
228 }
229
230 sas_probe_sata(port);
231
232 list_for_each_entry_safe(dev, n, &port->disco_list, disco_list_node) {
233 int err;
234
235 err = sas_rphy_add(dev->rphy);
236 if (err)
237 sas_fail_probe(dev, __func__, err);
238 else
239 list_del_init(&dev->disco_list_node);
240 }
241}
242 192
243static void sas_suspend_devices(struct work_struct *work)
244{
245 struct asd_sas_phy *phy;
246 struct domain_device *dev;
247 struct sas_discovery_event *ev = to_sas_discovery_event(work);
248 struct asd_sas_port *port = ev->port;
249 struct Scsi_Host *shost = port->ha->core.shost;
250 struct sas_internal *si = to_sas_internal(shost->transportt);
251
252 clear_bit(DISCE_SUSPEND, &port->disc.pending);
253
254 sas_suspend_sata(port);
255
256 /* lldd is free to forget the domain_device across the
257 * suspension, we force the issue here to keep the reference
258 * counts aligned
259 */
260 list_for_each_entry(dev, &port->dev_list, dev_list_node)
261 sas_notify_lldd_dev_gone(dev);
262
263 /* we are suspending, so we know events are disabled and
264 * phy_list is not being mutated
265 */
266 list_for_each_entry(phy, &port->phy_list, port_phy_el) {
267 if (si->dft->lldd_port_formed)
268 si->dft->lldd_port_deformed(phy);
269 phy->suspended = 1;
270 port->suspended = 1;
271 }
272}
273
274static void sas_resume_devices(struct work_struct *work)
275{
276 struct sas_discovery_event *ev = to_sas_discovery_event(work);
277 struct asd_sas_port *port = ev->port;
278
279 clear_bit(DISCE_RESUME, &port->disc.pending);
280
281 sas_resume_sata(port);
282}
283 193
284/** 194/**
285 * sas_discover_end_dev -- discover an end device (SSP, etc) 195 * sas_discover_end_dev -- discover an end device (SSP, etc)
@@ -293,138 +203,58 @@ int sas_discover_end_dev(struct domain_device *dev)
293 203
294 res = sas_notify_lldd_dev_found(dev); 204 res = sas_notify_lldd_dev_found(dev);
295 if (res) 205 if (res)
296 return res; 206 goto out_err2;
297 sas_discover_event(dev->port, DISCE_PROBE); 207
208 res = sas_rphy_add(dev->rphy);
209 if (res)
210 goto out_err;
298 211
299 return 0; 212 return 0;
213
214out_err:
215 sas_notify_lldd_dev_gone(dev);
216out_err2:
217 return res;
300} 218}
301 219
302/* ---------- Device registration and unregistration ---------- */ 220/* ---------- Device registration and unregistration ---------- */
303 221
304void sas_free_device(struct kref *kref) 222static inline void sas_unregister_common_dev(struct domain_device *dev)
305{
306 struct domain_device *dev = container_of(kref, typeof(*dev), kref);
307
308 put_device(&dev->rphy->dev);
309 dev->rphy = NULL;
310
311 if (dev->parent)
312 sas_put_device(dev->parent);
313
314 sas_port_put_phy(dev->phy);
315 dev->phy = NULL;
316
317 /* remove the phys and ports, everything else should be gone */
318 if (dev->dev_type == EDGE_DEV || dev->dev_type == FANOUT_DEV)
319 kfree(dev->ex_dev.ex_phy);
320
321 if (dev_is_sata(dev) && dev->sata_dev.ap) {
322 ata_sas_port_destroy(dev->sata_dev.ap);
323 dev->sata_dev.ap = NULL;
324 }
325
326 kfree(dev);
327}
328
329static void sas_unregister_common_dev(struct asd_sas_port *port, struct domain_device *dev)
330{ 223{
331 struct sas_ha_struct *ha = port->ha;
332
333 sas_notify_lldd_dev_gone(dev); 224 sas_notify_lldd_dev_gone(dev);
334 if (!dev->parent) 225 if (!dev->parent)
335 dev->port->port_dev = NULL; 226 dev->port->port_dev = NULL;
336 else 227 else
337 list_del_init(&dev->siblings); 228 list_del_init(&dev->siblings);
338
339 spin_lock_irq(&port->dev_list_lock);
340 list_del_init(&dev->dev_list_node); 229 list_del_init(&dev->dev_list_node);
341 if (dev_is_sata(dev))
342 sas_ata_end_eh(dev->sata_dev.ap);
343 spin_unlock_irq(&port->dev_list_lock);
344
345 spin_lock_irq(&ha->lock);
346 if (dev->dev_type == SAS_END_DEV &&
347 !list_empty(&dev->ssp_dev.eh_list_node)) {
348 list_del_init(&dev->ssp_dev.eh_list_node);
349 ha->eh_active--;
350 }
351 spin_unlock_irq(&ha->lock);
352
353 sas_put_device(dev);
354} 230}
355 231
356static void sas_destruct_devices(struct work_struct *work) 232void sas_unregister_dev(struct domain_device *dev)
357{ 233{
358 struct domain_device *dev, *n; 234 if (dev->rphy) {
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
364 list_for_each_entry_safe(dev, n, &port->destroy_list, disco_list_node) {
365 list_del_init(&dev->disco_list_node);
366
367 sas_remove_children(&dev->rphy->dev); 235 sas_remove_children(&dev->rphy->dev);
368 sas_rphy_delete(dev->rphy); 236 sas_rphy_delete(dev->rphy);
369 sas_unregister_common_dev(port, dev); 237 dev->rphy = NULL;
370 }
371}
372
373void sas_unregister_dev(struct asd_sas_port *port, struct domain_device *dev)
374{
375 if (!test_bit(SAS_DEV_DESTROY, &dev->state) &&
376 !list_empty(&dev->disco_list_node)) {
377 /* this rphy never saw sas_rphy_add */
378 list_del_init(&dev->disco_list_node);
379 sas_rphy_free(dev->rphy);
380 sas_unregister_common_dev(port, dev);
381 return;
382 } 238 }
383 239 if (dev->dev_type == EDGE_DEV || dev->dev_type == FANOUT_DEV) {
384 if (!test_and_set_bit(SAS_DEV_DESTROY, &dev->state)) { 240 /* remove the phys and ports, everything else should be gone */
385 sas_rphy_unlink(dev->rphy); 241 kfree(dev->ex_dev.ex_phy);
386 list_move_tail(&dev->disco_list_node, &port->destroy_list); 242 dev->ex_dev.ex_phy = NULL;
387 sas_discover_event(dev->port, DISCE_DESTRUCT);
388 } 243 }
244 sas_unregister_common_dev(dev);
389} 245}
390 246
391void sas_unregister_domain_devices(struct asd_sas_port *port, int gone) 247void sas_unregister_domain_devices(struct asd_sas_port *port)
392{ 248{
393 struct domain_device *dev, *n; 249 struct domain_device *dev, *n;
394 250
395 list_for_each_entry_safe_reverse(dev, n, &port->dev_list, dev_list_node) { 251 list_for_each_entry_safe_reverse(dev,n,&port->dev_list,dev_list_node)
396 if (gone) 252 sas_unregister_dev(dev);
397 set_bit(SAS_DEV_GONE, &dev->state);
398 sas_unregister_dev(port, dev);
399 }
400
401 list_for_each_entry_safe(dev, n, &port->disco_list, disco_list_node)
402 sas_unregister_dev(port, dev);
403 253
404 port->port->rphy = NULL; 254 port->port->rphy = NULL;
405 255
406} 256}
407 257
408void sas_device_set_phy(struct domain_device *dev, struct sas_port *port)
409{
410 struct sas_ha_struct *ha;
411 struct sas_phy *new_phy;
412
413 if (!dev)
414 return;
415
416 ha = dev->port->ha;
417 new_phy = sas_port_get_phy(port);
418
419 /* pin and record last seen phy */
420 spin_lock_irq(&ha->phy_port_lock);
421 if (new_phy) {
422 sas_port_put_phy(dev->phy);
423 dev->phy = new_phy;
424 }
425 spin_unlock_irq(&ha->phy_port_lock);
426}
427
428/* ---------- Discovery and Revalidation ---------- */ 258/* ---------- Discovery and Revalidation ---------- */
429 259
430/** 260/**
@@ -440,10 +270,12 @@ static void sas_discover_domain(struct work_struct *work)
440{ 270{
441 struct domain_device *dev; 271 struct domain_device *dev;
442 int error = 0; 272 int error = 0;
443 struct sas_discovery_event *ev = to_sas_discovery_event(work); 273 struct sas_discovery_event *ev =
274 container_of(work, struct sas_discovery_event, work);
444 struct asd_sas_port *port = ev->port; 275 struct asd_sas_port *port = ev->port;
445 276
446 clear_bit(DISCE_DISCOVER_DOMAIN, &port->disc.pending); 277 sas_begin_event(DISCE_DISCOVER_DOMAIN, &port->disc.disc_event_lock,
278 &port->disc.pending);
447 279
448 if (port->port_dev) 280 if (port->port_dev)
449 return; 281 return;
@@ -481,12 +313,13 @@ static void sas_discover_domain(struct work_struct *work)
481 313
482 if (error) { 314 if (error) {
483 sas_rphy_free(dev->rphy); 315 sas_rphy_free(dev->rphy);
484 list_del_init(&dev->disco_list_node); 316 dev->rphy = NULL;
317
485 spin_lock_irq(&port->dev_list_lock); 318 spin_lock_irq(&port->dev_list_lock);
486 list_del_init(&dev->dev_list_node); 319 list_del_init(&dev->dev_list_node);
487 spin_unlock_irq(&port->dev_list_lock); 320 spin_unlock_irq(&port->dev_list_lock);
488 321
489 sas_put_device(dev); 322 kfree(dev); /* not kobject_register-ed yet */
490 port->port_dev = NULL; 323 port->port_dev = NULL;
491 } 324 }
492 325
@@ -497,57 +330,24 @@ static void sas_discover_domain(struct work_struct *work)
497static void sas_revalidate_domain(struct work_struct *work) 330static void sas_revalidate_domain(struct work_struct *work)
498{ 331{
499 int res = 0; 332 int res = 0;
500 struct sas_discovery_event *ev = to_sas_discovery_event(work); 333 struct sas_discovery_event *ev =
334 container_of(work, struct sas_discovery_event, work);
501 struct asd_sas_port *port = ev->port; 335 struct asd_sas_port *port = ev->port;
502 struct sas_ha_struct *ha = port->ha;
503
504 /* prevent revalidation from finding sata links in recovery */
505 mutex_lock(&ha->disco_mutex);
506 if (test_bit(SAS_HA_ATA_EH_ACTIVE, &ha->state)) {
507 SAS_DPRINTK("REVALIDATION DEFERRED on port %d, pid:%d\n",
508 port->id, task_pid_nr(current));
509 goto out;
510 }
511 336
512 clear_bit(DISCE_REVALIDATE_DOMAIN, &port->disc.pending); 337 sas_begin_event(DISCE_REVALIDATE_DOMAIN, &port->disc.disc_event_lock,
338 &port->disc.pending);
513 339
514 SAS_DPRINTK("REVALIDATING DOMAIN on port %d, pid:%d\n", port->id, 340 SAS_DPRINTK("REVALIDATING DOMAIN on port %d, pid:%d\n", port->id,
515 task_pid_nr(current)); 341 task_pid_nr(current));
516
517 if (port->port_dev) 342 if (port->port_dev)
518 res = sas_ex_revalidate_domain(port->port_dev); 343 res = sas_ex_revalidate_domain(port->port_dev);
519 344
520 SAS_DPRINTK("done REVALIDATING DOMAIN on port %d, pid:%d, res 0x%x\n", 345 SAS_DPRINTK("done REVALIDATING DOMAIN on port %d, pid:%d, res 0x%x\n",
521 port->id, task_pid_nr(current), res); 346 port->id, task_pid_nr(current), res);
522 out:
523 mutex_unlock(&ha->disco_mutex);
524} 347}
525 348
526/* ---------- Events ---------- */ 349/* ---------- Events ---------- */
527 350
528static void sas_chain_work(struct sas_ha_struct *ha, struct sas_work *sw)
529{
530 /* chained work is not subject to SA_HA_DRAINING or
531 * SAS_HA_REGISTERED, because it is either submitted in the
532 * workqueue, or known to be submitted from a context that is
533 * not racing against draining
534 */
535 scsi_queue_work(ha->core.shost, &sw->work);
536}
537
538static void sas_chain_event(int event, unsigned long *pending,
539 struct sas_work *sw,
540 struct sas_ha_struct *ha)
541{
542 if (!test_and_set_bit(event, pending)) {
543 unsigned long flags;
544
545 spin_lock_irqsave(&ha->lock, flags);
546 sas_chain_work(ha, sw);
547 spin_unlock_irqrestore(&ha->lock, flags);
548 }
549}
550
551int sas_discover_event(struct asd_sas_port *port, enum discover_event ev) 351int sas_discover_event(struct asd_sas_port *port, enum discover_event ev)
552{ 352{
553 struct sas_discovery *disc; 353 struct sas_discovery *disc;
@@ -558,7 +358,8 @@ int sas_discover_event(struct asd_sas_port *port, enum discover_event ev)
558 358
559 BUG_ON(ev >= DISC_NUM_EVENTS); 359 BUG_ON(ev >= DISC_NUM_EVENTS);
560 360
561 sas_chain_event(ev, &disc->pending, &disc->disc_work[ev].work, port->ha); 361 sas_queue_event(ev, &disc->disc_event_lock, &disc->pending,
362 &disc->disc_work[ev].work, port->ha);
562 363
563 return 0; 364 return 0;
564} 365}
@@ -576,15 +377,12 @@ void sas_init_disc(struct sas_discovery *disc, struct asd_sas_port *port)
576 static const work_func_t sas_event_fns[DISC_NUM_EVENTS] = { 377 static const work_func_t sas_event_fns[DISC_NUM_EVENTS] = {
577 [DISCE_DISCOVER_DOMAIN] = sas_discover_domain, 378 [DISCE_DISCOVER_DOMAIN] = sas_discover_domain,
578 [DISCE_REVALIDATE_DOMAIN] = sas_revalidate_domain, 379 [DISCE_REVALIDATE_DOMAIN] = sas_revalidate_domain,
579 [DISCE_PROBE] = sas_probe_devices,
580 [DISCE_SUSPEND] = sas_suspend_devices,
581 [DISCE_RESUME] = sas_resume_devices,
582 [DISCE_DESTRUCT] = sas_destruct_devices,
583 }; 380 };
584 381
382 spin_lock_init(&disc->disc_event_lock);
585 disc->pending = 0; 383 disc->pending = 0;
586 for (i = 0; i < DISC_NUM_EVENTS; i++) { 384 for (i = 0; i < DISC_NUM_EVENTS; i++) {
587 INIT_SAS_WORK(&disc->disc_work[i].work, sas_event_fns[i]); 385 INIT_WORK(&disc->disc_work[i].work, sas_event_fns[i]);
588 disc->disc_work[i].port = port; 386 disc->disc_work[i].port = port;
589 } 387 }
590} 388}