aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJason Yan <yanaijie@huawei.com>2017-12-08 04:42:04 -0500
committerMartin K. Petersen <martin.petersen@oracle.com>2018-01-08 21:59:28 -0500
commit1c393b970e0f4070e4376d45f89a2d19a5c895d0 (patch)
tree41706d1df454c4d020a6beaf335b30c27f5f4e20
parent6f5c592ce936b2a2f5d05d3112b550bb039050f2 (diff)
scsi: libsas: Use dynamic alloced work to avoid sas event lost
Now libsas hotplug work is static, every sas event type has its own static work, LLDD driver queues the hotplug work into shost->work_q. If LLDD driver burst posts lots hotplug events to libsas, the hotplug events may pending in the workqueue like shost->work_q new work[PORTE_BYTES_DMAED] --> |[PHYE_LOSS_OF_SIGNAL][PORTE_BYTES_DMAED] -> processing |<-------wait worker to process-------->| In this case, a new PORTE_BYTES_DMAED event coming, libsas try to queue it to shost->work_q, but this work is already pending, so it would be lost. Finally, libsas delete the related sas port and sas devices, but LLDD driver expect libsas add the sas port and devices(last sas event). This patch use dynamic allocated work to avoid this issue. Signed-off-by: Yijing Wang <wangyijing@huawei.com> CC: John Garry <john.garry@huawei.com> CC: Johannes Thumshirn <jthumshirn@suse.de> CC: Ewan Milne <emilne@redhat.com> CC: Christoph Hellwig <hch@lst.de> CC: Tomas Henzl <thenzl@redhat.com> CC: Dan Williams <dan.j.williams@intel.com> Reviewed-by: Hannes Reinecke <hare@suse.com> Signed-off-by: Jason Yan <yanaijie@huawei.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-rw-r--r--drivers/scsi/libsas/sas_event.c74
-rw-r--r--drivers/scsi/libsas/sas_init.c27
-rw-r--r--drivers/scsi/libsas/sas_internal.h6
-rw-r--r--drivers/scsi/libsas/sas_phy.c44
-rw-r--r--drivers/scsi/libsas/sas_port.c18
-rw-r--r--include/scsi/libsas.h17
6 files changed, 115 insertions, 71 deletions
diff --git a/drivers/scsi/libsas/sas_event.c b/drivers/scsi/libsas/sas_event.c
index 0bb9eefc08c8..5d7254aa2dd2 100644
--- a/drivers/scsi/libsas/sas_event.c
+++ b/drivers/scsi/libsas/sas_event.c
@@ -29,7 +29,8 @@
29 29
30int sas_queue_work(struct sas_ha_struct *ha, struct sas_work *sw) 30int sas_queue_work(struct sas_ha_struct *ha, struct sas_work *sw)
31{ 31{
32 int rc = 0; 32 /* it's added to the defer_q when draining so return succeed */
33 int rc = 1;
33 34
34 if (!test_bit(SAS_HA_REGISTERED, &ha->state)) 35 if (!test_bit(SAS_HA_REGISTERED, &ha->state))
35 return 0; 36 return 0;
@@ -44,19 +45,15 @@ int sas_queue_work(struct sas_ha_struct *ha, struct sas_work *sw)
44 return rc; 45 return rc;
45} 46}
46 47
47static int sas_queue_event(int event, unsigned long *pending, 48static int sas_queue_event(int event, struct sas_work *work,
48 struct sas_work *work,
49 struct sas_ha_struct *ha) 49 struct sas_ha_struct *ha)
50{ 50{
51 int rc = 0; 51 unsigned long flags;
52 int rc;
52 53
53 if (!test_and_set_bit(event, pending)) { 54 spin_lock_irqsave(&ha->lock, flags);
54 unsigned long flags; 55 rc = sas_queue_work(ha, work);
55 56 spin_unlock_irqrestore(&ha->lock, flags);
56 spin_lock_irqsave(&ha->lock, flags);
57 rc = sas_queue_work(ha, work);
58 spin_unlock_irqrestore(&ha->lock, flags);
59 }
60 57
61 return rc; 58 return rc;
62} 59}
@@ -66,6 +63,7 @@ void __sas_drain_work(struct sas_ha_struct *ha)
66{ 63{
67 struct workqueue_struct *wq = ha->core.shost->work_q; 64 struct workqueue_struct *wq = ha->core.shost->work_q;
68 struct sas_work *sw, *_sw; 65 struct sas_work *sw, *_sw;
66 int ret;
69 67
70 set_bit(SAS_HA_DRAINING, &ha->state); 68 set_bit(SAS_HA_DRAINING, &ha->state);
71 /* flush submitters */ 69 /* flush submitters */
@@ -78,7 +76,10 @@ void __sas_drain_work(struct sas_ha_struct *ha)
78 clear_bit(SAS_HA_DRAINING, &ha->state); 76 clear_bit(SAS_HA_DRAINING, &ha->state);
79 list_for_each_entry_safe(sw, _sw, &ha->defer_q, drain_node) { 77 list_for_each_entry_safe(sw, _sw, &ha->defer_q, drain_node) {
80 list_del_init(&sw->drain_node); 78 list_del_init(&sw->drain_node);
81 sas_queue_work(ha, sw); 79 ret = sas_queue_work(ha, sw);
80 if (ret != 1)
81 sas_free_event(to_asd_sas_event(&sw->work));
82
82 } 83 }
83 spin_unlock_irq(&ha->lock); 84 spin_unlock_irq(&ha->lock);
84} 85}
@@ -119,29 +120,68 @@ void sas_enable_revalidation(struct sas_ha_struct *ha)
119 if (!test_and_clear_bit(ev, &d->pending)) 120 if (!test_and_clear_bit(ev, &d->pending))
120 continue; 121 continue;
121 122
122 sas_queue_event(ev, &d->pending, &d->disc_work[ev].work, ha); 123 sas_queue_event(ev, &d->disc_work[ev].work, ha);
123 } 124 }
124 mutex_unlock(&ha->disco_mutex); 125 mutex_unlock(&ha->disco_mutex);
125} 126}
126 127
128
129static void sas_port_event_worker(struct work_struct *work)
130{
131 struct asd_sas_event *ev = to_asd_sas_event(work);
132
133 sas_port_event_fns[ev->event](work);
134 sas_free_event(ev);
135}
136
137static void sas_phy_event_worker(struct work_struct *work)
138{
139 struct asd_sas_event *ev = to_asd_sas_event(work);
140
141 sas_phy_event_fns[ev->event](work);
142 sas_free_event(ev);
143}
144
127static int sas_notify_port_event(struct asd_sas_phy *phy, enum port_event event) 145static int sas_notify_port_event(struct asd_sas_phy *phy, enum port_event event)
128{ 146{
147 struct asd_sas_event *ev;
129 struct sas_ha_struct *ha = phy->ha; 148 struct sas_ha_struct *ha = phy->ha;
149 int ret;
130 150
131 BUG_ON(event >= PORT_NUM_EVENTS); 151 BUG_ON(event >= PORT_NUM_EVENTS);
132 152
133 return sas_queue_event(event, &phy->port_events_pending, 153 ev = sas_alloc_event(phy);
134 &phy->port_events[event].work, ha); 154 if (!ev)
155 return -ENOMEM;
156
157 INIT_SAS_EVENT(ev, sas_port_event_worker, phy, event);
158
159 ret = sas_queue_event(event, &ev->work, ha);
160 if (ret != 1)
161 sas_free_event(ev);
162
163 return ret;
135} 164}
136 165
137int sas_notify_phy_event(struct asd_sas_phy *phy, enum phy_event event) 166int sas_notify_phy_event(struct asd_sas_phy *phy, enum phy_event event)
138{ 167{
168 struct asd_sas_event *ev;
139 struct sas_ha_struct *ha = phy->ha; 169 struct sas_ha_struct *ha = phy->ha;
170 int ret;
140 171
141 BUG_ON(event >= PHY_NUM_EVENTS); 172 BUG_ON(event >= PHY_NUM_EVENTS);
142 173
143 return sas_queue_event(event, &phy->phy_events_pending, 174 ev = sas_alloc_event(phy);
144 &phy->phy_events[event].work, ha); 175 if (!ev)
176 return -ENOMEM;
177
178 INIT_SAS_EVENT(ev, sas_phy_event_worker, phy, event);
179
180 ret = sas_queue_event(event, &ev->work, ha);
181 if (ret != 1)
182 sas_free_event(ev);
183
184 return ret;
145} 185}
146 186
147int sas_init_events(struct sas_ha_struct *sas_ha) 187int sas_init_events(struct sas_ha_struct *sas_ha)
diff --git a/drivers/scsi/libsas/sas_init.c b/drivers/scsi/libsas/sas_init.c
index 64fa6f53cb8b..e04f6d6f5aff 100644
--- a/drivers/scsi/libsas/sas_init.c
+++ b/drivers/scsi/libsas/sas_init.c
@@ -39,6 +39,7 @@
39#include "../scsi_sas_internal.h" 39#include "../scsi_sas_internal.h"
40 40
41static struct kmem_cache *sas_task_cache; 41static struct kmem_cache *sas_task_cache;
42static struct kmem_cache *sas_event_cache;
42 43
43struct sas_task *sas_alloc_task(gfp_t flags) 44struct sas_task *sas_alloc_task(gfp_t flags)
44{ 45{
@@ -364,8 +365,6 @@ void sas_prep_resume_ha(struct sas_ha_struct *ha)
364 struct asd_sas_phy *phy = ha->sas_phy[i]; 365 struct asd_sas_phy *phy = ha->sas_phy[i];
365 366
366 memset(phy->attached_sas_addr, 0, SAS_ADDR_SIZE); 367 memset(phy->attached_sas_addr, 0, SAS_ADDR_SIZE);
367 phy->port_events_pending = 0;
368 phy->phy_events_pending = 0;
369 phy->frame_rcvd_size = 0; 368 phy->frame_rcvd_size = 0;
370 } 369 }
371} 370}
@@ -555,20 +554,42 @@ sas_domain_attach_transport(struct sas_domain_function_template *dft)
555} 554}
556EXPORT_SYMBOL_GPL(sas_domain_attach_transport); 555EXPORT_SYMBOL_GPL(sas_domain_attach_transport);
557 556
557
558struct asd_sas_event *sas_alloc_event(struct asd_sas_phy *phy)
559{
560 gfp_t flags = in_interrupt() ? GFP_ATOMIC : GFP_KERNEL;
561
562 return kmem_cache_zalloc(sas_event_cache, flags);
563}
564
565void sas_free_event(struct asd_sas_event *event)
566{
567 kmem_cache_free(sas_event_cache, event);
568}
569
558/* ---------- SAS Class register/unregister ---------- */ 570/* ---------- SAS Class register/unregister ---------- */
559 571
560static int __init sas_class_init(void) 572static int __init sas_class_init(void)
561{ 573{
562 sas_task_cache = KMEM_CACHE(sas_task, SLAB_HWCACHE_ALIGN); 574 sas_task_cache = KMEM_CACHE(sas_task, SLAB_HWCACHE_ALIGN);
563 if (!sas_task_cache) 575 if (!sas_task_cache)
564 return -ENOMEM; 576 goto out;
577
578 sas_event_cache = KMEM_CACHE(asd_sas_event, SLAB_HWCACHE_ALIGN);
579 if (!sas_event_cache)
580 goto free_task_kmem;
565 581
566 return 0; 582 return 0;
583free_task_kmem:
584 kmem_cache_destroy(sas_task_cache);
585out:
586 return -ENOMEM;
567} 587}
568 588
569static void __exit sas_class_exit(void) 589static void __exit sas_class_exit(void)
570{ 590{
571 kmem_cache_destroy(sas_task_cache); 591 kmem_cache_destroy(sas_task_cache);
592 kmem_cache_destroy(sas_event_cache);
572} 593}
573 594
574MODULE_AUTHOR("Luben Tuikov <luben_tuikov@adaptec.com>"); 595MODULE_AUTHOR("Luben Tuikov <luben_tuikov@adaptec.com>");
diff --git a/drivers/scsi/libsas/sas_internal.h b/drivers/scsi/libsas/sas_internal.h
index c07e08136491..d8826a747690 100644
--- a/drivers/scsi/libsas/sas_internal.h
+++ b/drivers/scsi/libsas/sas_internal.h
@@ -61,6 +61,9 @@ int sas_show_oob_mode(enum sas_oob_mode oob_mode, char *buf);
61int sas_register_phys(struct sas_ha_struct *sas_ha); 61int sas_register_phys(struct sas_ha_struct *sas_ha);
62void sas_unregister_phys(struct sas_ha_struct *sas_ha); 62void sas_unregister_phys(struct sas_ha_struct *sas_ha);
63 63
64struct asd_sas_event *sas_alloc_event(struct asd_sas_phy *phy);
65void sas_free_event(struct asd_sas_event *event);
66
64int sas_register_ports(struct sas_ha_struct *sas_ha); 67int sas_register_ports(struct sas_ha_struct *sas_ha);
65void sas_unregister_ports(struct sas_ha_struct *sas_ha); 68void sas_unregister_ports(struct sas_ha_struct *sas_ha);
66 69
@@ -99,6 +102,9 @@ void sas_hae_reset(struct work_struct *work);
99 102
100void sas_free_device(struct kref *kref); 103void sas_free_device(struct kref *kref);
101 104
105extern const work_func_t sas_phy_event_fns[PHY_NUM_EVENTS];
106extern const work_func_t sas_port_event_fns[PORT_NUM_EVENTS];
107
102#ifdef CONFIG_SCSI_SAS_HOST_SMP 108#ifdef CONFIG_SCSI_SAS_HOST_SMP
103extern void sas_smp_host_handler(struct bsg_job *job, struct Scsi_Host *shost); 109extern void sas_smp_host_handler(struct bsg_job *job, struct Scsi_Host *shost);
104#else 110#else
diff --git a/drivers/scsi/libsas/sas_phy.c b/drivers/scsi/libsas/sas_phy.c
index cdee446c29e1..59f82929b0a3 100644
--- a/drivers/scsi/libsas/sas_phy.c
+++ b/drivers/scsi/libsas/sas_phy.c
@@ -35,7 +35,6 @@ static void sas_phye_loss_of_signal(struct work_struct *work)
35 struct asd_sas_event *ev = to_asd_sas_event(work); 35 struct asd_sas_event *ev = to_asd_sas_event(work);
36 struct asd_sas_phy *phy = ev->phy; 36 struct asd_sas_phy *phy = ev->phy;
37 37
38 clear_bit(PHYE_LOSS_OF_SIGNAL, &phy->phy_events_pending);
39 phy->error = 0; 38 phy->error = 0;
40 sas_deform_port(phy, 1); 39 sas_deform_port(phy, 1);
41} 40}
@@ -45,7 +44,6 @@ static void sas_phye_oob_done(struct work_struct *work)
45 struct asd_sas_event *ev = to_asd_sas_event(work); 44 struct asd_sas_event *ev = to_asd_sas_event(work);
46 struct asd_sas_phy *phy = ev->phy; 45 struct asd_sas_phy *phy = ev->phy;
47 46
48 clear_bit(PHYE_OOB_DONE, &phy->phy_events_pending);
49 phy->error = 0; 47 phy->error = 0;
50} 48}
51 49
@@ -58,8 +56,6 @@ static void sas_phye_oob_error(struct work_struct *work)
58 struct sas_internal *i = 56 struct sas_internal *i =
59 to_sas_internal(sas_ha->core.shost->transportt); 57 to_sas_internal(sas_ha->core.shost->transportt);
60 58
61 clear_bit(PHYE_OOB_ERROR, &phy->phy_events_pending);
62
63 sas_deform_port(phy, 1); 59 sas_deform_port(phy, 1);
64 60
65 if (!port && phy->enabled && i->dft->lldd_control_phy) { 61 if (!port && phy->enabled && i->dft->lldd_control_phy) {
@@ -88,8 +84,6 @@ static void sas_phye_spinup_hold(struct work_struct *work)
88 struct sas_internal *i = 84 struct sas_internal *i =
89 to_sas_internal(sas_ha->core.shost->transportt); 85 to_sas_internal(sas_ha->core.shost->transportt);
90 86
91 clear_bit(PHYE_SPINUP_HOLD, &phy->phy_events_pending);
92
93 phy->error = 0; 87 phy->error = 0;
94 i->dft->lldd_control_phy(phy, PHY_FUNC_RELEASE_SPINUP_HOLD, NULL); 88 i->dft->lldd_control_phy(phy, PHY_FUNC_RELEASE_SPINUP_HOLD, NULL);
95} 89}
@@ -99,8 +93,6 @@ static void sas_phye_resume_timeout(struct work_struct *work)
99 struct asd_sas_event *ev = to_asd_sas_event(work); 93 struct asd_sas_event *ev = to_asd_sas_event(work);
100 struct asd_sas_phy *phy = ev->phy; 94 struct asd_sas_phy *phy = ev->phy;
101 95
102 clear_bit(PHYE_RESUME_TIMEOUT, &phy->phy_events_pending);
103
104 /* phew, lldd got the phy back in the nick of time */ 96 /* phew, lldd got the phy back in the nick of time */
105 if (!phy->suspended) { 97 if (!phy->suspended) {
106 dev_info(&phy->phy->dev, "resume timeout cancelled\n"); 98 dev_info(&phy->phy->dev, "resume timeout cancelled\n");
@@ -119,39 +111,12 @@ int sas_register_phys(struct sas_ha_struct *sas_ha)
119{ 111{
120 int i; 112 int i;
121 113
122 static const work_func_t sas_phy_event_fns[PHY_NUM_EVENTS] = {
123 [PHYE_LOSS_OF_SIGNAL] = sas_phye_loss_of_signal,
124 [PHYE_OOB_DONE] = sas_phye_oob_done,
125 [PHYE_OOB_ERROR] = sas_phye_oob_error,
126 [PHYE_SPINUP_HOLD] = sas_phye_spinup_hold,
127 [PHYE_RESUME_TIMEOUT] = sas_phye_resume_timeout,
128
129 };
130
131 static const work_func_t sas_port_event_fns[PORT_NUM_EVENTS] = {
132 [PORTE_BYTES_DMAED] = sas_porte_bytes_dmaed,
133 [PORTE_BROADCAST_RCVD] = sas_porte_broadcast_rcvd,
134 [PORTE_LINK_RESET_ERR] = sas_porte_link_reset_err,
135 [PORTE_TIMER_EVENT] = sas_porte_timer_event,
136 [PORTE_HARD_RESET] = sas_porte_hard_reset,
137 };
138
139 /* Now register the phys. */ 114 /* Now register the phys. */
140 for (i = 0; i < sas_ha->num_phys; i++) { 115 for (i = 0; i < sas_ha->num_phys; i++) {
141 int k;
142 struct asd_sas_phy *phy = sas_ha->sas_phy[i]; 116 struct asd_sas_phy *phy = sas_ha->sas_phy[i];
143 117
144 phy->error = 0; 118 phy->error = 0;
145 INIT_LIST_HEAD(&phy->port_phy_el); 119 INIT_LIST_HEAD(&phy->port_phy_el);
146 for (k = 0; k < PORT_NUM_EVENTS; k++) {
147 INIT_SAS_WORK(&phy->port_events[k].work, sas_port_event_fns[k]);
148 phy->port_events[k].phy = phy;
149 }
150
151 for (k = 0; k < PHY_NUM_EVENTS; k++) {
152 INIT_SAS_WORK(&phy->phy_events[k].work, sas_phy_event_fns[k]);
153 phy->phy_events[k].phy = phy;
154 }
155 120
156 phy->port = NULL; 121 phy->port = NULL;
157 phy->ha = sas_ha; 122 phy->ha = sas_ha;
@@ -179,3 +144,12 @@ int sas_register_phys(struct sas_ha_struct *sas_ha)
179 144
180 return 0; 145 return 0;
181} 146}
147
148const work_func_t sas_phy_event_fns[PHY_NUM_EVENTS] = {
149 [PHYE_LOSS_OF_SIGNAL] = sas_phye_loss_of_signal,
150 [PHYE_OOB_DONE] = sas_phye_oob_done,
151 [PHYE_OOB_ERROR] = sas_phye_oob_error,
152 [PHYE_SPINUP_HOLD] = sas_phye_spinup_hold,
153 [PHYE_RESUME_TIMEOUT] = sas_phye_resume_timeout,
154
155};
diff --git a/drivers/scsi/libsas/sas_port.c b/drivers/scsi/libsas/sas_port.c
index d3c5297c6c89..93266283f51f 100644
--- a/drivers/scsi/libsas/sas_port.c
+++ b/drivers/scsi/libsas/sas_port.c
@@ -261,8 +261,6 @@ void sas_porte_bytes_dmaed(struct work_struct *work)
261 struct asd_sas_event *ev = to_asd_sas_event(work); 261 struct asd_sas_event *ev = to_asd_sas_event(work);
262 struct asd_sas_phy *phy = ev->phy; 262 struct asd_sas_phy *phy = ev->phy;
263 263
264 clear_bit(PORTE_BYTES_DMAED, &phy->port_events_pending);
265
266 sas_form_port(phy); 264 sas_form_port(phy);
267} 265}
268 266
@@ -273,8 +271,6 @@ void sas_porte_broadcast_rcvd(struct work_struct *work)
273 unsigned long flags; 271 unsigned long flags;
274 u32 prim; 272 u32 prim;
275 273
276 clear_bit(PORTE_BROADCAST_RCVD, &phy->port_events_pending);
277
278 spin_lock_irqsave(&phy->sas_prim_lock, flags); 274 spin_lock_irqsave(&phy->sas_prim_lock, flags);
279 prim = phy->sas_prim; 275 prim = phy->sas_prim;
280 spin_unlock_irqrestore(&phy->sas_prim_lock, flags); 276 spin_unlock_irqrestore(&phy->sas_prim_lock, flags);
@@ -288,8 +284,6 @@ void sas_porte_link_reset_err(struct work_struct *work)
288 struct asd_sas_event *ev = to_asd_sas_event(work); 284 struct asd_sas_event *ev = to_asd_sas_event(work);
289 struct asd_sas_phy *phy = ev->phy; 285 struct asd_sas_phy *phy = ev->phy;
290 286
291 clear_bit(PORTE_LINK_RESET_ERR, &phy->port_events_pending);
292
293 sas_deform_port(phy, 1); 287 sas_deform_port(phy, 1);
294} 288}
295 289
@@ -298,8 +292,6 @@ void sas_porte_timer_event(struct work_struct *work)
298 struct asd_sas_event *ev = to_asd_sas_event(work); 292 struct asd_sas_event *ev = to_asd_sas_event(work);
299 struct asd_sas_phy *phy = ev->phy; 293 struct asd_sas_phy *phy = ev->phy;
300 294
301 clear_bit(PORTE_TIMER_EVENT, &phy->port_events_pending);
302
303 sas_deform_port(phy, 1); 295 sas_deform_port(phy, 1);
304} 296}
305 297
@@ -308,8 +300,6 @@ void sas_porte_hard_reset(struct work_struct *work)
308 struct asd_sas_event *ev = to_asd_sas_event(work); 300 struct asd_sas_event *ev = to_asd_sas_event(work);
309 struct asd_sas_phy *phy = ev->phy; 301 struct asd_sas_phy *phy = ev->phy;
310 302
311 clear_bit(PORTE_HARD_RESET, &phy->port_events_pending);
312
313 sas_deform_port(phy, 1); 303 sas_deform_port(phy, 1);
314} 304}
315 305
@@ -353,3 +343,11 @@ void sas_unregister_ports(struct sas_ha_struct *sas_ha)
353 sas_deform_port(sas_ha->sas_phy[i], 0); 343 sas_deform_port(sas_ha->sas_phy[i], 0);
354 344
355} 345}
346
347const work_func_t sas_port_event_fns[PORT_NUM_EVENTS] = {
348 [PORTE_BYTES_DMAED] = sas_porte_bytes_dmaed,
349 [PORTE_BROADCAST_RCVD] = sas_porte_broadcast_rcvd,
350 [PORTE_LINK_RESET_ERR] = sas_porte_link_reset_err,
351 [PORTE_TIMER_EVENT] = sas_porte_timer_event,
352 [PORTE_HARD_RESET] = sas_porte_hard_reset,
353};
diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h
index 0f9cbf96c093..ee1b25299dd6 100644
--- a/include/scsi/libsas.h
+++ b/include/scsi/libsas.h
@@ -292,6 +292,7 @@ struct asd_sas_port {
292struct asd_sas_event { 292struct asd_sas_event {
293 struct sas_work work; 293 struct sas_work work;
294 struct asd_sas_phy *phy; 294 struct asd_sas_phy *phy;
295 int event;
295}; 296};
296 297
297static inline struct asd_sas_event *to_asd_sas_event(struct work_struct *work) 298static inline struct asd_sas_event *to_asd_sas_event(struct work_struct *work)
@@ -301,17 +302,21 @@ static inline struct asd_sas_event *to_asd_sas_event(struct work_struct *work)
301 return ev; 302 return ev;
302} 303}
303 304
305static inline void INIT_SAS_EVENT(struct asd_sas_event *ev,
306 void (*fn)(struct work_struct *),
307 struct asd_sas_phy *phy, int event)
308{
309 INIT_SAS_WORK(&ev->work, fn);
310 ev->phy = phy;
311 ev->event = event;
312}
313
314
304/* The phy pretty much is controlled by the LLDD. 315/* The phy pretty much is controlled by the LLDD.
305 * The class only reads those fields. 316 * The class only reads those fields.
306 */ 317 */
307struct asd_sas_phy { 318struct asd_sas_phy {
308/* private: */ 319/* private: */
309 struct asd_sas_event port_events[PORT_NUM_EVENTS];
310 struct asd_sas_event phy_events[PHY_NUM_EVENTS];
311
312 unsigned long port_events_pending;
313 unsigned long phy_events_pending;
314
315 int error; 320 int error;
316 int suspended; 321 int suspended;
317 322