Re: [RFC/PATCH] USB reset on atomic context
David Vrabel <[email protected]> Thu, 14 Aug 2008 13:17:51 +0100
| Newsgroups | gmane.linux.usb.general,gmane.linux.usb.devel |
|---|---|
| Message-ID | <[email protected]> |
This is a multi-part message in MIME format.
--------------040704060100070904000600
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit
Inaky Perez-Gonzalez wrote:
> On Wednesday 13 August 2008, David Vrabel wrote:
>> Inaky Perez-Gonzalez wrote:
>>> Hi All
>>>
>>> This patch introduces a new call to be able to do a USB reset
>>> from an atomic contect. This is quite helpful in USB callbacks
>>> to handle errors (when the only thing that can be done is to
>>> do a device reset). The Wireless USB code for using wire adaptors
>>> needs this functionality.
>> I've since changed how resets are handled in the UWB/WUSB code and this
>> is no longer necessary for HWAs (reset requests go via the UWB stack
>> which carries them in out in the uwbd thread).
>
> Ouch...doesn't that make the error handling more twisted? Where do you have
> the code so i can take a look?
It's not so bad. The attached patch gives you some idea of the changes.
Most of them are related to the changes to the struct uwb_event.
I also think it makes more sense as it will allow the RC to inform PALs
of impending resets in a h/w independent way (the code does make any use
of this yet).
There are still problems with events still queued after a RC has been
removed, but these aren't unique to the reset event.
> I don't see how it'd be different for DWA though -- the base WA code is
> the same both for HWA and DWA.
DWAs don't have a radio controller or other PALs to worry about.
David
--
David Vrabel, Senior Software Engineer, Drivers
CSR, Churchill House, Cambridge Business Park, Tel: +44 (0)1223 692562
Cowley Road, Cambridge, CB4 0WZ http://www.csr.com/
--------------040704060100070904000600
Content-Type: text/x-diff;
name="uwb_rc_reset_all.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="uwb_rc_reset_all.patch"
---
drivers/usb/wusbcore/wa-hc.c | 12 ++++
drivers/usb/wusbcore/wa-hc.h | 1
drivers/usb/wusbcore/wa-nep.c | 4 -
drivers/usb/wusbcore/wa-xfer.c | 16 ++---
drivers/usb/wusbcore/wusbhc.c | 32 +++++++++--
drivers/usb/wusbcore/wusbhc.h | 1
drivers/uwb/beacon.c | 22 +++----
drivers/uwb/csr-sdio/uwb-sdio-rc.c | 12 +++-
drivers/uwb/drp-avail.c | 6 +-
drivers/uwb/drp.c | 8 +-
drivers/uwb/hwa-rc.c | 27 ++++++---
drivers/uwb/i1480/i1480u-wlp/lc.c | 2
drivers/uwb/i1480/i1480u-wlp/rx.c | 2
drivers/uwb/i1480/i1480u-wlp/tx.c | 4 -
drivers/uwb/ie-rcv.c | 6 +-
drivers/uwb/lc-dev.c | 1
drivers/uwb/lc-rc.c | 57 +++++++++++--------
drivers/uwb/neh.c | 5 +
drivers/uwb/reset.c | 31 ++++++++++
drivers/uwb/umc-bus.c | 37 +++++++++++-
drivers/uwb/urccli.c | 8 +-
drivers/uwb/uwb-internal.h | 51 +++++++++++++----
drivers/uwb/uwbd.c | 96 ++++++++++++++++++++++-----------
drivers/uwb/whc-rc.c | 26 ++++++++
drivers/uwb/wlp/wlp-lc.c | 13 ++++
series | 6 +-
uwb-reuse-radio-controller-names.patch | 38 +++++++++++++
uwb-umc_controller_reset.patch | 12 ++++
uwb-uwb_rc_reset_all.patch | 43 ++++++++++++++
29 files changed, 449 insertions(+), 130 deletions(-)
--- a/drivers/uwb/whc-rc.c 2008-08-14 13:11:15.000000000 +0100
+++ b/drivers/uwb/whc-rc.c 2008-08-14 13:11:17.000000000 +0100
@@ -76,6 +76,7 @@
struct work_struct event_work;
};
+static int whcrc_start_rc(struct whcrc *whcrc);
/**
* Execute an UWB RC command on WHCI/RC
@@ -107,6 +108,19 @@
goto error;
}
+ /*
+ * If the URC is halted, then the hardware has reset itself.
+ * Attempt to recover by restarting the device and then return
+ * an error as it's likely that the current command isn't
+ * valid for a newly started RC.
+ */
+ if (le_readl(whcrc->rc_base + URCSTS) & URCSTS_HALTED) {
+ dev_err(dev, "restarting halted radio controller\n");
+ uwb_rc_reset_all(uwb_rc);
+ result = -EIO;
+ goto error;
+ }
+
result = wait_event_timeout(whcrc->cmd_wq,
!(le_readl(whcrc->rc_base + URCCMD) & URCCMD_ACTIVE), HZ/2);
if (result == 0) {
@@ -129,9 +143,13 @@
d_fnend(3, dev, "(%p, %p, %zu) = %d\n",
uwb_rc, cmd, cmd_size, result);
return result;
+}
+static int whcrc_reset(struct uwb_rc *rc)
+{
+ struct whcrc *whcrc = rc->priv;
-
+ return umc_controller_reset(whcrc->umc_dev);
}
/**
@@ -437,7 +455,11 @@
goto error_start_rc;
}
whcrc->uwb_rc = uwb_rc;
- result = uwb_rc_add(uwb_rc, dev, whcrc, whcrc_cmd, NULL, NULL);
+
+ uwb_rc->cmd = whcrc_cmd;
+ uwb_rc->reset = whcrc_reset;
+
+ result = uwb_rc_add(uwb_rc, dev, whcrc);
if (result < 0)
goto error_rc_add;
umc_set_drvdata(umc_dev, whcrc);
--- a/drivers/uwb/lc-rc.c 2008-08-14 13:11:15.000000000 +0100
+++ b/drivers/uwb/lc-rc.c 2008-08-14 13:11:16.000000000 +0100
@@ -41,19 +41,38 @@
#include "uwb-internal.h"
#include "urccli.h"
+static int uwb_rc_index_match(struct device *dev, void *data)
+{
+ int *index = data;
+ struct uwb_rc *rc = dev_get_drvdata(dev);
+
+ if (rc->index == *index)
+ return 1;
+ return 0;
+}
-struct uwb_rcs {
- size_t count;
- struct mutex mutex;
-};
-
-/** List of UWB RCs we keep around. */
-static
-struct uwb_rcs uwb_rcs = {
- .count = 0,
- .mutex = __MUTEX_INITIALIZER(uwb_rcs.mutex),
-};
+static struct uwb_rc *uwb_rc_find_by_index(int index)
+{
+ struct device *dev;
+ struct uwb_rc *rc = NULL;
+
+ dev = class_find_device(&uwb_rc_class, NULL, &index, uwb_rc_index_match);
+ if (dev)
+ rc = dev_get_drvdata(dev);
+ return rc;
+}
+
+static int uwb_rc_new_index(void)
+{
+ int index = 0;
+ for (;;) {
+ if (!uwb_rc_find_by_index(index))
+ return index;
+ if (++index < 0)
+ index = 0;
+ }
+}
/**
* Release the backing device of a uwb_rc that has been dynamically allocated.
@@ -226,28 +245,18 @@
*
* @parent_dev is our real device, the one that provides the actual UWB device
*/
-int uwb_rc_add(struct uwb_rc *rc, struct device *parent_dev, void *priv,
- int (*cmd)(struct uwb_rc *, const struct uwb_rccb *, size_t),
- int (*filter_cmd)(struct uwb_rc *, struct uwb_rccb **, size_t *),
- int (*filter_event)(struct uwb_rc *, struct uwb_rceb **,
- const size_t, size_t *, size_t *))
+int uwb_rc_add(struct uwb_rc *rc, struct device *parent_dev, void *priv)
{
int result;
- size_t rc_count;
struct device *dev;
char macbuf[UWB_ADDR_STRSIZE], devbuf[UWB_ADDR_STRSIZE];
- mutex_lock(&uwb_rcs.mutex);
- rc_count = uwb_rcs.count++;
- mutex_unlock(&uwb_rcs.mutex);
+ rc->index = uwb_rc_new_index();
dev = &rc->uwb_dev.dev;
- dev_set_name(dev, "uwb%d", (int)rc_count);
+ dev_set_name(dev, "uwb%d", rc->index);
rc->priv = priv;
- rc->cmd = cmd;
- rc->filter_cmd = filter_cmd;
- rc->filter_event = filter_event;
result = uwb_rc_setup(rc);
if (result < 0) {
--- a/series 2008-08-14 13:11:18.000000000 +0100
+++ b/series 2008-08-14 13:11:18.000000000 +0100
@@ -10,8 +10,7 @@
#
# USB core patches
#
-# This needs fixing
-usb-add-usb_dev_reset_delayed.patch
+
#
# UWB/WUSB patches
#
@@ -62,6 +61,9 @@
uwb-depend-on-experimental.patch
usb-cbaf-correct-sysfs-api.patch
uwb-add-relinquish-ie-infrastructure.patch
+uwb-reuse-radio-controller-names.patch
+uwb-umc_controller_reset.patch
+uwb-uwb_rc_reset_all.patch
#
# Local patches not for upstream (or patches from upstream applied
# locally)
--- a/uwb-reuse-radio-controller-names.patch 1970-01-01 01:00:00.000000000 +0100
+++ b/uwb-reuse-radio-controller-names.patch 2008-08-14 13:11:15.000000000 +0100
@@ -0,0 +1,38 @@
+UWB: try and reuse old radio controller device names
+
+From: David Vrabel <[email protected]>
+
+It can be useful for radio controllers that are removed and re-added
+to keep the same name.
+
+Signed-off-by: David Vrabel <[email protected]>
+
+---
+ include/linux/uwb.h | 7 +++----
+ 1 file changed, 3 insertions(+), 4 deletions(-)
+
+Index: linux-2.6-working/include/linux/uwb.h
+===================================================================
+--- linux-2.6-working.orig/include/linux/uwb.h 2008-08-06 14:04:32.000000000 +0100
++++ linux-2.6-working/include/linux/uwb.h 2008-08-06 14:04:40.000000000 +0100
+@@ -285,10 +285,8 @@
+ *
+ * Life cycle rules: those of the UWB Device.
+ *
+- * FIXME: move most fields that are not continuously accessed to
+- * bitfields to pack the info a wee bit. Channels go from 0 to
+- * 46, for example.
+- *
++ * @index: an index number for this radio controller, as used in the
++ * device name.
+ * @version: version of protocol supported by this device
+ * @priv: Backend implementation; rw with uwb_dev.dev.sem taken.
+ * @cmd: Backend implementation to execute commands; rw and call
+@@ -322,6 +320,7 @@
+ */
+ struct uwb_rc {
+ struct uwb_dev uwb_dev;
++ int index;
+ u16 version;
+
+ void *priv;
--- a/drivers/uwb/urccli.c 2008-08-14 13:11:15.000000000 +0100
+++ b/drivers/uwb/urccli.c 2008-08-14 13:11:15.000000000 +0100
@@ -242,7 +242,6 @@
struct urccli_device *urccli;
struct device *dev = &uwb_rc->uwb_dev.dev;
struct uwb_dev *uwb_dev = container_of(dev, struct uwb_dev, dev);
- int rc_num = 0;
int ret = -1;
dev_t devno;
@@ -254,8 +253,7 @@
|| (uwb_rc->urccli != NULL)) /* already initialised */
return;
- sscanf(dev->bus_id, "uwb%d", &rc_num);
- if (rc_num >= URCCLI_DEVS_MAX) {
+ if (uwb_rc->index >= URCCLI_DEVS_MAX) {
dev_warn(dev, "too many urccli devices\n");
return;
}
@@ -278,13 +276,13 @@
atomic_set(&urccli->ref_count, 1);
- devno = MKDEV(MAJOR(urccli_dev), MINOR(urccli_dev) + rc_num);
+ devno = MKDEV(MAJOR(urccli_dev), MINOR(urccli_dev) + uwb_rc->index);
ret = cdev_add(&urccli->cdev, devno, 1);
if (ret)
goto error_cdev;
if (!device_create(urccli_class, NULL, urccli->cdev.dev, NULL,
- "urccli%d", MINOR(urccli->cdev.dev)))
+ "urccli%d", uwb_rc->index))
goto error_class_dev;
return;
--- a/drivers/uwb/umc-bus.c 2008-08-14 13:11:16.000000000 +0100
+++ b/drivers/uwb/umc-bus.c 2008-08-14 13:11:16.000000000 +0100
@@ -10,9 +10,40 @@
#include <linux/workqueue.h>
#include <linux/uwb/umc.h>
#include <linux/pci.h>
-#define D_LOCAL 0
-#include <linux/uwb/debug.h>
+static int umc_bus_unbind_helper(struct device *dev, void *data)
+{
+ struct device *parent = data;
+
+ if (dev->parent == parent && dev->driver)
+ device_release_driver(dev);
+ return 0;
+}
+
+/**
+ * umc_controller_reset - reset the whole UMC controller
+ * @umc: the UMC device for the radio controller.
+ *
+ * Drivers will be unbound from all UMC devices belonging to the
+ * controller and then the radio controller will be rebound. The
+ * radio controller is expected to do a full hardware reset when it is
+ * probed.
+ *
+ * Do not call from within a probe() or remove().
+ */
+int umc_controller_reset(struct umc_dev *umc)
+{
+ struct device *parent = umc->dev.parent;
+ int ret;
+
+ down(&parent->sem);
+ bus_for_each_dev(&umc_bus_type, NULL, parent, umc_bus_unbind_helper);
+ ret = device_attach(&umc->dev);
+ up(&parent->sem);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(umc_controller_reset);
/**
* umc_match_pci_id - match a UMC driver to a UMC device's parent PCI device.
@@ -174,9 +205,7 @@
static void __exit umc_bus_exit(void)
{
- d_fnstart(4, NULL, "()\n");
bus_unregister(&umc_bus_type);
- d_fnend(4, NULL, "() = void\n");
}
module_exit(umc_bus_exit);
--- a/drivers/uwb/beacon.c 2008-08-14 13:11:16.000000000 +0100
+++ b/drivers/uwb/beacon.c 2008-08-14 13:11:16.000000000 +0100
@@ -375,9 +375,9 @@
struct device *dev = &rc->uwb_dev.dev;
/* Is there enough data to decode a beacon frame? */
- if (evt->size < sizeof(*be) + sizeof(*bf)) {
+ if (evt->notif.size < sizeof(*be) + sizeof(*bf)) {
dev_err(dev, "BEACON event: Not enough data to decode "
- "(%zu vs %zu bytes needed)\n", evt->size,
+ "(%zu vs %zu bytes needed)\n", evt->notif.size,
sizeof(*be) + sizeof(*bf));
goto error;
}
@@ -410,7 +410,7 @@
unsigned long last_ts;
rc = evt->rc;
- be = container_of(evt->rceb, struct uwb_rc_evt_beacon, rceb);
+ be = container_of(evt->notif.rceb, struct uwb_rc_evt_beacon, rceb);
result = uwb_verify_beacon(rc, evt, be);
if (result < 0)
return result;
@@ -494,13 +494,13 @@
struct uwb_rc_evt_beacon_size *bs;
/* Is there enough data to decode the event? */
- if (evt->size < sizeof(*bs)) {
+ if (evt->notif.size < sizeof(*bs)) {
dev_err(dev, "BEACON SIZE notification: Not enough data to "
"decode (%zu vs %zu bytes needed)\n",
- evt->size, sizeof(*bs));
+ evt->notif.size, sizeof(*bs));
goto error;
}
- bs = container_of(evt->rceb, struct uwb_rc_evt_beacon_size, rceb);
+ bs = container_of(evt->notif.rceb, struct uwb_rc_evt_beacon_size, rceb);
if (0)
dev_info(dev, "Beacon size changed to %u bytes "
"(FIXME: action?)\n", le16_to_cpu(bs->wNewBeaconSize));
@@ -528,11 +528,11 @@
struct uwb_rc_evt_bp_slot_change *bpsc;
/* Is there enough data to decode a beacon frame? */
- if (evt->size < sizeof(*bpsc)) {
+ if (evt->notif.size < sizeof(*bpsc)) {
printk(KERN_ERR "BP SLOT CHANGE event: Not enough data\n");
goto error;
}
- bpsc = container_of(evt->rceb, struct uwb_rc_evt_bp_slot_change, rceb);
+ bpsc = container_of(evt->notif.rceb, struct uwb_rc_evt_bp_slot_change, rceb);
dev_info(dev, "BP slot changed to #%u (FIXME: action?)\n",
bpsc->bSlotNumber);
result = 0;
@@ -561,13 +561,13 @@
size_t iesize;
/* Is there enough data to decode it? */
- if (evt->size < sizeof(*bpoiec)) {
+ if (evt->notif.size < sizeof(*bpoiec)) {
dev_err(dev, "BPOIEC notification: Not enough data to "
"decode (%zu vs %zu bytes needed)\n",
- evt->size, sizeof(*bpoiec));
+ evt->notif.size, sizeof(*bpoiec));
goto error;
}
- bpoiec = container_of(evt->rceb, struct uwb_rc_evt_bpoie_change, rceb);
+ bpoiec = container_of(evt->notif.rceb, struct uwb_rc_evt_bpoie_change, rceb);
iesize = le16_to_cpu(bpoiec->wBPOIELength);
if (iesize < sizeof(*bpoie)) {
dev_err(dev, "BPOIEC notification: Not enough IE data to "
--- a/drivers/uwb/csr-sdio/uwb-sdio-rc.c 2008-08-14 13:11:16.000000000 +0100
+++ b/drivers/uwb/csr-sdio/uwb-sdio-rc.c 2008-08-14 13:11:16.000000000 +0100
@@ -26,6 +26,12 @@
return uwb_sdio_send(usdio, rccb, len, SDIO_BT_A_SID_CMD);
}
+static int uwb_sdio_rc_reset(struct uwb_rc *uwb_rc)
+{
+ /* FIXME! */
+ return -ENOTSUPP;
+}
+
static int uwb_sdio_rc_receive(struct uwb_sdio_device *usdio, struct sdio_bt_a_pkt_info *pkt)
{
if (sdio_bt_a_service_id(pkt->hdr) == SDIO_BT_A_SID_EVT
@@ -61,7 +67,11 @@
goto error_rc_alloc;
}
usdio->uwb_rc = uwb_rc;
- result = uwb_rc_add(uwb_rc, usdio->fdev->os_device, usdio, uwb_sdio_rc_cmd, NULL, NULL);
+
+ uwb_rc->cmd = uwb_sdio_rc_cmd;
+ uwb_rc->reset = uwb_sdio_rc_reset;
+
+ result = uwb_rc_add(uwb_rc, usdio->fdev->os_device, usdio);
if (result < 0)
goto error_rc_add;
return 0;
--- a/drivers/uwb/drp-avail.c 2008-08-14 13:11:16.000000000 +0100
+++ b/drivers/uwb/drp-avail.c 2008-08-14 13:11:16.000000000 +0100
@@ -230,13 +230,13 @@
int result = -EINVAL;
/* Is there enough data to decode the event? */
- if (evt->size < sizeof(*drp_evt)) {
+ if (evt->notif.size < sizeof(*drp_evt)) {
dev_err(dev, "DRP Availability Change: Not enough "
"data to decode event [%zu bytes, %zu "
- "needed]\n", evt->size, sizeof(*drp_evt));
+ "needed]\n", evt->notif.size, sizeof(*drp_evt));
goto error;
}
- drp_evt = container_of(evt->rceb, struct uwb_rc_evt_drp_avail, rceb);
+ drp_evt = container_of(evt->notif.rceb, struct uwb_rc_evt_drp_avail, rceb);
buffer_to_bmp(bmp, drp_evt->bmp, UWB_NUM_MAS/8);
result = 0;
error:
--- a/drivers/uwb/drp.c 2008-08-14 13:11:16.000000000 +0100
+++ b/drivers/uwb/drp.c 2008-08-14 13:11:16.000000000 +0100
@@ -395,14 +395,14 @@
/* Is there enough data to decode the event (and any IEs in
its payload)? */
- if (evt->size < sizeof(*drp_evt)) {
+ if (evt->notif.size < sizeof(*drp_evt)) {
dev_err(dev, "DRP event: Not enough data to decode event "
"[%zu bytes left, %zu needed]\n",
- evt->size, sizeof(*drp_evt));
+ evt->notif.size, sizeof(*drp_evt));
return 0;
}
- bytes_left = evt->size - sizeof(*drp_evt);
- drp_evt = container_of(evt->rceb, struct uwb_rc_evt_drp, rceb);
+ bytes_left = evt->notif.size - sizeof(*drp_evt);
+ drp_evt = container_of(evt->notif.rceb, struct uwb_rc_evt_drp, rceb);
ielength = le16_to_cpu(drp_evt->wIELength);
if (bytes_left != ielength) {
dev_err(dev, "DRP event: Not enough data in payload [%zu"
--- a/drivers/uwb/hwa-rc.c 2008-08-14 13:11:16.000000000 +0100
+++ b/drivers/uwb/hwa-rc.c 2008-08-14 13:11:16.000000000 +0100
@@ -608,6 +608,13 @@
(void *) cmd, cmd_size, 100 /* FIXME: this is totally arbitrary */);
}
+static
+int hwarc_reset(struct uwb_rc *uwb_rc)
+{
+ struct hwarc *hwarc = uwb_rc->priv;
+ return usb_reset_device(hwarc->usb_dev);
+}
+
/**
* Callback for the notification and event endpoint
*
@@ -656,8 +663,8 @@
dev_err(dev, "NEEP: URB max acceptable errors "
"exceeded, resetting device\n");
error:
- usb_dev_reset_delayed(hwarc->usb_dev);
uwb_rc_neh_error(hwarc->uwb_rc, result);
+ uwb_rc_reset_all(hwarc->uwb_rc);
return;
}
@@ -827,12 +834,18 @@
goto error_neep_init;
}
hwarc->uwb_rc = uwb_rc;
- if (id->driver_info & WUSB_QUIRK_WHCI_CMD_EVT)
- result = uwb_rc_add(uwb_rc, dev, hwarc, hwarc_cmd,
- NULL, NULL);
- else
- result = uwb_rc_add(uwb_rc, dev, hwarc, hwarc_cmd,
- hwarc_filter_cmd, hwarc_filter_event);
+
+ uwb_rc->cmd = hwarc_cmd;
+ uwb_rc->reset = hwarc_reset;
+ if (id->driver_info & WUSB_QUIRK_WHCI_CMD_EVT) {
+ uwb_rc->filter_cmd = NULL;
+ uwb_rc->filter_cmd = NULL;
+ } else {
+ uwb_rc->filter_cmd = hwarc_filter_cmd;
+ uwb_rc->filter_event = hwarc_filter_event;
+ }
+
+ result = uwb_rc_add(uwb_rc, dev, hwarc);
if (result < 0)
goto error_rc_add;
result = hwarc_get_version(uwb_rc);
--- a/drivers/uwb/ie-rcv.c 2008-08-14 13:11:16.000000000 +0100
+++ b/drivers/uwb/ie-rcv.c 2008-08-14 13:11:16.000000000 +0100
@@ -42,13 +42,13 @@
size_t iesize;
/* Is there enough data to decode it? */
- if (evt->size < sizeof(*iercv)) {
+ if (evt->notif.size < sizeof(*iercv)) {
dev_err(dev, "IE Received notification: Not enough data to "
"decode (%zu vs %zu bytes needed)\n",
- evt->size, sizeof(*iercv));
+ evt->notif.size, sizeof(*iercv));
goto error;
}
- iercv = container_of(evt->rceb, struct uwb_rc_evt_ie_rcv, rceb);
+ iercv = container_of(evt->notif.rceb, struct uwb_rc_evt_ie_rcv, rceb);
iesize = le16_to_cpu(iercv->wIELength);
dev_info(dev, "IE Received, ElementID=%d\n", *(iercv->IEData));
--- a/drivers/uwb/lc-dev.c 2008-08-14 13:11:16.000000000 +0100
+++ b/drivers/uwb/lc-dev.c 2008-08-14 13:11:16.000000000 +0100
@@ -185,7 +185,6 @@
static ssize_t uwb_dev_IEs_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- ssize_t result;
struct uwb_dev *uwb_dev = to_uwb_dev(dev);
return uwb_bce_print_IEs(uwb_dev, uwb_dev->bce, buf, PAGE_SIZE);
--- a/drivers/uwb/neh.c 2008-08-14 13:11:16.000000000 +0100
+++ b/drivers/uwb/neh.c 2008-08-14 13:11:16.000000000 +0100
@@ -397,9 +397,10 @@
return;
}
uwb_evt->rc = __uwb_rc_get(rc); /* will be put by uwbd's uwbd_event_handle() */
- uwb_evt->rceb = rceb;
- uwb_evt->size = size;
uwb_evt->ts_jiffies = jiffies;
+ uwb_evt->type = UWB_EVT_TYPE_NOTIF;
+ uwb_evt->notif.size = size;
+ uwb_evt->notif.rceb = rceb;
switch (le16_to_cpu(rceb->wEvent)) {
/* Trap some vendor specific events
--- a/drivers/uwb/reset.c 2008-08-14 13:11:16.000000000 +0100
+++ b/drivers/uwb/reset.c 2008-08-14 13:11:16.000000000 +0100
@@ -317,3 +317,34 @@
mutex_unlock(&rc->uwb_dev.mutex);
return result;
}
+
+int uwbd_msg_handle_reset(struct uwb_event *evt)
+{
+ struct uwb_rc *rc = evt->rc;
+
+ return rc->reset(rc);
+}
+
+/**
+ * uwb_rc_reset_all - request a reset of the radio controller and PALs
+ * @rc: the radio controller of the hardware device to be reset.
+ *
+ * The full hardware reset of the radio controller and all the PALs
+ * will be scheduled.
+ */
+void uwb_rc_reset_all(struct uwb_rc *rc)
+{
+ struct uwb_event *evt;
+
+ evt = kzalloc(sizeof(struct uwb_event), GFP_ATOMIC);
+ if (unlikely(evt == NULL))
+ return;
+
+ evt->rc = __uwb_rc_get(rc); /* will be put by uwbd's uwbd_event_handle() */
+ evt->ts_jiffies = jiffies;
+ evt->type = UWB_EVT_TYPE_MSG;
+ evt->message = UWB_EVT_MSG_RESET;
+
+ uwbd_event_queue(evt);
+}
+EXPORT_SYMBOL_GPL(uwb_rc_reset_all);
--- a/drivers/uwb/uwbd.c 2008-08-14 13:11:16.000000000 +0100
+++ b/drivers/uwb/uwbd.c 2008-08-14 13:11:16.000000000 +0100
@@ -163,9 +163,15 @@
size_t uwbd_evt_type_handlers_len =
sizeof(uwbd_evt_type_handlers) / sizeof(uwbd_evt_type_handlers[0]);
+static const struct uwbd_event uwbd_message_handlers[] = {
+ [UWB_EVT_MSG_RESET] = {
+ .handler = uwbd_msg_handle_reset,
+ .name = "reset",
+ },
+};
/**
- * Handle an event passed to the UWB Daemon
+ * Handle an URC event passed to the UWB Daemon
*
* @evt: the event to handle
* @returns: 0 if the event can be kfreed, !0 on the contrary
@@ -182,56 +188,45 @@
* it'll need to take another one.
*/
static
-int uwbd_event_handle(struct uwb_event *evt)
+int uwbd_event_handle_urc(struct uwb_event *evt)
{
int result;
struct uwbd_evt_type_handler *type_table;
uwbd_evt_handler_f handler;
- struct uwb_rc *rc;
u8 type, context;
u16 event;
- rc = evt->rc;
- if (rc == NULL) {
- if (printk_ratelimit())
- printk(KERN_ERR "UWBD: BUG: received event "
- "with NULL rc\n");
- return -EINVAL;
- }
- result = 0;
- if (!rc->ready) /* Not ready to process stuff, drop it */
- goto out_put;
- type = evt->rceb->bEventType;
- event = le16_to_cpu(evt->rceb->wEvent);
- context = evt->rceb->bEventContext;
- result = -EINVAL;
+ type = evt->notif.rceb->bEventType;
+ event = le16_to_cpu(evt->notif.rceb->wEvent);
+ context = evt->notif.rceb->bEventContext;
+
if (type > uwbd_evt_type_handlers_len) {
if (printk_ratelimit())
printk(KERN_ERR "UWBD: event type %u: unknown "
"(too high)\n", type);
- goto out_put;
+ return -EINVAL;
}
type_table = &uwbd_evt_type_handlers[type];
if (type_table->uwbd_events == NULL) {
if (printk_ratelimit())
printk(KERN_ERR "UWBD: event type %u: unknown\n", type);
- goto out_put;
+ return -EINVAL;
}
if (event > type_table->size) {
if (printk_ratelimit())
printk(KERN_ERR "UWBD: event %s[%u]: "
"unknown (too high)\n", type_table->name, event);
- goto out_put;
+ return -EINVAL;
}
handler = type_table->uwbd_events[event].handler;
if (handler == NULL) {
if (printk_ratelimit())
printk(KERN_ERR "UWBD: event %s[%u]: unknown\n",
type_table->name, event);
- goto out_put;
+ return -EINVAL;
}
d_printf(3, NULL, "processing 0x%02x/%04x/%02x, %zu bytes\n",
- type, event, context, evt->size);
+ type, event, context, evt->notif.size);
result = (*handler)(evt);
if (result < 0) {
if (printk_ratelimit())
@@ -239,14 +234,53 @@
"table %s[%u]: handling failed: %d\n",
type, event, context, type_table->name,
event, result);
- result = 0; /* make sure uwbd() frees the evt buffer */
}
-out_put:
- __uwb_rc_put(rc); /* for the __uwb_rc_get() in uwb_rc_notif_cb() */
return result;
}
+static void uwbd_event_handle_message(struct uwb_event *evt)
+{
+ struct uwb_rc *rc;
+ int result;
+
+ rc = evt->rc;
+ if (evt->message < 0 || evt->message >= ARRAY_SIZE(uwbd_message_handlers)) {
+ dev_err(&rc->uwb_dev.dev, "UWBD: invalid message type %d\n", evt->message);
+ return;
+ }
+
+ result = uwbd_message_handlers[evt->message].handler(evt);
+ if (result < 0)
+ dev_err(&rc->uwb_dev.dev, "UWBD: '%s' message failed: %d\n",
+ uwbd_message_handlers[evt->message].name, result);
+}
+
+static void uwbd_event_handle(struct uwb_event *evt)
+{
+ struct uwb_rc *rc;
+ int should_keep;
+
+ rc = evt->rc;
+
+ if (rc->ready) {
+ switch (evt->type) {
+ case UWB_EVT_TYPE_NOTIF:
+ should_keep = uwbd_event_handle_urc(evt);
+ if (should_keep <= 0)
+ kfree(evt->notif.rceb);
+ break;
+ case UWB_EVT_TYPE_MSG:
+ uwbd_event_handle_message(evt);
+ break;
+ default:
+ dev_err(&rc->uwb_dev.dev, "UWBD: invalid event type %d\n", evt->type);
+ break;
+ }
+ }
+
+ __uwb_rc_put(rc); /* for the __uwb_rc_get() in uwb_rc_notif_cb() */
+}
/* The UWB Daemon */
@@ -279,7 +313,7 @@
unsigned long flags;
struct list_head list = LIST_HEAD_INIT(list);
struct uwb_event *evt, *nxt;
- int should_stop = 0, should_keep;
+ int should_stop = 0;
while (1) {
wait_event_interruptible_timeout(
uwbd_wq,
@@ -294,9 +328,7 @@
spin_unlock_irqrestore(&uwbd_event_list_lock, flags);
list_for_each_entry_safe(evt, nxt, &list, list_node) {
list_del(&evt->list_node);
- should_keep = uwbd_event_handle(evt);
- if (!should_keep)
- kfree(evt->rceb);
+ uwbd_event_handle(evt);
kfree(evt);
}
uwb_beca_purge(); /* Purge devices that left */
@@ -325,7 +357,8 @@
spin_lock_irqsave(&uwbd_event_list_lock, flags);
uwbd_pid = 0;
list_for_each_entry_safe(evt, nxt, &uwbd_event_list, list_node) {
- kfree(evt->rceb);
+ if (evt->type == UWB_EVT_TYPE_NOTIF)
+ kfree(evt->notif.rceb);
kfree(evt);
}
spin_unlock_irqrestore(&uwbd_event_list_lock, flags);
@@ -352,7 +385,8 @@
list_add(&evt->list_node, &uwbd_event_list);
wake_up_all(&uwbd_wq);
} else {
- kfree(evt->rceb);
+ if (evt->type == UWB_EVT_TYPE_NOTIF)
+ kfree(evt->notif.rceb);
kfree(evt);
}
spin_unlock_irqrestore(&uwbd_event_list_lock, flags);
--- a/drivers/uwb/uwb-internal.h 2008-08-14 13:11:16.000000000 +0100
+++ b/drivers/uwb/uwb-internal.h 2008-08-14 13:11:16.000000000 +0100
@@ -113,32 +113,57 @@
/*
* UWB Events & management daemon
+ */
+
+/**
+ * enum uwb_event_type - types of UWB management daemon events
*
- * The UWBD daemon receives events following the RCI interface for
- * notifications (with an RCEB header)...basically it acts on the
- * notifications from that the radio controllers pipe to him.
+ * The UWB management daemon (uwbd) can receive two types of events:
+ * UWB_EVT_TYPE_NOTIF - notification from the radio controller.
+ * UWB_EVT_TYPE_MSG - a simple message.
+ */
+enum uwb_event_type {
+ UWB_EVT_TYPE_NOTIF,
+ UWB_EVT_TYPE_MSG,
+};
+
+/**
+ * struct uwb_event_notif - an event for a radio controller notification
+ * @size: Size of the buffer (ie: Guaranteed to contain at least
+ * a full 'struct uwb_rceb')
+ * @rceb: Pointer to a kmalloced() event payload
+ */
+struct uwb_event_notif {
+ size_t size;
+ struct uwb_rceb *rceb;
+};
+
+/**
+ * enum uwb_event_message - an event for a message for asynchronous processing
*
- * FIXME: rename events to notifications (as that's what they
- * are)...however, that'll mess with uwb_notifs.
+ * UWB_EVT_MSG_RESET - reset the radio controller and all PAL hardware.
*/
+enum uwb_event_message {
+ UWB_EVT_MSG_RESET,
+};
/**
* UWB Event
- *
* @rc: Radio controller that emitted the event (referenced)
- * @size: Size of the buffer (ie: Guaranteed to contain at least
- * a full 'struct uwb_rceb')
* @ts_jiffies: Timestamp, when was it received
- * @rceb: Pointer to a kmalloced() event payload
+ * @type: This event's type.
*/
-/* FIXME: rename to uwb_evt for consistency */
struct uwb_event {
struct list_head list_node;
struct uwb_rc *rc;
- size_t size;
unsigned long ts_jiffies;
- struct uwb_rceb *rceb;
+ enum uwb_event_type type;
+ union {
+ struct uwb_event_notif notif;
+ enum uwb_event_message message;
+ };
};
+
extern void uwbd_start(void);
extern void uwbd_stop(void);
extern struct uwb_event *uwb_event_alloc(size_t, gfp_t gfp_mask);
@@ -153,6 +178,8 @@
extern int uwbd_evt_handle_rc_drp(struct uwb_event *);
extern int uwbd_evt_handle_rc_drp_avail(struct uwb_event *);
+int uwbd_msg_handle_reset(struct uwb_event *evt);
+
/*
* Address management
--- a/drivers/usb/wusbcore/wa-hc.c 2008-08-14 13:11:17.000000000 +0100
+++ b/drivers/usb/wusbcore/wa-hc.c 2008-08-14 13:11:17.000000000 +0100
@@ -22,6 +22,7 @@
*
* FIXME: docs
*/
+#include "wusbhc.h"
#include "wa-hc.h"
/**
@@ -77,6 +78,17 @@
}
EXPORT_SYMBOL_GPL(__wa_destroy);
+/**
+ * wa_reset_all - reset the WA device
+ * @wa: the WA to be reset
+ *
+ * For HWAs the radio controller and all other PALs are also reset.
+ */
+void wa_reset_all(struct wahc *wa)
+{
+ /* FIXME: assuming HWA. */
+ wusbhc_reset_all(wa->wusb);
+}
MODULE_AUTHOR("Inaky Perez-Gonzalez <[email protected]>");
MODULE_DESCRIPTION("Wireless USB Wire Adapter core");
--- a/drivers/usb/wusbcore/wa-hc.h 2008-08-14 13:11:17.000000000 +0100
+++ b/drivers/usb/wusbcore/wa-hc.h 2008-08-14 13:11:17.000000000 +0100
@@ -198,6 +198,7 @@
extern int wa_create(struct wahc *wa, struct usb_interface *iface);
extern void __wa_destroy(struct wahc *wa);
+void wa_reset_all(struct wahc *wa);
/* Miscellaneous constants */
--- a/drivers/usb/wusbcore/wa-nep.c 2008-08-14 13:11:17.000000000 +0100
+++ b/drivers/usb/wusbcore/wa-nep.c 2008-08-14 13:11:17.000000000 +0100
@@ -246,7 +246,7 @@
EDC_ERROR_TIMEFRAME)) {
dev_err(dev, "NEP: URB max acceptable errors "
"exceeded, resetting device\n");
- usb_dev_reset_delayed(wa->usb_dev);
+ wa_reset_all(wa);
goto out;
}
dev_err(dev, "NEP: URB error %d\n", urb->status);
@@ -254,7 +254,7 @@
result = wa_nep_arm(wa, GFP_ATOMIC);
if (result < 0) {
dev_err(dev, "NEP: cannot submit URB: %d\n", result);
- usb_dev_reset_delayed(wa->usb_dev);
+ wa_reset_all(wa);
}
out:
return;
--- a/drivers/usb/wusbcore/wa-xfer.c 2008-08-14 13:11:17.000000000 +0100
+++ b/drivers/usb/wusbcore/wa-xfer.c 2008-08-14 13:11:17.000000000 +0100
@@ -562,7 +562,7 @@
EDC_ERROR_TIMEFRAME)){
dev_err(dev, "DTO: URB max acceptable errors "
"exceeded, resetting device\n");
- usb_dev_reset_delayed(wa->usb_dev);
+ wa_reset_all(wa);
}
if (seg->status != WA_SEG_ERROR) {
seg->status = WA_SEG_ERROR;
@@ -637,7 +637,7 @@
EDC_ERROR_TIMEFRAME)){
dev_err(dev, "DTO: URB max acceptable errors "
"exceeded, resetting device\n");
- usb_dev_reset_delayed(wa->usb_dev);
+ wa_reset_all(wa);
}
usb_unlink_urb(seg->dto_urb);
seg->status = WA_SEG_ERROR;
@@ -1399,7 +1399,7 @@
if (edc_inc(&wa->dti_edc, EDC_MAX_ERRORS, EDC_ERROR_TIMEFRAME)) {
dev_err(dev, "DTI: URB max acceptable errors "
"exceeded, resetting device\n");
- usb_dev_reset_delayed(wa->usb_dev);
+ wa_reset_all(wa);
}
if (printk_ratelimit())
dev_err(dev, "xfer %p#%u: can't submit DTI data phase: %d\n",
@@ -1429,7 +1429,7 @@
if (edc_inc(&wa->dti_edc, EDC_MAX_ERRORS, EDC_ERROR_TIMEFRAME)) {
dev_err(dev, "DTI: URB max acceptable errors "
"exceeded, resetting device\n");
- usb_dev_reset_delayed(wa->usb_dev);
+ wa_reset_all(wa);
}
d_fnend(3, dev, "(wa %p xfer %p) = void [bad seg]\n", wa, xfer);
return;
@@ -1500,7 +1500,7 @@
EDC_ERROR_TIMEFRAME)){
dev_err(dev, "DTO: URB max acceptable errors "
"exceeded, resetting device\n");
- usb_dev_reset_delayed(wa->usb_dev);
+ wa_reset_all(wa);
}
seg->status = WA_SEG_ERROR;
seg->result = urb->status;
@@ -1607,7 +1607,7 @@
EDC_ERROR_TIMEFRAME)) {
dev_err(dev, "DTI: URB max acceptable errors "
"exceeded, resetting device\n");
- usb_dev_reset_delayed(wa->usb_dev);
+ wa_reset_all(wa);
goto out;
}
if (printk_ratelimit())
@@ -1619,7 +1619,7 @@
if (result < 0) {
dev_err(dev, "DTI Error: Could not submit DTI URB (%d), "
"resetting\n", result);
- usb_dev_reset_delayed(wa->usb_dev);
+ wa_reset_all(wa);
}
out:
d_fnend(3, dev, "(%p) = void\n", wa);
@@ -1703,7 +1703,7 @@
wa->dti_urb = NULL;
error_dti_urb_alloc:
error:
- usb_dev_reset_delayed(wa->usb_dev);
+ wa_reset_all(wa);
d_fnend(4, dev, "(%p, %p) = void\n", wa, notif_hdr);
return;
}
--- a/drivers/usb/wusbcore/wusbhc.c 2008-08-14 13:11:17.000000000 +0100
+++ b/drivers/usb/wusbcore/wusbhc.c 2008-08-14 13:11:17.000000000 +0100
@@ -319,12 +319,21 @@
}
EXPORT_SYMBOL_GPL(wusb_cluster_id_put);
-/*
+/**
* wusbhc_giveback_urb - return an URB to the USB core
+ * @wusbhc: the host controller the URB is from.
+ * @urb: the URB.
+ * @status: the URB's status.
*
- * [WUSB] sections 4.13 and 7.5.1 specifies the stop retrasmittion
- * condition for the WCONNECTACK_IE is that the host has observed the
- * associated device responding to control transfer.
+ * Return an URB to the USB core doing some additional WUSB specific
+ * processing.
+ *
+ * - After a successful transfer, update the trust timeout timestamp
+ * for the WUSB device.
+ *
+ * - [WUSB] sections 4.13 and 7.5.1 specifies the stop retrasmittion
+ * condition for the WCONNECTACK_IE is that the host has observed
+ * the associated device responding to a control transfer.
*/
void wusbhc_giveback_urb(struct wusbhc *wusbhc, struct urb *urb, int status)
{
@@ -333,6 +342,8 @@
if (status == 0) {
wusb_dev->entry_ts = jiffies;
+ /* wusbhc_devconnect_acked() can't be called from from
+ atomic context so defer it to a work queue. */
if (!list_empty(&wusb_dev->cack_node))
queue_work(wusbd, &wusb_dev->devconnect_acked_work);
}
@@ -341,6 +352,19 @@
}
EXPORT_SYMBOL_GPL(wusbhc_giveback_urb);
+/**
+ * wusbhc_reset_all - reset the HC hardware
+ * @wusbhc: the host controller to reset.
+ *
+ * Request a full hardware reset of the chip. This will also reset
+ * the radio controller and any other PALs.
+ */
+void wusbhc_reset_all(struct wusbhc *wusbhc)
+{
+ uwb_rc_reset_all(wusbhc->uwb_rc);
+}
+EXPORT_SYMBOL_GPL(wusbhc_reset_all);
+
static struct notifier_block wusb_usb_notifier = {
.notifier_call = wusb_usb_ncb,
.priority = INT_MAX /* Need to be called first of all */
--- a/drivers/usb/wusbcore/wusbhc.h 2008-08-14 13:11:17.000000000 +0100
+++ b/drivers/usb/wusbcore/wusbhc.h 2008-08-14 13:11:17.000000000 +0100
@@ -339,6 +339,7 @@
extern void wusbhc_sec_destroy(struct wusbhc *);
extern void wusbhc_giveback_urb(struct wusbhc *wusbhc, struct urb *urb,
int status);
+void wusbhc_reset_all(struct wusbhc *wusbhc);
int wusbhc_pal_register(struct wusbhc *wusbhc);
void wusbhc_pal_unregister(struct wusbhc *wusbhc);
--- a/drivers/uwb/i1480/i1480u-wlp/lc.c 2008-08-14 13:11:17.000000000 +0100
+++ b/drivers/uwb/i1480/i1480u-wlp/lc.c 2008-08-14 13:11:18.000000000 +0100
@@ -175,7 +175,7 @@
return;
error_reset:
- usb_dev_reset_delayed(i1480u->usb_dev);
+ wlp_reset_all(&i1480-wlp);
error:
netif_stop_queue(i1480u->net_dev);
return;
--- a/drivers/uwb/i1480/i1480u-wlp/rx.c 2008-08-14 13:11:18.000000000 +0100
+++ b/drivers/uwb/i1480/i1480u-wlp/rx.c 2008-08-14 13:11:18.000000000 +0100
@@ -465,7 +465,7 @@
dev_err(dev, "RX: max acceptable errors exceeded,"
" resetting device.\n");
i1480u_rx_unlink_urbs(i1480u);
- usb_dev_reset_delayed(i1480u->usb_dev);
+ wlp_reset_all(&i1480u->wlp);
goto error;
}
do_parse_buffer = 0;
--- a/drivers/uwb/i1480/i1480u-wlp/tx.c 2008-08-14 13:11:18.000000000 +0100
+++ b/drivers/uwb/i1480/i1480u-wlp/tx.c 2008-08-14 13:11:18.000000000 +0100
@@ -140,7 +140,7 @@
"Reset device.\n");
netif_stop_queue(net_dev);
i1480u_tx_unlink_urbs(i1480u);
- usb_dev_reset_delayed(i1480u->usb_dev);
+ wlp_reset_all(&i1480u->wlp);
}
break;
}
@@ -600,7 +600,7 @@
{
struct i1480u *i1480u = netdev_priv(net_dev);
- usb_dev_reset_delayed(i1480u->usb_dev);
+ wlp_reset_all(&i1480u->wlp);
}
--- a/drivers/uwb/wlp/wlp-lc.c 2008-08-14 13:11:18.000000000 +0100
+++ b/drivers/uwb/wlp/wlp-lc.c 2008-08-14 13:11:18.000000000 +0100
@@ -570,3 +570,16 @@
d_fnend(6, NULL, "wlp %p\n", wlp);
}
EXPORT_SYMBOL_GPL(wlp_remove);
+
+/**
+ * wlp_reset_all - reset the WLP hardware
+ * @wlp: the WLP device to reset.
+ *
+ * This schedules a full hardware reset of the WLP device. The radio
+ * controller and any other PALs will also be reset.
+ */
+void wlp_reset_all(struct wlp *wlp)
+{
+ uwb_rc_reset_all(wlp->rc);
+}
+EXPORT_SYMBOL_GPL(wlp_reset_all);
--- a/uwb-uwb_rc_reset_all.patch 1970-01-01 01:00:00.000000000 +0100
+++ b/uwb-uwb_rc_reset_all.patch 2008-08-14 13:11:18.000000000 +0100
@@ -0,0 +1,43 @@
+---
+ include/linux/uwb.h | 11 ++++-------
+ 1 file changed, 4 insertions(+), 7 deletions(-)
+
+Index: linux-2.6-working/include/linux/uwb.h
+===================================================================
+--- linux-2.6-working.orig/include/linux/uwb.h 2008-08-07 13:06:13.000000000 +0100
++++ linux-2.6-working/include/linux/uwb.h 2008-08-07 13:06:45.000000000 +0100
+@@ -291,6 +291,7 @@
+ * @priv: Backend implementation; rw with uwb_dev.dev.sem taken.
+ * @cmd: Backend implementation to execute commands; rw and call
+ * only with uwb_dev.dev.sem taken.
++ * @reset: Hardware reset of radio controller and any PAL controllers.
+ * @filter: Backend implementation to manipulate data to and from device
+ * to be compliant to specification assumed by driver (WHCI
+ * 0.95).
+@@ -325,6 +326,7 @@
+
+ void *priv;
+ int (*cmd)(struct uwb_rc *, const struct uwb_rccb *, size_t);
++ int (*reset)(struct uwb_rc *);
+ int (*filter_cmd)(struct uwb_rc *, struct uwb_rccb **, size_t *);
+ int (*filter_event)(struct uwb_rc *, struct uwb_rceb **, const size_t,
+ size_t *, size_t *);
+@@ -507,16 +509,11 @@
+ * Radio Controllers.
+ */
+ extern void uwb_rc_init(struct uwb_rc *);
+-extern int uwb_rc_add(struct uwb_rc *, struct device *dev, void *rc_priv,
+- int (*cmd)(struct uwb_rc *, const struct uwb_rccb *,
+- size_t),
+- int (*filter_cmd)(struct uwb_rc *, struct uwb_rccb **,
+- size_t *),
+- int (*filter_event)(struct uwb_rc *, struct uwb_rceb **,
+- const size_t, size_t *, size_t *));
++extern int uwb_rc_add(struct uwb_rc *, struct device *dev, void *rc_priv);
+ extern void uwb_rc_rm(struct uwb_rc *);
+ extern void uwb_rc_neh_grok(struct uwb_rc *, void *, size_t);
+ extern void uwb_rc_neh_error(struct uwb_rc *, int);
++void uwb_rc_reset_all(struct uwb_rc *rc);
+
+ /**
+ * uwb_rsv_is_owner - is the owner of this reservation the RC?
--- a/uwb-umc_controller_reset.patch 1970-01-01 01:00:00.000000000 +0100
+++ b/uwb-umc_controller_reset.patch 2008-08-14 13:11:18.000000000 +0100
@@ -0,0 +1,12 @@
+Index: linux-2.6-working/include/linux/uwb/umc.h
+===================================================================
+--- linux-2.6-working.orig/include/linux/uwb/umc.h 2008-08-06 14:04:29.000000000 +0100
++++ linux-2.6-working/include/linux/uwb/umc.h 2008-08-06 19:19:01.000000000 +0100
+@@ -189,6 +189,6 @@
+ return dev_get_drvdata(&umc_dev->dev);
+ }
+
+-int umc_match_pci_id(struct umc_driver *umc_drv, struct umc_dev *umc);
++int umc_controller_reset(struct umc_dev *umc);
+
+ #endif /* #ifndef _LINUX_UWB_UMC_H_ */
--------------040704060100070904000600--
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html