diff options
author | David Vrabel <david.vrabel@csr.com> | 2008-10-27 11:22:46 -0400 |
---|---|---|
committer | David Vrabel <david.vrabel@csr.com> | 2008-10-28 08:07:23 -0400 |
commit | cae1c11414912bf77a62aebd65ced321f0b9da51 (patch) | |
tree | 1f83b9b82aec7f86740f8b1f7f5e8be1c6cf3196 /drivers/uwb | |
parent | b09ac64b7b2d93efab3998033588f5cb0e470ccf (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.c | 48 | ||||
-rw-r--r-- | drivers/uwb/uwb-debug.c | 13 |
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 | ||
85 | static 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 | |||
92 | static void uwb_rsv_get(struct uwb_rsv *rsv) | ||
93 | { | ||
94 | kref_get(&rsv->kref); | ||
95 | } | ||
96 | |||
97 | static 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 | ||
337 | static 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 | */ |
388 | void uwb_rsv_destroy(struct uwb_rsv *rsv) | 402 | void 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 | } |
396 | EXPORT_SYMBOL_GPL(uwb_rsv_destroy); | 406 | EXPORT_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 | */ |
482 | void uwb_rsv_accept(struct uwb_rsv *rsv, uwb_rsv_cb_f cb, void *pal_priv) | 496 | void 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 | ||
109 | static int cmd_rsv_establish(struct uwb_rc *rc, | 114 | static 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); |