mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-06-06 22:58:29 +00:00
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>
This commit is contained in:
parent
6d5a681dfb
commit
fec1a5932f
6 changed files with 100 additions and 122 deletions
|
@ -168,12 +168,6 @@ out_up:
|
||||||
* FIXME: use something faster for search than a list
|
* FIXME: use something faster for search than a list
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct uwb_beca uwb_beca = {
|
|
||||||
.list = LIST_HEAD_INIT(uwb_beca.list),
|
|
||||||
.mutex = __MUTEX_INITIALIZER(uwb_beca.mutex)
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
void uwb_bce_kfree(struct kref *_bce)
|
void uwb_bce_kfree(struct kref *_bce)
|
||||||
{
|
{
|
||||||
struct uwb_beca_e *bce = container_of(_bce, struct uwb_beca_e, refcnt);
|
struct uwb_beca_e *bce = container_of(_bce, struct uwb_beca_e, refcnt);
|
||||||
|
@ -185,10 +179,11 @@ void uwb_bce_kfree(struct kref *_bce)
|
||||||
|
|
||||||
/* Find a beacon by dev addr in the cache */
|
/* Find a beacon by dev addr in the cache */
|
||||||
static
|
static
|
||||||
struct uwb_beca_e *__uwb_beca_find_bydev(const struct uwb_dev_addr *dev_addr)
|
struct uwb_beca_e *__uwb_beca_find_bydev(struct uwb_rc *rc,
|
||||||
|
const struct uwb_dev_addr *dev_addr)
|
||||||
{
|
{
|
||||||
struct uwb_beca_e *bce, *next;
|
struct uwb_beca_e *bce, *next;
|
||||||
list_for_each_entry_safe(bce, next, &uwb_beca.list, node) {
|
list_for_each_entry_safe(bce, next, &rc->uwb_beca.list, node) {
|
||||||
d_printf(6, NULL, "looking for addr %02x:%02x in %02x:%02x\n",
|
d_printf(6, NULL, "looking for addr %02x:%02x in %02x:%02x\n",
|
||||||
dev_addr->data[0], dev_addr->data[1],
|
dev_addr->data[0], dev_addr->data[1],
|
||||||
bce->dev_addr.data[0], bce->dev_addr.data[1]);
|
bce->dev_addr.data[0], bce->dev_addr.data[1]);
|
||||||
|
@ -202,10 +197,11 @@ out:
|
||||||
|
|
||||||
/* Find a beacon by dev addr in the cache */
|
/* Find a beacon by dev addr in the cache */
|
||||||
static
|
static
|
||||||
struct uwb_beca_e *__uwb_beca_find_bymac(const struct uwb_mac_addr *mac_addr)
|
struct uwb_beca_e *__uwb_beca_find_bymac(struct uwb_rc *rc,
|
||||||
|
const struct uwb_mac_addr *mac_addr)
|
||||||
{
|
{
|
||||||
struct uwb_beca_e *bce, *next;
|
struct uwb_beca_e *bce, *next;
|
||||||
list_for_each_entry_safe(bce, next, &uwb_beca.list, node) {
|
list_for_each_entry_safe(bce, next, &rc->uwb_beca.list, node) {
|
||||||
if (!memcmp(bce->mac_addr, mac_addr->data,
|
if (!memcmp(bce->mac_addr, mac_addr->data,
|
||||||
sizeof(struct uwb_mac_addr)))
|
sizeof(struct uwb_mac_addr)))
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -229,11 +225,11 @@ struct uwb_dev *uwb_dev_get_by_devaddr(struct uwb_rc *rc,
|
||||||
struct uwb_dev *found = NULL;
|
struct uwb_dev *found = NULL;
|
||||||
struct uwb_beca_e *bce;
|
struct uwb_beca_e *bce;
|
||||||
|
|
||||||
mutex_lock(&uwb_beca.mutex);
|
mutex_lock(&rc->uwb_beca.mutex);
|
||||||
bce = __uwb_beca_find_bydev(devaddr);
|
bce = __uwb_beca_find_bydev(rc, devaddr);
|
||||||
if (bce)
|
if (bce)
|
||||||
found = uwb_dev_try_get(rc, bce->uwb_dev);
|
found = uwb_dev_try_get(rc, bce->uwb_dev);
|
||||||
mutex_unlock(&uwb_beca.mutex);
|
mutex_unlock(&rc->uwb_beca.mutex);
|
||||||
|
|
||||||
return found;
|
return found;
|
||||||
}
|
}
|
||||||
|
@ -249,11 +245,11 @@ struct uwb_dev *uwb_dev_get_by_macaddr(struct uwb_rc *rc,
|
||||||
struct uwb_dev *found = NULL;
|
struct uwb_dev *found = NULL;
|
||||||
struct uwb_beca_e *bce;
|
struct uwb_beca_e *bce;
|
||||||
|
|
||||||
mutex_lock(&uwb_beca.mutex);
|
mutex_lock(&rc->uwb_beca.mutex);
|
||||||
bce = __uwb_beca_find_bymac(macaddr);
|
bce = __uwb_beca_find_bymac(rc, macaddr);
|
||||||
if (bce)
|
if (bce)
|
||||||
found = uwb_dev_try_get(rc, bce->uwb_dev);
|
found = uwb_dev_try_get(rc, bce->uwb_dev);
|
||||||
mutex_unlock(&uwb_beca.mutex);
|
mutex_unlock(&rc->uwb_beca.mutex);
|
||||||
|
|
||||||
return found;
|
return found;
|
||||||
}
|
}
|
||||||
|
@ -274,7 +270,9 @@ static void uwb_beca_e_init(struct uwb_beca_e *bce)
|
||||||
* @bf: Beacon frame (part of b, really)
|
* @bf: Beacon frame (part of b, really)
|
||||||
* @ts_jiffies: Timestamp (in jiffies) when the beacon was received
|
* @ts_jiffies: Timestamp (in jiffies) when the beacon was received
|
||||||
*/
|
*/
|
||||||
struct uwb_beca_e *__uwb_beca_add(struct uwb_rc_evt_beacon *be,
|
static
|
||||||
|
struct uwb_beca_e *__uwb_beca_add(struct uwb_rc *rc,
|
||||||
|
struct uwb_rc_evt_beacon *be,
|
||||||
struct uwb_beacon_frame *bf,
|
struct uwb_beacon_frame *bf,
|
||||||
unsigned long ts_jiffies)
|
unsigned long ts_jiffies)
|
||||||
{
|
{
|
||||||
|
@ -286,7 +284,7 @@ struct uwb_beca_e *__uwb_beca_add(struct uwb_rc_evt_beacon *be,
|
||||||
uwb_beca_e_init(bce);
|
uwb_beca_e_init(bce);
|
||||||
bce->ts_jiffies = ts_jiffies;
|
bce->ts_jiffies = ts_jiffies;
|
||||||
bce->uwb_dev = NULL;
|
bce->uwb_dev = NULL;
|
||||||
list_add(&bce->node, &uwb_beca.list);
|
list_add(&bce->node, &rc->uwb_beca.list);
|
||||||
return bce;
|
return bce;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -295,13 +293,13 @@ struct uwb_beca_e *__uwb_beca_add(struct uwb_rc_evt_beacon *be,
|
||||||
*
|
*
|
||||||
* Remove associated devicest too.
|
* Remove associated devicest too.
|
||||||
*/
|
*/
|
||||||
void uwb_beca_purge(void)
|
void uwb_beca_purge(struct uwb_rc *rc)
|
||||||
{
|
{
|
||||||
struct uwb_beca_e *bce, *next;
|
struct uwb_beca_e *bce, *next;
|
||||||
unsigned long expires;
|
unsigned long expires;
|
||||||
|
|
||||||
mutex_lock(&uwb_beca.mutex);
|
mutex_lock(&rc->uwb_beca.mutex);
|
||||||
list_for_each_entry_safe(bce, next, &uwb_beca.list, node) {
|
list_for_each_entry_safe(bce, next, &rc->uwb_beca.list, node) {
|
||||||
expires = bce->ts_jiffies + msecs_to_jiffies(beacon_timeout_ms);
|
expires = bce->ts_jiffies + msecs_to_jiffies(beacon_timeout_ms);
|
||||||
if (time_after(jiffies, expires)) {
|
if (time_after(jiffies, expires)) {
|
||||||
uwbd_dev_offair(bce);
|
uwbd_dev_offair(bce);
|
||||||
|
@ -309,19 +307,20 @@ void uwb_beca_purge(void)
|
||||||
uwb_bce_put(bce);
|
uwb_bce_put(bce);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mutex_unlock(&uwb_beca.mutex);
|
mutex_unlock(&rc->uwb_beca.mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clean up the whole beacon cache. Called on shutdown */
|
/* Clean up the whole beacon cache. Called on shutdown */
|
||||||
void uwb_beca_release(void)
|
void uwb_beca_release(struct uwb_rc *rc)
|
||||||
{
|
{
|
||||||
struct uwb_beca_e *bce, *next;
|
struct uwb_beca_e *bce, *next;
|
||||||
mutex_lock(&uwb_beca.mutex);
|
|
||||||
list_for_each_entry_safe(bce, next, &uwb_beca.list, node) {
|
mutex_lock(&rc->uwb_beca.mutex);
|
||||||
|
list_for_each_entry_safe(bce, next, &rc->uwb_beca.list, node) {
|
||||||
list_del(&bce->node);
|
list_del(&bce->node);
|
||||||
uwb_bce_put(bce);
|
uwb_bce_put(bce);
|
||||||
}
|
}
|
||||||
mutex_unlock(&uwb_beca.mutex);
|
mutex_unlock(&rc->uwb_beca.mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void uwb_beacon_print(struct uwb_rc *rc, struct uwb_rc_evt_beacon *be,
|
static void uwb_beacon_print(struct uwb_rc *rc, struct uwb_rc_evt_beacon *be,
|
||||||
|
@ -437,18 +436,18 @@ int uwbd_evt_handle_rc_beacon(struct uwb_event *evt)
|
||||||
if (uwb_mac_addr_bcast(&bf->Device_Identifier))
|
if (uwb_mac_addr_bcast(&bf->Device_Identifier))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
mutex_lock(&uwb_beca.mutex);
|
mutex_lock(&rc->uwb_beca.mutex);
|
||||||
bce = __uwb_beca_find_bymac(&bf->Device_Identifier);
|
bce = __uwb_beca_find_bymac(rc, &bf->Device_Identifier);
|
||||||
if (bce == NULL) {
|
if (bce == NULL) {
|
||||||
/* Not in there, a new device is pinging */
|
/* Not in there, a new device is pinging */
|
||||||
uwb_beacon_print(evt->rc, be, bf);
|
uwb_beacon_print(evt->rc, be, bf);
|
||||||
bce = __uwb_beca_add(be, bf, evt->ts_jiffies);
|
bce = __uwb_beca_add(rc, be, bf, evt->ts_jiffies);
|
||||||
if (bce == NULL) {
|
if (bce == NULL) {
|
||||||
mutex_unlock(&uwb_beca.mutex);
|
mutex_unlock(&rc->uwb_beca.mutex);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mutex_unlock(&uwb_beca.mutex);
|
mutex_unlock(&rc->uwb_beca.mutex);
|
||||||
|
|
||||||
mutex_lock(&bce->mutex);
|
mutex_lock(&bce->mutex);
|
||||||
/* purge old beacon data */
|
/* purge old beacon data */
|
||||||
|
|
|
@ -118,7 +118,6 @@ static int __init uwb_subsys_init(void)
|
||||||
result = class_register(&uwb_rc_class);
|
result = class_register(&uwb_rc_class);
|
||||||
if (result < 0)
|
if (result < 0)
|
||||||
goto error_uwb_rc_class_register;
|
goto error_uwb_rc_class_register;
|
||||||
uwbd_start();
|
|
||||||
uwb_dbg_init();
|
uwb_dbg_init();
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -132,7 +131,6 @@ module_init(uwb_subsys_init);
|
||||||
static void __exit uwb_subsys_exit(void)
|
static void __exit uwb_subsys_exit(void)
|
||||||
{
|
{
|
||||||
uwb_dbg_exit();
|
uwb_dbg_exit();
|
||||||
uwbd_stop();
|
|
||||||
class_unregister(&uwb_rc_class);
|
class_unregister(&uwb_rc_class);
|
||||||
uwb_est_destroy();
|
uwb_est_destroy();
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -36,8 +36,6 @@
|
||||||
#include <linux/etherdevice.h>
|
#include <linux/etherdevice.h>
|
||||||
#include <linux/usb.h>
|
#include <linux/usb.h>
|
||||||
|
|
||||||
#define D_LOCAL 1
|
|
||||||
#include <linux/uwb/debug.h>
|
|
||||||
#include "uwb-internal.h"
|
#include "uwb-internal.h"
|
||||||
|
|
||||||
static int uwb_rc_index_match(struct device *dev, void *data)
|
static int uwb_rc_index_match(struct device *dev, void *data)
|
||||||
|
@ -83,7 +81,6 @@ static void uwb_rc_sys_release(struct device *dev)
|
||||||
|
|
||||||
uwb_rc_neh_destroy(rc);
|
uwb_rc_neh_destroy(rc);
|
||||||
uwb_rc_ie_release(rc);
|
uwb_rc_ie_release(rc);
|
||||||
d_printf(1, dev, "freed uwb_rc %p\n", rc);
|
|
||||||
kfree(rc);
|
kfree(rc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,6 +97,8 @@ void uwb_rc_init(struct uwb_rc *rc)
|
||||||
rc->scan_type = UWB_SCAN_DISABLED;
|
rc->scan_type = UWB_SCAN_DISABLED;
|
||||||
INIT_LIST_HEAD(&rc->notifs_chain.list);
|
INIT_LIST_HEAD(&rc->notifs_chain.list);
|
||||||
mutex_init(&rc->notifs_chain.mutex);
|
mutex_init(&rc->notifs_chain.mutex);
|
||||||
|
INIT_LIST_HEAD(&rc->uwb_beca.list);
|
||||||
|
mutex_init(&rc->uwb_beca.mutex);
|
||||||
uwb_drp_avail_init(rc);
|
uwb_drp_avail_init(rc);
|
||||||
uwb_rc_ie_init(rc);
|
uwb_rc_ie_init(rc);
|
||||||
uwb_rsv_init(rc);
|
uwb_rsv_init(rc);
|
||||||
|
@ -250,6 +249,12 @@ int uwb_rc_add(struct uwb_rc *rc, struct device *parent_dev, void *priv)
|
||||||
|
|
||||||
rc->priv = priv;
|
rc->priv = priv;
|
||||||
|
|
||||||
|
init_waitqueue_head(&rc->uwbd.wq);
|
||||||
|
INIT_LIST_HEAD(&rc->uwbd.event_list);
|
||||||
|
spin_lock_init(&rc->uwbd.event_list_lock);
|
||||||
|
|
||||||
|
uwbd_start(rc);
|
||||||
|
|
||||||
result = rc->start(rc);
|
result = rc->start(rc);
|
||||||
if (result < 0)
|
if (result < 0)
|
||||||
goto error_rc_start;
|
goto error_rc_start;
|
||||||
|
@ -284,7 +289,7 @@ error_sys_add:
|
||||||
error_dev_add:
|
error_dev_add:
|
||||||
error_rc_setup:
|
error_rc_setup:
|
||||||
rc->stop(rc);
|
rc->stop(rc);
|
||||||
uwbd_flush(rc);
|
uwbd_stop(rc);
|
||||||
error_rc_start:
|
error_rc_start:
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -315,16 +320,18 @@ void uwb_rc_rm(struct uwb_rc *rc)
|
||||||
uwb_rc_reset(rc);
|
uwb_rc_reset(rc);
|
||||||
|
|
||||||
rc->stop(rc);
|
rc->stop(rc);
|
||||||
uwbd_flush(rc);
|
|
||||||
|
uwbd_stop(rc);
|
||||||
|
|
||||||
uwb_dev_lock(&rc->uwb_dev);
|
uwb_dev_lock(&rc->uwb_dev);
|
||||||
rc->priv = NULL;
|
rc->priv = NULL;
|
||||||
rc->cmd = NULL;
|
rc->cmd = NULL;
|
||||||
uwb_dev_unlock(&rc->uwb_dev);
|
uwb_dev_unlock(&rc->uwb_dev);
|
||||||
mutex_lock(&uwb_beca.mutex);
|
mutex_lock(&rc->uwb_beca.mutex);
|
||||||
uwb_dev_for_each(rc, uwb_dev_offair_helper, NULL);
|
uwb_dev_for_each(rc, uwb_dev_offair_helper, NULL);
|
||||||
__uwb_rc_sys_rm(rc);
|
__uwb_rc_sys_rm(rc);
|
||||||
mutex_unlock(&uwb_beca.mutex);
|
mutex_unlock(&rc->uwb_beca.mutex);
|
||||||
|
uwb_beca_release(rc);
|
||||||
uwb_dev_rm(&rc->uwb_dev);
|
uwb_dev_rm(&rc->uwb_dev);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(uwb_rc_rm);
|
EXPORT_SYMBOL_GPL(uwb_rc_rm);
|
||||||
|
|
|
@ -160,8 +160,8 @@ struct uwb_event {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
extern void uwbd_start(void);
|
extern void uwbd_start(struct uwb_rc *rc);
|
||||||
extern void uwbd_stop(void);
|
extern void uwbd_stop(struct uwb_rc *rc);
|
||||||
extern struct uwb_event *uwb_event_alloc(size_t, gfp_t gfp_mask);
|
extern struct uwb_event *uwb_event_alloc(size_t, gfp_t gfp_mask);
|
||||||
extern void uwbd_event_queue(struct uwb_event *);
|
extern void uwbd_event_queue(struct uwb_event *);
|
||||||
void uwbd_flush(struct uwb_rc *rc);
|
void uwbd_flush(struct uwb_rc *rc);
|
||||||
|
@ -194,15 +194,6 @@ int uwbd_evt_handle_rc_dev_addr_conflict(struct uwb_event *evt);
|
||||||
|
|
||||||
extern unsigned long beacon_timeout_ms;
|
extern unsigned long beacon_timeout_ms;
|
||||||
|
|
||||||
/** Beacon cache list */
|
|
||||||
struct uwb_beca {
|
|
||||||
struct list_head list;
|
|
||||||
size_t entries;
|
|
||||||
struct mutex mutex;
|
|
||||||
};
|
|
||||||
|
|
||||||
extern struct uwb_beca uwb_beca;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Beacon cache entry
|
* Beacon cache entry
|
||||||
*
|
*
|
||||||
|
@ -229,9 +220,6 @@ struct uwb_beca_e {
|
||||||
struct uwb_beacon_frame;
|
struct uwb_beacon_frame;
|
||||||
extern ssize_t uwb_bce_print_IEs(struct uwb_dev *, struct uwb_beca_e *,
|
extern ssize_t uwb_bce_print_IEs(struct uwb_dev *, struct uwb_beca_e *,
|
||||||
char *, size_t);
|
char *, size_t);
|
||||||
extern struct uwb_beca_e *__uwb_beca_add(struct uwb_rc_evt_beacon *,
|
|
||||||
struct uwb_beacon_frame *,
|
|
||||||
unsigned long);
|
|
||||||
|
|
||||||
extern void uwb_bce_kfree(struct kref *_bce);
|
extern void uwb_bce_kfree(struct kref *_bce);
|
||||||
static inline void uwb_bce_get(struct uwb_beca_e *bce)
|
static inline void uwb_bce_get(struct uwb_beca_e *bce)
|
||||||
|
@ -242,8 +230,8 @@ static inline void uwb_bce_put(struct uwb_beca_e *bce)
|
||||||
{
|
{
|
||||||
kref_put(&bce->refcnt, uwb_bce_kfree);
|
kref_put(&bce->refcnt, uwb_bce_kfree);
|
||||||
}
|
}
|
||||||
extern void uwb_beca_purge(void);
|
extern void uwb_beca_purge(struct uwb_rc *rc);
|
||||||
extern void uwb_beca_release(void);
|
extern void uwb_beca_release(struct uwb_rc *rc);
|
||||||
|
|
||||||
struct uwb_dev *uwb_dev_get_by_devaddr(struct uwb_rc *rc,
|
struct uwb_dev *uwb_dev_get_by_devaddr(struct uwb_rc *rc,
|
||||||
const struct uwb_dev_addr *devaddr);
|
const struct uwb_dev_addr *devaddr);
|
||||||
|
|
|
@ -170,8 +170,6 @@ static const struct uwbd_event uwbd_message_handlers[] = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
static DEFINE_MUTEX(uwbd_event_mutex);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle an URC event passed to the UWB Daemon
|
* Handle an URC event passed to the UWB Daemon
|
||||||
*
|
*
|
||||||
|
@ -235,19 +233,10 @@ static void uwbd_event_handle_message(struct uwb_event *evt)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If this is a reset event we need to drop the
|
|
||||||
* uwbd_event_mutex or it deadlocks when the reset handler
|
|
||||||
* attempts to flush the uwbd events. */
|
|
||||||
if (evt->message == UWB_EVT_MSG_RESET)
|
|
||||||
mutex_unlock(&uwbd_event_mutex);
|
|
||||||
|
|
||||||
result = uwbd_message_handlers[evt->message].handler(evt);
|
result = uwbd_message_handlers[evt->message].handler(evt);
|
||||||
if (result < 0)
|
if (result < 0)
|
||||||
dev_err(&rc->uwb_dev.dev, "UWBD: '%s' message failed: %d\n",
|
dev_err(&rc->uwb_dev.dev, "UWBD: '%s' message failed: %d\n",
|
||||||
uwbd_message_handlers[evt->message].name, result);
|
uwbd_message_handlers[evt->message].name, result);
|
||||||
|
|
||||||
if (evt->message == UWB_EVT_MSG_RESET)
|
|
||||||
mutex_lock(&uwbd_event_mutex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void uwbd_event_handle(struct uwb_event *evt)
|
static void uwbd_event_handle(struct uwb_event *evt)
|
||||||
|
@ -275,20 +264,6 @@ static void uwbd_event_handle(struct uwb_event *evt)
|
||||||
|
|
||||||
__uwb_rc_put(rc); /* for the __uwb_rc_get() in uwb_rc_notif_cb() */
|
__uwb_rc_put(rc); /* for the __uwb_rc_get() in uwb_rc_notif_cb() */
|
||||||
}
|
}
|
||||||
/* The UWB Daemon */
|
|
||||||
|
|
||||||
|
|
||||||
/** Daemon's PID: used to decide if we can queue or not */
|
|
||||||
static int uwbd_pid;
|
|
||||||
/** Daemon's task struct for managing the kthread */
|
|
||||||
static struct task_struct *uwbd_task;
|
|
||||||
/** Daemon's waitqueue for waiting for new events */
|
|
||||||
static DECLARE_WAIT_QUEUE_HEAD(uwbd_wq);
|
|
||||||
/** Daemon's list of events; we queue/dequeue here */
|
|
||||||
static struct list_head uwbd_event_list = LIST_HEAD_INIT(uwbd_event_list);
|
|
||||||
/** Daemon's list lock to protect concurent access */
|
|
||||||
static DEFINE_SPINLOCK(uwbd_event_list_lock);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* UWB Daemon
|
* UWB Daemon
|
||||||
|
@ -302,65 +277,58 @@ static DEFINE_SPINLOCK(uwbd_event_list_lock);
|
||||||
* FIXME: should change so we don't have a 1HZ timer all the time, but
|
* FIXME: should change so we don't have a 1HZ timer all the time, but
|
||||||
* only if there are devices.
|
* only if there are devices.
|
||||||
*/
|
*/
|
||||||
static int uwbd(void *unused)
|
static int uwbd(void *param)
|
||||||
{
|
{
|
||||||
|
struct uwb_rc *rc = param;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
struct list_head list = LIST_HEAD_INIT(list);
|
struct uwb_event *evt;
|
||||||
struct uwb_event *evt, *nxt;
|
|
||||||
int should_stop = 0;
|
int should_stop = 0;
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
wait_event_interruptible_timeout(
|
wait_event_interruptible_timeout(
|
||||||
uwbd_wq,
|
rc->uwbd.wq,
|
||||||
!list_empty(&uwbd_event_list)
|
!list_empty(&rc->uwbd.event_list)
|
||||||
|| (should_stop = kthread_should_stop()),
|
|| (should_stop = kthread_should_stop()),
|
||||||
HZ);
|
HZ);
|
||||||
if (should_stop)
|
if (should_stop)
|
||||||
break;
|
break;
|
||||||
try_to_freeze();
|
try_to_freeze();
|
||||||
|
|
||||||
mutex_lock(&uwbd_event_mutex);
|
spin_lock_irqsave(&rc->uwbd.event_list_lock, flags);
|
||||||
spin_lock_irqsave(&uwbd_event_list_lock, flags);
|
if (!list_empty(&rc->uwbd.event_list)) {
|
||||||
list_splice_init(&uwbd_event_list, &list);
|
evt = list_first_entry(&rc->uwbd.event_list, struct uwb_event, list_node);
|
||||||
spin_unlock_irqrestore(&uwbd_event_list_lock, flags);
|
|
||||||
list_for_each_entry_safe(evt, nxt, &list, list_node) {
|
|
||||||
list_del(&evt->list_node);
|
list_del(&evt->list_node);
|
||||||
|
} else
|
||||||
|
evt = NULL;
|
||||||
|
spin_unlock_irqrestore(&rc->uwbd.event_list_lock, flags);
|
||||||
|
|
||||||
|
if (evt) {
|
||||||
uwbd_event_handle(evt);
|
uwbd_event_handle(evt);
|
||||||
kfree(evt);
|
kfree(evt);
|
||||||
}
|
}
|
||||||
mutex_unlock(&uwbd_event_mutex);
|
|
||||||
|
|
||||||
uwb_beca_purge(); /* Purge devices that left */
|
uwb_beca_purge(rc); /* Purge devices that left */
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** Start the UWB daemon */
|
/** Start the UWB daemon */
|
||||||
void uwbd_start(void)
|
void uwbd_start(struct uwb_rc *rc)
|
||||||
{
|
{
|
||||||
uwbd_task = kthread_run(uwbd, NULL, "uwbd");
|
rc->uwbd.task = kthread_run(uwbd, rc, "uwbd");
|
||||||
if (uwbd_task == NULL)
|
if (rc->uwbd.task == NULL)
|
||||||
printk(KERN_ERR "UWB: Cannot start management daemon; "
|
printk(KERN_ERR "UWB: Cannot start management daemon; "
|
||||||
"UWB won't work\n");
|
"UWB won't work\n");
|
||||||
else
|
else
|
||||||
uwbd_pid = uwbd_task->pid;
|
rc->uwbd.pid = rc->uwbd.task->pid;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Stop the UWB daemon and free any unprocessed events */
|
/* Stop the UWB daemon and free any unprocessed events */
|
||||||
void uwbd_stop(void)
|
void uwbd_stop(struct uwb_rc *rc)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
kthread_stop(rc->uwbd.task);
|
||||||
struct uwb_event *evt, *nxt;
|
uwbd_flush(rc);
|
||||||
kthread_stop(uwbd_task);
|
|
||||||
spin_lock_irqsave(&uwbd_event_list_lock, flags);
|
|
||||||
uwbd_pid = 0;
|
|
||||||
list_for_each_entry_safe(evt, nxt, &uwbd_event_list, list_node) {
|
|
||||||
if (evt->type == UWB_EVT_TYPE_NOTIF)
|
|
||||||
kfree(evt->notif.rceb);
|
|
||||||
kfree(evt);
|
|
||||||
}
|
|
||||||
spin_unlock_irqrestore(&uwbd_event_list_lock, flags);
|
|
||||||
uwb_beca_release();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -377,18 +345,20 @@ void uwbd_stop(void)
|
||||||
*/
|
*/
|
||||||
void uwbd_event_queue(struct uwb_event *evt)
|
void uwbd_event_queue(struct uwb_event *evt)
|
||||||
{
|
{
|
||||||
|
struct uwb_rc *rc = evt->rc;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
spin_lock_irqsave(&uwbd_event_list_lock, flags);
|
|
||||||
if (uwbd_pid != 0) {
|
spin_lock_irqsave(&rc->uwbd.event_list_lock, flags);
|
||||||
list_add(&evt->list_node, &uwbd_event_list);
|
if (rc->uwbd.pid != 0) {
|
||||||
wake_up_all(&uwbd_wq);
|
list_add(&evt->list_node, &rc->uwbd.event_list);
|
||||||
|
wake_up_all(&rc->uwbd.wq);
|
||||||
} else {
|
} else {
|
||||||
__uwb_rc_put(evt->rc);
|
__uwb_rc_put(evt->rc);
|
||||||
if (evt->type == UWB_EVT_TYPE_NOTIF)
|
if (evt->type == UWB_EVT_TYPE_NOTIF)
|
||||||
kfree(evt->notif.rceb);
|
kfree(evt->notif.rceb);
|
||||||
kfree(evt);
|
kfree(evt);
|
||||||
}
|
}
|
||||||
spin_unlock_irqrestore(&uwbd_event_list_lock, flags);
|
spin_unlock_irqrestore(&rc->uwbd.event_list_lock, flags);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -396,10 +366,8 @@ void uwbd_flush(struct uwb_rc *rc)
|
||||||
{
|
{
|
||||||
struct uwb_event *evt, *nxt;
|
struct uwb_event *evt, *nxt;
|
||||||
|
|
||||||
mutex_lock(&uwbd_event_mutex);
|
spin_lock_irq(&rc->uwbd.event_list_lock);
|
||||||
|
list_for_each_entry_safe(evt, nxt, &rc->uwbd.event_list, list_node) {
|
||||||
spin_lock_irq(&uwbd_event_list_lock);
|
|
||||||
list_for_each_entry_safe(evt, nxt, &uwbd_event_list, list_node) {
|
|
||||||
if (evt->rc == rc) {
|
if (evt->rc == rc) {
|
||||||
__uwb_rc_put(rc);
|
__uwb_rc_put(rc);
|
||||||
list_del(&evt->list_node);
|
list_del(&evt->list_node);
|
||||||
|
@ -408,7 +376,5 @@ void uwbd_flush(struct uwb_rc *rc)
|
||||||
kfree(evt);
|
kfree(evt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
spin_unlock_irq(&uwbd_event_list_lock);
|
spin_unlock_irq(&rc->uwbd.event_list_lock);
|
||||||
|
|
||||||
mutex_unlock(&uwbd_event_mutex);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
#include <linux/device.h>
|
#include <linux/device.h>
|
||||||
#include <linux/mutex.h>
|
#include <linux/mutex.h>
|
||||||
#include <linux/timer.h>
|
#include <linux/timer.h>
|
||||||
|
#include <linux/wait.h>
|
||||||
#include <linux/workqueue.h>
|
#include <linux/workqueue.h>
|
||||||
#include <linux/uwb/spec.h>
|
#include <linux/uwb/spec.h>
|
||||||
|
|
||||||
|
@ -86,6 +87,22 @@ struct uwb_notifs_chain {
|
||||||
struct mutex mutex;
|
struct mutex mutex;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Beacon cache list */
|
||||||
|
struct uwb_beca {
|
||||||
|
struct list_head list;
|
||||||
|
size_t entries;
|
||||||
|
struct mutex mutex;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Event handling thread. */
|
||||||
|
struct uwbd {
|
||||||
|
int pid;
|
||||||
|
struct task_struct *task;
|
||||||
|
wait_queue_head_t wq;
|
||||||
|
struct list_head event_list;
|
||||||
|
spinlock_t event_list_lock;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct uwb_mas_bm - a bitmap of all MAS in a superframe
|
* struct uwb_mas_bm - a bitmap of all MAS in a superframe
|
||||||
* @bm: a bitmap of length #UWB_NUM_MAS
|
* @bm: a bitmap of length #UWB_NUM_MAS
|
||||||
|
@ -342,6 +359,9 @@ struct uwb_rc {
|
||||||
enum uwb_scan_type scan_type:3;
|
enum uwb_scan_type scan_type:3;
|
||||||
unsigned ready:1;
|
unsigned ready:1;
|
||||||
struct uwb_notifs_chain notifs_chain;
|
struct uwb_notifs_chain notifs_chain;
|
||||||
|
struct uwb_beca uwb_beca;
|
||||||
|
|
||||||
|
struct uwbd uwbd;
|
||||||
|
|
||||||
struct uwb_drp_avail drp_avail;
|
struct uwb_drp_avail drp_avail;
|
||||||
struct list_head reservations;
|
struct list_head reservations;
|
||||||
|
|
Loading…
Add table
Reference in a new issue