diff options
Diffstat (limited to 'drivers/usb/musb')
-rw-r--r-- | drivers/usb/musb/am35x.c | 6 | ||||
-rw-r--r-- | drivers/usb/musb/musb_dsps.c | 8 | ||||
-rw-r--r-- | drivers/usb/musb/musb_gadget.c | 30 | ||||
-rw-r--r-- | drivers/usb/musb/ux500.c | 2 |
4 files changed, 37 insertions, 9 deletions
diff --git a/drivers/usb/musb/am35x.c b/drivers/usb/musb/am35x.c index 457f25e62c51..c964d6af178b 100644 --- a/drivers/usb/musb/am35x.c +++ b/drivers/usb/musb/am35x.c @@ -305,6 +305,12 @@ static irqreturn_t am35x_musb_interrupt(int irq, void *hci) ret = IRQ_HANDLED; } + /* Drop spurious RX and TX if device is disconnected */ + if (musb->int_usb & MUSB_INTR_DISCONNECT) { + musb->int_tx = 0; + musb->int_rx = 0; + } + if (musb->int_tx || musb->int_rx || musb->int_usb) ret |= musb_interrupt(musb); diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c index 444346e1e10d..ff5f112053d2 100644 --- a/drivers/usb/musb/musb_dsps.c +++ b/drivers/usb/musb/musb_dsps.c @@ -458,11 +458,11 @@ static int __devinit dsps_create_musb_pdev(struct dsps_glue *glue, u8 id) struct platform_device *musb; struct resource *res; struct resource resources[2]; - char res_name[10]; + char res_name[11]; int ret, musbid; /* get memory resource */ - sprintf(res_name, "musb%d", id); + snprintf(res_name, sizeof(res_name), "musb%d", id); res = platform_get_resource_byname(pdev, IORESOURCE_MEM, res_name); if (!res) { dev_err(dev, "%s get mem resource failed\n", res_name); @@ -473,7 +473,7 @@ static int __devinit dsps_create_musb_pdev(struct dsps_glue *glue, u8 id) resources[0] = *res; /* get irq resource */ - sprintf(res_name, "musb%d-irq", id); + snprintf(res_name, sizeof(res_name), "musb%d-irq", id); res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, res_name); if (!res) { dev_err(dev, "%s get irq resource failed\n", res_name); @@ -530,7 +530,7 @@ static int __devinit dsps_create_musb_pdev(struct dsps_glue *glue, u8 id) of_property_read_u32(np, "num-eps", (u32 *)&config->num_eps); of_property_read_u32(np, "ram-bits", (u32 *)&config->ram_bits); - sprintf(res_name, "port%d-mode", id); + snprintf(res_name, sizeof(res_name), "port%d-mode", id); of_property_read_u32(np, res_name, (u32 *)&pdata->mode); of_property_read_u32(np, "power", (u32 *)&pdata->power); config->multipoint = of_property_read_bool(np, "multipoint"); diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index d0b87e7b4abf..b6b84dacc791 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -707,11 +707,12 @@ static void rxstate(struct musb *musb, struct musb_request *req) fifo_count = musb_readw(epio, MUSB_RXCOUNT); /* - * use mode 1 only if we expect data of at least ep packet_sz - * and have not yet received a short packet + * Enable Mode 1 on RX transfers only when short_not_ok flag + * is set. Currently short_not_ok flag is set only from + * file_storage and f_mass_storage drivers */ - if ((request->length - request->actual >= musb_ep->packet_sz) && - (fifo_count >= musb_ep->packet_sz)) + + if (request->short_not_ok && fifo_count == musb_ep->packet_sz) use_mode_1 = 1; else use_mode_1 = 0; @@ -727,6 +728,27 @@ static void rxstate(struct musb *musb, struct musb_request *req) c = musb->dma_controller; channel = musb_ep->dma; + /* We use DMA Req mode 0 in rx_csr, and DMA controller operates in + * mode 0 only. So we do not get endpoint interrupts due to DMA + * completion. We only get interrupts from DMA controller. + * + * We could operate in DMA mode 1 if we knew the size of the tranfer + * in advance. For mass storage class, request->length = what the host + * sends, so that'd work. But for pretty much everything else, + * request->length is routinely more than what the host sends. For + * most these gadgets, end of is signified either by a short packet, + * or filling the last byte of the buffer. (Sending extra data in + * that last pckate should trigger an overflow fault.) But in mode 1, + * we don't get DMA completion interrupt for short packets. + * + * Theoretically, we could enable DMAReq irq (MUSB_RXCSR_DMAMODE = 1), + * to get endpoint interrupt on every DMA req, but that didn't seem + * to work reliably. + * + * REVISIT an updated g_file_storage can set req->short_not_ok, which + * then becomes usable as a runtime "use mode 1" hint... + */ + /* Experimental: Mode1 works with mass storage use cases */ if (use_mode_1) { csr |= MUSB_RXCSR_AUTOCLEAR; diff --git a/drivers/usb/musb/ux500.c b/drivers/usb/musb/ux500.c index d62a91fedc22..0e62f504410e 100644 --- a/drivers/usb/musb/ux500.c +++ b/drivers/usb/musb/ux500.c @@ -65,7 +65,7 @@ static int __devinit ux500_probe(struct platform_device *pdev) struct platform_device *musb; struct ux500_glue *glue; struct clk *clk; - + int musbid; int ret = -ENOMEM; glue = kzalloc(sizeof(*glue), GFP_KERNEL); |