bk://kernel.bkbits.net/gregkh/linux/usb-2.6 stern@rowland.harvard.edu|ChangeSet|20040905035315|47865 stern # This is a BitKeeper generated diff -Nru style patch. # # ChangeSet # 2004/09/06 17:32:27-07:00 akpm@bix.(none) # Merge bk://kernel.bkbits.net/gregkh/linux/usb-2.6 # into bix.(none):/usr/src/bk-usb # # drivers/usb/media/dabusb.c # 2004/09/06 17:32:23-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/usb/class/usb-midi.c # 2004/09/06 17:32:23-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/usb/class/audio.c # 2004/09/06 17:32:23-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/09/05 05:53:15+02:00 stern@rowland.harvard.edu # [PATCH] USB: Centralize logical disconnects in the hub driver # # This patch takes some code that was only used in one place in the hub # driver, and packages it up into a subroutine which is now called from # several places. The routine does a logical disconnect -- for example, # after issuing a port reset, if the device descriptors have changed # (because of a firmware update perhaps) we logically disconnect the old # device structure and create a new one. Or if a resume fails for any # reason we can do the same thing. # # This touches some of David Brownell's suspend/resume code, obviously. # (It also fixes a couple of small errors in there.) He has said it looks # okay. # # # # Signed-off-by: Alan Stern # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/core/hub.c # 2004/08/18 17:44:48+02:00 stern@rowland.harvard.edu +36 -23 # USB: Centralize logical disconnects in the hub driver # # ChangeSet # 2004/09/05 05:23:24+02:00 janitor@sternwelten.at # [PATCH] list_for_each_entry: drivers-usb-class-audio.c # # Make code more readable with list_for_each_entry. # Compile tested. # # # Signed-off-by: Domen Puncer # Signed-off-by: Maximilian Attems # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/class/audio.c # 2004/09/01 19:34:25+02:00 janitor@sternwelten.at +6 -15 # list_for_each_entry: drivers-usb-class-audio.c # # ChangeSet # 2004/09/05 05:22:50+02:00 janitor@sternwelten.at # [PATCH] list_for_each_entry: drivers-usb-class-usb-midi.c # # Make code more readable with list_for_each_entry. # Compile tested. # # # Signed-off-by: Domen Puncer # Signed-off-by: Maximilian Attems # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/class/usb-midi.c # 2004/09/01 19:34:26+02:00 janitor@sternwelten.at +3 -8 # list_for_each_entry: drivers-usb-class-usb-midi.c # # ChangeSet # 2004/09/05 05:22:18+02:00 janitor@sternwelten.at # [PATCH] list_for_each_entry: drivers-usb-media-dabusb.c # # Use list_for_each_entry to make code more readable. # Compile tested. # # Signed-off-by: Domen Puncer # Signed-off-by: Maximilian Attems # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/media/dabusb.c # 2004/09/01 19:34:30+02:00 janitor@sternwelten.at +1 -4 # list_for_each_entry: drivers-usb-media-dabusb.c # # ChangeSet # 2004/09/05 05:21:45+02:00 janitor@sternwelten.at # [PATCH] list_for_each_entry: drivers-usb-host-hc_sl811.c # # Make code more readable with list_for_each_entry_safe. # (Is this a non i386? I can't compile it.) # # Signed-off-by: Domen Puncer # Signed-off-by: Maximilian Attems # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/host/hc_sl811.c # 2004/09/01 19:34:32+02:00 janitor@sternwelten.at +2 -6 # list_for_each_entry: drivers-usb-host-hc_sl811.c # # ChangeSet # 2004/09/05 05:21:11+02:00 janitor@sternwelten.at # [PATCH] list_for_each_entry: drivers-usb-serial-ipaq.c # # Use list_for_each_entry_safe to make code more readable. # Compile tested. # # Signed-off-by: Domen Puncer # Signed-off-by: Maximilian Attems # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/serial/ipaq.c # 2004/09/01 19:34:33+02:00 janitor@sternwelten.at +5 -14 # list_for_each_entry: drivers-usb-serial-ipaq.c # # ChangeSet # 2004/09/05 05:04:18+02:00 janitor@sternwelten.at # [PATCH] list_for_each_entry: drivers-usb-core-devices.c # # Make code more readable with list_for_each_entry. # Compile tested. # # Patch incremental on the list_for_each() change. # # Signed-off-by: Domen Puncer # Signed-off-by: Maximilian Attems # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/core/devices.c # 2004/09/01 19:34:25+02:00 janitor@sternwelten.at +2 -6 # list_for_each_entry: drivers-usb-core-devices.c # # ChangeSet # 2004/09/05 04:53:18+02:00 greg@kroah.com # USB: remove usbdevfs filesystem name, usbfs is the proper one to use. # # This has been publicised for years now, and the usvfs name will work just # fine with a 2.4 kernel, so we are not breaking backwards compatibility. # # Signed-off-by: Greg Kroah-Hartman # # include/linux/usbdevice_fs.h # 2004/09/05 04:52:09+02:00 greg@kroah.com +0 -10 # USB: remove usbdevfs filesystem name, usbfs is the proper one to use. # # This has been publicised for years now, and the usvfs name will work just # fine with a 2.4 kernel, so we are not breaking backwards compatibility. # # Signed-off-by: Greg Kroah-Hartman # # include/linux/usb.h # 2004/09/05 04:52:09+02:00 greg@kroah.com +0 -2 # USB: remove usbdevfs filesystem name, usbfs is the proper one to use. # # This has been publicised for years now, and the usvfs name will work just # fine with a 2.4 kernel, so we are not breaking backwards compatibility. # # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/core/usb.h # 2004/09/05 04:52:09+02:00 greg@kroah.com +6 -0 # USB: remove usbdevfs filesystem name, usbfs is the proper one to use. # # This has been publicised for years now, and the usvfs name will work just # fine with a 2.4 kernel, so we are not breaking backwards compatibility. # # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/core/inode.c # 2004/09/05 04:52:09+02:00 greg@kroah.com +13 -108 # USB: remove usbdevfs filesystem name, usbfs is the proper one to use. # # This has been publicised for years now, and the usvfs name will work just # fine with a 2.4 kernel, so we are not breaking backwards compatibility. # # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/core/devio.c # 2004/09/05 04:52:09+02:00 greg@kroah.com +5 -5 # USB: remove usbdevfs filesystem name, usbfs is the proper one to use. # # This has been publicised for years now, and the usvfs name will work just # fine with a 2.4 kernel, so we are not breaking backwards compatibility. # # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/core/devices.c # 2004/09/05 04:52:09+02:00 greg@kroah.com +2 -2 # USB: remove usbdevfs filesystem name, usbfs is the proper one to use. # # This has been publicised for years now, and the usvfs name will work just # fine with a 2.4 kernel, so we are not breaking backwards compatibility. # # Signed-off-by: Greg Kroah-Hartman # # ChangeSet # 2004/09/03 14:25:14-07:00 akpm@bix.(none) # Merge bk://kernel.bkbits.net/gregkh/linux/usb-2.6 # into bix.(none):/usr/src/bk-usb # # drivers/usb/misc/tiglusb.c # 2004/09/03 14:25:09-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/usb/media/dabusb.c # 2004/09/03 14:25:09-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/09/03 14:24:12-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb # # MAINTAINERS # 2004/09/03 14:24:08-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/09/03 14:29:45+02:00 alborchers@steinerpoint.com # [PATCH] USB: close waits for drain in pl2303 # # Here is an additional patch for pl2303 in 2.6.9-rc1, # to be applied after my previous circular buffer patch. # This patch waits for the buffer to drain on close and # then clears the buffer. In addition to the obvious # features, this also fixes a bug where closing a port # with a full buffer would accidentally disable writes # when the port was re-opened. # # The original pl2303 could lose data that was still going # out the port on close, and even this patch only solves # the problem completely for data rates of 1200 bps and # above. # # Waiting for data to drain from the circular buffer is # easy, but the problem is waiting for data to drain from # the 256 byte hardware buffer on the device. I don't know # how much data is in the hardware buffer, so I just wait # long enough for a potentially full hardware buffer to # drain, but I don't want to wait that long for low data # rates if the buffer isn't full. There is probably some # way to query the pl2303 to find out how much data is in # its hardware buffer, maybe snooping would reveal that. # # - Added a wait for data to drain from the driver # write buffer when closing. # # - Added a wait for the data to drain from the # device hardware buffer when closing. # # - Cleared the driver write buffer when closing. # # Signed-off-by: Al Borchers # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/serial/pl2303.c # 2004/08/30 02:27:08+02:00 alborchers@steinerpoint.com +58 -4 # USB: close waits for drain in pl2303 # # ChangeSet # 2004/09/03 14:29:06+02:00 alborchers@steinerpoint.com # [PATCH] USB: circular buffer for pl2303 # # Here is the patch adding a circular buffer to pl2303 # updated to 2.6.9-rc1. Phil and I both tested this. # (Phil tested a slightly different earlier version.) # # This fixes the carriage return newline problem Olaf # Hering reported and helps Phil with hotsyncing his # phone. This patch also fixes a problem that would # sometimes leave a pl2303 port unable to send data, # reporting "already writing", after closing the port # while writing was in progress. This happened about # 1/3 of the time in my tests with the stock 2.6.9-rc1 # pl2303 driver. # # # - Added a circular write buffer, protected by the # existing spin lock. # # - Write_room and chars_in_buffer now report room and # chars in the circular buffer. # # - Added a "bounce buffer" when transfering data from # user space to the circular buffer--needed for locking. # # - Replaced (urb->status != -EINPROGRESS) with a private # write_urb_in_use flag protected by the existing spin # lock. Clear this flag when the urb is unlinked. # # - Free memory on failed startup. # # - These changes make ONLCR mapping work and fix a bug # that would sometimes leave the port unable to write, # reporting "already writing", after closing the port # while writing was in progress. # # Signed-off-by: Al Borchers # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/serial/pl2303.c # 2004/08/28 22:44:17+02:00 alborchers@steinerpoint.com +324 -25 # USB: circular buffer for pl2303 # # ChangeSet # 2004/09/03 13:33:55+02:00 stern@rowland.harvard.edu # [PATCH] USB: Nag message for usb_kill_urb # # This patch is only for nuisance value. It puts a nag message in the # system log every time usb_unlink_urb() is called for synchronous # unlinking. My hope is this will speed the process of converting drivers # to use usb_kill_urb(). # # Don't apply this if it generates too much noise, but otherwise go ahead. # A little prodding never hurt anyone. # # Signed-off-by: Alan Stern # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/core/urb.c # 2004/08/30 13:39:08+02:00 stern@rowland.harvard.edu +3 -0 # USB: Nag message for usb_kill_urb # # ChangeSet # 2004/09/03 13:33:20+02:00 janitor@sternwelten.at # [PATCH] usb/dabusb: insert set_current_state() before schedule_timeout() # # After discussing this patch with Mark Hollomon, I think it is much safer # / better to leave the conditional check within the while loop. This way # the mutex state is as expected and maintainability is not compromised. # The previous patch should not be applied. # # # Description: Inserts appropriate set_current_state() call so that # schedule_timeout() functions as expected. # # Signed-off-by: Nishanth Aravamudan # Signed-off-by: Maximilian Attems # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/media/dabusb.c # 2004/09/01 19:35:55+02:00 janitor@sternwelten.at +1 -0 # usb/dabusb: insert set_current_state() before schedule_timeout() # # ChangeSet # 2004/09/03 13:32:49+02:00 janitor@sternwelten.at # [PATCH] usb/tiglusb: insert set_current_state() before schedule_timeout() # # Insert set_current_state() so schedule_timeout() functions as expected. # # Signed-off-by: Nishanth Aravamudan # Signed-off-by: Maximilian Attems # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/misc/tiglusb.c # 2004/09/01 19:35:55+02:00 janitor@sternwelten.at +1 -0 # usb/tiglusb: insert set_current_state() before schedule_timeout() # # ChangeSet # 2004/09/03 13:32:12+02:00 bjorn.helgaas@hp.com # [PATCH] HCD PCI probe: print actual, not ioremapped, address # # I think the USB HCD should print the actual PCI memory address, not the # ioremapped address. AFAIK, there's no reason the ioremapped address has # to have any fixed relationship to the actual address. Also, this makes # it match what's in /proc/iomem. I also added a leading "0x". Example # from ia64: # # - ehci_hcd 0000:00:01.2: irq 52, pci mem c000000080021000 # + ehci_hcd 0000:00:01.2: irq 52, pci mem 0x80021000 # # # # USB HCD: print actual PCI mem address, not the ioremapped value. # # Signed-off-by: Bjorn Helgaas # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/core/hcd-pci.c # 2004/09/01 18:42:03+02:00 bjorn.helgaas@hp.com +2 -2 # HCD PCI probe: print actual, not ioremapped, address # # ChangeSet # 2004/09/03 13:31:41+02:00 stern@rowland.harvard.edu # [PATCH] USB: Remove inappropriate unusual_devs.h entry # # A couple of months ago you applied a patch from Torsten Scherer to create # a new unusual_devs.h entry. In further discussions with him I learned # that the entry wasn't needed to access the device; the only reason for it # was as a workaround for some old, buggy hotplug program on his system. # # Now Evan Fletcher reports that the entry actively prevents him from using # his device. For me that's the last straw, so here's a patch to remove the # entry. Torsten should be okay if he simply upgrades his hotplug package # or removes the buggy program. # # On Mon, 30 Aug 2004, Evan Fletcher wrote: # > Hi list, # > # > I have a Bytecc 5.25" External Enclosure, model ME-320U2F, that has # > both USB 2.0 and Firewire connections # > (http://www.byteccusa.com/product/enclosure/ME-320.htm). It used to # > work fine on earlier Linux 2.6 kernels, but stopped working a few # > revisions ago. # > # > I tracked the problem down to an entry in unusual_devs.h: # > # > /* : I don't know the name of the bridge # > * manufacturer, but I've got an external USB drive by the Revoltec company # > * that needs this. otherwise the drive is recognized as /dev/sda, but any # > * access to it blocks indefinitely. # > */ # > UNUSUAL_DEV( 0x0402, 0x5621, 0x0103, 0x0103, # > "Revoltec", # > "USB/IDE Bridge (ATA/ATAPI)", # > US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_INQUIRY), # # <...> # > So, is there some way that this entry can be modified so that my DVD+R # > works properly, and Mr. Scherer can still use his Revoltec external # > disk? # > # > Thank you, # > Evan Fletcher # # # # Signed-off-by: Alan Stern # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/storage/unusual_devs.h # 2004/08/30 16:12:17+02:00 stern@rowland.harvard.edu +0 -10 # USB: Remove inappropriate unusual_devs.h entry # # ChangeSet # 2004/09/03 13:31:05+02:00 akpm@osdl.org # [PATCH] USB: "Lost sync on frames" error in konicawc module # # From: # # http://bugme.osdl.org/show_bug.cgi?id=3286 # # The kernel keeps printing "Lost sync on frames" error messages as soon as a # program tries to access the webcam. No video data can be retrieved from # the webcam. # # The following patch seems enough to solve the problem. (just inverting the # order at which the old and new data blocks are sent to the user). # # Signed-off-by: Andrew Morton # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/media/konicawc.c # 2004/08/28 08:58:21+02:00 akpm@osdl.org +1 -1 # USB: "Lost sync on frames" error in konicawc module # # ChangeSet # 2004/09/03 13:30:33+02:00 abbotti@mev.co.uk # [PATCH] USB: Add B&B Electronics VID/PIDs to ftdi_sio # # This patch adds VID/PIDs for a few FTDI-based USB serial devices # from B&B Electronics to the ftdi_sio driver. # # # Signed-off-by: Ian Abbott # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/serial/ftdi_sio.h # 2004/09/01 14:04:37+02:00 abbotti@mev.co.uk +8 -0 # USB: Add B&B Electronics VID/PIDs to ftdi_sio # # drivers/usb/serial/ftdi_sio.c # 2004/09/01 14:04:37+02:00 abbotti@mev.co.uk +9 -0 # USB: Add B&B Electronics VID/PIDs to ftdi_sio # # ChangeSet # 2004/09/03 13:29:55+02:00 david-b@pacbell.net # [PATCH] USB: OHCI init cleanups # # This ought to fix the NS9750 init issue, and make the AMD756 case # at least somewhat better. It makes the init go "by the book" in more # ways, and formalizes one quirk. # # Various OHCI init/reset cleanups for different silicion environments: # # - Reset a bit more "by the book". # # * Define a new quirk flag for the SiS and OPTi problem seen earlier. # Since 2.4 we've always worked around that quirk, even though we've # not seen that on other chips; but it's "wrong" and doesn't work on # some chips (notably NetSilicon NS9750). # # The quirk still seems to be needed for SiS, but either this test # machine is too fast for the OPTi problem to show up, or the frame # timing setup problem there came from a now-fixed bug. # # * Look at the HC state before resetting it; depending on whether # it was previously owned by BIOS, SMM, an OS, or nobody, different # USB signaling (and timings) might be needed. # # * Re-init the frame timings right after soft reset, rather than # later (potentially too much later). # # * Restore a reset in the PCI startup code, so this logic more closely # resembles the non-PCI paths (future code sharing). It also makes it # easier to guarantee a 1-millisecond ceiling between reset and "go". # # An earlier reset is being done to help workaround BIOS-related # problems on some boards, but we may need an even earlier one # (as a PCI quirk, before IRQs get reconfigured). # # - Add an explicit #define to disable the BIOS/SMM handoff; it's # not just HPPA, many embedded chips don't expect BIOS either. # # - There are reports of AMD 756 machines disliking the OHCI suspend # patch of a few months back. Erratum #10 partly explains that, so # now root hubs won't autosuspend on those Slot-A era chips. # # - Other minor fixes # # * We've got lots of non-PCI OHCI now too, so comments shouldn't # be assuming all-is-pci! # # * Hey, it's unsafe to call hc_reset() in IRQ (after unrecoverable # error); so just force a soft reset, don't do the whole thing. # # Tested on half a dozen different OHCI versions, but maybe some other # versions of OHCI will be sensitive to one of these changes. # # Signed-off-by: David Brownell # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/host/ohci.h # 2004/09/02 18:39:10+02:00 david-b@pacbell.net +1 -0 # USB: OHCI init cleanups # # drivers/usb/host/ohci-pci.c # 2004/09/02 18:39:10+02:00 david-b@pacbell.net +18 -0 # USB: OHCI init cleanups # # drivers/usb/host/ohci-hcd.c # 2004/09/02 18:39:09+02:00 david-b@pacbell.net +52 -22 # USB: OHCI init cleanups # # ChangeSet # 2004/09/03 13:29:11+02:00 alborchers@steinerpoint.com # [PATCH] USB: corrected digi_acceleport 2.6.9-rc1 fix for hang on disconnect # # - Fixed hang on disconnect in digi_acceleport USB serial driver. # See http://bugme.osdl.org/show_bug.cgi?id=2459. Close after # disconnect no longer tries to communicate with the device. # # Signed-off-by: Al Borchers # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/serial/digi_acceleport.c # 2004/09/03 10:43:16+02:00 alborchers@steinerpoint.com +6 -1 # USB: corrected digi_acceleport 2.6.9-rc1 fix for hang on disconnect # # ChangeSet # 2004/09/03 13:28:34+02:00 oliver@neukum.org # [PATCH] USB: switching microtek to usb_kill_urb # # Am Dienstag, 31. August 2004 17:41 schrieb Alan Stern: # > On Tue, 31 Aug 2004, Oliver Neukum wrote: # > # > Alan Stern # > # > # > # > # > > @@ -822,9 +822,8 @@ # > > # > > usb_set_intfdata(intf, NULL); # > > # > > + usb_kill_urb(desc->urb); # > > scsi_remove_host(desc->host); # > > - usb_unlink_urb(desc->urb); # > > - scsi_host_put(desc->host); # > > # > > usb_free_urb(desc->urb); # > > kfree(desc); # > # > I think you still need the scsi_host_put(), to account for the fact that # > scsi_host_alloc() sets the refcount to 1 initially. # # Right you are. Greg, please also apply this one. # # Signed-Off-By: Oliver Neukum # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/image/microtek.c # 2004/08/31 21:10:57+02:00 oliver@neukum.org +1 -0 # USB: switching microtek to usb_kill_urb # # ChangeSet # 2004/09/03 13:28:02+02:00 petkan@nucleusys.com # [PATCH] USB: small rtl8150 patch # # this one make rtl8150 auto-load its register values at reset. Not doing # so is known to cause improper setup when the device is being reseted # frequently. # # # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/net/rtl8150.c # 2004/08/27 10:50:54+02:00 petkan@nucleusys.com +2 -2 # USB: small rtl8150 patch # # ChangeSet # 2004/09/03 13:27:27+02:00 wouter-kernel@fort-knox.rave.org # [PATCH] USB: usb audio is for oss only # # Doh. Fixed. # # drivers/usb/class/Kconfig # 2004/08/27 16:45:25+02:00 wouter-kernel@fort-knox.rave.org +2 -1 # USB: usb audio is for oss only # # ChangeSet # 2004/09/03 13:26:56+02:00 oliver@neukum.org # [PATCH] USB: correct interrupt interval for kaweth # # - overriding the media check interrupt interval # # Signed-Off-By: Oliver Neukum # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/net/kaweth.c # 2004/08/29 15:08:48+02:00 oliver@neukum.org +1 -1 # USB: correct interrupt interval for kaweth # # ChangeSet # 2004/09/03 13:26:21+02:00 stern@rowland.harvard.edu # [PATCH] USB: Suspend/resume/wakeup support for UHCI root hub ports # # This patch adds support for suspending, resuming, and remote wakeup # detection on root hub ports to the UHCI driver. It doesn't add support # for suspending or resuming the root hub itself (beyond what's already # there) -- that will require considerably more work. But at least devices # plugged directly into the computer will interact nicely with power # management. # # Of lesser importance, the patch also simplifies some constant expressions. # # # Signed-off-by: Alan Stern # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/host/uhci-hub.c # 2004/08/27 18:33:25+02:00 stern@rowland.harvard.edu +65 -26 # USB: Suspend/resume/wakeup support for UHCI root hub ports # # drivers/usb/host/uhci-hcd.h # 2004/08/27 18:33:25+02:00 stern@rowland.harvard.edu +6 -0 # USB: Suspend/resume/wakeup support for UHCI root hub ports # # drivers/usb/host/uhci-hcd.c # 2004/08/27 18:33:25+02:00 stern@rowland.harvard.edu +2 -0 # USB: Suspend/resume/wakeup support for UHCI root hub ports # # ChangeSet # 2004/09/03 13:25:50+02:00 stern@rowland.harvard.edu # [PATCH] USB: Make usbcore use usb_kill_urb() # # This patch changes the only places in usbcore where usb_unlink_urb() is # still used for synchronous unlinking; now they will use usb_kill_urb(). # As it turns out, there were only a couple of changes needed. # # This still leaves all the drivers to audit! # # Signed-off-by: Alan Stern # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/core/devio.c # 2004/08/30 13:34:24+02:00 stern@rowland.harvard.edu +4 -3 # USB: Make usbcore use usb_kill_urb() # # ChangeSet # 2004/09/03 13:25:14+02:00 zaitcev@redhat.com # [PATCH] USB: Fixes for ub in 2.4.9-rc1 from Oliver and Pat # # - Set the allocation size in REQUEST SENSE (Pat LaVarre) # - Move add_timer invocations to safer places (Oliver Neukum) # # # Signed-off-by: Greg Kroah-Hartman # # drivers/block/ub.c # 2004/08/27 21:24:25+02:00 zaitcev@redhat.com +32 -27 # USB: Fixes for ub in 2.4.9-rc1 from Oliver and Pat # # ChangeSet # 2004/09/03 13:24:41+02:00 oliver@neukum.org # [PATCH] USB: switching microtek to usb_kill_urb # # this reworks the microtek driver's disconnect method, now that # usb_kill_urb is available. # # Signed-Off-By: Oliver Neukum # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/image/microtek.c # 2004/08/30 23:10:24+02:00 oliver@neukum.org +2 -3 # USB: switching microtek to usb_kill_urb # # ChangeSet # 2004/09/03 13:24:05+02:00 oliver@neukum.org # [PATCH] USB: update of help text for hpusbscsi # # Signed-Off-By: Oliver Neukum # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/image/Kconfig # 2004/08/30 21:05:25+02:00 oliver@neukum.org +4 -3 # USB: update of help text for hpusbscsi # # ChangeSet # 2004/08/31 14:05:55-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb # # MAINTAINERS # 2004/08/31 14:05:51-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/08/28 16:26:13-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb # # MAINTAINERS # 2004/08/28 16:26:10-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/08/27 23:57:59-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb # # drivers/usb/gadget/inode.c # 2004/08/27 23:57:54-07:00 akpm@bix.(none) +0 -0 # Auto merged # # MAINTAINERS # 2004/08/27 23:57:54-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/08/27 14:14:37-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb # # include/linux/fs.h # 2004/08/27 14:14:34-07:00 akpm@bix.(none) +0 -0 # Auto merged # # MAINTAINERS # 2004/08/27 14:14:34-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/08/26 20:00:22-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb # # drivers/usb/gadget/inode.c # 2004/08/26 20:00:18-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/usb/core/message.c # 2004/08/26 20:00:18-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/08/25 19:43:53-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb # # drivers/usb/misc/auerswald.c # 2004/08/25 19:43:48-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/usb/gadget/inode.c # 2004/08/25 19:43:48-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/usb/core/message.c # 2004/08/25 19:43:48-07:00 akpm@bix.(none) +0 -0 # Auto merged # # MAINTAINERS # 2004/08/25 19:43:48-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/08/24 17:51:22-07:00 akpm@bix.(none) # Merge bk://kernel.bkbits.net/gregkh/linux/usb-2.6 # into bix.(none):/usr/src/bk-usb # # drivers/usb/misc/legousbtower.c # 2004/08/24 17:51:16-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/08/24 17:50:09-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb # # include/linux/fs.h # 2004/08/24 17:50:05-07:00 akpm@bix.(none) +0 -0 # Auto merged # # MAINTAINERS # 2004/08/24 17:50:05-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/08/23 17:04:36-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb # # include/linux/fs.h # 2004/08/23 17:04:32-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/usb/misc/auerswald.c # 2004/08/23 17:04:32-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/usb/media/dabusb.c # 2004/08/23 17:04:32-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/block/Kconfig # 2004/08/23 17:04:32-07:00 akpm@bix.(none) +0 -0 # Auto merged # # MAINTAINERS # 2004/08/23 17:04:32-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/08/23 14:47:21-07:00 akpm@bix.(none) # Merge bk://kernel.bkbits.net/gregkh/linux/usb-2.6 # into bix.(none):/usr/src/bk-usb # # include/linux/fs.h # 2004/08/23 14:47:18-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/usb/misc/tiglusb.c # 2004/08/23 14:47:18-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/usb/misc/legousbtower.c # 2004/08/23 14:47:18-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/usb/misc/auerswald.c # 2004/08/23 14:47:18-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/usb/media/ov511.c # 2004/08/23 14:47:18-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/usb/media/dabusb.c # 2004/08/23 14:47:18-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/usb/class/usb-midi.c # 2004/08/23 14:47:18-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/usb/class/audio.c # 2004/08/23 14:47:18-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/block/Kconfig # 2004/08/23 14:47:18-07:00 akpm@bix.(none) +0 -0 # Auto merged # # MAINTAINERS # 2004/08/23 14:47:17-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/08/23 14:46:26-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb # # include/linux/fs.h # 2004/08/23 14:46:22-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/usb/misc/auerswald.c # 2004/08/23 14:46:22-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/usb/media/dabusb.c # 2004/08/23 14:46:22-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/block/Kconfig # 2004/08/23 14:46:22-07:00 akpm@bix.(none) +0 -0 # Auto merged # # MAINTAINERS # 2004/08/23 14:46:22-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/08/22 21:47:19-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb # # MAINTAINERS # 2004/08/22 21:47:15-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/08/15 01:35:04-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb # # include/linux/fs.h # 2004/08/15 01:35:01-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/08/08 14:55:28-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb # # drivers/usb/misc/tiglusb.c # 2004/08/08 14:55:24-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/usb/misc/legousbtower.c # 2004/08/08 14:55:24-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/usb/misc/auerswald.c # 2004/08/08 14:55:24-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/usb/media/dabusb.c # 2004/08/08 14:55:24-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/usb/class/usb-midi.c # 2004/08/08 14:55:24-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/usb/class/audio.c # 2004/08/08 14:55:24-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/08/08 02:33:24-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb # # include/linux/fs.h # 2004/08/08 02:33:20-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/08/07 19:17:31-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb # # include/linux/fs.h # 2004/08/07 19:17:28-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/08/07 14:49:01-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb # # include/linux/fs.h # 2004/08/07 14:48:57-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/08/06 16:01:52-07:00 akpm@bix.(none) # Merge bk://kernel.bkbits.net/gregkh/linux/usb-2.6 # into bix.(none):/usr/src/bk-usb # # drivers/block/Kconfig # 2004/08/06 16:01:49-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/08/06 16:01:00-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb # # include/linux/fs.h # 2004/08/06 16:00:56-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/08/05 20:16:41-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb # # include/linux/fs.h # 2004/08/05 20:16:38-07:00 akpm@bix.(none) +0 -0 # Auto merged # # MAINTAINERS # 2004/08/05 20:16:38-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/08/05 13:06:30-07:00 akpm@bix.(none) # Merge bk://kernel.bkbits.net/gregkh/linux/usb-2.6 # into bix.(none):/usr/src/bk-usb # # drivers/usb/media/ov511.c # 2004/08/05 13:06:26-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/08/04 03:03:16-07:00 akpm@bix.(none) # Merge bk://kernel.bkbits.net/gregkh/linux/usb-2.6 # into bix.(none):/usr/src/bk-usb # # drivers/usb/misc/tiglusb.c # 2004/08/04 03:03:12-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/usb/media/ov511.c # 2004/08/04 03:03:12-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/08/02 13:35:47-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb # # MAINTAINERS # 2004/08/02 13:35:43-07:00 akpm@bix.(none) +0 -0 # Auto merged # diff -Nru a/drivers/block/ub.c b/drivers/block/ub.c --- a/drivers/block/ub.c 2004-09-06 17:33:19 -07:00 +++ b/drivers/block/ub.c 2004-09-06 17:33:19 -07:00 @@ -786,17 +786,16 @@ sc->work_urb.error_count = 0; sc->work_urb.status = 0; - sc->work_timer.expires = jiffies + UB_URB_TIMEOUT; - add_timer(&sc->work_timer); - if ((rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC)) != 0) { /* XXX Clear stalls */ printk("ub: cmd #%d start failed (%d)\n", cmd->tag, rc); /* P3 */ - del_timer(&sc->work_timer); ub_complete(&sc->work_done); return rc; } + sc->work_timer.expires = jiffies + UB_URB_TIMEOUT; + add_timer(&sc->work_timer); + cmd->state = UB_CMDST_CMD; ub_cmdtr_state(sc, cmd); return 0; @@ -968,18 +967,17 @@ sc->work_urb.error_count = 0; sc->work_urb.status = 0; - sc->work_timer.expires = jiffies + UB_URB_TIMEOUT; - add_timer(&sc->work_timer); - if ((rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC)) != 0) { /* XXX Clear stalls */ printk("ub: data #%d submit failed (%d)\n", cmd->tag, rc); /* P3 */ - del_timer(&sc->work_timer); ub_complete(&sc->work_done); ub_state_done(sc, cmd, rc); return; } + sc->work_timer.expires = jiffies + UB_URB_TIMEOUT; + add_timer(&sc->work_timer); + cmd->state = UB_CMDST_DATA; ub_cmdtr_state(sc, cmd); @@ -1063,19 +1061,18 @@ sc->work_urb.error_count = 0; sc->work_urb.status = 0; - sc->work_timer.expires = jiffies + UB_URB_TIMEOUT; - add_timer(&sc->work_timer); - rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC); if (rc != 0) { /* XXX Clear stalls */ printk("%s: CSW #%d submit failed (%d)\n", sc->name, cmd->tag, rc); /* P3 */ - del_timer(&sc->work_timer); ub_complete(&sc->work_done); ub_state_done(sc, cmd, rc); return; } + + sc->work_timer.expires = jiffies + UB_URB_TIMEOUT; + add_timer(&sc->work_timer); return; } @@ -1186,18 +1183,17 @@ sc->work_urb.error_count = 0; sc->work_urb.status = 0; - sc->work_timer.expires = jiffies + UB_URB_TIMEOUT; - add_timer(&sc->work_timer); - if ((rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC)) != 0) { /* XXX Clear stalls */ printk("ub: CSW #%d submit failed (%d)\n", cmd->tag, rc); /* P3 */ - del_timer(&sc->work_timer); ub_complete(&sc->work_done); ub_state_done(sc, cmd, rc); return; } + sc->work_timer.expires = jiffies + UB_URB_TIMEOUT; + add_timer(&sc->work_timer); + cmd->stat_count = 0; cmd->state = UB_CMDST_STAT; ub_cmdtr_state(sc, cmd); @@ -1217,9 +1213,17 @@ goto error; } + /* + * ``If the allocation length is eighteen or greater, and a device + * server returns less than eithteen bytes of data, the application + * client should assume that the bytes not transferred would have been + * zeroes had the device server returned those bytes.'' + */ memset(&sc->top_sense, 0, UB_SENSE_SIZE); + scmd = &sc->top_rqs_cmd; scmd->cdb[0] = REQUEST_SENSE; + scmd->cdb[4] = UB_SENSE_SIZE; scmd->cdb_len = 6; scmd->dir = UB_DIR_READ; scmd->state = UB_CMDST_INIT; @@ -1271,14 +1275,13 @@ sc->work_urb.error_count = 0; sc->work_urb.status = 0; - sc->work_timer.expires = jiffies + UB_CTRL_TIMEOUT; - add_timer(&sc->work_timer); - if ((rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC)) != 0) { - del_timer(&sc->work_timer); ub_complete(&sc->work_done); return rc; } + + sc->work_timer.expires = jiffies + UB_CTRL_TIMEOUT; + add_timer(&sc->work_timer); return 0; } @@ -1289,6 +1292,9 @@ unsigned char *sense = scmd->data; struct ub_scsi_cmd *cmd; + /* + * Ignoring scmd->act_len, because the buffer was pre-zeroed. + */ ub_cmdtr_sense(sc, scmd, sense); if ((cmd = ub_cmdq_peek(sc)) == NULL) { @@ -1725,18 +1731,17 @@ sc->work_urb.error_count = 0; sc->work_urb.status = 0; - init_timer(&timer); - timer.function = ub_probe_timeout; - timer.data = (unsigned long) &compl; - timer.expires = jiffies + UB_CTRL_TIMEOUT; - add_timer(&timer); - if ((rc = usb_submit_urb(&sc->work_urb, GFP_KERNEL)) != 0) { printk(KERN_WARNING "%s: Unable to submit a probe clear (%d)\n", sc->name, rc); - del_timer_sync(&timer); return rc; } + + init_timer(&timer); + timer.function = ub_probe_timeout; + timer.data = (unsigned long) &compl; + timer.expires = jiffies + UB_CTRL_TIMEOUT; + add_timer(&timer); wait_for_completion(&compl); diff -Nru a/drivers/usb/class/Kconfig b/drivers/usb/class/Kconfig --- a/drivers/usb/class/Kconfig 2004-09-06 17:33:19 -07:00 +++ b/drivers/usb/class/Kconfig 2004-09-06 17:33:19 -07:00 @@ -9,7 +9,8 @@ depends on USB && SOUND help Say Y here if you want to connect USB audio equipment such as - speakers to your computer's USB port. + speakers to your computer's USB port. You only need this if you use + the OSS sound driver; ALSA has its own option for usb audio support. To compile this driver as a module, choose M here: the module will be called audio. diff -Nru a/drivers/usb/class/audio.c b/drivers/usb/class/audio.c --- a/drivers/usb/class/audio.c 2004-09-06 17:33:19 -07:00 +++ b/drivers/usb/class/audio.c 2004-09-06 17:33:19 -07:00 @@ -1949,15 +1949,12 @@ static int usb_audio_open_mixdev(struct inode *inode, struct file *file) { unsigned int minor = iminor(inode); - struct list_head *devs, *mdevs; struct usb_mixerdev *ms; struct usb_audio_state *s; down(&open_sem); - list_for_each(devs, &audiodevs) { - s = list_entry(devs, struct usb_audio_state, audiodev); - list_for_each(mdevs, &s->mixerlist) { - ms = list_entry(mdevs, struct usb_mixerdev, list); + list_for_each_entry(s, &audiodevs, audiodev) { + list_for_each_entry(ms, &s->mixerlist, list) { if (ms->dev_mixer == minor) goto mixer_found; } @@ -2634,16 +2631,13 @@ { unsigned int minor = iminor(inode); DECLARE_WAITQUEUE(wait, current); - struct list_head *devs, *adevs; struct usb_audiodev *as; struct usb_audio_state *s; for (;;) { down(&open_sem); - list_for_each(devs, &audiodevs) { - s = list_entry(devs, struct usb_audio_state, audiodev); - list_for_each(adevs, &s->audiolist) { - as = list_entry(adevs, struct usb_audiodev, list); + list_for_each_entry(s, &audiodevs, audiodev) { + list_for_each_entry(as, &s->audiolist, list) { if (!((as->dev_audio ^ minor) & ~0xf)) goto device_found; } @@ -3809,7 +3803,6 @@ static void usb_audio_disconnect(struct usb_interface *intf) { struct usb_audio_state *s = usb_get_intfdata (intf); - struct list_head *list; struct usb_audiodev *as; struct usb_mixerdev *ms; @@ -3831,8 +3824,7 @@ usb_set_intfdata (intf, NULL); /* deregister all audio and mixer devices, so no new processes can open this device */ - list_for_each(list, &s->audiolist) { - as = list_entry(list, struct usb_audiodev, list); + list_for_each_entry(as, &s->audiolist, list) { usbin_disc(as); usbout_disc(as); wake_up(&as->usbin.dma.wait); @@ -3843,8 +3835,7 @@ } as->dev_audio = -1; } - list_for_each(list, &s->mixerlist) { - ms = list_entry(list, struct usb_mixerdev, list); + list_for_each_entry(ms, &s->mixerlist, list) { if (ms->dev_mixer >= 0) { unregister_sound_mixer(ms->dev_mixer); printk(KERN_INFO "usbaudio: unregister mixer 14,%d\n", ms->dev_mixer); diff -Nru a/drivers/usb/class/usb-midi.c b/drivers/usb/class/usb-midi.c --- a/drivers/usb/class/usb-midi.c 2004-09-06 17:33:19 -07:00 +++ b/drivers/usb/class/usb-midi.c 2004-09-06 17:33:19 -07:00 @@ -805,7 +805,6 @@ { int minor = iminor(inode); DECLARE_WAITQUEUE(wait, current); - struct list_head *devs, *mdevs; struct usb_midi_state *s; struct usb_mididev *m; unsigned long flags; @@ -817,10 +816,8 @@ for(;;) { down(&open_sem); - list_for_each(devs, &mididevs) { - s = list_entry(devs, struct usb_midi_state, mididev); - list_for_each(mdevs, &s->midiDevList) { - m = list_entry(mdevs, struct usb_mididev, list); + list_for_each_entry(s, &mididevs, mididev) { + list_for_each_entry(m, &s->midiDevList, list) { if ( !((m->dev_midi ^ minor) & ~0xf) ) goto device_found; } @@ -1994,7 +1991,6 @@ static void usb_midi_disconnect(struct usb_interface *intf) { struct usb_midi_state *s = usb_get_intfdata (intf); - struct list_head *list; struct usb_mididev *m; if ( !s ) @@ -2012,8 +2008,7 @@ s->usbdev = NULL; usb_set_intfdata (intf, NULL); - list_for_each(list, &s->midiDevList) { - m = list_entry(list, struct usb_mididev, list); + list_for_each_entry(m, &s->midiDevList, list) { wake_up(&(m->min.ep->wait)); wake_up(&(m->mout.ep->wait)); if ( m->dev_midi >= 0 ) { diff -Nru a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c --- a/drivers/usb/core/devices.c 2004-09-06 17:33:19 -07:00 +++ b/drivers/usb/core/devices.c 2004-09-06 17:33:19 -07:00 @@ -149,7 +149,7 @@ /*****************************************************************/ -void usbdevfs_conn_disc_event(void) +void usbfs_conn_disc_event(void) { conndiscevcnt++; wake_up(&deviceconndiscwq); @@ -569,7 +569,6 @@ static ssize_t usb_device_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos) { - struct list_head *buslist; struct usb_bus *bus; ssize_t ret, total_written = 0; loff_t skip_bytes = *ppos; @@ -581,12 +580,9 @@ if (!access_ok(VERIFY_WRITE, buf, nbytes)) return -EFAULT; - /* enumerate busses */ down (&usb_bus_list_lock); - list_for_each(buslist, &usb_bus_list) { - /* print devices for this bus */ - bus = list_entry(buslist, struct usb_bus, bus_list); - + /* print devices for all busses */ + list_for_each_entry(bus, &usb_bus_list, bus_list) { /* recurse through all children of the root hub */ if (!bus->root_hub) continue; @@ -682,7 +678,7 @@ return ret; } -struct file_operations usbdevfs_devices_fops = { +struct file_operations usbfs_devices_fops = { .llseek = usb_device_lseek, .read = usb_device_read, .poll = usb_device_poll, diff -Nru a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c --- a/drivers/usb/core/devio.c 2004-09-06 17:33:19 -07:00 +++ b/drivers/usb/core/devio.c 2004-09-06 17:33:19 -07:00 @@ -21,7 +21,7 @@ * * $Id: devio.c,v 1.7 2000/02/01 17:28:48 fliegl Exp $ * - * This file implements the usbdevfs/x/y files, where + * This file implements the usbfs/x/y files, where * x is the bus number and y the device number. * * It allows user space programs/"drivers" to communicate directly @@ -286,9 +286,10 @@ while (!list_empty(list)) { as = list_entry(list->next, struct async, asynclist); list_del_init(&as->asynclist); + + /* drop the spinlock so the completion handler can run */ spin_unlock_irqrestore(&ps->lock, flags); - /* usb_unlink_urb calls the completion handler with status == -ENOENT */ - usb_unlink_urb(as->urb); + usb_kill_urb(as->urb); spin_lock_irqsave(&ps->lock, flags); } spin_unlock_irqrestore(&ps->lock, flags); @@ -353,7 +354,7 @@ destroy_async_on_interface(ps, ifnum); } -struct usb_driver usbdevfs_driver = { +struct usb_driver usbfs_driver = { .owner = THIS_MODULE, .name = "usbfs", .probe = driver_probe, @@ -378,7 +379,7 @@ if (!intf) err = -ENOENT; else - err = usb_driver_claim_interface(&usbdevfs_driver, intf, ps); + err = usb_driver_claim_interface(&usbfs_driver, intf, ps); up_write(&usb_bus_type.subsys.rwsem); if (err == 0) set_bit(ifnum, &ps->ifclaimed); @@ -401,7 +402,7 @@ if (!intf) err = -ENOENT; else if (test_and_clear_bit(ifnum, &ps->ifclaimed)) { - usb_driver_release_interface(&usbdevfs_driver, intf); + usb_driver_release_interface(&usbfs_driver, intf); err = 0; } up_write(&usb_bus_type.subsys.rwsem); @@ -976,7 +977,7 @@ as = async_getpending(ps, arg); if (!as) return -EINVAL; - usb_unlink_urb(as->urb); + usb_kill_urb(as->urb); return 0; } @@ -1314,7 +1315,7 @@ return mask; } -struct file_operations usbdevfs_device_file_operations = { +struct file_operations usbfs_device_file_operations = { .llseek = usbdev_lseek, .read = usbdev_read, .poll = usbdev_poll, diff -Nru a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c --- a/drivers/usb/core/hcd-pci.c 2004-09-06 17:33:19 -07:00 +++ b/drivers/usb/core/hcd-pci.c 2004-09-06 17:33:19 -07:00 @@ -188,9 +188,9 @@ } hcd->irq = dev->irq; - dev_info (hcd->self.controller, "irq %s, %s %p\n", bufp, + dev_info (hcd->self.controller, "irq %s, %s 0x%lx\n", bufp, (driver->flags & HCD_MEMORY) ? "pci mem" : "io base", - base); + resource); usb_bus_init (&hcd->self); hcd->self.op = &usb_hcd_operations; diff -Nru a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c --- a/drivers/usb/core/hub.c 2004-09-06 17:33:19 -07:00 +++ b/drivers/usb/core/hub.c 2004-09-06 17:33:19 -07:00 @@ -1384,7 +1384,6 @@ int ret; if (hdev->children[port]) { - /* FIXME need disconnect() for NOTATTACHED device */ usb_set_device_state(hdev->children[port], USB_STATE_NOTATTACHED); } @@ -1396,6 +1395,30 @@ return ret; } +/* + * Disable a port and mark a logical connnect-change event, so that some + * time later khubd will disconnect() any existing usb_device on the port + * and will re-enumerate if there actually is a device attached. + */ +static void hub_port_logical_disconnect(struct usb_device *hdev, int port) +{ + struct usb_hub *hub; + + dev_dbg(hubdev(hdev), "logical disconnect on port %d\n", port + 1); + hub_port_disable(hdev, port); + + hub = usb_get_intfdata(hdev->actconfig->interface[0]); + set_bit(port, hub->change_bits); + + spin_lock_irq(&hub_event_lock); + if (list_empty(&hub->event_list)) { + list_add_tail(&hub->event_list, &hub_event_list); + wake_up(&khubd_wait); + } + spin_unlock_irq(&hub_event_lock); +} + + #ifdef CONFIG_USB_SUSPEND /* @@ -1729,7 +1752,7 @@ } } if (status < 0) - status = hub_port_disable(hdev, port); + hub_port_logical_disconnect(hdev, port - 1); return status; } @@ -1869,11 +1892,11 @@ status = hub_port_resume(hdev, port + 1); else { status = finish_port_resume(udev); - if (status < 0) - status = hub_port_disable(hdev, port); - if (status < 0) + if (status < 0) { dev_dbg(&intf->dev, "resume port %d --> %d\n", - port, status); + port + 1, status); + hub_port_logical_disconnect(hdev, port); + } } up(&udev->serialize); } @@ -2502,15 +2525,17 @@ if (portchange & USB_PORT_STAT_C_SUSPEND) { clear_port_feature(hdev, i + 1, USB_PORT_FEAT_C_SUSPEND); - if (hdev->children[i]) + if (hdev->children[i]) { ret = remote_wakeup(hdev->children[i]); - else + if (ret < 0) + connect_change = 1; + } else { ret = -ENODEV; + hub_port_disable(hdev, i); + } dev_dbg (hub_dev, "resume on port %d, status %d\n", i + 1, ret); - if (ret < 0) - ret = hub_port_disable(hdev, i); } if (portchange & USB_PORT_STAT_C_OVERCURRENT) { @@ -2713,7 +2738,6 @@ struct usb_device *parent = udev->parent; struct usb_device_descriptor descriptor = udev->descriptor; int i, ret, port = -1; - struct usb_hub *hub; if (udev->state == USB_STATE_NOTATTACHED || udev->state == USB_STATE_SUSPENDED) { @@ -2794,18 +2818,7 @@ return 0; re_enumerate: - hub_port_disable(parent, port); - - hub = usb_get_intfdata(parent->actconfig->interface[0]); - set_bit(port, hub->change_bits); - - spin_lock_irq(&hub_event_lock); - if (list_empty(&hub->event_list)) { - list_add_tail(&hub->event_list, &hub_event_list); - wake_up(&khubd_wait); - } - spin_unlock_irq(&hub_event_lock); - + hub_port_logical_disconnect(parent, port); return -ENODEV; } EXPORT_SYMBOL(__usb_reset_device); diff -Nru a/drivers/usb/core/inode.c b/drivers/usb/core/inode.c --- a/drivers/usb/core/inode.c 2004-09-06 17:33:19 -07:00 +++ b/drivers/usb/core/inode.c 2004-09-06 17:33:19 -07:00 @@ -4,7 +4,7 @@ * inode.c -- Inode/Dentry functions for the USB device file system. * * Copyright (C) 2000 Thomas Sailer (sailer@ife.ee.ethz.ch) - * Copyright (C) 2001,2002 Greg Kroah-Hartman (greg@kroah.com) + * Copyright (C) 2001,2002,2004 Greg Kroah-Hartman (greg@kroah.com) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -40,17 +40,15 @@ #include #include #include +#include "usb.h" static struct super_operations usbfs_ops; static struct file_operations default_file_operations; static struct inode_operations usbfs_dir_inode_operations; -static struct vfsmount *usbdevfs_mount; static struct vfsmount *usbfs_mount; -static int usbdevfs_mount_count; /* = 0 */ static int usbfs_mount_count; /* = 0 */ static int ignore_mount = 0; -static struct dentry *devices_usbdevfs_dentry; static struct dentry *devices_usbfs_dentry; static int num_buses; /* = 0 */ @@ -240,9 +238,6 @@ if (usbfs_mount && usbfs_mount->mnt_sb) update_sb(usbfs_mount->mnt_sb); - if (usbdevfs_mount && usbdevfs_mount->mnt_sb) - update_sb(usbdevfs_mount->mnt_sb); - return 0; } @@ -561,28 +556,12 @@ /* --------------------------------------------------------------------- */ - - -/* - * The usbdevfs name is now deprecated (as of 2.5.1). - * It will be removed when the 2.7.x development cycle is started. - * You have been warned :) - */ -static struct file_system_type usbdevice_fs_type; - static struct super_block *usb_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *data) { return get_sb_single(fs_type, flags, data, usbfs_fill_super); } -static struct file_system_type usbdevice_fs_type = { - .owner = THIS_MODULE, - .name = "usbdevfs", - .get_sb = usb_get_sb, - .kill_sb = kill_litter_super, -}; - static struct file_system_type usb_fs_type = { .owner = THIS_MODULE, .name = "usbfs", @@ -603,16 +582,10 @@ ignore_mount = 1; /* create the devices special file */ - retval = simple_pin_fs("usbdevfs", &usbdevfs_mount, &usbdevfs_mount_count); - if (retval) { - err ("Unable to get usbdevfs mount"); - goto exit; - } - retval = simple_pin_fs("usbfs", &usbfs_mount, &usbfs_mount_count); if (retval) { err ("Unable to get usbfs mount"); - goto error_clean_usbdevfs_mount; + goto exit; } ignore_mount = 0; @@ -620,7 +593,7 @@ parent = usbfs_mount->mnt_sb->s_root; devices_usbfs_dentry = fs_create_file ("devices", listmode | S_IFREG, parent, - NULL, &usbdevfs_devices_fops, + NULL, &usbfs_devices_fops, listuid, listgid); if (devices_usbfs_dentry == NULL) { err ("Unable to create devices usbfs file"); @@ -628,42 +601,19 @@ goto error_clean_mounts; } - parent = usbdevfs_mount->mnt_sb->s_root; - devices_usbdevfs_dentry = fs_create_file ("devices", - listmode | S_IFREG, parent, - NULL, &usbdevfs_devices_fops, - listuid, listgid); - if (devices_usbdevfs_dentry == NULL) { - err ("Unable to create devices usbfs file"); - retval = -ENODEV; - goto error_remove_file; - } - goto exit; -error_remove_file: - fs_remove_file (devices_usbfs_dentry); - devices_usbfs_dentry = NULL; - error_clean_mounts: simple_release_fs(&usbfs_mount, &usbfs_mount_count); - -error_clean_usbdevfs_mount: - simple_release_fs(&usbdevfs_mount, &usbdevfs_mount_count); - exit: return retval; } static void remove_special_files (void) { - if (devices_usbdevfs_dentry) - fs_remove_file (devices_usbdevfs_dentry); if (devices_usbfs_dentry) fs_remove_file (devices_usbfs_dentry); - devices_usbdevfs_dentry = NULL; devices_usbfs_dentry = NULL; - simple_release_fs(&usbdevfs_mount, &usbdevfs_mount_count); simple_release_fs(&usbfs_mount, &usbfs_mount_count); } @@ -671,11 +621,6 @@ { struct inode *inode; - if (devices_usbdevfs_dentry) { - inode = devices_usbdevfs_dentry->d_inode; - if (inode) - inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; - } if (devices_usbfs_dentry) { inode = devices_usbfs_dentry->d_inode; if (inode) @@ -707,29 +652,16 @@ return; } - parent = usbdevfs_mount->mnt_sb->s_root; - bus->usbdevfs_dentry = fs_create_file (name, busmode | S_IFDIR, parent, - bus, NULL, busuid, busgid); - if (bus->usbdevfs_dentry == NULL) { - err ("error creating usbdevfs bus entry"); - return; - } - usbfs_update_special(); - usbdevfs_conn_disc_event(); + usbfs_conn_disc_event(); } - void usbfs_remove_bus(struct usb_bus *bus) { if (bus->usbfs_dentry) { fs_remove_file (bus->usbfs_dentry); bus->usbfs_dentry = NULL; } - if (bus->usbdevfs_dentry) { - fs_remove_file (bus->usbdevfs_dentry); - bus->usbdevfs_dentry = NULL; - } --num_buses; if (num_buses <= 0) { @@ -738,7 +670,7 @@ } usbfs_update_special(); - usbdevfs_conn_disc_event(); + usbfs_conn_disc_event(); } void usbfs_add_device(struct usb_device *dev) @@ -750,20 +682,12 @@ sprintf (name, "%03d", dev->devnum); dev->usbfs_dentry = fs_create_file (name, devmode | S_IFREG, dev->bus->usbfs_dentry, dev, - &usbdevfs_device_file_operations, + &usbfs_device_file_operations, devuid, devgid); if (dev->usbfs_dentry == NULL) { err ("error creating usbfs device entry"); return; } - dev->usbdevfs_dentry = fs_create_file (name, devmode | S_IFREG, - dev->bus->usbdevfs_dentry, dev, - &usbdevfs_device_file_operations, - devuid, devgid); - if (dev->usbdevfs_dentry == NULL) { - err ("error creating usbdevfs device entry"); - return; - } /* Set the size of the device's file to be * equal to the size of the device descriptors. */ @@ -775,11 +699,9 @@ } if (dev->usbfs_dentry->d_inode) dev->usbfs_dentry->d_inode->i_size = i_size; - if (dev->usbdevfs_dentry->d_inode) - dev->usbdevfs_dentry->d_inode->i_size = i_size; usbfs_update_special(); - usbdevfs_conn_disc_event(); + usbfs_conn_disc_event(); } void usbfs_remove_device(struct usb_device *dev) @@ -791,10 +713,6 @@ fs_remove_file (dev->usbfs_dentry); dev->usbfs_dentry = NULL; } - if (dev->usbdevfs_dentry) { - fs_remove_file (dev->usbdevfs_dentry); - dev->usbdevfs_dentry = NULL; - } while (!list_empty(&dev->filelist)) { ds = list_entry(dev->filelist.next, struct dev_state, list); list_del_init(&ds->list); @@ -807,51 +725,38 @@ } } usbfs_update_special(); - usbdevfs_conn_disc_event(); + usbfs_conn_disc_event(); } /* --------------------------------------------------------------------- */ -#ifdef CONFIG_PROC_FS static struct proc_dir_entry *usbdir = NULL; -#endif int __init usbfs_init(void) { int retval; - retval = usb_register(&usbdevfs_driver); + retval = usb_register(&usbfs_driver); if (retval) return retval; retval = register_filesystem(&usb_fs_type); if (retval) { - usb_deregister(&usbdevfs_driver); - return retval; - } - retval = register_filesystem(&usbdevice_fs_type); - if (retval) { - unregister_filesystem(&usb_fs_type); - usb_deregister(&usbdevfs_driver); + usb_deregister(&usbfs_driver); return retval; } -#ifdef CONFIG_PROC_FS - /* create mount point for usbdevfs */ + /* create mount point for usbfs */ usbdir = proc_mkdir("usb", proc_bus); -#endif return 0; } void usbfs_cleanup(void) { - usb_deregister(&usbdevfs_driver); + usb_deregister(&usbfs_driver); unregister_filesystem(&usb_fs_type); - unregister_filesystem(&usbdevice_fs_type); -#ifdef CONFIG_PROC_FS if (usbdir) remove_proc_entry("usb", proc_bus); -#endif } diff -Nru a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c --- a/drivers/usb/core/urb.c 2004-09-06 17:33:19 -07:00 +++ b/drivers/usb/core/urb.c 2004-09-06 17:33:19 -07:00 @@ -451,6 +451,9 @@ if (!urb) return -EINVAL; if (!(urb->transfer_flags & URB_ASYNC_UNLINK)) { + printk(KERN_NOTICE "usb_unlink_urb() is deprecated for " + "synchronous unlinks. Use usb_kill_urb()\n"); + WARN_ON(1); usb_kill_urb(urb); return 0; } diff -Nru a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h --- a/drivers/usb/core/usb.h 2004-09-06 17:33:19 -07:00 +++ b/drivers/usb/core/usb.h 2004-09-06 17:33:19 -07:00 @@ -27,3 +27,9 @@ /* for labeling diagnostics */ extern const char *usbcore_name; + +/* usbfs stuff */ +extern struct usb_driver usbfs_driver; +extern struct file_operations usbfs_devices_fops; +extern struct file_operations usbfs_device_file_operations; +extern void usbfs_conn_disc_event(void); diff -Nru a/drivers/usb/host/hc_sl811.c b/drivers/usb/host/hc_sl811.c --- a/drivers/usb/host/hc_sl811.c 2004-09-06 17:33:19 -07:00 +++ b/drivers/usb/host/hc_sl811.c 2004-09-06 17:33:19 -07:00 @@ -1343,15 +1343,11 @@ *****************************************************************/ static void __exit hci_hcd_cleanup (void) { - struct list_head *hci_l; - hci_t *hci; + hci_t *hci, *tmp; DBGFUNC ("Enter hci_hcd_cleanup\n"); - for (hci_l = hci_hcd_list.next; hci_l != &hci_hcd_list;) { - hci = list_entry (hci_l, hci_t, hci_hcd_list); - hci_l = hci_l->next; + list_for_each_entry_safe(hci, tmp, &hci_hcd_list, hci_hcd_list) hc_release_hci (hci); - } } module_init (hci_hcd_init); diff -Nru a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c --- a/drivers/usb/host/ohci-hcd.c 2004-09-06 17:33:19 -07:00 +++ b/drivers/usb/host/ohci-hcd.c 2004-09-06 17:33:19 -07:00 @@ -2,7 +2,7 @@ * OHCI HCD (Host Controller Driver) for USB. * * (C) Copyright 1999 Roman Weissgaerber - * (C) Copyright 2000-2002 David Brownell + * (C) Copyright 2000-2004 David Brownell * * [ Initialisation is based on Linus' ] * [ uhci code and gregs ohci fragments ] @@ -122,6 +122,16 @@ #define OHCI_INTR_INIT \ (OHCI_INTR_MIE | OHCI_INTR_UE | OHCI_INTR_RD | OHCI_INTR_WDH) +#ifdef __hppa__ +/* On PA-RISC, PDC can leave IR set incorrectly; ignore it there. */ +#define IR_DISABLE +#endif + +#ifdef CONFIG_ARCH_OMAP +/* OMAP doesn't support IR (no SMM; not needed) */ +#define IR_DISABLE +#endif + /*-------------------------------------------------------------------------*/ static const char hcd_name [] = "ohci_hcd"; @@ -407,10 +417,8 @@ /* also: power/overcurrent flags in roothub.a */ } - /* SMM owns the HC? not for long! - * On PA-RISC, PDC can leave IR set incorrectly; ignore it there. - */ -#ifndef __hppa__ +#ifndef IR_DISABLE + /* SMM owns the HC? not for long! */ if (ohci_readl (&ohci->regs->control) & OHCI_CTRL_IR) { ohci_dbg (ohci, "USB HC TakeOver from BIOS/SMM\n"); @@ -435,18 +443,40 @@ /* Disable HC interrupts */ writel (OHCI_INTR_MIE, &ohci->regs->intrdisable); - ohci_dbg (ohci, "reset, control = 0x%x\n", - ohci_readl (&ohci->regs->control)); - - /* Reset USB (needed by some controllers); RemoteWakeupConnected + /* Reset USB nearly "by the book". RemoteWakeupConnected * saved if boot firmware (BIOS/SMM/...) told us it's connected * (for OHCI integrated on mainboard, it normally is) */ ohci->hc_control = ohci_readl (&ohci->regs->control); - ohci->hc_control &= OHCI_CTRL_RWC; /* hcfs 0 = RESET */ - if (ohci->hc_control) + ohci_dbg (ohci, "resetting from state '%s', control = 0x%x\n", + hcfs2string (ohci->hc_control & OHCI_CTRL_HCFS), + ohci->hc_control); + + if (ohci->hc_control & OHCI_CTRL_RWC + && !(ohci->flags & OHCI_QUIRK_AMD756)) ohci->hcd.can_wakeup = 1; + + switch (ohci->hc_control & OHCI_CTRL_HCFS) { + case OHCI_USB_OPER: + temp = 0; + break; + case OHCI_USB_SUSPEND: + case OHCI_USB_RESUME: + ohci->hc_control &= OHCI_CTRL_RWC; + ohci->hc_control |= OHCI_USB_RESUME; + temp = 10 /* msec wait */; + break; + // case OHCI_USB_RESET: + default: + ohci->hc_control &= OHCI_CTRL_RWC; + ohci->hc_control |= OHCI_USB_RESET; + temp = 50 /* msec wait */; + break; + } writel (ohci->hc_control, &ohci->regs->control); + // flush the writes + (void) ohci_readl (&ohci->regs->control); + msleep(temp); if (power_switching) { unsigned ports = roothub_a (ohci) & RH_A_NDP; @@ -455,9 +485,8 @@ writel (RH_PS_LSDA, &ohci->regs->roothub.portstatus [temp]); } - // flush those pci writes + // flush those writes (void) ohci_readl (&ohci->regs->control); - msleep (50); /* HC Reset requires max 10 us delay */ writel (OHCI_HCR, &ohci->regs->cmdstatus); @@ -469,6 +498,7 @@ } udelay (1); } + periodic_reinit (ohci); /* now we're in the SUSPEND state ... must go OPERATIONAL * within 2msec else HC enters RESUME @@ -477,10 +507,11 @@ * (SiS, OPTi ...), so reset again instead. SiS doesn't need * this if we write fmInterval after we're OPERATIONAL. */ - writel (ohci->hc_control, &ohci->regs->control); - // flush those pci writes - (void) ohci_readl (&ohci->regs->control); - + if (ohci->flags & OHCI_QUIRK_INITRESET) { + writel (ohci->hc_control, &ohci->regs->control); + // flush those writes + (void) ohci_readl (&ohci->regs->control); + } return 0; } @@ -506,8 +537,6 @@ /* a reset clears this */ writel ((u32) ohci->hcca_dma, &ohci->regs->hcca); - periodic_reinit (ohci); - /* some OHCI implementations are finicky about how they init. * bogus values here mean not even enumeration could work. */ @@ -553,7 +582,7 @@ writel (tmp, &ohci->regs->roothub.a); writel (RH_HS_LPSC, &ohci->regs->roothub.status); writel (power_switching ? RH_B_PPCM : 0, &ohci->regs->roothub.b); - // flush those pci writes + // flush those writes (void) ohci_readl (&ohci->regs->control); // POTPGT delay is bits 24-31, in 2 ms units. @@ -620,7 +649,8 @@ // e.g. due to PCI Master/Target Abort ohci_dump (ohci, 1); - hc_reset (ohci); + ohci->hc_control &= OHCI_CTRL_RWC; /* hcfs 0 = RESET */ + writel (ohci->hc_control, &ohci->regs->control); } if (ints & OHCI_INTR_RD) { @@ -655,7 +685,7 @@ if (HCD_IS_RUNNING(ohci->hcd.state)) { writel (ints, ®s->intrstatus); writel (OHCI_INTR_MIE, ®s->intrenable); - // flush those pci writes + // flush those writes (void) ohci_readl (&ohci->regs->control); } diff -Nru a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c --- a/drivers/usb/host/ohci-pci.c 2004-09-06 17:33:19 -07:00 +++ b/drivers/usb/host/ohci-pci.c 2004-09-06 17:33:19 -07:00 @@ -61,6 +61,7 @@ && pdev->device == 0x740c) { ohci->flags = OHCI_QUIRK_AMD756; ohci_info (ohci, "AMD756 erratum 4 workaround\n"); + // also somewhat erratum 10 (suspend/resume issues) } /* FIXME for some of the early AMD 760 southbridges, OHCI @@ -75,6 +76,8 @@ && pdev->device == 0xc861) { ohci_info (ohci, "WARNING: OPTi workarounds unavailable\n"); + /* OPTi sometimes acts wierd during init */ + ohci->flags = OHCI_QUIRK_INITRESET; } /* Check for NSC87560. We have to look at the bridge (fn1) to @@ -92,6 +95,12 @@ ohci_info (ohci, "Using NSC SuperIO setup\n"); } } + + /* SiS sometimes acts wierd during init */ + else if (pdev->vendor == PCI_VENDOR_ID_SI) { + ohci->flags = OHCI_QUIRK_INITRESET; + ohci_info(ohci, "SiS init quirk\n"); + } } @@ -99,6 +108,15 @@ if ((ret = ohci_mem_init (ohci)) < 0) { ohci_stop (hcd); return ret; + } + + /* NOTE: this is a second reset. the first one helps + * keep bios/smm irqs from making trouble, but it was + * probably more than 1msec ago... + */ + if (hc_reset (ohci) < 0) { + ohci_stop (hcd); + return -ENODEV; } if (hc_start (ohci) < 0) { diff -Nru a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h --- a/drivers/usb/host/ohci.h 2004-09-06 17:33:19 -07:00 +++ b/drivers/usb/host/ohci.h 2004-09-06 17:33:19 -07:00 @@ -387,6 +387,7 @@ unsigned long flags; /* for HC bugs */ #define OHCI_QUIRK_AMD756 0x01 /* erratum #4 */ #define OHCI_QUIRK_SUPERIO 0x02 /* natsemi */ +#define OHCI_QUIRK_INITRESET 0x04 /* SiS, OPTi, ... */ // there are also chip quirks/bugs in init logic /* diff -Nru a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c --- a/drivers/usb/host/uhci-hcd.c 2004-09-06 17:33:19 -07:00 +++ b/drivers/usb/host/uhci-hcd.c 2004-09-06 17:33:19 -07:00 @@ -1661,6 +1661,8 @@ /* Poll for and perform state transitions */ hc_state_transitions(uhci); + if (unlikely(uhci->suspended_ports && uhci->state != UHCI_SUSPENDED)) + uhci_check_resume(uhci); init_stall_timer(hcd); } diff -Nru a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h --- a/drivers/usb/host/uhci-hcd.h 2004-09-06 17:33:19 -07:00 +++ b/drivers/usb/host/uhci-hcd.h 2004-09-06 17:33:19 -07:00 @@ -352,6 +352,12 @@ int resume_detect; /* Need a Global Resume */ unsigned int saved_framenumber; /* Save during PM suspend */ + /* Support for port suspend/resume */ + unsigned long port_c_suspend; /* Bit-arrays of ports */ + unsigned long suspended_ports; + unsigned long resuming_ports; + unsigned long resume_timeout; /* Time to stop signalling */ + /* Main list of URB's currently controlled by this HC */ struct list_head urb_list; /* P: uhci->schedule_lock */ diff -Nru a/drivers/usb/host/uhci-hub.c b/drivers/usb/host/uhci-hub.c --- a/drivers/usb/host/uhci-hub.c 2004-09-06 17:33:19 -07:00 +++ b/drivers/usb/host/uhci-hub.c 2004-09-06 17:33:19 -07:00 @@ -36,13 +36,13 @@ static int uhci_hub_status_data(struct usb_hcd *hcd, char *buf) { struct uhci_hcd *uhci = hcd_to_uhci(hcd); - unsigned long io_addr = uhci->io_addr; - int i; + int port; *buf = 0; - for (i = 0; i < uhci->rh_numports; i++) { - if (inw(io_addr + USBPORTSC1 + i * 2) & RWC_BITS) - *buf |= (1 << (i + 1)); + for (port = 0; port < uhci->rh_numports; ++port) { + if ((inw(uhci->io_addr + USBPORTSC1 + port * 2) & RWC_BITS) || + test_bit(port, &uhci->port_c_suspend)) + *buf |= (1 << (port + 1)); } return !!*buf; } @@ -62,6 +62,35 @@ status &= ~(RWC_BITS|WZ_BITS); \ outw(status, port_addr) +/* UHCI controllers don't automatically stop resume signalling after 20 msec, + * so we have to poll and check timeouts in order to take care of it. + * FIXME: Synchronize access to these fields by a spinlock. + */ +static void uhci_check_resume(struct uhci_hcd *uhci) +{ + unsigned int port; + unsigned int port_addr; + int status; + + for (port = 0; port < uhci->rh_numports; ++port) { + port_addr = uhci->io_addr + USBPORTSC1 + 2 * port; + if (unlikely(inw(port_addr) & USBPORTSC_RD)) { + if (!test_bit(port, &uhci->resuming_ports)) { + + /* Port received a wakeup request */ + set_bit(port, &uhci->resuming_ports); + uhci->resume_timeout = jiffies + + msecs_to_jiffies(20); + } else if (time_after_eq(jiffies, + uhci->resume_timeout)) { + CLR_RH_PORTSTAT(USBPORTSC_SUSP | USBPORTSC_RD); + clear_bit(port, &uhci->resuming_ports); + clear_bit(port, &uhci->suspended_ports); + set_bit(port, &uhci->port_c_suspend); + } + } + } +} /* size of returned buffer is part of USB spec */ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, @@ -69,8 +98,9 @@ { struct uhci_hcd *uhci = hcd_to_uhci(hcd); int status, retval = 0, len = 0; - unsigned long port_addr = uhci->io_addr + USBPORTSC1 + 2 * (wIndex-1); - __u16 wPortChange, wPortStatus; + unsigned int port = wIndex - 1; + unsigned long port_addr = uhci->io_addr + USBPORTSC1 + 2 * port; + u16 wPortChange, wPortStatus; switch (typeReq) { /* Request Destination: @@ -82,11 +112,15 @@ */ case GetHubStatus: - *(__u32 *)buf = cpu_to_le32(0); + *(u32 *) buf = cpu_to_le32(0); OK(4); /* hub power */ case GetPortStatus: - if (!wIndex || wIndex > uhci->rh_numports) + if (port >= uhci->rh_numports) goto err; + + if (uhci->resuming_ports) + uhci_check_resume(uhci); + status = inw(port_addr); /* Intel controllers report the OverCurrent bit active on. @@ -97,37 +131,39 @@ PCI_VENDOR_ID_VIA) status ^= USBPORTSC_OC; - /* UHCI doesn't support C_SUSPEND and C_RESET (always false) */ + /* UHCI doesn't support C_RESET (always false) */ wPortChange = 0; if (status & USBPORTSC_CSC) - wPortChange |= 1 << (USB_PORT_FEAT_C_CONNECTION - 16); + wPortChange |= USB_PORT_STAT_C_CONNECTION; if (status & USBPORTSC_PEC) - wPortChange |= 1 << (USB_PORT_FEAT_C_ENABLE - 16); + wPortChange |= USB_PORT_STAT_C_ENABLE; if (status & USBPORTSC_OCC) - wPortChange |= 1 << (USB_PORT_FEAT_C_OVER_CURRENT - 16); + wPortChange |= USB_PORT_STAT_C_OVERCURRENT; + if (test_bit(port, &uhci->port_c_suspend)) + wPortChange |= USB_PORT_STAT_C_SUSPEND; /* UHCI has no power switching (always on) */ - wPortStatus = 1 << USB_PORT_FEAT_POWER; + wPortStatus = USB_PORT_STAT_POWER; if (status & USBPORTSC_CCS) - wPortStatus |= 1 << USB_PORT_FEAT_CONNECTION; + wPortStatus |= USB_PORT_STAT_CONNECTION; if (status & USBPORTSC_PE) { - wPortStatus |= 1 << USB_PORT_FEAT_ENABLE; + wPortStatus |= USB_PORT_STAT_ENABLE; if (status & (USBPORTSC_SUSP | USBPORTSC_RD)) - wPortStatus |= 1 << USB_PORT_FEAT_SUSPEND; + wPortStatus |= USB_PORT_STAT_SUSPEND; } if (status & USBPORTSC_OC) - wPortStatus |= 1 << USB_PORT_FEAT_OVER_CURRENT; + wPortStatus |= USB_PORT_STAT_OVERCURRENT; if (status & USBPORTSC_PR) - wPortStatus |= 1 << USB_PORT_FEAT_RESET; + wPortStatus |= USB_PORT_STAT_RESET; if (status & USBPORTSC_LSDA) - wPortStatus |= 1 << USB_PORT_FEAT_LOWSPEED; + wPortStatus |= USB_PORT_STAT_LOW_SPEED; if (wPortChange) dev_dbg(uhci_dev(uhci), "port %d portsc %04x\n", wIndex, status); - *(__u16 *)buf = cpu_to_le16(wPortStatus); - *(__u16 *)(buf + 2) = cpu_to_le16(wPortChange); + *(u16 *) buf = cpu_to_le16(wPortStatus); + *(u16 *) (buf + 2) = cpu_to_le16(wPortChange); OK(4); case SetHubFeature: /* We don't implement these */ case ClearHubFeature: @@ -140,11 +176,12 @@ } break; case SetPortFeature: - if (!wIndex || wIndex > uhci->rh_numports) + if (port >= uhci->rh_numports) goto err; switch (wValue) { case USB_PORT_FEAT_SUSPEND: + set_bit(port, &uhci->suspended_ports); SET_RH_PORTSTAT(USBPORTSC_SUSP); OK(0); case USB_PORT_FEAT_RESET: @@ -164,7 +201,7 @@ } break; case ClearPortFeature: - if (!wIndex || wIndex > uhci->rh_numports) + if (port >= uhci->rh_numports) goto err; switch (wValue) { @@ -175,10 +212,12 @@ CLR_RH_PORTSTAT(USBPORTSC_PEC); OK(0); case USB_PORT_FEAT_SUSPEND: - CLR_RH_PORTSTAT(USBPORTSC_SUSP); + set_bit(port, &uhci->resuming_ports); + uhci->resume_timeout = jiffies + msecs_to_jiffies(20); + SET_RH_PORTSTAT(USBPORTSC_RD); OK(0); case USB_PORT_FEAT_C_SUSPEND: - /* this driver won't report these */ + clear_bit(port, &uhci->port_c_suspend); OK(0); case USB_PORT_FEAT_POWER: /* UHCI has no power switching */ diff -Nru a/drivers/usb/image/Kconfig b/drivers/usb/image/Kconfig --- a/drivers/usb/image/Kconfig 2004-09-06 17:33:19 -07:00 +++ b/drivers/usb/image/Kconfig 2004-09-06 17:33:19 -07:00 @@ -30,11 +30,12 @@ This driver can be compiled as a module, called microtek. config USB_HPUSBSCSI - tristate "HP53xx USB scanner support (EXPERIMENTAL)" - depends on USB && SCSI && EXPERIMENTAL + tristate "HP53xx USB scanner support" + depends on USB && SCSI help Say Y here if you want support for the HP 53xx series of scanners - and the Minolta Scan Dual. This driver is experimental. + and the Minolta Scan Dual. The scanner will be accessible as a SCSI device. + Please note that recent versions of SANE use usbfs, not this driver. This can be compiled as a module, called hpusbscsi. diff -Nru a/drivers/usb/image/microtek.c b/drivers/usb/image/microtek.c --- a/drivers/usb/image/microtek.c 2004-09-06 17:33:19 -07:00 +++ b/drivers/usb/image/microtek.c 2004-09-06 17:33:19 -07:00 @@ -324,7 +324,7 @@ MTS_DEBUG_GOT_HERE(); mts_debug_dump(desc); - usb_unlink_urb( desc->urb ); + usb_kill_urb( desc->urb ); } static int mts_scsi_abort (Scsi_Cmnd *srb) @@ -822,10 +822,10 @@ usb_set_intfdata(intf, NULL); + usb_kill_urb(desc->urb); scsi_remove_host(desc->host); - usb_unlink_urb(desc->urb); - scsi_host_put(desc->host); + scsi_host_put(desc->host); usb_free_urb(desc->urb); kfree(desc); } diff -Nru a/drivers/usb/media/dabusb.c b/drivers/usb/media/dabusb.c --- a/drivers/usb/media/dabusb.c 2004-09-06 17:33:19 -07:00 +++ b/drivers/usb/media/dabusb.c 2004-09-06 17:33:19 -07:00 @@ -109,16 +109,13 @@ static int dabusb_cancel_queue (pdabusb_t s, struct list_head *q) { unsigned long flags; - struct list_head *p; pbuff_t b; dbg("dabusb_cancel_queue"); spin_lock_irqsave (&s->lock, flags); - for (p = q->next; p != q; p = p->next) { - b = list_entry (p, buff_t, buff_list); - + list_for_each_entry(b, q, buff_list) { #ifdef DEBUG dump_urb(b->purb); #endif @@ -598,6 +595,7 @@ if (file->f_flags & O_NONBLOCK) { return -EBUSY; } + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout (HZ / 2); if (signal_pending (current)) { diff -Nru a/drivers/usb/media/konicawc.c b/drivers/usb/media/konicawc.c --- a/drivers/usb/media/konicawc.c 2004-09-06 17:33:19 -07:00 +++ b/drivers/usb/media/konicawc.c 2004-09-06 17:33:19 -07:00 @@ -362,8 +362,8 @@ else if (!urb->status && !cam->last_data_urb->status) len = konicawc_compress_iso(uvd, cam->last_data_urb, urb); - resubmit_urb(uvd, urb); resubmit_urb(uvd, cam->last_data_urb); + resubmit_urb(uvd, urb); cam->last_data_urb = NULL; uvd->stats.urb_length = len; uvd->stats.data_count += len; diff -Nru a/drivers/usb/misc/tiglusb.c b/drivers/usb/misc/tiglusb.c --- a/drivers/usb/misc/tiglusb.c 2004-09-06 17:33:19 -07:00 +++ b/drivers/usb/misc/tiglusb.c 2004-09-06 17:33:19 -07:00 @@ -115,6 +115,7 @@ return -EBUSY; } + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout (HZ / 2); if (signal_pending (current)) { diff -Nru a/drivers/usb/net/kaweth.c b/drivers/usb/net/kaweth.c --- a/drivers/usb/net/kaweth.c 2004-09-06 17:33:19 -07:00 +++ b/drivers/usb/net/kaweth.c 2004-09-06 17:33:19 -07:00 @@ -668,7 +668,7 @@ INTBUFFERSIZE, int_callback, kaweth, - 8); + 250); /* overriding the descriptor */ kaweth->irq_urb->transfer_dma = kaweth->intbufferhandle; kaweth->irq_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; diff -Nru a/drivers/usb/net/rtl8150.c b/drivers/usb/net/rtl8150.c --- a/drivers/usb/net/rtl8150.c 2004-09-06 17:33:19 -07:00 +++ b/drivers/usb/net/rtl8150.c 2004-09-06 17:33:19 -07:00 @@ -20,7 +20,7 @@ #include /* Version Information */ -#define DRIVER_VERSION "v0.6.1 (2004/03/13)" +#define DRIVER_VERSION "v0.6.2 (2004/08/27)" #define DRIVER_AUTHOR "Petko Manolov " #define DRIVER_DESC "rtl8150 based usb-ethernet driver" @@ -344,7 +344,7 @@ static int rtl8150_reset(rtl8150_t * dev) { - u8 data = 0x10; + u8 data = 0x11; int i = HZ; set_registers(dev, CR, 1, &data); diff -Nru a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c --- a/drivers/usb/serial/digi_acceleport.c 2004-09-06 17:33:19 -07:00 +++ b/drivers/usb/serial/digi_acceleport.c 2004-09-06 17:33:19 -07:00 @@ -1553,13 +1553,17 @@ dbg( "digi_close: TOP: port=%d, open_count=%d", priv->dp_port_num, port->open_count ); + /* if disconnected, just clear flags */ + if (!usb_get_intfdata(port->serial->interface)) + goto exit; + /* do cleanup only after final close on this port */ spin_lock_irqsave( &priv->dp_port_lock, flags ); priv->dp_in_close = 1; spin_unlock_irqrestore( &priv->dp_port_lock, flags ); /* tell line discipline to process only XON/XOFF */ - tty->closing = 1; + tty->closing = 1; /* wait for output to drain */ if( (filp->f_flags&(O_NDELAY|O_NONBLOCK)) == 0 ) { @@ -1624,6 +1628,7 @@ tty->closing = 0; +exit: spin_lock_irqsave( &priv->dp_port_lock, flags ); priv->dp_write_urb_in_use = 0; priv->dp_in_close = 0; diff -Nru a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c --- a/drivers/usb/serial/ftdi_sio.c 2004-09-06 17:33:19 -07:00 +++ b/drivers/usb/serial/ftdi_sio.c 2004-09-06 17:33:19 -07:00 @@ -368,6 +368,9 @@ { USB_DEVICE_VER(INTREPID_VID, INTREPID_NEOVI_PID, 0, 0x3ff) }, { USB_DEVICE_VER(FALCOM_VID, FALCOM_TWIST_PID, 0, 0x3ff) }, { USB_DEVICE_VER(FTDI_VID, FTDI_SUUNTO_SPORTS_PID, 0, 0x3ff) }, + { USB_DEVICE_VER(BANDB_VID, BANDB_USOTL4_PID, 0, 0x3ff) }, + { USB_DEVICE_VER(BANDB_VID, BANDB_USTL4_PID, 0, 0x3ff) }, + { USB_DEVICE_VER(BANDB_VID, BANDB_USO9ML2_PID, 0, 0x3ff) }, { } /* Terminating entry */ }; @@ -478,6 +481,9 @@ { USB_DEVICE_VER(INTREPID_VID, INTREPID_NEOVI_PID, 0x400, 0xffff) }, { USB_DEVICE_VER(FALCOM_VID, FALCOM_TWIST_PID, 0x400, 0xffff) }, { USB_DEVICE_VER(FTDI_VID, FTDI_SUUNTO_SPORTS_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(BANDB_VID, BANDB_USOTL4_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(BANDB_VID, BANDB_USTL4_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(BANDB_VID, BANDB_USO9ML2_PID, 0x400, 0xffff) }, { } /* Terminating entry */ }; @@ -595,6 +601,9 @@ { USB_DEVICE(INTREPID_VID, INTREPID_NEOVI_PID) }, { USB_DEVICE(FALCOM_VID, FALCOM_TWIST_PID) }, { USB_DEVICE(FTDI_VID, FTDI_SUUNTO_SPORTS_PID) }, + { USB_DEVICE(BANDB_VID, BANDB_USOTL4_PID) }, + { USB_DEVICE(BANDB_VID, BANDB_USTL4_PID) }, + { USB_DEVICE(BANDB_VID, BANDB_USO9ML2_PID) }, { } /* Terminating entry */ }; diff -Nru a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h --- a/drivers/usb/serial/ftdi_sio.h 2004-09-06 17:33:19 -07:00 +++ b/drivers/usb/serial/ftdi_sio.h 2004-09-06 17:33:19 -07:00 @@ -225,6 +225,14 @@ */ #define FTDI_SUUNTO_SPORTS_PID 0xF680 /* Suunto Sports instrument */ +/* + * Definitions for B&B Electronics products. + */ +#define BANDB_VID 0x0856 /* B&B Electronics Vendor ID */ +#define BANDB_USOTL4_PID 0xAC01 /* USOTL4 Isolated RS-485 Converter */ +#define BANDB_USTL4_PID 0xAC02 /* USTL4 RS-485 Converter */ +#define BANDB_USO9ML2_PID 0xAC03 /* USO9ML2 Isolated RS-232 Converter */ + /* Commands */ #define FTDI_SIO_RESET 0 /* Reset the port */ #define FTDI_SIO_MODEM_CTRL 1 /* Set the modem control register */ diff -Nru a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c --- a/drivers/usb/serial/ipaq.c 2004-09-06 17:33:19 -07:00 +++ b/drivers/usb/serial/ipaq.c 2004-09-06 17:33:19 -07:00 @@ -419,9 +419,8 @@ struct ipaq_private *priv = usb_get_serial_port_data(port); struct usb_serial *serial = port->serial; int count, room; - struct ipaq_packet *pkt; + struct ipaq_packet *pkt, *tmp; struct urb *urb = port->write_urb; - struct list_head *tmp; if (urb->status == -EINPROGRESS) { /* Should never happen */ @@ -429,9 +428,7 @@ return; } room = URBDATA_SIZE; - for (tmp = priv->queue.next; tmp != &priv->queue;) { - pkt = list_entry(tmp, struct ipaq_packet, list); - tmp = tmp->next; + list_for_each_entry_safe(pkt, tmp, &priv->queue, list) { count = min(room, (int)(pkt->len - pkt->written)); memcpy(urb->transfer_buffer + (URBDATA_SIZE - room), pkt->data + pkt->written, count); @@ -503,22 +500,16 @@ static void ipaq_destroy_lists(struct usb_serial_port *port) { struct ipaq_private *priv = usb_get_serial_port_data(port); - struct list_head *tmp; - struct ipaq_packet *pkt; + struct ipaq_packet *pkt, *tmp; - for (tmp = priv->queue.next; tmp != &priv->queue;) { - pkt = list_entry(tmp, struct ipaq_packet, list); - tmp = tmp->next; + list_for_each_entry_safe(pkt, tmp, &priv->queue, list) { kfree(pkt->data); kfree(pkt); } - for (tmp = priv->freelist.next; tmp != &priv->freelist;) { - pkt = list_entry(tmp, struct ipaq_packet, list); - tmp = tmp->next; + list_for_each_entry_safe(pkt, tmp, &priv->freelist, list) { kfree(pkt->data); kfree(pkt); } - return; } diff -Nru a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c --- a/drivers/usb/serial/pl2303.c 2004-09-06 17:33:19 -07:00 +++ b/drivers/usb/serial/pl2303.c 2004-09-06 17:33:19 -07:00 @@ -55,11 +55,26 @@ /* * Version Information */ -#define DRIVER_VERSION "v0.11" +#define DRIVER_VERSION "v0.12" #define DRIVER_DESC "Prolific PL2303 USB to serial adaptor driver" static int debug; +#define PL2303_CLOSING_WAIT (30*HZ) + +#define PL2303_BUF_SIZE 1024 +#define PL2303_TMP_BUF_SIZE 1024 + +static char pl2303_tmp_buf[PL2303_TMP_BUF_SIZE]; +static DECLARE_MUTEX(pl2303_tmp_buf_sem); + +struct pl2303_buf { + unsigned int buf_size; + char *buf_buf; + char *buf_get; + char *buf_put; +}; + static struct usb_device_id id_table [] = { { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID) }, { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_RSAQ2) }, @@ -134,12 +149,24 @@ static void pl2303_write_bulk_callback (struct urb *urb, struct pt_regs *regs); static int pl2303_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count); +static void pl2303_send (struct usb_serial_port *port); +static int pl2303_write_room(struct usb_serial_port *port); +static int pl2303_chars_in_buffer(struct usb_serial_port *port); static void pl2303_break_ctl(struct usb_serial_port *port,int break_state); static int pl2303_tiocmget (struct usb_serial_port *port, struct file *file); static int pl2303_tiocmset (struct usb_serial_port *port, struct file *file, unsigned int set, unsigned int clear); static int pl2303_startup (struct usb_serial *serial); static void pl2303_shutdown (struct usb_serial *serial); +static struct pl2303_buf *pl2303_buf_alloc(unsigned int size); +static void pl2303_buf_free(struct pl2303_buf *pb); +static void pl2303_buf_clear(struct pl2303_buf *pb); +static unsigned int pl2303_buf_data_avail(struct pl2303_buf *pb); +static unsigned int pl2303_buf_space_avail(struct pl2303_buf *pb); +static unsigned int pl2303_buf_put(struct pl2303_buf *pb, const char *buf, + unsigned int count); +static unsigned int pl2303_buf_get(struct pl2303_buf *pb, char *buf, + unsigned int count); /* All of the device info needed for the PL2303 SIO serial converter */ @@ -162,6 +189,8 @@ .read_bulk_callback = pl2303_read_bulk_callback, .read_int_callback = pl2303_read_int_callback, .write_bulk_callback = pl2303_write_bulk_callback, + .write_room = pl2303_write_room, + .chars_in_buffer = pl2303_chars_in_buffer, .attach = pl2303_startup, .shutdown = pl2303_shutdown, }; @@ -174,6 +203,8 @@ struct pl2303_private { spinlock_t lock; + struct pl2303_buf *buf; + int write_urb_in_use; wait_queue_head_t delta_msr_wait; u8 line_control; u8 line_status; @@ -201,14 +232,28 @@ for (i = 0; i < serial->num_ports; ++i) { priv = kmalloc (sizeof (struct pl2303_private), GFP_KERNEL); if (!priv) - return -ENOMEM; + goto cleanup; memset (priv, 0x00, sizeof (struct pl2303_private)); spin_lock_init(&priv->lock); + priv->buf = pl2303_buf_alloc(PL2303_BUF_SIZE); + if (priv->buf == NULL) { + kfree(priv); + goto cleanup; + } init_waitqueue_head(&priv->delta_msr_wait); priv->type = type; usb_set_serial_port_data(serial->port[i], priv); } return 0; + +cleanup: + for (--i; i>=0; --i) { + priv = usb_get_serial_port_data(serial->port[i]); + pl2303_buf_free(priv->buf); + kfree(priv); + usb_set_serial_port_data(serial->port[i], NULL); + } + return -ENOMEM; } static int set_control_lines (struct usb_device *dev, u8 value) @@ -224,40 +269,109 @@ static int pl2303_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count) { - int result; + struct pl2303_private *priv = usb_get_serial_port_data(port); + unsigned long flags; dbg("%s - port %d, %d bytes", __FUNCTION__, port->number, count); if (!count) return count; - if (port->write_urb->status == -EINPROGRESS) { - dbg("%s - already writing", __FUNCTION__); - return 0; - } - - count = (count > port->bulk_out_size) ? port->bulk_out_size : count; if (from_user) { - if (copy_from_user (port->write_urb->transfer_buffer, buf, count)) + if (count > PL2303_TMP_BUF_SIZE) + count = PL2303_TMP_BUF_SIZE; + down(&pl2303_tmp_buf_sem); + if (copy_from_user(pl2303_tmp_buf, buf, count)) { + up(&pl2303_tmp_buf_sem); return -EFAULT; - } else { - memcpy (port->write_urb->transfer_buffer, buf, count); + } + buf = pl2303_tmp_buf; } - + + spin_lock_irqsave(&priv->lock, flags); + count = pl2303_buf_put(priv->buf, buf, count); + spin_unlock_irqrestore(&priv->lock, flags); + + if (from_user) + up(&pl2303_tmp_buf_sem); + + pl2303_send(port); + + return count; +} + +static void pl2303_send(struct usb_serial_port *port) +{ + int count, result; + struct pl2303_private *priv = usb_get_serial_port_data(port); + unsigned long flags; + + dbg("%s - port %d", __FUNCTION__, port->number); + + spin_lock_irqsave(&priv->lock, flags); + + if (priv->write_urb_in_use) { + spin_unlock_irqrestore(&priv->lock, flags); + return; + } + + count = pl2303_buf_get(priv->buf, port->write_urb->transfer_buffer, + port->bulk_out_size); + + if (count == 0) { + spin_unlock_irqrestore(&priv->lock, flags); + return; + } + + priv->write_urb_in_use = 1; + + spin_unlock_irqrestore(&priv->lock, flags); + usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, port->write_urb->transfer_buffer); port->write_urb->transfer_buffer_length = count; port->write_urb->dev = port->serial->dev; result = usb_submit_urb (port->write_urb, GFP_ATOMIC); - if (result) + if (result) { dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __FUNCTION__, result); - else - result = count; + priv->write_urb_in_use = 0; + // TODO: reschedule pl2303_send + } - return result; + schedule_work(&port->work); } +static int pl2303_write_room(struct usb_serial_port *port) +{ + struct pl2303_private *priv = usb_get_serial_port_data(port); + int room = 0; + unsigned long flags; + dbg("%s - port %d", __FUNCTION__, port->number); + + spin_lock_irqsave(&priv->lock, flags); + room = pl2303_buf_space_avail(priv->buf); + spin_unlock_irqrestore(&priv->lock, flags); + + dbg("%s - returns %d", __FUNCTION__, room); + return room; +} + +static int pl2303_chars_in_buffer(struct usb_serial_port *port) +{ + struct pl2303_private *priv = usb_get_serial_port_data(port); + int chars = 0; + unsigned long flags; + + dbg("%s - port %d", __FUNCTION__, port->number); + + spin_lock_irqsave(&priv->lock, flags); + chars = pl2303_buf_data_avail(priv->buf); + spin_unlock_irqrestore(&priv->lock, flags); + + dbg("%s - returns %d", __FUNCTION__, chars); + return chars; +} static void pl2303_set_termios (struct usb_serial_port *port, struct termios *old_termios) { @@ -422,7 +536,7 @@ } kfree (buf); -} +} static int pl2303_open (struct usb_serial_port *port, struct file *filp) { @@ -461,7 +575,7 @@ FISH (VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, 0x8383, 0); SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 0, 1); SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 1, 0); - + if (priv->type == HX) { /* HX chip */ SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 2, 0x44); @@ -504,13 +618,52 @@ static void pl2303_close (struct usb_serial_port *port, struct file *filp) { - struct pl2303_private *priv; + struct pl2303_private *priv = usb_get_serial_port_data(port); unsigned long flags; unsigned int c_cflag; int result; + int bps; + long timeout; + wait_queue_t wait; \ dbg("%s - port %d", __FUNCTION__, port->number); + /* wait for data to drain from the buffer */ + spin_lock_irqsave(&priv->lock, flags); + timeout = PL2303_CLOSING_WAIT; + init_waitqueue_entry(&wait, current); + add_wait_queue(&port->tty->write_wait, &wait); + for (;;) { + set_current_state(TASK_INTERRUPTIBLE); + if (pl2303_buf_data_avail(priv->buf) == 0 + || timeout == 0 || signal_pending(current) + || !usb_get_intfdata(port->serial->interface)) /* disconnect */ + break; + spin_unlock_irqrestore(&priv->lock, flags); + timeout = schedule_timeout(timeout); + spin_lock_irqsave(&priv->lock, flags); + } + set_current_state(TASK_RUNNING); + remove_wait_queue(&port->tty->write_wait, &wait); + /* clear out any remaining data in the buffer */ + pl2303_buf_clear(priv->buf); + spin_unlock_irqrestore(&priv->lock, flags); + + /* wait for characters to drain from the device */ + /* (this is long enough for the entire 256 byte */ + /* pl2303 hardware buffer to drain with no flow */ + /* control for data rates of 1200 bps or more, */ + /* for lower rates we should really know how much */ + /* data is in the buffer to compute a delay */ + /* that is not unnecessarily long) */ + bps = tty_get_baud_rate(port->tty); + if (bps > 1200) + timeout = max((HZ*2560)/bps,HZ/10); + else + timeout = 2*HZ; + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(timeout); + /* shutdown our urbs */ dbg("%s - shutting down urbs", __FUNCTION__); result = usb_unlink_urb (port->write_urb); @@ -535,14 +688,12 @@ c_cflag = port->tty->termios->c_cflag; if (c_cflag & HUPCL) { /* drop DTR and RTS */ - priv = usb_get_serial_port_data(port); spin_lock_irqsave(&priv->lock, flags); priv->line_control = 0; spin_unlock_irqrestore (&priv->lock, flags); set_control_lines (port->serial->dev, 0); } } - } static int pl2303_tiocmset (struct usb_serial_port *port, struct file *file, @@ -672,12 +823,17 @@ static void pl2303_shutdown (struct usb_serial *serial) { int i; + struct pl2303_private *priv; dbg("%s", __FUNCTION__); for (i = 0; i < serial->num_ports; ++i) { - kfree (usb_get_serial_port_data(serial->port[i])); - usb_set_serial_port_data(serial->port[i], NULL); + priv = usb_get_serial_port_data(serial->port[i]); + if (priv) { + pl2303_buf_free(priv->buf); + kfree(priv); + usb_set_serial_port_data(serial->port[i], NULL); + } } } @@ -815,11 +971,23 @@ static void pl2303_write_bulk_callback (struct urb *urb, struct pt_regs *regs) { struct usb_serial_port *port = (struct usb_serial_port *) urb->context; + struct pl2303_private *priv = usb_get_serial_port_data(port); int result; dbg("%s - port %d", __FUNCTION__, port->number); - - if (urb->status) { + + switch (urb->status) { + case 0: + /* success */ + break; + case -ECONNRESET: + case -ENOENT: + case -ESHUTDOWN: + /* this urb is terminated, clean up */ + dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status); + priv->write_urb_in_use = 0; + return; + default: /* error in the urb, so we have to resubmit it */ dbg("%s - Overflow in write", __FUNCTION__); dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status); @@ -828,13 +996,198 @@ result = usb_submit_urb (port->write_urb, GFP_ATOMIC); if (result) dev_err(&urb->dev->dev, "%s - failed resubmitting write urb, error %d\n", __FUNCTION__, result); + else + return; + } - return; + priv->write_urb_in_use = 0; + + /* send any buffered data */ + pl2303_send(port); +} + + +/* + * pl2303_buf_alloc + * + * Allocate a circular buffer and all associated memory. + */ + +static struct pl2303_buf *pl2303_buf_alloc(unsigned int size) +{ + + struct pl2303_buf *pb; + + + if (size == 0) + return NULL; + + pb = (struct pl2303_buf *)kmalloc(sizeof(struct pl2303_buf), GFP_KERNEL); + if (pb == NULL) + return NULL; + + pb->buf_buf = kmalloc(size, GFP_KERNEL); + if (pb->buf_buf == NULL) { + kfree(pb); + return NULL; } - schedule_work(&port->work); + pb->buf_size = size; + pb->buf_get = pb->buf_put = pb->buf_buf; + + return pb; + +} + + +/* + * pl2303_buf_free + * + * Free the buffer and all associated memory. + */ + +static void pl2303_buf_free(struct pl2303_buf *pb) +{ + if (pb != NULL) { + if (pb->buf_buf != NULL) + kfree(pb->buf_buf); + kfree(pb); + } } + +/* + * pl2303_buf_clear + * + * Clear out all data in the circular buffer. + */ + +static void pl2303_buf_clear(struct pl2303_buf *pb) +{ + if (pb != NULL) + pb->buf_get = pb->buf_put; + /* equivalent to a get of all data available */ +} + + +/* + * pl2303_buf_data_avail + * + * Return the number of bytes of data available in the circular + * buffer. + */ + +static unsigned int pl2303_buf_data_avail(struct pl2303_buf *pb) +{ + if (pb != NULL) + return ((pb->buf_size + pb->buf_put - pb->buf_get) % pb->buf_size); + else + return 0; +} + + +/* + * pl2303_buf_space_avail + * + * Return the number of bytes of space available in the circular + * buffer. + */ + +static unsigned int pl2303_buf_space_avail(struct pl2303_buf *pb) +{ + if (pb != NULL) + return ((pb->buf_size + pb->buf_get - pb->buf_put - 1) % pb->buf_size); + else + return 0; +} + + +/* + * pl2303_buf_put + * + * Copy data data from a user buffer and put it into the circular buffer. + * Restrict to the amount of space available. + * + * Return the number of bytes copied. + */ + +static unsigned int pl2303_buf_put(struct pl2303_buf *pb, const char *buf, + unsigned int count) +{ + + unsigned int len; + + + if (pb == NULL) + return 0; + + len = pl2303_buf_space_avail(pb); + if (count > len) + count = len; + + if (count == 0) + return 0; + + len = pb->buf_buf + pb->buf_size - pb->buf_put; + if (count > len) { + memcpy(pb->buf_put, buf, len); + memcpy(pb->buf_buf, buf+len, count - len); + pb->buf_put = pb->buf_buf + count - len; + } else { + memcpy(pb->buf_put, buf, count); + if (count < len) + pb->buf_put += count; + else /* count == len */ + pb->buf_put = pb->buf_buf; + } + + return count; + +} + + +/* + * pl2303_buf_get + * + * Get data from the circular buffer and copy to the given buffer. + * Restrict to the amount of data available. + * + * Return the number of bytes copied. + */ + +static unsigned int pl2303_buf_get(struct pl2303_buf *pb, char *buf, + unsigned int count) +{ + + unsigned int len; + + + if (pb == NULL) + return 0; + + len = pl2303_buf_data_avail(pb); + if (count > len) + count = len; + + if (count == 0) + return 0; + + len = pb->buf_buf + pb->buf_size - pb->buf_get; + if (count > len) { + memcpy(buf, pb->buf_get, len); + memcpy(buf+len, pb->buf_buf, count - len); + pb->buf_get = pb->buf_buf + count - len; + } else { + memcpy(buf, pb->buf_get, count); + if (count < len) + pb->buf_get += count; + else /* count == len */ + pb->buf_get = pb->buf_buf; + } + + return count; + +} static int __init pl2303_init (void) { diff -Nru a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h --- a/drivers/usb/storage/unusual_devs.h 2004-09-06 17:33:19 -07:00 +++ b/drivers/usb/storage/unusual_devs.h 2004-09-06 17:33:19 -07:00 @@ -68,16 +68,6 @@ US_SC_8070, US_PR_SCM_ATAPI, init_8200e, 0), #endif -/* : I don't know the name of the bridge - * manufacturer, but I've got an external USB drive by the Revoltec company - * that needs this. otherwise the drive is recognized as /dev/sda, but any - * access to it blocks indefinitely. - */ -UNUSUAL_DEV( 0x0402, 0x5621, 0x0103, 0x0103, - "Revoltec", - "USB/IDE Bridge (ATA/ATAPI)", - US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_INQUIRY), - /* Deduced by Jonathan Woithe * Entry needed for flags: US_FL_FIX_INQUIRY because initial inquiry message * always fails and confuses drive. diff -Nru a/include/linux/usb.h b/include/linux/usb.h --- a/include/linux/usb.h 2004-09-06 17:33:19 -07:00 +++ b/include/linux/usb.h 2004-09-06 17:33:19 -07:00 @@ -264,7 +264,6 @@ int bandwidth_isoc_reqs; /* number of Isoc. requests */ struct dentry *usbfs_dentry; /* usbfs dentry entry for the bus */ - struct dentry *usbdevfs_dentry; /* usbdevfs dentry entry for the bus */ struct class_device class_dev; /* class device for this bus */ void (*release)(struct usb_bus *bus); /* function to destroy this bus's memory */ @@ -315,7 +314,6 @@ struct list_head filelist; struct dentry *usbfs_dentry; /* usbfs dentry entry for the device */ - struct dentry *usbdevfs_dentry; /* usbdevfs dentry entry for the device */ /* * Child devices - these can be either new devices diff -Nru a/include/linux/usbdevice_fs.h b/include/linux/usbdevice_fs.h --- a/include/linux/usbdevice_fs.h 2004-09-06 17:33:19 -07:00 +++ b/include/linux/usbdevice_fs.h 2004-09-06 17:33:19 -07:00 @@ -166,16 +166,6 @@ unsigned long ifclaimed; }; -/* internal methods & data */ -extern struct usb_driver usbdevfs_driver; -extern struct file_operations usbdevfs_drivers_fops; -extern struct file_operations usbdevfs_devices_fops; -extern struct file_operations usbdevfs_device_file_operations; -extern struct inode_operations usbdevfs_device_inode_operations; -extern struct inode_operations usbdevfs_bus_inode_operations; -extern struct file_operations usbdevfs_bus_file_operations; -extern void usbdevfs_conn_disc_event(void); - #endif /* __KERNEL__ */ /* --------------------------------------------------------------------- */