mirror of https://gitee.com/openkylin/linux.git
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>
This commit is contained in:
parent
b09ac64b7b
commit
cae1c11414
|
@ -59,7 +59,6 @@ static void wusbhc_rsv_complete_cb(struct uwb_rsv *rsv)
|
||||||
case UWB_RSV_STATE_NONE:
|
case UWB_RSV_STATE_NONE:
|
||||||
dev_dbg(dev, "removed reservation\n");
|
dev_dbg(dev, "removed reservation\n");
|
||||||
wusbhc_bwa_set(wusbhc, 0, NULL);
|
wusbhc_bwa_set(wusbhc, 0, NULL);
|
||||||
wusbhc->rsv = NULL;
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
dev_dbg(dev, "unexpected reservation state: %d\n", rsv->state);
|
dev_dbg(dev, "unexpected reservation state: %d\n", rsv->state);
|
||||||
|
@ -105,11 +104,11 @@ int wusbhc_rsv_establish(struct wusbhc *wusbhc)
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* wusbhc_rsv_terminate - terminate any cluster reservation
|
* wusbhc_rsv_terminate - terminate the cluster reservation
|
||||||
* @wusbhc: the WUSB host whose reservation is to be terminated
|
* @wusbhc: the WUSB host whose reservation is to be terminated
|
||||||
*/
|
*/
|
||||||
void wusbhc_rsv_terminate(struct wusbhc *wusbhc)
|
void wusbhc_rsv_terminate(struct wusbhc *wusbhc)
|
||||||
{
|
{
|
||||||
if (wusbhc->rsv)
|
uwb_rsv_terminate(wusbhc->rsv);
|
||||||
uwb_rsv_terminate(wusbhc->rsv);
|
uwb_rsv_destroy(wusbhc->rsv);
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,6 +82,23 @@ static void uwb_rsv_dump(struct uwb_rsv *rsv)
|
||||||
dev_dbg(dev, "rsv %s -> %s: %s\n", owner, target, uwb_rsv_state_str(rsv->state));
|
dev_dbg(dev, "rsv %s -> %s: %s\n", owner, target, uwb_rsv_state_str(rsv->state));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void uwb_rsv_release(struct kref *kref)
|
||||||
|
{
|
||||||
|
struct uwb_rsv *rsv = container_of(kref, struct uwb_rsv, kref);
|
||||||
|
|
||||||
|
kfree(rsv);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void uwb_rsv_get(struct uwb_rsv *rsv)
|
||||||
|
{
|
||||||
|
kref_get(&rsv->kref);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void uwb_rsv_put(struct uwb_rsv *rsv)
|
||||||
|
{
|
||||||
|
kref_put(&rsv->kref, uwb_rsv_release);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get a free stream index for a reservation.
|
* Get a free stream index for a reservation.
|
||||||
*
|
*
|
||||||
|
@ -325,6 +342,7 @@ static struct uwb_rsv *uwb_rsv_alloc(struct uwb_rc *rc)
|
||||||
|
|
||||||
INIT_LIST_HEAD(&rsv->rc_node);
|
INIT_LIST_HEAD(&rsv->rc_node);
|
||||||
INIT_LIST_HEAD(&rsv->pal_node);
|
INIT_LIST_HEAD(&rsv->pal_node);
|
||||||
|
kref_init(&rsv->kref);
|
||||||
init_timer(&rsv->timer);
|
init_timer(&rsv->timer);
|
||||||
rsv->timer.function = uwb_rsv_timer;
|
rsv->timer.function = uwb_rsv_timer;
|
||||||
rsv->timer.data = (unsigned long)rsv;
|
rsv->timer.data = (unsigned long)rsv;
|
||||||
|
@ -334,14 +352,6 @@ static struct uwb_rsv *uwb_rsv_alloc(struct uwb_rc *rc)
|
||||||
return rsv;
|
return rsv;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void uwb_rsv_free(struct uwb_rsv *rsv)
|
|
||||||
{
|
|
||||||
uwb_dev_put(rsv->owner);
|
|
||||||
if (rsv->target.type == UWB_RSV_TARGET_DEV)
|
|
||||||
uwb_dev_put(rsv->target.dev);
|
|
||||||
kfree(rsv);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* uwb_rsv_create - allocate and initialize a UWB reservation structure
|
* uwb_rsv_create - allocate and initialize a UWB reservation structure
|
||||||
* @rc: the radio controller
|
* @rc: the radio controller
|
||||||
|
@ -375,23 +385,23 @@ void uwb_rsv_remove(struct uwb_rsv *rsv)
|
||||||
if (rsv->state != UWB_RSV_STATE_NONE)
|
if (rsv->state != UWB_RSV_STATE_NONE)
|
||||||
uwb_rsv_set_state(rsv, UWB_RSV_STATE_NONE);
|
uwb_rsv_set_state(rsv, UWB_RSV_STATE_NONE);
|
||||||
del_timer_sync(&rsv->timer);
|
del_timer_sync(&rsv->timer);
|
||||||
list_del(&rsv->rc_node);
|
uwb_dev_put(rsv->owner);
|
||||||
uwb_rsv_free(rsv);
|
if (rsv->target.type == UWB_RSV_TARGET_DEV)
|
||||||
|
uwb_dev_put(rsv->target.dev);
|
||||||
|
|
||||||
|
list_del_init(&rsv->rc_node);
|
||||||
|
uwb_rsv_put(rsv);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* uwb_rsv_destroy - free a UWB reservation structure
|
* uwb_rsv_destroy - free a UWB reservation structure
|
||||||
* @rsv: the reservation to free
|
* @rsv: the reservation to free
|
||||||
*
|
*
|
||||||
* The reservation will be terminated if it is pending or established.
|
* The reservation must already be terminated.
|
||||||
*/
|
*/
|
||||||
void uwb_rsv_destroy(struct uwb_rsv *rsv)
|
void uwb_rsv_destroy(struct uwb_rsv *rsv)
|
||||||
{
|
{
|
||||||
struct uwb_rc *rc = rsv->rc;
|
uwb_rsv_put(rsv);
|
||||||
|
|
||||||
mutex_lock(&rc->rsvs_mutex);
|
|
||||||
uwb_rsv_remove(rsv);
|
|
||||||
mutex_unlock(&rc->rsvs_mutex);
|
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(uwb_rsv_destroy);
|
EXPORT_SYMBOL_GPL(uwb_rsv_destroy);
|
||||||
|
|
||||||
|
@ -423,6 +433,7 @@ int uwb_rsv_establish(struct uwb_rsv *rsv)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uwb_rsv_get(rsv);
|
||||||
list_add_tail(&rsv->rc_node, &rc->reservations);
|
list_add_tail(&rsv->rc_node, &rc->reservations);
|
||||||
rsv->owner = &rc->uwb_dev;
|
rsv->owner = &rc->uwb_dev;
|
||||||
uwb_dev_get(rsv->owner);
|
uwb_dev_get(rsv->owner);
|
||||||
|
@ -478,9 +489,14 @@ EXPORT_SYMBOL_GPL(uwb_rsv_terminate);
|
||||||
*
|
*
|
||||||
* Reservation requests from peers are denied unless a PAL accepts it
|
* Reservation requests from peers are denied unless a PAL accepts it
|
||||||
* by calling this function.
|
* by calling this function.
|
||||||
|
*
|
||||||
|
* The PAL call uwb_rsv_destroy() for all accepted reservations before
|
||||||
|
* calling uwb_pal_unregister().
|
||||||
*/
|
*/
|
||||||
void uwb_rsv_accept(struct uwb_rsv *rsv, uwb_rsv_cb_f cb, void *pal_priv)
|
void uwb_rsv_accept(struct uwb_rsv *rsv, uwb_rsv_cb_f cb, void *pal_priv)
|
||||||
{
|
{
|
||||||
|
uwb_rsv_get(rsv);
|
||||||
|
|
||||||
rsv->callback = cb;
|
rsv->callback = cb;
|
||||||
rsv->pal_priv = pal_priv;
|
rsv->pal_priv = pal_priv;
|
||||||
rsv->state = UWB_RSV_STATE_T_ACCEPTED;
|
rsv->state = UWB_RSV_STATE_T_ACCEPTED;
|
||||||
|
|
|
@ -104,6 +104,11 @@ static void uwb_dbg_rsv_cb(struct uwb_rsv *rsv)
|
||||||
|
|
||||||
dev_dbg(dev, "debug: rsv %s -> %s: %s\n",
|
dev_dbg(dev, "debug: rsv %s -> %s: %s\n",
|
||||||
owner, target, uwb_rsv_state_str(rsv->state));
|
owner, target, uwb_rsv_state_str(rsv->state));
|
||||||
|
|
||||||
|
if (rsv->state == UWB_RSV_STATE_NONE) {
|
||||||
|
list_del(&rsv->pal_node);
|
||||||
|
uwb_rsv_destroy(rsv);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cmd_rsv_establish(struct uwb_rc *rc,
|
static int cmd_rsv_establish(struct uwb_rc *rc,
|
||||||
|
@ -153,11 +158,11 @@ static int cmd_rsv_terminate(struct uwb_rc *rc,
|
||||||
found = rsv;
|
found = rsv;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
i++;
|
||||||
}
|
}
|
||||||
if (!found)
|
if (!found)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
list_del(&found->pal_node);
|
|
||||||
uwb_rsv_terminate(found);
|
uwb_rsv_terminate(found);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -287,8 +292,10 @@ static void uwb_dbg_new_rsv(struct uwb_rsv *rsv)
|
||||||
{
|
{
|
||||||
struct uwb_rc *rc = rsv->rc;
|
struct uwb_rc *rc = rsv->rc;
|
||||||
|
|
||||||
if (rc->dbg->accept)
|
if (rc->dbg->accept) {
|
||||||
|
list_add_tail(&rsv->pal_node, &rc->dbg->rsvs);
|
||||||
uwb_rsv_accept(rsv, uwb_dbg_rsv_cb, NULL);
|
uwb_rsv_accept(rsv, uwb_dbg_rsv_cb, NULL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -336,7 +343,7 @@ void uwb_dbg_del_rc(struct uwb_rc *rc)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
list_for_each_entry_safe(rsv, t, &rc->dbg->rsvs, pal_node) {
|
list_for_each_entry_safe(rsv, t, &rc->dbg->rsvs, pal_node) {
|
||||||
uwb_rsv_destroy(rsv);
|
uwb_rsv_terminate(rsv);
|
||||||
}
|
}
|
||||||
|
|
||||||
uwb_pal_unregister(rc, &rc->dbg->pal);
|
uwb_pal_unregister(rc, &rc->dbg->pal);
|
||||||
|
|
|
@ -201,6 +201,7 @@ struct uwb_rsv {
|
||||||
struct uwb_rc *rc;
|
struct uwb_rc *rc;
|
||||||
struct list_head rc_node;
|
struct list_head rc_node;
|
||||||
struct list_head pal_node;
|
struct list_head pal_node;
|
||||||
|
struct kref kref;
|
||||||
|
|
||||||
struct uwb_dev *owner;
|
struct uwb_dev *owner;
|
||||||
struct uwb_rsv_target target;
|
struct uwb_rsv_target target;
|
||||||
|
|
Loading…
Reference in New Issue