summaryrefslogtreecommitdiffstats
path: root/drivers/usb/host
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/host')
-rw-r--r--drivers/usb/host/hwa-hc.c104
-rw-r--r--drivers/usb/host/whci/hcd.c3
-rw-r--r--drivers/usb/host/whci/hw.c8
-rw-r--r--drivers/usb/host/whci/int.c1
-rw-r--r--drivers/usb/host/whci/whcd.h2
-rw-r--r--drivers/usb/host/whci/whci-hc.h2
-rw-r--r--drivers/usb/host/whci/wusb.c16
7 files changed, 68 insertions, 68 deletions
diff --git a/drivers/usb/host/hwa-hc.c b/drivers/usb/host/hwa-hc.c
index 64be4d88df11..2a4d36fa70b0 100644
--- a/drivers/usb/host/hwa-hc.c
+++ b/drivers/usb/host/hwa-hc.c
@@ -54,7 +54,6 @@
* DWA).
*/
#include <linux/kernel.h>
-#include <linux/version.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/workqueue.h>
@@ -171,11 +170,6 @@ static int hwahc_op_start(struct usb_hcd *usb_hcd)
if (result < 0)
goto error_set_cluster_id;
- result = wa_nep_arm(&hwahc->wa, GFP_KERNEL);
- if (result < 0) {
- dev_err(dev, "cannot listen to notifications: %d\n", result);
- goto error_stop;
- }
usb_hcd->uses_new_polling = 1;
usb_hcd->poll_rh = 1;
usb_hcd->state = HC_STATE_RUNNING;
@@ -185,8 +179,6 @@ out:
d_fnend(4, dev, "(hwahc %p) = %d\n", hwahc, result);
return result;
-error_stop:
- __wa_stop(&hwahc->wa);
error_set_cluster_id:
wusb_cluster_id_put(wusbhc->cluster_id);
error_cluster_id_get:
@@ -194,39 +186,6 @@ error_cluster_id_get:
}
-/*
- * FIXME: break this function up
- */
-static int __hwahc_op_wusbhc_start(struct wusbhc *wusbhc)
-{
- int result;
- struct hwahc *hwahc = container_of(wusbhc, struct hwahc, wusbhc);
- struct device *dev = &hwahc->wa.usb_iface->dev;
-
- /* Set up a Host Info WUSB Information Element */
- d_fnstart(4, dev, "(hwahc %p)\n", hwahc);
- result = -ENOSPC;
-
- result = __wa_set_feature(&hwahc->wa, WA_ENABLE);
- if (result < 0) {
- dev_err(dev, "error commanding HC to start: %d\n", result);
- goto error_stop;
- }
- result = __wa_wait_status(&hwahc->wa, WA_ENABLE, WA_ENABLE);
- if (result < 0) {
- dev_err(dev, "error waiting for HC to start: %d\n", result);
- goto error_stop;
- }
- result = 0;
-out:
- d_fnend(4, dev, "(hwahc %p) = %d\n", hwahc, result);
- return result;
-
-error_stop:
- result = __wa_clear_feature(&hwahc->wa, WA_ENABLE);
- goto out;
-}
-
static int hwahc_op_suspend(struct usb_hcd *usb_hcd, pm_message_t msg)
{
struct wusbhc *wusbhc = usb_hcd_to_wusbhc(usb_hcd);
@@ -246,18 +205,6 @@ static int hwahc_op_resume(struct usb_hcd *usb_hcd)
return -ENOSYS;
}
-static void __hwahc_op_wusbhc_stop(struct wusbhc *wusbhc)
-{
- int result;
- struct hwahc *hwahc = container_of(wusbhc, struct hwahc, wusbhc);
- struct device *dev = &hwahc->wa.usb_iface->dev;
-
- d_fnstart(4, dev, "(hwahc %p)\n", hwahc);
- /* Nothing for now */
- d_fnend(4, dev, "(hwahc %p) = %d\n", hwahc, result);
- return;
-}
-
/*
* No need to abort pipes, as when this is called, all the children
* has been disconnected and that has done it [through
@@ -274,9 +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);
- wa_nep_disarm(&hwahc->wa);
- result = __wa_stop(&hwahc->wa);
wusb_cluster_id_put(wusbhc->cluster_id);
mutex_unlock(&wusbhc->mutex);
d_fnend(4, dev, "(hwahc %p) = %d\n", hwahc, result);
@@ -325,6 +269,54 @@ static void hwahc_op_endpoint_disable(struct usb_hcd *usb_hcd,
rpipe_ep_disable(&hwahc->wa, ep);
}
+static int __hwahc_op_wusbhc_start(struct wusbhc *wusbhc)
+{
+ int result;
+ struct hwahc *hwahc = container_of(wusbhc, struct hwahc, wusbhc);
+ struct device *dev = &hwahc->wa.usb_iface->dev;
+
+ result = __wa_set_feature(&hwahc->wa, WA_ENABLE);
+ if (result < 0) {
+ dev_err(dev, "error commanding HC to start: %d\n", result);
+ goto error_stop;
+ }
+ result = __wa_wait_status(&hwahc->wa, WA_ENABLE, WA_ENABLE);
+ if (result < 0) {
+ dev_err(dev, "error waiting for HC to start: %d\n", result);
+ goto error_stop;
+ }
+ result = wa_nep_arm(&hwahc->wa, GFP_KERNEL);
+ if (result < 0) {
+ dev_err(dev, "cannot listen to notifications: %d\n", result);
+ goto error_stop;
+ }
+ return result;
+
+error_stop:
+ __wa_clear_feature(&hwahc->wa, WA_ENABLE);
+ return result;
+}
+
+static void __hwahc_op_wusbhc_stop(struct wusbhc *wusbhc, int delay)
+{
+ struct hwahc *hwahc = container_of(wusbhc, struct hwahc, wusbhc);
+ struct wahc *wa = &hwahc->wa;
+ u8 iface_no = wa->usb_iface->cur_altsetting->desc.bInterfaceNumber;
+ int ret;
+
+ ret = usb_control_msg(wa->usb_dev, usb_sndctrlpipe(wa->usb_dev, 0),
+ WUSB_REQ_CHAN_STOP,
+ USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+ delay * 1000,
+ iface_no,
+ NULL, 0, 1000 /* FIXME: arbitrary */);
+ if (ret == 0)
+ msleep(delay);
+
+ wa_nep_disarm(&hwahc->wa);
+ __wa_stop(&hwahc->wa);
+}
+
/*
* Set the UWB MAS allocation for the WUSB cluster
*
diff --git a/drivers/usb/host/whci/hcd.c b/drivers/usb/host/whci/hcd.c
index ef3ad4dca945..f599f89d3be1 100644
--- a/drivers/usb/host/whci/hcd.c
+++ b/drivers/usb/host/whci/hcd.c
@@ -15,7 +15,6 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/uwb/umc.h>
@@ -92,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);
diff --git a/drivers/usb/host/whci/hw.c b/drivers/usb/host/whci/hw.c
index ac86e59c1225..d498e7203217 100644
--- a/drivers/usb/host/whci/hw.c
+++ b/drivers/usb/host/whci/hw.c
@@ -50,6 +50,7 @@ int whc_do_gencmd(struct whc *whc, u32 cmd, u32 params, void *addr, size_t len)
unsigned long flags;
dma_addr_t dma_addr;
int t;
+ int ret = 0;
mutex_lock(&whc->mutex);
@@ -61,7 +62,8 @@ int whc_do_gencmd(struct whc *whc, u32 cmd, u32 params, void *addr, size_t len)
dev_err(&whc->umc->dev, "generic command timeout (%04x/%04x)\n",
le_readl(whc->base + WUSBGENCMDSTS),
le_readl(whc->base + WUSBGENCMDPARAMS));
- return -ETIMEDOUT;
+ ret = -ETIMEDOUT;
+ goto out;
}
if (addr) {
@@ -80,8 +82,8 @@ int whc_do_gencmd(struct whc *whc, u32 cmd, u32 params, void *addr, size_t len)
whc->base + WUSBGENCMDSTS);
spin_unlock_irqrestore(&whc->lock, flags);
-
+out:
mutex_unlock(&whc->mutex);
- return 0;
+ return ret;
}
diff --git a/drivers/usb/host/whci/int.c b/drivers/usb/host/whci/int.c
index fce01174aa9b..6aae70028101 100644
--- a/drivers/usb/host/whci/int.c
+++ b/drivers/usb/host/whci/int.c
@@ -15,7 +15,6 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/uwb/umc.h>
diff --git a/drivers/usb/host/whci/whcd.h b/drivers/usb/host/whci/whcd.h
index 1d2a53bd39fd..1bbb8cb6bf80 100644
--- a/drivers/usb/host/whci/whcd.h
+++ b/drivers/usb/host/whci/whcd.h
@@ -136,7 +136,7 @@ int whc_do_gencmd(struct whc *whc, u32 cmd, u32 params, void *addr, size_t len);
/* wusb.c */
int whc_wusbhc_start(struct wusbhc *wusbhc);
-void whc_wusbhc_stop(struct wusbhc *wusbhc);
+void whc_wusbhc_stop(struct wusbhc *wusbhc, int delay);
int whc_mmcie_add(struct wusbhc *wusbhc, u8 interval, u8 repeat_cnt,
u8 handle, struct wuie_hdr *wuie);
int whc_mmcie_rm(struct wusbhc *wusbhc, u8 handle);
diff --git a/drivers/usb/host/whci/whci-hc.h b/drivers/usb/host/whci/whci-hc.h
index bff1eb7a35cf..51df7e313b38 100644
--- a/drivers/usb/host/whci/whci-hc.h
+++ b/drivers/usb/host/whci/whci-hc.h
@@ -410,6 +410,8 @@ struct dn_buf_entry {
# define WUSBDNTSCTRL_SLOTS(s) ((s) << 0)
#define WUSBTIME 0x68
+# define WUSBTIME_CHANNEL_TIME_MASK 0x00ffffff
+
#define WUSBBPST 0x6c
#define WUSBDIBUPDATED 0x70
diff --git a/drivers/usb/host/whci/wusb.c b/drivers/usb/host/whci/wusb.c
index 66e4ddcd961d..540021a0971e 100644
--- a/drivers/usb/host/whci/wusb.c
+++ b/drivers/usb/host/whci/wusb.c
@@ -15,7 +15,6 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/uwb/umc.h>
@@ -64,8 +63,9 @@ static int whc_update_di(struct whc *whc, int idx)
}
/*
- * WHCI starts and stops MMCs based on there being a valid GTK so
- * these need only start/stop the asynchronous and periodic schedules.
+ * WHCI starts MMCs based on there being a valid GTK so these need
+ * only start/stop the asynchronous and periodic schedules and send a
+ * channel stop command.
*/
int whc_wusbhc_start(struct wusbhc *wusbhc)
@@ -78,12 +78,20 @@ int whc_wusbhc_start(struct wusbhc *wusbhc)
return 0;
}
-void whc_wusbhc_stop(struct wusbhc *wusbhc)
+void whc_wusbhc_stop(struct wusbhc *wusbhc, int delay)
{
struct whc *whc = wusbhc_to_whc(wusbhc);
+ u32 stop_time, now_time;
+ int ret;
pzl_stop(whc);
asl_stop(whc);
+
+ now_time = le_readl(whc->base + WUSBTIME) & WUSBTIME_CHANNEL_TIME_MASK;
+ stop_time = (now_time + ((delay * 8) << 7)) & 0x00ffffff;
+ ret = whc_do_gencmd(whc, WUSBGENCMDSTS_CHAN_STOP, stop_time, NULL, 0);
+ if (ret == 0)
+ msleep(delay);
}
int whc_mmcie_add(struct wusbhc *wusbhc, u8 interval, u8 repeat_cnt,