aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefano Panella <stefano.panella@csr.com>2008-11-04 10:39:08 -0500
committerDavid Vrabel <david.vrabel@csr.com>2008-11-04 10:55:26 -0500
commitfec1a5932f16c0eb1b3f5ca2e18d81d860924088 (patch)
tree48836158dbd458bb462b18f4deffa89e9db80376
parent6d5a681dfb583b2f1eefe7cd5505419ca2d4d6c8 (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.c61
-rw-r--r--drivers/uwb/driver.c2
-rw-r--r--drivers/uwb/lc-rc.c21
-rw-r--r--drivers/uwb/uwb-internal.h20
-rw-r--r--drivers/uwb/uwbd.c98
-rw-r--r--include/linux/uwb.h20
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
171struct uwb_beca uwb_beca = {
172 .list = LIST_HEAD_INIT(uwb_beca.list),
173 .mutex = __MUTEX_INITIALIZER(uwb_beca.mutex)
174};
175
176
177void uwb_bce_kfree(struct kref *_bce) 171void 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 */
187static 181static
188struct uwb_beca_e *__uwb_beca_find_bydev(const struct uwb_dev_addr *dev_addr) 182struct 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 */
204static 199static
205struct uwb_beca_e *__uwb_beca_find_bymac(const struct uwb_mac_addr *mac_addr) 200struct 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 */
277struct uwb_beca_e *__uwb_beca_add(struct uwb_rc_evt_beacon *be, 273static
274struct 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 */
298void uwb_beca_purge(void) 296void 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 */
316void uwb_beca_release(void) 314void 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
327static void uwb_beacon_print(struct uwb_rc *rc, struct uwb_rc_evt_beacon *be, 326static 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);
132static void __exit uwb_subsys_exit(void) 131static 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
43static int uwb_rc_index_match(struct device *dev, void *data) 41static 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:
284error_dev_add: 289error_dev_add:
285error_rc_setup: 290error_rc_setup:
286 rc->stop(rc); 291 rc->stop(rc);
287 uwbd_flush(rc); 292 uwbd_stop(rc);
288error_rc_start: 293error_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}
330EXPORT_SYMBOL_GPL(uwb_rc_rm); 337EXPORT_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
163extern void uwbd_start(void); 163extern void uwbd_start(struct uwb_rc *rc);
164extern void uwbd_stop(void); 164extern void uwbd_stop(struct uwb_rc *rc);
165extern struct uwb_event *uwb_event_alloc(size_t, gfp_t gfp_mask); 165extern struct uwb_event *uwb_event_alloc(size_t, gfp_t gfp_mask);
166extern void uwbd_event_queue(struct uwb_event *); 166extern void uwbd_event_queue(struct uwb_event *);
167void uwbd_flush(struct uwb_rc *rc); 167void uwbd_flush(struct uwb_rc *rc);
@@ -194,15 +194,6 @@ int uwbd_evt_handle_rc_dev_addr_conflict(struct uwb_event *evt);
194 194
195extern unsigned long beacon_timeout_ms; 195extern unsigned long beacon_timeout_ms;
196 196
197/** Beacon cache list */
198struct uwb_beca {
199 struct list_head list;
200 size_t entries;
201 struct mutex mutex;
202};
203
204extern 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 {
229struct uwb_beacon_frame; 220struct uwb_beacon_frame;
230extern ssize_t uwb_bce_print_IEs(struct uwb_dev *, struct uwb_beca_e *, 221extern ssize_t uwb_bce_print_IEs(struct uwb_dev *, struct uwb_beca_e *,
231 char *, size_t); 222 char *, size_t);
232extern struct uwb_beca_e *__uwb_beca_add(struct uwb_rc_evt_beacon *,
233 struct uwb_beacon_frame *,
234 unsigned long);
235 223
236extern void uwb_bce_kfree(struct kref *_bce); 224extern void uwb_bce_kfree(struct kref *_bce);
237static inline void uwb_bce_get(struct uwb_beca_e *bce) 225static 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}
245extern void uwb_beca_purge(void); 233extern void uwb_beca_purge(struct uwb_rc *rc);
246extern void uwb_beca_release(void); 234extern void uwb_beca_release(struct uwb_rc *rc);
247 235
248struct uwb_dev *uwb_dev_get_by_devaddr(struct uwb_rc *rc, 236struct 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
173static 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
253static void uwbd_event_handle(struct uwb_event *evt) 242static 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 */
282static int uwbd_pid;
283/** Daemon's task struct for managing the kthread */
284static struct task_struct *uwbd_task;
285/** Daemon's waitqueue for waiting for new events */
286static DECLARE_WAIT_QUEUE_HEAD(uwbd_wq);
287/** Daemon's list of events; we queue/dequeue here */
288static struct list_head uwbd_event_list = LIST_HEAD_INIT(uwbd_event_list);
289/** Daemon's list lock to protect concurent access */
290static 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 */
305static int uwbd(void *unused) 280static 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 */
339void uwbd_start(void) 317void 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 */
350void uwbd_stop(void) 328void 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 */
378void uwbd_event_queue(struct uwb_event *evt) 346void 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 */
91struct uwb_beca {
92 struct list_head list;
93 size_t entries;
94 struct mutex mutex;
95};
96
97/* Event handling thread. */
98struct 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;