aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/uwb/uwbd.c
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 /drivers/uwb/uwbd.c
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>
Diffstat (limited to 'drivers/uwb/uwbd.c')
-rw-r--r--drivers/uwb/uwbd.c98
1 files changed, 32 insertions, 66 deletions
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}