uwb: improved MAS allocator and reservation conflict handling
Greatly enhance the MAS allocator:
- Handle row and column reservations.
- Permit all the available MAS to be allocated.
- Follows the WiMedia rules on MAS selection.
Take appropriate action when reservation conflicts are detected.
- Correctly identify which reservation wins the conflict.
- Protect alien BP reservations.
- If an owned reservation loses, resize/move it.
- Follow the backoff procedure before requesting additional MAS.
When reservations are terminated, move the remaining reservations (if
necessary) so they keep following the MAS allocation rules.
Signed-off-by: Stefano Panella <stefano.panella@csr.com>
Signed-off-by: David Vrabel <david.vrabel@csr.com>
diff --git a/drivers/uwb/uwb-debug.c b/drivers/uwb/uwb-debug.c
index a6debb9..89b2e6a 100644
--- a/drivers/uwb/uwb-debug.c
+++ b/drivers/uwb/uwb-debug.c
@@ -82,29 +82,21 @@
struct dentry *reservations_f;
struct dentry *accept_f;
struct dentry *drp_avail_f;
+ spinlock_t list_lock;
};
static struct dentry *root_dir;
static void uwb_dbg_rsv_cb(struct uwb_rsv *rsv)
{
- struct uwb_rc *rc = rsv->rc;
- struct device *dev = &rc->uwb_dev.dev;
- struct uwb_dev_addr devaddr;
- char owner[UWB_ADDR_STRSIZE], target[UWB_ADDR_STRSIZE];
+ struct uwb_dbg *dbg = rsv->pal_priv;
- uwb_dev_addr_print(owner, sizeof(owner), &rsv->owner->dev_addr);
- if (rsv->target.type == UWB_RSV_TARGET_DEV)
- devaddr = rsv->target.dev->dev_addr;
- else
- devaddr = rsv->target.devaddr;
- uwb_dev_addr_print(target, sizeof(target), &devaddr);
-
- dev_dbg(dev, "debug: rsv %s -> %s: %s\n",
- owner, target, uwb_rsv_state_str(rsv->state));
+ uwb_rsv_dump("debug", rsv);
if (rsv->state == UWB_RSV_STATE_NONE) {
+ spin_lock(&dbg->list_lock);
list_del(&rsv->pal_node);
+ spin_unlock(&dbg->list_lock);
uwb_rsv_destroy(rsv);
}
}
@@ -128,20 +120,21 @@
return -ENOMEM;
}
- rsv->owner = &rc->uwb_dev;
- rsv->target.type = UWB_RSV_TARGET_DEV;
- rsv->target.dev = target;
- rsv->type = cmd->type;
- rsv->max_mas = cmd->max_mas;
- rsv->min_mas = cmd->min_mas;
- rsv->sparsity = cmd->sparsity;
+ rsv->target.type = UWB_RSV_TARGET_DEV;
+ rsv->target.dev = target;
+ rsv->type = cmd->type;
+ rsv->max_mas = cmd->max_mas;
+ rsv->min_mas = cmd->min_mas;
+ rsv->max_interval = cmd->max_interval;
ret = uwb_rsv_establish(rsv);
if (ret)
uwb_rsv_destroy(rsv);
- else
+ else {
+ spin_lock(&(rc->dbg)->list_lock);
list_add_tail(&rsv->pal_node, &rc->dbg->rsvs);
-
+ spin_unlock(&(rc->dbg)->list_lock);
+ }
return ret;
}
@@ -151,17 +144,24 @@
struct uwb_rsv *rsv, *found = NULL;
int i = 0;
+ spin_lock(&(rc->dbg)->list_lock);
+
list_for_each_entry(rsv, &rc->dbg->rsvs, pal_node) {
if (i == cmd->index) {
found = rsv;
+ uwb_rsv_get(found);
break;
}
i++;
}
+
+ spin_unlock(&(rc->dbg)->list_lock);
+
if (!found)
return -EINVAL;
uwb_rsv_terminate(found);
+ uwb_rsv_put(found);
return 0;
}
@@ -191,7 +191,7 @@
struct uwb_rc *rc = file->private_data;
struct uwb_dbg_cmd cmd;
int ret = 0;
-
+
if (len != sizeof(struct uwb_dbg_cmd))
return -EINVAL;
@@ -325,7 +325,9 @@
struct uwb_dbg *dbg = container_of(pal, struct uwb_dbg, pal);
if (dbg->accept) {
+ spin_lock(&dbg->list_lock);
list_add_tail(&rsv->pal_node, &dbg->rsvs);
+ spin_unlock(&dbg->list_lock);
uwb_rsv_accept(rsv, uwb_dbg_rsv_cb, dbg);
}
}
@@ -341,6 +343,7 @@
return;
INIT_LIST_HEAD(&rc->dbg->rsvs);
+ spin_lock_init(&(rc->dbg)->list_lock);
uwb_pal_init(&rc->dbg->pal);
rc->dbg->pal.rc = rc;