From 7a3783efffc7bc2e702d774e47fad5b8e37e9ad1 Mon Sep 17 00:00:00 2001 From: Paul Zimmerman Date: Wed, 17 Nov 2010 16:26:50 -0800 Subject: xhci: Fix reset-device and configure-endpoint commands We have been having problems with the USB-IF Gold Tree tests when plugging and unplugging devices from the tree. I have seen that the reset-device and configure-endpoint commands, which are invoked from xhci_discover_or_reset_device() and xhci_configure_endpoint(), will sometimes time out. After much debugging, I determined that the commands themselves do not actually time out, but rather their completion events do not get delivered to the right place. This happens when the command ring has just wrapped around, and it's enqueue pointer is left pointing to the link TRB. xhci_discover_or_reset_device() and xhci_configure_endpoint() use the enqueue pointer directly as their command TRB pointer, without checking whether it's pointing to the link TRB. When the completion event arrives, if the command TRB is pointing to the link TRB, the check against the command ring dequeue pointer in handle_cmd_in_cmd_wait_list() fails, so the completion inside the command does not get signaled. The patch below fixes the timeout problem for me. This should be queued for the 2.6.35 and 2.6.36 stable trees. Signed-off-by: Paul Zimmerman Signed-off-by: Sarah Sharp Cc: stable@kernel.org --- drivers/usb/host/xhci.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 06fca0835b52..45e4a3108cc3 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -1549,6 +1549,15 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci, cmd_completion = command->completion; cmd_status = &command->status; command->command_trb = xhci->cmd_ring->enqueue; + + /* Enqueue pointer can be left pointing to the link TRB, + * we must handle that + */ + if ((command->command_trb->link.control & TRB_TYPE_BITMASK) + == TRB_TYPE(TRB_LINK)) + command->command_trb = + xhci->cmd_ring->enq_seg->next->trbs; + list_add_tail(&command->cmd_list, &virt_dev->cmd_list); } else { in_ctx = virt_dev->in_ctx; @@ -2272,6 +2281,15 @@ int xhci_discover_or_reset_device(struct usb_hcd *hcd, struct usb_device *udev) /* Attempt to submit the Reset Device command to the command ring */ spin_lock_irqsave(&xhci->lock, flags); reset_device_cmd->command_trb = xhci->cmd_ring->enqueue; + + /* Enqueue pointer can be left pointing to the link TRB, + * we must handle that + */ + if ((reset_device_cmd->command_trb->link.control & TRB_TYPE_BITMASK) + == TRB_TYPE(TRB_LINK)) + reset_device_cmd->command_trb = + xhci->cmd_ring->enq_seg->next->trbs; + list_add_tail(&reset_device_cmd->cmd_list, &virt_dev->cmd_list); ret = xhci_queue_reset_device(xhci, slot_id); if (ret) { -- cgit v1.2.3-55-g7522 From da6699ce4a889c3795624ccdcfe7181cc89f18e8 Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Tue, 26 Oct 2010 16:47:13 -0700 Subject: xhci: Setup array of USB 2.0 and USB 3.0 ports. An xHCI host controller contains USB 2.0 and USB 3.0 ports, which can occur in any order in the PORTSC registers. We cannot read the port speed bits in the PORTSC registers at init time to determine the port speed, since those bits are only valid when a USB device is plugged into the port. Instead, we read the "Supported Protocol Capability" registers in the xHC Extended Capabilities space. Those describe the protocol, port offset in the PORTSC registers, and port count. We use those registers to create two arrays of pointers to the PORTSC registers, one for USB 3.0 ports, and another for USB 2.0 ports. A third array keeps track of the port protocol major revision, and is indexed with the internal xHCI port number. This commit is a bit big, but it should be queued for stable because the "Don't let the USB core disable SuperSpeed ports" patch depends on it. There is no other way to determine which ports are SuperSpeed ports without this patch. Signed-off-by: Sarah Sharp Tested-by: Don Zickus Cc: stable@kernel.org --- drivers/usb/host/xhci-mem.c | 164 ++++++++++++++++++++++++++++++++++++++++++++ drivers/usb/host/xhci.h | 26 +++++++ 2 files changed, 190 insertions(+) diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index d178761c3981..0fae58ef8afe 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -1443,6 +1443,13 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci) xhci->dcbaa = NULL; scratchpad_free(xhci); + + xhci->num_usb2_ports = 0; + xhci->num_usb3_ports = 0; + kfree(xhci->usb2_ports); + kfree(xhci->usb3_ports); + kfree(xhci->port_array); + xhci->page_size = 0; xhci->page_shift = 0; xhci->bus_suspended = 0; @@ -1627,6 +1634,161 @@ static void xhci_set_hc_event_deq(struct xhci_hcd *xhci) &xhci->ir_set->erst_dequeue); } +static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports, + u32 __iomem *addr, u8 major_revision) +{ + u32 temp, port_offset, port_count; + int i; + + if (major_revision > 0x03) { + xhci_warn(xhci, "Ignoring unknown port speed, " + "Ext Cap %p, revision = 0x%x\n", + addr, major_revision); + /* Ignoring port protocol we can't understand. FIXME */ + return; + } + + /* Port offset and count in the third dword, see section 7.2 */ + temp = xhci_readl(xhci, addr + 2); + port_offset = XHCI_EXT_PORT_OFF(temp); + port_count = XHCI_EXT_PORT_COUNT(temp); + xhci_dbg(xhci, "Ext Cap %p, port offset = %u, " + "count = %u, revision = 0x%x\n", + addr, port_offset, port_count, major_revision); + /* Port count includes the current port offset */ + if (port_offset == 0 || (port_offset + port_count - 1) > num_ports) + /* WTF? "Valid values are ‘1’ to MaxPorts" */ + return; + port_offset--; + for (i = port_offset; i < (port_offset + port_count); i++) { + /* Duplicate entry. Ignore the port if the revisions differ. */ + if (xhci->port_array[i] != 0) { + xhci_warn(xhci, "Duplicate port entry, Ext Cap %p," + " port %u\n", addr, i); + xhci_warn(xhci, "Port was marked as USB %u, " + "duplicated as USB %u\n", + xhci->port_array[i], major_revision); + /* Only adjust the roothub port counts if we haven't + * found a similar duplicate. + */ + if (xhci->port_array[i] != major_revision && + xhci->port_array[i] != (u8) -1) { + if (xhci->port_array[i] == 0x03) + xhci->num_usb3_ports--; + else + xhci->num_usb2_ports--; + xhci->port_array[i] = (u8) -1; + } + /* FIXME: Should we disable the port? */ + } + xhci->port_array[i] = major_revision; + if (major_revision == 0x03) + xhci->num_usb3_ports++; + else + xhci->num_usb2_ports++; + } + /* FIXME: Should we disable ports not in the Extended Capabilities? */ +} + +/* + * Scan the Extended Capabilities for the "Supported Protocol Capabilities" that + * specify what speeds each port is supposed to be. We can't count on the port + * speed bits in the PORTSC register being correct until a device is connected, + * but we need to set up the two fake roothubs with the correct number of USB + * 3.0 and USB 2.0 ports at host controller initialization time. + */ +static int xhci_setup_port_arrays(struct xhci_hcd *xhci, gfp_t flags) +{ + u32 __iomem *addr; + u32 offset; + unsigned int num_ports; + int i, port_index; + + addr = &xhci->cap_regs->hcc_params; + offset = XHCI_HCC_EXT_CAPS(xhci_readl(xhci, addr)); + if (offset == 0) { + xhci_err(xhci, "No Extended Capability registers, " + "unable to set up roothub.\n"); + return -ENODEV; + } + + num_ports = HCS_MAX_PORTS(xhci->hcs_params1); + xhci->port_array = kzalloc(sizeof(*xhci->port_array)*num_ports, flags); + if (!xhci->port_array) + return -ENOMEM; + + /* + * For whatever reason, the first capability offset is from the + * capability register base, not from the HCCPARAMS register. + * See section 5.3.6 for offset calculation. + */ + addr = &xhci->cap_regs->hc_capbase + offset; + while (1) { + u32 cap_id; + + cap_id = xhci_readl(xhci, addr); + if (XHCI_EXT_CAPS_ID(cap_id) == XHCI_EXT_CAPS_PROTOCOL) + xhci_add_in_port(xhci, num_ports, addr, + (u8) XHCI_EXT_PORT_MAJOR(cap_id)); + offset = XHCI_EXT_CAPS_NEXT(cap_id); + if (!offset || (xhci->num_usb2_ports + xhci->num_usb3_ports) + == num_ports) + break; + /* + * Once you're into the Extended Capabilities, the offset is + * always relative to the register holding the offset. + */ + addr += offset; + } + + if (xhci->num_usb2_ports == 0 && xhci->num_usb3_ports == 0) { + xhci_warn(xhci, "No ports on the roothubs?\n"); + return -ENODEV; + } + xhci_dbg(xhci, "Found %u USB 2.0 ports and %u USB 3.0 ports.\n", + xhci->num_usb2_ports, xhci->num_usb3_ports); + /* + * Note we could have all USB 3.0 ports, or all USB 2.0 ports. + * Not sure how the USB core will handle a hub with no ports... + */ + if (xhci->num_usb2_ports) { + xhci->usb2_ports = kmalloc(sizeof(*xhci->usb2_ports)* + xhci->num_usb2_ports, flags); + if (!xhci->usb2_ports) + return -ENOMEM; + + port_index = 0; + for (i = 0; i < num_ports; i++) + if (xhci->port_array[i] != 0x03) { + xhci->usb2_ports[port_index] = + &xhci->op_regs->port_status_base + + NUM_PORT_REGS*i; + xhci_dbg(xhci, "USB 2.0 port at index %u, " + "addr = %p\n", i, + xhci->usb2_ports[port_index]); + port_index++; + } + } + if (xhci->num_usb3_ports) { + xhci->usb3_ports = kmalloc(sizeof(*xhci->usb3_ports)* + xhci->num_usb3_ports, flags); + if (!xhci->usb3_ports) + return -ENOMEM; + + port_index = 0; + for (i = 0; i < num_ports; i++) + if (xhci->port_array[i] == 0x03) { + xhci->usb3_ports[port_index] = + &xhci->op_regs->port_status_base + + NUM_PORT_REGS*i; + xhci_dbg(xhci, "USB 3.0 port at index %u, " + "addr = %p\n", i, + xhci->usb3_ports[port_index]); + port_index++; + } + } + return 0; +} int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) { @@ -1809,6 +1971,8 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) if (scratchpad_alloc(xhci, flags)) goto fail; + if (xhci_setup_port_arrays(xhci, flags)) + goto fail; return 0; diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 85e65647d445..170c367112d2 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -453,6 +453,24 @@ struct xhci_doorbell_array { #define STREAM_ID_TO_DB(p) (((p) & 0xffff) << 16) +/** + * struct xhci_protocol_caps + * @revision: major revision, minor revision, capability ID, + * and next capability pointer. + * @name_string: Four ASCII characters to say which spec this xHC + * follows, typically "USB ". + * @port_info: Port offset, count, and protocol-defined information. + */ +struct xhci_protocol_caps { + u32 revision; + u32 name_string; + u32 port_info; +}; + +#define XHCI_EXT_PORT_MAJOR(x) (((x) >> 24) & 0xff) +#define XHCI_EXT_PORT_OFF(x) ((x) & 0xff) +#define XHCI_EXT_PORT_COUNT(x) (((x) >> 8) & 0xff) + /** * struct xhci_container_ctx * @type: Type of context. Used to calculated offsets to contained contexts. @@ -1240,6 +1258,14 @@ struct xhci_hcd { u32 suspended_ports[8]; /* which ports are suspended */ unsigned long resume_done[MAX_HC_PORTS]; + /* Is each xHCI roothub port a USB 3.0, USB 2.0, or USB 1.1 port? */ + u8 *port_array; + /* Array of pointers to USB 3.0 PORTSC registers */ + u32 __iomem **usb3_ports; + unsigned int num_usb3_ports; + /* Array of pointers to USB 2.0 PORTSC registers */ + u32 __iomem **usb2_ports; + unsigned int num_usb2_ports; }; /* For testing purposes */ -- cgit v1.2.3-55-g7522 From 6dd0a3a7e0793dbeae1b951f091025d8cf896cb4 Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Tue, 16 Nov 2010 15:58:52 -0800 Subject: xhci: Don't let the USB core disable SuperSpeed ports. Disabling SuperSpeed ports is a Very Bad Thing (TM). It disables SuperSpeed terminations, which means that devices will never connect at SuperSpeed on that port. For USB 2.0/1.1 ports, disabling the port meant that the USB core could always get a connect status change later. That's not true with USB 3.0 ports. Do not let the USB core disable SuperSpeed ports. We can't rely on the device speed in the port status registers, since that isn't valid until there's a USB device connected to the port. Instead, we use the port speed array that's created from the Extended Capabilities registers. Signed-off-by: Sarah Sharp Tested-by: Don Zickus Cc: stable@kernel.org --- drivers/usb/host/xhci-hub.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index fef5a1f9d483..5d963e350494 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -229,6 +229,13 @@ void xhci_ring_device(struct xhci_hcd *xhci, int slot_id) static void xhci_disable_port(struct xhci_hcd *xhci, u16 wIndex, u32 __iomem *addr, u32 port_status) { + /* Don't allow the USB core to disable SuperSpeed ports. */ + if (xhci->port_array[wIndex] == 0x03) { + xhci_dbg(xhci, "Ignoring request to disable " + "SuperSpeed port.\n"); + return; + } + /* Write 1 to disable the port */ xhci_writel(xhci, port_status | PORT_PE, addr); port_status = xhci_readl(xhci, addr); -- cgit v1.2.3-55-g7522 From 92d2711f5dc15bf956546923a5718e74853f9912 Mon Sep 17 00:00:00 2001 From: Hema Kalliguddi Date: Mon, 15 Nov 2010 04:24:01 -0600 Subject: usb: musb: unmap dma buffer when switching to PIO Buffer is mapped to dma when dma channel is allocated. If, for some reason, dma channel programming fails, musb code will fallback to PIO mode to transfer that request. In that case, we need to unmap the buffer back to CPU. MUSB RTL1.8 and above cannot handle buffers which are not 32bit aligned. That happens to every request sent by g_ether gadget driver. Since the buffer sent was unaligned, we need to fallback to PIO. Because of that, g_ether was failing due to missing buffer unmapping. With this patch and [1] g_ether works fine with all MUSB revisions. Verified with OMAP3630 board, which has MUSB RTL1.8 using g_ether and g_zero. [1] http://www.spinics.net/lists/linux-usb/msg38400.html Signed-off-by: Hema HK Signed-off-by: Felipe Balbi --- drivers/usb/musb/musb_gadget.c | 117 ++++++++++++++++++++++++++++------------- 1 file changed, 79 insertions(+), 38 deletions(-) diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index 36cfd060dbe5..0169dcf3a6ff 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -92,6 +92,59 @@ /* ----------------------------------------------------------------------- */ +/* Maps the buffer to dma */ + +static inline void map_dma_buffer(struct musb_request *request, + struct musb *musb) +{ + if (request->request.dma == DMA_ADDR_INVALID) { + request->request.dma = dma_map_single( + musb->controller, + request->request.buf, + request->request.length, + request->tx + ? DMA_TO_DEVICE + : DMA_FROM_DEVICE); + request->mapped = 1; + } else { + dma_sync_single_for_device(musb->controller, + request->request.dma, + request->request.length, + request->tx + ? DMA_TO_DEVICE + : DMA_FROM_DEVICE); + request->mapped = 0; + } +} + +/* Unmap the buffer from dma and maps it back to cpu */ +static inline void unmap_dma_buffer(struct musb_request *request, + struct musb *musb) +{ + if (request->request.dma == DMA_ADDR_INVALID) { + DBG(20, "not unmapping a never mapped buffer\n"); + return; + } + if (request->mapped) { + dma_unmap_single(musb->controller, + request->request.dma, + request->request.length, + request->tx + ? DMA_TO_DEVICE + : DMA_FROM_DEVICE); + request->request.dma = DMA_ADDR_INVALID; + request->mapped = 0; + } else { + dma_sync_single_for_cpu(musb->controller, + request->request.dma, + request->request.length, + request->tx + ? DMA_TO_DEVICE + : DMA_FROM_DEVICE); + + } +} + /* * Immediately complete a request. * @@ -119,24 +172,8 @@ __acquires(ep->musb->lock) ep->busy = 1; spin_unlock(&musb->lock); - if (is_dma_capable()) { - if (req->mapped) { - dma_unmap_single(musb->controller, - req->request.dma, - req->request.length, - req->tx - ? DMA_TO_DEVICE - : DMA_FROM_DEVICE); - req->request.dma = DMA_ADDR_INVALID; - req->mapped = 0; - } else if (req->request.dma != DMA_ADDR_INVALID) - dma_sync_single_for_cpu(musb->controller, - req->request.dma, - req->request.length, - req->tx - ? DMA_TO_DEVICE - : DMA_FROM_DEVICE); - } + if (is_dma_capable() && ep->dma) + unmap_dma_buffer(req, musb); if (request->status == 0) DBG(5, "%s done request %p, %d/%d\n", ep->end_point.name, request, @@ -395,6 +432,13 @@ static void txstate(struct musb *musb, struct musb_request *req) #endif if (!use_dma) { + /* + * Unmap the dma buffer back to cpu if dma channel + * programming fails + */ + if (is_dma_capable() && musb_ep->dma) + unmap_dma_buffer(req, musb); + musb_write_fifo(musb_ep->hw_ep, fifo_count, (u8 *) (request->buf + request->actual)); request->actual += fifo_count; @@ -713,6 +757,20 @@ static void rxstate(struct musb *musb, struct musb_request *req) return; } #endif + /* + * Unmap the dma buffer back to cpu if dma channel + * programming fails. This buffer is mapped if the + * channel allocation is successful + */ + if (is_dma_capable() && musb_ep->dma) { + unmap_dma_buffer(req, musb); + + /* Clear DMAENAB for the + * PIO mode transfer + */ + csr &= ~MUSB_RXCSR_DMAENAB; + musb_writew(epio, MUSB_RXCSR, csr); + } musb_read_fifo(musb_ep->hw_ep, fifo_count, (u8 *) (request->buf + request->actual)); @@ -1150,26 +1208,9 @@ static int musb_gadget_queue(struct usb_ep *ep, struct usb_request *req, request->epnum = musb_ep->current_epnum; request->tx = musb_ep->is_in; - if (is_dma_capable() && musb_ep->dma) { - if (request->request.dma == DMA_ADDR_INVALID) { - request->request.dma = dma_map_single( - musb->controller, - request->request.buf, - request->request.length, - request->tx - ? DMA_TO_DEVICE - : DMA_FROM_DEVICE); - request->mapped = 1; - } else { - dma_sync_single_for_device(musb->controller, - request->request.dma, - request->request.length, - request->tx - ? DMA_TO_DEVICE - : DMA_FROM_DEVICE); - request->mapped = 0; - } - } else + if (is_dma_capable() && musb_ep->dma) + map_dma_buffer(request, musb); + else request->mapped = 0; spin_lock_irqsave(&musb->lock, lockflags); -- cgit v1.2.3-55-g7522 From e75df37165c639b06213ec88b4763c3e50a7f079 Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Tue, 16 Nov 2010 23:37:37 +0800 Subject: usb: musb: clear RXCSR_AUTOCLEAR before PIO read If RXCSR_AUTOCLEAR flag is not cleard before PIO reading, one packet may be recieved by musb fifo, but no chance to notify software, so cause packet loss, follows the detailed process: - PIO read one packet - musb fifo auto clear the MUSB_RXCSR_RXPKTRDY - musb continue to recieve the next packet, and MUSB_RXCSR_RXPKTRDY is set - software clear the MUSB_RXCSR_RXPKTRDY, so there is no chance for musb to notify software that the 2nd recieved packet. The patch does fix the g_ether issue below: - use fifo_mode 3 to enable double buffer - 'ping -s 1024 IP_OF_BEAGLE_XM' - one usb packet of 512 byte is lost, so ping failed, which can be observed by wireshark note: Beagle xm takes musb rtl1.8 and may fallback to pio mode for unaligned buffer. Signed-off-by: Ming Lei Signed-off-by: Felipe Balbi --- drivers/usb/musb/musb_gadget.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index 0169dcf3a6ff..363cfad003f8 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -765,10 +765,11 @@ static void rxstate(struct musb *musb, struct musb_request *req) if (is_dma_capable() && musb_ep->dma) { unmap_dma_buffer(req, musb); - /* Clear DMAENAB for the + /* + * Clear DMAENAB and AUTOCLEAR for the * PIO mode transfer */ - csr &= ~MUSB_RXCSR_DMAENAB; + csr &= ~(MUSB_RXCSR_DMAENAB | MUSB_RXCSR_AUTOCLEAR); musb_writew(epio, MUSB_RXCSR, csr); } -- cgit v1.2.3-55-g7522 From bb324b08165d5656d221af013ed9994a54e455be Mon Sep 17 00:00:00 2001 From: Ajay Kumar Gupta Date: Mon, 22 Nov 2010 14:22:41 +0530 Subject: usb: musb: gadget: fix compilation warning Fixes below compilation warning when musb driver is compiled for PIO mode: drivers/usb/musb/musb_gadget.c: In function 'musb_g_rx': drivers/usb/musb/musb_gadget.c:840: warning: label 'exit' defined but not used Signed-off-by: Ajay Kumar Gupta Signed-off-by: Felipe Balbi --- drivers/usb/musb/musb_gadget.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index 363cfad003f8..c8de0e123f2c 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -896,7 +896,9 @@ void musb_g_rx(struct musb *musb, u8 epnum) if (!request) return; } +#if defined(CONFIG_USB_INVENTRA_DMA) || defined(CONFIG_USB_TUSB_OMAP_DMA) exit: +#endif /* Analyze request */ rxstate(musb, to_musb_request(request)); } -- cgit v1.2.3-55-g7522 From 07a8cdd2bb17a4da68136d963b8bc71959bd31a5 Mon Sep 17 00:00:00 2001 From: Anand Gadiyar Date: Thu, 18 Nov 2010 18:54:17 +0530 Subject: 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 Signed-off-by: Santosh Shilimkar Signed-off-by: Anand Gadiyar Cc: Oliver Neukum Cc: Alan Stern Cc: Praveena NADAHALLY Cc: Ajay Kumar Gupta Signed-off-by: Felipe Balbi --- drivers/usb/core/hcd.c | 2 ++ drivers/usb/musb/musb_core.c | 3 +++ drivers/usb/musb/musb_gadget.c | 4 ++++ include/linux/usb.h | 4 ++++ 4 files changed, 13 insertions(+) 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? */ -- cgit v1.2.3-55-g7522 From 28942bb6a9dd4e2ed793675e515cfb8297ed355b Mon Sep 17 00:00:00 2001 From: Michael Stuermer Date: Thu, 18 Nov 2010 00:45:43 +0100 Subject: USB: ftdi_sio: Add ID for RT Systems USB-29B radio cable Another variant of the RT Systems programming cable for ham radios. Signed-off-by: Michael Stuermer Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 1 + drivers/usb/serial/ftdi_sio_ids.h | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 76f8b3556672..1c5892a2deea 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -696,6 +696,7 @@ static struct usb_device_id id_table_combined [] = { .driver_info = (kernel_ulong_t)&ftdi_NDI_device_quirk }, { USB_DEVICE(TELLDUS_VID, TELLDUS_TELLSTICK_PID) }, { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_SERIAL_VX7_PID) }, + { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_CT29B_PID) }, { USB_DEVICE(FTDI_VID, FTDI_MAXSTREAM_PID) }, { USB_DEVICE(FTDI_VID, FTDI_PHI_FISCO_PID) }, { USB_DEVICE(TML_VID, TML_USB_SERIAL_PID) }, diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index 263f62551197..cee062fbbb4e 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -721,6 +721,7 @@ */ #define RTSYSTEMS_VID 0x2100 /* Vendor ID */ #define RTSYSTEMS_SERIAL_VX7_PID 0x9e52 /* Serial converter for VX-7 Radios using FT232RL */ +#define RTSYSTEMS_CT29B_PID 0x9e54 /* CT29B Radio Cable */ /* * Bayer Ascensia Contour blood glucose meter USB-converter cable. -- cgit v1.2.3-55-g7522 From 27f485b5b27926878ffc8f528bdefeb25e6bd3d3 Mon Sep 17 00:00:00 2001 From: Tomoki Sekiyama Date: Mon, 22 Nov 2010 19:29:23 +0900 Subject: USB: yurex: add .llseek fop to file_operations Default llseek operation behavior was changed by the patch named "vfs: make no_llseek the default" after the yurex driver had been merged, so the llseek to yurex is now ignored. This patch add llseek fop with default_llseek to yurex driver to catch up to the change. Signed-off-by: Tomoki Sekiyama Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/yurex.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/misc/yurex.c b/drivers/usb/misc/yurex.c index 719c6180b31f..ac5bfd619e62 100644 --- a/drivers/usb/misc/yurex.c +++ b/drivers/usb/misc/yurex.c @@ -536,6 +536,7 @@ static const struct file_operations yurex_fops = { .open = yurex_open, .release = yurex_release, .fasync = yurex_fasync, + .llseek = default_llseek, }; -- cgit v1.2.3-55-g7522 From 6fdbad8021151a9e93af8159a6232c8f26415c09 Mon Sep 17 00:00:00 2001 From: Jacques Viviers Date: Wed, 24 Nov 2010 11:56:38 +0200 Subject: USB: serial: ftdi_sio: Vardaan USB RS422/485 converter PID added Add the PID for the Vardaan Enterprises VEUSB422R3 USB to RS422/485 converter. It uses the same chip as the FTDI_8U232AM_PID 0x6001. This should also work with the stable branches for: 2.6.31, 2.6.32, 2.6.33, 2.6.34, 2.6.35, 2.6.36 Signed-off-by: Jacques Viviers Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 1 + drivers/usb/serial/ftdi_sio_ids.h | 3 +++ 2 files changed, 4 insertions(+) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 1c5892a2deea..6a50965e23f2 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -201,6 +201,7 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(FTDI_VID, FTDI_MTXORB_5_PID) }, { USB_DEVICE(FTDI_VID, FTDI_MTXORB_6_PID) }, { USB_DEVICE(FTDI_VID, FTDI_R2000KU_TRUE_RNG) }, + { USB_DEVICE(FTDI_VID, FTDI_VARDAAN_PID) }, { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0100_PID) }, { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0101_PID) }, { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0102_PID) }, diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index cee062fbbb4e..1286f1e23d8c 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -114,6 +114,9 @@ /* Lenz LI-USB Computer Interface. */ #define FTDI_LENZ_LIUSB_PID 0xD780 +/* Vardaan Enterprises Serial Interface VEUSB422R3 */ +#define FTDI_VARDAAN_PID 0xF070 + /* * Xsens Technologies BV products (http://www.xsens.com). */ -- cgit v1.2.3-55-g7522 From a85b4e7f4481c5a1ca89fa63c9c871151965075e Mon Sep 17 00:00:00 2001 From: Brian J. Tarricone Date: Sun, 21 Nov 2010 21:15:52 -0800 Subject: USB: ehci: disable LPM and PPCD for nVidia MCP89 chips Tested on MacBookAir3,1. Without this, we get EPROTO errors when fetching device config descriptors. Signed-off-by: Brian Tarricone Reported-by: Benoit Gschwind Tested-by: Edgar Hucek Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-pci.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index 01bb72b71832..655f3c9f88bf 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c @@ -161,6 +161,18 @@ static int ehci_pci_setup(struct usb_hcd *hcd) if (pdev->revision < 0xa4) ehci->no_selective_suspend = 1; break; + + /* MCP89 chips on the MacBookAir3,1 give EPROTO when + * fetching device descriptors unless LPM is disabled. + * There are also intermittent problems enumerating + * devices with PPCD enabled. + */ + case 0x0d9d: + ehci_info(ehci, "disable lpm/ppcd for nvidia mcp89"); + ehci->has_lpm = 0; + ehci->has_ppcd = 0; + ehci->command &= ~CMD_PPCEE; + break; } break; case PCI_VENDOR_ID_VIA: -- cgit v1.2.3-55-g7522 From abf03184a31a3286fc0ab30f838ddee8ba9f9b7b Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Mon, 29 Nov 2010 10:17:22 -0500 Subject: USB: fix autosuspend bug in usb-serial This patch (as1437) fixes a bug in the usb-serial autosuspend handling. Since the usb-serial core now has autosuspend support, it must set the .supports_autosuspend member in every serial driver it registers. Otherwise the usb_autopm_get_interface() call won't work. This fixes Bugzilla #23012. Signed-off-by: Alan Stern CC: stable@kernel.org Reported-by: Kevin Smith Reported-and-tested-by: Simon Gerber Reported-and-tested-by: Matteo Croce Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/usb-serial.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 861223f2af6e..6954de50c0ff 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -51,6 +51,7 @@ static struct usb_driver usb_serial_driver = { .suspend = usb_serial_suspend, .resume = usb_serial_resume, .no_dynamic_id = 1, + .supports_autosuspend = 1, }; /* There is no MODULE_DEVICE_TABLE for usbserial.c. Instead @@ -1343,6 +1344,8 @@ int usb_serial_register(struct usb_serial_driver *driver) return -ENODEV; fixup_generic(driver); + if (driver->usb_driver) + driver->usb_driver->supports_autosuspend = 1; if (!driver->description) driver->description = driver->driver.name; -- cgit v1.2.3-55-g7522