diff options
author | Stefano Panella <stefano.panella@csr.com> | 2008-11-04 10:39:08 -0500 |
---|---|---|
committer | David Vrabel <david.vrabel@csr.com> | 2008-11-04 10:55:26 -0500 |
commit | fec1a5932f16c0eb1b3f5ca2e18d81d860924088 (patch) | |
tree | 48836158dbd458bb462b18f4deffa89e9db80376 | |
parent | 6d5a681dfb583b2f1eefe7cd5505419ca2d4d6c8 (diff) |
uwb: per-radio controller event thread and beacon cache
Use an event thread per-radio controller so processing events from one
radio controller doesn't delay another.
A radio controller shouldn't have information on devices seen by a
different radio controller (they may be on different channels) so make the
beacon cache per-radio controller.
Signed-off-by: Stefano Panella <stefano.panella@csr.com>
Signed-off-by: David Vrabel <david.vrabel@csr.com>
-rw-r--r-- | drivers/uwb/beacon.c | 61 | ||||
-rw-r--r-- | drivers/uwb/driver.c | 2 | ||||
-rw-r--r-- | drivers/uwb/lc-rc.c | 21 | ||||
-rw-r--r-- | drivers/uwb/uwb-internal.h | 20 | ||||
-rw-r--r-- | drivers/uwb/uwbd.c | 98 | ||||
-rw-r--r-- | include/linux/uwb.h | 20 |
6 files changed, 100 insertions, 122 deletions
diff --git a/drivers/uwb/beacon.c b/drivers/uwb/beacon.c index ad823987cede..d9f2a8acc593 100644 --- a/drivers/uwb/beacon.c +++ b/drivers/uwb/beacon.c | |||
@@ -168,12 +168,6 @@ out_up: | |||
168 | * FIXME: use something faster for search than a list | 168 | * FIXME: use something faster for search than a list |
169 | */ | 169 | */ |
170 | 170 | ||
171 | struct uwb_beca uwb_beca = { | ||
172 | .list = LIST_HEAD_INIT(uwb_beca.list), | ||
173 | .mutex = __MUTEX_INITIALIZER(uwb_beca.mutex) | ||
174 | }; | ||
175 | |||
176 | |||
177 | void uwb_bce_kfree(struct kref *_bce) | 171 | void uwb_bce_kfree(struct kref *_bce) |
178 | { | 172 | { |
179 | struct uwb_beca_e *bce = container_of(_bce, struct uwb_beca_e, refcnt); | 173 | struct uwb_beca_e *bce = container_of(_bce, struct uwb_beca_e, refcnt); |
@@ -185,10 +179,11 @@ void uwb_bce_kfree(struct kref *_bce) | |||
185 | 179 | ||
186 | /* Find a beacon by dev addr in the cache */ | 180 | /* Find a beacon by dev addr in the cache */ |
187 | static | 181 | static |
188 | struct uwb_beca_e *__uwb_beca_find_bydev(const struct uwb_dev_addr *dev_addr) | 182 | struct uwb_beca_e *__uwb_beca_find_bydev(struct uwb_rc *rc, |
183 | const struct uwb_dev_addr *dev_addr) | ||
189 | { | 184 | { |
190 | struct uwb_beca_e *bce, *next; | 185 | struct uwb_beca_e *bce, *next; |
191 | list_for_each_entry_safe(bce, next, &uwb_beca.list, node) { | 186 | list_for_each_entry_safe(bce, next, &rc->uwb_beca.list, node) { |
192 | d_printf(6, NULL, "looking for addr %02x:%02x in %02x:%02x\n", | 187 | d_printf(6, NULL, "looking for addr %02x:%02x in %02x:%02x\n", |
193 | dev_addr->data[0], dev_addr->data[1], | 188 | dev_addr->data[0], dev_addr->data[1], |
194 | bce->dev_addr.data[0], bce->dev_addr.data[1]); | 189 | bce->dev_addr.data[0], bce->dev_addr.data[1]); |
@@ -202,10 +197,11 @@ out: | |||
202 | 197 | ||
203 | /* Find a beacon by dev addr in the cache */ | 198 | /* Find a beacon by dev addr in the cache */ |
204 | static | 199 | static |
205 | struct uwb_beca_e *__uwb_beca_find_bymac(const struct uwb_mac_addr *mac_addr) | 200 | struct uwb_beca_e *__uwb_beca_find_bymac(struct uwb_rc *rc, |
201 | const struct uwb_mac_addr *mac_addr) | ||
206 | { | 202 | { |
207 | struct uwb_beca_e *bce, *next; | 203 | struct uwb_beca_e *bce, *next; |
208 | list_for_each_entry_safe(bce, next, &uwb_beca.list, node) { | 204 | list_for_each_entry_safe(bce, next, &rc->uwb_beca.list, node) { |
209 | if (!memcmp(bce->mac_addr, mac_addr->data, | 205 | if (!memcmp(bce->mac_addr, mac_addr->data, |
210 | sizeof(struct uwb_mac_addr))) | 206 | sizeof(struct uwb_mac_addr))) |
211 | goto out; | 207 | goto out; |
@@ -229,11 +225,11 @@ struct uwb_dev *uwb_dev_get_by_devaddr(struct uwb_rc *rc, | |||
229 | struct uwb_dev *found = NULL; | 225 | struct uwb_dev *found = NULL; |
230 | struct uwb_beca_e *bce; | 226 | struct uwb_beca_e *bce; |
231 | 227 | ||
232 | mutex_lock(&uwb_beca.mutex); | 228 | mutex_lock(&rc->uwb_beca.mutex); |
233 | bce = __uwb_beca_find_bydev(devaddr); | 229 | bce = __uwb_beca_find_bydev(rc, devaddr); |
234 | if (bce) | 230 | if (bce) |
235 | found = uwb_dev_try_get(rc, bce->uwb_dev); | 231 | found = uwb_dev_try_get(rc, bce->uwb_dev); |
236 | mutex_unlock(&uwb_beca.mutex); | 232 | mutex_unlock(&rc->uwb_beca.mutex); |
237 | 233 | ||
238 | return found; | 234 | return found; |
239 | } | 235 | } |
@@ -249,11 +245,11 @@ struct uwb_dev *uwb_dev_get_by_macaddr(struct uwb_rc *rc, | |||
249 | struct uwb_dev *found = NULL; | 245 | struct uwb_dev *found = NULL; |
250 | struct uwb_beca_e *bce; | 246 | struct uwb_beca_e *bce; |
251 | 247 | ||
252 | mutex_lock(&uwb_beca.mutex); | 248 | mutex_lock(&rc->uwb_beca.mutex); |
253 | bce = __uwb_beca_find_bymac(macaddr); | 249 | bce = __uwb_beca_find_bymac(rc, macaddr); |
254 | if (bce) | 250 | if (bce) |
255 | found = uwb_dev_try_get(rc, bce->uwb_dev); | 251 | found = uwb_dev_try_get(rc, bce->uwb_dev); |
256 | mutex_unlock(&uwb_beca.mutex); | 252 | mutex_unlock(&rc->uwb_beca.mutex); |
257 | 253 | ||
258 | return found; | 254 | return found; |
259 | } | 255 | } |
@@ -274,7 +270,9 @@ static void uwb_beca_e_init(struct uwb_beca_e *bce) | |||
274 | * @bf: Beacon frame (part of b, really) | 270 | * @bf: Beacon frame (part of b, really) |
275 | * @ts_jiffies: Timestamp (in jiffies) when the beacon was received | 271 | * @ts_jiffies: Timestamp (in jiffies) when the beacon was received |
276 | */ | 272 | */ |
277 | struct uwb_beca_e *__uwb_beca_add(struct uwb_rc_evt_beacon *be, | 273 | static |
274 | struct uwb_beca_e *__uwb_beca_add(struct uwb_rc *rc, | ||
275 | struct uwb_rc_evt_beacon *be, | ||
278 | struct uwb_beacon_frame *bf, | 276 | struct uwb_beacon_frame *bf, |
279 | unsigned long ts_jiffies) | 277 | unsigned long ts_jiffies) |
280 | { | 278 | { |
@@ -286,7 +284,7 @@ struct uwb_beca_e *__uwb_beca_add(struct uwb_rc_evt_beacon *be, | |||
286 | uwb_beca_e_init(bce); | 284 | uwb_beca_e_init(bce); |
287 | bce->ts_jiffies = ts_jiffies; | 285 | bce->ts_jiffies = ts_jiffies; |
288 | bce->uwb_dev = NULL; | 286 | bce->uwb_dev = NULL; |
289 | list_add(&bce->node, &uwb_beca.list); | 287 | list_add(&bce->node, &rc->uwb_beca.list); |
290 | return bce; | 288 | return bce; |
291 | } | 289 | } |
292 | 290 | ||
@@ -295,13 +293,13 @@ struct uwb_beca_e *__uwb_beca_add(struct uwb_rc_evt_beacon *be, | |||
295 | * | 293 | * |
296 | * Remove associated devicest too. | 294 | * Remove associated devicest too. |
297 | */ | 295 | */ |
298 | void uwb_beca_purge(void) | 296 | void uwb_beca_purge(struct uwb_rc *rc) |
299 | { | 297 | { |
300 | struct uwb_beca_e *bce, *next; | 298 | struct uwb_beca_e *bce, *next; |
301 | unsigned long expires; | 299 | unsigned long expires; |
302 | 300 | ||
303 | mutex_lock(&uwb_beca.mutex); | 301 | mutex_lock(&rc->uwb_beca.mutex); |
304 | list_for_each_entry_safe(bce, next, &uwb_beca.list, node) { | 302 | list_for_each_entry_safe(bce, next, &rc->uwb_beca.list, node) { |
305 | expires = bce->ts_jiffies + msecs_to_jiffies(beacon_timeout_ms); | 303 | expires = bce->ts_jiffies + msecs_to_jiffies(beacon_timeout_ms); |
306 | if (time_after(jiffies, expires)) { | 304 | if (time_after(jiffies, expires)) { |
307 | uwbd_dev_offair(bce); | 305 | uwbd_dev_offair(bce); |
@@ -309,19 +307,20 @@ void uwb_beca_purge(void) | |||
309 | uwb_bce_put(bce); | 307 | uwb_bce_put(bce); |
310 | } | 308 | } |
311 | } | 309 | } |
312 | mutex_unlock(&uwb_beca.mutex); | 310 | mutex_unlock(&rc->uwb_beca.mutex); |
313 | } | 311 | } |
314 | 312 | ||
315 | /* Clean up the whole beacon cache. Called on shutdown */ | 313 | /* Clean up the whole beacon cache. Called on shutdown */ |
316 | void uwb_beca_release(void) | 314 | void uwb_beca_release(struct uwb_rc *rc) |
317 | { | 315 | { |
318 | struct uwb_beca_e *bce, *next; | 316 | struct uwb_beca_e *bce, *next; |
319 | mutex_lock(&uwb_beca.mutex); | 317 | |
320 | list_for_each_entry_safe(bce, next, &uwb_beca.list, node) { | 318 | mutex_lock(&rc->uwb_beca.mutex); |
319 | list_for_each_entry_safe(bce, next, &rc->uwb_beca.list, node) { | ||
321 | list_del(&bce->node); | 320 | list_del(&bce->node); |
322 | uwb_bce_put(bce); | 321 | uwb_bce_put(bce); |
323 | } | 322 | } |
324 | mutex_unlock(&uwb_beca.mutex); | 323 | mutex_unlock(&rc->uwb_beca.mutex); |
325 | } | 324 | } |
326 | 325 | ||
327 | static void uwb_beacon_print(struct uwb_rc *rc, struct uwb_rc_evt_beacon *be, | 326 | static void uwb_beacon_print(struct uwb_rc *rc, struct uwb_rc_evt_beacon *be, |
@@ -437,18 +436,18 @@ int uwbd_evt_handle_rc_beacon(struct uwb_event *evt) | |||
437 | if (uwb_mac_addr_bcast(&bf->Device_Identifier)) | 436 | if (uwb_mac_addr_bcast(&bf->Device_Identifier)) |
438 | return 0; | 437 | return 0; |
439 | 438 | ||
440 | mutex_lock(&uwb_beca.mutex); | 439 | mutex_lock(&rc->uwb_beca.mutex); |
441 | bce = __uwb_beca_find_bymac(&bf->Device_Identifier); | 440 | bce = __uwb_beca_find_bymac(rc, &bf->Device_Identifier); |
442 | if (bce == NULL) { | 441 | if (bce == NULL) { |
443 | /* Not in there, a new device is pinging */ | 442 | /* Not in there, a new device is pinging */ |
444 | uwb_beacon_print(evt->rc, be, bf); | 443 | uwb_beacon_print(evt->rc, be, bf); |
445 | bce = __uwb_beca_add(be, bf, evt->ts_jiffies); | 444 | bce = __uwb_beca_add(rc, be, bf, evt->ts_jiffies); |
446 | if (bce == NULL) { | 445 | if (bce == NULL) { |
447 | mutex_unlock(&uwb_beca.mutex); | 446 | mutex_unlock(&rc->uwb_beca.mutex); |
448 | return -ENOMEM; | 447 | return -ENOMEM; |
449 | } | 448 | } |
450 | } | 449 | } |
451 | mutex_unlock(&uwb_beca.mutex); | 450 | mutex_unlock(&rc->uwb_beca.mutex); |
452 | 451 | ||
453 | mutex_lock(&bce->mutex); | 452 | mutex_lock(&bce->mutex); |
454 | /* purge old beacon data */ | 453 | /* purge old beacon data */ |
diff --git a/drivers/uwb/driver.c b/drivers/uwb/driver.c index 521cdeb84971..f57c26580de2 100644 --- a/drivers/uwb/driver.c +++ b/drivers/uwb/driver.c | |||
@@ -118,7 +118,6 @@ static int __init uwb_subsys_init(void) | |||
118 | result = class_register(&uwb_rc_class); | 118 | result = class_register(&uwb_rc_class); |
119 | if (result < 0) | 119 | if (result < 0) |
120 | goto error_uwb_rc_class_register; | 120 | goto error_uwb_rc_class_register; |
121 | uwbd_start(); | ||
122 | uwb_dbg_init(); | 121 | uwb_dbg_init(); |
123 | return 0; | 122 | return 0; |
124 | 123 | ||
@@ -132,7 +131,6 @@ module_init(uwb_subsys_init); | |||
132 | static void __exit uwb_subsys_exit(void) | 131 | static void __exit uwb_subsys_exit(void) |
133 | { | 132 | { |
134 | uwb_dbg_exit(); | 133 | uwb_dbg_exit(); |
135 | uwbd_stop(); | ||
136 | class_unregister(&uwb_rc_class); | 134 | class_unregister(&uwb_rc_class); |
137 | uwb_est_destroy(); | 135 | uwb_est_destroy(); |
138 | return; | 136 | return; |
diff --git a/drivers/uwb/lc-rc.c b/drivers/uwb/lc-rc.c index 1129e8767b58..38e3d57ec8f7 100644 --- a/drivers/uwb/lc-rc.c +++ b/drivers/uwb/lc-rc.c | |||
@@ -36,8 +36,6 @@ | |||
36 | #include <linux/etherdevice.h> | 36 | #include <linux/etherdevice.h> |
37 | #include <linux/usb.h> | 37 | #include <linux/usb.h> |
38 | 38 | ||
39 | #define D_LOCAL 1 | ||
40 | #include <linux/uwb/debug.h> | ||
41 | #include "uwb-internal.h" | 39 | #include "uwb-internal.h" |
42 | 40 | ||
43 | static int uwb_rc_index_match(struct device *dev, void *data) | 41 | static int uwb_rc_index_match(struct device *dev, void *data) |
@@ -83,7 +81,6 @@ static void uwb_rc_sys_release(struct device *dev) | |||
83 | 81 | ||
84 | uwb_rc_neh_destroy(rc); | 82 | uwb_rc_neh_destroy(rc); |
85 | uwb_rc_ie_release(rc); | 83 | uwb_rc_ie_release(rc); |
86 | d_printf(1, dev, "freed uwb_rc %p\n", rc); | ||
87 | kfree(rc); | 84 | kfree(rc); |
88 | } | 85 | } |
89 | 86 | ||
@@ -100,6 +97,8 @@ void uwb_rc_init(struct uwb_rc *rc) | |||
100 | rc->scan_type = UWB_SCAN_DISABLED; | 97 | rc->scan_type = UWB_SCAN_DISABLED; |
101 | INIT_LIST_HEAD(&rc->notifs_chain.list); | 98 | INIT_LIST_HEAD(&rc->notifs_chain.list); |
102 | mutex_init(&rc->notifs_chain.mutex); | 99 | mutex_init(&rc->notifs_chain.mutex); |
100 | INIT_LIST_HEAD(&rc->uwb_beca.list); | ||
101 | mutex_init(&rc->uwb_beca.mutex); | ||
103 | uwb_drp_avail_init(rc); | 102 | uwb_drp_avail_init(rc); |
104 | uwb_rc_ie_init(rc); | 103 | uwb_rc_ie_init(rc); |
105 | uwb_rsv_init(rc); | 104 | uwb_rsv_init(rc); |
@@ -250,6 +249,12 @@ int uwb_rc_add(struct uwb_rc *rc, struct device *parent_dev, void *priv) | |||
250 | 249 | ||
251 | rc->priv = priv; | 250 | rc->priv = priv; |
252 | 251 | ||
252 | init_waitqueue_head(&rc->uwbd.wq); | ||
253 | INIT_LIST_HEAD(&rc->uwbd.event_list); | ||
254 | spin_lock_init(&rc->uwbd.event_list_lock); | ||
255 | |||
256 | uwbd_start(rc); | ||
257 | |||
253 | result = rc->start(rc); | 258 | result = rc->start(rc); |
254 | if (result < 0) | 259 | if (result < 0) |
255 | goto error_rc_start; | 260 | goto error_rc_start; |
@@ -284,7 +289,7 @@ error_sys_add: | |||
284 | error_dev_add: | 289 | error_dev_add: |
285 | error_rc_setup: | 290 | error_rc_setup: |
286 | rc->stop(rc); | 291 | rc->stop(rc); |
287 | uwbd_flush(rc); | 292 | uwbd_stop(rc); |
288 | error_rc_start: | 293 | error_rc_start: |
289 | return result; | 294 | return result; |
290 | } | 295 | } |
@@ -315,16 +320,18 @@ void uwb_rc_rm(struct uwb_rc *rc) | |||
315 | uwb_rc_reset(rc); | 320 | uwb_rc_reset(rc); |
316 | 321 | ||
317 | rc->stop(rc); | 322 | rc->stop(rc); |
318 | uwbd_flush(rc); | 323 | |
324 | uwbd_stop(rc); | ||
319 | 325 | ||
320 | uwb_dev_lock(&rc->uwb_dev); | 326 | uwb_dev_lock(&rc->uwb_dev); |
321 | rc->priv = NULL; | 327 | rc->priv = NULL; |
322 | rc->cmd = NULL; | 328 | rc->cmd = NULL; |
323 | uwb_dev_unlock(&rc->uwb_dev); | 329 | uwb_dev_unlock(&rc->uwb_dev); |
324 | mutex_lock(&uwb_beca.mutex); | 330 | mutex_lock(&rc->uwb_beca.mutex); |
325 | uwb_dev_for_each(rc, uwb_dev_offair_helper, NULL); | 331 | uwb_dev_for_each(rc, uwb_dev_offair_helper, NULL); |
326 | __uwb_rc_sys_rm(rc); | 332 | __uwb_rc_sys_rm(rc); |
327 | mutex_unlock(&uwb_beca.mutex); | 333 | mutex_unlock(&rc->uwb_beca.mutex); |
334 | uwb_beca_release(rc); | ||
328 | uwb_dev_rm(&rc->uwb_dev); | 335 | uwb_dev_rm(&rc->uwb_dev); |
329 | } | 336 | } |
330 | EXPORT_SYMBOL_GPL(uwb_rc_rm); | 337 | EXPORT_SYMBOL_GPL(uwb_rc_rm); |
diff --git a/drivers/uwb/uwb-internal.h b/drivers/uwb/uwb-internal.h index 031e8a885681..4c2449679978 100644 --- a/drivers/uwb/uwb-internal.h +++ b/drivers/uwb/uwb-internal.h | |||
@@ -160,8 +160,8 @@ struct uwb_event { | |||
160 | }; | 160 | }; |
161 | }; | 161 | }; |
162 | 162 | ||
163 | extern void uwbd_start(void); | 163 | extern void uwbd_start(struct uwb_rc *rc); |
164 | extern void uwbd_stop(void); | 164 | extern void uwbd_stop(struct uwb_rc *rc); |
165 | extern struct uwb_event *uwb_event_alloc(size_t, gfp_t gfp_mask); | 165 | extern struct uwb_event *uwb_event_alloc(size_t, gfp_t gfp_mask); |
166 | extern void uwbd_event_queue(struct uwb_event *); | 166 | extern void uwbd_event_queue(struct uwb_event *); |
167 | void uwbd_flush(struct uwb_rc *rc); | 167 | void uwbd_flush(struct uwb_rc *rc); |
@@ -194,15 +194,6 @@ int uwbd_evt_handle_rc_dev_addr_conflict(struct uwb_event *evt); | |||
194 | 194 | ||
195 | extern unsigned long beacon_timeout_ms; | 195 | extern unsigned long beacon_timeout_ms; |
196 | 196 | ||
197 | /** Beacon cache list */ | ||
198 | struct uwb_beca { | ||
199 | struct list_head list; | ||
200 | size_t entries; | ||
201 | struct mutex mutex; | ||
202 | }; | ||
203 | |||
204 | extern struct uwb_beca uwb_beca; | ||
205 | |||
206 | /** | 197 | /** |
207 | * Beacon cache entry | 198 | * Beacon cache entry |
208 | * | 199 | * |
@@ -229,9 +220,6 @@ struct uwb_beca_e { | |||
229 | struct uwb_beacon_frame; | 220 | struct uwb_beacon_frame; |
230 | extern ssize_t uwb_bce_print_IEs(struct uwb_dev *, struct uwb_beca_e *, | 221 | extern ssize_t uwb_bce_print_IEs(struct uwb_dev *, struct uwb_beca_e *, |
231 | char *, size_t); | 222 | char *, size_t); |
232 | extern struct uwb_beca_e *__uwb_beca_add(struct uwb_rc_evt_beacon *, | ||
233 | struct uwb_beacon_frame *, | ||
234 | unsigned long); | ||
235 | 223 | ||
236 | extern void uwb_bce_kfree(struct kref *_bce); | 224 | extern void uwb_bce_kfree(struct kref *_bce); |
237 | static inline void uwb_bce_get(struct uwb_beca_e *bce) | 225 | static inline void uwb_bce_get(struct uwb_beca_e *bce) |
@@ -242,8 +230,8 @@ static inline void uwb_bce_put(struct uwb_beca_e *bce) | |||
242 | { | 230 | { |
243 | kref_put(&bce->refcnt, uwb_bce_kfree); | 231 | kref_put(&bce->refcnt, uwb_bce_kfree); |
244 | } | 232 | } |
245 | extern void uwb_beca_purge(void); | 233 | extern void uwb_beca_purge(struct uwb_rc *rc); |
246 | extern void uwb_beca_release(void); | 234 | extern void uwb_beca_release(struct uwb_rc *rc); |
247 | 235 | ||
248 | struct uwb_dev *uwb_dev_get_by_devaddr(struct uwb_rc *rc, | 236 | struct uwb_dev *uwb_dev_get_by_devaddr(struct uwb_rc *rc, |
249 | const struct uwb_dev_addr *devaddr); | 237 | const struct uwb_dev_addr *devaddr); |
diff --git a/drivers/uwb/uwbd.c b/drivers/uwb/uwbd.c index f75113571f4a..ec42ce92dbce 100644 --- a/drivers/uwb/uwbd.c +++ b/drivers/uwb/uwbd.c | |||
@@ -170,8 +170,6 @@ static const struct uwbd_event uwbd_message_handlers[] = { | |||
170 | }, | 170 | }, |
171 | }; | 171 | }; |
172 | 172 | ||
173 | static DEFINE_MUTEX(uwbd_event_mutex); | ||
174 | |||
175 | /** | 173 | /** |
176 | * Handle an URC event passed to the UWB Daemon | 174 | * Handle an URC event passed to the UWB Daemon |
177 | * | 175 | * |
@@ -235,19 +233,10 @@ static void uwbd_event_handle_message(struct uwb_event *evt) | |||
235 | return; | 233 | return; |
236 | } | 234 | } |
237 | 235 | ||
238 | /* If this is a reset event we need to drop the | ||
239 | * uwbd_event_mutex or it deadlocks when the reset handler | ||
240 | * attempts to flush the uwbd events. */ | ||
241 | if (evt->message == UWB_EVT_MSG_RESET) | ||
242 | mutex_unlock(&uwbd_event_mutex); | ||
243 | |||
244 | result = uwbd_message_handlers[evt->message].handler(evt); | 236 | result = uwbd_message_handlers[evt->message].handler(evt); |
245 | if (result < 0) | 237 | if (result < 0) |
246 | dev_err(&rc->uwb_dev.dev, "UWBD: '%s' message failed: %d\n", | 238 | dev_err(&rc->uwb_dev.dev, "UWBD: '%s' message failed: %d\n", |
247 | uwbd_message_handlers[evt->message].name, result); | 239 | uwbd_message_handlers[evt->message].name, result); |
248 | |||
249 | if (evt->message == UWB_EVT_MSG_RESET) | ||
250 | mutex_lock(&uwbd_event_mutex); | ||
251 | } | 240 | } |
252 | 241 | ||
253 | static void uwbd_event_handle(struct uwb_event *evt) | 242 | static void uwbd_event_handle(struct uwb_event *evt) |
@@ -275,20 +264,6 @@ static void uwbd_event_handle(struct uwb_event *evt) | |||
275 | 264 | ||
276 | __uwb_rc_put(rc); /* for the __uwb_rc_get() in uwb_rc_notif_cb() */ | 265 | __uwb_rc_put(rc); /* for the __uwb_rc_get() in uwb_rc_notif_cb() */ |
277 | } | 266 | } |
278 | /* The UWB Daemon */ | ||
279 | |||
280 | |||
281 | /** Daemon's PID: used to decide if we can queue or not */ | ||
282 | static int uwbd_pid; | ||
283 | /** Daemon's task struct for managing the kthread */ | ||
284 | static struct task_struct *uwbd_task; | ||
285 | /** Daemon's waitqueue for waiting for new events */ | ||
286 | static DECLARE_WAIT_QUEUE_HEAD(uwbd_wq); | ||
287 | /** Daemon's list of events; we queue/dequeue here */ | ||
288 | static struct list_head uwbd_event_list = LIST_HEAD_INIT(uwbd_event_list); | ||
289 | /** Daemon's list lock to protect concurent access */ | ||
290 | static DEFINE_SPINLOCK(uwbd_event_list_lock); | ||
291 | |||
292 | 267 | ||
293 | /** | 268 | /** |
294 | * UWB Daemon | 269 | * UWB Daemon |
@@ -302,65 +277,58 @@ static DEFINE_SPINLOCK(uwbd_event_list_lock); | |||
302 | * FIXME: should change so we don't have a 1HZ timer all the time, but | 277 | * FIXME: should change so we don't have a 1HZ timer all the time, but |
303 | * only if there are devices. | 278 | * only if there are devices. |
304 | */ | 279 | */ |
305 | static int uwbd(void *unused) | 280 | static int uwbd(void *param) |
306 | { | 281 | { |
282 | struct uwb_rc *rc = param; | ||
307 | unsigned long flags; | 283 | unsigned long flags; |
308 | struct list_head list = LIST_HEAD_INIT(list); | 284 | struct uwb_event *evt; |
309 | struct uwb_event *evt, *nxt; | ||
310 | int should_stop = 0; | 285 | int should_stop = 0; |
286 | |||
311 | while (1) { | 287 | while (1) { |
312 | wait_event_interruptible_timeout( | 288 | wait_event_interruptible_timeout( |
313 | uwbd_wq, | 289 | rc->uwbd.wq, |
314 | !list_empty(&uwbd_event_list) | 290 | !list_empty(&rc->uwbd.event_list) |
315 | || (should_stop = kthread_should_stop()), | 291 | || (should_stop = kthread_should_stop()), |
316 | HZ); | 292 | HZ); |
317 | if (should_stop) | 293 | if (should_stop) |
318 | break; | 294 | break; |
319 | try_to_freeze(); | 295 | try_to_freeze(); |
320 | 296 | ||
321 | mutex_lock(&uwbd_event_mutex); | 297 | spin_lock_irqsave(&rc->uwbd.event_list_lock, flags); |
322 | spin_lock_irqsave(&uwbd_event_list_lock, flags); | 298 | if (!list_empty(&rc->uwbd.event_list)) { |
323 | list_splice_init(&uwbd_event_list, &list); | 299 | evt = list_first_entry(&rc->uwbd.event_list, struct uwb_event, list_node); |
324 | spin_unlock_irqrestore(&uwbd_event_list_lock, flags); | ||
325 | list_for_each_entry_safe(evt, nxt, &list, list_node) { | ||
326 | list_del(&evt->list_node); | 300 | list_del(&evt->list_node); |
301 | } else | ||
302 | evt = NULL; | ||
303 | spin_unlock_irqrestore(&rc->uwbd.event_list_lock, flags); | ||
304 | |||
305 | if (evt) { | ||
327 | uwbd_event_handle(evt); | 306 | uwbd_event_handle(evt); |
328 | kfree(evt); | 307 | kfree(evt); |
329 | } | 308 | } |
330 | mutex_unlock(&uwbd_event_mutex); | ||
331 | 309 | ||
332 | uwb_beca_purge(); /* Purge devices that left */ | 310 | uwb_beca_purge(rc); /* Purge devices that left */ |
333 | } | 311 | } |
334 | return 0; | 312 | return 0; |
335 | } | 313 | } |
336 | 314 | ||
337 | 315 | ||
338 | /** Start the UWB daemon */ | 316 | /** Start the UWB daemon */ |
339 | void uwbd_start(void) | 317 | void uwbd_start(struct uwb_rc *rc) |
340 | { | 318 | { |
341 | uwbd_task = kthread_run(uwbd, NULL, "uwbd"); | 319 | rc->uwbd.task = kthread_run(uwbd, rc, "uwbd"); |
342 | if (uwbd_task == NULL) | 320 | if (rc->uwbd.task == NULL) |
343 | printk(KERN_ERR "UWB: Cannot start management daemon; " | 321 | printk(KERN_ERR "UWB: Cannot start management daemon; " |
344 | "UWB won't work\n"); | 322 | "UWB won't work\n"); |
345 | else | 323 | else |
346 | uwbd_pid = uwbd_task->pid; | 324 | rc->uwbd.pid = rc->uwbd.task->pid; |
347 | } | 325 | } |
348 | 326 | ||
349 | /* Stop the UWB daemon and free any unprocessed events */ | 327 | /* Stop the UWB daemon and free any unprocessed events */ |
350 | void uwbd_stop(void) | 328 | void uwbd_stop(struct uwb_rc *rc) |
351 | { | 329 | { |
352 | unsigned long flags; | 330 | kthread_stop(rc->uwbd.task); |
353 | struct uwb_event *evt, *nxt; | 331 | uwbd_flush(rc); |
354 | kthread_stop(uwbd_task); | ||
355 | spin_lock_irqsave(&uwbd_event_list_lock, flags); | ||
356 | uwbd_pid = 0; | ||
357 | list_for_each_entry_safe(evt, nxt, &uwbd_event_list, list_node) { | ||
358 | if (evt->type == UWB_EVT_TYPE_NOTIF) | ||
359 | kfree(evt->notif.rceb); | ||
360 | kfree(evt); | ||
361 | } | ||
362 | spin_unlock_irqrestore(&uwbd_event_list_lock, flags); | ||
363 | uwb_beca_release(); | ||
364 | } | 332 | } |
365 | 333 | ||
366 | /* | 334 | /* |
@@ -377,18 +345,20 @@ void uwbd_stop(void) | |||
377 | */ | 345 | */ |
378 | void uwbd_event_queue(struct uwb_event *evt) | 346 | void uwbd_event_queue(struct uwb_event *evt) |
379 | { | 347 | { |
348 | struct uwb_rc *rc = evt->rc; | ||
380 | unsigned long flags; | 349 | unsigned long flags; |
381 | spin_lock_irqsave(&uwbd_event_list_lock, flags); | 350 | |
382 | if (uwbd_pid != 0) { | 351 | spin_lock_irqsave(&rc->uwbd.event_list_lock, flags); |
383 | list_add(&evt->list_node, &uwbd_event_list); | 352 | if (rc->uwbd.pid != 0) { |
384 | wake_up_all(&uwbd_wq); | 353 | list_add(&evt->list_node, &rc->uwbd.event_list); |
354 | wake_up_all(&rc->uwbd.wq); | ||
385 | } else { | 355 | } else { |
386 | __uwb_rc_put(evt->rc); | 356 | __uwb_rc_put(evt->rc); |
387 | if (evt->type == UWB_EVT_TYPE_NOTIF) | 357 | if (evt->type == UWB_EVT_TYPE_NOTIF) |
388 | kfree(evt->notif.rceb); | 358 | kfree(evt->notif.rceb); |
389 | kfree(evt); | 359 | kfree(evt); |
390 | } | 360 | } |
391 | spin_unlock_irqrestore(&uwbd_event_list_lock, flags); | 361 | spin_unlock_irqrestore(&rc->uwbd.event_list_lock, flags); |
392 | return; | 362 | return; |
393 | } | 363 | } |
394 | 364 | ||
@@ -396,10 +366,8 @@ void uwbd_flush(struct uwb_rc *rc) | |||
396 | { | 366 | { |
397 | struct uwb_event *evt, *nxt; | 367 | struct uwb_event *evt, *nxt; |
398 | 368 | ||
399 | mutex_lock(&uwbd_event_mutex); | 369 | spin_lock_irq(&rc->uwbd.event_list_lock); |
400 | 370 | list_for_each_entry_safe(evt, nxt, &rc->uwbd.event_list, list_node) { | |
401 | spin_lock_irq(&uwbd_event_list_lock); | ||
402 | list_for_each_entry_safe(evt, nxt, &uwbd_event_list, list_node) { | ||
403 | if (evt->rc == rc) { | 371 | if (evt->rc == rc) { |
404 | __uwb_rc_put(rc); | 372 | __uwb_rc_put(rc); |
405 | list_del(&evt->list_node); | 373 | list_del(&evt->list_node); |
@@ -408,7 +376,5 @@ void uwbd_flush(struct uwb_rc *rc) | |||
408 | kfree(evt); | 376 | kfree(evt); |
409 | } | 377 | } |
410 | } | 378 | } |
411 | spin_unlock_irq(&uwbd_event_list_lock); | 379 | spin_unlock_irq(&rc->uwbd.event_list_lock); |
412 | |||
413 | mutex_unlock(&uwbd_event_mutex); | ||
414 | } | 380 | } |
diff --git a/include/linux/uwb.h b/include/linux/uwb.h index 6d93f54b8879..881f0c5b6d28 100644 --- a/include/linux/uwb.h +++ b/include/linux/uwb.h | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/device.h> | 30 | #include <linux/device.h> |
31 | #include <linux/mutex.h> | 31 | #include <linux/mutex.h> |
32 | #include <linux/timer.h> | 32 | #include <linux/timer.h> |
33 | #include <linux/wait.h> | ||
33 | #include <linux/workqueue.h> | 34 | #include <linux/workqueue.h> |
34 | #include <linux/uwb/spec.h> | 35 | #include <linux/uwb/spec.h> |
35 | 36 | ||
@@ -86,6 +87,22 @@ struct uwb_notifs_chain { | |||
86 | struct mutex mutex; | 87 | struct mutex mutex; |
87 | }; | 88 | }; |
88 | 89 | ||
90 | /* Beacon cache list */ | ||
91 | struct uwb_beca { | ||
92 | struct list_head list; | ||
93 | size_t entries; | ||
94 | struct mutex mutex; | ||
95 | }; | ||
96 | |||
97 | /* Event handling thread. */ | ||
98 | struct uwbd { | ||
99 | int pid; | ||
100 | struct task_struct *task; | ||
101 | wait_queue_head_t wq; | ||
102 | struct list_head event_list; | ||
103 | spinlock_t event_list_lock; | ||
104 | }; | ||
105 | |||
89 | /** | 106 | /** |
90 | * struct uwb_mas_bm - a bitmap of all MAS in a superframe | 107 | * struct uwb_mas_bm - a bitmap of all MAS in a superframe |
91 | * @bm: a bitmap of length #UWB_NUM_MAS | 108 | * @bm: a bitmap of length #UWB_NUM_MAS |
@@ -342,6 +359,9 @@ struct uwb_rc { | |||
342 | enum uwb_scan_type scan_type:3; | 359 | enum uwb_scan_type scan_type:3; |
343 | unsigned ready:1; | 360 | unsigned ready:1; |
344 | struct uwb_notifs_chain notifs_chain; | 361 | struct uwb_notifs_chain notifs_chain; |
362 | struct uwb_beca uwb_beca; | ||
363 | |||
364 | struct uwbd uwbd; | ||
345 | 365 | ||
346 | struct uwb_drp_avail drp_avail; | 366 | struct uwb_drp_avail drp_avail; |
347 | struct list_head reservations; | 367 | struct list_head reservations; |