aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/uwb
diff options
context:
space:
mode:
authorDavid Vrabel <david.vrabel@csr.com>2008-10-27 11:22:46 -0400
committerDavid Vrabel <david.vrabel@csr.com>2008-10-28 08:07:23 -0400
commitcae1c11414912bf77a62aebd65ced321f0b9da51 (patch)
tree1f83b9b82aec7f86740f8b1f7f5e8be1c6cf3196 /drivers/uwb
parentb09ac64b7b2d93efab3998033588f5cb0e470ccf (diff)
uwb: reference count reservations
Reference counting the struct uwb_rsv's is safer and easier to get right than the transferring ownership of the structures from the PAL to reservation manager. This fixes an oops in the debug PAL after a reservation timed out. Signed-off-by: David Vrabel <david.vrabel@csr.com>
Diffstat (limited to 'drivers/uwb')
-rw-r--r--drivers/uwb/rsv.c48
-rw-r--r--drivers/uwb/uwb-debug.c13
2 files changed, 42 insertions, 19 deletions
diff --git a/drivers/uwb/rsv.c b/drivers/uwb/rsv.c
index e4facae46e0d..bcc41a4a6606 100644
--- a/drivers/uwb/rsv.c
+++ b/drivers/uwb/rsv.c
@@ -82,6 +82,23 @@ static void uwb_rsv_dump(struct uwb_rsv *rsv)
82 dev_dbg(dev, "rsv %s -> %s: %s\n", owner, target, uwb_rsv_state_str(rsv->state)); 82 dev_dbg(dev, "rsv %s -> %s: %s\n", owner, target, uwb_rsv_state_str(rsv->state));
83} 83}
84 84
85static void uwb_rsv_release(struct kref *kref)
86{
87 struct uwb_rsv *rsv = container_of(kref, struct uwb_rsv, kref);
88
89 kfree(rsv);
90}
91
92static void uwb_rsv_get(struct uwb_rsv *rsv)
93{
94 kref_get(&rsv->kref);
95}
96
97static void uwb_rsv_put(struct uwb_rsv *rsv)
98{
99 kref_put(&rsv->kref, uwb_rsv_release);
100}
101
85/* 102/*
86 * Get a free stream index for a reservation. 103 * Get a free stream index for a reservation.
87 * 104 *
@@ -325,6 +342,7 @@ static struct uwb_rsv *uwb_rsv_alloc(struct uwb_rc *rc)
325 342
326 INIT_LIST_HEAD(&rsv->rc_node); 343 INIT_LIST_HEAD(&rsv->rc_node);
327 INIT_LIST_HEAD(&rsv->pal_node); 344 INIT_LIST_HEAD(&rsv->pal_node);
345 kref_init(&rsv->kref);
328 init_timer(&rsv->timer); 346 init_timer(&rsv->timer);
329 rsv->timer.function = uwb_rsv_timer; 347 rsv->timer.function = uwb_rsv_timer;
330 rsv->timer.data = (unsigned long)rsv; 348 rsv->timer.data = (unsigned long)rsv;
@@ -334,14 +352,6 @@ static struct uwb_rsv *uwb_rsv_alloc(struct uwb_rc *rc)
334 return rsv; 352 return rsv;
335} 353}
336 354
337static void uwb_rsv_free(struct uwb_rsv *rsv)
338{
339 uwb_dev_put(rsv->owner);
340 if (rsv->target.type == UWB_RSV_TARGET_DEV)
341 uwb_dev_put(rsv->target.dev);
342 kfree(rsv);
343}
344
345/** 355/**
346 * uwb_rsv_create - allocate and initialize a UWB reservation structure 356 * uwb_rsv_create - allocate and initialize a UWB reservation structure
347 * @rc: the radio controller 357 * @rc: the radio controller
@@ -375,23 +385,23 @@ void uwb_rsv_remove(struct uwb_rsv *rsv)
375 if (rsv->state != UWB_RSV_STATE_NONE) 385 if (rsv->state != UWB_RSV_STATE_NONE)
376 uwb_rsv_set_state(rsv, UWB_RSV_STATE_NONE); 386 uwb_rsv_set_state(rsv, UWB_RSV_STATE_NONE);
377 del_timer_sync(&rsv->timer); 387 del_timer_sync(&rsv->timer);
378 list_del(&rsv->rc_node); 388 uwb_dev_put(rsv->owner);
379 uwb_rsv_free(rsv); 389 if (rsv->target.type == UWB_RSV_TARGET_DEV)
390 uwb_dev_put(rsv->target.dev);
391
392 list_del_init(&rsv->rc_node);
393 uwb_rsv_put(rsv);
380} 394}
381 395
382/** 396/**
383 * uwb_rsv_destroy - free a UWB reservation structure 397 * uwb_rsv_destroy - free a UWB reservation structure
384 * @rsv: the reservation to free 398 * @rsv: the reservation to free
385 * 399 *
386 * The reservation will be terminated if it is pending or established. 400 * The reservation must already be terminated.
387 */ 401 */
388void uwb_rsv_destroy(struct uwb_rsv *rsv) 402void uwb_rsv_destroy(struct uwb_rsv *rsv)
389{ 403{
390 struct uwb_rc *rc = rsv->rc; 404 uwb_rsv_put(rsv);
391
392 mutex_lock(&rc->rsvs_mutex);
393 uwb_rsv_remove(rsv);
394 mutex_unlock(&rc->rsvs_mutex);
395} 405}
396EXPORT_SYMBOL_GPL(uwb_rsv_destroy); 406EXPORT_SYMBOL_GPL(uwb_rsv_destroy);
397 407
@@ -423,6 +433,7 @@ int uwb_rsv_establish(struct uwb_rsv *rsv)
423 goto out; 433 goto out;
424 } 434 }
425 435
436 uwb_rsv_get(rsv);
426 list_add_tail(&rsv->rc_node, &rc->reservations); 437 list_add_tail(&rsv->rc_node, &rc->reservations);
427 rsv->owner = &rc->uwb_dev; 438 rsv->owner = &rc->uwb_dev;
428 uwb_dev_get(rsv->owner); 439 uwb_dev_get(rsv->owner);
@@ -478,9 +489,14 @@ EXPORT_SYMBOL_GPL(uwb_rsv_terminate);
478 * 489 *
479 * Reservation requests from peers are denied unless a PAL accepts it 490 * Reservation requests from peers are denied unless a PAL accepts it
480 * by calling this function. 491 * by calling this function.
492 *
493 * The PAL call uwb_rsv_destroy() for all accepted reservations before
494 * calling uwb_pal_unregister().
481 */ 495 */
482void uwb_rsv_accept(struct uwb_rsv *rsv, uwb_rsv_cb_f cb, void *pal_priv) 496void uwb_rsv_accept(struct uwb_rsv *rsv, uwb_rsv_cb_f cb, void *pal_priv)
483{ 497{
498 uwb_rsv_get(rsv);
499
484 rsv->callback = cb; 500 rsv->callback = cb;
485 rsv->pal_priv = pal_priv; 501 rsv->pal_priv = pal_priv;
486 rsv->state = UWB_RSV_STATE_T_ACCEPTED; 502 rsv->state = UWB_RSV_STATE_T_ACCEPTED;
diff --git a/drivers/uwb/uwb-debug.c b/drivers/uwb/uwb-debug.c
index 6d232c35d07d..6db641e45313 100644
--- a/drivers/uwb/uwb-debug.c
+++ b/drivers/uwb/uwb-debug.c
@@ -104,6 +104,11 @@ static void uwb_dbg_rsv_cb(struct uwb_rsv *rsv)
104 104
105 dev_dbg(dev, "debug: rsv %s -> %s: %s\n", 105 dev_dbg(dev, "debug: rsv %s -> %s: %s\n",
106 owner, target, uwb_rsv_state_str(rsv->state)); 106 owner, target, uwb_rsv_state_str(rsv->state));
107
108 if (rsv->state == UWB_RSV_STATE_NONE) {
109 list_del(&rsv->pal_node);
110 uwb_rsv_destroy(rsv);
111 }
107} 112}
108 113
109static int cmd_rsv_establish(struct uwb_rc *rc, 114static int cmd_rsv_establish(struct uwb_rc *rc,
@@ -153,11 +158,11 @@ static int cmd_rsv_terminate(struct uwb_rc *rc,
153 found = rsv; 158 found = rsv;
154 break; 159 break;
155 } 160 }
161 i++;
156 } 162 }
157 if (!found) 163 if (!found)
158 return -EINVAL; 164 return -EINVAL;
159 165
160 list_del(&found->pal_node);
161 uwb_rsv_terminate(found); 166 uwb_rsv_terminate(found);
162 167
163 return 0; 168 return 0;
@@ -287,8 +292,10 @@ static void uwb_dbg_new_rsv(struct uwb_rsv *rsv)
287{ 292{
288 struct uwb_rc *rc = rsv->rc; 293 struct uwb_rc *rc = rsv->rc;
289 294
290 if (rc->dbg->accept) 295 if (rc->dbg->accept) {
296 list_add_tail(&rsv->pal_node, &rc->dbg->rsvs);
291 uwb_rsv_accept(rsv, uwb_dbg_rsv_cb, NULL); 297 uwb_rsv_accept(rsv, uwb_dbg_rsv_cb, NULL);
298 }
292} 299}
293 300
294/** 301/**
@@ -336,7 +343,7 @@ void uwb_dbg_del_rc(struct uwb_rc *rc)
336 return; 343 return;
337 344
338 list_for_each_entry_safe(rsv, t, &rc->dbg->rsvs, pal_node) { 345 list_for_each_entry_safe(rsv, t, &rc->dbg->rsvs, pal_node) {
339 uwb_rsv_destroy(rsv); 346 uwb_rsv_terminate(rsv);
340 } 347 }
341 348
342 uwb_pal_unregister(rc, &rc->dbg->pal); 349 uwb_pal_unregister(rc, &rc->dbg->pal);