Skip to content

Commit

Permalink
uwb: add basic radio manager
Browse files Browse the repository at this point in the history
The UWB radio manager coordinates the use of the radio between the
PALs that may be using it.  PALs request use of the radio with
uwb_radio_start() and the radio manager will start beaconing if its
not already doing so.  When the last PAL has called uwb_radio_stop()
beaconing will be stopped.

In the future, the radio manager will have a more sophisticated channel
selection algorithm, probably following the Channel Selection Policy
from the WiMedia Alliance when it is finalized.  For now, channel 9
(BG1, TFC1) is selected.

The user may override the channel selected by the radio manager and may
force the radio to stop beaconing.

The WUSB Host Controller PAL makes use of this and there are two new
debug PAL commands that can be used for testing.

Signed-off-by: David Vrabel <david.vrabel@csr.com>
  • Loading branch information
David Vrabel committed Nov 19, 2008
1 parent e17be2b commit 6fae35f
Show file tree
Hide file tree
Showing 21 changed files with 323 additions and 162 deletions.
14 changes: 8 additions & 6 deletions Documentation/ABI/testing/sysfs-class-uwb_rc
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,16 @@ Contact: linux-usb@vger.kernel.org
Description:
Write:

<channel> [<bpst offset>]
<channel>

to start beaconing on a specific channel, or stop
beaconing if <channel> is -1. Valid channels depends
on the radio controller's supported band groups.
to force a specific channel to be used when beaconing,
or, if <channel> is -1, to prohibit beaconing. If
<channel> is 0, then the default channel selection
algorithm will be used. Valid channels depends on the
radio controller's supported band groups.

<bpst offset> may be used to try and join a specific
beacon group if more than one was found during a scan.
Reading returns the currently active channel, or -1 if
the radio controller is not beaconing.

What: /sys/class/uwb_rc/uwbN/scan
Date: July 2008
Expand Down
9 changes: 0 additions & 9 deletions Documentation/usb/wusb-cbaf
Original file line number Diff line number Diff line change
Expand Up @@ -80,12 +80,6 @@ case $1 in
start)
for dev in ${2:-$hdevs}
do
uwb_rc=$(readlink -f $dev/uwb_rc)
if cat $uwb_rc/beacon | grep -q -- "-1"
then
echo 13 0 > $uwb_rc/beacon
echo I: started beaconing on ch 13 on $(basename $uwb_rc) >&2
fi
echo $host_CHID > $dev/wusb_chid
echo I: started host $(basename $dev) >&2
done
Expand All @@ -95,9 +89,6 @@ case $1 in
do
echo 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 > $dev/wusb_chid
echo I: stopped host $(basename $dev) >&2
uwb_rc=$(readlink -f $dev/uwb_rc)
echo -1 | cat > $uwb_rc/beacon
echo I: stopped beaconing on $(basename $uwb_rc) >&2
done
;;
set-chid)
Expand Down
1 change: 0 additions & 1 deletion drivers/usb/host/hwa-hc.c
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,6 @@ static void hwahc_op_stop(struct usb_hcd *usb_hcd)

d_fnstart(4, dev, "(hwahc %p)\n", hwahc);
mutex_lock(&wusbhc->mutex);
wusbhc_stop(wusbhc);
wusb_cluster_id_put(wusbhc->cluster_id);
mutex_unlock(&wusbhc->mutex);
d_fnend(4, dev, "(hwahc %p) = %d\n", hwahc, result);
Expand Down
2 changes: 0 additions & 2 deletions drivers/usb/host/whci/hcd.c
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,6 @@ static void whc_stop(struct usb_hcd *usb_hcd)

mutex_lock(&wusbhc->mutex);

wusbhc_stop(wusbhc);

/* stop HC */
le_writel(0, whc->base + WUSBINTR);
whc_write_wusbcmd(whc, WUSBCMD_RUN, 0);
Expand Down
5 changes: 2 additions & 3 deletions drivers/usb/wusbcore/devconnect.c
Original file line number Diff line number Diff line change
Expand Up @@ -1124,8 +1124,7 @@ void wusbhc_devconnect_destroy(struct wusbhc *wusbhc)
* FIXME: This also enables the keep alives but this is not necessary
* until there are connected and authenticated devices.
*/
int wusbhc_devconnect_start(struct wusbhc *wusbhc,
const struct wusb_ckhdid *chid)
int wusbhc_devconnect_start(struct wusbhc *wusbhc)
{
struct device *dev = wusbhc->dev;
struct wuie_host_info *hi;
Expand All @@ -1138,7 +1137,7 @@ int wusbhc_devconnect_start(struct wusbhc *wusbhc,
hi->hdr.bLength = sizeof(*hi);
hi->hdr.bIEIdentifier = WUIE_ID_HOST_INFO;
hi->attributes = cpu_to_le16((wusbhc->rsv->stream << 3) | WUIE_HI_CAP_ALL);
hi->CHID = *chid;
hi->CHID = wusbhc->chid;
result = wusbhc_mmcie_set(wusbhc, 0, 0, &hi->hdr);
if (result < 0) {
dev_err(dev, "Cannot add Host Info MMCIE: %d\n", result);
Expand Down
75 changes: 13 additions & 62 deletions drivers/usb/wusbcore/mmc.c
Original file line number Diff line number Diff line change
Expand Up @@ -162,12 +162,11 @@ EXPORT_SYMBOL_GPL(wusbhc_mmcie_rm);
/*
* wusbhc_start - start transmitting MMCs and accepting connections
* @wusbhc: the HC to start
* @chid: the CHID to use for this host
*
* Establishes a cluster reservation, enables device connections, and
* starts MMCs with appropriate DNTS parameters.
*/
int wusbhc_start(struct wusbhc *wusbhc, const struct wusb_ckhdid *chid)
int wusbhc_start(struct wusbhc *wusbhc)
{
int result;
struct device *dev = wusbhc->dev;
Expand All @@ -181,7 +180,7 @@ int wusbhc_start(struct wusbhc *wusbhc, const struct wusb_ckhdid *chid)
goto error_rsv_establish;
}

result = wusbhc_devconnect_start(wusbhc, chid);
result = wusbhc_devconnect_start(wusbhc);
if (result < 0) {
dev_err(dev, "error enabling device connections: %d\n", result);
goto error_devconnect_start;
Expand Down Expand Up @@ -218,34 +217,6 @@ int wusbhc_start(struct wusbhc *wusbhc, const struct wusb_ckhdid *chid)
return result;
}

/*
* Disconnect all from the WUSB Channel
*
* Send a Host Disconnect IE in the MMC, wait, don't send it any more
*/
static int __wusbhc_host_disconnect_ie(struct wusbhc *wusbhc)
{
int result = -ENOMEM;
struct wuie_host_disconnect *host_disconnect_ie;
might_sleep();
host_disconnect_ie = kmalloc(sizeof(*host_disconnect_ie), GFP_KERNEL);
if (host_disconnect_ie == NULL)
goto error_alloc;
host_disconnect_ie->hdr.bLength = sizeof(*host_disconnect_ie);
host_disconnect_ie->hdr.bIEIdentifier = WUIE_ID_HOST_DISCONNECT;
result = wusbhc_mmcie_set(wusbhc, 0, 0, &host_disconnect_ie->hdr);
if (result < 0)
goto error_mmcie_set;

/* WUSB1.0[8.5.3.1 & 7.5.2] */
msleep(100);
wusbhc_mmcie_rm(wusbhc, &host_disconnect_ie->hdr);
error_mmcie_set:
kfree(host_disconnect_ie);
error_alloc:
return result;
}

/*
* wusbhc_stop - stop transmitting MMCs
* @wusbhc: the HC to stop
Expand All @@ -264,29 +235,6 @@ void wusbhc_stop(struct wusbhc *wusbhc)
}
EXPORT_SYMBOL_GPL(wusbhc_stop);

/*
* Change the CHID in a WUSB Channel
*
* If it is just a new CHID, send a Host Disconnect IE and then change
* the CHID IE.
*/
static int __wusbhc_chid_change(struct wusbhc *wusbhc,
const struct wusb_ckhdid *chid)
{
int result = -ENOSYS;
struct device *dev = wusbhc->dev;
dev_err(dev, "%s() not implemented yet\n", __func__);
return result;

BUG_ON(wusbhc->wuie_host_info == NULL);
__wusbhc_host_disconnect_ie(wusbhc);
wusbhc->wuie_host_info->CHID = *chid;
result = wusbhc_mmcie_set(wusbhc, 0, 0, &wusbhc->wuie_host_info->hdr);
if (result < 0)
dev_err(dev, "Can't update Host Info WUSB IE: %d\n", result);
return result;
}

/*
* Set/reset/update a new CHID
*
Expand All @@ -302,16 +250,19 @@ int wusbhc_chid_set(struct wusbhc *wusbhc, const struct wusb_ckhdid *chid)
chid = NULL;

mutex_lock(&wusbhc->mutex);
if (wusbhc->active) {
if (chid)
result = __wusbhc_chid_change(wusbhc, chid);
else
wusbhc_stop(wusbhc);
} else {
if (chid)
wusbhc_start(wusbhc, chid);
if (chid) {
if (wusbhc->active) {
mutex_unlock(&wusbhc->mutex);
return -EBUSY;
}
wusbhc->chid = *chid;
}
mutex_unlock(&wusbhc->mutex);

if (chid)
result = uwb_radio_start(&wusbhc->pal);
else
uwb_radio_stop(&wusbhc->pal);
return result;
}
EXPORT_SYMBOL_GPL(wusbhc_chid_set);
16 changes: 14 additions & 2 deletions drivers/usb/wusbcore/pal.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,16 @@
*/
#include "wusbhc.h"

static void wusbhc_channel_changed(struct uwb_pal *pal, int channel)
{
struct wusbhc *wusbhc = container_of(pal, struct wusbhc, pal);

if (channel < 0)
wusbhc_stop(wusbhc);
else
wusbhc_start(wusbhc);
}

/**
* wusbhc_pal_register - register the WUSB HC as a UWB PAL
* @wusbhc: the WUSB HC
Expand All @@ -28,8 +38,10 @@ int wusbhc_pal_register(struct wusbhc *wusbhc)

wusbhc->pal.name = "wusbhc";
wusbhc->pal.device = wusbhc->usb_hcd.self.controller;
wusbhc->pal.rc = wusbhc->uwb_rc;
wusbhc->pal.channel_changed = wusbhc_channel_changed;

return uwb_pal_register(wusbhc->uwb_rc, &wusbhc->pal);
return uwb_pal_register(&wusbhc->pal);
}

/**
Expand All @@ -38,5 +50,5 @@ int wusbhc_pal_register(struct wusbhc *wusbhc)
*/
void wusbhc_pal_unregister(struct wusbhc *wusbhc)
{
uwb_pal_unregister(wusbhc->uwb_rc, &wusbhc->pal);
uwb_pal_unregister(&wusbhc->pal);
}
8 changes: 4 additions & 4 deletions drivers/usb/wusbcore/wusbhc.h
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,8 @@ struct wusbhc {
struct uwb_pal pal;

unsigned trust_timeout; /* in jiffies */
struct wuie_host_info *wuie_host_info; /* Includes CHID */
struct wusb_ckhdid chid;
struct wuie_host_info *wuie_host_info;

struct mutex mutex; /* locks everything else */
u16 cluster_id; /* Wireless USB Cluster ID */
Expand Down Expand Up @@ -376,15 +377,14 @@ static inline void wusbhc_put(struct wusbhc *wusbhc)
usb_put_hcd(&wusbhc->usb_hcd);
}

int wusbhc_start(struct wusbhc *wusbhc, const struct wusb_ckhdid *chid);
int wusbhc_start(struct wusbhc *wusbhc);
void wusbhc_stop(struct wusbhc *wusbhc);
extern int wusbhc_chid_set(struct wusbhc *, const struct wusb_ckhdid *);

/* Device connect handling */
extern int wusbhc_devconnect_create(struct wusbhc *);
extern void wusbhc_devconnect_destroy(struct wusbhc *);
extern int wusbhc_devconnect_start(struct wusbhc *wusbhc,
const struct wusb_ckhdid *chid);
extern int wusbhc_devconnect_start(struct wusbhc *wusbhc);
extern void wusbhc_devconnect_stop(struct wusbhc *wusbhc);
extern void wusbhc_handle_dn(struct wusbhc *, u8 srcaddr,
struct wusb_dn_hdr *dn_hdr, size_t size);
Expand Down
1 change: 1 addition & 0 deletions drivers/uwb/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ uwb-objs := \
lc-rc.o \
neh.o \
pal.o \
radio.o \
reset.o \
rsv.o \
scan.o \
Expand Down
26 changes: 8 additions & 18 deletions drivers/uwb/beacon.c
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,6 @@ int uwb_rc_beacon(struct uwb_rc *rc, int channel, unsigned bpst_offset)
int result;
struct device *dev = &rc->uwb_dev.dev;

mutex_lock(&rc->uwb_dev.mutex);
if (channel < 0)
channel = -1;
if (channel == -1)
Expand All @@ -128,7 +127,7 @@ int uwb_rc_beacon(struct uwb_rc *rc, int channel, unsigned bpst_offset)
/* channel >= 0...dah */
result = uwb_rc_start_beacon(rc, bpst_offset, channel);
if (result < 0)
goto out_up;
return result;
if (le16_to_cpu(rc->ies->wIELength) > 0) {
result = uwb_rc_set_ie(rc, rc->ies);
if (result < 0) {
Expand All @@ -137,19 +136,14 @@ int uwb_rc_beacon(struct uwb_rc *rc, int channel, unsigned bpst_offset)
result = uwb_rc_stop_beacon(rc);
channel = -1;
bpst_offset = 0;
} else
result = 0;
}
}
}

if (result < 0)
goto out_up;
rc->beaconing = channel;

uwb_notify(rc, NULL, uwb_bg_joined(rc) ? UWB_NOTIF_BG_JOIN : UWB_NOTIF_BG_LEAVE);

out_up:
mutex_unlock(&rc->uwb_dev.mutex);
if (result >= 0) {
rc->beaconing = channel;
uwb_notify(rc, NULL, uwb_bg_joined(rc) ? UWB_NOTIF_BG_JOIN : UWB_NOTIF_BG_LEAVE);
}
return result;
}

Expand Down Expand Up @@ -618,9 +612,6 @@ static ssize_t uwb_rc_beacon_show(struct device *dev,

/*
* Start beaconing on the specified channel, or stop beaconing.
*
* The BPST offset of when to start searching for a beacon group to
* join may be specified.
*/
static ssize_t uwb_rc_beacon_store(struct device *dev,
struct device_attribute *attr,
Expand All @@ -629,12 +620,11 @@ static ssize_t uwb_rc_beacon_store(struct device *dev,
struct uwb_dev *uwb_dev = to_uwb_dev(dev);
struct uwb_rc *rc = uwb_dev->rc;
int channel;
unsigned bpst_offset = 0;
ssize_t result = -EINVAL;

result = sscanf(buf, "%d %u\n", &channel, &bpst_offset);
result = sscanf(buf, "%d", &channel);
if (result >= 1)
result = uwb_rc_beacon(rc, channel, bpst_offset);
result = uwb_radio_force_channel(rc, channel);

return result < 0 ? result : size;
}
Expand Down
24 changes: 2 additions & 22 deletions drivers/uwb/drp.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,13 @@
*
* A DRP Availability IE is appended.
*
* rc->uwb_dev.mutex is held
* rc->rsvs_mutex is held
*
* FIXME We currently ignore the returned value indicating the remaining space
* in beacon. This could be used to deny reservation requests earlier if
* determined that they would cause the beacon space to be exceeded.
*/
static
int uwb_rc_gen_send_drp_ie(struct uwb_rc *rc)
int uwb_rc_send_all_drp_ie(struct uwb_rc *rc)
{
int result;
struct device *dev = &rc->uwb_dev.dev;
Expand Down Expand Up @@ -102,25 +101,6 @@ int uwb_rc_gen_send_drp_ie(struct uwb_rc *rc)
kfree(cmd);
error:
return result;

}
/**
* Send all DRP IEs associated with this host
*
* @returns: >= 0 number of bytes still available in the beacon
* < 0 errno code on error.
*
* As per the protocol we obtain the host controller device lock to access
* bandwidth structures.
*/
int uwb_rc_send_all_drp_ie(struct uwb_rc *rc)
{
int result;

mutex_lock(&rc->uwb_dev.mutex);
result = uwb_rc_gen_send_drp_ie(rc);
mutex_unlock(&rc->uwb_dev.mutex);
return result;
}

void uwb_drp_handle_timeout(struct uwb_rsv *rsv)
Expand Down
Loading

0 comments on commit 6fae35f

Please sign in to comment.