summaryrefslogtreecommitdiff
path: root/drivers/usb/wusbcore
diff options
context:
space:
mode:
authorDavid Vrabel <david.vrabel@csr.com>2008-11-25 17:23:40 +0300
committerDavid Vrabel <david.vrabel@csr.com>2008-11-25 17:23:40 +0300
commit56968d0c1a920eb165c06318f5c458724e1df0af (patch)
tree9516fdc8ef8bc67bf6a51a1e4940d3ae59008dfa /drivers/usb/wusbcore
parent65d76f368295973a35d195c9b13053502a67b6bc (diff)
downloadlinux-56968d0c1a920eb165c06318f5c458724e1df0af.tar.xz
wusb: whci-hcd shouldn't do ASL/PZL updates while channel is inactive
ASL/PZL updates while the WUSB channel is inactive (i.e., the PZL and ASL are stopped) may not complete. This causes hangs when removing the whci-hcd module if a device is still connected (removing the device does an endpoint_disable which results in an ASL update to remove the qset). If the WUSB channel is inactive the update can simply be skipped as the WHC doesn't care about the state of the ASL/PZL. Signed-off-by: David Vrabel <david.vrabel@csr.com>
Diffstat (limited to 'drivers/usb/wusbcore')
-rw-r--r--drivers/usb/wusbcore/devconnect.c24
-rw-r--r--drivers/usb/wusbcore/mmc.c37
2 files changed, 36 insertions, 25 deletions
diff --git a/drivers/usb/wusbcore/devconnect.c b/drivers/usb/wusbcore/devconnect.c
index 08a1ec903867..26cbc89ea281 100644
--- a/drivers/usb/wusbcore/devconnect.c
+++ b/drivers/usb/wusbcore/devconnect.c
@@ -484,21 +484,15 @@ static void __wusbhc_keep_alive(struct wusbhc *wusbhc)
*/
static void wusbhc_keep_alive_run(struct work_struct *ws)
{
- struct delayed_work *dw =
- container_of(ws, struct delayed_work, work);
- struct wusbhc *wusbhc =
- container_of(dw, struct wusbhc, keep_alive_timer);
-
- d_fnstart(5, wusbhc->dev, "(wusbhc %p)\n", wusbhc);
- if (wusbhc->active) {
- mutex_lock(&wusbhc->mutex);
- __wusbhc_keep_alive(wusbhc);
- mutex_unlock(&wusbhc->mutex);
- queue_delayed_work(wusbd, &wusbhc->keep_alive_timer,
- (wusbhc->trust_timeout * CONFIG_HZ)/1000/2);
- }
- d_fnend(5, wusbhc->dev, "(wusbhc %p) = void\n", wusbhc);
- return;
+ struct delayed_work *dw = container_of(ws, struct delayed_work, work);
+ struct wusbhc *wusbhc = container_of(dw, struct wusbhc, keep_alive_timer);
+
+ mutex_lock(&wusbhc->mutex);
+ __wusbhc_keep_alive(wusbhc);
+ mutex_unlock(&wusbhc->mutex);
+
+ queue_delayed_work(wusbd, &wusbhc->keep_alive_timer,
+ msecs_to_jiffies(wusbhc->trust_timeout / 2));
}
/*
diff --git a/drivers/usb/wusbcore/mmc.c b/drivers/usb/wusbcore/mmc.c
index 5463ecebafdf..3b52161e6e9c 100644
--- a/drivers/usb/wusbcore/mmc.c
+++ b/drivers/usb/wusbcore/mmc.c
@@ -159,6 +159,27 @@ found:
}
EXPORT_SYMBOL_GPL(wusbhc_mmcie_rm);
+static int wusbhc_mmc_start(struct wusbhc *wusbhc)
+{
+ int ret;
+
+ mutex_lock(&wusbhc->mutex);
+ ret = wusbhc->start(wusbhc);
+ if (ret >= 0)
+ wusbhc->active = 1;
+ mutex_unlock(&wusbhc->mutex);
+
+ return ret;
+}
+
+static void wusbhc_mmc_stop(struct wusbhc *wusbhc)
+{
+ mutex_lock(&wusbhc->mutex);
+ wusbhc->active = 0;
+ wusbhc->stop(wusbhc, WUSB_CHANNEL_STOP_DELAY_MS);
+ mutex_unlock(&wusbhc->mutex);
+}
+
/*
* wusbhc_start - start transmitting MMCs and accepting connections
* @wusbhc: the HC to start
@@ -198,12 +219,12 @@ int wusbhc_start(struct wusbhc *wusbhc)
dev_err(dev, "Cannot set DNTS parameters: %d\n", result);
goto error_set_num_dnts;
}
- result = wusbhc->start(wusbhc);
+ result = wusbhc_mmc_start(wusbhc);
if (result < 0) {
dev_err(dev, "error starting wusbch: %d\n", result);
goto error_wusbhc_start;
}
- wusbhc->active = 1;
+
return 0;
error_wusbhc_start:
@@ -225,15 +246,11 @@ error_rsv_establish:
*/
void wusbhc_stop(struct wusbhc *wusbhc)
{
- if (wusbhc->active) {
- wusbhc->active = 0;
- wusbhc->stop(wusbhc, WUSB_CHANNEL_STOP_DELAY_MS);
- wusbhc_sec_stop(wusbhc);
- wusbhc_devconnect_stop(wusbhc);
- wusbhc_rsv_terminate(wusbhc);
- }
+ wusbhc_mmc_stop(wusbhc);
+ wusbhc_sec_stop(wusbhc);
+ wusbhc_devconnect_stop(wusbhc);
+ wusbhc_rsv_terminate(wusbhc);
}
-EXPORT_SYMBOL_GPL(wusbhc_stop);
/*
* Set/reset/update a new CHID