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