This is the latest snapshot of the net2280 code. I'm sending it for testing, since the last update turned up some issues that were a surprise to me and so I think this should get more testing than I've yet had a chance to do.
Pull from http://usb-gadget.bkbits.net/gadget-2.6 to get the same code, with complete change history.
Notable changes:
- Fixes several DMA chaining bugs, mostly for OUT data
- Merges ISO updates from Mark Huang <[EMAIL PROTECTED]>
- Merges a shutdown fix from Alan Stern
- Fixes a minor locking goof found by "smatch"
- Pays proper attention to the "selfpowered" and "remote wakeup" bits (so device status should be correct, and the host will need to enable remote wakeup).
- USE_DMA_CHAINING became a module parameter, so that you can "modprobe net2280 use_dma_chaining=n" to kick in a less aggressive DMA mode.
- Is more paranoid about some dma errata
- Removes some ancient dma workaround #ifdefs, and similar minor cleanup
If you're using this driver on 2.6, please let me know if this breaks anything.
- Dave
--- a/drivers/usb/gadget/net2280.c Fri Dec 19 14:48:57 2003 +++ b/drivers/usb/gadget/net2280.c Fri Dec 19 14:48:57 2003 @@ -25,9 +25,6 @@ * rev1 chips. Rev1a silicon (0110) fixes almost all of them. */ -#define USE_DMA_CHAINING - - /* * Copyright (C) 2003 David Brownell * Copyright (C) 2003 NetChip Technologies @@ -47,8 +44,8 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#define DEBUG 1 -// #define VERBOSE /* extra debug messages (success too) */ +#undef DEBUG /* messages on error and most fault paths */ +#undef VERBOSE /* extra debug messages (success too) */ #include <linux/config.h> #include <linux/module.h> @@ -77,7 +74,7 @@ #define DRIVER_DESC "NetChip 2280 USB Peripheral Controller" -#define DRIVER_VERSION "Bastille Day 2003" +#define DRIVER_VERSION "19 December 2003" #define DMA_ADDR_INVALID (~(dma_addr_t)0) #define EP_DONTUSE 13 /* nonzero */ @@ -96,10 +93,21 @@ "ep-e", "ep-f", }; +/* use_dma -- general goodness, fewer interrupts, less cpu load (vs PIO) + * use_dma_chaining -- dma descriptor queues gives even more irq reduction + * + * The net2280 DMA engines are not tightly integrated with their FIFOs; + * not all cases are (yet) handled well in this driver or the silicon. + * Some gadget drivers work better with the dma support here than others. + * These two parameters let you use PIO or less aggressive DMA. + */ static int use_dma = 1; +static int use_dma_chaining = 1; /* "modprobe net2280 use_dma=n" etc */ -module_param (use_dma, bool, S_IRUGO|S_IWUSR); +module_param (use_dma, bool, S_IRUGO); +module_param (use_dma_chaining, bool, S_IRUGO); + /* mode 0 == ep-{a,b,c,d} 1K fifo each * mode 1 == ep-{a,b} 2K fifo each, ep-{c,d} unavailable @@ -110,6 +118,7 @@ /* "modprobe net2280 fifo_mode=1" etc */ module_param (fifo_mode, ushort, 0644); + #define DIR_STRING(bAddress) (((bAddress) & USB_DIR_IN) ? "in" : "out") #if defined(USE_SYSFS_DEBUG_FILES) || defined (DEBUG) @@ -169,8 +178,8 @@ /* FIFO lines can't go to different packets. PIO is ok, so * use it instead of troublesome (non-bulk) multi-packet DMA. */ - if (ep->is_in && ep->dma && (max % 4) != 0) { - DEBUG (ep->dev, "%s, no IN dma for maxpacket %d\n", + if (ep->dma && (max % 4) != 0 && use_dma_chaining) { + DEBUG (ep->dev, "%s, no dma for maxpacket %d\n", ep->ep.name, ep->ep.maxpacket); ep->dma = 0; } @@ -188,8 +197,10 @@ if ((dev->gadget.speed == USB_SPEED_HIGH && max != 512) || (dev->gadget.speed == USB_SPEED_FULL - && max > 64)) + && max > 64)) { + spin_unlock_irqrestore (&dev->lock, flags); return -ERANGE; + } } ep->is_iso = (tmp == USB_ENDPOINT_XFER_ISOC) ? 1 : 0; tmp <<= ENDPOINT_TYPE; @@ -205,11 +216,6 @@ writel (tmp, &ep->regs->ep_cfg); -#ifdef NET2280_DMA_OUT_WORKAROUND - if (!ep->is_in) - ep->dma = 0; -#endif - /* enable irqs */ if (!ep->dma) { /* pio, per-packet */ tmp = (1 << ep->num) | readl (&dev->regs->pciirqenb0); @@ -541,8 +547,11 @@ count -= 4; } - /* last fifo entry is "short" unless we wrote a full packet */ - if (total < ep->ep.maxpacket) { + /* last fifo entry is "short" unless we wrote a full packet. + * also explicitly validate last word in (periodic) transfers + * when maxpacket is not a multiple of 4 bytes. + */ + if (count || total < ep->ep.maxpacket) { tmp = count ? get_unaligned ((u32 *)buf) : count; cpu_to_le32s (&tmp); set_fifo_bytecount (ep, count & 0x03); @@ -555,6 +564,9 @@ /* work around erratum 0106: PCI and USB race over the OUT fifo. * caller guarantees chiprev 0100, out endpoint is NAKing, and * there's no real data in the fifo. + * + * NOTE: also used in cases where that erratum doesn't apply: + * where the host wrote "too much" data to us. */ static void out_flush (struct net2280_ep *ep) { @@ -626,7 +638,10 @@ ep->ep.name, count, tmp); req->req.status = -EOVERFLOW; cleanup = 1; - } + /* NAK_OUT_PACKETS will be set, so flushing is safe; + * the next read will start with the next packet + */ + } /* else it's a ZLP, no worries */ count = tmp; } req->req.actual += count; @@ -665,7 +680,7 @@ } /* fill out dma descriptor to match a given request */ -static inline void +static void fill_dma_desc (struct net2280_ep *ep, struct net2280_request *req, int valid) { struct net2280_dma *td = req->td; @@ -678,15 +693,13 @@ */ if (ep->is_in) dmacount |= (1 << DMA_DIRECTION); - else + else if ((dmacount % ep->ep.maxpacket) != 0) dmacount |= (1 << END_OF_CHAIN); req->valid = valid; if (valid) dmacount |= (1 << VALID_BIT); -#ifdef USE_DMA_CHAINING - if (!req->req.no_interrupt) -#endif + if (likely(!req->req.no_interrupt || !use_dma_chaining)) dmacount |= (1 << DMA_DONE_INTERRUPT_ENABLE); /* td->dmadesc = previously set by caller */ @@ -698,7 +711,8 @@ } static const u32 dmactl_default = - (1 << DMA_CLEAR_COUNT_ENABLE) + (1 << DMA_SCATTER_GATHER_DONE_INTERRUPT) + | (1 << DMA_CLEAR_COUNT_ENABLE) /* erratum 0116 workaround part 1 (use POLLING) */ | (POLL_100_USEC << DESCRIPTOR_POLLING_RATE) | (1 << DMA_VALID_BIT_POLLING_ENABLE) @@ -744,6 +758,8 @@ req->td->dmacount = cpu_to_le32 (req->req.length - tmp); writel ((1 << DMA_DONE_INTERRUPT_ENABLE) | tmp, &dma->dmacount); + req->td->dmadesc = 0; + req->valid = 1; writel ((1 << DMA_ENABLE), &dma->dmactl); writel ((1 << DMA_START), &dma->dmastat); @@ -772,13 +788,12 @@ req->td->dmadesc = cpu_to_le32 (ep->td_dma); fill_dma_desc (ep, req, 1); -#ifdef USE_DMA_CHAINING - writel ( (1 << VALID_BIT) - | (ep->is_in << DMA_DIRECTION) - | 0, &dma->dmacount); -#else - req->td->dmacount |= __constant_cpu_to_le32 (1 << END_OF_CHAIN); -#endif + if (use_dma_chaining) + writel ( (1 << VALID_BIT) + | (ep->is_in << DMA_DIRECTION) + | 0, &dma->dmacount); + else + req->td->dmacount |= __constant_cpu_to_le32 (1 << END_OF_CHAIN); writel (req->td_dma, &dma->dmadesc); writel (tmp, &dma->dmactl); @@ -977,7 +992,6 @@ ) { req->req.actual = req->req.length - (DMA_BYTE_COUNT_MASK & dmacount); - rmb (); done (ep, req, status); } @@ -1002,10 +1016,23 @@ /* SHORT_PACKET_TRANSFERRED_INTERRUPT handles "usb-short" * packets, including overruns, even when the transfer was * exactly the length requested (dmacount now zero). - * FIXME there's an overrun case here too, where we expect + * Except when this s/g was faked (read-from-fifo). + * + * NOTE: there's an overrun case here too, where we expect * a short packet but receive a max length one (won't NAK). + * In that case only this dma completion irq happens! + * + * AVOID by making gadget drivers always read N*maxpacket. + * (Which also avoids errata 0121, 0122, and 0124...) */ - if (!ep->is_in && (req->req.length % ep->ep.maxpacket) != 0) { + if (!ep->is_in + && req->td->dmadesc + && (req->req.length % ep->ep.maxpacket) != 0) { + tmp = readl (&ep->regs->ep_stat); + + if ((tmp & (1 << NAK_OUT_PACKETS)) == 0) + WARN (ep->dev, "%s short read trouble!\n", + ep->ep.name); req->dma_done = 1; break; } @@ -1021,13 +1048,18 @@ return; req = list_entry (ep->queue.next, struct net2280_request, queue); -#ifdef USE_DMA_CHAINING + if (!use_dma_chaining) { + start_dma (ep, req); + return; + } + /* the 2280 will be processing the queue unless queue hiccups after * the previous transfer: * IN: wanted automagic zlp, head doesn't (or vice versa) + * DMA_FIFO_VALIDATE doesn't init from dma descriptors. * OUT: was "usb-short", we must restart. */ - if (!req->valid) { + if (ep->is_in && !req->valid) { struct net2280_request *entry, *prev = 0; int qmode, reqmode, done = 0; @@ -1037,7 +1069,7 @@ list_for_each_entry (entry, &ep->queue, queue) { u32 dmacount; - if (entry != req) + if (entry == req) continue; dmacount = entry->td->dmacount; if (!done) { @@ -1051,6 +1083,7 @@ prev = entry; continue; } else { + /* force a hiccup */ prev->td->dmacount |= dma_done_ie; done = 1; } @@ -1062,22 +1095,26 @@ entry->td->dmacount = dmacount; prev = entry; } - start_dma (ep, req); - } else if (!ep->is_in - && (readl (&ep->regs->ep_stat) - & (1 << NAK_OUT_PACKETS)) != 0) - start_dma (ep, req); -#else - start_dma (ep, req); -#endif + } + + /* descriptor queue was already set up */ + writel (req->td_dma, &ep->dma->dmadesc); + writel (dmactl_default, &ep->dma->dmactl); + writel ((1 << DMA_START), &ep->dma->dmastat); + + if (!ep->is_in) + stop_out_naking (ep); } -static inline void abort_dma (struct net2280_ep *ep) +static void abort_dma (struct net2280_ep *ep) { /* abort the current transfer */ - writel ((1 << DMA_ABORT), &ep->dma->dmastat); - - /* collect completed transfers (except the current one) */ + if (likely (!list_empty (&ep->queue))) { + /* FIXME work around errata 0121, 0122, 0124 */ + writel ((1 << DMA_ABORT), &ep->dma->dmastat); + spin_stop_dma (ep->dma); + } else + stop_dma (ep->dma); scan_dma_completions (ep); } @@ -1108,43 +1145,52 @@ int stopped; ep = container_of (_ep, struct net2280_ep, ep); - req = container_of (_req, struct net2280_request, req); if (!_ep || (!ep->desc && ep->num != 0) || !_req) return -EINVAL; spin_lock_irqsave (&ep->dev->lock, flags); stopped = ep->stopped; - /* pause dma while we scan the queue */ + /* quiesce dma while we patch the queue */ dmactl = 0; ep->stopped = 1; if (ep->dma) { dmactl = readl (&ep->dma->dmactl); - writel (dmactl & ~(1 << DMA_ENABLE), &ep->dma->dmactl); - /* force synch, clean any completed requests */ - spin_stop_dma (ep->dma); + /* WARNING errataum 0127 may kick in ... */ + stop_dma (ep->dma); scan_dma_completions (ep); } + /* make sure it's still queued on this endpoint */ + list_for_each_entry (req, &ep->queue, queue) { + if (&req->req == _req) + break; + } + if (&req->req != _req) { + spin_unlock_irqrestore (&ep->dev->lock, flags); + return -EINVAL; + } + /* queue head may be partially complete. */ if (ep->queue.next == &req->queue) { if (ep->dma) { DEBUG (ep->dev, "unlink (%s) dma\n", _ep->name); _req->status = -ECONNRESET; abort_dma (ep); - if (likely (ep->queue.next == &req->queue)) + if (likely (ep->queue.next == &req->queue)) { + req->td->dmacount = 0; /* invalidate */ dma_done (ep, req, - le32_to_cpup (&req->td->dmacount), + readl (&ep->dma->dmacount), -ECONNRESET); + } } else { DEBUG (ep->dev, "unlink (%s) pio\n", _ep->name); done (ep, req, -ECONNRESET); } req = 0; -#ifdef USE_DMA_CHAINING /* patch up hardware chaining data */ - } else if (ep->dma) { + } else if (ep->dma && use_dma_chaining) { if (req->queue.prev == ep->queue.next) { writel (le32_to_cpu (req->td->dmadesc), &ep->dma->dmadesc); @@ -1161,7 +1207,6 @@ if (req->td->dmacount & dma_done_ie) prev->td->dmacount |= dma_done_ie; } -#endif } if (req) @@ -1188,10 +1233,14 @@ /*-------------------------------------------------------------------------*/ +static int net2280_fifo_status (struct usb_ep *_ep); + static int net2280_set_halt (struct usb_ep *_ep, int value) { struct net2280_ep *ep; + unsigned long flags; + int retval = 0; ep = container_of (_ep, struct net2280_ep, ep); if (!_ep || (!ep->desc && ep->num != 0)) @@ -1202,19 +1251,27 @@ == USB_ENDPOINT_XFER_ISOC) return -EINVAL; - VDEBUG (ep->dev, "%s %s halt\n", _ep->name, value ? "set" : "clear"); - - /* set/clear, then synch memory views with the device */ - if (value) { - if (ep->num == 0) - ep->dev->protocol_stall = 1; - else - set_halt (ep); - } else - clear_halt (ep); - (void) readl (&ep->regs->ep_rsp); + spin_lock_irqsave (&ep->dev->lock, flags); + if (!list_empty (&ep->queue)) + retval = -EAGAIN; + else if (ep->is_in && value && net2280_fifo_status (_ep) != 0) + retval = -EAGAIN; + else { + VDEBUG (ep->dev, "%s %s halt\n", _ep->name, + value ? "set" : "clear"); + /* set/clear, then synch memory views with the device */ + if (value) { + if (ep->num == 0) + ep->dev->protocol_stall = 1; + else + set_halt (ep); + } else + clear_halt (ep); + (void) readl (&ep->regs->ep_rsp); + } + spin_unlock_irqrestore (&ep->dev->lock, flags); - return 0; + return retval; } static int @@ -1290,21 +1347,49 @@ static int net2280_wakeup (struct usb_gadget *_gadget) { struct net2280 *dev; + u32 tmp; + unsigned long flags; if (!_gadget) return 0; dev = container_of (_gadget, struct net2280, gadget); - writel (1 << GENERATE_RESUME, &dev->usb->usbstat); + + spin_lock_irqsave (&dev->lock, flags); + tmp = readl (&dev->usb->usbctl); + if (tmp & (1 << DEVICE_REMOTE_WAKEUP_ENABLE)) + writel (1 << GENERATE_RESUME, &dev->usb->usbstat); + spin_unlock_irqrestore (&dev->lock, flags); /* pci writes may still be posted */ return 0; } +static int net2280_set_selfpowered (struct usb_gadget *_gadget, int value) +{ + struct net2280 *dev; + u32 tmp; + unsigned long flags; + + if (!_gadget) + return 0; + dev = container_of (_gadget, struct net2280, gadget); + + spin_lock_irqsave (&dev->lock, flags); + tmp = readl (&dev->usb->usbctl); + if (value) + tmp |= (1 << SELF_POWERED_STATUS); + else + tmp &= ~(1 << SELF_POWERED_STATUS); + writel (tmp, &dev->usb->usbctl); + spin_unlock_irqrestore (&dev->lock, flags); + + return 0; +} + static const struct usb_gadget_ops net2280_ops = { .get_frame = net2280_get_frame, .wakeup = net2280_wakeup, - - // .set_selfpowered = net2280_set_selfpowered, + .set_selfpowered = net2280_set_selfpowered, }; /*-------------------------------------------------------------------------*/ @@ -1348,11 +1433,14 @@ /* Main Control Registers */ t = snprintf (next, size, "%s version " DRIVER_VERSION - ", chiprev %04x\n" + ", chiprev %04x, dma %s\n\n" "devinit %03x fifoctl %08x gadget '%s'\n" "pci irqenb0 %02x irqenb1 %08x " "irqstat0 %04x irqstat1 %08x\n", driver_name, dev->chiprev, + use_dma + ? (use_dma_chaining ? "chaining" : "enabled") + : "disabled", readl (&dev->regs->devinit), readl (&dev->regs->fifoctl), s, @@ -1399,7 +1487,7 @@ t1 = readl (&ep->regs->ep_cfg); t2 = readl (&ep->regs->ep_rsp) & 0xff; t = snprintf (next, size, - "%s\tcfg %05x rsp (%02x) %s%s%s%s%s%s%s%s" + "\n%s\tcfg %05x rsp (%02x) %s%s%s%s%s%s%s%s" "irqenb %02x\n", ep->ep.name, t1, t2, (t2 & (1 << CLEAR_NAK_OUT_PACKETS)) @@ -1453,7 +1541,7 @@ // none yet /* Statistics */ - t = snprintf (next, size, "irqs: "); + t = snprintf (next, size, "\nirqs: "); size -= t; next += t; for (i = 0; i < 7; i++) { @@ -1504,7 +1592,7 @@ continue; t = d->bEndpointAddress; t = snprintf (next, size, - "%s (ep%d%s-%s) max %04x %s\n", + "\n%s (ep%d%s-%s) max %04x %s\n", ep->ep.name, t & USB_ENDPOINT_NUMBER_MASK, (t & USB_DIR_IN) ? "in" : "out", ({ char *val; @@ -1552,6 +1640,20 @@ goto done; size -= t; next += t; + + if (ep->dma) { + struct net2280_dma *td; + + td = req->td; + t = snprintf (next, size, "\t td %08x " + " count %08x buf %08x desc %08x\n", + req->td_dma, td->dmacount, + td->dmaaddr, td->dmadesc); + if (t <= 0 || t > size) + goto done; + size -= t; + next += t; + } } } @@ -1686,8 +1788,10 @@ /* clear old dma and irq state */ for (tmp = 0; tmp < 4; tmp++) { - writel ((1 << DMA_ABORT), &dev->dma [tmp].dmastat); - stop_dma (&dev->dma [tmp]); + struct net2280_ep *ep = &dev->ep [tmp + 1]; + + if (ep->dma) + abort_dma (ep); } writel (~0, &dev->regs->irqstat0), writel (~(1 << SUSPEND_REQUEST_INTERRUPT), &dev->regs->irqstat1), @@ -1767,7 +1871,7 @@ | (1 << SELF_POWERED_USB_DEVICE) | (1 << REMOTE_WAKEUP_SUPPORT) | (1 << USB_DETECT_ENABLE) - | (1 << DEVICE_REMOTE_WAKEUP_ENABLE) + | (1 << SELF_POWERED_STATUS) , &dev->usb->usbctl); /* enable irqs so we can see ep0 and general operation */ @@ -1889,6 +1993,7 @@ spin_unlock_irqrestore (&dev->lock, flags); driver->unbind (&dev->gadget); + dev->gadget.dev.driver = 0; dev->driver = 0; net2280_led_active (dev, 0); @@ -2009,6 +2114,7 @@ /* stop DMA, leave ep NAKing */ writel ((1 << DMA_ABORT), &ep->dma->dmastat); spin_stop_dma (ep->dma); + req->td->dmacount = 0; /* invalidate; abort won't */ /* buffer might have been too small */ t = readl (&ep->regs->ep_avail); @@ -2021,9 +2127,11 @@ if (t || ep->dev->chiprev == 0x0100) out_flush (ep); - /* restart dma (still NAKing OUT!) if needed */ + /* (re)start dma if needed, stop NAKing */ if (!list_empty (&ep->queue)) restart_dma (ep); + else + stop_out_naking (ep); } else DEBUG (ep->dev, "%s dma ep_stat %08x ??\n", ep->ep.name, t); @@ -2398,18 +2506,18 @@ tmp = readl (&dma->dmastat); writel (tmp, &dma->dmastat); -#ifdef USE_DMA_CHAINING - /* chaining should stop only on error (which?) + /* chaining should stop on abort, short OUT from fifo, * or (stat0 codepath) short OUT transfer. */ -#else - if ((tmp & (1 << DMA_TRANSACTION_DONE_INTERRUPT)) == 0) { - DEBUG (ep->dev, "%s no xact done? %08x\n", - ep->ep.name, tmp); - continue; + if (!use_dma_chaining) { + if ((tmp & (1 << DMA_TRANSACTION_DONE_INTERRUPT)) + == 0) { + DEBUG (ep->dev, "%s no xact done? %08x\n", + ep->ep.name, tmp); + continue; + } + stop_dma (ep->dma); } - stop_dma (ep->dma); -#endif /* OUT transfers terminate when the data from the * host is in our memory. Process whatever's done. @@ -2425,16 +2533,14 @@ /* disable dma on inactive queues; else maybe restart */ if (list_empty (&ep->queue)) { -#ifdef USE_DMA_CHAINING - stop_dma (ep->dma); -#endif + if (use_dma_chaining) + stop_dma (ep->dma); } else { tmp = readl (&dma->dmactl); - if ((tmp & (1 << DMA_SCATTER_GATHER_ENABLE)) == 0 + if (!use_dma_chaining || (tmp & (1 << DMA_ENABLE)) == 0) restart_dma (ep); -#ifdef USE_DMA_CHAINING - else if (ep->desc->bEndpointAddress & USB_DIR_IN) { + else if (ep->is_in && use_dma_chaining) { struct net2280_request *req; u32 dmacount; @@ -2449,12 +2555,9 @@ dmacount &= __constant_cpu_to_le32 ( (1 << VALID_BIT) | DMA_BYTE_COUNT_MASK); - if (dmacount && (dmacount & valid_bit) == 0) { - stop_dma (ep->dma); + if (dmacount && (dmacount & valid_bit) == 0) restart_dma (ep); - } } -#endif } ep->irqs++; } @@ -2505,7 +2608,7 @@ /* tear down the binding between this driver and the pci device */ -static void net2280_remove (struct pci_dev *pdev) +static void __exit net2280_remove (struct pci_dev *pdev) { struct net2280 *dev = pci_get_drvdata (pdev); @@ -2669,8 +2772,9 @@ } /* enable lower-overhead pci memory bursts during DMA */ - writel ((1 << PCI_RETRY_ABORT_ENABLE) - | (1 << DMA_MEMORY_WRITE_AND_INVALIDATE_ENABLE) + writel ( (1 << DMA_MEMORY_WRITE_AND_INVALIDATE_ENABLE) + // 256 write retries may not be enough... + // | (1 << PCI_RETRY_ABORT_ENABLE) | (1 << DMA_READ_MULTIPLE_ENABLE) | (1 << DMA_READ_LINE_ENABLE) , &dev->pci->pcimstctl); @@ -2686,15 +2790,10 @@ INFO (dev, "%s\n", driver_desc); INFO (dev, "irq %s, pci mem %p, chip rev %04x\n", bufp, base, dev->chiprev); - bufp = DRIVER_VERSION -#ifndef USE_DMA_CHAINING - " (no dma chain)" -#endif -#ifdef NET2280_DMA_OUT_WORKAROUND - " (no dma out)" -#endif - ; - INFO (dev, "version: %s\n", bufp); + INFO (dev, "version: " DRIVER_VERSION "; dma %s\n", + use_dma + ? (use_dma_chaining ? "chaining" : "enabled") + : "disabled"); the_controller = dev; device_register (&dev->gadget.dev); @@ -2729,7 +2828,7 @@ .id_table = pci_ids, .probe = net2280_probe, - .remove = net2280_remove, + .remove = __exit_p(net2280_remove), /* FIXME add power management support */ }; @@ -2740,6 +2839,8 @@ static int __init init (void) { + if (!use_dma) + use_dma_chaining = 0; return pci_module_init (&net2280_pci_driver); } module_init (init); --- a/drivers/usb/gadget/net2280.h Fri Dec 19 14:48:57 2003 +++ b/drivers/usb/gadget/net2280.h Fri Dec 19 14:48:57 2003 @@ -559,8 +559,7 @@ unsigned enabled : 1, protocol_stall : 1, got_irq : 1, - region : 1, - selfpowered : 1; + region : 1; u16 chiprev; /* pci state used to access those endpoints */