aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
authorDavid Brownell <david-b@pacbell.net>2006-09-02 06:13:45 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2006-09-27 14:58:57 -0400
commit901b3d75e71535f29b64f352e94ff474d95df475 (patch)
treebc9dd49a1184bac831afb76943661e47f6366ad0 /drivers/usb
parent80f8af0c59385b41564a3ae670f94a1b4caa43b2 (diff)
USB: net2280: update dma buffer allocation
This updates the code handling dma-coherent buffer allocations, basically reusing code from the musb_hdrc driver. Instead of trying to work around two significant limitations of the dma framework (memory wastage for buffers smaller than a page, and inconsistency between calling context requirements for allocation and free) this just works around one of them (the latter). So count this as two steps forward (bugfixes: the latter issue could cause errors on some platforms, and some MIPS changes broke code for the former), and one step back (increasing cross-platform memory wastage). Plus linelength and whitespace fixes; and minor data segment shrinkage. Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/gadget/net2280.c156
1 files changed, 88 insertions, 68 deletions
diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c
index 09243239d948..3bda37f9a35f 100644
--- a/drivers/usb/gadget/net2280.c
+++ b/drivers/usb/gadget/net2280.c
@@ -2,7 +2,7 @@
2 * Driver for the PLX NET2280 USB device controller. 2 * Driver for the PLX NET2280 USB device controller.
3 * Specs and errata are available from <http://www.plxtech.com>. 3 * Specs and errata are available from <http://www.plxtech.com>.
4 * 4 *
5 * PLX Technology Inc. (formerly NetChip Technology) supported the 5 * PLX Technology Inc. (formerly NetChip Technology) supported the
6 * development of this driver. 6 * development of this driver.
7 * 7 *
8 * 8 *
@@ -26,7 +26,8 @@
26 * Copyright (C) 2003 David Brownell 26 * Copyright (C) 2003 David Brownell
27 * Copyright (C) 2003-2005 PLX Technology, Inc. 27 * Copyright (C) 2003-2005 PLX Technology, Inc.
28 * 28 *
29 * Modified Seth Levy 2005 PLX Technology, Inc. to provide compatibility with 2282 chip 29 * Modified Seth Levy 2005 PLX Technology, Inc. to provide compatibility
30 * with 2282 chip
30 * 31 *
31 * This program is free software; you can redistribute it and/or modify 32 * This program is free software; you can redistribute it and/or modify
32 * it under the terms of the GNU General Public License as published by 33 * it under the terms of the GNU General Public License as published by
@@ -85,7 +86,7 @@ static const char driver_name [] = "net2280";
85static const char driver_desc [] = DRIVER_DESC; 86static const char driver_desc [] = DRIVER_DESC;
86 87
87static const char ep0name [] = "ep0"; 88static const char ep0name [] = "ep0";
88static const char *ep_name [] = { 89static const char *const ep_name [] = {
89 ep0name, 90 ep0name,
90 "ep-a", "ep-b", "ep-c", "ep-d", 91 "ep-a", "ep-b", "ep-c", "ep-d",
91 "ep-e", "ep-f", 92 "ep-e", "ep-f",
@@ -225,7 +226,9 @@ net2280_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
225 if (!ep->is_in) 226 if (!ep->is_in)
226 writel ((1 << SET_NAK_OUT_PACKETS), &ep->regs->ep_rsp); 227 writel ((1 << SET_NAK_OUT_PACKETS), &ep->regs->ep_rsp);
227 else if (dev->pdev->device != 0x2280) { 228 else if (dev->pdev->device != 0x2280) {
228 /* Added for 2282, Don't use nak packets on an in endpoint, this was ignored on 2280 */ 229 /* Added for 2282, Don't use nak packets on an in endpoint,
230 * this was ignored on 2280
231 */
229 writel ((1 << CLEAR_NAK_OUT_PACKETS) 232 writel ((1 << CLEAR_NAK_OUT_PACKETS)
230 | (1 << CLEAR_NAK_OUT_PACKETS_MODE), &ep->regs->ep_rsp); 233 | (1 << CLEAR_NAK_OUT_PACKETS_MODE), &ep->regs->ep_rsp);
231 } 234 }
@@ -288,7 +291,7 @@ static int handshake (u32 __iomem *ptr, u32 mask, u32 done, int usec)
288 return -ETIMEDOUT; 291 return -ETIMEDOUT;
289} 292}
290 293
291static struct usb_ep_ops net2280_ep_ops; 294static const struct usb_ep_ops net2280_ep_ops;
292 295
293static void ep_reset (struct net2280_regs __iomem *regs, struct net2280_ep *ep) 296static void ep_reset (struct net2280_regs __iomem *regs, struct net2280_ep *ep)
294{ 297{
@@ -449,34 +452,15 @@ net2280_free_request (struct usb_ep *_ep, struct usb_request *_req)
449 452
450/*-------------------------------------------------------------------------*/ 453/*-------------------------------------------------------------------------*/
451 454
452#undef USE_KMALLOC 455/*
453 456 * dma-coherent memory allocation (for dma-capable endpoints)
454/* many common platforms have dma-coherent caches, which means that it's
455 * safe to use kmalloc() memory for all i/o buffers without using any
456 * cache flushing calls. (unless you're trying to share cache lines
457 * between dma and non-dma activities, which is a slow idea in any case.)
458 * 457 *
459 * other platforms need more care, with 2.5 having a moderately general 458 * NOTE: the dma_*_coherent() API calls suck. Most implementations are
460 * solution (which falls down for allocations smaller than one page) 459 * (a) page-oriented, so small buffers lose big; and (b) asymmetric with
461 * that improves significantly on the 2.4 PCI allocators by removing 460 * respect to calls with irqs disabled: alloc is safe, free is not.
462 * the restriction that memory never be freed in_interrupt(). 461 * We currently work around (b), but not (a).
463 */ 462 */
464#if defined(CONFIG_X86)
465#define USE_KMALLOC
466
467#elif defined(CONFIG_PPC) && !defined(CONFIG_NOT_COHERENT_CACHE)
468#define USE_KMALLOC
469 463
470#elif defined(CONFIG_MIPS) && !defined(CONFIG_DMA_NONCOHERENT)
471#define USE_KMALLOC
472
473/* FIXME there are other cases, including an x86-64 one ... */
474#endif
475
476/* allocating buffers this way eliminates dma mapping overhead, which
477 * on some platforms will mean eliminating a per-io buffer copy. with
478 * some kinds of system caches, further tweaks may still be needed.
479 */
480static void * 464static void *
481net2280_alloc_buffer ( 465net2280_alloc_buffer (
482 struct usb_ep *_ep, 466 struct usb_ep *_ep,
@@ -493,43 +477,71 @@ net2280_alloc_buffer (
493 return NULL; 477 return NULL;
494 *dma = DMA_ADDR_INVALID; 478 *dma = DMA_ADDR_INVALID;
495 479
496#if defined(USE_KMALLOC) 480 if (ep->dma)
497 retval = kmalloc(bytes, gfp_flags);
498 if (retval)
499 *dma = virt_to_phys(retval);
500#else
501 if (ep->dma) {
502 /* the main problem with this call is that it wastes memory
503 * on typical 1/N page allocations: it allocates 1-N pages.
504 */
505#warning Using dma_alloc_coherent even with buffers smaller than a page.
506 retval = dma_alloc_coherent(&ep->dev->pdev->dev, 481 retval = dma_alloc_coherent(&ep->dev->pdev->dev,
507 bytes, dma, gfp_flags); 482 bytes, dma, gfp_flags);
508 } else 483 else
509 retval = kmalloc(bytes, gfp_flags); 484 retval = kmalloc(bytes, gfp_flags);
510#endif
511 return retval; 485 return retval;
512} 486}
513 487
488static DEFINE_SPINLOCK(buflock);
489static LIST_HEAD(buffers);
490
491struct free_record {
492 struct list_head list;
493 struct device *dev;
494 unsigned bytes;
495 dma_addr_t dma;
496};
497
498static void do_free(unsigned long ignored)
499{
500 spin_lock_irq(&buflock);
501 while (!list_empty(&buffers)) {
502 struct free_record *buf;
503
504 buf = list_entry(buffers.next, struct free_record, list);
505 list_del(&buf->list);
506 spin_unlock_irq(&buflock);
507
508 dma_free_coherent(buf->dev, buf->bytes, buf, buf->dma);
509
510 spin_lock_irq(&buflock);
511 }
512 spin_unlock_irq(&buflock);
513}
514
515static DECLARE_TASKLET(deferred_free, do_free, 0);
516
514static void 517static void
515net2280_free_buffer ( 518net2280_free_buffer (
516 struct usb_ep *_ep, 519 struct usb_ep *_ep,
517 void *buf, 520 void *address,
518 dma_addr_t dma, 521 dma_addr_t dma,
519 unsigned bytes 522 unsigned bytes
520) { 523) {
521 /* free memory into the right allocator */ 524 /* free memory into the right allocator */
522#ifndef USE_KMALLOC
523 if (dma != DMA_ADDR_INVALID) { 525 if (dma != DMA_ADDR_INVALID) {
524 struct net2280_ep *ep; 526 struct net2280_ep *ep;
527 struct free_record *buf = address;
528 unsigned long flags;
525 529
526 ep = container_of(_ep, struct net2280_ep, ep); 530 ep = container_of(_ep, struct net2280_ep, ep);
527 if (!_ep) 531 if (!_ep)
528 return; 532 return;
529 dma_free_coherent(&ep->dev->pdev->dev, bytes, buf, dma); 533
534 ep = container_of (_ep, struct net2280_ep, ep);
535 buf->dev = &ep->dev->pdev->dev;
536 buf->bytes = bytes;
537 buf->dma = dma;
538
539 spin_lock_irqsave(&buflock, flags);
540 list_add_tail(&buf->list, &buffers);
541 tasklet_schedule(&deferred_free);
542 spin_unlock_irqrestore(&buflock, flags);
530 } else 543 } else
531#endif 544 kfree (address);
532 kfree (buf);
533} 545}
534 546
535/*-------------------------------------------------------------------------*/ 547/*-------------------------------------------------------------------------*/
@@ -737,7 +749,8 @@ fill_dma_desc (struct net2280_ep *ep, struct net2280_request *req, int valid)
737 */ 749 */
738 if (ep->is_in) 750 if (ep->is_in)
739 dmacount |= (1 << DMA_DIRECTION); 751 dmacount |= (1 << DMA_DIRECTION);
740 if ((!ep->is_in && (dmacount % ep->ep.maxpacket) != 0) || ep->dev->pdev->device != 0x2280) 752 if ((!ep->is_in && (dmacount % ep->ep.maxpacket) != 0)
753 || ep->dev->pdev->device != 0x2280)
741 dmacount |= (1 << END_OF_CHAIN); 754 dmacount |= (1 << END_OF_CHAIN);
742 755
743 req->valid = valid; 756 req->valid = valid;
@@ -812,7 +825,7 @@ static void start_dma (struct net2280_ep *ep, struct net2280_request *req)
812 825
813 /* previous OUT packet might have been short */ 826 /* previous OUT packet might have been short */
814 if (!ep->is_in && ((tmp = readl (&ep->regs->ep_stat)) 827 if (!ep->is_in && ((tmp = readl (&ep->regs->ep_stat))
815 & (1 << NAK_OUT_PACKETS)) != 0) { 828 & (1 << NAK_OUT_PACKETS)) != 0) {
816 writel ((1 << SHORT_PACKET_TRANSFERRED_INTERRUPT), 829 writel ((1 << SHORT_PACKET_TRANSFERRED_INTERRUPT),
817 &ep->regs->ep_stat); 830 &ep->regs->ep_stat);
818 831
@@ -1373,7 +1386,7 @@ net2280_fifo_flush (struct usb_ep *_ep)
1373 (void) readl (&ep->regs->ep_rsp); 1386 (void) readl (&ep->regs->ep_rsp);
1374} 1387}
1375 1388
1376static struct usb_ep_ops net2280_ep_ops = { 1389static const struct usb_ep_ops net2280_ep_ops = {
1377 .enable = net2280_enable, 1390 .enable = net2280_enable,
1378 .disable = net2280_disable, 1391 .disable = net2280_disable,
1379 1392
@@ -1631,7 +1644,7 @@ show_registers (struct device *_dev, struct device_attribute *attr, char *buf)
1631 } 1644 }
1632 1645
1633 /* Indexed Registers */ 1646 /* Indexed Registers */
1634 // none yet 1647 // none yet
1635 1648
1636 /* Statistics */ 1649 /* Statistics */
1637 t = scnprintf (next, size, "\nirqs: "); 1650 t = scnprintf (next, size, "\nirqs: ");
@@ -1691,11 +1704,11 @@ show_queues (struct device *_dev, struct device_attribute *attr, char *buf)
1691 ({ char *val; 1704 ({ char *val;
1692 switch (d->bmAttributes & 0x03) { 1705 switch (d->bmAttributes & 0x03) {
1693 case USB_ENDPOINT_XFER_BULK: 1706 case USB_ENDPOINT_XFER_BULK:
1694 val = "bulk"; break; 1707 val = "bulk"; break;
1695 case USB_ENDPOINT_XFER_INT: 1708 case USB_ENDPOINT_XFER_INT:
1696 val = "intr"; break; 1709 val = "intr"; break;
1697 default: 1710 default:
1698 val = "iso"; break; 1711 val = "iso"; break;
1699 }; val; }), 1712 }; val; }),
1700 le16_to_cpu (d->wMaxPacketSize) & 0x1fff, 1713 le16_to_cpu (d->wMaxPacketSize) & 0x1fff,
1701 ep->dma ? "dma" : "pio", ep->fifo_size 1714 ep->dma ? "dma" : "pio", ep->fifo_size
@@ -1808,8 +1821,8 @@ extern int net2280_set_fifo_mode (struct usb_gadget *gadget, int mode);
1808 * net2280_set_fifo_mode - change allocation of fifo buffers 1821 * net2280_set_fifo_mode - change allocation of fifo buffers
1809 * @gadget: access to the net2280 device that will be updated 1822 * @gadget: access to the net2280 device that will be updated
1810 * @mode: 0 for default, four 1kB buffers (ep-a through ep-d); 1823 * @mode: 0 for default, four 1kB buffers (ep-a through ep-d);
1811 * 1 for two 2kB buffers (ep-a and ep-b only); 1824 * 1 for two 2kB buffers (ep-a and ep-b only);
1812 * 2 for one 2kB buffer (ep-a) and two 1kB ones (ep-b, ep-c). 1825 * 2 for one 2kB buffer (ep-a) and two 1kB ones (ep-b, ep-c).
1813 * 1826 *
1814 * returns zero on success, else negative errno. when this succeeds, 1827 * returns zero on success, else negative errno. when this succeeds,
1815 * the contents of gadget->ep_list may have changed. 1828 * the contents of gadget->ep_list may have changed.
@@ -2241,7 +2254,8 @@ static void handle_ep_small (struct net2280_ep *ep)
2241 req->td->dmacount = 0; 2254 req->td->dmacount = 0;
2242 t = readl (&ep->regs->ep_avail); 2255 t = readl (&ep->regs->ep_avail);
2243 dma_done (ep, req, count, 2256 dma_done (ep, req, count,
2244 (ep->out_overflow || t) ? -EOVERFLOW : 0); 2257 (ep->out_overflow || t)
2258 ? -EOVERFLOW : 0);
2245 } 2259 }
2246 2260
2247 /* also flush to prevent erratum 0106 trouble */ 2261 /* also flush to prevent erratum 0106 trouble */
@@ -2411,7 +2425,7 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat)
2411 , &ep->regs->ep_stat); 2425 , &ep->regs->ep_stat);
2412 u.raw [0] = readl (&dev->usb->setup0123); 2426 u.raw [0] = readl (&dev->usb->setup0123);
2413 u.raw [1] = readl (&dev->usb->setup4567); 2427 u.raw [1] = readl (&dev->usb->setup4567);
2414 2428
2415 cpu_to_le32s (&u.raw [0]); 2429 cpu_to_le32s (&u.raw [0]);
2416 cpu_to_le32s (&u.raw [1]); 2430 cpu_to_le32s (&u.raw [1]);
2417 2431
@@ -2578,14 +2592,16 @@ static void handle_stat1_irqs (struct net2280 *dev, u32 stat)
2578 2592
2579 /* VBUS disconnect is indicated by VBUS_PIN and VBUS_INTERRUPT set. 2593 /* VBUS disconnect is indicated by VBUS_PIN and VBUS_INTERRUPT set.
2580 * Root Port Reset is indicated by ROOT_PORT_RESET_INTERRRUPT set and 2594 * Root Port Reset is indicated by ROOT_PORT_RESET_INTERRRUPT set and
2581 * both HIGH_SPEED and FULL_SPEED clear (as ROOT_PORT_RESET_INTERRUPT 2595 * both HIGH_SPEED and FULL_SPEED clear (as ROOT_PORT_RESET_INTERRUPT
2582 * only indicates a change in the reset state). 2596 * only indicates a change in the reset state).
2583 */ 2597 */
2584 if (stat & tmp) { 2598 if (stat & tmp) {
2585 writel (tmp, &dev->regs->irqstat1); 2599 writel (tmp, &dev->regs->irqstat1);
2586 if ((((stat & (1 << ROOT_PORT_RESET_INTERRUPT)) && 2600 if ((((stat & (1 << ROOT_PORT_RESET_INTERRUPT))
2587 ((readl (&dev->usb->usbstat) & mask) == 0)) 2601 && ((readl (&dev->usb->usbstat) & mask)
2588 || ((readl (&dev->usb->usbctl) & (1 << VBUS_PIN)) == 0) 2602 == 0))
2603 || ((readl (&dev->usb->usbctl)
2604 & (1 << VBUS_PIN)) == 0)
2589 ) && ( dev->gadget.speed != USB_SPEED_UNKNOWN)) { 2605 ) && ( dev->gadget.speed != USB_SPEED_UNKNOWN)) {
2590 DEBUG (dev, "disconnect %s\n", 2606 DEBUG (dev, "disconnect %s\n",
2591 dev->driver->driver.name); 2607 dev->driver->driver.name);
@@ -2852,7 +2868,7 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id)
2852 2868
2853 /* now all the pci goodies ... */ 2869 /* now all the pci goodies ... */
2854 if (pci_enable_device (pdev) < 0) { 2870 if (pci_enable_device (pdev) < 0) {
2855 retval = -ENODEV; 2871 retval = -ENODEV;
2856 goto done; 2872 goto done;
2857 } 2873 }
2858 dev->enabled = 1; 2874 dev->enabled = 1;
@@ -2870,6 +2886,10 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id)
2870 } 2886 }
2871 dev->region = 1; 2887 dev->region = 1;
2872 2888
2889 /* FIXME provide firmware download interface to put
2890 * 8051 code into the chip, e.g. to turn on PCI PM.
2891 */
2892
2873 base = ioremap_nocache (resource, len); 2893 base = ioremap_nocache (resource, len);
2874 if (base == NULL) { 2894 if (base == NULL) {
2875 DEBUG (dev, "can't map memory\n"); 2895 DEBUG (dev, "can't map memory\n");
@@ -2984,16 +3004,16 @@ static void net2280_shutdown (struct pci_dev *pdev)
2984 3004
2985/*-------------------------------------------------------------------------*/ 3005/*-------------------------------------------------------------------------*/
2986 3006
2987static struct pci_device_id pci_ids [] = { { 3007static const struct pci_device_id pci_ids [] = { {
2988 .class = ((PCI_CLASS_SERIAL_USB << 8) | 0xfe), 3008 .class = ((PCI_CLASS_SERIAL_USB << 8) | 0xfe),
2989 .class_mask = ~0, 3009 .class_mask = ~0,
2990 .vendor = 0x17cc, 3010 .vendor = 0x17cc,
2991 .device = 0x2280, 3011 .device = 0x2280,
2992 .subvendor = PCI_ANY_ID, 3012 .subvendor = PCI_ANY_ID,
2993 .subdevice = PCI_ANY_ID, 3013 .subdevice = PCI_ANY_ID,
2994}, { 3014}, {
2995 .class = ((PCI_CLASS_SERIAL_USB << 8) | 0xfe), 3015 .class = ((PCI_CLASS_SERIAL_USB << 8) | 0xfe),
2996 .class_mask = ~0, 3016 .class_mask = ~0,
2997 .vendor = 0x17cc, 3017 .vendor = 0x17cc,
2998 .device = 0x2282, 3018 .device = 0x2282,
2999 .subvendor = PCI_ANY_ID, 3019 .subvendor = PCI_ANY_ID,