summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnand Gadiyar <gadiyar@ti.com>2010-11-18 18:54:17 +0530
committerFelipe Balbi <balbi@ti.com>2010-11-22 12:55:02 +0200
commit07a8cdd2bb17a4da68136d963b8bc71959bd31a5 (patch)
treefbc64d9842b38848ee7b4d410bab626ff2abd893
parentbb324b08165d5656d221af013ed9994a54e455be (diff)
downloadlinux-07a8cdd2bb17a4da68136d963b8bc71959bd31a5.tar.bz2
usb: musb: do not use dma for control transfers
The Inventra DMA engine used with the MUSB controller in many SoCs cannot use DMA for control transfers on EP0, but can use DMA for all other transfers. The USB core maps urbs for DMA if hcd->self.uses_dma is true. (hcd->self.uses_dma is true for MUSB as well). Split the uses_dma flag into two - one that says if the controller needs to use PIO for control transfers, and another which says if the controller uses DMA (for all other transfers). Also, populate this flag for all MUSB by default. (Tested on OMAP3 and OMAP4 boards, with EHCI and MUSB HCDs simultaneously in use). Signed-off-by: Maulik Mankad <x0082077@ti.com> Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com> Signed-off-by: Anand Gadiyar <gadiyar@ti.com> Cc: Oliver Neukum <oliver@neukum.org> Cc: Alan Stern <stern@rowland.harvard.edu> Cc: Praveena NADAHALLY <praveen.nadahally@stericsson.com> Cc: Ajay Kumar Gupta <ajay.gupta@ti.com> Signed-off-by: Felipe Balbi <balbi@ti.com>
-rw-r--r--drivers/usb/core/hcd.c2
-rw-r--r--drivers/usb/musb/musb_core.c3
-rw-r--r--drivers/usb/musb/musb_gadget.c4
-rw-r--r--include/linux/usb.h4
4 files changed, 13 insertions, 0 deletions
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 61800f77dac8..ced846ac4141 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -1330,6 +1330,8 @@ static int map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
*/
if (usb_endpoint_xfer_control(&urb->ep->desc)) {
+ if (hcd->self.uses_pio_for_control)
+ return ret;
if (hcd->self.uses_dma) {
urb->setup_dma = dma_map_single(
hcd->self.controller,
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index e6669fc3b804..99beebce8550 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -2116,12 +2116,15 @@ bad_config:
* Otherwise, wait till the gadget driver hooks up.
*/
if (!is_otg_enabled(musb) && is_host_enabled(musb)) {
+ struct usb_hcd *hcd = musb_to_hcd(musb);
+
MUSB_HST_MODE(musb);
musb->xceiv->default_a = 1;
musb->xceiv->state = OTG_STATE_A_IDLE;
status = usb_add_hcd(musb_to_hcd(musb), -1, 0);
+ hcd->self.uses_pio_for_control = 1;
DBG(1, "%s mode, status %d, devctl %02x %c\n",
"HOST", status,
musb_readb(musb->mregs, MUSB_DEVCTL),
diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c
index c8de0e123f2c..9d6ade82b9f2 100644
--- a/drivers/usb/musb/musb_gadget.c
+++ b/drivers/usb/musb/musb_gadget.c
@@ -1833,6 +1833,8 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
spin_unlock_irqrestore(&musb->lock, flags);
if (is_otg_enabled(musb)) {
+ struct usb_hcd *hcd = musb_to_hcd(musb);
+
DBG(3, "OTG startup...\n");
/* REVISIT: funcall to other code, which also
@@ -1847,6 +1849,8 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
musb->gadget_driver = NULL;
musb->g.dev.driver = NULL;
spin_unlock_irqrestore(&musb->lock, flags);
+ } else {
+ hcd->self.uses_pio_for_control = 1;
}
}
}
diff --git a/include/linux/usb.h b/include/linux/usb.h
index 24300d8a1bc1..a28eb2592577 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -313,6 +313,10 @@ struct usb_bus {
int busnum; /* Bus number (in order of reg) */
const char *bus_name; /* stable id (PCI slot_name etc) */
u8 uses_dma; /* Does the host controller use DMA? */
+ u8 uses_pio_for_control; /*
+ * Does the host controller use PIO
+ * for control transfers?
+ */
u8 otg_port; /* 0, or number of OTG/HNP port */
unsigned is_b_host:1; /* true during some HNP roleswitches */
unsigned b_hnp_enable:1; /* OTG: did A-Host enable HNP? */