bk://kernel.bkbits.net/gregkh/linux/usb-2.6 phil@ipom.com[gregkh]|ChangeSet|20050325001128|11500 phil # This is a BitKeeper generated diff -Nru style patch. # # ChangeSet # 2005/03/24 16:11:28-08:00 phil@ipom.com # [PATCH] USB Storage: Remove dup in unusual_devs # # Matthew Dharm pointed out that your BK tree somehow got 2 versions of an # unusual_devs entry in it. One was from a patch in January and the other # was from an automerge. # # I dug around in bk - which I find to be the most counter-intuitive # program in the world - and generated a patch against your latest BK # tree, and I've attached it. It just removes the dup. # # Signed-off-by: Phil Dibowitz # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/storage/unusual_devs.h # 2005/03/21 01:28:39-08:00 phil@ipom.com +0 -8 # USB Storage: Remove dup in unusual_devs # # ChangeSet # 2005/03/24 16:11:11-08:00 colin@colino.net # [PATCH] USB: fix harmful typos in zd1201.c # # I was looking around to see why monitor mode wouldn't work using the # zd1201 driver, and spotted these obvious typos. # # I think you can safely apply :) # # Signed-off-by: Colin Leroy # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/net/zd1201.c # 2005/03/24 03:24:41-08:00 colin@colino.net +2 -2 # USB: fix harmful typos in zd1201.c # # ChangeSet # 2005/03/24 15:31:46-08:00 david-b@pacbell.net # [PATCH] USB: ehci split ISO fixes (full speed audio etc) # # This contains patches to the EHCI driver for the full speed isochronous # transfer support: # # - The sitd->hw_buf[1] and sitd->hw_buf_hi[1] fields were not # correctly initialized, affecting transfers which crossed 4K # boundaries. Helps resolve some "buzz" in audio playback. # # - Correctly rounds 188-byte OUT transfers to fit into a single # packet ... no split transfers needed. Resolves other "buzz" in # audio OUT streams. # # - Fixes a cut'n'paste error in the logic to check for microframe # scheduling collisions with a given transaction translator. # The error caused full speed iso tds to be treated in part as # if they were high speed iso tds, which could oops. # # - The split transaction state flag doesn't indicate an error, and # it should be ignored when deciding if (IN) transfers had errors. # # - Remove some code rejecting full speed iso IN transfers; it's # not fully working yet though. # # Plus a some minor cleanups: reporting the iso start frame in the # relevant units, making a debug message more consistent. # # Signed-off-by: Karsten Wiese # Signed-off-by: David Brownell # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/host/ehci.h # 2005/03/22 11:23:47-08:00 david-b@pacbell.net +1 -1 # USB: ehci split ISO fixes (full speed audio etc) # # drivers/usb/host/ehci-sched.c # 2005/03/23 16:30:13-08:00 david-b@pacbell.net +13 -18 # USB: ehci split ISO fixes (full speed audio etc) # # ChangeSet # 2005/03/24 15:31:29-08:00 david-b@pacbell.net # [PATCH] USB: usbnet uses netif_msg_*() ethtool filtering # # This converts most of the usbnet code to actually use the ethtool # message flags. The ASIX code is left untouched, since there are # a bunch of patches pending there ... that's where the remaining # handful of "sparse -Wbitwise" warnings come from. # # Signed-off-by: David Brownell # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/net/usbnet.c # 2005/03/21 00:19:25-08:00 david-b@pacbell.net +108 -85 # USB: usbnet uses netif_msg_*() ethtool filtering # # ChangeSet # 2005/03/24 15:31:13-08:00 david-b@pacbell.net # [PATCH] USB: usbnet minor bugfixes # # Two bugfixes to usbnet. The important one is that it's OK when the # minidriver doesn't want to use a status endpoint. That shouldn't # be treated as an error ... errors prevent probe() from succeeding! # # The minor fix is that software driven interface shutdown should neither # be accounted as an error, nor generate a diagnostic. # # Signed-off-by: David Brownell # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/net/usbnet.c # 2005/03/21 01:04:33-08:00 david-b@pacbell.net +6 -1 # USB: usbnet minor bugfixes # # ChangeSet # 2005/03/24 15:30:57-08:00 david-b@pacbell.net # [PATCH] USB: pegasus uses netif_msg_*() filters # # This updates the messaging for the pegasus driver: # # - Use driver model diagnostics or printk using the interface name # for all diagnostic messages ... not dbg()/warn()/err(). # # - Almost everywhere, use the netif_msg_XXX() macros to check the # message control bitmask maintained by ethtool. The default mask # is initialized using a new "message_level" module parameter. # # Also: # # - Removes the needless PEGASUS_RUNNING flag, replacing it with the # standard netdevice mechanism. # # - Cleaner access for unaligned values. Not all processors spend # silicon to support them like x86 does. # # - Adds a few "sparse" fixes. # # - Saves the return values for the requests that manipulate chip # registers ... doesn't yet check them, but at least anyone looking # at the code (e.g. to find out why the link check task is wedged...) # will see where those failure modes are ignored. Currently the # errors may be reported by printk, but the netif_msg_*() filters # make that an even worse alert mechanism. # # Signed-off-by: David Brownell # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/net/pegasus.h # 2005/03/20 21:42:40-08:00 david-b@pacbell.net +2 -2 # USB: pegasus uses netif_msg_*() filters # # drivers/usb/net/pegasus.c # 2005/03/21 00:19:25-08:00 david-b@pacbell.net +191 -106 # USB: pegasus uses netif_msg_*() filters # # ChangeSet # 2005/03/24 15:30:41-08:00 david-b@pacbell.net # [PATCH] USB: usb rndis gadget sparse fixes [4/5] # # This is a bunch of "sparse" fixups for the RNDIS code, saying it's # little-endian on the wire and swapping cpu_to_le32() calls with # more-correct le32_to_cpu() ones. # # Signed-off-by: David Brownell # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/gadget/rndis.h # 2005/03/19 14:05:11-08:00 david-b@pacbell.net +81 -81 # USB: usb rndis gadget sparse fixes [4/5] # # drivers/usb/gadget/rndis.c # 2005/03/19 14:05:11-08:00 david-b@pacbell.net +86 -83 # USB: usb rndis gadget sparse fixes [4/5] # # ChangeSet # 2005/03/24 15:30:24-08:00 david-b@pacbell.net # [PATCH] USB: gadget zero sparse fixes [5/5] # # Some "sparse" updates for the Gadget Zero driver, preparing it to # expect SETUP packets to be little endian. # # Signed-off-by: David Brownell # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/gadget/zero.c # 2005/03/19 15:00:06-08:00 david-b@pacbell.net +25 -23 # USB: gadget zero sparse fixes [5/5] # # ChangeSet # 2005/03/24 15:30:07-08:00 david-b@pacbell.net # [PATCH] USB: usb gadgetfs sparse fixes [3/5] # # Many "sparse" updates for GadgetFS driver, preparing it to expect # SETUP packets to be little endian. # # Signed-off-by: David Brownell # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/gadget/inode.c # 2005/03/19 15:15:46-08:00 david-b@pacbell.net +15 -14 # USB: usb gadgetfs sparse fixes [3/5] # # ChangeSet # 2005/03/24 15:29:50-08:00 stern@rowland.harvard.edu # [PATCH] USB: fix usb file_storage gadget sparse fixes [2/5] # # On Sun, 20 Mar 2005, David Brownell wrote: # # > > - gfile-0319 ... gets rid of most byteorder warnings from the # > > file_storage gadget driver (except for SETUP packet fields) # # This patch causes an undeclared variable error when verbose debugging is # enabled. Please add the following on top of it. # # Signed-off-by: Alan Stern # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/gadget/file_storage.c # 2005/03/21 02:39:23-08:00 stern@rowland.harvard.edu +1 -1 # USB: fix usb file_storage gadget sparse fixes [2/5] # # ChangeSet # 2005/03/24 15:29:34-08:00 david-b@pacbell.net # [PATCH] USB: usb file_storage gadget sparse fixes [2/5] # # Some "sparse" updates for the File-backed Storage Gadget driver, # preparing it to expect SETUP packets to be little endian. # # Signed-off-by: David Brownell # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/gadget/file_storage.c # 2005/03/19 14:05:11-08:00 david-b@pacbell.net +27 -22 # USB: usb file_storage gadget sparse fixes [2/5] # # ChangeSet # 2005/03/24 15:29:17-08:00 david-b@pacbell.net # [PATCH] USB: usb gadget misc sparse fixes [1/5] # # This lets the file_storage gadget appear again in Kconfig, and fixes # some minor "sparse" warnings. # # Signed-off-by: David Brownell # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/gadget/usbstring.c # 2005/03/19 15:00:06-08:00 david-b@pacbell.net +2 -2 # USB: usb gadget misc sparse fixes [1/5] # # drivers/usb/gadget/config.c # 2005/03/19 15:00:06-08:00 david-b@pacbell.net +1 -0 # USB: usb gadget misc sparse fixes [1/5] # # drivers/usb/gadget/Kconfig # 2005/03/19 15:00:06-08:00 david-b@pacbell.net +0 -2 # USB: usb gadget misc sparse fixes [1/5] # # ChangeSet # 2005/03/24 15:14:10-08:00 mdharm-usb@one-eyed-alien.net # [PATCH] USB Storage: remove RW_DETECT from being a config option # # This patch started life as as454b from Alan Stern. It has been rediffed # against the tip, including updates for the way unusual_devs flags are # defined. # # This patch removes the Kconfig option USB_STORAGE_RW_DETECT. That option # was used to enable/supress the attempt to detect if a device was write # protected. # # It seems that the vast majority of devices properly respond to the latest # algorithm for making that determination. So now we move to excluding only # those devices that can't handle it. We accomplish this via the # unusual_devs.h list. # # Signed-off-by: Alan Stern # Signed-off-by: Matthew Dharm # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/storage/usb.h # 2005/03/21 00:40:36-08:00 mdharm-usb@one-eyed-alien.net +2 -0 # USB Storage: remove RW_DETECT from being a config option # # drivers/usb/storage/unusual_devs.h # 2005/03/21 00:40:36-08:00 mdharm-usb@one-eyed-alien.net +8 -1 # USB Storage: remove RW_DETECT from being a config option # # drivers/usb/storage/scsiglue.c # 2005/03/21 00:40:36-08:00 mdharm-usb@one-eyed-alien.net +10 -8 # USB Storage: remove RW_DETECT from being a config option # # drivers/usb/storage/Kconfig # 2005/03/21 00:40:36-08:00 mdharm-usb@one-eyed-alien.net +0 -22 # USB Storage: remove RW_DETECT from being a config option # # ChangeSet # 2005/03/24 15:13:53-08:00 mdharm-usb@one-eyed-alien.net # [PATCH] USB Storage: combine waitqueues # # This patch started life as as476, and has been rediffed against the tip. # However, that was a few days ago. # # This patch combines the two separate waitqueue heads used by the # scsi-scanning thread and the device-reset routine into one. After all, # until the scanning thread is through waiting there will be no SCSI # devices and hence no device resets. # # Once the scanning thread is done waiting, the waitqueue can be used by the # reset logic -- so even if the act of scanning produces resets, we're fine. # # Signed-off-by: Alan Stern # Signed-off-by: Matthew Dharm # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/storage/usb.h # 2005/03/13 21:33:16-08:00 mdharm-usb@one-eyed-alien.net +3 -5 # USB Storage: combine waitqueues # # drivers/usb/storage/usb.c # 2005/03/13 21:33:16-08:00 mdharm-usb@one-eyed-alien.net +6 -8 # USB Storage: combine waitqueues # # drivers/usb/storage/transport.c # 2005/03/13 21:33:16-08:00 mdharm-usb@one-eyed-alien.net +1 -1 # USB Storage: combine waitqueues # # ChangeSet # 2005/03/24 15:13:36-08:00 mdharm-usb@one-eyed-alien.net # [PATCH] USB Storage: allow disconnect to complete faster # # This patch started life as as476 from Alan Stern. It has been rediffed # against the tip, tho that was a few days ago. # # This patch makes the disconnect() routine not wait for the control and # scanning threads to exit. This may not seem important now, but it will # become important later: We would end up with a deadlock if disconnect() # (which is called with the device locked) was waiting for the control # thread to exit, while the control thread was waiting to lock the device so # it could do an autosuspend. # # It's necessary to make sure that the host and us_data structures aren't # deallocated before the control and scanning threads are through with them. # This is done by calling scsi_host_get and scsi_host_put at the start and # end of each thread, before signalling that the threads are running. Since # the probe() and disconnect() routines cannot run concurrently (guaranteed # to us by the USB core), this method will guarantee the structures are not # deallocated too soon. # # While there's nothing wrong with leaving the threads alive after # disconnect() returns, there would be a real problem if the threads were # still alive when usb_stor_exit returned! So now usb_stor_exit has to wait # to make sure all the threads have died. Apparently the only safe way for # one thread to signal another while exiting is to use complete_and_exit, # which we've been doing. So the patch adds a new driver-wide struct # completion, named threads_gone, and each thread signals it while exiting. # usb_stor_exit must call wait_for_completion the appropriate number of # times, and that number is stored in a new counter named total_threads. # # # Signed-off-by: Alan Stern # Signed-off-by: Matthew Dharm # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/storage/usb.c # 2005/03/13 21:33:29-08:00 mdharm-usb@one-eyed-alien.net +41 -7 # USB Storage: allow disconnect to complete faster # # ChangeSet # 2005/03/24 15:13:20-08:00 mdharm-usb@one-eyed-alien.net # [PATCH] USB Storage: exit control thread immediately upon disconnect # # This patch started life as as475 from Alan Stern. It has been rediffed # against the tip, tho that was several days ago. # # This patch causes the main control thread to exit as soon as possible, # i.e., as soon as the DISCONNECTING flag is set. It no longer waits for an # explicit exit command, one with srb == NULL. # # There won't be any bad implications for our interaction with the SCSI # midlayer, because once the DISCONNECTING flag is set we fail every # submitted command immediately in the queuecommand routine. And if a # command manages to squeeze through the crack (submitted and accepted # before we disconnect but not yet processed), the SCSI midlayer will cancel # it automatically when we remove the host. # # Signed-off-by: Alan Stern # Signed-off-by: Matthew Dharm # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/storage/usb.c # 2005/03/13 21:33:41-08:00 mdharm-usb@one-eyed-alien.net +9 -36 # USB Storage: exit control thread immediately upon disconnect # # ChangeSet # 2005/03/24 15:13:02-08:00 mdharm-usb@one-eyed-alien.net # [PATCH] USB Storage: make usb-storage structures refcounted by SCSI # # This patch started life as as474 from Alan Stern. It's been rediffed # against the tip, tho that is now several days old. # # This patch changes the way our private struct us_data is allocated; now it # gets stored at the end of the Scsi_Host rather than separately. That's # what the hostdata field is intended for, and this is how other low-level # host drivers operate. In order to convert between us_data and the # corresponding Scsi_Host I added two new inline routines: us_to_host and # host_to_us. (The conversion actually should be quicker than before by a # microscopic amount, because now it only involves adding an offset whereas # before it involved dereferencing a pointer.) # # The main advantage is that the host is refcounted, so now our us_data # automatically is too. Although that doesn't matter at the moment, it will # matter later on when the control thread may need to outlive the disconnect # callback. # # # Signed-off-by: Alan Stern # Signed-off-by: Matthew Dharm # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/storage/usb.h # 2005/03/13 21:33:54-08:00 mdharm-usb@one-eyed-alien.net +8 -1 # USB Storage: make usb-storage structures refcounted by SCSI # # drivers/usb/storage/usb.c # 2005/03/13 21:33:54-08:00 mdharm-usb@one-eyed-alien.net +23 -32 # USB Storage: make usb-storage structures refcounted by SCSI # # drivers/usb/storage/transport.c # 2005/03/13 21:33:54-08:00 mdharm-usb@one-eyed-alien.net +2 -2 # USB Storage: make usb-storage structures refcounted by SCSI # # drivers/usb/storage/scsiglue.c # 2005/03/13 21:33:54-08:00 mdharm-usb@one-eyed-alien.net +24 -27 # USB Storage: make usb-storage structures refcounted by SCSI # # ChangeSet # 2005/03/24 14:45:05-08:00 bunk@stusta.de # [PATCH] drivers/usb/core/devices.c: small corrections # # total_written is used at places where it can't have any value different # from 0. # # This patch is partially based on findings of the Coverity checker. # # Signed-off-by: Adrian Bunk # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/core/devices.c # 2005/03/22 12:15:02-08:00 bunk@stusta.de +2 -5 # drivers/usb/core/devices.c: small corrections # # ChangeSet # 2005/03/24 14:34:40-08:00 rkagan@mail.ru # [PATCH] drivers/usb/core/usb.c: add MODALIAS env var to hotplug # # The patch below adds MODALIAS environment variable to usb hotplug # callout, allowing for its straightforward use with modprobe. # # Signed-off-by: Roman Kagan # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/core/usb.c # 2005/03/24 14:30:58-08:00 rkagan@mail.ru +27 -0 # drivers/usb/core/usb.c: add MODALIAS env var to hotplug # # ChangeSet # 2005/03/24 14:29:06-08:00 david-b@pacbell.net # [PATCH] USB: pxa25x udc updates, mostly PM # # This has various updates to the PXA 21x/25x/26x UDC driver. # # - Implement the "new" pullup() and vbus_session() methods, and # use them to keep the UDC 48 MHz clock off much of the time. # # * Reworked that ugly Lubbock VBUS IRQ code. Claim both IRQs, # enable only one at a time; clock the UDC only when VBUS is # present. (And get rid of rude runtime messages.) # # * Implement driver model suspend() and resume() calls. When # this device suspends, it clocks off the UDC. On boards that # support it (including Zaurus clamshells, but not Lubbock) # the D+ pullup is disabled, so the host won't see the device. # # - Hmm, the "latest" errata defined some "Must Be One" bits. OK. # # - Change the LED support for debugging. It stopped compiling for # Lubbock a while back. This switches to the standard LED calls # (so it can work on non-Lubbock hardware), removes the EP0 calls # (not very useful any more), and for Lubbock now initializes the # hex leds (U-Boot doesn't enable them, BLOB did). # # - "sparse" updates, and get rid of a warning that's pointless # unless someone's working on DMA support; # # Tested on Lubbock (VBUS sensing but no pullup) and some Zaurus # clamshells (pullup but no VBUS). # # Signed-off-by: David Brownell # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/gadget/pxa2xx_udc.h # 2005/03/12 16:35:52-08:00 david-b@pacbell.net +16 -13 # USB: pxa25x udc updates, mostly PM # # drivers/usb/gadget/pxa2xx_udc.c # 2005/03/12 16:35:52-08:00 david-b@pacbell.net +183 -96 # USB: pxa25x udc updates, mostly PM # # ChangeSet # 2005/03/24 14:28:49-08:00 david-b@pacbell.net # [PATCH] USB: ohci-omap update (mostly clock gating) # # This syncs the OMAP OHCI code with the latest from the OMAP tree. # The main changes are updated clock gating support (goes with some # clock tree updates, submitted separately) and two minor cleanups: # the platform device resources use physical addressing, not the # static i/o mapped addresses; and there's no longer a need for a # (noexistent in mainstream) separate header file. # # Signed-off-by: David Brownell # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/host/ohci-omap.c # 2005/03/16 21:21:33-08:00 david-b@pacbell.net +51 -70 # USB: ohci-omap update (mostly clock gating) # # arch/arm/mach-omap/usb.c # 2005/03/16 20:19:25-08:00 david-b@pacbell.net +2 -2 # USB: ohci-omap update (mostly clock gating) # # ChangeSet # 2005/03/24 14:28:28-08:00 colin@colino.net # [PATCH] USB: fix missing hunk in drivers/usb/Makefile # # I see there's been a driver for zd1201 added in drivers/usb/net/. # There's a hunk missing in drivers/usb/Makefile, the driver doesn't # get built in nothing else in drivers/usb/net is configured in : # # Signed-off-by: Colin Leroy # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/Makefile # 2005/03/18 01:27:22-08:00 colin@colino.net +1 -0 # USB: fix missing hunk in drivers/usb/Makefile # # ChangeSet # 2005/03/24 00:35:43-08:00 gregkh@suse.de # USB: mark usb-serial interface GPL only # # This is done because you have to use a GPL only licensed .h file in order to write a usb-serial # driver. # # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/serial/usb-serial.c # 2005/03/24 00:35:30-08:00 gregkh@suse.de +5 -5 # USB: mark usb-serial interface GPL only # # This is done because you have to use a GPL only licensed .h file in order to write a usb-serial # driver. # # Signed-off-by: Greg Kroah-Hartman # # ChangeSet # 2005/03/23 20:34:15-08:00 zaitcev@redhat.com # [PATCH] USB: Add myself to MAINTAINERS # # A Jan Kasprzak asked a few days ago to have a MAINTAINERS entry for ub. # This patch updates my entries in MAINTAINERS (ub & ymfpci). # # Signed-off-by: Pete Zaitcev # Signed-off-by: Greg Kroah-Hartman # # MAINTAINERS # 2005/03/21 10:16:56-08:00 zaitcev@redhat.com +9 -2 # USB: Add myself to MAINTAINERS # # ChangeSet # 2005/03/23 20:33:55-08:00 zaitcev@redhat.com # [PATCH] USB: usbmon - document and kill pipe from API # # Someone at linux-usb-devel observed that usbmon should not leak the concept # of pipe to the user space. This patch makes a compromise between having # too many words in the line and the pipe. It breaks API, but I doubt anyone # has any usbmon tools in circulation at this time, so I decided not to move # to a different filename. # # Also, I decided to add a document which describes what is going on. I was # reluctant to do it because I doubt my ability to keep it synchronized and # updated, but there were requests to have one. # # Signed-off-by: Pete Zaitcev # Signed-off-by: Greg Kroah-Hartman # # Documentation/usb/usbmon.txt # 2005/03/23 13:07:28-08:00 zaitcev@redhat.com +156 -0 # USB: usbmon - document and kill pipe from API # # drivers/usb/mon/mon_text.c # 2005/03/18 17:22:26-08:00 zaitcev@redhat.com +12 -2 # USB: usbmon - document and kill pipe from API # # Documentation/usb/usbmon.txt # 2005/03/23 13:07:28-08:00 zaitcev@redhat.com +0 -0 # BitKeeper file /home/greg/linux/BK/usb-2.6/Documentation/usb/usbmon.txt # # ChangeSet # 2005/03/23 20:33:34-08:00 zaitcev@redhat.com # [PATCH] USB: Fix baud selection in mct_u232 # # This is a patch by Hansjoerg Lipp to fix coding error in divisor calculation. # # Signed-off-by: Pete Zaitcev # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/serial/mct_u232.c # 2005/03/23 08:26:12-08:00 zaitcev@redhat.com +11 -11 # USB: Fix baud selection in mct_u232 # # ChangeSet # 2005/03/23 20:33:13-08:00 zaitcev@redhat.com # [PATCH] USB: ub static patch # # I'm pretty sure this comes from Bunk originally, but I didn't keep the # original, so only one signed-off-by is present. # # Signed-off-by: Pete Zaitcev # Signed-off-by: Greg Kroah-Hartman # # drivers/block/ub.c # 2005/03/18 17:31:40-08:00 zaitcev@redhat.com +1 -1 # USB: ub static patch # # ChangeSet # 2005/03/23 15:26:40-08:00 gregkh@suse.de # USB: fix bug in visor driver with throttle/unthrottle causing oopses. # # Thanks to Mark Lord for reporting this and helping with testing. # # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/serial/visor.c # 2005/03/23 15:26:23-08:00 gregkh@suse.de +27 -11 # USB: fix bug in visor driver with throttle/unthrottle causing oopses. # # Thanks to Mark Lord for reporting this and helping with testing. # # Signed-off-by: Greg Kroah-Hartman # # ChangeSet # 2005/03/21 22:36:57-08:00 stern@rowland.harvard.edu # [PATCH] UHCI updates # # This is the fifth of five updates to the uhci-hcd driver: # # Separate out the part of the driver responsible for scanning the # schedule and doing delayed processing. Put it in a new routine # which can be called as needed (such as when the controller is # suspended) from several places in addition to the usual IRQ # handler. # # Signed-off-by: Alan Stern # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/host/uhci-q.c # 2005/03/14 10:01:36-08:00 stern@rowland.harvard.edu +55 -0 # UHCI updates # # drivers/usb/host/uhci-hcd.h # 2005/03/14 10:01:36-08:00 stern@rowland.harvard.edu +4 -1 # UHCI updates # # drivers/usb/host/uhci-hcd.c # 2005/03/14 10:01:36-08:00 stern@rowland.harvard.edu +6 -60 # UHCI updates # # ChangeSet # 2005/03/21 22:36:17-08:00 stern@rowland.harvard.edu # [PATCH] UHCI updates # # This is the fourth of five updates to the uhci-hcd driver: # # Reimplement the get_current_frame routines so that when the # controller isn't running they return a cached value. Also add # a flag to track whether the controller is running and allow # critical data structure updates to occur immediately if the # controller is stopped. # # Signed-off-by: Alan Stern # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/host/uhci-q.c # 2005/03/21 22:33:16-08:00 stern@rowland.harvard.edu +14 -17 # UHCI updates # # drivers/usb/host/uhci-hcd.h # 2005/03/21 22:33:16-08:00 stern@rowland.harvard.edu +3 -1 # UHCI updates # # drivers/usb/host/uhci-hcd.c # 2005/03/21 22:34:27-08:00 stern@rowland.harvard.edu +35 -16 # UHCI updates # # ChangeSet # 2005/03/21 22:30:56-08:00 stern@rowland.harvard.edu # [PATCH] UHCI updates # # This is the third of five updates to the uhci-hcd driver: # # Change the first argument to uhci_finish_completion from hcd # to uhci and expand the spinlock-protected region to include # the entire timer callback routine plus the suspend and resume # routines. It's a little awkward that the reset routine must # run without the spinlock, but that whole pathway will vanish # before long. # # Signed-off-by: Alan Stern # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/host/uhci-q.c # 2005/03/14 09:53:09-08:00 stern@rowland.harvard.edu +2 -3 # UHCI updates # # drivers/usb/host/uhci-hcd.c # 2005/03/14 09:53:09-08:00 stern@rowland.harvard.edu +18 -5 # UHCI updates # # ChangeSet # 2005/03/21 22:27:09-08:00 stern@rowland.harvard.edu # [PATCH] UHCI updates # # This is the second of five updates to the uhci-hcd driver: # # Reimplement the port reset function by splitting it into two # parts like the other HC drivers do, where the second part is # triggered by a port status request when the reset finishes. Now # the entire hub_control routine can run without sleeping and can # hold the device spinlock. # # Signed-off-by: Alan Stern # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/host/uhci-hub.c # 2005/03/14 09:30:15-08:00 stern@rowland.harvard.edu +30 -16 # UHCI updates # # drivers/usb/host/uhci-hcd.h # 2005/03/14 09:30:15-08:00 stern@rowland.harvard.edu +2 -2 # UHCI updates # # drivers/usb/host/uhci-hcd.c # 2005/03/14 09:30:15-08:00 stern@rowland.harvard.edu +1 -1 # UHCI updates # # ChangeSet # 2005/03/21 22:26:12-08:00 stern@rowland.harvard.edu # [PATCH] UHCI updates # # This is the first of five updates to the uhci-hcd driver: # # Rename the uhci->schedule_lock to just plain uhci->lock. # Originally I had thought of adding a separate device-management # lock, but now it seems better to use a single lock for both # purposes. # # Signed-off-by: Alan Stern # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/host/uhci-q.c # 2005/03/14 09:26:50-08:00 stern@rowland.harvard.edu +8 -8 # UHCI updates # # drivers/usb/host/uhci-hcd.h # 2005/03/14 09:26:50-08:00 stern@rowland.harvard.edu +12 -12 # UHCI updates # # drivers/usb/host/uhci-hcd.c # 2005/03/14 09:26:50-08:00 stern@rowland.harvard.edu +7 -7 # UHCI updates # # drivers/usb/host/uhci-debug.c # 2005/03/14 09:26:50-08:00 stern@rowland.harvard.edu +2 -2 # UHCI updates # # ChangeSet # 2005/03/21 22:24:51-08:00 stern@rowland.harvard.edu # [PATCH] USBcore updates # # This is the fifth of five updates to usbcore: # # Add some extra debugging messages to the hub driver and make it # set the power state for root hubs like it does for external hubs. # # Signed-off-by: Alan Stern # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/core/hub.c # 2005/03/14 07:26:56-08:00 stern@rowland.harvard.edu +11 -2 # USBcore updates # # ChangeSet # 2005/03/21 15:04:00-08:00 stern@rowland.harvard.edu # [PATCH] USBcore updates # # This is the fourth of five updates to usbcore: # # Add a new usb_hcd_resume_root_hub function for use by HCDs in # processing resume requests from their root hubs. No calls to # this new routine are in the patch but they will be added in # due course. # # Signed-off-by: Alan Stern # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/core/usb.h # 2005/03/21 15:00:03-08:00 stern@rowland.harvard.edu +1 -0 # USBcore updates # # drivers/usb/core/hub.h # 2005/03/21 15:00:03-08:00 stern@rowland.harvard.edu +1 -0 # USBcore updates # # drivers/usb/core/hub.c # 2005/03/21 15:00:03-08:00 stern@rowland.harvard.edu +14 -0 # USBcore updates # # drivers/usb/core/hcd.h # 2005/03/21 15:00:03-08:00 stern@rowland.harvard.edu +2 -0 # USBcore updates # # drivers/usb/core/hcd.c # 2005/03/21 15:01:10-08:00 stern@rowland.harvard.edu +24 -0 # USBcore updates # # ChangeSet # 2005/03/21 14:58:02-08:00 stern@rowland.harvard.edu # [PATCH] USBcore updates # # This is the third of five updates to usbcore: # # Adjust the usb_hc_died routine to eliminate races with root-hub # registration/deregistration and have it tell khubd to remove # all devices below the root hub. # # Signed-off-by: Alan Stern # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/core/usb.h # 2005/03/14 07:19:06-08:00 stern@rowland.harvard.edu +2 -0 # USBcore updates # # drivers/usb/core/hub.c # 2005/03/14 07:19:06-08:00 stern@rowland.harvard.edu +16 -1 # USBcore updates # # drivers/usb/core/hcd.h # 2005/03/14 07:19:06-08:00 stern@rowland.harvard.edu +2 -0 # USBcore updates # # drivers/usb/core/hcd.c # 2005/03/14 07:19:06-08:00 stern@rowland.harvard.edu +29 -3 # USBcore updates # # ChangeSet # 2005/03/21 14:43:56-08:00 stern@rowland.harvard.edu # [PATCH] USBcore and HCD updates # # This is the second of five updates to usbcore: # # Rename the hcd->state constants so that they all begin with # HC_STATE. Right now some of them start with HCD_STATE and # others with USB_STATE, which can be very confusing. # # Signed-off-by: Alan Stern # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/host/uhci-hcd.c # 2005/03/21 14:28:32-08:00 stern@rowland.harvard.edu +2 -2 # USBcore and HCD updates # # drivers/usb/host/sl811-hcd.c # 2005/03/21 14:29:26-08:00 stern@rowland.harvard.edu +3 -3 # USBcore and HCD updates # # drivers/usb/host/ohci.h # 2005/03/21 14:28:32-08:00 stern@rowland.harvard.edu +1 -1 # USBcore and HCD updates # # drivers/usb/host/ohci-q.c # 2005/03/21 14:28:32-08:00 stern@rowland.harvard.edu +5 -5 # USBcore and HCD updates # # drivers/usb/host/ohci-omap.c # 2005/03/21 14:28:32-08:00 stern@rowland.harvard.edu +1 -1 # USBcore and HCD updates # # drivers/usb/host/ohci-hub.c # 2005/03/21 14:28:32-08:00 stern@rowland.harvard.edu +7 -7 # USBcore and HCD updates # # drivers/usb/host/ohci-hcd.c # 2005/03/21 14:28:32-08:00 stern@rowland.harvard.edu +9 -9 # USBcore and HCD updates # # drivers/usb/host/ehci-sched.c # 2005/03/21 14:28:32-08:00 stern@rowland.harvard.edu +6 -6 # USBcore and HCD updates # # drivers/usb/host/ehci-q.c # 2005/03/21 14:28:32-08:00 stern@rowland.harvard.edu +7 -7 # USBcore and HCD updates # # drivers/usb/host/ehci-hub.c # 2005/03/21 14:28:32-08:00 stern@rowland.harvard.edu +5 -5 # USBcore and HCD updates # # drivers/usb/host/ehci-hcd.c # 2005/03/21 14:28:32-08:00 stern@rowland.harvard.edu +12 -12 # USBcore and HCD updates # # drivers/usb/gadget/dummy_hcd.c # 2005/03/21 14:28:32-08:00 stern@rowland.harvard.edu +2 -2 # USBcore and HCD updates # # drivers/usb/core/hcd.h # 2005/03/21 14:28:32-08:00 stern@rowland.harvard.edu +7 -7 # USBcore and HCD updates # # drivers/usb/core/hcd.c # 2005/03/21 14:28:32-08:00 stern@rowland.harvard.edu +11 -11 # USBcore and HCD updates # # drivers/usb/core/hcd-pci.c # 2005/03/21 14:28:32-08:00 stern@rowland.harvard.edu +7 -7 # USBcore and HCD updates # # ChangeSet # 2005/03/18 15:08:47-08:00 stern@rowland.harvard.edu # [PATCH] USBcore updates # # This is the first of five updates to usbcore: # # Merge the hcd_register_root macro with the usb_register_root_hub # function. This is part of the ongoing campaign to flatten out # the hcd glue layer. # # Signed-off-by: Alan Stern # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/host/uhci-hcd.c # 2005/03/18 14:22:27-08:00 stern@rowland.harvard.edu +1 -1 # USBcore updates # # drivers/usb/host/sl811-hcd.c # 2005/03/18 14:22:27-08:00 stern@rowland.harvard.edu +1 -1 # USBcore updates # # drivers/usb/host/ohci-hcd.c # 2005/03/18 14:22:27-08:00 stern@rowland.harvard.edu +1 -1 # USBcore updates # # drivers/usb/host/ehci-hcd.c # 2005/03/18 14:22:27-08:00 stern@rowland.harvard.edu +1 -1 # USBcore updates # # drivers/usb/gadget/dummy_hcd.c # 2005/03/18 14:22:27-08:00 stern@rowland.harvard.edu +1 -1 # USBcore updates # # drivers/usb/core/hcd.h # 2005/03/18 14:22:27-08:00 stern@rowland.harvard.edu +2 -19 # USBcore updates # # drivers/usb/core/hcd.c # 2005/03/18 14:23:34-08:00 stern@rowland.harvard.edu +15 -6 # USBcore updates # # ChangeSet # 2005/03/18 13:56:40-08:00 olh@suse.de # [PATCH] USB: another broken usb floppy # # Signed-off-by: Olaf Hering # Signed-off-by: Phil Dibowitz # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/storage/unusual_devs.h # 2005/03/18 13:53:59-08:00 olh@suse.de +7 -0 # USB: another broken usb floppy # # ChangeSet # 2005/03/18 13:51:56-08:00 phil@ipom.com # [PATCH] USB unusual_devs: add another datafab device # # The following was reported by Josef Reisinger # . This entry allows the device to be # found and prevents it from showing up twice. # # Signed-off-by: Phil Dibowitz # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/storage/unusual_devs.h # 2005/01/01 22:31:04-08:00 phil@ipom.com +7 -0 # USB unusual_devs: add another datafab device # # ChangeSet # 2005/03/18 13:51:36-08:00 phil@ipom.com # [PATCH] USB unusual_devs: Add another Tekom entry # # This patch adds support for Another "Tekom 300" camera - or more # specifically a BenQ DC5330. # # Versions of this patch were submitted by both Frank Copeland # and Manuel Fombuena - but # neither were quite right, so I've tweaked it accordingly. # # Signed-off-by: Phil Dibowitz # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/storage/unusual_devs.h # 2005/03/13 21:18:47-08:00 phil@ipom.com +9 -0 # USB unusual_devs: Add another Tekom entry # # ChangeSet # 2005/03/18 13:51:17-08:00 gmenguez@usuarios.retecal.es # [PATCH] USB: Support for new ipod mini (and possibly others) + usb # # Just a little patch to unusual_devs.h in usb-storage in order to support # new ipods mini (ie. the new 6 gig model) and possibly other new big # models reported to have problems through usb in linux 2.6. # # # From: Guillermo Menguez Alvarez # Signed-off-by: Phil Dibowitz # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/storage/unusual_devs.h # 2005/03/12 06:54:43-08:00 gmenguez@usuarios.retecal.es +6 -0 # USB: Support for new ipod mini (and possibly others) + usb # # ChangeSet # 2005/03/18 13:40:24-08:00 clemens@ladisch.de # [PATCH] emi26: add another product ID for the Emi2|6/A26 # # This adds the product ID for another hardware revision of the Emi 2|6. # Except for the ID, this device behaves the same and uses the same # firmware. # # Signed-off-by: Clemens Ladisch # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/misc/emi26.c # 2005/03/12 09:19:39-08:00 clemens@ladisch.de +2 -0 # emi26: add another product ID for the Emi2|6/A26 # # ChangeSet # 2005/03/17 18:15:50-08:00 gregkh@suse.de # [PATCH] USB Storage: remove unneeded unusual_devs.h entry. # # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/storage/unusual_devs.h # 2005/03/17 18:12:25-08:00 gregkh@suse.de +0 -6 # USB Storage: remove unneeded unusual_devs.h entry. # # ChangeSet # 2005/03/17 18:15:30-08:00 mdharm-usb@one-eyed-alien.net # [PATCH] USB Storage: change how unusual_devs.h flags are defined # # This patch started life as as473 from Alan Stern, and has been rediffed # against the current tip. # # This patch changes the way the flags bits are defined, so that the # proc_info routine can automatically list all the flags that are set. As a # side effect it will also include the NEED_OVERRIDE flag; that shouldn't # really matter. (As another side effect, the definitions grew too long to # fit on a single 80-character line so I had to wrap the comments.) # # This patch also takes the opportunity to remove a couple of obsolete flags # and to renumber the bit values. The patch also removes an unusual_devs # entry whose only purpose was to set one of those obsolete flags; apparently # it got left behind when all the other uses of those flags were removed. # # Signed-off-by: Alan Stern # Signed-off-by: Matthew Dharm # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/storage/usb.h # 2005/03/13 21:34:07-08:00 mdharm-usb@one-eyed-alien.net +27 -12 # USB Storage: change how unusual_devs.h flags are defined # # drivers/usb/storage/scsiglue.c # 2005/03/13 21:34:07-08:00 mdharm-usb@one-eyed-alien.net +4 -6 # USB Storage: change how unusual_devs.h flags are defined # # ChangeSet # 2005/03/17 18:15:11-08:00 rddunlap@osdl.org # [PATCH] pwc: fix printk arg types # # Fix gcc printk arg type warnings: # drivers/usb/media/pwc/pwc-if.c:325: warning: int format, different type arg (arg 2) # drivers/usb/media/pwc/pwc-if.c:1182: warning: int format, different type arg (arg 4) # # Signed-off-by: Randy Dunlap # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/media/pwc/pwc-if.c # 2005/03/14 12:04:31-08:00 rddunlap@osdl.org +2 -2 # pwc: fix printk arg types # # ChangeSet # 2005/03/17 18:14:52-08:00 rddunlap@osdl.org # [PATCH] sisusb: fix arg. types # # Fix gcc printk arg type and other function parameter warnings: # # drivers/usb/misc/sisusbvga/sisusb.c: In function `sisusb_send_packet': # drivers/usb/misc/sisusbvga/sisusb.c:583: warning: passing arg 7 of `sisusb_send_bulk_msg' from incompatible pointer type # drivers/usb/misc/sisusbvga/sisusb.c:591: warning: passing arg 6 of `sisusb_recv_bulk_msg' from incompatible pointer type # drivers/usb/misc/sisusbvga/sisusb.c: In function `sisusb_send_bridge_packet': # drivers/usb/misc/sisusbvga/sisusb.c:620: warning: passing arg 7 of `sisusb_send_bulk_msg' from incompatible pointer type # drivers/usb/misc/sisusbvga/sisusb.c:628: warning: passing arg 6 of `sisusb_recv_bulk_msg' from incompatible pointer type # drivers/usb/misc/sisusbvga/sisusb.c: In function `sisusb_write_mem_bulk': # drivers/usb/misc/sisusbvga/sisusb.c:989: warning: int format, different type arg (arg 3) # drivers/usb/misc/sisusbvga/sisusb.c:989: warning: int format, different type arg (arg 3) # drivers/usb/misc/sisusbvga/sisusb.c: In function `sisusb_clear_vram': # drivers/usb/misc/sisusbvga/sisusb.c:1407: warning: passing arg 7 of `sisusb_write_mem_bulk' from incompatible pointer type # # Signed-off-by: Randy Dunlap # Signed-off-by: Thomas Winischhofer # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/misc/sisusbvga/sisusb.c # 2005/03/14 11:57:23-08:00 rddunlap@osdl.org +5 -4 # sisusb: fix arg. types # # ChangeSet # 2005/03/17 18:14:33-08:00 mdharm-usb@one-eyed-alien.net # [PATCH] USB Storage: remove unneeded NULL tests # # This patch started life as as472 from Alan Stern, and has been rediffed # against the current tip. # # This patch simply removes some unnecessary NULL checking before kfree() # calls. # # Signed-off-by: Alan Stern # Signed-off-by: Matthew Dharm # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/storage/usb.c # 2005/03/13 21:34:20-08:00 mdharm-usb@one-eyed-alien.net +2 -5 # USB Storage: remove unneeded NULL tests # # ChangeSet # 2005/03/17 18:14:14-08:00 mdharm-usb@one-eyed-alien.net # [PATCH] USB Storage: Header reorganization # # This patch started life as as471 from Alan Stern, and has been regenerated # against the current tip. # # This patch cleans up the use of header files. Primarily it makes sure # that "usb.h" is included before any of the other local headers. It also # removes some unnecessary declarations of struct us_data and struct # scsi_cmnd, and it moves the inclusion of to usb.h where # it will be needed by a later patch. # # # Signed-off-by: Alan Stern # Signed-off-by: Matthew Dharm # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/storage/usb.h # 2005/03/13 21:34:34-08:00 mdharm-usb@one-eyed-alien.net +1 -0 # USB Storage: Header reorganization # # drivers/usb/storage/usb.c # 2005/03/13 21:34:34-08:00 mdharm-usb@one-eyed-alien.net +3 -4 # USB Storage: Header reorganization # # drivers/usb/storage/transport.h # 2005/03/13 21:34:34-08:00 mdharm-usb@one-eyed-alien.net +0 -3 # USB Storage: Header reorganization # # drivers/usb/storage/transport.c # 2005/03/13 21:34:34-08:00 mdharm-usb@one-eyed-alien.net +1 -1 # USB Storage: Header reorganization # # drivers/usb/storage/shuttle_usbat.c # 2005/03/13 21:34:34-08:00 mdharm-usb@one-eyed-alien.net +1 -1 # USB Storage: Header reorganization # # drivers/usb/storage/sddr55.c # 2005/03/13 21:34:34-08:00 mdharm-usb@one-eyed-alien.net +1 -1 # USB Storage: Header reorganization # # drivers/usb/storage/sddr09.c # 2005/03/13 21:34:34-08:00 mdharm-usb@one-eyed-alien.net +1 -1 # USB Storage: Header reorganization # # drivers/usb/storage/scsiglue.h # 2005/03/13 21:34:34-08:00 mdharm-usb@one-eyed-alien.net +0 -5 # USB Storage: Header reorganization # # drivers/usb/storage/scsiglue.c # 2005/03/13 21:34:34-08:00 mdharm-usb@one-eyed-alien.net +1 -2 # USB Storage: Header reorganization # # drivers/usb/storage/protocol.h # 2005/03/13 21:34:34-08:00 mdharm-usb@one-eyed-alien.net +0 -3 # USB Storage: Header reorganization # # drivers/usb/storage/protocol.c # 2005/03/13 21:34:34-08:00 mdharm-usb@one-eyed-alien.net +2 -1 # USB Storage: Header reorganization # # drivers/usb/storage/jumpshot.c # 2005/03/13 21:34:34-08:00 mdharm-usb@one-eyed-alien.net +1 -1 # USB Storage: Header reorganization # # drivers/usb/storage/isd200.c # 2005/03/13 21:34:34-08:00 mdharm-usb@one-eyed-alien.net +1 -1 # USB Storage: Header reorganization # # drivers/usb/storage/initializers.c # 2005/03/13 21:34:34-08:00 mdharm-usb@one-eyed-alien.net +2 -0 # USB Storage: Header reorganization # # drivers/usb/storage/freecom.c # 2005/03/13 21:34:34-08:00 mdharm-usb@one-eyed-alien.net +1 -1 # USB Storage: Header reorganization # # drivers/usb/storage/dpcm.c # 2005/03/13 21:34:34-08:00 mdharm-usb@one-eyed-alien.net +1 -1 # USB Storage: Header reorganization # # drivers/usb/storage/debug.h # 2005/03/13 21:34:34-08:00 mdharm-usb@one-eyed-alien.net +0 -2 # USB Storage: Header reorganization # # drivers/usb/storage/datafab.c # 2005/03/13 21:34:34-08:00 mdharm-usb@one-eyed-alien.net +1 -1 # USB Storage: Header reorganization # # ChangeSet # 2005/03/17 18:13:54-08:00 okir@suse.de # [PATCH] USB: fix uhci irq 10: nobody cared! error # # From: Olaf Kirch # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/host/uhci-hcd.c # 2005/03/17 16:00:00-08:00 okir@suse.de +3 -1 # USB: fix uhci irq 10: nobody cared! error # # ChangeSet # 2005/03/17 18:13:34-08:00 domen@coderock.org # [PATCH] USB: compile warning cleanup # # compile warning cleanup - handle error return from # scsi_add_host # # Signed-off-by: Stephen Biggs # Signed-off-by: Domen Puncer # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/image/microtek.c # 2005/03/05 07:13:09-08:00 domen@coderock.org +6 -2 # USB: compile warning cleanup # # ChangeSet # 2005/03/17 18:13:15-08:00 domen@coderock.org # [PATCH] usb/digi_acceleport: remove interruptible_sleep_on_timeout() usage # # Replace deprecated interruptible_sleep_on_timeout() with direct # wait-queue usage. Also replace some rather odd wait-queue usage with the # existent macros. Also adjusted the wake_up_interruptible() call appropriately, # as I changed all the states to TASK_UNINTERRUPTIBLE (signals were not be checked # in the current code). Patch is compile-tested. # # Signed-off-by: Nishanth Aravamudan # Signed-off-by: Domen Puncer # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/serial/digi_acceleport.c # 2005/03/05 07:12:12-08:00 domen@coderock.org +11 -18 # usb/digi_acceleport: remove interruptible_sleep_on_timeout() usage # # ChangeSet # 2005/03/17 18:12:55-08:00 domen@coderock.org # [PATCH] usb/rio500: remove interruptible_sleep_on_timeout() usage # # Replace deprecated interruptible_sleep_on_timeout() with direct # wait-queue usage. Patch is compile-tested. # # Signed-off-by: Nishanth Aravamudan # Signed-off-by: Domen Puncer # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/misc/rio500.c # 2005/03/05 07:12:11-08:00 domen@coderock.org +9 -3 # usb/rio500: remove interruptible_sleep_on_timeout() usage # # ChangeSet # 2005/03/17 17:58:07-08:00 oliver@neukum.org # [PATCH] USB: removal of obsolete error code from kaweth # # this patch from David removes an obsolete error code from kaweth. # # Signed-off-by: Oliver Neukum # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/net/kaweth.c # 2005/03/04 23:57:34-08:00 oliver@neukum.org +1 -1 # USB: removal of obsolete error code from kaweth # # ChangeSet # 2005/03/17 17:57:47-08:00 stern@rowland.harvard.edu # [PATCH] USB: Prevent hub driver interference during port reset # # This patch causes the hub driver to ignore ports that are being reset by # another driver. Without this protection khubd will sometimes notice that # the port is behaving funny while the reset is taking place and will # unilaterally disconnect it, which is not what we want. # # Signed-off-by: Alan Stern # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/core/hub.h # 2005/02/27 05:30:15-08:00 stern@rowland.harvard.edu +1 -0 # USB: Prevent hub driver interference during port reset # # drivers/usb/core/hub.c # 2005/02/27 05:30:15-08:00 stern@rowland.harvard.edu +4 -0 # USB: Prevent hub driver interference during port reset # # ChangeSet # 2005/03/17 17:57:27-08:00 stern@rowland.harvard.edu # [PATCH] g_file_storage: add configuration and interface strings # # This patch adds iConfiguration and iInterface strings to the # g_file_storage driver (just to spiff it up and help in testing software # that looks at those strings). It also enlarges the space reserved for the # Manufacturer string, since combinations of long kernel names and long UDC # driver names were sometimes getting truncated. # # Signed-off-by: Alan Stern # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/gadget/file_storage.c # 2005/02/25 07:39:06-08:00 stern@rowland.harvard.edu +8 -2 # g_file_storage: add configuration and interface strings # # ChangeSet # 2005/03/17 17:57:07-08:00 stern@rowland.harvard.edu # [PATCH] usb-midi: fix arguments to usb_maxpacket() # # The usb-midi driver uses an incorrect value for the is_out argument to # usb_maxpacket(), triggering a WARN_ON. This patch fixes the mistake. # # Signed-off-by: Alan Stern # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/class/usb-midi.c # 2005/02/26 02:17:03-08:00 stern@rowland.harvard.edu +2 -2 # usb-midi: fix arguments to usb_maxpacket() # # ChangeSet # 2005/03/17 17:56:48-08:00 akpm@osdl.org # [PATCH] usb hcd u64 warning fix # # drivers/usb/core/hcd.c:1689: warning: long long unsigned int format, u64 arg (arg 6) # drivers/usb/core/hcd.c:1695: warning: long long unsigned int format, u64 arg (arg 5) # # We must not assume that u64 is implemented as `unsigned long long'. On ppc64 # (for example) it is `unsigned long'. # # Signed-off-by: Andrew Morton # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/core/hcd.c # 2005/02/28 07:44:29-08:00 akpm@osdl.org +4 -2 # usb hcd u64 warning fix # # ChangeSet # 2005/03/17 17:49:09-08:00 zaitcev@redhat.com # [PATCH] USB: Patch for ub to fix oops after disconnect # # This patch was developed by Glenn Maynard for his oops back in December, # but for some reason I forgot about it and had it reimplemented when I stepped # on this problem myself. In my case, there was no oops, but a warning about # slab corruption. # # Signed-off-by: Pete Zaitcev # Signed-off-by: Greg Kroah-Hartman # # drivers/block/ub.c # 2005/02/20 21:46:58-08:00 zaitcev@redhat.com +5 -6 # USB: Patch for ub to fix oops after disconnect # # ChangeSet # 2005/03/17 17:35:24-08:00 david-b@pacbell.net # [PATCH] USB: ethernet/rndis gadget driver updates # # Various fixes to the Ethernet/RNDIS gadget core code: # # - Pre-allocate the request used to transfer status back to the host. # Used initially for CDC Ethernet; RNDIS will change later. This # resolves a longstanding FIXME, elimininating fault modes. # # - Use larger packets for those status reports, 16 bytes not 8; this # eliminates some fault modes, without losing hardware support. # # - Streamline endpoint configuration, just save the endpoints during # driver binding. The previous scheme was a complex leftover from # before the endpoint autoselection library code existed, and this # bit of cleanup prepares for more simplifications later. # # - Implement a basic outgoing packet filter, for CDC Ethernet and RNDIS # but not the CDC subset. This improves conformance to both specs. # # - Correct the bit rate reports for CDC Ethernet and RNDIS to match # the peak bulk transfer rates, not the raw signaling rates. # # This still doesn't issue CDC or RNDIS link status change notifications # to the host as often as it should, but that'll be easier now. # # Signed-off-by: David Brownell # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/gadget/ether.c # 2005/02/28 18:26:02-08:00 david-b@pacbell.net +154 -92 # USB: ethernet/rndis gadget driver updates # # ChangeSet # 2005/03/17 17:35:05-08:00 david-b@pacbell.net # [PATCH] USB: net2280 reports correct dequeue status # # Minor bugfix to net2280: don't return incorrect dequeue() status. # # Signed-off-by: David Brownell # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/gadget/net2280.c # 2005/02/06 15:35:42-08:00 david-b@pacbell.net +1 -1 # USB: net2280 reports correct dequeue status # # ChangeSet # 2005/03/17 17:34:45-08:00 david-b@pacbell.net # [PATCH] USB: usbnet fix for Zaurus C-860 # # This patch resolves a recent problem with the Zaurus C-860 support. # # A change to correct handling of Zaurii that are lying about their support # for the "CDC Ethernet" class specification broke the C-860, which tells # an entirely different lie (that it supports "CDC MDLM", providing access # to a cell phone modem). The code expecting it to be telling a lie about # CDC Ethernet support naturally misbehaved. (Sharp should straighten out # its story. The 2.6 OpenZaurus kernels don't have any such issues...) # # The fix is just to recognize this bogus MDLM stuff and ignore it. # This patch also includes the two MDLM descriptors in # although they're not currently used. # # Signed-off-by: David Brownell # Signed-off-by: Greg Kroah-Hartman # # include/linux/usb_cdc.h # 2005/03/04 13:27:54-08:00 david-b@pacbell.net +32 -2 # USB: usbnet fix for Zaurus C-860 # # drivers/usb/net/usbnet.c # 2005/03/04 13:42:57-08:00 david-b@pacbell.net +31 -1 # USB: usbnet fix for Zaurus C-860 # # ChangeSet # 2005/03/17 17:34:24-08:00 david-b@pacbell.net # [PATCH] USB: usbnet gets status polling, uses for CDC Ethernet # # This adds status/interrupt transfer infrastructure to "usbnet", and # uses it for CDC Ethernet support. It can be used with other devices # that define an interrupt-IN endpoint (quite a few!), so long as the # meaning of the events is documented (erm, not so many). # # Signed-off-by: David Brownell # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/net/usbnet.c # 2005/02/03 23:10:02-08:00 david-b@pacbell.net +186 -9 # USB: usbnet gets status polling, uses for CDC Ethernet # # ChangeSet # 2005/03/17 17:34:04-08:00 david-b@pacbell.net # [PATCH] USB: ehci and short in-bulk transfers with 20KB+ urbs # # This changes handling of short bulk IN transfers with URB buffers that require # two or more transfer descriptors. The case is rare in most systems, since few # drivers use such large buffers (bigger than 20KB, assuming 4K-aligned). # # The existing code misbehave on at least NEC's EHCI 0.95 silicon, where it seems # to hit a new variant of a silicon quirk relating to dummy TDs. Symptom of the # misbehavior is that the host stops polling on the IN endpoint, and the URB queue # no longer progresses. # # This fix uses simpler logic to detect those short reads, dodging that quirk. # # Signed-off-by: David Brownell # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/host/ehci-q.c # 2005/03/03 10:55:26-08:00 david-b@pacbell.net +4 -3 # USB: ehci and short in-bulk transfers with 20KB+ urbs # # ChangeSet # 2005/03/17 17:33:44-08:00 david-b@pacbell.net # [PATCH] USB: ohci zero length control IN transfers # # This fixes a longstanding bug in the OHCI driver, inherited from the 2.4 # code. It also fixes a related comment in the EHCI driver, which came when # the EHCI code was first derived from OHCI. (The EHCI code doesn't have # that bug; the comment was effectively "FIXME add bug".) # # The bug: control-IN transfers with no data stages have status stages with # an IN packet (like a control-OUT transfer), instead of using an OUT packet. # See figure 8-37 of the USB spec. The current code makes trouble with some # peripheral hardware and zero length IN transfers (scarce in the Real World). # # Signed-off-by: David Brownell # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/host/ohci-q.c # 2005/03/01 13:28:30-08:00 david-b@pacbell.net +1 -1 # USB: ohci zero length control IN transfers # # drivers/usb/host/ehci-q.c # 2005/03/02 08:59:20-08:00 david-b@pacbell.net +1 -1 # USB: ohci zero length control IN transfers # # ChangeSet # 2005/03/17 17:33:24-08:00 david-b@pacbell.net # [PATCH] USB: usb gadget kconfig tweaks # # This makes two small changes to the gadget Kconfig. # # - It removes SA-1100 support ... if anyone gets around to # finishing that controller driver, it could go back, but # until then there's no real point. # # - The "dummy_hcd" moves to the end, with a comment to please # keep it there. # # Moving that Kconfig entry helps keep "real hardware" as the default # on systems that have it ... otherwise Kconfig will surprise people # with a curious default. # # Signed-off-by: David Brownell # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/gadget/Kconfig # 2005/02/28 18:57:37-08:00 david-b@pacbell.net +32 -43 # USB: usb gadget kconfig tweaks # # ChangeSet # 2005/03/17 17:33:03-08:00 david-b@pacbell.net # [PATCH] USB: add at91_udc recognition # # Add declarations to recognize the AT91 USB peripheral controller, # as used in various ARMv4T chips including the mmu-ful at91rm9200. # # Signed-off-by: David Brownell # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/gadget/zero.c # 2005/02/28 18:21:59-08:00 david-b@pacbell.net +2 -0 # USB: add at91_udc recognition # # drivers/usb/gadget/serial.c # 2005/02/28 18:21:59-08:00 david-b@pacbell.net +3 -0 # USB: add at91_udc recognition # # drivers/usb/gadget/gadget_chips.h # 2005/02/28 18:21:59-08:00 david-b@pacbell.net +6 -1 # USB: add at91_udc recognition # # drivers/usb/gadget/file_storage.c # 2005/02/28 18:21:59-08:00 david-b@pacbell.net +4 -0 # USB: add at91_udc recognition # # drivers/usb/gadget/ether.c # 2005/02/28 18:21:59-08:00 david-b@pacbell.net +6 -0 # USB: add at91_udc recognition # # ChangeSet # 2005/03/17 17:13:54-08:00 bunk@stusta.de # [PATCH] remove drivers/usb/image/hpusbscsi.c # # USB_HPUSBSCSI was marked as BROKEN in 2.6.11 since libsane is the # preferred way to access these devices. # # Unless someone plans to resurrect this driver, I'm therefore proposing # this patch to completely remove it. # # Signed-off-by: Adrian Bunk # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/image/Makefile # 2005/03/02 07:02:30-08:00 bunk@stusta.de +0 -1 # remove drivers/usb/image/hpusbscsi.c # # drivers/usb/image/Kconfig # 2005/03/03 05:24:33-08:00 bunk@stusta.de +0 -11 # remove drivers/usb/image/hpusbscsi.c # # drivers/usb/Makefile # 2005/03/02 07:02:18-08:00 bunk@stusta.de +0 -1 # remove drivers/usb/image/hpusbscsi.c # # BitKeeper/deleted/.del-hpusbscsi.h~d532117e5fee2a33 # 2005/03/17 17:13:35-08:00 bunk@stusta.de +0 -0 # Delete: drivers/usb/image/hpusbscsi.h # # BitKeeper/deleted/.del-hpusbscsi.c~b365c31f2ad86af1 # 2005/03/17 17:13:35-08:00 bunk@stusta.de +0 -0 # Delete: drivers/usb/image/hpusbscsi.c # # ChangeSet # 2005/03/17 17:09:47-08:00 bunk@stusta.de # [PATCH] drivers/usb/net/pegasus.c: make some code static # # This patch makes some needlessly global code static. # # Signed-off-by: Adrian Bunk # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/net/pegasus.c # 2005/02/28 14:27:45-08:00 bunk@stusta.de +4 -3 # drivers/usb/net/pegasus.c: make some code static # # ChangeSet # 2005/03/17 17:09:18-08:00 bunk@stusta.de # [PATCH] drivers/usb/storage/: cleanups # # This patch contains the following cleanups: # - make needlessly global code static # - scsiglue.c: remove the unused usb_stor_sense_notready # # Signed-off-by: Adrian Bunk # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/storage/usb.h # 2005/02/28 14:26:12-08:00 bunk@stusta.de +0 -3 # drivers/usb/storage/: cleanups # # drivers/usb/storage/usb.c # 2005/02/28 14:25:58-08:00 bunk@stusta.de +2 -2 # drivers/usb/storage/: cleanups # # drivers/usb/storage/transport.h # 2005/02/28 14:23:56-08:00 bunk@stusta.de +0 -5 # drivers/usb/storage/: cleanups # # drivers/usb/storage/transport.c # 2005/02/28 14:24:26-08:00 bunk@stusta.de +3 -2 # drivers/usb/storage/: cleanups # # drivers/usb/storage/shuttle_usbat.h # 2005/02/28 14:20:55-08:00 bunk@stusta.de +0 -4 # drivers/usb/storage/: cleanups # # drivers/usb/storage/shuttle_usbat.c # 2005/02/28 14:22:52-08:00 bunk@stusta.de +8 -5 # drivers/usb/storage/: cleanups # # drivers/usb/storage/scsiglue.h # 2005/02/28 14:18:41-08:00 bunk@stusta.de +0 -1 # drivers/usb/storage/: cleanups # # drivers/usb/storage/scsiglue.c # 2005/02/28 14:19:00-08:00 bunk@stusta.de +0 -9 # drivers/usb/storage/: cleanups # # ChangeSet # 2005/03/17 17:07:38-08:00 bunk@stusta.de # [PATCH] drivers/usb/serial/: make some functions static # # This patch makes some needlessly global functions static. # # Signed-off-by: Adrian Bunk # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/serial/ipw.c # 2005/02/28 14:33:43-08:00 bunk@stusta.de +2 -2 # drivers/usb/serial/: make some functions static # # drivers/usb/serial/garmin_gps.c # 2005/02/28 14:32:50-08:00 bunk@stusta.de +2 -2 # drivers/usb/serial/: make some functions static # # drivers/usb/serial/ftdi_sio.c # 2005/02/28 14:32:13-08:00 bunk@stusta.de +7 -5 # drivers/usb/serial/: make some functions static # # ChangeSet # 2005/03/17 17:04:11-08:00 bunk@stusta.de # [PATCH] USB: possible cleanups # # Before I'm getting flamed to death: # This patch contains possible cleanups. If parts of this patch conflict # with pending changes these parts of my patch have to be dropped. # # This patch contains the following possible cleanups: # - make needlessly global code static # - #if 0 the following unused global functions: # - core/usb.c: usb_buffer_map # - core/usb.c: usb_buffer_unmap # - remove the following unneeded EXPORT_SYMBOL's: # - core/hcd.c: usb_bus_init # - core/hcd.c: usb_alloc_bus # - core/hcd.c: usb_register_bus # - core/hcd.c: usb_deregister_bus # - core/hcd.c: usb_hcd_irq # - core/usb.c: usb_buffer_map # - core/usb.c: usb_buffer_unmap # - core/buffer.c: hcd_buffer_create # - core/buffer.c: hcd_buffer_destroy # # Signed-off-by: Adrian Bunk # Signed-off-by: Greg Kroah-Hartman # # include/linux/usb.h # 2005/02/28 15:38:40-08:00 bunk@stusta.de +2 -2 # USB: possible cleanups # # drivers/usb/net/kawethfw.h # 2005/02/28 15:10:01-08:00 bunk@stusta.de +4 -4 # USB: possible cleanups # # drivers/usb/net/catc.c # 2005/02/28 15:08:56-08:00 bunk@stusta.de +2 -1 # USB: possible cleanups # # drivers/usb/misc/sisusbvga/sisusb.c # 2005/02/28 15:07:14-08:00 bunk@stusta.de +4 -4 # USB: possible cleanups # # drivers/usb/media/ibmcam.c # 2005/02/28 15:05:09-08:00 bunk@stusta.de +2 -1 # USB: possible cleanups # # drivers/usb/input/aiptek.c # 2005/02/28 15:04:35-08:00 bunk@stusta.de +1 -1 # USB: possible cleanups # # drivers/usb/core/usb.h # 2005/02/28 15:03:31-08:00 bunk@stusta.de +0 -5 # USB: possible cleanups # # drivers/usb/core/usb.c # 2005/02/28 15:37:27-08:00 bunk@stusta.de +9 -5 # USB: possible cleanups # # drivers/usb/core/message.c # 2005/02/28 14:58:25-08:00 bunk@stusta.de +6 -4 # USB: possible cleanups # # drivers/usb/core/hub.c # 2005/02/28 14:56:41-08:00 bunk@stusta.de +2 -1 # USB: possible cleanups # # drivers/usb/core/hcd.h # 2005/02/28 14:52:44-08:00 bunk@stusta.de +0 -1 # USB: possible cleanups # # drivers/usb/core/hcd.c # 2005/02/28 15:27:36-08:00 bunk@stusta.de +1 -6 # USB: possible cleanups # # drivers/usb/core/config.c # 2005/02/28 14:49:04-08:00 bunk@stusta.de +1 -1 # USB: possible cleanups # # drivers/usb/core/buffer.c # 2005/02/28 15:28:42-08:00 bunk@stusta.de +0 -2 # USB: possible cleanups # # ChangeSet # 2005/03/14 23:57:02-08:00 gregkh@suse.de # USB: fix cpia_usb driver's warning messages in the syslog # # This fixes the cpia driver to call usb_kill_urb() instead of # usb_unlink_urb() which reduces the ammount of syslog messages when # kernel debugging is enabled. # # Signed-off-by: Greg Kroah-Hartman # # drivers/media/video/cpia_usb.c # 2005/03/14 23:56:43-08:00 gregkh@suse.de +2 -2 # USB: fix cpia_usb driver's warning messages in the syslog # # This fixes the cpia driver to call usb_kill_urb() instead of # usb_unlink_urb() which reduces the ammount of syslog messages when # kernel debugging is enabled. # # Signed-off-by: Greg Kroah-Hartman # # ChangeSet # 2005/03/14 22:57:48-08:00 gregkh@suse.de # [PATCH] USB: minor cleanup of string freeing in core code. # # As pointed out by Paulo Marques # # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/core/config.c # 2005/03/14 16:31:43-08:00 gregkh@suse.de +2 -2 # USB: minor cleanup of string freeing in core code. # # ChangeSet # 2005/03/14 22:57:23-08:00 gregkh@suse.de # [PATCH] USB: optimize the usb-storage device string logic a bit. # # As pointed out by Alan Stern # # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/storage/scsiglue.c # 2005/03/14 16:32:38-08:00 gregkh@suse.de +12 -8 # USB: optimize the usb-storage device string logic a bit. # diff -Nru a/Documentation/usb/usbmon.txt b/Documentation/usb/usbmon.txt --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/Documentation/usb/usbmon.txt 2005-03-24 18:21:08 -08:00 @@ -0,0 +1,156 @@ +* Introduction + +The name "usbmon" in lowercase refers to a facility in kernel which is +used to collect traces of I/O on the USB bus. This function is analogous +to a packet socket used by network monitoring tools such as tcpdump(1) +or Ethereal. Similarly, it is expected that a tool such as usbdump or +USBMon (with uppercase letters) is used to examine raw traces produced +by usbmon. + +The usbmon reports requests made by peripheral-specific drivers to Host +Controller Drivers (HCD). So, if HCD is buggy, the traces reported by +usbmon may not correspond to bus transactions precisely. This is the same +situation as with tcpdump. + +* How to use usbmon to collect raw text traces + +Unlike the packet socket, usbmon has an interface which provides traces +in a text format. This is used for two purposes. First, it serves as a +common trace exchange format for tools while most sophisticated formats +are finalized. Second, humans can read it in case tools are not available. + +To collect a raw text trace, execute following steps. + +1. Prepare + +Mount debugfs (it has to be enabled in your kernel configuration), and +load the usbmon module (if built as module). The second step is skipped +if usbmon is built into the kernel. + +# mount -t debugfs none_debugs /sys/kernel/debug +# modprobe usbmon + +Verify that bus sockets are present. + +[root@lembas zaitcev]# ls /sys/kernel/debug/usbmon +1s 1t 2s 2t 3s 3t 4s 4t +[root@lembas zaitcev]# + +# ls /sys/kernel + +2. Find which bus connects to the desired device + +Run "cat /proc/bus/usb/devices", and find the T-line which corresponds to +the device. Usually you do it by looking for the vendor string. If you have +many similar devices, unplug one and compare two /proc/bus/usb/devices outputs. +The T-line will have a bus number. Example: + +T: Bus=03 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 2 Spd=12 MxCh= 0 +D: Ver= 1.10 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1 +P: Vendor=0557 ProdID=2004 Rev= 1.00 +S: Manufacturer=ATEN +S: Product=UC100KM V2.00 + +Bus=03 means it's bus 3. + +3. Start 'cat' + +# cat /sys/kernel/debug/usbmon/3t > /tmp/1.mon.out + +This process will be reading until killed. Naturally, the output can be +redirected to a desirable location. This is preferred, because it is going +to be quite long. + +4. Perform the desired operation on the USB bus + +This is where you do something that creates the traffic: plug in a flash key, +copy files, control a webcam, etc. + +5. Kill cat + +Usually it's done with a keyboard interrupt (Control-C). + +At this point the output file (/tmp/1.mon.out in this example) can be saved, +sent by e-mail, or inspected with a text editor. In the last case make sure +that the file size is not excessive for your favourite editor. + +* Raw text data format + +The '0t' type data consists of a stream of events, such as URB submission, +URB callback, submission error. Every event is a text line, which consists +of whitespace separated words. The number of position of words may depend +on the event type, but there is a set of words, common for all types. + +Here is the list of words, from left to right: +- URB Tag. This is used to identify URBs is normally a kernel mode address + of the URB structure in hexadecimal. +- Timestamp in microseconds, a decimal number. The timestamp's resolution + depends on available clock, and so it can be much worse than a microsecond + (if the implementation uses jiffies, for example). +- Event Type. This type refers to the format of the event, not URB type. + Available types are: S - submission, C - callback, E - submission error. +- "Pipe". The pipe concept is deprecated. This is a composite word, used to + be derived from information in pipes. It consists of three fields, separated + by colons: URB type and direction, Device address, Endpoint number. + Type and direction are encoded with two bytes in the following manner: + Ci Co Control input and output + Zi Zo Isochronous input and output + Ii Io Interrupt input and output + Bi Bo Bulk input and output + Device address and Endpoint number are decimal numbers with leading zeroes + or 3 and 2 positions, correspondingly. +- URB Status. This field makes no sense for submissions, but is present + to help scripts with parsing. In error case, it contains the error code. +- Data Length. This is the actual length in the URB. +- Data tag. The usbmon may not always capture data, even if length is nonzero. + Only if tag is '=', the data words are present. +- Data words follow, in big endian hexadecimal format. Notice that they are + not machine words, but really just a byte stream split into words to make + it easier to read. Thus, the last word may contain from one to four bytes. + The length of collected data is limited and can be less than the data length + report in Data Length word. + +Here is an example of code to read the data stream in a well known programming +language: + +class ParsedLine { + int data_len; /* Available length of data */ + byte data[]; + + void parseData(StringTokenizer st) { + int availwords = st.countTokens(); + data = new byte[availwords * 4]; + data_len = 0; + while (st.hasMoreTokens()) { + String data_str = st.nextToken(); + int len = data_str.length() / 2; + int i; + for (i = 0; i < len; i++) { + data[data_len] = Byte.parseByte( + data_str.substring(i*2, i*2 + 2), + 16); + data_len++; + } + } + } +} + +This format is obviously deficient. For example, the setup packet for control +transfers is not delivered. This will change in the future. + +Examples: + +An input control transfer to get a port status: + +d74ff9a0 2640288196 S Ci:001:00 -115 4 < +d74ff9a0 2640288202 C Ci:001:00 0 4 = 01010100 + +An output bulk transfer to send a SCSI command 0x5E in a 31-byte Bulk wrapper +to a storage device at address 5: + +dd65f0e8 4128379752 S Bo:005:02 -115 31 = 55534243 5e000000 00000000 00000600 00000000 00000000 00000000 000000 +dd65f0e8 4128379808 C Bo:005:02 0 31 > + +* Raw binary format and API + +TBD diff -Nru a/MAINTAINERS b/MAINTAINERS --- a/MAINTAINERS 2005-03-24 18:21:08 -08:00 +++ b/MAINTAINERS 2005-03-24 18:21:08 -08:00 @@ -2313,6 +2313,13 @@ L: linux-usb-devel@lists.sourceforge.net S: Maintained +USB BLOCK DRIVER (UB ub) +P: Pete Zaitcev +M: zaitcev@redhat.com +L: linux-kernel@vger.kernel.org +L: linux-usb-devel@lists.sourceforge.net +S: Supported + USB BLUETOOTH TTY CONVERTER DRIVER P: Greg Kroah-Hartman M: greg@kroah.com @@ -2661,11 +2668,11 @@ L: linux-hams@vger.kernel.org S: Maintained -YMFPCI YAMAHA PCI SOUND +YMFPCI YAMAHA PCI SOUND (Use ALSA instead) P: Pete Zaitcev M: zaitcev@yahoo.com L: linux-kernel@vger.kernel.org -S: Maintained +S: Obsolete Z8530 DRIVER FOR AX.25 P: Joerg Reuter diff -Nru a/arch/arm/mach-omap/usb.c b/arch/arm/mach-omap/usb.c --- a/arch/arm/mach-omap/usb.c 2005-03-24 18:21:08 -08:00 +++ b/arch/arm/mach-omap/usb.c 2005-03-24 18:21:08 -08:00 @@ -322,8 +322,8 @@ static struct resource ohci_resources[] = { { - .start = IO_ADDRESS(OMAP_OHCI_BASE), - .end = IO_ADDRESS(OMAP_OHCI_BASE + 4096), + .start = OMAP_OHCI_BASE, + .end = OMAP_OHCI_BASE + 4096, .flags = IORESOURCE_MEM, }, { diff -Nru a/drivers/block/ub.c b/drivers/block/ub.c --- a/drivers/block/ub.c 2005-03-24 18:21:08 -08:00 +++ b/drivers/block/ub.c 2005-03-24 18:21:08 -08:00 @@ -496,6 +496,11 @@ */ static void ub_cleanup(struct ub_dev *sc) { + request_queue_t *q; + + /* I don't think queue can be NULL. But... Stolen from sx8.c */ + if ((q = sc->disk->queue) != NULL) + blk_cleanup_queue(q); /* * If we zero disk->private_data BEFORE put_disk, we have to check @@ -2056,7 +2061,6 @@ { struct ub_dev *sc = usb_get_intfdata(intf); struct gendisk *disk = sc->disk; - request_queue_t *q = disk->queue; unsigned long flags; /* @@ -2099,13 +2103,8 @@ */ if (disk->flags & GENHD_FL_UP) del_gendisk(disk); - if (q) - blk_cleanup_queue(q); /* - * We really expect blk_cleanup_queue() to wait, so no amount - * of paranoya is too much. - * * Taking a lock on a structure which is about to be freed * is very nonsensual. Here it is largely a way to do a debug freeze, * and a bracket which shows where the nonsensual code segment ends. @@ -2145,7 +2144,7 @@ spin_unlock_irqrestore(&ub_lock, flags); } -struct usb_driver ub_driver = { +static struct usb_driver ub_driver = { .owner = THIS_MODULE, .name = "ub", .probe = ub_probe, diff -Nru a/drivers/media/video/cpia_usb.c b/drivers/media/video/cpia_usb.c --- a/drivers/media/video/cpia_usb.c 2005-03-24 18:21:08 -08:00 +++ b/drivers/media/video/cpia_usb.c 2005-03-24 18:21:08 -08:00 @@ -440,7 +440,7 @@ /* Unschedule all of the iso td's */ if (ucpia->sbuf[1].urb) { - usb_unlink_urb(ucpia->sbuf[1].urb); + usb_kill_urb(ucpia->sbuf[1].urb); usb_free_urb(ucpia->sbuf[1].urb); ucpia->sbuf[1].urb = NULL; } @@ -451,7 +451,7 @@ } if (ucpia->sbuf[0].urb) { - usb_unlink_urb(ucpia->sbuf[0].urb); + usb_kill_urb(ucpia->sbuf[0].urb); usb_free_urb(ucpia->sbuf[0].urb); ucpia->sbuf[0].urb = NULL; } diff -Nru a/drivers/usb/Makefile b/drivers/usb/Makefile --- a/drivers/usb/Makefile 2005-03-24 18:21:08 -08:00 +++ b/drivers/usb/Makefile 2005-03-24 18:21:08 -08:00 @@ -50,8 +50,8 @@ obj-$(CONFIG_USB_PEGASUS) += net/ obj-$(CONFIG_USB_RTL8150) += net/ obj-$(CONFIG_USB_USBNET) += net/ +obj-$(CONFIG_USB_ZD1201) += net/ -obj-$(CONFIG_USB_HPUSBSCSI) += image/ obj-$(CONFIG_USB_MDC800) += image/ obj-$(CONFIG_USB_MICROTEK) += image/ diff -Nru a/drivers/usb/class/usb-midi.c b/drivers/usb/class/usb-midi.c --- a/drivers/usb/class/usb-midi.c 2005-03-24 18:21:08 -08:00 +++ b/drivers/usb/class/usb-midi.c 2005-03-24 18:21:08 -08:00 @@ -992,7 +992,7 @@ endPoint &= 0x0f; /* Silently force endPoint to lie in range 0 to 15. */ pipe = usb_rcvbulkpipe( d, endPoint ); - bufSize = usb_maxpacket( d, pipe, usb_pipein(pipe) ); + bufSize = usb_maxpacket( d, pipe, 0 ); /* usb_pipein() = ! usb_pipeout() = true for an in Endpoint */ ep = (struct midi_in_endpoint *)kmalloc(sizeof(struct midi_in_endpoint), GFP_KERNEL); @@ -1063,7 +1063,7 @@ endPoint &= 0x0f; pipe = usb_sndbulkpipe( d, endPoint ); - bufSize = usb_maxpacket( d, pipe, usb_pipeout(pipe) ); + bufSize = usb_maxpacket( d, pipe, 1 ); ep = (struct midi_out_endpoint *)kmalloc(sizeof(struct midi_out_endpoint), GFP_KERNEL); if ( !ep ) { diff -Nru a/drivers/usb/core/buffer.c b/drivers/usb/core/buffer.c --- a/drivers/usb/core/buffer.c 2005-03-24 18:21:08 -08:00 +++ b/drivers/usb/core/buffer.c 2005-03-24 18:21:08 -08:00 @@ -76,7 +76,6 @@ } return 0; } -EXPORT_SYMBOL (hcd_buffer_create); /** @@ -98,7 +97,6 @@ } } } -EXPORT_SYMBOL (hcd_buffer_destroy); /* sometimes alloc/free could use kmalloc with SLAB_DMA, for diff -Nru a/drivers/usb/core/config.c b/drivers/usb/core/config.c --- a/drivers/usb/core/config.c 2005-03-24 18:21:08 -08:00 +++ b/drivers/usb/core/config.c 2005-03-24 18:21:08 -08:00 @@ -221,7 +221,7 @@ return buffer - buffer0 + i; } -int usb_parse_configuration(struct device *ddev, int cfgidx, +static int usb_parse_configuration(struct device *ddev, int cfgidx, struct usb_host_config *config, unsigned char *buffer, int size) { unsigned char *buffer0 = buffer; @@ -420,8 +420,8 @@ for (c = 0; c < dev->descriptor.bNumConfigurations; c++) { struct usb_host_config *cf = &dev->config[c]; - if (cf->string) - kfree(cf->string); + kfree(cf->string); + cf->string = NULL; for (i = 0; i < cf->desc.bNumInterfaces; i++) { if (cf->intf_cache[i]) diff -Nru a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c --- a/drivers/usb/core/devices.c 2005-03-24 18:21:08 -08:00 +++ b/drivers/usb/core/devices.c 2005-03-24 18:21:08 -08:00 @@ -460,7 +460,7 @@ return 0; if (level > MAX_TOPO_LEVEL) - return total_written; + return 0; /* allocate 2^1 pages = 8K (on i386); should be more than enough for one device */ if (!(pages_start = (char*) __get_free_pages(GFP_KERNEL,1))) return -ENOMEM; @@ -527,10 +527,7 @@ length = *nbytes; if (copy_to_user(*buffer, pages_start + *skip_bytes, length)) { free_pages((unsigned long)pages_start, 1); - - if (total_written == 0) - return -EFAULT; - return total_written; + return -EFAULT; } *nbytes -= length; *file_offset += length; diff -Nru a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c --- a/drivers/usb/core/hcd-pci.c 2005-03-24 18:21:08 -08:00 +++ b/drivers/usb/core/hcd-pci.c 2005-03-24 18:21:08 -08:00 @@ -226,8 +226,8 @@ /* entry if root hub wasn't yet suspended ... from sysfs, * without autosuspend, or if USB_SUSPEND isn't configured. */ - case USB_STATE_RUNNING: - hcd->state = USB_STATE_QUIESCING; + case HC_STATE_RUNNING: + hcd->state = HC_STATE_QUIESCING; retval = hcd->driver->suspend (hcd, state); if (retval) { dev_dbg (hcd->self.controller, @@ -235,7 +235,7 @@ retval); break; } - hcd->state = HCD_STATE_SUSPENDED; + hcd->state = HC_STATE_SUSPENDED; /* FALLTHROUGH */ /* entry with CONFIG_USB_SUSPEND, or hcds that autosuspend: the @@ -245,7 +245,7 @@ * FIXME only CONFIG_USB_SUSPEND guarantees hub_suspend() will * have been called, otherwise root hub timers still run ... */ - case HCD_STATE_SUSPENDED: + case HC_STATE_SUSPENDED: if (state <= dev->current_state) break; @@ -311,7 +311,7 @@ int has_pci_pm; hcd = pci_get_drvdata(dev); - if (hcd->state != HCD_STATE_SUSPENDED) { + if (hcd->state != HC_STATE_SUSPENDED) { dev_dbg (hcd->self.controller, "can't resume, not suspended!\n"); return 0; @@ -323,7 +323,7 @@ pci_state(dev->current_state), has_pci_pm ? "" : " (legacy)"); - hcd->state = USB_STATE_RESUMING; + hcd->state = HC_STATE_RESUMING; if (has_pci_pm) pci_set_power_state (dev, 0); @@ -343,7 +343,7 @@ #endif retval = hcd->driver->resume (hcd); - if (!HCD_IS_RUNNING (hcd->state)) { + if (!HC_IS_RUNNING (hcd->state)) { dev_dbg (hcd->self.controller, "resume fail, retval %d\n", retval); usb_hc_died (hcd); diff -Nru a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c --- a/drivers/usb/core/hcd.c 2005-03-24 18:21:08 -08:00 +++ b/drivers/usb/core/hcd.c 2005-03-24 18:21:08 -08:00 @@ -101,6 +101,9 @@ DECLARE_MUTEX (usb_bus_list_lock); /* exported only for usbfs */ EXPORT_SYMBOL_GPL (usb_bus_list_lock); +/* used for controlling access to virtual root hubs */ +static DEFINE_SPINLOCK(hcd_root_hub_lock); + /* used when updating hcd data */ static DEFINE_SPINLOCK(hcd_data_lock); @@ -455,7 +458,7 @@ default: /* non-generic request */ - if (HCD_IS_SUSPENDED (hcd->state)) + if (HC_IS_SUSPENDED (hcd->state)) status = -EAGAIN; else { switch (typeReq) { @@ -701,7 +704,7 @@ * This code is used to initialize a usb_bus structure, memory for which is * separately managed. */ -void usb_bus_init (struct usb_bus *bus) +static void usb_bus_init (struct usb_bus *bus) { memset (&bus->devmap, 0, sizeof(struct usb_devmap)); @@ -719,7 +722,6 @@ class_device_initialize(&bus->class_dev); bus->class_dev.class = &usb_host_class; } -EXPORT_SYMBOL (usb_bus_init); /** * usb_alloc_bus - creates a new USB host controller structure @@ -745,7 +747,6 @@ bus->op = op; return bus; } -EXPORT_SYMBOL (usb_alloc_bus); /*-------------------------------------------------------------------------*/ @@ -757,7 +758,7 @@ * Assigns a bus number, and links the controller into usbcore data * structures so that it can be seen by scanning the bus list. */ -int usb_register_bus(struct usb_bus *bus) +static int usb_register_bus(struct usb_bus *bus) { int busnum; int retval; @@ -792,7 +793,6 @@ dev_info (bus->controller, "new USB bus registered, assigned bus number %d\n", bus->busnum); return 0; } -EXPORT_SYMBOL (usb_register_bus); /** * usb_deregister_bus - deregisters the USB host controller @@ -802,7 +802,7 @@ * Recycles the bus number, and unlinks the controller from usbcore data * structures so that it won't be seen by scanning the bus list. */ -void usb_deregister_bus (struct usb_bus *bus) +static void usb_deregister_bus (struct usb_bus *bus) { dev_info (bus->controller, "USB bus %d deregistered\n", bus->busnum); @@ -822,12 +822,11 @@ class_device_del(&bus->class_dev); } -EXPORT_SYMBOL (usb_deregister_bus); /** - * usb_register_root_hub - called by HCD to register its root hub + * usb_hcd_register_root_hub - called by HCD to register its root hub * @usb_dev: the usb root hub device to be registered. - * @parent_dev: the parent device of this root hub. + * @hcd: host controller for this root hub * * The USB host controller calls this function to register the root hub * properly with the USB subsystem. It sets up the device properly in @@ -835,11 +834,20 @@ * then calls usb_new_device() to register the usb device. It also * assigns the root hub's USB address (always 1). */ -int usb_register_root_hub (struct usb_device *usb_dev, struct device *parent_dev) +int usb_hcd_register_root_hub (struct usb_device *usb_dev, struct usb_hcd *hcd) { + struct device *parent_dev = hcd->self.controller; const int devnum = 1; int retval; + /* hcd->driver->start() reported can_wakeup, probably with + * assistance from board's boot firmware. + * NOTE: normal devices won't enable wakeup by default. + */ + if (hcd->can_wakeup) + dev_dbg (parent_dev, "supports USB remote wakeup\n"); + hcd->remote_wakeup = hcd->can_wakeup; + usb_dev->devnum = devnum; usb_dev->bus->devnum_next = devnum + 1; memset (&usb_dev->bus->devmap.devicemap, 0, @@ -869,9 +877,20 @@ usb_dev->dev.bus_id, retval); } up (&usb_bus_list_lock); + + if (retval == 0) { + spin_lock_irq (&hcd_root_hub_lock); + hcd->rh_registered = 1; + spin_unlock_irq (&hcd_root_hub_lock); + + /* Did the HC die before the root hub was registered? */ + if (hcd->state == HC_STATE_HALT) + usb_hc_died (hcd); /* This time clean up */ + } + return retval; } -EXPORT_SYMBOL (usb_register_root_hub); +EXPORT_SYMBOL_GPL(usb_hcd_register_root_hub); /*-------------------------------------------------------------------------*/ @@ -1112,8 +1131,8 @@ else if (unlikely (urb->reject)) status = -EPERM; else switch (hcd->state) { - case USB_STATE_RUNNING: - case USB_STATE_RESUMING: + case HC_STATE_RUNNING: + case HC_STATE_RESUMING: usb_get_dev (urb->dev); list_add_tail (&urb->urb_list, &ep->urb_list); status = 0; @@ -1187,7 +1206,7 @@ static int hcd_get_frame_number (struct usb_device *udev) { struct usb_hcd *hcd = (struct usb_hcd *)udev->bus->hcpriv; - if (!HCD_IS_RUNNING (hcd->state)) + if (!HC_IS_RUNNING (hcd->state)) return -ESHUTDOWN; return hcd->driver->get_frame_number (hcd); } @@ -1269,7 +1288,7 @@ * halted ~= no unlink handshake is needed * suspended, resuming == should never happen */ - WARN_ON (!HCD_IS_RUNNING (hcd->state) && hcd->state != USB_STATE_HALT); + WARN_ON (!HC_IS_RUNNING (hcd->state) && hcd->state != HC_STATE_HALT); /* insist the urb is still queued */ list_for_each(tmp, &ep->urb_list) { @@ -1336,7 +1355,7 @@ hcd = udev->bus->hcpriv; - WARN_ON (!HCD_IS_RUNNING (hcd->state) && hcd->state != USB_STATE_HALT); + WARN_ON (!HC_IS_RUNNING (hcd->state) && hcd->state != HC_STATE_HALT); local_irq_disable (); @@ -1423,7 +1442,31 @@ return 0; } +/** + * usb_hcd_resume_root_hub - called by HCD to resume its root hub + * @hcd: host controller for this root hub + * + * The USB host controller calls this function when its root hub is + * suspended (with the remote wakeup feature enabled) and a remote + * wakeup request is received. It queues a request for khubd to + * resume the root hub. + */ +void usb_hcd_resume_root_hub (struct usb_hcd *hcd) +{ + unsigned long flags; + + spin_lock_irqsave (&hcd_root_hub_lock, flags); + if (hcd->rh_registered) + usb_resume_root_hub (hcd->self.root_hub); + spin_unlock_irqrestore (&hcd_root_hub_lock, flags); +} + +#else +void usb_hcd_resume_root_hub (struct usb_hcd *hcd) +{ +} #endif +EXPORT_SYMBOL_GPL(usb_hcd_resume_root_hub); /*-------------------------------------------------------------------------*/ @@ -1547,17 +1590,16 @@ struct usb_hcd *hcd = __hcd; int start = hcd->state; - if (start == USB_STATE_HALT) + if (start == HC_STATE_HALT) return IRQ_NONE; if (hcd->driver->irq (hcd, r) == IRQ_NONE) return IRQ_NONE; hcd->saw_irq = 1; - if (hcd->state != start && hcd->state == USB_STATE_HALT) + if (hcd->state != start && hcd->state == HC_STATE_HALT) usb_hc_died (hcd); return IRQ_HANDLED; } -EXPORT_SYMBOL (usb_hcd_irq); /*-------------------------------------------------------------------------*/ @@ -1571,12 +1613,21 @@ */ void usb_hc_died (struct usb_hcd *hcd) { + unsigned long flags; + dev_err (hcd->self.controller, "HC died; cleaning up\n"); - /* make khubd clean up old urbs and devices */ - usb_set_device_state(hcd->self.root_hub, USB_STATE_NOTATTACHED); - mod_timer(&hcd->rh_timer, jiffies); + spin_lock_irqsave (&hcd_root_hub_lock, flags); + if (hcd->rh_registered) { + + /* make khubd clean up old urbs and devices */ + usb_set_device_state (hcd->self.root_hub, + USB_STATE_NOTATTACHED); + usb_kick_khubd (hcd->self.root_hub); + } + spin_unlock_irqrestore (&hcd_root_hub_lock, flags); } +EXPORT_SYMBOL_GPL (usb_hc_died); /*-------------------------------------------------------------------------*/ @@ -1688,13 +1739,15 @@ hcd->irq = irqnum; dev_info(hcd->self.controller, "irq %s, %s 0x%08llx\n", bufp, (hcd->driver->flags & HCD_MEMORY) ? - "io mem" : "io base", hcd->rsrc_start); + "io mem" : "io base", + (unsigned long long)hcd->rsrc_start); } else { hcd->irq = -1; if (hcd->rsrc_start) dev_info(hcd->self.controller, "%s 0x%08llx\n", (hcd->driver->flags & HCD_MEMORY) ? - "io mem" : "io base", hcd->rsrc_start); + "io mem" : "io base", + (unsigned long long)hcd->rsrc_start); } if ((retval = hcd->driver->start(hcd)) < 0) { @@ -1727,14 +1780,17 @@ { dev_info(hcd->self.controller, "remove, state %x\n", hcd->state); - if (HCD_IS_RUNNING (hcd->state)) - hcd->state = USB_STATE_QUIESCING; + if (HC_IS_RUNNING (hcd->state)) + hcd->state = HC_STATE_QUIESCING; dev_dbg(hcd->self.controller, "roothub graceful disconnect\n"); + spin_lock_irq (&hcd_root_hub_lock); + hcd->rh_registered = 0; + spin_unlock_irq (&hcd_root_hub_lock); usb_disconnect(&hcd->self.root_hub); hcd->driver->stop(hcd); - hcd->state = USB_STATE_HALT; + hcd->state = HC_STATE_HALT; if (hcd->irq >= 0) free_irq(hcd->irq, hcd); diff -Nru a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h --- a/drivers/usb/core/hcd.h 2005-03-24 18:21:08 -08:00 +++ b/drivers/usb/core/hcd.h 2005-03-24 18:21:08 -08:00 @@ -74,6 +74,8 @@ unsigned saw_irq : 1; unsigned can_wakeup:1; /* hw supports wakeup? */ unsigned remote_wakeup:1;/* sw should use wakeup? */ + unsigned rh_registered:1;/* is root hub registered? */ + int irq; /* irq allocated */ void __iomem *regs; /* device memory/io */ u64 rsrc_start; /* memory/io resource start */ @@ -87,14 +89,14 @@ # define __SUSPEND 0x04 # define __TRANSIENT 0x80 -# define USB_STATE_HALT 0 -# define USB_STATE_RUNNING (__ACTIVE) -# define USB_STATE_QUIESCING (__SUSPEND|__TRANSIENT|__ACTIVE) -# define USB_STATE_RESUMING (__SUSPEND|__TRANSIENT) -# define HCD_STATE_SUSPENDED (__SUSPEND) +# define HC_STATE_HALT 0 +# define HC_STATE_RUNNING (__ACTIVE) +# define HC_STATE_QUIESCING (__SUSPEND|__TRANSIENT|__ACTIVE) +# define HC_STATE_RESUMING (__SUSPEND|__TRANSIENT) +# define HC_STATE_SUSPENDED (__SUSPEND) -#define HCD_IS_RUNNING(state) ((state) & __ACTIVE) -#define HCD_IS_SUSPENDED(state) ((state) & __SUSPEND) +#define HC_IS_RUNNING(state) ((state) & __ACTIVE) +#define HC_IS_SUSPENDED(state) ((state) & __SUSPEND) /* more shared queuing code would be good; it should support * smarter scheduling, handle transaction translators, etc; @@ -208,7 +210,6 @@ }; extern void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb, struct pt_regs *regs); -extern void usb_bus_init (struct usb_bus *bus); extern struct usb_hcd *usb_create_hcd (const struct hc_driver *driver, struct device *dev, char *bus_name); @@ -340,25 +341,10 @@ extern struct usb_bus *usb_alloc_bus (struct usb_operations *); -extern int usb_register_bus (struct usb_bus *); -extern void usb_deregister_bus (struct usb_bus *); - -extern int usb_register_root_hub (struct usb_device *usb_dev, - struct device *parent_dev); - -static inline int hcd_register_root (struct usb_device *usb_dev, - struct usb_hcd *hcd) -{ - /* hcd->driver->start() reported can_wakeup, probably with - * assistance from board's boot firmware. - * NOTE: normal devices won't enable wakeup by default. - */ - if (hcd->can_wakeup) - dev_dbg (hcd->self.controller, "supports USB remote wakeup\n"); - hcd->remote_wakeup = hcd->can_wakeup; +extern int usb_hcd_register_root_hub (struct usb_device *usb_dev, + struct usb_hcd *hcd); - return usb_register_root_hub (usb_dev, hcd->self.controller); -} +extern void usb_hcd_resume_root_hub (struct usb_hcd *hcd); extern void usb_set_device_state(struct usb_device *udev, enum usb_device_state new_state); diff -Nru a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c --- a/drivers/usb/core/hub.c 2005-03-24 18:21:08 -08:00 +++ b/drivers/usb/core/hub.c 2005-03-24 18:21:08 -08:00 @@ -289,6 +289,11 @@ spin_unlock_irqrestore(&hub_event_lock, flags); } +void usb_kick_khubd(struct usb_device *hdev) +{ + kick_khubd(hdev_to_hub(hdev)); +} + /* completion function, fires on port status changes and various faults */ static void hub_irq(struct urb *urb, struct pt_regs *regs) @@ -1383,8 +1388,13 @@ dev_err(hub->intfdev, "cannot reset port %d (err = %d)\n", port1, status); - else + else { status = hub_port_wait_reset(hub, port1, udev, delay); + if (status) + dev_dbg(hub->intfdev, + "port_wait_reset: err = %d\n", + status); + } /* return on disconnect or reset */ switch (status) { @@ -1533,7 +1543,8 @@ * Linux (2.6) currently has NO mechanisms to initiate that: no khubd * timer, no SRP, no requests through sysfs. */ -int __usb_suspend_device (struct usb_device *udev, int port1, pm_message_t state) +static int __usb_suspend_device (struct usb_device *udev, int port1, + pm_message_t state) { int status; @@ -1614,9 +1625,11 @@ struct usb_bus *bus = udev->bus; if (bus && bus->op->hub_suspend) { status = bus->op->hub_suspend (bus); - if (status == 0) + if (status == 0) { + dev_dbg(&udev->dev, "usb suspend\n"); usb_set_device_state(udev, USB_STATE_SUSPENDED); + } } else status = -EOPNOTSUPP; } else @@ -1834,9 +1847,11 @@ } else status = -EOPNOTSUPP; if (status == 0) { + dev_dbg(&udev->dev, "usb resume\n"); /* TRSMRCY = 10 msec */ msleep(10); usb_set_device_state (udev, USB_STATE_CONFIGURED); + udev->dev.power.power_state = PMSG_ON; status = hub_resume (udev ->actconfig->interface[0]); } @@ -1955,10 +1970,19 @@ } intf->dev.power.power_state = PMSG_ON; + hub->resume_root_hub = 0; hub_activate(hub); return 0; } +void usb_resume_root_hub(struct usb_device *hdev) +{ + struct usb_hub *hub = hdev_to_hub(hdev); + + hub->resume_root_hub = 1; + kick_khubd(hub); +} + #else /* !CONFIG_USB_SUSPEND */ int usb_suspend_device(struct usb_device *udev, u32 state) @@ -2615,15 +2639,30 @@ (u16) hub->event_bits[0]); usb_get_intf(intf); + i = hub->resume_root_hub; spin_unlock_irq(&hub_event_lock); + /* Is this is a root hub wanting to be resumed? */ + if (i) + usb_resume_device(hdev); + /* Lock the device, then check to see if we were * disconnected while waiting for the lock to succeed. */ if (locktree(hdev) < 0) { usb_put_intf(intf); continue; } - if (hub != usb_get_intfdata(intf) || hub->quiescing) + if (hub != usb_get_intfdata(intf)) + goto loop; + + /* If the hub has died, clean up after it */ + if (hdev->state == USB_STATE_NOTATTACHED) { + hub_pre_reset(hub); + goto loop; + } + + /* If this is an inactive or suspended hub, do nothing */ + if (hub->quiescing) goto loop; if (hub->error) { @@ -2643,6 +2682,8 @@ /* deal with port status changes */ for (i = 1; i <= hub->descriptor->bNbrPorts; i++) { + if (test_bit(i, hub->busy_bits)) + continue; connect_change = test_bit(i, hub->change_bits); if (!test_and_clear_bit(i, hub->event_bits) && !connect_change && !hub->activating) @@ -2948,6 +2989,7 @@ hub_pre_reset(hub); } + set_bit(port1, parent_hub->busy_bits); for (i = 0; i < SET_CONFIG_TRIES; ++i) { /* ep0 maxpacket size may change; let the HCD know about it. @@ -2957,6 +2999,7 @@ if (ret >= 0) break; } + clear_bit(port1, parent_hub->busy_bits); if (ret < 0) goto re_enumerate; diff -Nru a/drivers/usb/core/hub.h b/drivers/usb/core/hub.h --- a/drivers/usb/core/hub.h 2005-03-24 18:21:08 -08:00 +++ b/drivers/usb/core/hub.h 2005-03-24 18:21:08 -08:00 @@ -205,6 +205,7 @@ unsigned long event_bits[1]; /* status change bitmask */ unsigned long change_bits[1]; /* ports with logical connect status change */ + unsigned long busy_bits[1]; /* ports being reset */ #if USB_MAXCHILDREN > 31 /* 8*sizeof(unsigned long) - 1 */ #error event_bits[] is too short! #endif @@ -216,6 +217,7 @@ unsigned quiescing:1; unsigned activating:1; + unsigned resume_root_hub:1; unsigned has_indicators:1; enum hub_led_mode indicator[USB_MAXCHILDREN]; diff -Nru a/drivers/usb/core/message.c b/drivers/usb/core/message.c --- a/drivers/usb/core/message.c 2005-03-24 18:21:08 -08:00 +++ b/drivers/usb/core/message.c 2005-03-24 18:21:08 -08:00 @@ -90,8 +90,10 @@ /*-------------------------------------------------------------------*/ // returns status (negative) or length (positive) -int usb_internal_control_msg(struct usb_device *usb_dev, unsigned int pipe, - struct usb_ctrlrequest *cmd, void *data, int len, int timeout) +static int usb_internal_control_msg(struct usb_device *usb_dev, + unsigned int pipe, + struct usb_ctrlrequest *cmd, + void *data, int len, int timeout) { struct urb *urb; int retv; @@ -1041,8 +1043,8 @@ * * Enables all the endpoints for the interface's current altsetting. */ -void usb_enable_interface(struct usb_device *dev, - struct usb_interface *intf) +static void usb_enable_interface(struct usb_device *dev, + struct usb_interface *intf) { struct usb_host_interface *alt = intf->cur_altsetting; int i; diff -Nru a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c --- a/drivers/usb/core/usb.c 2005-03-24 18:21:08 -08:00 +++ b/drivers/usb/core/usb.c 2005-03-24 18:21:08 -08:00 @@ -60,7 +60,7 @@ const char *usbcore_name = "usbcore"; -int nousb; /* Disable USB when built into kernel image */ +static int nousb; /* Disable USB when built into kernel image */ /* Not honored on modular build */ static DECLARE_RWSEM(usb_all_devices_rwsem); @@ -86,7 +86,7 @@ static int usb_generic_driver_data; /* called from driver core with usb_bus_type.subsys writelock */ -int usb_probe_interface(struct device *dev) +static int usb_probe_interface(struct device *dev) { struct usb_interface * intf = to_usb_interface(dev); struct usb_driver * driver = to_usb_driver(dev->driver); @@ -114,7 +114,7 @@ } /* called from driver core with usb_bus_type.subsys writelock */ -int usb_unbind_interface(struct device *dev) +static int usb_unbind_interface(struct device *dev) { struct usb_interface *intf = to_usb_interface(dev); struct usb_driver *driver = to_usb_driver(intf->dev.driver); @@ -615,6 +615,33 @@ alt->desc.bInterfaceSubClass, alt->desc.bInterfaceProtocol)) return -ENOMEM; + + if (add_hotplug_env_var(envp, num_envp, &i, + buffer, buffer_size, &length, + "MODALIAS=usb:v%04Xp%04Xdl%04Xdh%04Xdc%02Xdsc%02Xdp%02Xic%02Xisc%02Xip%02X", + le16_to_cpu(usb_dev->descriptor.idVendor), + le16_to_cpu(usb_dev->descriptor.idProduct), + le16_to_cpu(usb_dev->descriptor.bcdDevice), + le16_to_cpu(usb_dev->descriptor.bcdDevice), + usb_dev->descriptor.bDeviceClass, + usb_dev->descriptor.bDeviceSubClass, + usb_dev->descriptor.bDeviceProtocol, + alt->desc.bInterfaceClass, + alt->desc.bInterfaceSubClass, + alt->desc.bInterfaceProtocol)) + return -ENOMEM; + } else { + if (add_hotplug_env_var(envp, num_envp, &i, + buffer, buffer_size, &length, + "MODALIAS=usb:v%04Xp%04Xdl%04Xdh%04Xdc%02Xdsc%02Xdp%02Xic*isc*ip*", + le16_to_cpu(usb_dev->descriptor.idVendor), + le16_to_cpu(usb_dev->descriptor.idProduct), + le16_to_cpu(usb_dev->descriptor.bcdDevice), + le16_to_cpu(usb_dev->descriptor.bcdDevice), + usb_dev->descriptor.bDeviceClass, + usb_dev->descriptor.bDeviceSubClass, + usb_dev->descriptor.bDeviceProtocol)) + return -ENOMEM; } envp[i] = NULL; @@ -1148,6 +1175,7 @@ * * Reverse the effect of this call with usb_buffer_unmap(). */ +#if 0 struct urb *usb_buffer_map (struct urb *urb) { struct usb_bus *bus; @@ -1177,6 +1205,7 @@ | URB_NO_SETUP_DMA_MAP); return urb; } +#endif /* 0 */ /* XXX DISABLED, no users currently. If you wish to re-enable this * XXX please determine whether the sync is to transfer ownership of @@ -1221,6 +1250,7 @@ * * Reverses the effect of usb_buffer_map(). */ +#if 0 void usb_buffer_unmap (struct urb *urb) { struct usb_bus *bus; @@ -1247,6 +1277,7 @@ urb->transfer_flags &= ~(URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP); } +#endif /* 0 */ /** * usb_buffer_map_sg - create scatterlist DMA mapping(s) for an endpoint @@ -1527,11 +1558,11 @@ EXPORT_SYMBOL (usb_buffer_alloc); EXPORT_SYMBOL (usb_buffer_free); -EXPORT_SYMBOL (usb_buffer_map); #if 0 +EXPORT_SYMBOL (usb_buffer_map); EXPORT_SYMBOL (usb_buffer_dmasync); -#endif EXPORT_SYMBOL (usb_buffer_unmap); +#endif EXPORT_SYMBOL (usb_buffer_map_sg); #if 0 diff -Nru a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h --- a/drivers/usb/core/usb.h 2005-03-24 18:21:08 -08:00 +++ b/drivers/usb/core/usb.h 2005-03-24 18:21:08 -08:00 @@ -4,8 +4,6 @@ extern void usb_remove_sysfs_dev_files (struct usb_device *dev); extern void usb_create_sysfs_intf_files (struct usb_interface *intf); extern void usb_remove_sysfs_intf_files (struct usb_interface *intf); -extern int usb_probe_interface (struct device *dev); -extern int usb_unbind_interface (struct device *dev); extern void usb_disable_endpoint (struct usb_device *dev, unsigned int epaddr); extern void usb_disable_interface (struct usb_device *dev, @@ -13,15 +11,15 @@ extern void usb_release_interface_cache(struct kref *ref); extern void usb_disable_device (struct usb_device *dev, int skip_ep0); -extern void usb_enable_interface (struct usb_device *dev, - struct usb_interface *intf); - extern int usb_get_device_descriptor(struct usb_device *dev, unsigned int size); extern int usb_set_configuration(struct usb_device *dev, int configuration); extern void usb_lock_all_devices(void); extern void usb_unlock_all_devices(void); + +extern void usb_kick_khubd(struct usb_device *dev); +extern void usb_resume_root_hub(struct usb_device *dev); /* for labeling diagnostics */ extern const char *usbcore_name; diff -Nru a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig --- a/drivers/usb/gadget/Kconfig 2005-03-24 18:21:08 -08:00 +++ b/drivers/usb/gadget/Kconfig 2005-03-24 18:21:08 -08:00 @@ -135,21 +135,6 @@ depends on USB_GADGET_GOKU default USB_GADGET -# this could be built elsewhere (doesn't yet exist) -config USB_GADGET_SA1100 - boolean "SA 1100" - depends on ARCH_SA1100 - help - Intel's SA-1100 is an ARM-4 processor with an integrated - full speed USB 1.1 device controller. - - It has two fixed-function endpoints, as well as endpoint - zero (for control transfers). - -config USB_SA1100 - tristate - depends on USB_GADGET_SA1100 - default USB_GADGET config USB_GADGET_LH7A40X boolean "LH7A40X" @@ -163,34 +148,6 @@ default USB_GADGET -config USB_GADGET_DUMMY_HCD - boolean "Dummy HCD (DEVELOPMENT)" - depends on USB && EXPERIMENTAL - select USB_GADGET_DUALSPEED - help - This host controller driver emulates USB, looping all data transfer - requests back to a USB "gadget driver" in the same host. The host - side is the master; the gadget side is the slave. Gadget drivers - can be high, full, or low speed; and they have access to endpoints - like those from NET2280, PXA2xx, or SA1100 hardware. - - This may help in some stages of creating a driver to embed in a - Linux device, since it lets you debug several parts of the gadget - driver without its hardware or drivers being involved. - - Since such a gadget side driver needs to interoperate with a host - side Linux-USB device driver, this may help to debug both sides - of a USB protocol stack. - - Say "y" to link the driver statically, or "m" to build a - dynamically linked module called "dummy_hcd" and force all - gadget drivers to also be dynamically linked. - -config USB_DUMMY_HCD - tristate - depends on USB_GADGET_DUMMY_HCD - default USB_GADGET - config USB_GADGET_OMAP boolean "OMAP USB Device Controller" depends on ARCH_OMAP @@ -222,6 +179,38 @@ Select this only if your OMAP board has a Mini-AB connector. + +config USB_GADGET_DUMMY_HCD + boolean "Dummy HCD (DEVELOPMENT)" + depends on USB && EXPERIMENTAL + select USB_GADGET_DUALSPEED + help + This host controller driver emulates USB, looping all data transfer + requests back to a USB "gadget driver" in the same host. The host + side is the master; the gadget side is the slave. Gadget drivers + can be high, full, or low speed; and they have access to endpoints + like those from NET2280, PXA2xx, or SA1100 hardware. + + This may help in some stages of creating a driver to embed in a + Linux device, since it lets you debug several parts of the gadget + driver without its hardware or drivers being involved. + + Since such a gadget side driver needs to interoperate with a host + side Linux-USB device driver, this may help to debug both sides + of a USB protocol stack. + + Say "y" to link the driver statically, or "m" to build a + dynamically linked module called "dummy_hcd" and force all + gadget drivers to also be dynamically linked. + +config USB_DUMMY_HCD + tristate + depends on USB_GADGET_DUMMY_HCD + default USB_GADGET + +# NOTE: Please keep dummy_hcd LAST so that "real hardware" appears +# first and will be selected by default. + endchoice config USB_GADGET_DUALSPEED @@ -355,8 +344,6 @@ config USB_FILE_STORAGE tristate "File-backed Storage Gadget" - # we don't support the SA1100 because of its limitations - depends on USB_GADGET_SA1100 = n help The File-backed Storage Gadget acts as a USB Mass Storage disk drive. As its storage repository it can use a regular diff -Nru a/drivers/usb/gadget/config.c b/drivers/usb/gadget/config.c --- a/drivers/usb/gadget/config.c 2005-03-24 18:21:08 -08:00 +++ b/drivers/usb/gadget/config.c 2005-03-24 18:21:08 -08:00 @@ -25,6 +25,7 @@ #include #include +#include /** diff -Nru a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c --- a/drivers/usb/gadget/dummy_hcd.c 2005-03-24 18:21:08 -08:00 +++ b/drivers/usb/gadget/dummy_hcd.c 2005-03-24 18:21:08 -08:00 @@ -1647,11 +1647,11 @@ return -ENOMEM; /* root hub enters addressed state... */ - hcd->state = USB_STATE_RUNNING; + hcd->state = HC_STATE_RUNNING; root->speed = USB_SPEED_HIGH; /* ...then configured, so khubd sees us. */ - if ((retval = hcd_register_root (root, hcd)) != 0) { + if ((retval = usb_hcd_register_root_hub (root, hcd)) != 0) { goto err1; } @@ -1669,7 +1669,7 @@ usb_disconnect (&hcd->self.root_hub); err1: usb_put_dev (root); - hcd->state = USB_STATE_QUIESCING; + hcd->state = HC_STATE_QUIESCING; return retval; } diff -Nru a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c --- a/drivers/usb/gadget/ether.c 2005-03-24 18:21:08 -08:00 +++ b/drivers/usb/gadget/ether.c 2005-03-24 18:21:08 -08:00 @@ -1,7 +1,7 @@ /* * ether.c -- Ethernet gadget driver, with CDC and non-CDC options * - * Copyright (C) 2003-2004 David Brownell + * Copyright (C) 2003-2005 David Brownell * Copyright (C) 2003-2004 Robert Schwebel, Benedikt Spranger * * This program is free software; you can redistribute it and/or modify @@ -98,12 +98,18 @@ #define rndis_exit() do{}while(0) #endif +/* CDC and RNDIS support the same host-chosen outgoing packet filters. */ +#define DEFAULT_FILTER (USB_CDC_PACKET_TYPE_BROADCAST \ + |USB_CDC_PACKET_TYPE_DIRECTED) + + /*-------------------------------------------------------------------------*/ struct eth_dev { spinlock_t lock; struct usb_gadget *gadget; struct usb_request *req; /* for control responses */ + struct usb_request *stat_req; /* for cdc & rndis status */ u8 config; struct usb_ep *in_ep, *out_ep, *status_ep; @@ -243,6 +249,10 @@ #define DEV_CONFIG_CDC #endif +#ifdef CONFIG_USB_GADGET_AT91 +#define DEV_CONFIG_CDC +#endif + /* For CDC-incapable hardware, choose the simple cdc subset. * Anything that talks bulk (without notable bugs) can do this. @@ -266,8 +276,39 @@ /*-------------------------------------------------------------------------*/ +/* "main" config is either CDC, or its simple subset */ +static inline int is_cdc(struct eth_dev *dev) +{ +#if !defined(DEV_CONFIG_SUBSET) + return 1; /* only cdc possible */ +#elif !defined (DEV_CONFIG_CDC) + return 0; /* only subset possible */ +#else + return dev->cdc; /* depends on what hardware we found */ +#endif +} + +/* "secondary" RNDIS config may sometimes be activated */ +static inline int rndis_active(struct eth_dev *dev) +{ +#ifdef CONFIG_USB_ETH_RNDIS + return dev->rndis; +#else + return 0; +#endif +} + +#define subset_active(dev) (!is_cdc(dev) && !rndis_active(dev)) +#define cdc_active(dev) ( is_cdc(dev) && !rndis_active(dev)) + + + #define DEFAULT_QLEN 2 /* double buffering by default */ +/* peak bulk transfer bits-per-second */ +#define HS_BPS (13 * 512 * 8 * 1000 * 8) +#define FS_BPS (19 * 64 * 1 * 1000 * 8) + #ifdef CONFIG_USB_GADGET_DUALSPEED static unsigned qmult = 5; @@ -281,12 +322,12 @@ /* also defer IRQs on highspeed TX */ #define TX_DELAY qmult -#define BITRATE(g) ((g->speed == USB_SPEED_HIGH) ? 4800000 : 120000) +#define BITRATE(g) (((g)->speed == USB_SPEED_HIGH) ? HS_BPS : FS_BPS) #else /* full speed (low speed doesn't do bulk) */ #define qlen(gadget) DEFAULT_QLEN -#define BITRATE(g) (12000) +#define BITRATE(g) FS_BPS #endif @@ -519,9 +560,8 @@ #if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS) /* include the status endpoint if we can, even where it's optional. - * use small wMaxPacketSize, since many "interrupt" endpoints have - * very small fifos and it's no big deal if CDC_NOTIFY_SPEED_CHANGE - * takes two packets. also default to a big transfer interval, to + * use wMaxPacketSize big enough to fit CDC_NOTIFY_SPEED_CHANGE in one + * packet, to simplify cancelation; and a big transfer interval, to * waste less bandwidth. * * some drivers (like Linux 2.4 cdc-ether!) "need" it to exist even @@ -534,7 +574,7 @@ */ #define LOG2_STATUS_INTERVAL_MSEC 5 /* 1 << 5 == 32 msec */ -#define STATUS_BYTECOUNT 8 /* 8 byte header + data */ +#define STATUS_BYTECOUNT 16 /* 8 byte header + data */ static struct usb_endpoint_descriptor fs_status_desc = { @@ -916,14 +956,12 @@ if (strcmp (ep->name, EP_IN_NAME) == 0) { d = ep_desc (dev->gadget, &hs_source_desc, &fs_source_desc); ep->driver_data = dev; - dev->in_ep = ep; dev->in = d; /* one endpoint just reads OUT packets */ } else if (strcmp (ep->name, EP_OUT_NAME) == 0) { d = ep_desc (dev->gadget, &hs_sink_desc, &fs_sink_desc); ep->driver_data = dev; - dev->out_ep = ep; dev->out = d; /* optional status/notification endpoint */ @@ -937,7 +975,6 @@ return result; ep->driver_data = dev; - dev->status_ep = ep; dev->status = d; } return 0; @@ -964,7 +1001,6 @@ return result; ep->driver_data = dev; - dev->in_ep = ep; dev->in = d; /* one endpoint just reads OUT packets */ @@ -975,7 +1011,6 @@ return result; ep->driver_data = dev; - dev->out_ep = ep; dev->out = d; } @@ -1006,7 +1041,6 @@ result = usb_ep_enable (ep, d); if (result == 0) { ep->driver_data = dev; - dev->status_ep = ep; dev->status = d; continue; } @@ -1034,22 +1068,19 @@ /* on error, disable any endpoints */ if (result < 0) { #if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS) - if (dev->status_ep) + if (dev->status) (void) usb_ep_disable (dev->status_ep); #endif - dev->status_ep = NULL; dev->status = NULL; #if defined(DEV_CONFIG_SUBSET) || defined(CONFIG_USB_ETH_RNDIS) if (dev->rndis || !dev->cdc) { - if (dev->in_ep) + if (dev->in) (void) usb_ep_disable (dev->in_ep); - if (dev->out_ep) + if (dev->out) (void) usb_ep_disable (dev->out_ep); } #endif - dev->in_ep = NULL; dev->in = NULL; - dev->out_ep = NULL; dev->out = NULL; } else @@ -1089,7 +1120,7 @@ /* disable endpoints, forcing (synchronous) completion of * pending i/o. then free the requests. */ - if (dev->in_ep) { + if (dev->in) { usb_ep_disable (dev->in_ep); while (likely (!list_empty (&dev->tx_reqs))) { req = container_of (dev->tx_reqs.next, @@ -1097,9 +1128,8 @@ list_del (&req->list); usb_ep_free_request (dev->in_ep, req); } - dev->in_ep = NULL; } - if (dev->out_ep) { + if (dev->out) { usb_ep_disable (dev->out_ep); while (likely (!list_empty (&dev->rx_reqs))) { req = container_of (dev->rx_reqs.next, @@ -1107,12 +1137,10 @@ list_del (&req->list); usb_ep_free_request (dev->out_ep, req); } - dev->out_ep = NULL; } - if (dev->status_ep) { + if (dev->status) { usb_ep_disable (dev->status_ep); - dev->status_ep = NULL; } dev->config = 0; } @@ -1213,28 +1241,22 @@ event->wLength = __constant_cpu_to_le16 (8); /* SPEED_CHANGE data is up/down speeds in bits/sec */ - data [0] = data [1] = cpu_to_le32( - (dev->gadget->speed == USB_SPEED_HIGH) - ? (13 * 512 * 8 * 1000 * 8) - : (19 * 64 * 1 * 1000 * 8)); + data [0] = data [1] = cpu_to_le32 (BITRATE (dev->gadget)); - req->length = 16; + req->length = STATUS_BYTECOUNT; value = usb_ep_queue (ep, req, GFP_ATOMIC); DEBUG (dev, "send SPEED_CHANGE --> %d\n", value); if (value == 0) return; - } else + } else if (value != -ECONNRESET) DEBUG (dev, "event %02x --> %d\n", event->bNotificationType, value); - - /* free when done */ - usb_ep_free_buffer (ep, req->buf, req->dma, 16); - usb_ep_free_request (ep, req); + event->bmRequestType = 0xff; } static void issue_start_status (struct eth_dev *dev) { - struct usb_request *req; + struct usb_request *req = dev->stat_req; struct usb_cdc_notification *event; int value; @@ -1250,21 +1272,6 @@ usb_ep_disable (dev->status_ep); usb_ep_enable (dev->status_ep, dev->status); - /* FIXME make these allocations static like dev->req */ - req = usb_ep_alloc_request (dev->status_ep, GFP_ATOMIC); - if (req == 0) { - DEBUG (dev, "status ENOMEM\n"); - return; - } - req->buf = usb_ep_alloc_buffer (dev->status_ep, 16, - &dev->req->dma, GFP_ATOMIC); - if (req->buf == 0) { - DEBUG (dev, "status buf ENOMEM\n"); -free_req: - usb_ep_free_request (dev->status_ep, req); - return; - } - /* 3.8.1 says to issue first NETWORK_CONNECTION, then * a SPEED_CHANGE. could be useful in some configs. */ @@ -1275,15 +1282,11 @@ event->wIndex = __constant_cpu_to_le16 (1); event->wLength = 0; - req->length = 8; + req->length = sizeof *event; req->complete = eth_status_complete; value = usb_ep_queue (dev->status_ep, req, GFP_ATOMIC); - if (value < 0) { + if (value < 0) DEBUG (dev, "status buf queue --> %d\n", value); - usb_ep_free_buffer (dev->status_ep, - req->buf, dev->req->dma, 16); - goto free_req; - } } #endif @@ -1431,7 +1434,7 @@ case 0: /* control/master intf */ if (wValue != 0) break; - if (dev->status_ep) { + if (dev->status) { usb_ep_disable (dev->status_ep); usb_ep_enable (dev->status_ep, dev->status); } @@ -1450,8 +1453,9 @@ if (wValue == 1) { usb_ep_enable (dev->in_ep, dev->in); usb_ep_enable (dev->out_ep, dev->out); + dev->cdc_filter = DEFAULT_FILTER; netif_carrier_on (dev->net); - if (dev->status_ep) + if (dev->status) issue_start_status (dev); if (netif_running (dev->net)) { spin_unlock (&dev->lock); @@ -1502,14 +1506,18 @@ || wLength != 0 || wIndex > 1) break; - DEBUG (dev, "NOP packet filter %04x\n", wValue); - /* NOTE: table 62 has 5 filter bits to reduce traffic, - * and we "must" support multicast and promiscuous. - * this NOP implements a bad filter (always promisc) - */ + DEBUG (dev, "packet filter %02x\n", wValue); dev->cdc_filter = wValue; value = 0; break; + + /* and potentially: + * case USB_CDC_SET_ETHERNET_MULTICAST_FILTERS: + * case USB_CDC_SET_ETHERNET_PM_PATTERN_FILTER: + * case USB_CDC_GET_ETHERNET_PM_PATTERN_FILTER: + * case USB_CDC_GET_ETHERNET_STATISTIC: + */ + #endif /* DEV_CONFIG_CDC */ #ifdef CONFIG_USB_ETH_RNDIS @@ -1904,6 +1912,14 @@ netif_wake_queue (dev->net); } +static inline int eth_is_promisc (struct eth_dev *dev) +{ + /* no filters for the CDC subset; always promisc */ + if (subset_active (dev)) + return 1; + return dev->cdc_filter & USB_CDC_PACKET_TYPE_PROMISCUOUS; +} + static int eth_start_xmit (struct sk_buff *skb, struct net_device *net) { struct eth_dev *dev = netdev_priv(net); @@ -1912,10 +1928,27 @@ struct usb_request *req = NULL; unsigned long flags; - /* FIXME check dev->cdc_filter to decide whether to send this, - * instead of acting as if USB_CDC_PACKET_TYPE_PROMISCUOUS were - * always set. RNDIS has the same kind of outgoing filter. - */ + /* apply outgoing CDC or RNDIS filters */ + if (!eth_is_promisc (dev)) { + u8 *dest = skb->data; + + if (dest [0] & 0x01) { + u16 type; + + /* ignores USB_CDC_PACKET_TYPE_MULTICAST and host + * SET_ETHERNET_MULTICAST_FILTERS requests + */ + if (memcmp (dest, net->broadcast, ETH_ALEN) == 0) + type = USB_CDC_PACKET_TYPE_BROADCAST; + else + type = USB_CDC_PACKET_TYPE_ALL_MULTICAST; + if (!(dev->cdc_filter & type)) { + dev_kfree_skb_any (skb); + return 0; + } + } + /* ignores USB_CDC_PACKET_TYPE_DIRECTED */ + } spin_lock_irqsave (&dev->lock, flags); req = container_of (dev->tx_reqs.next, struct usb_request, list); @@ -2137,6 +2170,30 @@ /*-------------------------------------------------------------------------*/ +static struct usb_request *eth_req_alloc (struct usb_ep *ep, unsigned size) +{ + struct usb_request *req; + + req = usb_ep_alloc_request (ep, GFP_KERNEL); + if (!req) + return NULL; + + req->buf = kmalloc (size, GFP_KERNEL); + if (!req->buf) { + usb_ep_free_request (ep, req); + req = NULL; + } + return req; +} + +static void +eth_req_free (struct usb_ep *ep, struct usb_request *req) +{ + kfree (req->buf); + usb_ep_free_request (ep, req); +} + + static void eth_unbind (struct usb_gadget *gadget) { @@ -2150,12 +2207,13 @@ /* we've already been disconnected ... no i/o is active */ if (dev->req) { - usb_ep_free_buffer (gadget->ep0, - dev->req->buf, dev->req->dma, - USB_BUFSIZ); - usb_ep_free_request (gadget->ep0, dev->req); + eth_req_free (gadget->ep0, dev->req); dev->req = NULL; } + if (dev->stat_req) { + eth_req_free (dev->status_ep, dev->stat_req); + dev->stat_req = NULL; + } unregister_netdev (dev->net); free_netdev(dev->net); @@ -2201,7 +2259,7 @@ struct eth_dev *dev; struct net_device *net; u8 cdc = 1, zlp = 1, rndis = 1; - struct usb_ep *ep; + struct usb_ep *in_ep, *out_ep, *status_ep = NULL; int status = -ENOMEM; /* these flags are only ever cleared; compiler take note */ @@ -2251,6 +2309,8 @@ device_desc.bcdDevice = __constant_cpu_to_le16 (0x0211); } else if (gadget_is_s3c2410(gadget)) { device_desc.bcdDevice = __constant_cpu_to_le16 (0x0212); + } else if (gadget_is_at91(gadget)) { + device_desc.bcdDevice = __constant_cpu_to_le16 (0x0213); } else { /* can't assume CDC works. don't want to default to * anything less functional on CDC-capable hardware, @@ -2308,32 +2368,32 @@ /* all we really need is bulk IN/OUT */ usb_ep_autoconfig_reset (gadget); - ep = usb_ep_autoconfig (gadget, &fs_source_desc); - if (!ep) { + in_ep = usb_ep_autoconfig (gadget, &fs_source_desc); + if (!in_ep) { autoconf_fail: dev_err (&gadget->dev, "can't autoconfigure on %s\n", gadget->name); return -ENODEV; } - EP_IN_NAME = ep->name; - ep->driver_data = ep; /* claim */ + EP_IN_NAME = in_ep->name; + in_ep->driver_data = in_ep; /* claim */ - ep = usb_ep_autoconfig (gadget, &fs_sink_desc); - if (!ep) + out_ep = usb_ep_autoconfig (gadget, &fs_sink_desc); + if (!out_ep) goto autoconf_fail; - EP_OUT_NAME = ep->name; - ep->driver_data = ep; /* claim */ + EP_OUT_NAME = out_ep->name; + out_ep->driver_data = out_ep; /* claim */ #if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS) /* CDC Ethernet control interface doesn't require a status endpoint. * Since some hosts expect one, try to allocate one anyway. */ if (cdc || rndis) { - ep = usb_ep_autoconfig (gadget, &fs_status_desc); - if (ep) { - EP_STATUS_NAME = ep->name; - ep->driver_data = ep; /* claim */ + status_ep = usb_ep_autoconfig (gadget, &fs_status_desc); + if (status_ep) { + EP_STATUS_NAME = status_ep->name; + status_ep->driver_data = status_ep; /* claim */ } else if (rndis) { dev_err (&gadget->dev, "can't run RNDIS on %s\n", @@ -2409,6 +2469,10 @@ dev->cdc = cdc; dev->zlp = zlp; + dev->in_ep = in_ep; + dev->out_ep = out_ep; + dev->status_ep = status_ep; + /* Module params for these addresses should come from ID proms. * The host side address is used with CDC and RNDIS, and commonly * ends up in a persistent config database. @@ -2442,16 +2506,20 @@ // set_multicast_list SET_ETHTOOL_OPS(net, &ops); - /* preallocate control response and buffer */ - dev->req = usb_ep_alloc_request (gadget->ep0, GFP_KERNEL); + /* preallocate control message data and buffer */ + dev->req = eth_req_alloc (gadget->ep0, USB_BUFSIZ); if (!dev->req) goto fail; dev->req->complete = eth_setup_complete; - dev->req->buf = usb_ep_alloc_buffer (gadget->ep0, USB_BUFSIZ, - &dev->req->dma, GFP_KERNEL); - if (!dev->req->buf) { - usb_ep_free_request (gadget->ep0, dev->req); - goto fail; + + /* ... and maybe likewise for status transfer */ + if (dev->status_ep) { + dev->stat_req = eth_req_alloc (dev->status_ep, + STATUS_BYTECOUNT); + if (!dev->stat_req) { + eth_req_free (gadget->ep0, dev->req); + goto fail; + } } /* finish hookup to lower layer ... */ diff -Nru a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c --- a/drivers/usb/gadget/file_storage.c 2005-03-24 18:21:08 -08:00 +++ b/drivers/usb/gadget/file_storage.c 2005-03-24 18:21:08 -08:00 @@ -1,7 +1,7 @@ /* * file_storage.c -- File-backed USB Storage Gadget, for USB development * - * Copyright (C) 2003, 2004 Alan Stern + * Copyright (C) 2003-2005 Alan Stern * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -832,6 +832,8 @@ #define STRING_MANUFACTURER 1 #define STRING_PRODUCT 2 #define STRING_SERIAL 3 +#define STRING_CONFIG 4 +#define STRING_INTERFACE 5 /* There is only one configuration. */ #define CONFIG_VALUE 1 @@ -863,6 +865,7 @@ /* wTotalLength computed by usb_gadget_config_buf() */ .bNumInterfaces = 1, .bConfigurationValue = CONFIG_VALUE, + .iConfiguration = STRING_CONFIG, .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER, .bMaxPower = 1, // self-powered }; @@ -886,6 +889,7 @@ .bInterfaceClass = USB_CLASS_MASS_STORAGE, .bInterfaceSubClass = USB_SC_SCSI, // Adjusted during fsg_bind() .bInterfaceProtocol = USB_PR_BULK, // Adjusted during fsg_bind() + .iInterface = STRING_INTERFACE, }; /* Three full-speed endpoint descriptors: bulk-in, bulk-out, @@ -1009,7 +1013,7 @@ /* The CBI specification limits the serial string to 12 uppercase hexadecimal * characters. */ -static char manufacturer[50]; +static char manufacturer[64]; static char serial[13]; /* Static strings, in UTF-8 (for simplicity we use only ASCII characters) */ @@ -1017,6 +1021,8 @@ {STRING_MANUFACTURER, manufacturer}, {STRING_PRODUCT, longname}, {STRING_SERIAL, serial}, + {STRING_CONFIG, "Self-powered"}, + {STRING_INTERFACE, "Mass Storage"}, {} }; @@ -1270,6 +1276,8 @@ { struct usb_request *req = fsg->ep0req; int value = -EOPNOTSUPP; + u16 w_index = ctrl->wIndex; + u16 w_length = ctrl->wLength; if (!fsg->config) return value; @@ -1282,7 +1290,7 @@ if (ctrl->bRequestType != (USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE)) break; - if (ctrl->wIndex != 0) { + if (w_index != 0) { value = -EDOM; break; } @@ -1298,13 +1306,13 @@ if (ctrl->bRequestType != (USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE)) break; - if (ctrl->wIndex != 0) { + if (w_index != 0) { value = -EDOM; break; } VDBG(fsg, "get max LUN\n"); *(u8 *) req->buf = fsg->nluns - 1; - value = min(ctrl->wLength, (u16) 1); + value = min(w_length, (u16) 1); break; } } @@ -1317,15 +1325,15 @@ if (ctrl->bRequestType != (USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE)) break; - if (ctrl->wIndex != 0) { + if (w_index != 0) { value = -EDOM; break; } - if (ctrl->wLength > MAX_COMMAND_SIZE) { + if (w_length > MAX_COMMAND_SIZE) { value = -EOVERFLOW; break; } - value = ctrl->wLength; + value = w_length; fsg->ep0req->context = received_cbi_adsc; break; } @@ -1336,7 +1344,7 @@ "unknown class-specific control req " "%02x.%02x v%04x i%04x l%u\n", ctrl->bRequestType, ctrl->bRequest, - ctrl->wValue, ctrl->wIndex, ctrl->wLength); + ctrl->wValue, w_index, w_length); return value; } @@ -1350,6 +1358,9 @@ { struct usb_request *req = fsg->ep0req; int value = -EOPNOTSUPP; + u16 w_index = ctrl->wIndex; + u16 w_value = ctrl->wValue; + u16 w_length = ctrl->wLength; /* Usually this just stores reply data in the pre-allocated ep0 buffer, * but config change events will also reconfigure hardware. */ @@ -1359,11 +1370,11 @@ if (ctrl->bRequestType != (USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE)) break; - switch (ctrl->wValue >> 8) { + switch (w_value >> 8) { case USB_DT_DEVICE: VDBG(fsg, "get device descriptor\n"); - value = min(ctrl->wLength, (u16) sizeof device_desc); + value = min(w_length, (u16) sizeof device_desc); memcpy(req->buf, &device_desc, value); break; #ifdef CONFIG_USB_GADGET_DUALSPEED @@ -1371,7 +1382,7 @@ VDBG(fsg, "get device qualifier\n"); if (!fsg->gadget->is_dualspeed) break; - value = min(ctrl->wLength, (u16) sizeof dev_qualifier); + value = min(w_length, (u16) sizeof dev_qualifier); memcpy(req->buf, &dev_qualifier, value); break; @@ -1388,10 +1399,10 @@ #endif value = populate_config_buf(fsg->gadget, req->buf, - ctrl->wValue >> 8, - ctrl->wValue & 0xff); + w_value >> 8, + w_value & 0xff); if (value >= 0) - value = min(ctrl->wLength, (u16) value); + value = min(w_length, (u16) value); break; case USB_DT_STRING: @@ -1399,9 +1410,9 @@ /* wIndex == language code */ value = usb_gadget_get_string(&stringtab, - ctrl->wValue & 0xff, req->buf); + w_value & 0xff, req->buf); if (value >= 0) - value = min(ctrl->wLength, (u16) value); + value = min(w_length, (u16) value); break; } break; @@ -1412,8 +1423,8 @@ USB_RECIP_DEVICE)) break; VDBG(fsg, "set configuration\n"); - if (ctrl->wValue == CONFIG_VALUE || ctrl->wValue == 0) { - fsg->new_config = ctrl->wValue; + if (w_value == CONFIG_VALUE || w_value == 0) { + fsg->new_config = w_value; /* Raise an exception to wipe out previous transaction * state (queued bufs, etc) and set the new config. */ @@ -1427,14 +1438,14 @@ break; VDBG(fsg, "get configuration\n"); *(u8 *) req->buf = fsg->config; - value = min(ctrl->wLength, (u16) 1); + value = min(w_length, (u16) 1); break; case USB_REQ_SET_INTERFACE: if (ctrl->bRequestType != (USB_DIR_OUT| USB_TYPE_STANDARD | USB_RECIP_INTERFACE)) break; - if (fsg->config && ctrl->wIndex == 0) { + if (fsg->config && w_index == 0) { /* Raise an exception to wipe out previous transaction * state (queued bufs, etc) and install the new @@ -1449,20 +1460,20 @@ break; if (!fsg->config) break; - if (ctrl->wIndex != 0) { + if (w_index != 0) { value = -EDOM; break; } VDBG(fsg, "get interface\n"); *(u8 *) req->buf = 0; - value = min(ctrl->wLength, (u16) 1); + value = min(w_length, (u16) 1); break; default: VDBG(fsg, "unknown control req %02x.%02x v%04x i%04x l%u\n", ctrl->bRequestType, ctrl->bRequest, - ctrl->wValue, ctrl->wIndex, ctrl->wLength); + w_value, w_index, w_length); } return value; @@ -3740,6 +3751,10 @@ mod_data.release = 0x0310; else if (gadget_is_pxa27x(fsg->gadget)) mod_data.release = 0x0311; + else if (gadget_is_s3c2410(gadget)) + mod_data.release = 0x0312; + else if (gadget_is_at91(fsg->gadget)) + mod_data.release = 0x0313; else { WARN(fsg, "controller '%s' not recognized\n", fsg->gadget->name); diff -Nru a/drivers/usb/gadget/gadget_chips.h b/drivers/usb/gadget/gadget_chips.h --- a/drivers/usb/gadget/gadget_chips.h 2005-03-24 18:21:08 -08:00 +++ b/drivers/usb/gadget/gadget_chips.h 2005-03-24 18:21:08 -08:00 @@ -80,7 +80,12 @@ #define gadget_is_s3c2410(g) 0 #endif -// CONFIG_USB_GADGET_AT91RM9200 +#ifdef CONFIG_USB_GADGET_AT91 +#define gadget_is_at91(g) !strcmp("at91_udc", (g)->name) +#else +#define gadget_is_at91(g) 0 +#endif + // CONFIG_USB_GADGET_SX2 // CONFIG_USB_GADGET_AU1X00 // ... diff -Nru a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c --- a/drivers/usb/gadget/inode.c 2005-03-24 18:21:08 -08:00 +++ b/drivers/usb/gadget/inode.c 2005-03-24 18:21:08 -08:00 @@ -1318,6 +1318,8 @@ struct usb_request *req = dev->req; int value = -EOPNOTSUPP; struct usb_gadgetfs_event *event; + u16 w_value = ctrl->wValue; + u16 w_length = ctrl->wLength; spin_lock (&dev->lock); dev->setup_abort = 0; @@ -1378,17 +1380,17 @@ case USB_REQ_GET_DESCRIPTOR: if (ctrl->bRequestType != USB_DIR_IN) goto unrecognized; - switch (ctrl->wValue >> 8) { + switch (w_value >> 8) { case USB_DT_DEVICE: - value = min (ctrl->wLength, (u16) sizeof *dev->dev); + value = min (w_length, (u16) sizeof *dev->dev); req->buf = dev->dev; break; #ifdef HIGHSPEED case USB_DT_DEVICE_QUALIFIER: if (!dev->hs_config) break; - value = min (ctrl->wLength, (u16) + value = min (w_length, (u16) sizeof (struct usb_qualifier_descriptor)); make_qualifier (dev); break; @@ -1397,10 +1399,10 @@ #endif case USB_DT_CONFIG: value = config_buf (dev, - ctrl->wValue >> 8, - ctrl->wValue & 0xff); + w_value >> 8, + w_value & 0xff); if (value >= 0) - value = min (ctrl->wLength, (u16) value); + value = min (w_length, (u16) value); break; case USB_DT_STRING: goto unrecognized; @@ -1414,7 +1416,7 @@ case USB_REQ_SET_CONFIGURATION: if (ctrl->bRequestType != 0) break; - if (0 == (u8) ctrl->wValue) { + if (0 == (u8) w_value) { value = 0; dev->current_config = 0; usb_gadget_vbus_draw(gadget, 8 /* mA */ ); @@ -1432,7 +1434,7 @@ power = dev->config->bMaxPower; } - if (config == (u8) ctrl->wValue) { + if (config == (u8) w_value) { value = 0; dev->current_config = config; usb_gadget_vbus_draw(gadget, 2 * power); @@ -1463,7 +1465,7 @@ if (ctrl->bRequestType != 0x80) break; *(u8 *)req->buf = dev->current_config; - value = min (ctrl->wLength, (u16) 1); + value = min (w_length, (u16) 1); break; #endif @@ -1472,7 +1474,7 @@ VDEBUG (dev, "%s req%02x.%02x v%04x i%04x l%d\n", dev->usermode_setup ? "delegate" : "fail", ctrl->bRequestType, ctrl->bRequest, - ctrl->wValue, ctrl->wIndex, ctrl->wLength); + w_value, le16_to_cpu(ctrl->wIndex), w_length); /* if there's an ep0 reader, don't stall */ if (dev->usermode_setup) { @@ -1485,9 +1487,9 @@ value = 0; /* read DATA stage for OUT right away */ - if (unlikely (!dev->setup_in && ctrl->wLength)) { + if (unlikely (!dev->setup_in && w_length)) { value = setup_req (gadget->ep0, dev->req, - ctrl->wLength); + w_length); if (value < 0) break; value = usb_ep_queue (gadget->ep0, dev->req, @@ -1513,8 +1515,7 @@ /* proceed with data transfer and status phases? */ if (value >= 0 && dev->state != STATE_SETUP) { req->length = value; - req->zero = value < ctrl->wLength - && (value % gadget->ep0->maxpacket) == 0; + req->zero = value < w_length; value = usb_ep_queue (gadget->ep0, req, GFP_ATOMIC); if (value < 0) { DBG (dev, "ep_queue --> %d\n", value); diff -Nru a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c --- a/drivers/usb/gadget/net2280.c 2005-03-24 18:21:08 -08:00 +++ b/drivers/usb/gadget/net2280.c 2005-03-24 18:21:08 -08:00 @@ -1270,7 +1270,7 @@ } spin_unlock_irqrestore (&ep->dev->lock, flags); - return req ? 0 : -EOPNOTSUPP; + return 0; } /*-------------------------------------------------------------------------*/ diff -Nru a/drivers/usb/gadget/pxa2xx_udc.c b/drivers/usb/gadget/pxa2xx_udc.c --- a/drivers/usb/gadget/pxa2xx_udc.c 2005-03-24 18:21:08 -08:00 +++ b/drivers/usb/gadget/pxa2xx_udc.c 2005-03-24 18:21:08 -08:00 @@ -310,7 +310,7 @@ /* flush fifo (mostly for IN buffers) */ pxa2xx_ep_fifo_flush (_ep); - ep->desc = 0; + ep->desc = NULL; ep->stopped = 1; DBG(DBG_VERBOSE, "%s disabled\n", _ep->name); @@ -334,7 +334,7 @@ req = kmalloc (sizeof *req, gfp_flags); if (!req) - return 0; + return NULL; memset (req, 0, sizeof *req); INIT_LIST_HEAD (&req->queue); @@ -369,7 +369,11 @@ retval = kmalloc (bytes, gfp_flags & ~(__GFP_DMA|__GFP_HIGHMEM)); if (retval) +#ifdef USE_DMA *dma = virt_to_bus (retval); +#else + *dma = (dma_addr_t)~0; +#endif return retval; } @@ -411,7 +415,6 @@ static inline void ep0_idle (struct pxa2xx_udc *dev) { dev->ep0state = EP0_IDLE; - LED_EP0_OFF; } static int @@ -930,7 +933,7 @@ case EP0_IN_DATA_PHASE: dev->stats.write.ops++; if (write_ep0_fifo(ep, req)) - req = 0; + req = NULL; break; case EP0_OUT_DATA_PHASE: @@ -940,7 +943,8 @@ DBG(DBG_VERBOSE, "ep0 config ack%s\n", dev->has_cfr ? "" : " raced"); if (dev->has_cfr) - UDCCFR = UDCCFR_AREN|UDCCFR_ACM; + UDCCFR = UDCCFR_AREN|UDCCFR_ACM + |UDCCFR_MB1; done(ep, req, 0); dev->ep0state = EP0_END_XFER; local_irq_restore (flags); @@ -952,7 +956,7 @@ && read_ep0_fifo(ep, req))) { ep0_idle(dev); done(ep, req, 0); - req = 0; + req = NULL; } break; @@ -970,10 +974,10 @@ } else if ((ep->bEndpointAddress & USB_DIR_IN) != 0 && (*ep->reg_udccs & UDCCS_BI_TFS) != 0 && write_fifo(ep, req)) { - req = 0; + req = NULL; } else if ((*ep->reg_udccs & UDCCS_BO_RFS) != 0 && read_fifo(ep, req)) { - req = 0; + req = NULL; } if (likely (req && ep->desc) && ep->dma < 0) @@ -1094,7 +1098,6 @@ start_watchdog(ep->dev); ep->dev->req_pending = 0; ep->dev->ep0state = EP0_STALL; - LED_EP0_OFF; /* and bulk/intr endpoints like dropping stalls too */ } else { @@ -1194,13 +1197,71 @@ return 0; } +static void stop_activity(struct pxa2xx_udc *, struct usb_gadget_driver *); +static void udc_enable (struct pxa2xx_udc *); +static void udc_disable(struct pxa2xx_udc *); + +/* We disable the UDC -- and its 48 MHz clock -- whenever it's not + * in active use. + */ +static int pullup(struct pxa2xx_udc *udc, int is_active) +{ + is_active = is_active && udc->vbus && udc->pullup; + DMSG("%s\n", is_active ? "active" : "inactive"); + if (is_active) + udc_enable(udc); + else { + if (udc->gadget.speed != USB_SPEED_UNKNOWN) { + DMSG("disconnect %s\n", udc->driver + ? udc->driver->driver.name + : "(no driver)"); + stop_activity(udc, udc->driver); + } + udc_disable(udc); + } + return 0; +} + +/* VBUS reporting logically comes from a transceiver */ +static int pxa2xx_udc_vbus_session(struct usb_gadget *_gadget, int is_active) +{ + struct pxa2xx_udc *udc; + + udc = container_of(_gadget, struct pxa2xx_udc, gadget); + udc->vbus = is_active = (is_active != 0); + DMSG("vbus %s\n", is_active ? "supplied" : "inactive"); + pullup(udc, is_active); + return 0; +} + +/* drivers may have software control over D+ pullup */ +static int pxa2xx_udc_pullup(struct usb_gadget *_gadget, int is_active) +{ + struct pxa2xx_udc *udc; + + udc = container_of(_gadget, struct pxa2xx_udc, gadget); + + /* not all boards support pullup control */ + if (!udc->mach->udc_command) + return -EOPNOTSUPP; + + is_active = (is_active != 0); + udc->pullup = is_active; + pullup(udc, is_active); + return 0; +} + static const struct usb_gadget_ops pxa2xx_udc_ops = { - .get_frame = pxa2xx_udc_get_frame, - .wakeup = pxa2xx_udc_wakeup, - // current versions must always be self-powered + .get_frame = pxa2xx_udc_get_frame, + .wakeup = pxa2xx_udc_wakeup, + .vbus_session = pxa2xx_udc_vbus_session, + .pullup = pxa2xx_udc_pullup, + + // .vbus_draw ... boards may consume current from VBUS, up to + // 100-500mA based on config. the 500uA suspend ceiling means + // that exclusively vbus-powered PXA designs violate USB specs. }; - /*-------------------------------------------------------------------------*/ #ifdef CONFIG_USB_GADGET_DEBUG_FILES @@ -1427,7 +1488,7 @@ if (i != 0) list_add_tail (&ep->ep.ep_list, &dev->gadget.ep_list); - ep->desc = 0; + ep->desc = NULL; ep->stopped = 0; INIT_LIST_HEAD (&ep->queue); ep->pio_irqs = ep->dma_irqs = 0; @@ -1446,6 +1507,7 @@ #ifdef CONFIG_ARCH_PXA /* Enable clock for USB device */ pxa_set_cken(CKEN11_USB, 1); + udelay(5); #endif /* try to clear these bits before we enable the udc */ @@ -1469,7 +1531,7 @@ /* pxa255 (a0+) can avoid a set_config race that could * prevent gadget drivers from configuring correctly */ - UDCCFR = UDCCFR_ACM; + UDCCFR = UDCCFR_ACM | UDCCFR_MB1; } else { /* "USB test mode" for pxa250 errata 40-42 (stepping a0, a1) * which could result in missing packets and interrupts. @@ -1498,18 +1560,13 @@ } #endif - /* caller must be able to sleep in order to cope - * with startup transients. - */ - msleep(100); - /* enable suspend/resume and reset irqs */ udc_clear_mask_UDCCR(UDCCR_SRM | UDCCR_REM); /* enable ep0 irqs */ UICR0 &= ~UICR0_IM0; - /* if hardware supports it, connect to usb and wait for host */ + /* if hardware supports it, pullup D+ and wait for reset */ let_usb_appear(); } @@ -1540,6 +1597,7 @@ /* first hook up the driver ... */ dev->driver = driver; dev->gadget.dev.driver = &driver->driver; + dev->pullup = 1; device_add (&dev->gadget.dev); retval = driver->bind(&dev->gadget); @@ -1548,18 +1606,17 @@ driver->driver.name, retval); device_del (&dev->gadget.dev); - dev->driver = 0; - dev->gadget.dev.driver = 0; + dev->driver = NULL; + dev->gadget.dev.driver = NULL; return retval; } device_create_file(dev->dev, &dev_attr_function); /* ... then enable host detection and ep0; and we're ready * for set_configuration as well as eventual disconnect. - * NOTE: this shouldn't power up until later. */ DMSG("registered gadget driver '%s'\n", driver->driver.name); - udc_enable(dev); + pullup(dev, 1); dump_state(dev); return 0; } @@ -1572,7 +1629,7 @@ /* don't disconnect drivers more than once */ if (dev->gadget.speed == USB_SPEED_UNKNOWN) - driver = 0; + driver = NULL; dev->gadget.speed = USB_SPEED_UNKNOWN; /* prevent new request submissions, kill any outstanding requests */ @@ -1603,12 +1660,12 @@ return -EINVAL; local_irq_disable(); - udc_disable(dev); + pullup(dev, 0); stop_activity(dev, driver); local_irq_enable(); driver->unbind(&dev->gadget); - dev->driver = 0; + dev->driver = NULL; device_del (&dev->gadget.dev); device_remove_file(dev->dev, &dev_attr_function); @@ -1624,61 +1681,41 @@ #ifdef CONFIG_ARCH_LUBBOCK -/* Lubbock can report connect or disconnect irqs. Likely more hardware - * could support it as a timer callback. - * - * FIXME for better power management, keep the hardware powered down - * until a host is powering the link. means scheduling work later - * in some task that can udc_enable(). +/* Lubbock has separate connect and disconnect irqs. More typical designs + * use one GPIO as the VBUS IRQ, and another to control the D+ pullup. */ -#define enable_disconnect_irq() \ - if (machine_is_lubbock()) { enable_irq(LUBBOCK_USB_DISC_IRQ); } -#define disable_disconnect_irq() \ - if (machine_is_lubbock()) { disable_irq(LUBBOCK_USB_DISC_IRQ); } - static irqreturn_t -usb_connection_irq(int irq, void *_dev, struct pt_regs *r) +lubbock_vbus_irq(int irq, void *_dev, struct pt_regs *r) { struct pxa2xx_udc *dev = _dev; + int vbus; dev->stats.irqs++; HEX_DISPLAY(dev->stats.irqs); - - if (!is_usb_connected()) { - LED_CONNECTED_OFF; - disable_disconnect_irq(); - /* report disconnect just once */ - if (dev->gadget.speed != USB_SPEED_UNKNOWN) { - DMSG("disconnect %s\n", - dev->driver ? dev->driver->driver.name : 0); - stop_activity(dev, dev->driver); - - // udc_disable (dev); - // no more udc irqs - // maybe "ACTION=disconnect /sbin/hotplug gadget". - } - } else if (dev->gadget.speed == USB_SPEED_UNKNOWN) { + switch (irq) { + case LUBBOCK_USB_IRQ: LED_CONNECTED_ON; - - DMSG("?? connect irq ??\n"); - - // if there's no driver bound, ignore; else - // udc_enable (dev); - // UDC irqs drive the rest. - // maybe "ACTION=connect /sbin/hotplug gadget". + vbus = 1; + disable_irq(LUBBOCK_USB_IRQ); + enable_irq(LUBBOCK_USB_DISC_IRQ); + break; + case LUBBOCK_USB_DISC_IRQ: + LED_CONNECTED_OFF; + vbus = 0; + disable_irq(LUBBOCK_USB_DISC_IRQ); + enable_irq(LUBBOCK_USB_IRQ); + break; + default: + return IRQ_NONE; } + + pxa2xx_udc_vbus_session(&dev->gadget, vbus); return IRQ_HANDLED; } #endif -#ifndef enable_disconnect_irq -#warning USB disconnect() is not yet reported. -#define enable_disconnect_irq() do {} while (0) -#define disable_disconnect_irq() do {} while (0) -#endif - /*-------------------------------------------------------------------------*/ @@ -1720,7 +1757,7 @@ } u; if (list_empty(&ep->queue)) - req = 0; + req = NULL; else req = list_entry(ep->queue.next, struct pxa2xx_request, queue); @@ -1764,14 +1801,11 @@ goto bad_setup; got_setup: - le16_to_cpus (&u.r.wValue); - le16_to_cpus (&u.r.wIndex); - le16_to_cpus (&u.r.wLength); - - LED_EP0_ON; DBG(DBG_VERBOSE, "SETUP %02x.%02x v%04x i%04x l%04x\n", u.r.bRequestType, u.r.bRequest, - u.r.wValue, u.r.wIndex, u.r.wLength); + le16_to_cpu(u.r.wValue), + le16_to_cpu(u.r.wIndex), + le16_to_cpu(u.r.wLength)); /* cope with automagic for some standard requests. */ dev->req_std = (u.r.bRequestType & USB_TYPE_MASK) @@ -1803,7 +1837,8 @@ * - ep reset doesn't include halt(?). */ DMSG("broken set_interface (%d/%d)\n", - u.r.wIndex, u.r.wValue); + le16_to_cpu(u.r.wIndex), + le16_to_cpu(u.r.wValue)); goto config_change; } break; @@ -1847,7 +1882,6 @@ ep0start(dev, UDCCS0_FST|UDCCS0_FTF, "stall"); start_watchdog(dev); dev->ep0state = EP0_STALL; - LED_EP0_OFF; /* deferred i/o == no response yet */ } else if (dev->req_pending) { @@ -1948,7 +1982,7 @@ req = list_entry(ep->queue.next, struct pxa2xx_request, queue); else - req = 0; + req = NULL; // TODO check FST handling @@ -2050,8 +2084,6 @@ if ((UDCCR & UDCCR_UDA) == 0) { DBG(DBG_VERBOSE, "USB reset start\n"); - if (dev->gadget.speed != USB_SPEED_UNKNOWN) - disable_disconnect_irq(); /* reset driver and endpoints, * in case that's not yet done @@ -2059,12 +2091,11 @@ stop_activity (dev, dev->driver); } else { - INFO("USB reset\n"); + DBG(DBG_VERBOSE, "USB reset end\n"); dev->gadget.speed = USB_SPEED_FULL; LED_CONNECTED_ON; memset(&dev->stats, 0, sizeof dev->stats); /* driver and endpoints are still reset */ - enable_disconnect_irq(); } } else { @@ -2478,6 +2509,8 @@ udc_disable(dev); udc_reinit(dev); + dev->vbus = is_usb_connected(); + /* irq setup after old hardware state is cleaned up */ retval = request_irq(IRQ_USB, pxa2xx_udc_irq, SA_INTERRUPT, driver_name, dev); @@ -2490,18 +2523,32 @@ #ifdef CONFIG_ARCH_LUBBOCK if (machine_is_lubbock()) { - disable_irq(LUBBOCK_USB_DISC_IRQ); retval = request_irq(LUBBOCK_USB_DISC_IRQ, - usb_connection_irq, - SA_INTERRUPT /* OOPSING | SA_SAMPLE_RANDOM */, + lubbock_vbus_irq, + SA_INTERRUPT | SA_SAMPLE_RANDOM, driver_name, dev); if (retval != 0) { - enable_irq(LUBBOCK_USB_DISC_IRQ); printk(KERN_ERR "%s: can't get irq %i, err %d\n", driver_name, LUBBOCK_USB_DISC_IRQ, retval); +lubbock_fail0: + free_irq(IRQ_USB, dev); return -EBUSY; } - dev->got_disc = 1; + retval = request_irq(LUBBOCK_USB_IRQ, + lubbock_vbus_irq, + SA_INTERRUPT | SA_SAMPLE_RANDOM, + driver_name, dev); + if (retval != 0) { + printk(KERN_ERR "%s: can't get irq %i, err %d\n", + driver_name, LUBBOCK_USB_IRQ, retval); + free_irq(LUBBOCK_USB_DISC_IRQ, dev); + goto lubbock_fail0; + } +#ifdef DEBUG + /* with U-Boot (but not BLOB), hex is off by default */ + HEX_DISPLAY(dev->stats.irqs); + LUB_DISC_BLNK_LED &= 0xff; +#endif } #endif create_proc_files(); @@ -2510,7 +2557,7 @@ } static int __exit pxa2xx_udc_remove(struct device *_dev) { - struct pxa2xx_udc *dev = _dev->driver_data; + struct pxa2xx_udc *dev = dev_get_drvdata(_dev); udc_disable(dev); remove_proc_files(); @@ -2520,26 +2567,66 @@ free_irq(IRQ_USB, dev); dev->got_irq = 0; } - if (machine_is_lubbock() && dev->got_disc) { + if (machine_is_lubbock()) { free_irq(LUBBOCK_USB_DISC_IRQ, dev); - dev->got_disc = 0; + free_irq(LUBBOCK_USB_IRQ, dev); } - dev_set_drvdata(_dev, 0); - the_controller = 0; + dev_set_drvdata(_dev, NULL); + the_controller = NULL; return 0; } /*-------------------------------------------------------------------------*/ +#ifdef CONFIG_PM + +/* USB suspend (controlled by the host) and system suspend (controlled + * by the PXA) don't necessarily work well together. If USB is active, + * the 48 MHz clock is required; so the system can't enter 33 MHz idle + * mode, or any deeper PM saving state. + * + * For now, we punt and forcibly disconnect from the USB host when PXA + * enters any suspend state. While we're disconnected, we always disable + * the 48MHz USB clock ... allowing PXA sleep and/or 33 MHz idle states. + * Boards without software pullup control shouldn't use those states. + * VBUS IRQs should probably be ignored so that the PXA device just acts + * "dead" to USB hosts until system resume. + */ +static int pxa2xx_udc_suspend(struct device *dev, u32 state, u32 level) +{ + struct pxa2xx_udc *udc = dev_get_drvdata(dev); + + if (level == SUSPEND_POWER_DOWN) { + if (!udc->mach->udc_command) + WARN("USB host won't detect disconnect!\n"); + pullup(udc, 0); + } + return 0; +} + +static int pxa2xx_udc_resume(struct device *dev, u32 level) +{ + struct pxa2xx_udc *udc = dev_get_drvdata(dev); + + if (level == RESUME_POWER_ON) + pullup(udc, 1); + return 0; +} + +#else +#define pxa2xx_udc_suspend NULL +#define pxa2xx_udc_resume NULL +#endif + +/*-------------------------------------------------------------------------*/ + static struct device_driver udc_driver = { .name = "pxa2xx-udc", .bus = &platform_bus_type, .probe = pxa2xx_udc_probe, .remove = __exit_p(pxa2xx_udc_remove), - - // FIXME power management support - // .suspend = ... disable UDC - // .resume = ... re-enable UDC + .suspend = pxa2xx_udc_suspend, + .resume = pxa2xx_udc_resume, }; static int __init udc_init(void) diff -Nru a/drivers/usb/gadget/pxa2xx_udc.h b/drivers/usb/gadget/pxa2xx_udc.h --- a/drivers/usb/gadget/pxa2xx_udc.h 2005-03-24 18:21:08 -08:00 +++ b/drivers/usb/gadget/pxa2xx_udc.h 2005-03-24 18:21:08 -08:00 @@ -40,6 +40,9 @@ #define UDCCFR_AREN (1 << 7) /* ACK response enable (now) */ #define UDCCFR_ACM (1 << 2) /* ACK control mode (wait for AREN) */ +/* latest pxa255 errata define new "must be one" bits in UDCCFR */ +#define UDCCFR_MB1 (0xff & ~(UDCCFR_AREN|UDCCFR_ACM)) + /*-------------------------------------------------------------------------*/ struct pxa2xx_udc; @@ -120,7 +123,8 @@ enum ep0_state ep0state; struct udc_stats stats; unsigned got_irq : 1, - got_disc : 1, + vbus : 1, + pullup : 1, has_cfr : 1, req_pending : 1, req_std : 1, @@ -143,14 +147,7 @@ #ifdef DEBUG #define HEX_DISPLAY(n) if (machine_is_lubbock()) { LUB_HEXLED = (n); } - -#define LED_CONNECTED_ON if (machine_is_lubbock()) { \ - DISCRETE_LED_ON(D26); } -#define LED_CONNECTED_OFF if(machine_is_lubbock()) { \ - DISCRETE_LED_OFF(D26); LUB_HEXLED = 0; } -#define LED_EP0_ON if (machine_is_lubbock()) { DISCRETE_LED_ON(D25); } -#define LED_EP0_OFF if (machine_is_lubbock()) { DISCRETE_LED_OFF(D25); } -#endif /* DEBUG */ +#endif #endif @@ -161,13 +158,19 @@ #define HEX_DISPLAY(n) do {} while(0) #endif +#ifdef DEBUG +#include + +#define LED_CONNECTED_ON leds_event(led_green_on) +#define LED_CONNECTED_OFF do { \ + leds_event(led_green_off); \ + HEX_DISPLAY(0); \ + } while(0) +#endif + #ifndef LED_CONNECTED_ON #define LED_CONNECTED_ON do {} while(0) #define LED_CONNECTED_OFF do {} while(0) -#endif -#ifndef LED_EP0_ON -#define LED_EP0_ON do {} while (0) -#define LED_EP0_OFF do {} while (0) #endif /*-------------------------------------------------------------------------*/ diff -Nru a/drivers/usb/gadget/rndis.c b/drivers/usb/gadget/rndis.c --- a/drivers/usb/gadget/rndis.c 2005-03-24 18:21:08 -08:00 +++ b/drivers/usb/gadget/rndis.c 2005-03-24 18:21:08 -08:00 @@ -74,7 +74,7 @@ static rndis_params rndis_per_dev_params [RNDIS_MAX_CONFIGS]; /* Driver Version */ -static const u32 rndis_driver_version = __constant_cpu_to_le32 (1); +static const __le32 rndis_driver_version = __constant_cpu_to_le32 (1); /* Function Prototypes */ static int rndis_init_response (int configNr, rndis_init_msg_type *buf); @@ -92,7 +92,7 @@ { int retval = -ENOTSUPP; u32 length = 0; - u32 *tmp; + __le32 *tmp; int i, count; rndis_query_cmplt_type *resp; @@ -110,7 +110,7 @@ DEBUG ("%s: OID_GEN_SUPPORTED_LIST\n", __FUNCTION__); length = sizeof (oid_supported_list); count = length / sizeof (u32); - tmp = (u32 *) ((u8 *)resp + 24); + tmp = (__le32 *) ((u8 *)resp + 24); for (i = 0; i < count; i++) tmp[i] = cpu_to_le32 (oid_supported_list[i]); retval = 0; @@ -126,7 +126,7 @@ * reddite ergo quae sunt Caesaris Caesari * et quae sunt Dei Deo! */ - *((u32 *) resp + 6) = __constant_cpu_to_le32 (0); + *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0); retval = 0; break; @@ -134,7 +134,7 @@ case OID_GEN_MEDIA_SUPPORTED: DEBUG("%s: OID_GEN_MEDIA_SUPPORTED\n", __FUNCTION__); length = 4; - *((u32 *) resp + 6) = cpu_to_le32 ( + *((__le32 *) resp + 6) = cpu_to_le32 ( rndis_per_dev_params [configNr].medium); retval = 0; break; @@ -144,7 +144,7 @@ DEBUG("%s: OID_GEN_MEDIA_IN_USE\n", __FUNCTION__); length = 4; /* one medium, one transport... (maybe you do it better) */ - *((u32 *) resp + 6) = cpu_to_le32 ( + *((__le32 *) resp + 6) = cpu_to_le32 ( rndis_per_dev_params [configNr].medium); retval = 0; break; @@ -154,11 +154,11 @@ DEBUG("%s: OID_GEN_MAXIMUM_FRAME_SIZE\n", __FUNCTION__); if (rndis_per_dev_params [configNr].dev) { length = 4; - *((u32 *) resp + 6) = cpu_to_le32 ( + *((__le32 *) resp + 6) = cpu_to_le32 ( rndis_per_dev_params [configNr].dev->mtu); retval = 0; } else { - *((u32 *) resp + 6) = __constant_cpu_to_le32 (0); + *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0); retval = 0; } break; @@ -169,9 +169,9 @@ length = 4; if (rndis_per_dev_params [configNr].media_state == NDIS_MEDIA_STATE_DISCONNECTED) - *((u32 *) resp + 6) = __constant_cpu_to_le32 (0); + *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0); else - *((u32 *) resp + 6) = cpu_to_le32 ( + *((__le32 *) resp + 6) = cpu_to_le32 ( rndis_per_dev_params [configNr].speed); retval = 0; break; @@ -181,7 +181,7 @@ DEBUG("%s: OID_GEN_TRANSMIT_BLOCK_SIZE\n", __FUNCTION__); if (rndis_per_dev_params [configNr].dev) { length = 4; - *((u32 *) resp + 6) = cpu_to_le32 ( + *((__le32 *) resp + 6) = cpu_to_le32 ( rndis_per_dev_params [configNr].dev->mtu); retval = 0; } @@ -192,7 +192,7 @@ DEBUG("%s: OID_GEN_RECEIVE_BLOCK_SIZE\n", __FUNCTION__); if (rndis_per_dev_params [configNr].dev) { length = 4; - *((u32 *) resp + 6) = cpu_to_le32 ( + *((__le32 *) resp + 6) = cpu_to_le32 ( rndis_per_dev_params [configNr].dev->mtu); retval = 0; } @@ -202,7 +202,7 @@ case OID_GEN_VENDOR_ID: DEBUG("%s: OID_GEN_VENDOR_ID\n", __FUNCTION__); length = 4; - *((u32 *) resp + 6) = cpu_to_le32 ( + *((__le32 *) resp + 6) = cpu_to_le32 ( rndis_per_dev_params [configNr].vendorID); retval = 0; break; @@ -220,7 +220,7 @@ DEBUG("%s: OID_GEN_VENDOR_DRIVER_VERSION\n", __FUNCTION__); length = 4; /* Created as LE */ - *((u32 *) resp + 6) = rndis_driver_version; + *((__le32 *) resp + 6) = rndis_driver_version; retval = 0; break; @@ -228,7 +228,7 @@ case OID_GEN_CURRENT_PACKET_FILTER: DEBUG("%s: OID_GEN_CURRENT_PACKET_FILTER\n", __FUNCTION__); length = 4; - *((u32 *) resp + 6) = cpu_to_le32 ( + *((__le32 *) resp + 6) = cpu_to_le32 ( rndis_per_dev_params[configNr].filter); retval = 0; break; @@ -237,7 +237,7 @@ case OID_GEN_MAXIMUM_TOTAL_SIZE: DEBUG("%s: OID_GEN_MAXIMUM_TOTAL_SIZE\n", __FUNCTION__); length = 4; - *((u32 *) resp + 6) = __constant_cpu_to_le32( + *((__le32 *) resp + 6) = __constant_cpu_to_le32( RNDIS_MAX_TOTAL_SIZE); retval = 0; break; @@ -246,7 +246,7 @@ case OID_GEN_MEDIA_CONNECT_STATUS: DEBUG("%s: OID_GEN_MEDIA_CONNECT_STATUS\n", __FUNCTION__); length = 4; - *((u32 *) resp + 6) = cpu_to_le32 ( + *((__le32 *) resp + 6) = cpu_to_le32 ( rndis_per_dev_params [configNr] .media_state); retval = 0; @@ -255,7 +255,7 @@ case OID_GEN_PHYSICAL_MEDIUM: DEBUG("%s: OID_GEN_PHYSICAL_MEDIUM\n", __FUNCTION__); length = 4; - *((u32 *) resp + 6) = __constant_cpu_to_le32 (0); + *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0); retval = 0; break; @@ -266,7 +266,7 @@ case OID_GEN_MAC_OPTIONS: /* from WinME */ DEBUG("%s: OID_GEN_MAC_OPTIONS\n", __FUNCTION__); length = 4; - *((u32 *) resp + 6) = __constant_cpu_to_le32( + *((__le32 *) resp + 6) = __constant_cpu_to_le32( NDIS_MAC_OPTION_RECEIVE_SERIALIZED | NDIS_MAC_OPTION_FULL_DUPLEX); retval = 0; @@ -279,13 +279,13 @@ DEBUG("%s: OID_GEN_XMIT_OK\n", __FUNCTION__); if (rndis_per_dev_params [configNr].stats) { length = 4; - *((u32 *) resp + 6) = cpu_to_le32 ( + *((__le32 *) resp + 6) = cpu_to_le32 ( rndis_per_dev_params [configNr].stats->tx_packets - rndis_per_dev_params [configNr].stats->tx_errors - rndis_per_dev_params [configNr].stats->tx_dropped); retval = 0; } else { - *((u32 *) resp + 6) = __constant_cpu_to_le32 (0); + *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0); retval = 0; } break; @@ -295,13 +295,13 @@ DEBUG("%s: OID_GEN_RCV_OK\n", __FUNCTION__); if (rndis_per_dev_params [configNr].stats) { length = 4; - *((u32 *) resp + 6) = cpu_to_le32 ( + *((__le32 *) resp + 6) = cpu_to_le32 ( rndis_per_dev_params [configNr].stats->rx_packets - rndis_per_dev_params [configNr].stats->rx_errors - rndis_per_dev_params [configNr].stats->rx_dropped); retval = 0; } else { - *((u32 *) resp + 6) = __constant_cpu_to_le32 (0); + *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0); retval = 0; } break; @@ -311,12 +311,12 @@ DEBUG("%s: OID_GEN_XMIT_ERROR\n", __FUNCTION__); if (rndis_per_dev_params [configNr].stats) { length = 4; - *((u32 *) resp + 6) = cpu_to_le32 ( + *((__le32 *) resp + 6) = cpu_to_le32 ( rndis_per_dev_params [configNr] .stats->tx_errors); retval = 0; } else { - *((u32 *) resp + 6) = __constant_cpu_to_le32 (0); + *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0); retval = 0; } break; @@ -325,12 +325,12 @@ case OID_GEN_RCV_ERROR: DEBUG("%s: OID_GEN_RCV_ERROR\n", __FUNCTION__); if (rndis_per_dev_params [configNr].stats) { - *((u32 *) resp + 6) = cpu_to_le32 ( + *((__le32 *) resp + 6) = cpu_to_le32 ( rndis_per_dev_params [configNr] .stats->rx_errors); retval = 0; } else { - *((u32 *) resp + 6) = __constant_cpu_to_le32 (0); + *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0); retval = 0; } break; @@ -339,12 +339,12 @@ case OID_GEN_RCV_NO_BUFFER: DEBUG("%s: OID_GEN_RCV_NO_BUFFER\n", __FUNCTION__); if (rndis_per_dev_params [configNr].stats) { - *((u32 *) resp + 6) = cpu_to_le32 ( + *((__le32 *) resp + 6) = cpu_to_le32 ( rndis_per_dev_params [configNr] .stats->rx_dropped); retval = 0; } else { - *((u32 *) resp + 6) = __constant_cpu_to_le32 (0); + *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0); retval = 0; } break; @@ -359,7 +359,7 @@ */ if (rndis_per_dev_params [configNr].stats) { length = 4; - *((u32 *) resp + 6) = cpu_to_le32 ( + *((__le32 *) resp + 6) = cpu_to_le32 ( (rndis_per_dev_params [configNr] .stats->tx_packets - rndis_per_dev_params [configNr] @@ -369,7 +369,7 @@ * 123); retval = 0; } else { - *((u32 *) resp + 6) = __constant_cpu_to_le32 (0); + *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0); retval = 0; } break; @@ -379,7 +379,7 @@ /* dito */ if (rndis_per_dev_params [configNr].stats) { length = 4; - *((u32 *) resp + 6) = cpu_to_le32 ( + *((__le32 *) resp + 6) = cpu_to_le32 ( (rndis_per_dev_params [configNr] .stats->tx_packets - rndis_per_dev_params [configNr] @@ -389,7 +389,7 @@ / 123); retval = 0; } else { - *((u32 *) resp + 6) = __constant_cpu_to_le32 (0); + *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0); retval = 0; } break; @@ -397,12 +397,12 @@ case OID_GEN_MULTICAST_BYTES_XMIT: DEBUG("%s: OID_GEN_MULTICAST_BYTES_XMIT\n", __FUNCTION__); if (rndis_per_dev_params [configNr].stats) { - *((u32 *) resp + 6) = cpu_to_le32 ( + *((__le32 *) resp + 6) = cpu_to_le32 ( rndis_per_dev_params [configNr] .stats->multicast*1234); retval = 0; } else { - *((u32 *) resp + 6) = __constant_cpu_to_le32 (0); + *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0); retval = 0; } break; @@ -410,12 +410,12 @@ case OID_GEN_MULTICAST_FRAMES_XMIT: DEBUG("%s: OID_GEN_MULTICAST_FRAMES_XMIT\n", __FUNCTION__); if (rndis_per_dev_params [configNr].stats) { - *((u32 *) resp + 6) = cpu_to_le32 ( + *((__le32 *) resp + 6) = cpu_to_le32 ( rndis_per_dev_params [configNr] .stats->multicast); retval = 0; } else { - *((u32 *) resp + 6) = __constant_cpu_to_le32 (0); + *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0); retval = 0; } break; @@ -423,12 +423,12 @@ case OID_GEN_BROADCAST_BYTES_XMIT: DEBUG("%s: OID_GEN_BROADCAST_BYTES_XMIT\n", __FUNCTION__); if (rndis_per_dev_params [configNr].stats) { - *((u32 *) resp + 6) = cpu_to_le32 ( + *((__le32 *) resp + 6) = cpu_to_le32 ( rndis_per_dev_params [configNr] .stats->tx_packets/42*255); retval = 0; } else { - *((u32 *) resp + 6) = __constant_cpu_to_le32 (0); + *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0); retval = 0; } break; @@ -436,37 +436,37 @@ case OID_GEN_BROADCAST_FRAMES_XMIT: DEBUG("%s: OID_GEN_BROADCAST_FRAMES_XMIT\n", __FUNCTION__); if (rndis_per_dev_params [configNr].stats) { - *((u32 *) resp + 6) = cpu_to_le32 ( + *((__le32 *) resp + 6) = cpu_to_le32 ( rndis_per_dev_params [configNr] .stats->tx_packets/42); retval = 0; } else { - *((u32 *) resp + 6) = __constant_cpu_to_le32 (0); + *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0); retval = 0; } break; case OID_GEN_DIRECTED_BYTES_RCV: DEBUG("%s: OID_GEN_DIRECTED_BYTES_RCV\n", __FUNCTION__); - *((u32 *) resp + 6) = __constant_cpu_to_le32 (0); + *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0); retval = 0; break; case OID_GEN_DIRECTED_FRAMES_RCV: DEBUG("%s: OID_GEN_DIRECTED_FRAMES_RCV\n", __FUNCTION__); - *((u32 *) resp + 6) = __constant_cpu_to_le32 (0); + *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0); retval = 0; break; case OID_GEN_MULTICAST_BYTES_RCV: DEBUG("%s: OID_GEN_MULTICAST_BYTES_RCV\n", __FUNCTION__); if (rndis_per_dev_params [configNr].stats) { - *((u32 *) resp + 6) = cpu_to_le32 ( + *((__le32 *) resp + 6) = cpu_to_le32 ( rndis_per_dev_params [configNr] .stats->multicast * 1111); retval = 0; } else { - *((u32 *) resp + 6) = __constant_cpu_to_le32 (0); + *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0); retval = 0; } break; @@ -474,12 +474,12 @@ case OID_GEN_MULTICAST_FRAMES_RCV: DEBUG("%s: OID_GEN_MULTICAST_FRAMES_RCV\n", __FUNCTION__); if (rndis_per_dev_params [configNr].stats) { - *((u32 *) resp + 6) = cpu_to_le32 ( + *((__le32 *) resp + 6) = cpu_to_le32 ( rndis_per_dev_params [configNr] .stats->multicast); retval = 0; } else { - *((u32 *) resp + 6) = __constant_cpu_to_le32 (0); + *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0); retval = 0; } break; @@ -487,12 +487,12 @@ case OID_GEN_BROADCAST_BYTES_RCV: DEBUG("%s: OID_GEN_BROADCAST_BYTES_RCV\n", __FUNCTION__); if (rndis_per_dev_params [configNr].stats) { - *((u32 *) resp + 6) = cpu_to_le32 ( + *((__le32 *) resp + 6) = cpu_to_le32 ( rndis_per_dev_params [configNr] .stats->rx_packets/42*255); retval = 0; } else { - *((u32 *) resp + 6) = __constant_cpu_to_le32 (0); + *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0); retval = 0; } break; @@ -500,12 +500,12 @@ case OID_GEN_BROADCAST_FRAMES_RCV: DEBUG("%s: OID_GEN_BROADCAST_FRAMES_RCV\n", __FUNCTION__); if (rndis_per_dev_params [configNr].stats) { - *((u32 *) resp + 6) = cpu_to_le32 ( + *((__le32 *) resp + 6) = cpu_to_le32 ( rndis_per_dev_params [configNr] .stats->rx_packets/42); retval = 0; } else { - *((u32 *) resp + 6) = __constant_cpu_to_le32 (0); + *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0); retval = 0; } break; @@ -513,19 +513,19 @@ case OID_GEN_RCV_CRC_ERROR: DEBUG("%s: OID_GEN_RCV_CRC_ERROR\n", __FUNCTION__); if (rndis_per_dev_params [configNr].stats) { - *((u32 *) resp + 6) = cpu_to_le32 ( + *((__le32 *) resp + 6) = cpu_to_le32 ( rndis_per_dev_params [configNr] .stats->rx_crc_errors); retval = 0; } else { - *((u32 *) resp + 6) = __constant_cpu_to_le32 (0); + *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0); retval = 0; } break; case OID_GEN_TRANSMIT_QUEUE_LENGTH: DEBUG("%s: OID_GEN_TRANSMIT_QUEUE_LENGTH\n", __FUNCTION__); - *((u32 *) resp + 6) = __constant_cpu_to_le32 (0); + *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0); retval = 0; break; #endif /* RNDIS_OPTIONAL_STATS */ @@ -542,7 +542,7 @@ length); retval = 0; } else { - *((u32 *) resp + 6) = __constant_cpu_to_le32 (0); + *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0); retval = 0; } break; @@ -564,7 +564,7 @@ DEBUG("%s: OID_802_3_MULTICAST_LIST\n", __FUNCTION__); length = 4; /* Multicast base address only */ - *((u32 *) resp + 6) = __constant_cpu_to_le32 (0xE0000000); + *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0xE0000000); retval = 0; break; @@ -573,7 +573,7 @@ DEBUG("%s: OID_802_3_MAXIMUM_LIST_SIZE\n", __FUNCTION__); length = 4; /* Multicast base address only */ - *((u32 *) resp + 6) = __constant_cpu_to_le32 (1); + *((__le32 *) resp + 6) = __constant_cpu_to_le32 (1); retval = 0; break; @@ -589,7 +589,7 @@ if (rndis_per_dev_params [configNr].stats) { length = 4; - *((u32 *) resp + 6) = cpu_to_le32 ( + *((__le32 *) resp + 6) = cpu_to_le32 ( rndis_per_dev_params [configNr] .stats->rx_frame_errors); retval = 0; @@ -600,7 +600,7 @@ case OID_802_3_XMIT_ONE_COLLISION: DEBUG("%s: OID_802_3_XMIT_ONE_COLLISION\n", __FUNCTION__); length = 4; - *((u32 *) resp + 6) = __constant_cpu_to_le32 (0); + *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0); retval = 0; break; @@ -608,7 +608,7 @@ case OID_802_3_XMIT_MORE_COLLISIONS: DEBUG("%s: OID_802_3_XMIT_MORE_COLLISIONS\n", __FUNCTION__); length = 4; - *((u32 *) resp + 6) = __constant_cpu_to_le32 (0); + *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0); retval = 0; break; @@ -734,7 +734,7 @@ * PROMISCUOUS, DIRECTED, * MULTICAST, ALL_MULTICAST, BROADCAST */ - params->filter = cpu_to_le32p((u32 *)buf); + params->filter = le32_to_cpup((__le32 *)buf); DEBUG("%s: OID_GEN_CURRENT_PACKET_FILTER %08x\n", __FUNCTION__, params->filter); @@ -866,7 +866,7 @@ resp->MessageLength = __constant_cpu_to_le32 (24); resp->RequestID = buf->RequestID; /* Still LE in msg buffer */ - if (gen_ndis_query_resp (configNr, cpu_to_le32 (buf->OID), r)) { + if (gen_ndis_query_resp (configNr, le32_to_cpu (buf->OID), r)) { /* OID not supported */ resp->Status = __constant_cpu_to_le32 ( RNDIS_STATUS_NOT_SUPPORTED); @@ -893,8 +893,8 @@ resp = (rndis_set_cmplt_type *) r->buf; if (!resp) return -ENOMEM; - BufLength = cpu_to_le32 (buf->InformationBufferLength); - BufOffset = cpu_to_le32 (buf->InformationBufferOffset); + BufLength = le32_to_cpu (buf->InformationBufferLength); + BufOffset = le32_to_cpu (buf->InformationBufferOffset); #ifdef VERBOSE DEBUG("%s: Length: %d\n", __FUNCTION__, BufLength); @@ -911,7 +911,7 @@ resp->MessageType = __constant_cpu_to_le32 (REMOTE_NDIS_SET_CMPLT); resp->MessageLength = __constant_cpu_to_le32 (16); resp->RequestID = buf->RequestID; /* Still LE in msg buffer */ - if (gen_ndis_set_resp (configNr, cpu_to_le32 (buf->OID), + if (gen_ndis_set_resp (configNr, le32_to_cpu (buf->OID), ((u8 *) buf) + 8 + BufOffset, BufLength, r)) resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_NOT_SUPPORTED); else resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_SUCCESS); @@ -1030,15 +1030,16 @@ */ int rndis_msg_parser (u8 configNr, u8 *buf) { - u32 MsgType, MsgLength, *tmp; + u32 MsgType, MsgLength; + __le32 *tmp; struct rndis_params *params; if (!buf) return -ENOMEM; - tmp = (u32 *) buf; - MsgType = cpu_to_le32p(tmp++); - MsgLength = cpu_to_le32p(tmp++); + tmp = (__le32 *) buf; + MsgType = le32_to_cpup(tmp++); + MsgLength = le32_to_cpup(tmp++); if (configNr >= RNDIS_MAX_CONFIGS) return -ENOTSUPP; @@ -1187,15 +1188,16 @@ void rndis_add_hdr (struct sk_buff *skb) { - if (!skb) return; - skb_push (skb, sizeof (struct rndis_packet_msg_type)); - memset (skb->data, 0, sizeof (struct rndis_packet_msg_type)); - *((u32 *) skb->data) = __constant_cpu_to_le32 (1); - *((u32 *) skb->data + 1) = cpu_to_le32(skb->len); - *((u32 *) skb->data + 2) = __constant_cpu_to_le32 (36); - *((u32 *) skb->data + 3) = cpu_to_le32(skb->len - 44); - - return; + struct rndis_packet_msg_type *header; + + if (!skb) + return; + header = (void *) skb_push (skb, sizeof *header); + memset (header, 0, sizeof *header); + header->MessageType = __constant_cpu_to_le32 (1); + header->MessageLength = cpu_to_le32(skb->len); + header->DataOffset = __constant_cpu_to_le32 (36); + header->OOBDataOffset = cpu_to_le32(skb->len - 44); } void rndis_free_response (int configNr, u8 *buf) @@ -1253,15 +1255,16 @@ int rndis_rm_hdr (u8 *buf, u32 *length) { - u32 i, messageLen, dataOffset, *tmp; + u32 i, messageLen, dataOffset; + __le32 *tmp; - tmp = (u32 *) buf; + tmp = (__le32 *) buf; if (!buf || !length) return -1; - if (cpu_to_le32p(tmp++) != 1) return -1; + if (le32_to_cpup(tmp++) != 1) return -1; - messageLen = cpu_to_le32p(tmp++); - dataOffset = cpu_to_le32p(tmp++) + 8; + messageLen = le32_to_cpup(tmp++); + dataOffset = le32_to_cpup(tmp++) + 8; if (messageLen < dataOffset || messageLen > *length) return -1; diff -Nru a/drivers/usb/gadget/rndis.h b/drivers/usb/gadget/rndis.h --- a/drivers/usb/gadget/rndis.h 2005-03-24 18:21:08 -08:00 +++ b/drivers/usb/gadget/rndis.h 2005-03-24 18:21:08 -08:00 @@ -154,139 +154,139 @@ typedef struct rndis_init_msg_type { - u32 MessageType; - u32 MessageLength; - u32 RequestID; - u32 MajorVersion; - u32 MinorVersion; - u32 MaxTransferSize; + __le32 MessageType; + __le32 MessageLength; + __le32 RequestID; + __le32 MajorVersion; + __le32 MinorVersion; + __le32 MaxTransferSize; } rndis_init_msg_type; typedef struct rndis_init_cmplt_type { - u32 MessageType; - u32 MessageLength; - u32 RequestID; - u32 Status; - u32 MajorVersion; - u32 MinorVersion; - u32 DeviceFlags; - u32 Medium; - u32 MaxPacketsPerTransfer; - u32 MaxTransferSize; - u32 PacketAlignmentFactor; - u32 AFListOffset; - u32 AFListSize; + __le32 MessageType; + __le32 MessageLength; + __le32 RequestID; + __le32 Status; + __le32 MajorVersion; + __le32 MinorVersion; + __le32 DeviceFlags; + __le32 Medium; + __le32 MaxPacketsPerTransfer; + __le32 MaxTransferSize; + __le32 PacketAlignmentFactor; + __le32 AFListOffset; + __le32 AFListSize; } rndis_init_cmplt_type; typedef struct rndis_halt_msg_type { - u32 MessageType; - u32 MessageLength; - u32 RequestID; + __le32 MessageType; + __le32 MessageLength; + __le32 RequestID; } rndis_halt_msg_type; typedef struct rndis_query_msg_type { - u32 MessageType; - u32 MessageLength; - u32 RequestID; - u32 OID; - u32 InformationBufferLength; - u32 InformationBufferOffset; - u32 DeviceVcHandle; + __le32 MessageType; + __le32 MessageLength; + __le32 RequestID; + __le32 OID; + __le32 InformationBufferLength; + __le32 InformationBufferOffset; + __le32 DeviceVcHandle; } rndis_query_msg_type; typedef struct rndis_query_cmplt_type { - u32 MessageType; - u32 MessageLength; - u32 RequestID; - u32 Status; - u32 InformationBufferLength; - u32 InformationBufferOffset; + __le32 MessageType; + __le32 MessageLength; + __le32 RequestID; + __le32 Status; + __le32 InformationBufferLength; + __le32 InformationBufferOffset; } rndis_query_cmplt_type; typedef struct rndis_set_msg_type { - u32 MessageType; - u32 MessageLength; - u32 RequestID; - u32 OID; - u32 InformationBufferLength; - u32 InformationBufferOffset; - u32 DeviceVcHandle; + __le32 MessageType; + __le32 MessageLength; + __le32 RequestID; + __le32 OID; + __le32 InformationBufferLength; + __le32 InformationBufferOffset; + __le32 DeviceVcHandle; } rndis_set_msg_type; typedef struct rndis_set_cmplt_type { - u32 MessageType; - u32 MessageLength; - u32 RequestID; - u32 Status; + __le32 MessageType; + __le32 MessageLength; + __le32 RequestID; + __le32 Status; } rndis_set_cmplt_type; typedef struct rndis_reset_msg_type { - u32 MessageType; - u32 MessageLength; - u32 Reserved; + __le32 MessageType; + __le32 MessageLength; + __le32 Reserved; } rndis_reset_msg_type; typedef struct rndis_reset_cmplt_type { - u32 MessageType; - u32 MessageLength; - u32 Status; - u32 AddressingReset; + __le32 MessageType; + __le32 MessageLength; + __le32 Status; + __le32 AddressingReset; } rndis_reset_cmplt_type; typedef struct rndis_indicate_status_msg_type { - u32 MessageType; - u32 MessageLength; - u32 Status; - u32 StatusBufferLength; - u32 StatusBufferOffset; + __le32 MessageType; + __le32 MessageLength; + __le32 Status; + __le32 StatusBufferLength; + __le32 StatusBufferOffset; } rndis_indicate_status_msg_type; typedef struct rndis_keepalive_msg_type { - u32 MessageType; - u32 MessageLength; - u32 RequestID; + __le32 MessageType; + __le32 MessageLength; + __le32 RequestID; } rndis_keepalive_msg_type; typedef struct rndis_keepalive_cmplt_type { - u32 MessageType; - u32 MessageLength; - u32 RequestID; - u32 Status; + __le32 MessageType; + __le32 MessageLength; + __le32 RequestID; + __le32 Status; } rndis_keepalive_cmplt_type; struct rndis_packet_msg_type { - u32 MessageType; - u32 MessageLength; - u32 DataOffset; - u32 DataLength; - u32 OOBDataOffset; - u32 OOBDataLength; - u32 NumOOBDataElements; - u32 PerPacketInfoOffset; - u32 PerPacketInfoLength; - u32 VcHandle; - u32 Reserved; + __le32 MessageType; + __le32 MessageLength; + __le32 DataOffset; + __le32 DataLength; + __le32 OOBDataOffset; + __le32 OOBDataLength; + __le32 NumOOBDataElements; + __le32 PerPacketInfoOffset; + __le32 PerPacketInfoLength; + __le32 VcHandle; + __le32 Reserved; }; struct rndis_config_parameter { - u32 ParameterNameOffset; - u32 ParameterNameLength; - u32 ParameterType; - u32 ParameterValueOffset; - u32 ParameterValueLength; + __le32 ParameterNameOffset; + __le32 ParameterNameLength; + __le32 ParameterType; + __le32 ParameterValueOffset; + __le32 ParameterValueLength; }; /* implementation specific */ diff -Nru a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c --- a/drivers/usb/gadget/serial.c 2005-03-24 18:21:08 -08:00 +++ b/drivers/usb/gadget/serial.c 2005-03-24 18:21:08 -08:00 @@ -1461,6 +1461,9 @@ } else if (gadget_is_s3c2410(gadget)) { gs_device_desc.bcdDevice = __constant_cpu_to_le16(GS_VERSION_NUM|0x0012); + } else if (gadget_is_at91(gadget)) { + gs_device_desc.bcdDevice = + __constant_cpu_to_le16(GS_VERSION_NUM|0x0013); } else { printk(KERN_WARNING "gs_bind: controller '%s' not recognized\n", gadget->name); diff -Nru a/drivers/usb/gadget/usbstring.c b/drivers/usb/gadget/usbstring.c --- a/drivers/usb/gadget/usbstring.c 2005-03-24 18:21:08 -08:00 +++ b/drivers/usb/gadget/usbstring.c 2005-03-24 18:21:08 -08:00 @@ -20,7 +20,7 @@ #include -static int utf8_to_utf16le(const char *s, u16 *cp, unsigned len) +static int utf8_to_utf16le(const char *s, __le16 *cp, unsigned len) { int count = 0; u8 c; @@ -126,7 +126,7 @@ /* string descriptors have length, tag, then UTF16-LE text */ len = min ((size_t) 126, strlen (s->s)); memset (buf + 2, 0, 2 * len); /* zero all the bytes */ - len = utf8_to_utf16le(s->s, (u16 *)&buf[2], len); + len = utf8_to_utf16le(s->s, (__le16 *)&buf[2], len); if (len < 0) return -EINVAL; buf [0] = (len + 1) * 2; diff -Nru a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c --- a/drivers/usb/gadget/zero.c 2005-03-24 18:21:08 -08:00 +++ b/drivers/usb/gadget/zero.c 2005-03-24 18:21:08 -08:00 @@ -919,6 +919,9 @@ struct zero_dev *dev = get_gadget_data (gadget); struct usb_request *req = dev->req; int value = -EOPNOTSUPP; + u16 w_index = ctrl->wIndex; + u16 w_value = ctrl->wValue; + u16 w_length = ctrl->wLength; /* usually this stores reply data in the pre-allocated ep0 buffer, * but config change events will reconfigure hardware. @@ -929,17 +932,17 @@ case USB_REQ_GET_DESCRIPTOR: if (ctrl->bRequestType != USB_DIR_IN) goto unknown; - switch (ctrl->wValue >> 8) { + switch (w_value >> 8) { case USB_DT_DEVICE: - value = min (ctrl->wLength, (u16) sizeof device_desc); + value = min (w_length, (u16) sizeof device_desc); memcpy (req->buf, &device_desc, value); break; #ifdef CONFIG_USB_GADGET_DUALSPEED case USB_DT_DEVICE_QUALIFIER: if (!gadget->is_dualspeed) break; - value = min (ctrl->wLength, (u16) sizeof dev_qualifier); + value = min (w_length, (u16) sizeof dev_qualifier); memcpy (req->buf, &dev_qualifier, value); break; @@ -950,10 +953,10 @@ #endif /* CONFIG_USB_GADGET_DUALSPEED */ case USB_DT_CONFIG: value = config_buf (gadget, req->buf, - ctrl->wValue >> 8, - ctrl->wValue & 0xff); + w_value >> 8, + w_value & 0xff); if (value >= 0) - value = min (ctrl->wLength, (u16) value); + value = min (w_length, (u16) value); break; case USB_DT_STRING: @@ -963,9 +966,9 @@ * any UTF-8 characters */ value = usb_gadget_get_string (&stringtab, - ctrl->wValue & 0xff, req->buf); + w_value & 0xff, req->buf); if (value >= 0) - value = min (ctrl->wLength, (u16) value); + value = min (w_length, (u16) value); break; } break; @@ -981,14 +984,14 @@ else VDBG (dev, "HNP inactive\n"); spin_lock (&dev->lock); - value = zero_set_config (dev, ctrl->wValue, GFP_ATOMIC); + value = zero_set_config (dev, w_value, GFP_ATOMIC); spin_unlock (&dev->lock); break; case USB_REQ_GET_CONFIGURATION: if (ctrl->bRequestType != USB_DIR_IN) goto unknown; *(u8 *)req->buf = dev->config; - value = min (ctrl->wLength, (u16) 1); + value = min (w_length, (u16) 1); break; /* until we add altsetting support, or other interfaces, @@ -999,7 +1002,7 @@ if (ctrl->bRequestType != USB_RECIP_INTERFACE) goto unknown; spin_lock (&dev->lock); - if (dev->config && ctrl->wIndex == 0 && ctrl->wValue == 0) { + if (dev->config && w_index == 0 && w_value == 0) { u8 config = dev->config; /* resets interface configuration, forgets about @@ -1020,12 +1023,12 @@ goto unknown; if (!dev->config) break; - if (ctrl->wIndex != 0) { + if (w_index != 0) { value = -EDOM; break; } *(u8 *)req->buf = 0; - value = min (ctrl->wLength, (u16) 1); + value = min (w_length, (u16) 1); break; /* @@ -1036,23 +1039,23 @@ case 0x5b: /* control WRITE test -- fill the buffer */ if (ctrl->bRequestType != (USB_DIR_OUT|USB_TYPE_VENDOR)) goto unknown; - if (ctrl->wValue || ctrl->wIndex) + if (w_value || w_index) break; /* just read that many bytes into the buffer */ - if (ctrl->wLength > USB_BUFSIZ) + if (w_length > USB_BUFSIZ) break; - value = ctrl->wLength; + value = w_length; break; case 0x5c: /* control READ test -- return the buffer */ if (ctrl->bRequestType != (USB_DIR_IN|USB_TYPE_VENDOR)) goto unknown; - if (ctrl->wValue || ctrl->wIndex) + if (w_value || w_index) break; /* expect those bytes are still in the buffer; send back */ - if (ctrl->wLength > USB_BUFSIZ - || ctrl->wLength != req->length) + if (w_length > USB_BUFSIZ + || w_length != req->length) break; - value = ctrl->wLength; + value = w_length; break; default: @@ -1060,14 +1063,13 @@ VDBG (dev, "unknown control req%02x.%02x v%04x i%04x l%d\n", ctrl->bRequestType, ctrl->bRequest, - ctrl->wValue, ctrl->wIndex, ctrl->wLength); + w_value, w_index, w_length); } /* respond with data transfer before status phase? */ if (value >= 0) { req->length = value; - req->zero = value < ctrl->wLength - && (value % gadget->ep0->maxpacket) == 0; + req->zero = value < w_length; value = usb_ep_queue (gadget->ep0, req, GFP_ATOMIC); if (value < 0) { DBG (dev, "ep_queue --> %d\n", value); @@ -1193,6 +1195,8 @@ device_desc.bcdDevice = __constant_cpu_to_le16 (0x0211); } else if (gadget_is_s3c2410(gadget)) { device_desc.bcdDevice = __constant_cpu_to_le16 (0x0212); + } else if (gadget_is_at91(gadget)) { + device_desc.bcdDevice = __constant_cpu_to_le16 (0x0213); } else { /* gadget zero is so simple (for now, no altsettings) that * it SHOULD NOT have problems with bulk-capable hardware. diff -Nru a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c --- a/drivers/usb/host/ehci-hcd.c 2005-03-24 18:21:08 -08:00 +++ b/drivers/usb/host/ehci-hcd.c 2005-03-24 18:21:08 -08:00 @@ -212,7 +212,7 @@ command |= CMD_RESET; dbg_cmd (ehci, "reset", command); writel (command, &ehci->regs->command); - ehci_to_hcd(ehci)->state = USB_STATE_HALT; + ehci_to_hcd(ehci)->state = HC_STATE_HALT; ehci->next_statechange = jiffies; retval = handshake (&ehci->regs->command, CMD_RESET, 0, 250 * 1000); @@ -231,7 +231,7 @@ u32 temp; #ifdef DEBUG - if (!HCD_IS_RUNNING (ehci_to_hcd(ehci)->state)) + if (!HC_IS_RUNNING (ehci_to_hcd(ehci)->state)) BUG (); #endif @@ -240,7 +240,7 @@ temp &= STS_ASS | STS_PSS; if (handshake (&ehci->regs->status, STS_ASS | STS_PSS, temp, 16 * 125) != 0) { - ehci_to_hcd(ehci)->state = USB_STATE_HALT; + ehci_to_hcd(ehci)->state = HC_STATE_HALT; return; } @@ -252,7 +252,7 @@ /* hardware can take 16 microframes to turn off ... */ if (handshake (&ehci->regs->status, STS_ASS | STS_PSS, 0, 16 * 125) != 0) { - ehci_to_hcd(ehci)->state = USB_STATE_HALT; + ehci_to_hcd(ehci)->state = HC_STATE_HALT; return; } } @@ -615,7 +615,7 @@ register_reboot_notifier (&ehci->reboot_notifier); } - hcd->state = USB_STATE_RUNNING; + hcd->state = HC_STATE_RUNNING; writel (FLAG_CF, &ehci->regs->configured_flag); readl (&ehci->regs->command); /* unblock posted write */ @@ -635,8 +635,8 @@ * Before this point the HC was idle/ready. After, khubd * and device drivers may start it running. */ - if (first && hcd_register_root (udev, hcd) != 0) { - if (hcd->state == USB_STATE_RUNNING) + if (first && usb_hcd_register_root_hub (udev, hcd) != 0) { + if (hcd->state == HC_STATE_RUNNING) ehci_quiesce (ehci); ehci_reset (ehci); usb_put_dev (udev); @@ -672,7 +672,7 @@ del_timer_sync (&ehci->watchdog); spin_lock_irq(&ehci->lock); - if (HCD_IS_RUNNING (hcd->state)) + if (HC_IS_RUNNING (hcd->state)) ehci_quiesce (ehci); ehci_reset (ehci); @@ -839,7 +839,7 @@ * misplace IRQs, and should let us run completely without IRQs. * such lossage has been observed on both VT6202 and VT8235. */ - if (HCD_IS_RUNNING (ehci_to_hcd(ehci)->state) && + if (HC_IS_RUNNING (ehci_to_hcd(ehci)->state) && (ehci->async->qh_next.ptr != NULL || ehci->periodic_sched != 0)) timer_action (ehci, TIMER_IO_WATCHDOG); @@ -1000,7 +1000,7 @@ /* if we need to use IAA and it's busy, defer */ if (qh->qh_state == QH_STATE_LINKED && ehci->reclaim - && HCD_IS_RUNNING (ehci_to_hcd(ehci)->state)) { + && HC_IS_RUNNING (ehci_to_hcd(ehci)->state)) { struct ehci_qh *last; for (last = ehci->reclaim; @@ -1011,7 +1011,7 @@ last->reclaim = qh; /* bypass IAA if the hc can't care */ - } else if (!HCD_IS_RUNNING (ehci_to_hcd(ehci)->state) && ehci->reclaim) + } else if (!HC_IS_RUNNING (ehci_to_hcd(ehci)->state) && ehci->reclaim) end_unlink_async (ehci, NULL); /* something else might have unlinked the qh by now */ @@ -1059,7 +1059,7 @@ /* reschedule QH iff another request is queued */ if (!list_empty (&qh->qtd_list) - && HCD_IS_RUNNING (hcd->state)) { + && HC_IS_RUNNING (hcd->state)) { int status; status = qh_schedule (ehci, qh); @@ -1115,7 +1115,7 @@ goto idle_timeout; } - if (!HCD_IS_RUNNING (hcd->state)) + if (!HC_IS_RUNNING (hcd->state)) qh->qh_state = QH_STATE_IDLE; switch (qh->qh_state) { case QH_STATE_LINKED: diff -Nru a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c --- a/drivers/usb/host/ehci-hub.c 2005-03-24 18:21:08 -08:00 +++ b/drivers/usb/host/ehci-hub.c 2005-03-24 18:21:08 -08:00 @@ -42,9 +42,9 @@ spin_lock_irq (&ehci->lock); /* stop schedules, clean any completed work */ - if (HCD_IS_RUNNING(hcd->state)) { + if (HC_IS_RUNNING(hcd->state)) { ehci_quiesce (ehci); - hcd->state = USB_STATE_QUIESCING; + hcd->state = HC_STATE_QUIESCING; } ehci->command = readl (&ehci->regs->command); if (ehci->reclaim) @@ -73,7 +73,7 @@ /* turn off now-idle HC */ ehci_halt (ehci); - hcd->state = HCD_STATE_SUSPENDED; + hcd->state = HC_STATE_SUSPENDED; ehci->next_statechange = jiffies + msecs_to_jiffies(10); spin_unlock_irq (&ehci->lock); @@ -145,7 +145,7 @@ } ehci->next_statechange = jiffies + msecs_to_jiffies(5); - hcd->state = USB_STATE_RUNNING; + hcd->state = HC_STATE_RUNNING; /* Now we can safely re-enable irqs */ if (intr_enable) @@ -212,7 +212,7 @@ unsigned long flags; /* if !USB_SUSPEND, root hub timers won't get shut down ... */ - if (!HCD_IS_RUNNING(hcd->state)) + if (!HC_IS_RUNNING(hcd->state)) return 0; /* init status to no-changes */ diff -Nru a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c --- a/drivers/usb/host/ehci-q.c 2005-03-24 18:21:08 -08:00 +++ b/drivers/usb/host/ehci-q.c 2005-03-24 18:21:08 -08:00 @@ -338,23 +338,24 @@ if ((token & QTD_STS_HALT) != 0) { stopped = 1; - /* magic dummy for some short reads; qh won't advance */ + /* magic dummy for some short reads; qh won't advance. + * that silicon quirk can kick in with this dummy too. + */ } else if (IS_SHORT_READ (token) - && (qh->hw_alt_next & QTD_MASK) - == ehci->async->hw_alt_next) { + && !(qtd->hw_alt_next & EHCI_LIST_END)) { stopped = 1; goto halt; } /* stop scanning when we reach qtds the hc is using */ } else if (likely (!stopped - && HCD_IS_RUNNING (ehci_to_hcd(ehci)->state))) { + && HC_IS_RUNNING (ehci_to_hcd(ehci)->state))) { break; } else { stopped = 1; - if (unlikely (!HCD_IS_RUNNING (ehci_to_hcd(ehci)->state))) + if (unlikely (!HC_IS_RUNNING (ehci_to_hcd(ehci)->state))) urb->status = -ESHUTDOWN; /* ignore active urbs unless some previous qtd @@ -522,7 +523,7 @@ else buf = 0; - // FIXME this 'buf' check break some zlps... + /* for zero length DATA stages, STATUS is always IN */ if (!buf || is_input) token |= (1 /* "in" */ << 8); /* else it's already initted to "out" pid (0 << 8) */ @@ -780,7 +781,7 @@ (void) handshake (&ehci->regs->status, STS_ASS, 0, 150); cmd |= CMD_ASE | CMD_RUN; writel (cmd, &ehci->regs->command); - ehci_to_hcd(ehci)->state = USB_STATE_RUNNING; + ehci_to_hcd(ehci)->state = HC_STATE_RUNNING; /* posted write need not be known to HC yet ... */ } } @@ -959,7 +960,7 @@ qh_completions (ehci, qh, regs); if (!list_empty (&qh->qtd_list) - && HCD_IS_RUNNING (ehci_to_hcd(ehci)->state)) + && HC_IS_RUNNING (ehci_to_hcd(ehci)->state)) qh_link_async (ehci, qh); else { qh_put (qh); // refcount from async list @@ -967,7 +968,7 @@ /* it's not free to turn the async schedule on/off; leave it * active but idle for a while once it empties. */ - if (HCD_IS_RUNNING (ehci_to_hcd(ehci)->state) + if (HC_IS_RUNNING (ehci_to_hcd(ehci)->state) && ehci->async->qh_next.qh == NULL) timer_action (ehci, TIMER_ASYNC_OFF); } @@ -998,7 +999,7 @@ /* stop async schedule right now? */ if (unlikely (qh == ehci->async)) { /* can't get here without STS_ASS set */ - if (ehci_to_hcd(ehci)->state != USB_STATE_HALT) { + if (ehci_to_hcd(ehci)->state != HC_STATE_HALT) { writel (cmd & ~CMD_ASE, &ehci->regs->command); wmb (); // handshake later, if we need to @@ -1018,7 +1019,7 @@ prev->qh_next = qh->qh_next; wmb (); - if (unlikely (ehci_to_hcd(ehci)->state == USB_STATE_HALT)) { + if (unlikely (ehci_to_hcd(ehci)->state == HC_STATE_HALT)) { /* if (unlikely (qh->reclaim != 0)) * this will recurse, probably not much */ diff -Nru a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c --- a/drivers/usb/host/ehci-sched.c 2005-03-24 18:21:08 -08:00 +++ b/drivers/usb/host/ehci-sched.c 2005-03-24 18:21:08 -08:00 @@ -208,7 +208,7 @@ here = here.qh->qh_next; continue; case Q_TYPE_SITD: - if (same_tt (dev, here.itd->urb->dev)) { + if (same_tt (dev, here.sitd->urb->dev)) { u16 mask; mask = le32_to_cpu (here.sitd @@ -218,7 +218,7 @@ if (mask & uf_mask) break; } - type = Q_NEXT_TYPE (here.qh->hw_next); + type = Q_NEXT_TYPE (here.sitd->hw_next); here = here.sitd->sitd_next; continue; // case Q_TYPE_FSTN: @@ -249,14 +249,14 @@ */ status = handshake (&ehci->regs->status, STS_PSS, 0, 9 * 125); if (status != 0) { - ehci_to_hcd(ehci)->state = USB_STATE_HALT; + ehci_to_hcd(ehci)->state = HC_STATE_HALT; return status; } cmd = readl (&ehci->regs->command) | CMD_PSE; writel (cmd, &ehci->regs->command); /* posted write ... PSS happens later */ - ehci_to_hcd(ehci)->state = USB_STATE_RUNNING; + ehci_to_hcd(ehci)->state = HC_STATE_RUNNING; /* make sure ehci_work scans these */ ehci->next_uframe = readl (&ehci->regs->frame_index) @@ -274,7 +274,7 @@ */ status = handshake (&ehci->regs->status, STS_PSS, STS_PSS, 9 * 125); if (status != 0) { - ehci_to_hcd(ehci)->state = USB_STATE_HALT; + ehci_to_hcd(ehci)->state = HC_STATE_HALT; return status; } @@ -1180,7 +1180,10 @@ return status; ready: + /* report high speed start in uframes; full speed, in frames */ urb->start_frame = stream->next_uframe; + if (!stream->highspeed) + urb->start_frame >>= 3; return 0; } @@ -1504,18 +1507,17 @@ /* might need to cross a buffer page within a td */ packet->bufp = buf; - buf += length; - packet->buf1 = buf & ~0x0fff; + packet->buf1 = (buf + length) & ~0x0fff; if (packet->buf1 != (buf & ~(u64)0x0fff)) packet->cross = 1; /* OUT uses multiple start-splits */ if (stream->bEndpointAddress & USB_DIR_IN) continue; - length = 1 + (length / 188); - packet->buf1 |= length; + length = (length + 187) / 188; if (length > 1) /* BEGIN vs ALL */ - packet->buf1 |= 1 << 3; + length |= 1 << 3; + packet->buf1 |= length; } } @@ -1610,10 +1612,9 @@ sitd->hw_buf_hi [0] = cpu_to_le32 (bufp >> 32); sitd->hw_buf [1] = cpu_to_le32 (uf->buf1); - if (uf->cross) { + if (uf->cross) bufp += 4096; - sitd->hw_buf_hi [1] = cpu_to_le32 (bufp >> 32); - } + sitd->hw_buf_hi [1] = cpu_to_le32 (bufp >> 32); sitd->index = index; } @@ -1650,7 +1651,7 @@ ehci_to_hcd(ehci)->self.bandwidth_allocated += stream->bandwidth; ehci_vdbg (ehci, - "sched dev%s ep%d%s-iso [%d] %dms/%04x\n", + "sched devp %s ep%d%s-iso [%d] %dms/%04x\n", urb->dev->devpath, stream->bEndpointAddress & 0x0f, (stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out", (next_uframe >> 3) % ehci->periodic_size, @@ -1697,7 +1698,7 @@ /*-------------------------------------------------------------------------*/ #define SITD_ERRS (SITD_STS_ERR | SITD_STS_DBE | SITD_STS_BABBLE \ - | SITD_STS_XACT | SITD_STS_MMF | SITD_STS_STS) + | SITD_STS_XACT | SITD_STS_MMF) static unsigned sitd_complete ( @@ -1780,12 +1781,6 @@ unsigned long flags; struct ehci_iso_stream *stream; - // FIXME remove when csplits behave - if (usb_pipein(urb->pipe)) { - ehci_dbg (ehci, "no iso-IN split transactions yet\n"); - return -ENOMEM; - } - /* Get iso_stream head */ stream = iso_stream_find (ehci, urb); if (stream == NULL) { @@ -1864,7 +1859,7 @@ * Touches as few pages as possible: cache-friendly. */ now_uframe = ehci->next_uframe; - if (HCD_IS_RUNNING (ehci_to_hcd(ehci)->state)) + if (HC_IS_RUNNING (ehci_to_hcd(ehci)->state)) clock = readl (&ehci->regs->frame_index); else clock = now_uframe + mod - 1; @@ -1898,7 +1893,7 @@ union ehci_shadow temp; int live; - live = HCD_IS_RUNNING (ehci_to_hcd(ehci)->state); + live = HC_IS_RUNNING (ehci_to_hcd(ehci)->state); switch (type) { case Q_TYPE_QH: /* handle any completions */ @@ -1987,7 +1982,7 @@ if (now_uframe == clock) { unsigned now; - if (!HCD_IS_RUNNING (ehci_to_hcd(ehci)->state)) + if (!HC_IS_RUNNING (ehci_to_hcd(ehci)->state)) break; ehci->next_uframe = now_uframe; now = readl (&ehci->regs->frame_index) % mod; diff -Nru a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h --- a/drivers/usb/host/ehci.h 2005-03-24 18:21:08 -08:00 +++ b/drivers/usb/host/ehci.h 2005-03-24 18:21:08 -08:00 @@ -430,7 +430,7 @@ __le32 transaction; /* itd->hw_transaction[i] |= */ u8 cross; /* buf crosses pages */ /* for full speed OUT splits */ - u16 buf1; + u32 buf1; }; /* temporary schedule data for packets from iso urbs (both speeds) diff -Nru a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c --- a/drivers/usb/host/ohci-hcd.c 2005-03-24 18:21:08 -08:00 +++ b/drivers/usb/host/ohci-hcd.c 2005-03-24 18:21:08 -08:00 @@ -252,7 +252,7 @@ spin_lock_irqsave (&ohci->lock, flags); /* don't submit to a dead HC */ - if (!HCD_IS_RUNNING(hcd->state)) { + if (!HC_IS_RUNNING(hcd->state)) { retval = -ENODEV; goto fail; } @@ -320,7 +320,7 @@ #endif spin_lock_irqsave (&ohci->lock, flags); - if (HCD_IS_RUNNING(hcd->state)) { + if (HC_IS_RUNNING(hcd->state)) { urb_priv_t *urb_priv; /* Unless an IRQ completed the unlink while it was being @@ -367,7 +367,7 @@ rescan: spin_lock_irqsave (&ohci->lock, flags); - if (!HCD_IS_RUNNING (hcd->state)) { + if (!HC_IS_RUNNING (hcd->state)) { sanitize: ed->state = ED_IDLE; finish_unlinks (ohci, 0, NULL); @@ -620,7 +620,7 @@ ohci->hc_control &= OHCI_CTRL_RWC; ohci->hc_control |= OHCI_CONTROL_INIT | OHCI_USB_OPER; ohci_writel (ohci, ohci->hc_control, &ohci->regs->control); - ohci_to_hcd(ohci)->state = USB_STATE_RUNNING; + ohci_to_hcd(ohci)->state = HC_STATE_RUNNING; /* wake on ConnectStatusChange, matching external hubs */ ohci_writel (ohci, RH_HS_DRWE, &ohci->regs->roothub.status); @@ -656,7 +656,7 @@ // POTPGT delay is bits 24-31, in 2 ms units. mdelay ((temp >> 23) & 0x1fe); bus = &ohci_to_hcd(ohci)->self; - ohci_to_hcd(ohci)->state = USB_STATE_RUNNING; + ohci_to_hcd(ohci)->state = HC_STATE_RUNNING; ohci_dump (ohci, 1); @@ -675,7 +675,7 @@ } udev->speed = USB_SPEED_FULL; - if (hcd_register_root (udev, ohci_to_hcd(ohci)) != 0) { + if (usb_hcd_register_root_hub (udev, ohci_to_hcd(ohci)) != 0) { usb_put_dev (udev); disable (ohci); ohci->hc_control &= ~OHCI_CTRL_HCFS; @@ -732,12 +732,12 @@ } if (ints & OHCI_INTR_WDH) { - if (HCD_IS_RUNNING(hcd->state)) + if (HC_IS_RUNNING(hcd->state)) ohci_writel (ohci, OHCI_INTR_WDH, ®s->intrdisable); spin_lock (&ohci->lock); dl_done_list (ohci, ptregs); spin_unlock (&ohci->lock); - if (HCD_IS_RUNNING(hcd->state)) + if (HC_IS_RUNNING(hcd->state)) ohci_writel (ohci, OHCI_INTR_WDH, ®s->intrenable); } @@ -750,11 +750,11 @@ if (ohci->ed_rm_list) finish_unlinks (ohci, ohci_frame_no(ohci), ptregs); if ((ints & OHCI_INTR_SF) != 0 && !ohci->ed_rm_list - && HCD_IS_RUNNING(hcd->state)) + && HC_IS_RUNNING(hcd->state)) ohci_writel (ohci, OHCI_INTR_SF, ®s->intrdisable); spin_unlock (&ohci->lock); - if (HCD_IS_RUNNING(hcd->state)) { + if (HC_IS_RUNNING(hcd->state)) { ohci_writel (ohci, ints, ®s->intrstatus); ohci_writel (ohci, OHCI_INTR_MIE, ®s->intrenable); // flush those writes diff -Nru a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c --- a/drivers/usb/host/ohci-hub.c 2005-03-24 18:21:08 -08:00 +++ b/drivers/usb/host/ohci-hub.c 2005-03-24 18:21:08 -08:00 @@ -73,7 +73,7 @@ ohci_dbg (ohci, "suspend root hub\n"); /* First stop any processing */ - hcd->state = USB_STATE_QUIESCING; + hcd->state = HC_STATE_QUIESCING; if (ohci->hc_control & OHCI_SCHED_ENABLES) { int limit; @@ -119,7 +119,7 @@ done: if (status == 0) - hcd->state = HCD_STATE_SUSPENDED; + hcd->state = HC_STATE_SUSPENDED; spin_unlock_irqrestore (&ohci->lock, flags); return status; } @@ -147,7 +147,7 @@ if (ohci->hc_control & (OHCI_CTRL_IR | OHCI_SCHED_ENABLES)) { /* this can happen after suspend-to-disk */ - if (hcd->state == USB_STATE_RESUMING) { + if (hcd->state == HC_STATE_RESUMING) { ohci_dbg (ohci, "BIOS/SMM active, control %03x\n", ohci->hc_control); status = -EBUSY; @@ -198,7 +198,7 @@ } /* Some controllers (lucent) need extra-long delays */ - hcd->state = USB_STATE_RESUMING; + hcd->state = HC_STATE_RESUMING; mdelay (20 /* usb 11.5.1.10 */ + 15); temp = ohci_readl (ohci, &ohci->regs->control); @@ -272,7 +272,7 @@ (void) ohci_readl (ohci, &ohci->regs->control); } - hcd->state = USB_STATE_RUNNING; + hcd->state = HC_STATE_RUNNING; return 0; } @@ -313,7 +313,7 @@ * letting khubd or root hub timer see state changes. */ if ((ohci->hc_control & OHCI_CTRL_HCFS) != OHCI_USB_OPER - || !HCD_IS_RUNNING(hcd->state)) { + || !HC_IS_RUNNING(hcd->state)) { can_suspend = 0; goto done; } @@ -378,7 +378,7 @@ ) { ohci_vdbg (ohci, "autosuspend\n"); (void) ohci_hub_suspend (hcd); - hcd->state = USB_STATE_RUNNING; + hcd->state = HC_STATE_RUNNING; usb_unlock_device (hcd->self.root_hub); } #endif diff -Nru a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c --- a/drivers/usb/host/ohci-omap.c 2005-03-24 18:21:08 -08:00 +++ b/drivers/usb/host/ohci-omap.c 2005-03-24 18:21:08 -08:00 @@ -2,16 +2,14 @@ * OHCI HCD (Host Controller Driver) for USB. * * (C) Copyright 1999 Roman Weissgaerber - * (C) Copyright 2000-2004 David Brownell + * (C) Copyright 2000-2005 David Brownell * (C) Copyright 2002 Hewlett-Packard Company * * OMAP Bus Glue * - * Written by Christopher Hoover - * Based on fragments of previous driver by Russell King et al. - * - * Modified for OMAP from ohci-sa1111.c by Tony Lindgren + * Modified for OMAP by Tony Lindgren * Based on the 2.4 OMAP OHCI driver originally done by MontaVista Software Inc. + * and on ohci-sa1111.c by Christopher Hoover * * This file is licenced under the GPL. */ @@ -26,8 +24,20 @@ #include #include #include +#include + + +/* OMAP-1510 OHCI has its own MMU for DMA */ +#define OMAP1510_LB_MEMSIZE 32 /* Should be same as SDRAM size */ +#define OMAP1510_LB_CLOCK_DIV 0xfffec10c +#define OMAP1510_LB_MMU_CTL 0xfffec208 +#define OMAP1510_LB_MMU_LCK 0xfffec224 +#define OMAP1510_LB_MMU_LD_TLB 0xfffec228 +#define OMAP1510_LB_MMU_CAM_H 0xfffec22c +#define OMAP1510_LB_MMU_CAM_L 0xfffec230 +#define OMAP1510_LB_MMU_RAM_H 0xfffec234 +#define OMAP1510_LB_MMU_RAM_L 0xfffec238 -#include "ohci-omap.h" #ifndef CONFIG_ARCH_OMAP #error "This file is OMAP bus glue. CONFIG_OMAP must be defined." @@ -52,45 +62,17 @@ extern int usb_disabled(void); extern int ocpi_enable(void); -/* - * OHCI clock initialization for OMAP-1510 and 16xx - */ -static int omap_ohci_clock_power(int on) +static struct clk *usb_host_ck; + +static void omap_ohci_clock_power(int on) { if (on) { - /* for 1510, 48MHz DPLL is set up in usb init */ - - if (cpu_is_omap16xx()) { - /* Enable OHCI */ - omap_writel(omap_readl(ULPD_SOFT_REQ) | SOFT_USB_OTG_REQ, - ULPD_SOFT_REQ); - - /* USB host clock request if not using OTG */ - omap_writel(omap_readl(ULPD_SOFT_REQ) | SOFT_USB_REQ, - ULPD_SOFT_REQ); - - omap_writel(omap_readl(ULPD_STATUS_REQ) | USB_HOST_DPLL_REQ, - ULPD_STATUS_REQ); - } - - /* Enable 48MHz clock to USB */ - omap_writel(omap_readl(ULPD_CLOCK_CTRL) | USB_MCLK_EN, - ULPD_CLOCK_CTRL); - - omap_writel(omap_readl(ARM_IDLECT2) | (1 << EN_LBFREECK) | (1 << EN_LBCK), - ARM_IDLECT2); - - omap_writel(omap_readl(MOD_CONF_CTRL_0) | USB_HOST_HHC_UHOST_EN, - MOD_CONF_CTRL_0); + clk_enable(usb_host_ck); + /* guesstimate for T5 == 1x 32K clock + APLL lock time */ + udelay(100); } else { - /* Disable 48MHz clock to USB */ - omap_writel(omap_readl(ULPD_CLOCK_CTRL) & ~USB_MCLK_EN, - ULPD_CLOCK_CTRL); - - /* FIXME: The DPLL stays on for now */ + clk_disable(usb_host_ck); } - - return 0; } /* @@ -204,7 +186,7 @@ /* boards can use OTG transceivers in non-OTG modes */ need_transceiver = need_transceiver - || machine_is_omap_h2(); + || machine_is_omap_h2() || machine_is_omap_h3(); if (cpu_is_omap16xx()) ocpi_enable(); @@ -261,7 +243,7 @@ omap_cfg_reg(W4_USB_HIGHZ); } ohci_writel(ohci, rh, &ohci->regs->roothub.a); - // distrust_firmware = 0; + distrust_firmware = 0; } /* FIXME khubd hub requests should manage power switching */ @@ -278,21 +260,14 @@ static void omap_stop_hc(struct platform_device *pdev) { dev_dbg(&pdev->dev, "stopping USB Controller\n"); - - /* - * FIXME: Put the USB host controller into reset. - */ - - /* - * FIXME: Stop the USB clock. - */ - //omap_disable_device(dev); - + omap_ohci_clock_power(0); } /*-------------------------------------------------------------------------*/ +void usb_hcd_omap_remove (struct usb_hcd *, struct platform_device *); + /* configure so an HC device and id are always provided */ /* always called with process context; sleeping is OK */ @@ -309,7 +284,7 @@ struct platform_device *pdev) { int retval; - struct usb_hcd *hcd; + struct usb_hcd *hcd = 0; struct ohci_hcd *ohci; if (pdev->num_resources != 2) { @@ -319,14 +294,20 @@ } if (pdev->resource[0].flags != IORESOURCE_MEM - || pdev->resource[1].flags != IORESOURCE_IRQ) { + || pdev->resource[1].flags != IORESOURCE_IRQ) { printk(KERN_ERR "hcd probe: invalid resource type\n"); return -ENODEV; } + usb_host_ck = clk_get(0, "usb_hhc_ck"); + if (IS_ERR(usb_host_ck)) + return PTR_ERR(usb_host_ck); + hcd = usb_create_hcd (driver, &pdev->dev, pdev->dev.bus_id); - if (!hcd) - return -ENOMEM; + if (!hcd) { + retval = -ENOMEM; + goto err0; + } hcd->rsrc_start = pdev->resource[0].start; hcd->rsrc_len = pdev->resource[0].end - pdev->resource[0].start + 1; @@ -336,9 +317,7 @@ goto err1; } - /* FIXME: Cast to pointer from integer of different size! - * Needs ioremap */ - hcd->regs = (void __iomem *) (u32) hcd->rsrc_start; + hcd->regs = (void __iomem *) (int) IO_ADDRESS(hcd->rsrc_start); ohci = hcd_to_ohci(hcd); ohci_hcd_init(ohci); @@ -347,20 +326,21 @@ if (retval < 0) goto err2; - retval = usb_add_hcd(hcd, pdev->resource[1].start, SA_INTERRUPT); + retval = usb_add_hcd(hcd, platform_get_irq(pdev, 0), SA_INTERRUPT); if (retval == 0) return retval; omap_stop_hc(pdev); - err2: +err2: release_mem_region(hcd->rsrc_start, hcd->rsrc_len); - err1: +err1: usb_put_hcd(hcd); +err0: + clk_put(usb_host_ck); return retval; } -/* may be called without controller electrically present */ /* may be called with controller, bus, and devices active */ /** @@ -381,6 +361,7 @@ omap_stop_hc(pdev); release_mem_region(hcd->rsrc_start, hcd->rsrc_len); usb_put_hcd(hcd); + clk_put(usb_host_ck); } /*-------------------------------------------------------------------------*/ @@ -397,7 +378,7 @@ writel(OHCI_CTRL_RWC, &ohci->regs->control); if ((ret = ohci_run (ohci)) < 0) { - err ("can't start %s", hcd->self.bus_name); + dev_err(hcd->self.controller, "can't start\n"); ohci_stop (hcd); return ret; } @@ -466,13 +447,14 @@ (void) otg_set_host(ohci->transceiver, 0); put_device(ohci->transceiver->dev); } + dev_set_drvdata(dev, NULL); return 0; } /*-------------------------------------------------------------------------*/ -#if defined(CONFIG_USB_SUSPEND) || defined(CONFIG_PM) +#ifdef CONFIG_PM /* states match PCI usage, always suspending the root hub except that * 4 ~= D3cold (ACPI D3) with clock off (resume sees reset). @@ -493,13 +475,12 @@ status = ohci_hub_suspend(ohci_to_hcd(ohci)); if (status == 0) { if (state >= 4) { - /* power off + reset */ - OTG_SYSCON_2_REG &= ~UHOST_EN; + omap_ohci_clock_power(0); ohci_to_hcd(ohci)->self.root_hub->state = USB_STATE_SUSPENDED; state = 4; } - ohci_to_hcd(ohci)->state = HCD_STATE_SUSPENDED; + ohci_to_hcd(ohci)->state = HC_STATE_SUSPENDED; dev->power.power_state = state; } up(&ohci_to_hcd(ohci)->self.root_hub->serialize); @@ -521,7 +502,7 @@ if (time_before(jiffies, ohci->next_statechange)) msleep(5); ohci->next_statechange = jiffies; - OTG_SYSCON_2_REG |= UHOST_EN; + omap_ohci_clock_power(1); /* FALLTHROUGH */ default: dev_dbg(dev, "resume from %d\n", dev->power.power_state); @@ -552,7 +533,7 @@ .bus = &platform_bus_type, .probe = ohci_hcd_omap_drv_probe, .remove = ohci_hcd_omap_drv_remove, -#if defined(CONFIG_USB_SUSPEND) || defined(CONFIG_PM) +#ifdef CONFIG_PM .suspend = ohci_omap_suspend, .resume = ohci_omap_resume, #endif diff -Nru a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c --- a/drivers/usb/host/ohci-q.c 2005-03-24 18:21:08 -08:00 +++ b/drivers/usb/host/ohci-q.c 2005-03-24 18:21:08 -08:00 @@ -172,7 +172,7 @@ { int branch; - if (ohci_to_hcd(ohci)->state == USB_STATE_QUIESCING) + if (ohci_to_hcd(ohci)->state == HC_STATE_QUIESCING) return -EAGAIN; ed->state = ED_OPER; @@ -663,7 +663,7 @@ /* NOTE: mishandles transfers >8K, some >4K */ td_fill (ohci, info, data, data_len, urb, cnt++); } - info = is_out + info = (is_out || data_len == 0) ? TD_CC | TD_DP_IN | TD_T_DATA1 : TD_CC | TD_DP_OUT | TD_T_DATA1; td_fill (ohci, info, data, 0, urb, cnt++); @@ -923,7 +923,7 @@ /* only take off EDs that the HC isn't using, accounting for * frame counter wraps and EDs with partially retired TDs */ - if (likely (regs && HCD_IS_RUNNING(ohci_to_hcd(ohci)->state))) { + if (likely (regs && HC_IS_RUNNING(ohci_to_hcd(ohci)->state))) { if (tick_before (tick, ed->tick)) { skip_ed: last = &ed->ed_next; @@ -1005,7 +1005,7 @@ /* but if there's work queued, reschedule */ if (!list_empty (&ed->td_list)) { - if (HCD_IS_RUNNING(ohci_to_hcd(ohci)->state)) + if (HC_IS_RUNNING(ohci_to_hcd(ohci)->state)) ed_schedule (ohci, ed); } @@ -1014,8 +1014,8 @@ } /* maybe reenable control and bulk lists */ - if (HCD_IS_RUNNING(ohci_to_hcd(ohci)->state) - && ohci_to_hcd(ohci)->state != USB_STATE_QUIESCING + if (HC_IS_RUNNING(ohci_to_hcd(ohci)->state) + && ohci_to_hcd(ohci)->state != HC_STATE_QUIESCING && !ohci->ed_rm_list) { u32 command = 0, control = 0; diff -Nru a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h --- a/drivers/usb/host/ohci.h 2005-03-24 18:21:08 -08:00 +++ b/drivers/usb/host/ohci.h 2005-03-24 18:21:08 -08:00 @@ -594,7 +594,7 @@ static inline void disable (struct ohci_hcd *ohci) { - ohci_to_hcd(ohci)->state = USB_STATE_HALT; + ohci_to_hcd(ohci)->state = HC_STATE_HALT; } #define FI 0x2edf /* 12000 bits per frame (-1) */ diff -Nru a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c --- a/drivers/usb/host/sl811-hcd.c 2005-03-24 18:21:08 -08:00 +++ b/drivers/usb/host/sl811-hcd.c 2005-03-24 18:21:08 -08:00 @@ -105,7 +105,7 @@ } else { sl811->port1 = 0; sl811->irq_enable = 0; - hcd->state = USB_STATE_HALT; + hcd->state = HC_STATE_HALT; hcd->self.controller->power.power_state = PM_SUSPEND_DISK; } sl811->ctrl1 = 0; @@ -834,7 +834,7 @@ /* don't submit to a dead or disabled port */ if (!(sl811->port1 & (1 << USB_PORT_FEAT_ENABLE)) - || !HCD_IS_RUNNING(hcd->state)) { + || !HC_IS_RUNNING(hcd->state)) { retval = -ENODEV; goto fail; } @@ -1562,12 +1562,12 @@ return -ENOMEM; udev->speed = USB_SPEED_FULL; - hcd->state = USB_STATE_RUNNING; + hcd->state = HC_STATE_RUNNING; if (sl811->board) hcd->can_wakeup = sl811->board->can_wakeup; - if (hcd_register_root(udev, hcd) != 0) { + if (usb_hcd_register_root_hub(udev, hcd) != 0) { usb_put_dev(udev); sl811h_stop(hcd); return -ENODEV; diff -Nru a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c --- a/drivers/usb/host/uhci-debug.c 2005-03-24 18:21:08 -08:00 +++ b/drivers/usb/host/uhci-debug.c 2005-03-24 18:21:08 -08:00 @@ -406,7 +406,7 @@ struct uhci_td *td; struct list_head *tmp, *head; - spin_lock_irqsave(&uhci->schedule_lock, flags); + spin_lock_irqsave(&uhci->lock, flags); out += sprintf(out, "HC status\n"); out += uhci_show_status(uhci, out, len - (out - buf)); @@ -492,7 +492,7 @@ if (debug > 2) out += uhci_show_lists(uhci, out, len - (out - buf)); - spin_unlock_irqrestore(&uhci->schedule_lock, flags); + spin_unlock_irqrestore(&uhci->lock, flags); return out - buf; } diff -Nru a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c --- a/drivers/usb/host/uhci-hcd.c 2005-03-24 18:21:08 -08:00 +++ b/drivers/usb/host/uhci-hcd.c 2005-03-24 18:21:08 -08:00 @@ -89,7 +89,7 @@ static kmem_cache_t *uhci_up_cachep; /* urb_priv */ -static unsigned int uhci_get_current_frame_number(struct uhci_hcd *uhci); +static void uhci_get_current_frame_number(struct uhci_hcd *uhci); static void hc_state_transitions(struct uhci_hcd *uhci); /* If a transfer is still active after this much time, turn off FSBR */ @@ -113,15 +113,9 @@ struct uhci_hcd *uhci = hcd_to_uhci(hcd); struct urb_priv *up; unsigned long flags; - int called_uhci_finish_completion = 0; - spin_lock_irqsave(&uhci->schedule_lock, flags); - if (!list_empty(&uhci->urb_remove_list) && - uhci_get_current_frame_number(uhci) != uhci->urb_remove_age) { - uhci_remove_pending_urbps(uhci); - uhci_finish_completion(hcd, NULL); - called_uhci_finish_completion = 1; - } + spin_lock_irqsave(&uhci->lock, flags); + uhci_scan_schedule(uhci, NULL); list_for_each_entry(up, &uhci->urb_list, urb_list) { struct urb *u = up->urb; @@ -134,11 +128,6 @@ spin_unlock(&u->lock); } - spin_unlock_irqrestore(&uhci->schedule_lock, flags); - - /* Wake up anyone waiting for an URB to complete */ - if (called_uhci_finish_completion) - wake_up_all(&uhci->waitqh); /* Really disable FSBR */ if (!uhci->fsbr && uhci->fsbrtimeout && time_after_eq(jiffies, uhci->fsbrtimeout)) { @@ -149,9 +138,10 @@ /* Poll for and perform state transitions */ hc_state_transitions(uhci); if (unlikely(uhci->suspended_ports && uhci->state != UHCI_SUSPENDED)) - uhci_check_resume(uhci); + uhci_check_ports(uhci); init_stall_timer(hcd); + spin_unlock_irqrestore(&uhci->lock, flags); } static int init_stall_timer(struct usb_hcd *hcd) @@ -172,8 +162,6 @@ struct uhci_hcd *uhci = hcd_to_uhci(hcd); unsigned long io_addr = uhci->io_addr; unsigned short status; - struct urb_priv *urbp, *tmp; - unsigned int age; /* * Read the interrupt status, and write it back to clear the @@ -202,37 +190,9 @@ if (status & USBSTS_RD) uhci->resume_detect = 1; - spin_lock(&uhci->schedule_lock); - - age = uhci_get_current_frame_number(uhci); - if (age != uhci->qh_remove_age) - uhci_free_pending_qhs(uhci); - if (age != uhci->td_remove_age) - uhci_free_pending_tds(uhci); - if (age != uhci->urb_remove_age) - uhci_remove_pending_urbps(uhci); - - if (list_empty(&uhci->urb_remove_list) && - list_empty(&uhci->td_remove_list) && - list_empty(&uhci->qh_remove_list)) - uhci_clear_next_interrupt(uhci); - else - uhci_set_next_interrupt(uhci); - - /* Walk the list of pending URBs to see which ones completed - * (must be _safe because uhci_transfer_result() dequeues URBs) */ - list_for_each_entry_safe(urbp, tmp, &uhci->urb_list, urb_list) { - struct urb *urb = urbp->urb; - - /* Checks the status and does all of the magic necessary */ - uhci_transfer_result(uhci, urb); - } - uhci_finish_completion(hcd, regs); - - spin_unlock(&uhci->schedule_lock); - - /* Wake up anyone waiting for an URB to complete */ - wake_up_all(&uhci->waitqh); + spin_lock(&uhci->lock); + uhci_scan_schedule(uhci, regs); + spin_unlock(&uhci->lock); return IRQ_HANDLED; } @@ -256,6 +216,7 @@ /* Another 10ms delay */ msleep(10); uhci->resume_detect = 0; + uhci->is_stopped = UHCI_IS_STOPPED; } static void suspend_hc(struct uhci_hcd *uhci) @@ -266,6 +227,12 @@ uhci->state = UHCI_SUSPENDED; uhci->resume_detect = 0; outw(USBCMD_EGSM, io_addr + USBCMD); + + /* FIXME: Wait for the controller to actually stop */ + uhci_get_current_frame_number(uhci); + uhci->is_stopped = UHCI_IS_STOPPED; + + uhci_scan_schedule(uhci, NULL); } static void wakeup_hc(struct uhci_hcd *uhci) @@ -280,6 +247,7 @@ outw(USBCMD_FGR | USBCMD_EGSM, io_addr + USBCMD); uhci->state = UHCI_RESUMING_1; uhci->state_end = jiffies + msecs_to_jiffies(20); + uhci->is_stopped = 0; break; case UHCI_RESUMING_1: /* End global resume */ @@ -386,11 +354,13 @@ } /* - * returns the current frame number for a USB bus/controller. + * Store the current frame number in uhci->frame_number if the controller + * is runnning */ -static unsigned int uhci_get_current_frame_number(struct uhci_hcd *uhci) +static void uhci_get_current_frame_number(struct uhci_hcd *uhci) { - return inw(uhci->io_addr + USBFRNUM); + if (!uhci->is_stopped) + uhci->frame_number = inw(uhci->io_addr + USBFRNUM); } static int start_hc(struct uhci_hcd *uhci) @@ -413,6 +383,9 @@ msleep(1); } + /* Mark controller as running before we enable interrupts */ + uhci_to_hcd(uhci)->state = HC_STATE_RUNNING; + /* Turn on PIRQ and all interrupts */ pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, USBLEGSUP_DEFAULT); @@ -427,8 +400,8 @@ uhci->state = UHCI_RUNNING_GRACE; uhci->state_end = jiffies + HZ; outw(USBCMD_RS | USBCMD_CF | USBCMD_MAXP, io_addr + USBCMD); + uhci->is_stopped = 0; - uhci_to_hcd(uhci)->state = USB_STATE_RUNNING; return 0; } @@ -524,7 +497,7 @@ uhci->fsbr = 0; uhci->fsbrtimeout = 0; - spin_lock_init(&uhci->schedule_lock); + spin_lock_init(&uhci->lock); INIT_LIST_HEAD(&uhci->qh_remove_list); INIT_LIST_HEAD(&uhci->td_remove_list); @@ -678,7 +651,7 @@ udev->speed = USB_SPEED_FULL; - if (hcd_register_root(udev, hcd) != 0) { + if (usb_hcd_register_root_hub(udev, hcd) != 0) { dev_err(uhci_dev(uhci), "unable to start root hub\n"); retval = -ENOMEM; goto err_start_root_hub; @@ -733,26 +706,11 @@ struct uhci_hcd *uhci = hcd_to_uhci(hcd); del_timer_sync(&uhci->stall_timer); - - /* - * At this point, we're guaranteed that no new connects can be made - * to this bus since there are no more parents - */ - reset_hc(uhci); - spin_lock_irq(&uhci->schedule_lock); - uhci_free_pending_qhs(uhci); - uhci_free_pending_tds(uhci); - uhci_remove_pending_urbps(uhci); - uhci_finish_completion(hcd, NULL); - - uhci_free_pending_qhs(uhci); - uhci_free_pending_tds(uhci); - spin_unlock_irq(&uhci->schedule_lock); - - /* Wake up anyone waiting for an URB to complete */ - wake_up_all(&uhci->waitqh); + spin_lock_irq(&uhci->lock); + uhci_scan_schedule(uhci, NULL); + spin_unlock_irq(&uhci->lock); release_uhci(uhci); } @@ -762,13 +720,19 @@ { struct uhci_hcd *uhci = hcd_to_uhci(hcd); + spin_lock_irq(&uhci->lock); + /* Don't try to suspend broken motherboards, reset instead */ - if (suspend_allowed(uhci)) { + if (suspend_allowed(uhci)) suspend_hc(uhci); - uhci->saved_framenumber = - inw(uhci->io_addr + USBFRNUM) & 0x3ff; - } else + else { + spin_unlock_irq(&uhci->lock); reset_hc(uhci); + spin_lock_irq(&uhci->lock); + uhci_scan_schedule(uhci, NULL); + } + + spin_unlock_irq(&uhci->lock); return 0; } @@ -779,6 +743,8 @@ pci_set_master(to_pci_dev(uhci_dev(uhci))); + spin_lock_irq(&uhci->lock); + if (uhci->state == UHCI_SUSPENDED) { /* @@ -789,7 +755,7 @@ */ pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, 0); - outw(uhci->saved_framenumber, uhci->io_addr + USBFRNUM); + outw(uhci->frame_number, uhci->io_addr + USBFRNUM); outl(uhci->fl->dma_handle, uhci->io_addr + USBFLBASEADD); outw(USBINTR_TIMEOUT | USBINTR_RESUME | USBINTR_IOC | USBINTR_SP, uhci->io_addr + USBINTR); @@ -797,11 +763,15 @@ pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, USBLEGSUP_DEFAULT); } else { + spin_unlock_irq(&uhci->lock); reset_hc(uhci); if ((rc = start_hc(uhci)) != 0) return rc; + spin_lock_irq(&uhci->lock); } - hcd->state = USB_STATE_RUNNING; + hcd->state = HC_STATE_RUNNING; + + spin_unlock_irq(&uhci->lock); return 0; } #endif @@ -817,7 +787,17 @@ static int uhci_hcd_get_frame_number(struct usb_hcd *hcd) { - return uhci_get_current_frame_number(hcd_to_uhci(hcd)); + struct uhci_hcd *uhci = hcd_to_uhci(hcd); + int frame_number; + unsigned long flags; + + /* Minimize latency by avoiding the spinlock */ + local_irq_save(flags); + rmb(); + frame_number = (uhci->is_stopped ? uhci->frame_number : + inw(uhci->io_addr + USBFRNUM)); + local_irq_restore(flags); + return frame_number; } static const char hcd_name[] = "uhci_hcd"; diff -Nru a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h --- a/drivers/usb/host/uhci-hcd.h 2005-03-24 18:21:08 -08:00 +++ b/drivers/usb/host/uhci-hcd.h 2005-03-24 18:21:08 -08:00 @@ -358,39 +358,44 @@ struct uhci_td *term_td; /* Terminating TD, see UHCI bug */ struct uhci_qh *skelqh[UHCI_NUM_SKELQH]; /* Skeleton QH's */ - spinlock_t schedule_lock; - struct uhci_frame_list *fl; /* P: uhci->schedule_lock */ + spinlock_t lock; + struct uhci_frame_list *fl; /* P: uhci->lock */ int fsbr; /* Full-speed bandwidth reclamation */ unsigned long fsbrtimeout; /* FSBR delay */ enum uhci_state state; /* FIXME: needs a spinlock */ unsigned long state_end; /* Time of next transition */ - int resume_detect; /* Need a Global Resume */ - unsigned int saved_framenumber; /* Save during PM suspend */ + unsigned int frame_number; /* As of last check */ + unsigned int is_stopped; +#define UHCI_IS_STOPPED 9999 /* Larger than a frame # */ + + unsigned int scan_in_progress:1; /* Schedule scan is running */ + unsigned int need_rescan:1; /* Redo the schedule scan */ + unsigned int resume_detect:1; /* Need a Global Resume */ - /* Support for port suspend/resume */ + /* Support for port suspend/resume/reset */ 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 */ + unsigned long ports_timeout; /* Time to stop signalling */ /* Main list of URB's currently controlled by this HC */ - struct list_head urb_list; /* P: uhci->schedule_lock */ + struct list_head urb_list; /* P: uhci->lock */ /* List of QH's that are done, but waiting to be unlinked (race) */ - struct list_head qh_remove_list; /* P: uhci->schedule_lock */ + struct list_head qh_remove_list; /* P: uhci->lock */ unsigned int qh_remove_age; /* Age in frames */ /* List of TD's that are done, but waiting to be freed (race) */ - struct list_head td_remove_list; /* P: uhci->schedule_lock */ + struct list_head td_remove_list; /* P: uhci->lock */ unsigned int td_remove_age; /* Age in frames */ /* List of asynchronously unlinked URB's */ - struct list_head urb_remove_list; /* P: uhci->schedule_lock */ + struct list_head urb_remove_list; /* P: uhci->lock */ unsigned int urb_remove_age; /* Age in frames */ /* List of URB's awaiting completion callback */ - struct list_head complete_list; /* P: uhci->schedule_lock */ + struct list_head complete_list; /* P: uhci->lock */ int rh_numports; @@ -436,13 +441,13 @@ * Locking in uhci.c * * Almost everything relating to the hardware schedule and processing - * of URBs is protected by uhci->schedule_lock. urb->status is protected - * by urb->lock; that's the one exception. + * of URBs is protected by uhci->lock. urb->status is protected by + * urb->lock; that's the one exception. * - * To prevent deadlocks, never lock uhci->schedule_lock while holding - * urb->lock. The safe order of locking is: + * To prevent deadlocks, never lock uhci->lock while holding urb->lock. + * The safe order of locking is: * - * #1 uhci->schedule_lock + * #1 uhci->lock * #2 urb->lock */ diff -Nru a/drivers/usb/host/uhci-hub.c b/drivers/usb/host/uhci-hub.c --- a/drivers/usb/host/uhci-hub.c 2005-03-24 18:21:08 -08:00 +++ b/drivers/usb/host/uhci-hub.c 2005-03-24 18:21:08 -08:00 @@ -66,7 +66,6 @@ /* 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_finish_suspend(struct uhci_hcd *uhci, int port, unsigned long port_addr) @@ -87,22 +86,37 @@ } } -static void uhci_check_resume(struct uhci_hcd *uhci) +static void uhci_check_ports(struct uhci_hcd *uhci) { unsigned int port; unsigned long 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)) { + status = inw(port_addr); + if (unlikely(status & USBPORTSC_PR)) { + if (time_after_eq(jiffies, uhci->ports_timeout)) { + CLR_RH_PORTSTAT(USBPORTSC_PR); + udelay(10); + + /* If the port was enabled before, turning + * reset on caused a port enable change. + * Turning reset off causes a port connect + * status change. Clear these changes. */ + CLR_RH_PORTSTAT(USBPORTSC_CSC | USBPORTSC_PEC); + SET_RH_PORTSTAT(USBPORTSC_PE); + } + } + if (unlikely(status & USBPORTSC_RD)) { if (!test_bit(port, &uhci->resuming_ports)) { /* Port received a wakeup request */ set_bit(port, &uhci->resuming_ports); - uhci->resume_timeout = jiffies + + uhci->ports_timeout = jiffies + msecs_to_jiffies(20); } else if (time_after_eq(jiffies, - uhci->resume_timeout)) { + uhci->ports_timeout)) { uhci_finish_suspend(uhci, port, port_addr); } } @@ -118,7 +132,9 @@ unsigned int port = wIndex - 1; unsigned long port_addr = uhci->io_addr + USBPORTSC1 + 2 * port; u16 wPortChange, wPortStatus; + unsigned long flags; + spin_lock_irqsave(&uhci->lock, flags); switch (typeReq) { case GetHubStatus: @@ -128,9 +144,7 @@ if (port >= uhci->rh_numports) goto err; - if (uhci->resuming_ports) - uhci_check_resume(uhci); - + uhci_check_ports(uhci); status = inw(port_addr); /* Intel controllers report the OverCurrent bit active on. @@ -203,15 +217,12 @@ OK(0); case USB_PORT_FEAT_RESET: SET_RH_PORTSTAT(USBPORTSC_PR); - mdelay(50); /* USB v1.1 7.1.7.3 */ - CLR_RH_PORTSTAT(USBPORTSC_PR); - udelay(10); /* Reset terminates Resume signalling */ uhci_finish_suspend(uhci, port, port_addr); - SET_RH_PORTSTAT(USBPORTSC_PE); - mdelay(10); - CLR_RH_PORTSTAT(USBPORTSC_PEC|USBPORTSC_CSC); + + /* USB v2.0 7.1.7.5 */ + uhci->ports_timeout = jiffies + msecs_to_jiffies(50); OK(0); case USB_PORT_FEAT_POWER: /* UHCI has no power switching */ @@ -238,8 +249,6 @@ if (test_bit(port, &uhci->suspended_ports) && !test_and_set_bit(port, &uhci->resuming_ports)) { - uhci->resume_timeout = jiffies + - msecs_to_jiffies(20); SET_RH_PORTSTAT(USBPORTSC_RD); /* The controller won't allow RD to be set @@ -249,6 +258,10 @@ if (!(inw(port_addr) & USBPORTSC_RD)) uhci_finish_suspend(uhci, port, port_addr); + else + /* USB v2.0 7.1.7.7 */ + uhci->ports_timeout = jiffies + + msecs_to_jiffies(20); } OK(0); case USB_PORT_FEAT_C_SUSPEND: @@ -280,6 +293,7 @@ err: retval = -EPIPE; } + spin_unlock_irqrestore(&uhci->lock, flags); return retval; } diff -Nru a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c --- a/drivers/usb/host/uhci-q.c 2005-03-24 18:21:08 -08:00 +++ b/drivers/usb/host/uhci-q.c 2005-03-24 18:21:08 -08:00 @@ -264,7 +264,6 @@ { struct uhci_qh *pqh; __le32 newlink; - unsigned int age; if (!qh) return; @@ -310,10 +309,10 @@ list_del_init(&qh->urbp->queue_list); qh->urbp = NULL; - age = uhci_get_current_frame_number(uhci); - if (age != uhci->qh_remove_age) { + uhci_get_current_frame_number(uhci); + if (uhci->frame_number + uhci->is_stopped != uhci->qh_remove_age) { uhci_free_pending_qhs(uhci); - uhci->qh_remove_age = age; + uhci->qh_remove_age = uhci->frame_number; } /* Check to see if the remove list is empty. Set the IOC bit */ @@ -492,7 +491,6 @@ { struct uhci_td *td, *tmp; struct urb_priv *urbp; - unsigned int age; urbp = (struct urb_priv *)urb->hcpriv; if (!urbp) @@ -502,10 +500,10 @@ dev_warn(uhci_dev(uhci), "urb %p still on uhci->urb_list " "or uhci->remove_list!\n", urb); - age = uhci_get_current_frame_number(uhci); - if (age != uhci->td_remove_age) { + uhci_get_current_frame_number(uhci); + if (uhci->frame_number + uhci->is_stopped != uhci->td_remove_age) { uhci_free_pending_tds(uhci); - uhci->td_remove_age = age; + uhci->td_remove_age = uhci->frame_number; } /* Check to see if the remove list is empty. Set the IOC bit */ @@ -1063,11 +1061,11 @@ limits = isochronous_find_limits(uhci, urb, &start, &end); if (urb->transfer_flags & URB_ISO_ASAP) { - if (limits) - urb->start_frame = - (uhci_get_current_frame_number(uhci) + - 10) & (UHCI_NUMFRAMES - 1); - else + if (limits) { + uhci_get_current_frame_number(uhci); + urb->start_frame = (uhci->frame_number + 10) + & (UHCI_NUMFRAMES - 1); + } else urb->start_frame = end; } else { urb->start_frame &= (UHCI_NUMFRAMES - 1); @@ -1184,7 +1182,7 @@ struct urb *eurb; int bustime; - spin_lock_irqsave(&uhci->schedule_lock, flags); + spin_lock_irqsave(&uhci->lock, flags); ret = urb->status; if (ret != -EINPROGRESS) /* URB already unlinked! */ @@ -1242,7 +1240,7 @@ ret = 0; out: - spin_unlock_irqrestore(&uhci->schedule_lock, flags); + spin_unlock_irqrestore(&uhci->lock, flags); return ret; } @@ -1371,9 +1369,8 @@ struct uhci_hcd *uhci = hcd_to_uhci(hcd); unsigned long flags; struct urb_priv *urbp; - unsigned int age; - spin_lock_irqsave(&uhci->schedule_lock, flags); + spin_lock_irqsave(&uhci->lock, flags); urbp = urb->hcpriv; if (!urbp) /* URB was never linked! */ goto done; @@ -1381,10 +1378,10 @@ uhci_unlink_generic(uhci, urb); - age = uhci_get_current_frame_number(uhci); - if (age != uhci->urb_remove_age) { + uhci_get_current_frame_number(uhci); + if (uhci->frame_number + uhci->is_stopped != uhci->urb_remove_age) { uhci_remove_pending_urbps(uhci); - uhci->urb_remove_age = age; + uhci->urb_remove_age = uhci->frame_number; } /* If we're the first, set the next interrupt bit */ @@ -1393,7 +1390,7 @@ list_add_tail(&urbp->urb_list, &uhci->urb_remove_list); done: - spin_unlock_irqrestore(&uhci->schedule_lock, flags); + spin_unlock_irqrestore(&uhci->lock, flags); return 0; } @@ -1455,28 +1452,27 @@ static void uhci_finish_urb(struct usb_hcd *hcd, struct urb *urb, struct pt_regs *regs) -__releases(uhci->schedule_lock) -__acquires(uhci->schedule_lock) +__releases(uhci->lock) +__acquires(uhci->lock) { struct uhci_hcd *uhci = hcd_to_uhci(hcd); uhci_destroy_urb_priv(uhci, urb); - spin_unlock(&uhci->schedule_lock); + spin_unlock(&uhci->lock); usb_hcd_giveback_urb(hcd, urb, regs); - spin_lock(&uhci->schedule_lock); + spin_lock(&uhci->lock); } -static void uhci_finish_completion(struct usb_hcd *hcd, struct pt_regs *regs) +static void uhci_finish_completion(struct uhci_hcd *uhci, struct pt_regs *regs) { - struct uhci_hcd *uhci = hcd_to_uhci(hcd); struct urb_priv *urbp, *tmp; list_for_each_entry_safe(urbp, tmp, &uhci->complete_list, urb_list) { struct urb *urb = urbp->urb; list_del_init(&urbp->urb_list); - uhci_finish_urb(hcd, urb, regs); + uhci_finish_urb(uhci_to_hcd(uhci), urb, regs); } } @@ -1485,4 +1481,59 @@ /* Splice the urb_remove_list onto the end of the complete_list */ list_splice_init(&uhci->urb_remove_list, uhci->complete_list.prev); +} + +/* Process events in the schedule, but only in one thread at a time */ +static void uhci_scan_schedule(struct uhci_hcd *uhci, struct pt_regs *regs) +{ + struct urb_priv *urbp, *tmp; + + /* Don't allow re-entrant calls */ + if (uhci->scan_in_progress) { + uhci->need_rescan = 1; + return; + } + uhci->scan_in_progress = 1; + rescan: + uhci->need_rescan = 0; + + uhci_get_current_frame_number(uhci); + + if (uhci->frame_number + uhci->is_stopped != uhci->qh_remove_age) + uhci_free_pending_qhs(uhci); + if (uhci->frame_number + uhci->is_stopped != uhci->td_remove_age) + uhci_free_pending_tds(uhci); + if (uhci->frame_number + uhci->is_stopped != uhci->urb_remove_age) + uhci_remove_pending_urbps(uhci); + + /* Walk the list of pending URBs to see which ones completed + * (must be _safe because uhci_transfer_result() dequeues URBs) */ + list_for_each_entry_safe(urbp, tmp, &uhci->urb_list, urb_list) { + struct urb *urb = urbp->urb; + + /* Checks the status and does all of the magic necessary */ + uhci_transfer_result(uhci, urb); + } + uhci_finish_completion(uhci, regs); + + /* If the controller is stopped, we can finish these off right now */ + if (uhci->is_stopped) { + uhci_free_pending_qhs(uhci); + uhci_free_pending_tds(uhci); + uhci_remove_pending_urbps(uhci); + } + + if (uhci->need_rescan) + goto rescan; + uhci->scan_in_progress = 0; + + if (list_empty(&uhci->urb_remove_list) && + list_empty(&uhci->td_remove_list) && + list_empty(&uhci->qh_remove_list)) + uhci_clear_next_interrupt(uhci); + else + uhci_set_next_interrupt(uhci); + + /* Wake up anyone waiting for an URB to complete */ + wake_up_all(&uhci->waitqh); } diff -Nru a/drivers/usb/image/Kconfig b/drivers/usb/image/Kconfig --- a/drivers/usb/image/Kconfig 2005-03-24 18:21:08 -08:00 +++ b/drivers/usb/image/Kconfig 2005-03-24 18:21:08 -08:00 @@ -28,14 +28,3 @@ The scanner will appear as a scsi generic device to the rest of the system. Scsi support is required. This driver can be compiled as a module, called microtek. - -config USB_HPUSBSCSI - tristate "HP53xx USB scanner support" - depends on USB && SCSI && BROKEN - help - Say Y here if you want support for the HP 53xx series of scanners - 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/Makefile b/drivers/usb/image/Makefile --- a/drivers/usb/image/Makefile 2005-03-24 18:21:08 -08:00 +++ b/drivers/usb/image/Makefile 2005-03-24 18:21:08 -08:00 @@ -3,5 +3,4 @@ # obj-$(CONFIG_USB_MDC800) += mdc800.o -obj-$(CONFIG_USB_HPUSBSCSI) += hpusbscsi.o obj-$(CONFIG_USB_MICROTEK) += microtek.o diff -Nru a/drivers/usb/image/hpusbscsi.c b/drivers/usb/image/hpusbscsi.c --- a/drivers/usb/image/hpusbscsi.c 2005-03-24 18:21:08 -08:00 +++ /dev/null Wed Dec 31 16:00:00 196900 @@ -1,523 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "../../scsi/scsi.h" -#include - -#include "hpusbscsi.h" - -#define DEBUG(x...) \ - printk( KERN_DEBUG x ) - -static char *states[]={"FREE", "BEGINNING", "WORKING", "ERROR", "WAIT", "PREMATURE"}; - -#define TRACE_STATE printk(KERN_DEBUG"hpusbscsi->state = %s at line %d\n", states[hpusbscsi->state], __LINE__) - -static Scsi_Host_Template hpusbscsi_scsi_host_template = { - .module = THIS_MODULE, - .name = "hpusbscsi", - .proc_name = "hpusbscsi", - .queuecommand = hpusbscsi_scsi_queuecommand, - .eh_abort_handler = hpusbscsi_scsi_abort, - .eh_host_reset_handler = hpusbscsi_scsi_host_reset, - .sg_tablesize = SG_ALL, - .can_queue = 1, - .this_id = -1, - .cmd_per_lun = 1, - .use_clustering = 1, - .emulated = 1, -}; - -static int -hpusbscsi_usb_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - struct usb_device *dev = interface_to_usbdev(intf); - struct usb_host_interface *altsetting = intf->cur_altsetting; - struct hpusbscsi *new; - int error = -ENOMEM; - int i; - - if (altsetting->desc.bNumEndpoints != 3) { - printk (KERN_ERR "Wrong number of endpoints\n"); - return -ENODEV; - } - - new = kmalloc(sizeof(struct hpusbscsi), GFP_KERNEL); - if (!new) - return -ENOMEM; - memset(new, 0, sizeof(struct hpusbscsi)); - new->dataurb = usb_alloc_urb(0, GFP_KERNEL); - if (!new->dataurb) - goto out_kfree; - new->controlurb = usb_alloc_urb(0, GFP_KERNEL); - if (!new->controlurb) - goto out_free_dataurb; - - new->dev = dev; - init_waitqueue_head(&new->pending); - init_waitqueue_head(&new->deathrow); - - error = -ENODEV; - for (i = 0; i < altsetting->desc.bNumEndpoints; i++) { - if ((altsetting->endpoint[i].desc. - bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == - USB_ENDPOINT_XFER_BULK) { - if (altsetting->endpoint[i].desc. - bEndpointAddress & USB_DIR_IN) { - new->ep_in = - altsetting->endpoint[i].desc. - bEndpointAddress & - USB_ENDPOINT_NUMBER_MASK; - } else { - new->ep_out = - altsetting->endpoint[i].desc. - bEndpointAddress & - USB_ENDPOINT_NUMBER_MASK; - } - } else { - new->ep_int = - altsetting->endpoint[i].desc. - bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; - new->interrupt_interval= altsetting->endpoint[i].desc. - bInterval; - } - } - - /* build and submit an interrupt URB for status byte handling */ - usb_fill_int_urb(new->controlurb, new->dev, - usb_rcvintpipe(new->dev, new->ep_int), - &new->scsi_state_byte, 1, - control_interrupt_callback,new, - new->interrupt_interval); - - if (usb_submit_urb(new->controlurb, GFP_KERNEL) < 0) - goto out_free_controlurb; - - /* In host->hostdata we store a pointer to desc */ - new->host = scsi_host_alloc(&hpusbscsi_scsi_host_template, sizeof(new)); - if (!new->host) - goto out_kill_controlurb; - - new->host->hostdata[0] = (unsigned long)new; - scsi_add_host(new->host, &intf->dev); /* XXX handle failure */ - scsi_scan_host(new->host); - - new->sense_command[0] = REQUEST_SENSE; - new->sense_command[4] = HPUSBSCSI_SENSE_LENGTH; - - usb_set_intfdata(intf, new); - return 0; - - out_kill_controlurb: - usb_kill_urb(new->controlurb); - out_free_controlurb: - usb_free_urb(new->controlurb); - out_free_dataurb: - usb_free_urb(new->dataurb); - out_kfree: - kfree(new); - return error; -} - -static void -hpusbscsi_usb_disconnect(struct usb_interface *intf) -{ - struct hpusbscsi *desc = usb_get_intfdata(intf); - - usb_set_intfdata(intf, NULL); - - scsi_remove_host(desc->host); - usb_kill_urb(desc->controlurb); - scsi_host_put(desc->host); - - usb_free_urb(desc->controlurb); - usb_free_urb(desc->dataurb); - kfree(desc); -} - -static struct usb_device_id hpusbscsi_usb_ids[] = { - {USB_DEVICE (0x03f0, 0x0701)}, /* HP 53xx */ - {USB_DEVICE (0x03f0, 0x0801)}, /* HP 7400 */ - {USB_DEVICE (0x0638, 0x0268)}, /*iVina 1200U */ - {USB_DEVICE (0x0638, 0x026a)}, /*Scan Dual II */ - {USB_DEVICE (0x0638, 0x0A13)}, /*Avision AV600U */ - {USB_DEVICE (0x0638, 0x0A16)}, /*Avision DS610CU Scancopier */ - {USB_DEVICE (0x0638, 0x0A18)}, /*Avision AV600U Plus */ - {USB_DEVICE (0x0638, 0x0A23)}, /*Avision AV220 */ - {USB_DEVICE (0x0638, 0x0A24)}, /*Avision AV210 */ - {USB_DEVICE (0x0686, 0x4004)}, /*Minolta Elite II */ - {} /* Terminating entry */ -}; - -MODULE_DEVICE_TABLE (usb, hpusbscsi_usb_ids); -MODULE_LICENSE("GPL"); - - -static struct usb_driver hpusbscsi_usb_driver = { - .owner = THIS_MODULE, - .name ="hpusbscsi", - .probe =hpusbscsi_usb_probe, - .disconnect =hpusbscsi_usb_disconnect, - .id_table =hpusbscsi_usb_ids, -}; - -/* module initialisation */ - -static int __init -hpusbscsi_init (void) -{ - return usb_register(&hpusbscsi_usb_driver); -} - -static void __exit -hpusbscsi_exit (void) -{ - usb_deregister(&hpusbscsi_usb_driver); -} - -module_init (hpusbscsi_init); -module_exit (hpusbscsi_exit); - -static int hpusbscsi_scsi_queuecommand (Scsi_Cmnd *srb, scsi_callback callback) -{ - struct hpusbscsi* hpusbscsi = (struct hpusbscsi*)(srb->device->host->hostdata[0]); - usb_complete_t usb_callback; - int res; - - /* we don't answer for anything but our single device on any faked host controller */ - if ( srb->device->lun || srb->device->id || srb->device->channel ) { - if (callback) { - srb->result = DID_BAD_TARGET; - callback(srb); - } - goto out; - } - - /* Now we need to decide which callback to give to the urb we send the command with */ - - if (!srb->bufflen) { - if (srb->cmnd[0] == REQUEST_SENSE){ - hpusbscsi->current_data_pipe = usb_rcvbulkpipe(hpusbscsi->dev, hpusbscsi->ep_in); - usb_callback = request_sense_callback; - } else { - usb_callback = simple_command_callback; - } - } else { - if (likely(srb->use_sg)) { - usb_callback = scatter_gather_callback; - hpusbscsi->fragment = 0; - } else { - usb_callback = simple_payload_callback; - } - /* Now we find out which direction data is to be transferred in */ - hpusbscsi->current_data_pipe = DIRECTION_IS_IN(srb->cmnd[0]) ? - usb_rcvbulkpipe(hpusbscsi->dev, hpusbscsi->ep_in) - : - usb_sndbulkpipe(hpusbscsi->dev, hpusbscsi->ep_out) - ; - } - - - TRACE_STATE; - - /* We zero the sense buffer to avoid confusing user space */ - memset(srb->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE); - - hpusbscsi->state = HP_STATE_BEGINNING; - TRACE_STATE; - - /* We prepare the urb for writing out the scsi command */ - usb_fill_bulk_urb( - hpusbscsi->dataurb, - hpusbscsi->dev, - usb_sndbulkpipe(hpusbscsi->dev,hpusbscsi->ep_out), - srb->cmnd, - srb->cmd_len, - usb_callback, - hpusbscsi - ); - hpusbscsi->scallback = callback; - hpusbscsi->srb = srb; - - res = usb_submit_urb(hpusbscsi->dataurb, GFP_ATOMIC); - if (unlikely(res)) { - hpusbscsi->state = HP_STATE_FREE; - TRACE_STATE; - if (likely(callback != NULL)) { - srb->result = DID_ERROR; - callback(srb); - } - } - -out: - return 0; -} - -static int hpusbscsi_scsi_host_reset (Scsi_Cmnd *srb) -{ - struct hpusbscsi* hpusbscsi = (struct hpusbscsi*)(srb->device->host->hostdata[0]); - - printk(KERN_DEBUG"SCSI reset requested.\n"); - //usb_reset_device(hpusbscsi->dev); - //printk(KERN_DEBUG"SCSI reset completed.\n"); - hpusbscsi->state = HP_STATE_FREE; - - return 0; -} - -static int hpusbscsi_scsi_abort (Scsi_Cmnd *srb) -{ - struct hpusbscsi* hpusbscsi = (struct hpusbscsi*)(srb->device->host->hostdata[0]); - printk(KERN_DEBUG"Requested is canceled.\n"); - - usb_kill_urb(hpusbscsi->dataurb); - usb_kill_urb(hpusbscsi->controlurb); - hpusbscsi->state = HP_STATE_FREE; - - return SCSI_ABORT_PENDING; -} - -/* usb interrupt handlers - they are all running IN INTERRUPT ! */ - -static void handle_usb_error (struct hpusbscsi *hpusbscsi) -{ - if (likely(hpusbscsi->scallback != NULL)) { - hpusbscsi->srb->result = DID_ERROR; - hpusbscsi->scallback(hpusbscsi->srb); - } - hpusbscsi->state = HP_STATE_FREE; -} - -static void control_interrupt_callback (struct urb *u, struct pt_regs *regs) -{ - struct hpusbscsi * hpusbscsi = (struct hpusbscsi *)u->context; - u8 scsi_state; - -DEBUG("Getting status byte %d \n",hpusbscsi->scsi_state_byte); - if(unlikely(u->status < 0)) { - if (likely(hpusbscsi->state != HP_STATE_FREE)) - handle_usb_error(hpusbscsi); - if (u->status == -ECONNRESET || u->status == -ENOENT || u->status == -ESHUTDOWN) - return; - else - goto resub; - } - - scsi_state = hpusbscsi->scsi_state_byte; - if (hpusbscsi->state != HP_STATE_ERROR) { - hpusbscsi->srb->result &= SCSI_ERR_MASK; - hpusbscsi->srb->result |= scsi_state; - } - - if (scsi_state == CHECK_CONDITION << 1) { - if (hpusbscsi->state == HP_STATE_WAIT) { - issue_request_sense(hpusbscsi); - } else { - /* we request sense after an eventual data transfer */ - hpusbscsi->state = HP_STATE_ERROR; - } - } - - if (hpusbscsi->scallback != NULL && hpusbscsi->state == HP_STATE_WAIT && scsi_state != CHECK_CONDITION <<1 ) - /* we do a callback to the scsi layer if and only if all data has been transferred */ - hpusbscsi->scallback(hpusbscsi->srb); - - TRACE_STATE; - switch (hpusbscsi->state) { - case HP_STATE_WAIT: - hpusbscsi->state = HP_STATE_FREE; - TRACE_STATE; - break; - case HP_STATE_WORKING: - case HP_STATE_BEGINNING: - hpusbscsi->state = HP_STATE_PREMATURE; - TRACE_STATE; - break; - case HP_STATE_ERROR: - break; - default: - printk(KERN_ERR"hpusbscsi: Unexpected status report.\n"); - TRACE_STATE; - hpusbscsi->state = HP_STATE_FREE; - TRACE_STATE; - break; - } -resub: - usb_submit_urb(u, GFP_ATOMIC); -} - -static void simple_command_callback(struct urb *u, struct pt_regs *regs) -{ - struct hpusbscsi * hpusbscsi = (struct hpusbscsi *)u->context; - if (unlikely(u->status<0)) { - handle_usb_error(hpusbscsi); - return; - } - TRACE_STATE; - if (hpusbscsi->state != HP_STATE_PREMATURE) { - TRACE_STATE; - hpusbscsi->state = HP_STATE_WAIT; - } else { - if (likely(hpusbscsi->scallback != NULL)) - hpusbscsi->scallback(hpusbscsi->srb); - hpusbscsi->state = HP_STATE_FREE; - TRACE_STATE; - } -} - -static void scatter_gather_callback(struct urb *u, struct pt_regs *regs) -{ - struct hpusbscsi * hpusbscsi = (struct hpusbscsi *)u->context; - struct scatterlist *sg = hpusbscsi->srb->buffer; - usb_complete_t callback; - int res; - - DEBUG("Going through scatter/gather\n"); - if (unlikely(u->status < 0)) { - handle_usb_error(hpusbscsi); - return; - } - - if (hpusbscsi->fragment + 1 != hpusbscsi->srb->use_sg) - callback = scatter_gather_callback; - else - callback = simple_done; - - TRACE_STATE; - if (hpusbscsi->state != HP_STATE_PREMATURE) - hpusbscsi->state = HP_STATE_WORKING; - TRACE_STATE; - - usb_fill_bulk_urb( - u, - hpusbscsi->dev, - hpusbscsi->current_data_pipe, - page_address(sg[hpusbscsi->fragment].page) + - sg[hpusbscsi->fragment].offset, - sg[hpusbscsi->fragment++].length, - callback, - hpusbscsi - ); - - res = usb_submit_urb(u, GFP_ATOMIC); - if (unlikely(res)) - handle_usb_error(hpusbscsi); - TRACE_STATE; -} - -static void simple_done (struct urb *u, struct pt_regs *regs) -{ - struct hpusbscsi * hpusbscsi = (struct hpusbscsi *)u->context; - - if (unlikely(u->status < 0)) { - handle_usb_error(hpusbscsi); - return; - } - DEBUG("Data transfer done\n"); - TRACE_STATE; - if (hpusbscsi->state != HP_STATE_PREMATURE) { - if (unlikely(u->status < 0)) { - handle_usb_error(hpusbscsi); - } else { - if (hpusbscsi->state != HP_STATE_ERROR) { - hpusbscsi->state = HP_STATE_WAIT; - } else { - issue_request_sense(hpusbscsi); - } - } - } else { - if (likely(hpusbscsi->scallback != NULL)) - hpusbscsi->scallback(hpusbscsi->srb); - hpusbscsi->state = HP_STATE_FREE; - } -} - -static void simple_payload_callback (struct urb *u, struct pt_regs *regs) -{ - struct hpusbscsi * hpusbscsi = (struct hpusbscsi *)u->context; - int res; - - if (unlikely(u->status<0)) { - handle_usb_error(hpusbscsi); - return; - } - - usb_fill_bulk_urb( - u, - hpusbscsi->dev, - hpusbscsi->current_data_pipe, - hpusbscsi->srb->buffer, - hpusbscsi->srb->bufflen, - simple_done, - hpusbscsi - ); - - res = usb_submit_urb(u, GFP_ATOMIC); - if (unlikely(res)) { - handle_usb_error(hpusbscsi); - return; - } - TRACE_STATE; - if (hpusbscsi->state != HP_STATE_PREMATURE) { - hpusbscsi->state = HP_STATE_WORKING; - TRACE_STATE; - } -} - -static void request_sense_callback (struct urb *u, struct pt_regs *regs) -{ - struct hpusbscsi * hpusbscsi = (struct hpusbscsi *)u->context; - - if (u->status<0) { - handle_usb_error(hpusbscsi); - return; - } - - usb_fill_bulk_urb( - u, - hpusbscsi->dev, - hpusbscsi->current_data_pipe, - hpusbscsi->srb->sense_buffer, - SCSI_SENSE_BUFFERSIZE, - simple_done, - hpusbscsi - ); - - if (0 > usb_submit_urb(u, GFP_ATOMIC)) { - handle_usb_error(hpusbscsi); - return; - } - if (hpusbscsi->state != HP_STATE_PREMATURE && hpusbscsi->state != HP_STATE_ERROR) - hpusbscsi->state = HP_STATE_WORKING; -} - -static void issue_request_sense (struct hpusbscsi *hpusbscsi) -{ - usb_fill_bulk_urb( - hpusbscsi->dataurb, - hpusbscsi->dev, - usb_sndbulkpipe(hpusbscsi->dev, hpusbscsi->ep_out), - &hpusbscsi->sense_command, - SENSE_COMMAND_SIZE, - request_sense_callback, - hpusbscsi - ); - - hpusbscsi->current_data_pipe = usb_rcvbulkpipe(hpusbscsi->dev, hpusbscsi->ep_in); - - if (0 > usb_submit_urb(hpusbscsi->dataurb, GFP_ATOMIC)) { - handle_usb_error(hpusbscsi); - } -} - - diff -Nru a/drivers/usb/image/hpusbscsi.h b/drivers/usb/image/hpusbscsi.h --- a/drivers/usb/image/hpusbscsi.h 2005-03-24 18:21:08 -08:00 +++ /dev/null Wed Dec 31 16:00:00 196900 @@ -1,73 +0,0 @@ -/* Header file for the hpusbscsi driver */ -/* (C) Copyright 2001 Oliver Neukum */ -/* sponsored by the Linux Usb Project */ -/* large parts based on or taken from code by John Fremlin and Matt Dharm */ -/* this file is licensed under the GPL */ - -/* A big thanks to Jose for untiring testing */ - -typedef void (*scsi_callback)(Scsi_Cmnd *); - -#define SENSE_COMMAND_SIZE 6 -#define HPUSBSCSI_SENSE_LENGTH 0x16 - -struct hpusbscsi -{ - struct usb_device *dev; /* NULL indicates unplugged device */ - int ep_out; - int ep_in; - int ep_int; - int interrupt_interval; - int number; - int fragment; - struct Scsi_Host *host; - - scsi_callback scallback; - Scsi_Cmnd *srb; - - - wait_queue_head_t pending; - wait_queue_head_t deathrow; - - struct urb *dataurb; - struct urb *controlurb; - - - int state; - int current_data_pipe; - u8 sense_command[SENSE_COMMAND_SIZE]; - u8 scsi_state_byte; -}; - -#define SCSI_ERR_MASK ~0x3fu - -static const unsigned char scsi_command_direction[256/8] = { - 0x28, 0x81, 0x14, 0x14, 0x20, 0x01, 0x90, 0x77, - 0x0C, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -#define DIRECTION_IS_IN(x) ((scsi_command_direction[x>>3] >> (x & 7)) & 1) - -static void simple_command_callback(struct urb *u, struct pt_regs *regs); -static void scatter_gather_callback(struct urb *u, struct pt_regs *regs); -static void simple_payload_callback (struct urb *u, struct pt_regs *regs); -static void request_sense_callback (struct urb *u, struct pt_regs *regs); -static void control_interrupt_callback (struct urb *u, struct pt_regs *regs); -static void simple_done (struct urb *u, struct pt_regs *regs); -static int hpusbscsi_scsi_queuecommand (Scsi_Cmnd *srb, scsi_callback callback); -static int hpusbscsi_scsi_host_reset (Scsi_Cmnd *srb); -static int hpusbscsi_scsi_abort (Scsi_Cmnd *srb); -static void issue_request_sense (struct hpusbscsi *hpusbscsi); - -/* defines for internal driver state */ -#define HP_STATE_FREE 0 /*ready for next request */ -#define HP_STATE_BEGINNING 1 /*command being transferred */ -#define HP_STATE_WORKING 2 /* data transfer stage */ -#define HP_STATE_ERROR 3 /* error has been reported */ -#define HP_STATE_WAIT 4 /* waiting for status transfer */ -#define HP_STATE_PREMATURE 5 /* status prematurely reported */ - - - diff -Nru a/drivers/usb/image/microtek.c b/drivers/usb/image/microtek.c --- a/drivers/usb/image/microtek.c 2005-03-24 18:21:08 -08:00 +++ b/drivers/usb/image/microtek.c 2005-03-24 18:21:08 -08:00 @@ -703,6 +703,7 @@ int ep_in_set[3]; /* this will break if we have more than three endpoints which is why we check */ int *ep_in_current = ep_in_set; + int err_retval = -ENOMEM; struct mts_desc * new_desc; struct vendor_product const* p; @@ -809,7 +810,10 @@ goto out_free_urb; new_desc->host->hostdata[0] = (unsigned long)new_desc; - scsi_add_host(new_desc->host, NULL); /* XXX handle failure */ + if (scsi_add_host(new_desc->host, NULL)) { + err_retval = -EIO; + goto out_free_urb; + } scsi_scan_host(new_desc->host); usb_set_intfdata(intf, new_desc); @@ -820,7 +824,7 @@ out_kfree: kfree(new_desc); out: - return -ENOMEM; + return err_retval; } static void mts_usb_disconnect (struct usb_interface *intf) diff -Nru a/drivers/usb/input/aiptek.c b/drivers/usb/input/aiptek.c --- a/drivers/usb/input/aiptek.c 2005-03-24 18:21:08 -08:00 +++ b/drivers/usb/input/aiptek.c 2005-03-24 18:21:08 -08:00 @@ -794,7 +794,7 @@ * manufacturing revisions. In any event, we consider these * IDs to not be model-specific nor unique. */ -struct usb_device_id aiptek_ids[] = { +static const struct usb_device_id aiptek_ids[] = { {USB_DEVICE(USB_VENDOR_ID_AIPTEK, 0x01)}, {USB_DEVICE(USB_VENDOR_ID_AIPTEK, 0x10)}, {USB_DEVICE(USB_VENDOR_ID_AIPTEK, 0x20)}, diff -Nru a/drivers/usb/media/ibmcam.c b/drivers/usb/media/ibmcam.c --- a/drivers/usb/media/ibmcam.c 2005-03-24 18:21:08 -08:00 +++ b/drivers/usb/media/ibmcam.c 2005-03-24 18:21:08 -08:00 @@ -1036,7 +1036,8 @@ * History: * 1/21/00 Created. */ -void ibmcam_ProcessIsocData(struct uvd *uvd, struct usbvideo_frame *frame) +static void ibmcam_ProcessIsocData(struct uvd *uvd, + struct usbvideo_frame *frame) { enum ParseState newstate; long copylen = 0; diff -Nru a/drivers/usb/media/pwc/pwc-if.c b/drivers/usb/media/pwc/pwc-if.c --- a/drivers/usb/media/pwc/pwc-if.c 2005-03-24 18:21:08 -08:00 +++ b/drivers/usb/media/pwc/pwc-if.c 2005-03-24 18:21:08 -08:00 @@ -322,7 +322,7 @@ case 730: case 740: case 750: - Trace(TRACE_MEMORY,"private_data(%d)\n",sizeof(struct pwc_dec23_private)); + Trace(TRACE_MEMORY,"private_data(%Zd)\n",sizeof(struct pwc_dec23_private)); kbuf = kmalloc(sizeof(struct pwc_dec23_private), GFP_KERNEL); /* Timon & Kiara */ break; case 645: @@ -1179,7 +1179,7 @@ DECLARE_WAITQUEUE(wait, current); int bytes_to_read; - Trace(TRACE_READ, "video_read(0x%p, %p, %d) called.\n", vdev, buf, count); + Trace(TRACE_READ, "video_read(0x%p, %p, %Zd) called.\n", vdev, buf, count); if (vdev == NULL) return -EFAULT; pdev = vdev->priv; diff -Nru a/drivers/usb/misc/emi26.c b/drivers/usb/misc/emi26.c --- a/drivers/usb/misc/emi26.c 2005-03-24 18:21:08 -08:00 +++ b/drivers/usb/misc/emi26.c 2005-03-24 18:21:08 -08:00 @@ -30,6 +30,7 @@ #define EMI26_VENDOR_ID 0x086a /* Emagic Soft-und Hardware GmBH */ #define EMI26_PRODUCT_ID 0x0100 /* EMI 2|6 without firmware */ +#define EMI26B_PRODUCT_ID 0x0102 /* EMI 2|6 without firmware */ #define ANCHOR_LOAD_INTERNAL 0xA0 /* Vendor specific request code for Anchor Upload/Download (This one is implemented in the core) */ #define ANCHOR_LOAD_EXTERNAL 0xA3 /* This command is not implemented in the core. Requires firmware */ @@ -203,6 +204,7 @@ static struct usb_device_id id_table [] = { { USB_DEVICE(EMI26_VENDOR_ID, EMI26_PRODUCT_ID) }, + { USB_DEVICE(EMI26_VENDOR_ID, EMI26B_PRODUCT_ID) }, { } /* Terminating entry */ }; diff -Nru a/drivers/usb/misc/rio500.c b/drivers/usb/misc/rio500.c --- a/drivers/usb/misc/rio500.c 2005-03-24 18:21:08 -08:00 +++ b/drivers/usb/misc/rio500.c 2005-03-24 18:21:08 -08:00 @@ -40,6 +40,7 @@ #include #include #include +#include #include "rio500_usb.h" @@ -264,6 +265,7 @@ write_rio(struct file *file, const char __user *buffer, size_t count, loff_t * ppos) { + DEFINE_WAIT(wait); struct rio_usb_data *rio = &rio_instance; unsigned long copy_size; @@ -319,7 +321,9 @@ errn = -ETIME; goto error; } - interruptible_sleep_on_timeout(&rio-> wait_q, NAK_TIMEOUT); + prepare_to_wait(&rio->wait_q, &wait, TASK_INTERRUPTIBLE); + schedule_timeout(NAK_TIMEOUT); + finish_wait(&rio->wait_q, &wait); continue; } else if (!result && partial) { obuf += partial; @@ -349,6 +353,7 @@ static ssize_t read_rio(struct file *file, char __user *buffer, size_t count, loff_t * ppos) { + DEFINE_WAIT(wait); struct rio_usb_data *rio = &rio_instance; ssize_t read_count; unsigned int partial; @@ -399,8 +404,9 @@ err("read_rio: maxretry timeout"); return -ETIME; } - interruptible_sleep_on_timeout(&rio->wait_q, - NAK_TIMEOUT); + prepare_to_wait(&rio->wait_q, &wait, TASK_INTERRUPTIBLE); + schedule_timeout(NAK_TIMEOUT); + finish_wait(&rio->wait_q, &wait); continue; } else if (result != -EREMOTEIO) { up(&(rio->lock)); diff -Nru a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c --- a/drivers/usb/misc/sisusbvga/sisusb.c 2005-03-24 18:21:08 -08:00 +++ b/drivers/usb/misc/sisusbvga/sisusb.c 2005-03-24 18:21:08 -08:00 @@ -564,7 +564,7 @@ struct sisusb_packet *packet) { int ret; - int bytes_transferred = 0; + ssize_t bytes_transferred = 0; __le32 tmp; if (len == 6) @@ -601,7 +601,7 @@ unsigned int tflags) { int ret; - int bytes_transferred = 0; + ssize_t bytes_transferred = 0; __le32 tmp; if (len == 6) @@ -983,7 +983,7 @@ msgcount++; if (msgcount < 500) printk(KERN_ERR - "sisusbvga[%d]: Wrote %d of " + "sisusbvga[%d]: Wrote %Zd of " "%d bytes, error %d\n", sisusb->minor, *bytes_written, length, ret); @@ -1381,7 +1381,8 @@ static int sisusb_clear_vram(struct sisusb_usb_data *sisusb, u32 address, int length) { - int ret, i, j; + int ret, i; + ssize_t j; if (address < sisusb->vrambase) return 1; @@ -2271,7 +2272,7 @@ /* fops */ -int +static int sisusb_open(struct inode *inode, struct file *file) { struct sisusb_usb_data *sisusb; @@ -2361,7 +2362,7 @@ kfree(sisusb); } -int +static int sisusb_release(struct inode *inode, struct file *file) { struct sisusb_usb_data *sisusb; @@ -2399,7 +2400,7 @@ return 0; } -ssize_t +static ssize_t sisusb_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) { struct sisusb_usb_data *sisusb; @@ -2540,7 +2541,7 @@ return errno ? errno : bytes_read; } -ssize_t +static ssize_t sisusb_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) { diff -Nru a/drivers/usb/mon/mon_text.c b/drivers/usb/mon/mon_text.c --- a/drivers/usb/mon/mon_text.c 2005-03-24 18:21:08 -08:00 +++ b/drivers/usb/mon/mon_text.c 2005-03-24 18:21:08 -08:00 @@ -261,6 +261,7 @@ struct mon_event_text *ep; int cnt, limit; char *pbuf; + char udir, utype; int data_len, i; add_wait_queue(&rp->wait, &waita); @@ -290,9 +291,18 @@ pbuf = rp->printf_buf; limit = rp->printf_size; + udir = usb_pipein(ep->pipe) ? 'i' : 'o'; + switch (usb_pipetype(ep->pipe)) { + case PIPE_ISOCHRONOUS: utype = 'Z'; break; + case PIPE_INTERRUPT: utype = 'I'; break; + case PIPE_CONTROL: utype = 'C'; break; + default: /* PIPE_BULK */ utype = 'B'; + } cnt += snprintf(pbuf + cnt, limit - cnt, - "%lx %u %c %08x %d %d", - ep->id, ep->tstamp, ep->type, ep->pipe, ep->status, ep->length); + "%lx %u %c %c%c:%03u:%02u %d %d", + ep->id, ep->tstamp, ep->type, + utype, udir, usb_pipedevice(ep->pipe), usb_pipeendpoint(ep->pipe), + ep->status, ep->length); if ((data_len = ep->length) > 0) { if (ep->data_flag == 0) { diff -Nru a/drivers/usb/net/catc.c b/drivers/usb/net/catc.c --- a/drivers/usb/net/catc.c 2005-03-24 18:21:08 -08:00 +++ b/drivers/usb/net/catc.c 2005-03-24 18:21:08 -08:00 @@ -664,7 +664,8 @@ } } -void catc_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) +static void catc_get_drvinfo(struct net_device *dev, + struct ethtool_drvinfo *info) { struct catc *catc = netdev_priv(dev); strncpy(info->driver, driver_name, ETHTOOL_BUSINFO_LEN); diff -Nru a/drivers/usb/net/kaweth.c b/drivers/usb/net/kaweth.c --- a/drivers/usb/net/kaweth.c 2005-03-24 18:21:08 -08:00 +++ b/drivers/usb/net/kaweth.c 2005-03-24 18:21:08 -08:00 @@ -594,7 +594,7 @@ struct sk_buff *skb; - if(unlikely(urb->status == -ECONNRESET || urb->status == -ECONNABORTED || urb->status == -ESHUTDOWN)) + if(unlikely(urb->status == -ECONNRESET || urb->status == -ESHUTDOWN)) /* we are killed - set a flag and wake the disconnect handler */ { kaweth->end = 1; diff -Nru a/drivers/usb/net/kawethfw.h b/drivers/usb/net/kawethfw.h --- a/drivers/usb/net/kawethfw.h 2005-03-24 18:21:08 -08:00 +++ b/drivers/usb/net/kawethfw.h 2005-03-24 18:21:08 -08:00 @@ -551,7 +551,7 @@ }; -const int len_kaweth_trigger_code = sizeof(kaweth_trigger_code); -const int len_kaweth_trigger_code_fix = sizeof(kaweth_trigger_code_fix); -const int len_kaweth_new_code = sizeof(kaweth_new_code); -const int len_kaweth_new_code_fix = sizeof(kaweth_new_code_fix); +static const int len_kaweth_trigger_code = sizeof(kaweth_trigger_code); +static const int len_kaweth_trigger_code_fix = sizeof(kaweth_trigger_code_fix); +static const int len_kaweth_new_code = sizeof(kaweth_new_code); +static const int len_kaweth_new_code_fix = sizeof(kaweth_new_code_fix); diff -Nru a/drivers/usb/net/pegasus.c b/drivers/usb/net/pegasus.c --- a/drivers/usb/net/pegasus.c 2005-03-24 18:21:08 -08:00 +++ b/drivers/usb/net/pegasus.c 2005-03-24 18:21:08 -08:00 @@ -85,6 +85,11 @@ MODULE_PARM_DESC(loopback, "Enable MAC loopback mode (bit 0)"); MODULE_PARM_DESC(mii_mode, "Enable HomePNA mode (bit 0),default=MII mode = 0"); +/* use ethtool to change the level for any given device */ +static int msg_level = -1; +module_param (msg_level, int, 0); +MODULE_PARM_DESC (msg_level, "Override default message level"); + MODULE_DEVICE_TABLE(usb, pegasus_ids); static int update_eth_regs_async(pegasus_t *); @@ -110,7 +115,9 @@ case -ENOENT: break; default: - warn("%s: status %d", __FUNCTION__, urb->status); + if (netif_msg_drv(pegasus)) + dev_err(&pegasus->intf->dev, "%s, status %d\n", + __FUNCTION__, urb->status); } pegasus->flags &= ~ETH_REGS_CHANGED; wake_up(&pegasus->ctrl_wait); @@ -125,7 +132,9 @@ buffer = kmalloc(size, GFP_KERNEL); if (!buffer) { - warn("%s: looks like we're out of memory", __FUNCTION__); + if (netif_msg_drv(pegasus)) + dev_warn(&pegasus->intf->dev, "out of memory in %s\n", + __FUNCTION__); return -ENOMEM; } add_wait_queue(&pegasus->ctrl_wait, &wait); @@ -152,7 +161,9 @@ /* using ATOMIC, we'd never wake up if we slept */ if ((ret = usb_submit_urb(pegasus->ctrl_urb, GFP_ATOMIC))) { - err("%s: BAD CTRLs %d", __FUNCTION__, ret); + if (netif_msg_drv(pegasus)) + dev_err(&pegasus->intf->dev, "%s, status %d\n", + __FUNCTION__, ret); goto out; } @@ -174,7 +185,9 @@ buffer = kmalloc(size, GFP_KERNEL); if (!buffer) { - warn("%s: looks like we're out of memory", __FUNCTION__); + if (netif_msg_drv(pegasus)) + dev_warn(&pegasus->intf->dev, "out of memory in %s\n", + __FUNCTION__); return -ENOMEM; } memcpy(buffer, data, size); @@ -202,7 +215,9 @@ set_current_state(TASK_UNINTERRUPTIBLE); if ((ret = usb_submit_urb(pegasus->ctrl_urb, GFP_ATOMIC))) { - err("%s: BAD CTRL %d", __FUNCTION__, ret); + if (netif_msg_drv(pegasus)) + dev_err(&pegasus->intf->dev, "%s, status %d\n", + __FUNCTION__, ret); goto out; } @@ -222,7 +237,9 @@ tmp = kmalloc(1, GFP_KERNEL); if (!tmp) { - warn("%s: looks like we're out of memory", __FUNCTION__); + if (netif_msg_drv(pegasus)) + dev_warn(&pegasus->intf->dev, "out of memory in %s\n", + __FUNCTION__); return -ENOMEM; } memcpy(tmp, &data, 1); @@ -249,7 +266,9 @@ set_current_state(TASK_UNINTERRUPTIBLE); if ((ret = usb_submit_urb(pegasus->ctrl_urb, GFP_ATOMIC))) { - err("%s: BAD CTRL %d", __FUNCTION__, ret); + if (netif_msg_drv(pegasus)) + dev_err(&pegasus->intf->dev, "%s, status %d\n", + __FUNCTION__, ret); goto out; } @@ -278,8 +297,9 @@ pegasus->eth_regs, 3, ctrl_callback, pegasus); if ((ret = usb_submit_urb(pegasus->ctrl_urb, GFP_ATOMIC))) - err("%s: BAD CTRL %d, flgs %x", __FUNCTION__, ret, - pegasus->flags); + if (netif_msg_drv(pegasus)) + dev_err(&pegasus->intf->dev, "%s, status %d\n", + __FUNCTION__, ret); return ret; } @@ -289,21 +309,23 @@ int i; __u8 data[4] = { phy, 0, 0, indx }; __le16 regdi; + int ret; - set_register(pegasus, PhyCtrl, 0); - set_registers(pegasus, PhyAddr, sizeof (data), data); - set_register(pegasus, PhyCtrl, (indx | PHY_READ)); + ret = set_register(pegasus, PhyCtrl, 0); + ret = set_registers(pegasus, PhyAddr, sizeof (data), data); + ret = set_register(pegasus, PhyCtrl, (indx | PHY_READ)); for (i = 0; i < REG_TIMEOUT; i++) { - get_registers(pegasus, PhyCtrl, 1, data); + ret = get_registers(pegasus, PhyCtrl, 1, data); if (data[0] & PHY_DONE) break; } if (i < REG_TIMEOUT) { - get_registers(pegasus, PhyData, 2, ®di); + ret = get_registers(pegasus, PhyData, 2, ®di); *regd = le16_to_cpu(regdi); return 1; } - warn("%s: failed", __FUNCTION__); + if (netif_msg_drv(pegasus)) + dev_warn(&pegasus->intf->dev, "fail %s\n", __FUNCTION__); return 0; } @@ -311,7 +333,7 @@ static int mdio_read(struct net_device *dev, int phy_id, int loc) { pegasus_t *pegasus = (pegasus_t *) netdev_priv(dev); - __le16 res; + u16 res; read_mii_word(pegasus, phy_id, loc, &res); return (int)res; @@ -321,20 +343,23 @@ { int i; __u8 data[4] = { phy, 0, 0, indx }; + int ret; - *(data + 1) = cpu_to_le16p(®d); - set_register(pegasus, PhyCtrl, 0); - set_registers(pegasus, PhyAddr, sizeof(data), data); - set_register(pegasus, PhyCtrl, (indx | PHY_WRITE)); + data[1] = (u8) regd; + data[2] = (u8) (regd >> 8); + ret = set_register(pegasus, PhyCtrl, 0); + ret = set_registers(pegasus, PhyAddr, sizeof(data), data); + ret = set_register(pegasus, PhyCtrl, (indx | PHY_WRITE)); for (i = 0; i < REG_TIMEOUT; i++) { - get_registers(pegasus, PhyCtrl, 1, data); + ret = get_registers(pegasus, PhyCtrl, 1, data); if (data[0] & PHY_DONE) break; } if (i < REG_TIMEOUT) return 0; - warn("%s: failed", __FUNCTION__); + if (netif_msg_drv(pegasus)) + dev_warn(&pegasus->intf->dev, "fail %s\n", __FUNCTION__); return 1; } @@ -350,23 +375,25 @@ int i; __u8 tmp; __le16 retdatai; + int ret; - set_register(pegasus, EpromCtrl, 0); - set_register(pegasus, EpromOffset, index); - set_register(pegasus, EpromCtrl, EPROM_READ); + ret = set_register(pegasus, EpromCtrl, 0); + ret = set_register(pegasus, EpromOffset, index); + ret = set_register(pegasus, EpromCtrl, EPROM_READ); for (i = 0; i < REG_TIMEOUT; i++) { - get_registers(pegasus, EpromCtrl, 1, &tmp); + ret = get_registers(pegasus, EpromCtrl, 1, &tmp); if (tmp & EPROM_DONE) break; } if (i < REG_TIMEOUT) { - get_registers(pegasus, EpromData, 2, &retdatai); + ret = get_registers(pegasus, EpromData, 2, &retdatai); *retdata = le16_to_cpu(retdatai); return 0; } - warn("%s: failed", __FUNCTION__); + if (netif_msg_drv(pegasus)) + dev_warn(&pegasus->intf->dev, "fail %s\n", __FUNCTION__); return -1; } @@ -374,40 +401,44 @@ static inline void enable_eprom_write(pegasus_t * pegasus) { __u8 tmp; + int ret; - get_registers(pegasus, EthCtrl2, 1, &tmp); - set_register(pegasus, EthCtrl2, tmp | EPROM_WR_ENABLE); + ret = get_registers(pegasus, EthCtrl2, 1, &tmp); + ret = set_register(pegasus, EthCtrl2, tmp | EPROM_WR_ENABLE); } static inline void disable_eprom_write(pegasus_t * pegasus) { __u8 tmp; + int ret; - get_registers(pegasus, EthCtrl2, 1, &tmp); - set_register(pegasus, EpromCtrl, 0); - set_register(pegasus, EthCtrl2, tmp & ~EPROM_WR_ENABLE); + ret = get_registers(pegasus, EthCtrl2, 1, &tmp); + ret = set_register(pegasus, EpromCtrl, 0); + ret = set_register(pegasus, EthCtrl2, tmp & ~EPROM_WR_ENABLE); } static int write_eprom_word(pegasus_t * pegasus, __u8 index, __u16 data) { int i; __u8 tmp, d[4] = { 0x3f, 0, 0, EPROM_WRITE }; + int ret; - set_registers(pegasus, EpromOffset, 4, d); + ret = set_registers(pegasus, EpromOffset, 4, d); enable_eprom_write(pegasus); - set_register(pegasus, EpromOffset, index); - set_registers(pegasus, EpromData, 2, &data); - set_register(pegasus, EpromCtrl, EPROM_WRITE); + ret = set_register(pegasus, EpromOffset, index); + ret = set_registers(pegasus, EpromData, 2, &data); + ret = set_register(pegasus, EpromCtrl, EPROM_WRITE); for (i = 0; i < REG_TIMEOUT; i++) { - get_registers(pegasus, EpromCtrl, 1, &tmp); + ret = get_registers(pegasus, EpromCtrl, 1, &tmp); if (tmp & EPROM_DONE) break; } disable_eprom_write(pegasus); if (i < REG_TIMEOUT) return 0; - warn("%s: failed", __FUNCTION__); + if (netif_msg_drv(pegasus)) + dev_warn(&pegasus->intf->dev, "fail %s\n", __FUNCTION__); return -1; } #endif /* PEGASUS_WRITE_EEPROM */ @@ -426,9 +457,10 @@ static void set_ethernet_addr(pegasus_t * pegasus) { __u8 node_id[6]; + int ret; get_node_id(pegasus, node_id); - set_registers(pegasus, EthID, sizeof (node_id), node_id); + ret = set_registers(pegasus, EthID, sizeof (node_id), node_id); memcpy(pegasus->net->dev_addr, node_id, sizeof (node_id)); } @@ -436,19 +468,20 @@ { __u8 data = 0x8; int i; + int ret; - set_register(pegasus, EthCtrl1, data); + ret = set_register(pegasus, EthCtrl1, data); for (i = 0; i < REG_TIMEOUT; i++) { - get_registers(pegasus, EthCtrl1, 1, &data); + ret = get_registers(pegasus, EthCtrl1, 1, &data); if (~data & 0x08) { if (loopback & 1) break; if (mii_mode && (pegasus->features & HAS_HOME_PNA)) - set_register(pegasus, Gpio1, 0x34); + ret = set_register(pegasus, Gpio1, 0x34); else - set_register(pegasus, Gpio1, 0x26); - set_register(pegasus, Gpio0, pegasus->features); - set_register(pegasus, Gpio0, DEFAULT_GPIO_SET); + ret = set_register(pegasus, Gpio1, 0x26); + ret = set_register(pegasus, Gpio0, pegasus->features); + ret = set_register(pegasus, Gpio0, DEFAULT_GPIO_SET); break; } } @@ -457,8 +490,8 @@ if (usb_dev_id[pegasus->dev_index].vendor == VENDOR_LINKSYS || usb_dev_id[pegasus->dev_index].vendor == VENDOR_DLINK) { - set_register(pegasus, Gpio0, 0x24); - set_register(pegasus, Gpio0, 0x26); + ret = set_register(pegasus, Gpio0, 0x24); + ret = set_register(pegasus, Gpio0, 0x26); } if (usb_dev_id[pegasus->dev_index].vendor == VENDOR_ELCON) { __u16 auxmode; @@ -474,6 +507,7 @@ __u16 linkpart; __u8 data[4]; pegasus_t *pegasus = netdev_priv(dev); + int ret; read_mii_word(pegasus, pegasus->phy, MII_LPA, &linkpart); data[0] = 0xc9; @@ -487,7 +521,7 @@ data[2] = (loopback & 1) ? 0x09 : 0x01; memcpy(pegasus->eth_regs, data, sizeof (data)); - set_registers(pegasus, EthCtrl0, 3, data); + ret = set_registers(pegasus, EthCtrl0, 3, data); if (usb_dev_id[pegasus->dev_index].vendor == VENDOR_LINKSYS || usb_dev_id[pegasus->dev_index].vendor == VENDOR_DLINK) { @@ -550,48 +584,56 @@ pegasus_t *pegasus = urb->context; struct net_device *net; int rx_status, count = urb->actual_length; + u8 *buf = urb->transfer_buffer; __u16 pkt_len; - if (!pegasus || !(pegasus->flags & PEGASUS_RUNNING)) + if (!pegasus) return; net = pegasus->net; - if (!netif_device_present(net)) + if (!netif_device_present(net) || !netif_running(net)) return; switch (urb->status) { case 0: break; case -ETIMEDOUT: - dbg("%s: reset MAC", net->name); + if (netif_msg_rx_err(pegasus)) + pr_debug("%s: reset MAC\n", net->name); pegasus->flags &= ~PEGASUS_RX_BUSY; break; case -EPIPE: /* stall, or disconnect from TT */ /* FIXME schedule work to clear the halt */ - warn("%s: no rx stall recovery", net->name); + if (netif_msg_rx_err(pegasus)) + printk(KERN_WARNING "%s: no rx stall recovery\n", + net->name); return; case -ENOENT: case -ECONNRESET: case -ESHUTDOWN: - dbg("%s: rx unlink, %d", net->name, urb->status); + if (netif_msg_ifdown(pegasus)) + pr_debug("%s: rx unlink, %d\n", net->name, urb->status); return; default: - dbg("%s: RX status %d", net->name, urb->status); + if (netif_msg_rx_err(pegasus)) + pr_debug("%s: RX status %d\n", net->name, urb->status); goto goon; } - if (!count) + if (!count || count < 4) goto goon; - rx_status = le32_to_cpu(*(__le32 *) (urb->transfer_buffer + count - 4)); - if (rx_status & 0x000e0000) { - dbg("%s: RX packet error %x", net->name, rx_status & 0xe0000); + rx_status = buf[count - 2]; + if (rx_status & 0x1e) { + if (netif_msg_rx_err(pegasus)) + pr_debug("%s: RX packet error %x\n", + net->name, rx_status); pegasus->stats.rx_errors++; - if (rx_status & 0x060000) + if (rx_status & 0x06) // long or runt pegasus->stats.rx_length_errors++; - if (rx_status & 0x080000) + if (rx_status & 0x08) pegasus->stats.rx_crc_errors++; - if (rx_status & 0x100000) + if (rx_status & 0x10) // extra bits pegasus->stats.rx_frame_errors++; goto goon; } @@ -600,7 +642,10 @@ pkt_len &= 0x0fff; pegasus->rx_skb->data += 2; } else { - pkt_len = (rx_status & 0xfff) - 8; + pkt_len = buf[count - 3] << 8; + pkt_len += buf[count - 4]; + pkt_len &= 0xfff; + pkt_len -= 8; } /* @@ -658,7 +703,9 @@ pegasus->rx_skb = pull_skb(pegasus); } if (pegasus->rx_skb == NULL) { - warn("wow, low on memory"); + if (netif_msg_rx_err(pegasus)) + printk(KERN_WARNING "%s: low on memory\n", + pegasus->net->name); tasklet_schedule(&pegasus->rx_tl); goto done; } @@ -682,25 +729,29 @@ pegasus_t *pegasus = urb->context; struct net_device *net = pegasus->net; - if (!pegasus || !(pegasus->flags & PEGASUS_RUNNING)) + if (!pegasus) return; - if (!netif_device_present(net)) + if (!netif_device_present(net) || !netif_running(net)) return; switch (urb->status) { case -EPIPE: /* FIXME schedule_work() to clear the tx halt */ netif_stop_queue(net); - warn("%s: no tx stall recovery", net->name); + if (netif_msg_tx_err(pegasus)) + printk(KERN_WARNING "%s: no tx stall recovery\n", + net->name); return; case -ENOENT: case -ECONNRESET: case -ESHUTDOWN: - dbg("%s: tx unlink, %d", net->name, urb->status); + if (netif_msg_ifdown(pegasus)) + pr_debug("%s: tx unlink, %d\n", net->name, urb->status); return; default: - info("%s: TX status %d", net->name, urb->status); + if (netif_msg_tx_err(pegasus)) + pr_info("%s: TX status %d\n", net->name, urb->status); /* FALL THROUGH */ case 0: break; @@ -731,7 +782,9 @@ /* some Pegasus-I products report LOTS of data * toggle errors... avoid log spamming */ - pr_debug("%s: intr status %d\n", net->name, urb->status); + if (netif_msg_timer(pegasus)) + pr_debug("%s: intr status %d\n", net->name, + urb->status); } if (urb->actual_length >= 6) { @@ -763,7 +816,7 @@ } status = usb_submit_urb(urb, SLAB_ATOMIC); - if (status) + if (status && netif_msg_timer(pegasus)) printk(KERN_ERR "%s: can't resubmit interrupt urb, %d\n", net->name, status); } @@ -771,7 +824,8 @@ static void pegasus_tx_timeout(struct net_device *net) { pegasus_t *pegasus = netdev_priv(net); - printk(KERN_WARNING "%s: tx timeout\n", net->name); + if (netif_msg_timer(pegasus)) + printk(KERN_WARNING "%s: tx timeout\n", net->name); pegasus->tx_urb->transfer_flags |= URB_ASYNC_UNLINK; usb_unlink_urb(pegasus->tx_urb); pegasus->stats.tx_errors++; @@ -793,7 +847,9 @@ pegasus->tx_buff, count, write_bulk_callback, pegasus); if ((res = usb_submit_urb(pegasus->tx_urb, GFP_ATOMIC))) { - warn("failed tx_urb %d", res); + if (netif_msg_tx_err(pegasus)) + printk(KERN_WARNING "%s: fail tx, %d\n", + net->name, res); switch (res) { case -EPIPE: /* stall, or disconnect from TT */ /* cleanup should already have been scheduled */ @@ -822,8 +878,9 @@ static inline void disable_net_traffic(pegasus_t * pegasus) { int tmp = 0; + int ret; - set_registers(pegasus, EthCtrl0, 2, &tmp); + ret = set_registers(pegasus, EthCtrl0, 2, &tmp); } static inline void get_interrupt_interval(pegasus_t * pegasus) @@ -832,8 +889,10 @@ read_eprom_word(pegasus, 4, (__u16 *) data); if (data[1] < 0x80) { - info("intr interval will be changed from %ums to %ums", - data[1], 0x80); + if (netif_msg_timer(pegasus)) + dev_info(&pegasus->intf->dev, + "intr interval changed from %ums to %ums\n", + data[1], 0x80); data[1] = 0x80; #ifdef PEGASUS_WRITE_EEPROM write_eprom_word(pegasus, 4, *(__u16 *) data); @@ -845,7 +904,7 @@ static void set_carrier(struct net_device *net) { pegasus_t *pegasus = netdev_priv(net); - __le16 tmp; + u16 tmp; if (read_mii_word(pegasus, pegasus->phy, MII_BMSR, &tmp)) return; @@ -912,24 +971,32 @@ if (!pegasus->rx_skb) return -ENOMEM; - set_registers(pegasus, EthID, 6, net->dev_addr); + res = set_registers(pegasus, EthID, 6, net->dev_addr); usb_fill_bulk_urb(pegasus->rx_urb, pegasus->usb, usb_rcvbulkpipe(pegasus->usb, 1), pegasus->rx_skb->data, PEGASUS_MTU + 8, read_bulk_callback, pegasus); - if ((res = usb_submit_urb(pegasus->rx_urb, GFP_KERNEL))) - warn("%s: failed rx_urb %d", __FUNCTION__, res); + if ((res = usb_submit_urb(pegasus->rx_urb, GFP_KERNEL))) { + if (netif_msg_ifup(pegasus)) + pr_debug("%s: failed rx_urb, %d", net->name, res); + goto exit; + } + usb_fill_int_urb(pegasus->intr_urb, pegasus->usb, usb_rcvintpipe(pegasus->usb, 3), pegasus->intr_buff, sizeof (pegasus->intr_buff), intr_callback, pegasus, pegasus->intr_interval); - if ((res = usb_submit_urb(pegasus->intr_urb, GFP_KERNEL))) - warn("%s: failed intr_urb %d", __FUNCTION__, res); - netif_start_queue(net); - pegasus->flags |= PEGASUS_RUNNING; + if ((res = usb_submit_urb(pegasus->intr_urb, GFP_KERNEL))) { + if (netif_msg_ifup(pegasus)) + pr_debug("%s: failed intr_urb, %d\n", net->name, res); + usb_kill_urb(pegasus->rx_urb); + goto exit; + } if ((res = enable_net_traffic(net, pegasus->usb))) { - err("can't enable_net_traffic() - %d", res); + if (netif_msg_ifup(pegasus)) + pr_debug("%s: can't enable_net_traffic() - %d\n", + net->name, res); res = -EIO; usb_kill_urb(pegasus->rx_urb); usb_kill_urb(pegasus->intr_urb); @@ -937,6 +1004,9 @@ goto exit; } set_carrier(net); + netif_start_queue(net); + if (netif_msg_ifup(pegasus)) + pr_debug("%s: open\n", net->name); res = 0; exit: return res; @@ -946,7 +1016,6 @@ { pegasus_t *pegasus = netdev_priv(net); - pegasus->flags &= ~PEGASUS_RUNNING; netif_stop_queue(net); if (!(pegasus->flags & PEGASUS_UNPLUG)) disable_net_traffic(pegasus); @@ -956,7 +1025,8 @@ return 0; } -void pegasus_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) +static void pegasus_get_drvinfo(struct net_device *dev, + struct ethtool_drvinfo *info) { pegasus_t *pegasus = netdev_priv(dev); strncpy(info->driver, driver_name, sizeof (info->driver) - 1); @@ -989,6 +1059,7 @@ reg78 |= 0x80; if (wol->wolopts & WAKE_PHY) reg78 |= 0x40; + /* FIXME this 0x10 bit still needs to get set in the chip... */ if (wol->wolopts) pegasus->eth_regs[0] |= 0x10; else @@ -1041,13 +1112,13 @@ static u32 pegasus_get_msglevel(struct net_device *dev) { pegasus_t *pegasus = netdev_priv(dev); - return pegasus->msg_level; + return pegasus->msg_enable; } static void pegasus_set_msglevel(struct net_device *dev, u32 v) { pegasus_t *pegasus = netdev_priv(dev); - pegasus->msg_level = v; + pegasus->msg_enable = v; } static struct ethtool_ops ops = { @@ -1093,12 +1164,14 @@ if (net->flags & IFF_PROMISC) { pegasus->eth_regs[EthCtrl2] |= RX_PROMISCUOUS; - pr_info("%s: Promiscuous mode enabled.\n", net->name); + if (netif_msg_link(pegasus)) + pr_info("%s: Promiscuous mode enabled.\n", net->name); } else if ((net->mc_count > multicast_filter_limit) || (net->flags & IFF_ALLMULTI)) { pegasus->eth_regs[EthCtrl0] |= RX_MULTICAST; pegasus->eth_regs[EthCtrl2] &= ~RX_PROMISCUOUS; - pr_info("%s: set allmulti\n", net->name); + if (netif_msg_link(pegasus)) + pr_info("%s: set allmulti\n", net->name); } else { pegasus->eth_regs[EthCtrl0] &= ~RX_MULTICAST; pegasus->eth_regs[EthCtrl2] &= ~RX_PROMISCUOUS; @@ -1127,17 +1200,18 @@ static inline void setup_pegasus_II(pegasus_t * pegasus) { __u8 data = 0xa5; + int ret; - set_register(pegasus, Reg1d, 0); - set_register(pegasus, Reg7b, 1); + ret = set_register(pegasus, Reg1d, 0); + ret = set_register(pegasus, Reg7b, 1); mdelay(100); if ((pegasus->features & HAS_HOME_PNA) && mii_mode) - set_register(pegasus, Reg7b, 0); + ret = set_register(pegasus, Reg7b, 0); else - set_register(pegasus, Reg7b, 2); + ret = set_register(pegasus, Reg7b, 2); - set_register(pegasus, 0x83, data); - get_registers(pegasus, 0x83, 1, &data); + ret = set_register(pegasus, 0x83, data); + ret = get_registers(pegasus, 0x83, 1, &data); if (data == 0xa5) { pegasus->chip = 0x8513; @@ -1145,21 +1219,21 @@ pegasus->chip = 0; } - set_register(pegasus, 0x80, 0xc0); - set_register(pegasus, 0x83, 0xff); - set_register(pegasus, 0x84, 0x01); + ret = set_register(pegasus, 0x80, 0xc0); + ret = set_register(pegasus, 0x83, 0xff); + ret = set_register(pegasus, 0x84, 0x01); if (pegasus->features & HAS_HOME_PNA && mii_mode) - set_register(pegasus, Reg81, 6); + ret = set_register(pegasus, Reg81, 6); else - set_register(pegasus, Reg81, 2); + ret = set_register(pegasus, Reg81, 2); } -struct workqueue_struct *pegasus_workqueue = NULL; +static struct workqueue_struct *pegasus_workqueue = NULL; #define CARRIER_CHECK_DELAY (2 * HZ) -void check_carrier(void *data) +static void check_carrier(void *data) { pegasus_t *pegasus = data; set_carrier(pegasus->net); @@ -1181,7 +1255,7 @@ usb_get_dev(dev); net = alloc_etherdev(sizeof(struct pegasus)); if (!net) { - err("out of memory allocating device structure"); + dev_err(&intf->dev, "can't allocate %s\n", "device"); goto out; } @@ -1190,13 +1264,16 @@ pegasus->dev_index = dev_index; init_waitqueue_head(&pegasus->ctrl_wait); - if (!alloc_urbs(pegasus)) + if (!alloc_urbs(pegasus)) { + dev_err(&intf->dev, "can't allocate %s\n", "urbs"); goto out1; + } tasklet_init(&pegasus->rx_tl, rx_fixup, (unsigned long) pegasus); INIT_WORK(&pegasus->carrier_check, check_carrier, pegasus); + pegasus->intf = intf; pegasus->usb = dev; pegasus->net = net; SET_MODULE_OWNER(net); @@ -1215,6 +1292,8 @@ pegasus->mii.phy_id_mask = 0x1f; pegasus->mii.reg_num_mask = 0x1f; spin_lock_init(&pegasus->rx_pool_lock); + pegasus->msg_enable = netif_msg_init (msg_level, NETIF_MSG_DRV + | NETIF_MSG_PROBE | NETIF_MSG_LINK); pegasus->features = usb_dev_id[dev_index].private; get_interrupt_interval(pegasus); @@ -1241,8 +1320,15 @@ res = register_netdev(net); if (res) goto out3; - queue_delayed_work(pegasus_workqueue, &pegasus->carrier_check, CARRIER_CHECK_DELAY); - pr_info("%s: %s\n", net->name, usb_dev_id[dev_index].name); + queue_delayed_work(pegasus_workqueue, &pegasus->carrier_check, + CARRIER_CHECK_DELAY); + + dev_info(&intf->dev, "%s, %s, %02x:%02x:%02x:%02x:%02x:%02x\n", + net->name, + usb_dev_id[dev_index].name, + net->dev_addr [0], net->dev_addr [1], + net->dev_addr [2], net->dev_addr [3], + net->dev_addr [4], net->dev_addr [5]); return 0; out3: @@ -1263,7 +1349,7 @@ usb_set_intfdata(intf, NULL); if (!pegasus) { - warn("unregistering non-existent device"); + dev_dbg(&intf->dev, "unregistering non-bound device?\n"); return; } diff -Nru a/drivers/usb/net/pegasus.h b/drivers/usb/net/pegasus.h --- a/drivers/usb/net/pegasus.h 2005-03-24 18:21:08 -08:00 +++ b/drivers/usb/net/pegasus.h 2005-03-24 18:21:08 -08:00 @@ -29,7 +29,6 @@ #define DEFAULT_GPIO_SET 0x26 #define PEGASUS_PRESENT 0x00000001 -#define PEGASUS_RUNNING 0x00000002 #define PEGASUS_TX_BUSY 0x00000004 #define PEGASUS_RX_BUSY 0x00000008 #define CTRL_URB_RUNNING 0x00000010 @@ -86,12 +85,13 @@ typedef struct pegasus { struct usb_device *usb; + struct usb_interface *intf; struct net_device *net; struct net_device_stats stats; struct mii_if_info mii; unsigned flags; unsigned features; - u32 msg_level; + u32 msg_enable; u32 wolopts; int dev_index; int intr_interval; diff -Nru a/drivers/usb/net/usbnet.c b/drivers/usb/net/usbnet.c --- a/drivers/usb/net/usbnet.c 2005-03-24 18:21:08 -08:00 +++ b/drivers/usb/net/usbnet.c 2005-03-24 18:21:08 -08:00 @@ -185,13 +185,14 @@ // i/o info: pipes etc unsigned in, out; + struct usb_host_endpoint *status; unsigned maxpacket; struct timer_list delay; // protocol/interface state struct net_device *net; struct net_device_stats stats; - int msg_level; + int msg_enable; unsigned long data [5]; struct mii_if_info mii; @@ -200,6 +201,7 @@ struct sk_buff_head rxq; struct sk_buff_head txq; struct sk_buff_head done; + struct urb *interrupt; struct tasklet_struct bh; struct work_struct kevent; @@ -207,6 +209,7 @@ # define EVENT_TX_HALT 0 # define EVENT_RX_HALT 1 # define EVENT_RX_MEMORY 2 +# define EVENT_STS_SPLIT 3 }; // device-specific info used by the driver @@ -237,6 +240,9 @@ /* see if peer is connected ... can sleep */ int (*check_connect)(struct usbnet *); + /* for status polling */ + void (*status)(struct usbnet *, struct urb *); + /* fixup rx packet (strip framing) */ int (*rx_fixup)(struct usbnet *dev, struct sk_buff *skb); @@ -272,9 +278,9 @@ static const char driver_name [] = "usbnet"; /* use ethtool to change the level for any given device */ -static int msg_level = 1; +static int msg_level = -1; module_param (msg_level, int, 0); -MODULE_PARM_DESC (msg_level, "Initial message level (default = 1)"); +MODULE_PARM_DESC (msg_level, "Override default message level"); #ifdef DEBUG @@ -290,9 +296,7 @@ printk(KERN_WARNING "%s: " fmt "\n" , (usbnet)->net->name , ## arg) #define devinfo(usbnet, fmt, arg...) \ - do { if ((usbnet)->msg_level >= 1) \ printk(KERN_INFO "%s: " fmt "\n" , (usbnet)->net->name , ## arg); \ - } while (0) /*-------------------------------------------------------------------------*/ @@ -312,38 +316,52 @@ get_endpoints (struct usbnet *dev, struct usb_interface *intf) { int tmp; - struct usb_host_interface *alt; - struct usb_host_endpoint *in, *out; + struct usb_host_interface *alt = NULL; + struct usb_host_endpoint *in = NULL, *out = NULL; + struct usb_host_endpoint *status = NULL; for (tmp = 0; tmp < intf->num_altsetting; tmp++) { unsigned ep; - in = out = NULL; + in = out = status = NULL; alt = intf->altsetting + tmp; /* take the first altsetting with in-bulk + out-bulk; + * remember any status endpoint, just in case; * ignore other endpoints and altsetttings. */ for (ep = 0; ep < alt->desc.bNumEndpoints; ep++) { struct usb_host_endpoint *e; + int intr = 0; e = alt->endpoint + ep; - if (e->desc.bmAttributes != USB_ENDPOINT_XFER_BULK) + switch (e->desc.bmAttributes) { + case USB_ENDPOINT_XFER_INT: + if (!(e->desc.bEndpointAddress & USB_DIR_IN)) + continue; + intr = 1; + /* FALLTHROUGH */ + case USB_ENDPOINT_XFER_BULK: + break; + default: continue; + } if (e->desc.bEndpointAddress & USB_DIR_IN) { - if (!in) + if (!intr && !in) in = e; + else if (intr && !status) + status = e; } else { if (!out) out = e; } - if (in && out) - goto found; } + if (in && out) + break; } - return -EINVAL; + if (!alt || !in || !out) + return -EINVAL; -found: if (alt->desc.bAlternateSetting != 0 || !(dev->driver_info->flags & FLAG_NO_SETINT)) { tmp = usb_set_interface (dev->udev, alt->desc.bInterfaceNumber, @@ -356,9 +374,48 @@ in->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK); dev->out = usb_sndbulkpipe (dev->udev, out->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK); + dev->status = status; return 0; } +static void intr_complete (struct urb *urb, struct pt_regs *regs); + +static int init_status (struct usbnet *dev, struct usb_interface *intf) +{ + char *buf = NULL; + unsigned pipe = 0; + unsigned maxp; + unsigned period; + + if (!dev->driver_info->status) + return 0; + + pipe = usb_rcvintpipe (dev->udev, + dev->status->desc.bEndpointAddress + & USB_ENDPOINT_NUMBER_MASK); + maxp = usb_maxpacket (dev->udev, pipe, 0); + + /* avoid 1 msec chatter: min 8 msec poll rate */ + period = max ((int) dev->status->desc.bInterval, + (dev->udev->speed == USB_SPEED_HIGH) ? 7 : 3); + + buf = kmalloc (maxp, SLAB_KERNEL); + if (buf) { + dev->interrupt = usb_alloc_urb (0, SLAB_KERNEL); + if (!dev->interrupt) { + kfree (buf); + return -ENOMEM; + } else { + usb_fill_int_urb(dev->interrupt, dev->udev, pipe, + buf, maxp, intr_complete, dev, period); + dev_dbg(&intf->dev, + "status ep%din, %d bytes period %d\n", + usb_pipeendpoint(pipe), maxp, period); + } + } + return 0; +} + static void skb_return (struct usbnet *dev, struct sk_buff *skb) { int status; @@ -368,13 +425,12 @@ dev->stats.rx_packets++; dev->stats.rx_bytes += skb->len; -#ifdef VERBOSE - devdbg (dev, "< rx, len %d, type 0x%x", - skb->len + sizeof (struct ethhdr), skb->protocol); -#endif + if (netif_msg_rx_status (dev)) + devdbg (dev, "< rx, len %d, type 0x%x", + skb->len + sizeof (struct ethhdr), skb->protocol); memset (skb->cb, 0, sizeof (struct skb_data)); status = netif_rx (skb); - if (status != NET_RX_SUCCESS) + if (status != NET_RX_SUCCESS && netif_msg_rx_err (dev)) devdbg (dev, "netif_rx status %d", status); } @@ -1414,6 +1470,29 @@ usb_driver_release_interface (&usbnet_driver, info->data); return status; } + + /* status endpoint: optional for CDC Ethernet, not RNDIS (or ACM) */ + dev->status = NULL; + if (info->control->cur_altsetting->desc.bNumEndpoints == 1) { + struct usb_endpoint_descriptor *desc; + + dev->status = &info->control->cur_altsetting->endpoint [0]; + desc = &dev->status->desc; + if (desc->bmAttributes != USB_ENDPOINT_XFER_INT + || !(desc->bEndpointAddress & USB_DIR_IN) + || (le16_to_cpu(desc->wMaxPacketSize) + < sizeof (struct usb_cdc_notification)) + || !desc->bInterval) { + dev_dbg (&intf->dev, "bad notification endpoint\n"); + dev->status = NULL; + } + } + if (rndis && !dev->status) { + dev_dbg (&intf->dev, "missing RNDIS status endpoint\n"); + usb_set_intfdata(info->data, NULL); + usb_driver_release_interface (&usbnet_driver, info->data); + return -ENODEV; + } return 0; bad_desc: @@ -1442,6 +1521,56 @@ } } + +static void dumpspeed (struct usbnet *dev, __le32 *speeds) +{ + if (netif_msg_timer (dev)) + devinfo (dev, "link speeds: %u kbps up, %u kbps down", + __le32_to_cpu(speeds[0]) / 1000, + __le32_to_cpu(speeds[1]) / 1000); +} + +static void cdc_status (struct usbnet *dev, struct urb *urb) +{ + struct usb_cdc_notification *event; + + if (urb->actual_length < sizeof *event) + return; + + /* SPEED_CHANGE can get split into two 8-byte packets */ + if (test_and_clear_bit (EVENT_STS_SPLIT, &dev->flags)) { + dumpspeed (dev, (__le32 *) urb->transfer_buffer); + return; + } + + event = urb->transfer_buffer; + switch (event->bNotificationType) { + case USB_CDC_NOTIFY_NETWORK_CONNECTION: + if (netif_msg_timer (dev)) + devdbg (dev, "CDC: carrier %s", + event->wValue ? "on" : "off"); + if (event->wValue) + netif_carrier_on(dev->net); + else + netif_carrier_off(dev->net); + break; + case USB_CDC_NOTIFY_SPEED_CHANGE: /* tx/rx rates */ + if (netif_msg_timer (dev)) + devdbg (dev, "CDC: speed change (len %d)", + urb->actual_length); + if (urb->actual_length != (sizeof *event + 8)) + set_bit (EVENT_STS_SPLIT, &dev->flags); + else + dumpspeed (dev, (__le32 *) &event[1]); + break; + // case USB_CDC_NOTIFY_RESPONSE_AVAILABLE: /* RNDIS; or unsolicited */ + default: + deverr (dev, "CDC: unexpected notification %02x!", + event->bNotificationType); + break; + } +} + #endif /* NEED_GENERIC_CDC */ @@ -1520,6 +1649,7 @@ // .check_connect = cdc_check_connect, .bind = cdc_bind, .unbind = cdc_unbind, + .status = cdc_status, }; #endif /* CONFIG_USB_CDCETHER */ @@ -2051,7 +2181,8 @@ static inline void nc_dump_usbctl (struct usbnet *dev, u16 usbctl) { -#ifdef DEBUG + if (!netif_msg_link (dev)) + return; devdbg (dev, "net1080 %s-%s usbctl 0x%x:%s%s%s%s%s;" " this%s%s;" " other%s%s; r/o 0x%x", @@ -2069,7 +2200,6 @@ (usbctl & USBCTL_DISCONN_THIS) ? " DIS" : "", usbctl & ~USBCTL_WRITABLE_MASK ); -#endif } /*-------------------------------------------------------------------------*/ @@ -2096,7 +2226,8 @@ static inline void nc_dump_status (struct usbnet *dev, u16 status) { -#ifdef DEBUG + if (!netif_msg_link (dev)) + return; devdbg (dev, "net1080 %s-%s status 0x%x:" " this (%c) PKT=%d%s%s%s;" " other PKT=%d%s%s%s; unspec 0x%x", @@ -2119,7 +2250,6 @@ status & STATUS_UNSPEC_MASK ); -#endif } /*-------------------------------------------------------------------------*/ @@ -2134,15 +2264,10 @@ static inline void nc_dump_ttl (struct usbnet *dev, u16 ttl) { -#ifdef DEBUG - devdbg (dev, "net1080 %s-%s ttl 0x%x this = %d, other = %d", - dev->udev->bus->bus_name, dev->udev->devpath, - ttl, - - TTL_THIS (ttl), - TTL_OTHER (ttl) - ); -#endif + if (netif_msg_link (dev)) + devdbg (dev, "net1080 %s-%s ttl 0x%x this = %d, other = %d", + dev->udev->bus->bus_name, dev->udev->devpath, + ttl, TTL_THIS (ttl), TTL_OTHER (ttl)); } /*-------------------------------------------------------------------------*/ @@ -2164,14 +2289,14 @@ goto done; } status = *vp; - // nc_dump_status (dev, status); + nc_dump_status (dev, status); if ((retval = nc_register_read (dev, REG_USBCTL, vp)) < 0) { dbg ("can't read USBCTL, %d", retval); goto done; } usbctl = *vp; - // nc_dump_usbctl (dev, usbctl); + nc_dump_usbctl (dev, usbctl); nc_register_write (dev, REG_USBCTL, USBCTL_FLUSH_THIS | USBCTL_FLUSH_OTHER); @@ -2187,7 +2312,7 @@ MK_TTL (NC_READ_TTL_MS, TTL_OTHER (ttl)) ); dbg ("%s: assigned TTL, %d ms", dev->net->name, NC_READ_TTL_MS); - if (dev->msg_level >= 2) + if (netif_msg_link (dev)) devinfo (dev, "port %c, peer %sconnected", (status & STATUS_PORT_A) ? 'A' : 'B', (status & STATUS_CONN_OTHER) ? "" : "dis" @@ -2268,7 +2393,8 @@ return; } - devdbg (dev, "flush net1080; too many framing errors"); + if (netif_msg_rx_err (dev)) + devdbg (dev, "flush net1080; too many framing errors"); dev->frame_errors = 0; } } @@ -2526,11 +2652,17 @@ * For the current version of that driver, the main way that framing is * nonstandard (also from perspective of the CDC ethernet model!) is a * crc32, added to help detect when some sa1100 usb-to-memory DMA errata - * haven't been fully worked around. + * haven't been fully worked around. Also, all Zaurii use the same + * default Ethernet address. * * PXA based models use the same framing, and also can't implement * set_interface properly. * + * All known Zaurii lie about their standards conformance. Most lie by + * saying they support CDC Ethernet. Some lie and say they support CDC + * MDLM (as if for access to cell phone modems). Someone, please beat + * on Sharp for a while with a cluestick. + * *-------------------------------------------------------------------------*/ static struct sk_buff * @@ -2582,6 +2714,13 @@ }; #define ZAURUS_PXA_INFO ((unsigned long)&zaurus_pxa_info) +static const struct driver_info zaurus_pxa_mdlm_info = { + .description = "Sharp Zaurus, PXA-255 based", + .flags = FLAG_FRAMING_Z, + .check_connect = always_connected, + .tx_fixup = zaurus_tx_fixup, +}; + static const struct driver_info olympus_mxl_info = { .description = "Olympus R1000", .flags = FLAG_FRAMING_Z, @@ -2715,7 +2854,8 @@ size = (sizeof (struct ethhdr) + dev->net->mtu); if ((skb = alloc_skb (size + NET_IP_ALIGN, flags)) == NULL) { - devdbg (dev, "no rx skb"); + if (netif_msg_rx_err (dev)) + devdbg (dev, "no rx skb"); defer_kevent (dev, EVENT_RX_MEMORY); usb_free_urb (urb); return; @@ -2745,18 +2885,21 @@ defer_kevent (dev, EVENT_RX_MEMORY); break; case -ENODEV: - devdbg (dev, "device gone"); + if (netif_msg_ifdown (dev)) + devdbg (dev, "device gone"); netif_device_detach (dev->net); break; default: - devdbg (dev, "rx submit, %d", retval); + if (netif_msg_rx_err (dev)) + devdbg (dev, "rx submit, %d", retval); tasklet_schedule (&dev->bh); break; case 0: __skb_queue_tail (&dev->rxq, skb); } } else { - devdbg (dev, "rx: stopped"); + if (netif_msg_ifdown (dev)) + devdbg (dev, "rx: stopped"); retval = -ENOLINK; } spin_unlock_irqrestore (&dev->rxq.lock, lockflags); @@ -2779,7 +2922,8 @@ if (skb->len) skb_return (dev, skb); else { - devdbg (dev, "drop"); + if (netif_msg_rx_err (dev)) + devdbg (dev, "drop"); error: dev->stats.rx_errors++; skb_queue_tail (&dev->done, skb); @@ -2806,7 +2950,8 @@ entry->state = rx_cleanup; dev->stats.rx_errors++; dev->stats.rx_length_errors++; - devdbg (dev, "rx length %d", skb->len); + if (netif_msg_rx_err (dev)) + devdbg (dev, "rx length %d", skb->len); } break; @@ -2822,9 +2967,8 @@ // software-driven interface shutdown case -ECONNRESET: // async unlink case -ESHUTDOWN: // hardware gone -#ifdef VERBOSE - devdbg (dev, "rx shutdown, code %d", urb_status); -#endif + if (netif_msg_ifdown (dev)) + devdbg (dev, "rx shutdown, code %d", urb_status); goto block; // we get controller i/o faults during khubd disconnect() delays. @@ -2836,7 +2980,8 @@ dev->stats.rx_errors++; if (!timer_pending (&dev->delay)) { mod_timer (&dev->delay, jiffies + THROTTLE_JIFFIES); - devdbg (dev, "rx throttle %d", urb_status); + if (netif_msg_link (dev)) + devdbg (dev, "rx throttle %d", urb_status); } block: entry->state = rx_cleanup; @@ -2852,7 +2997,8 @@ default: entry->state = rx_cleanup; dev->stats.rx_errors++; - devdbg (dev, "rx status %d", urb_status); + if (netif_msg_rx_err (dev)) + devdbg (dev, "rx status %d", urb_status); break; } @@ -2866,9 +3012,43 @@ } usb_free_urb (urb); } -#ifdef VERBOSE - devdbg (dev, "no read resubmitted"); -#endif /* VERBOSE */ + if (netif_msg_rx_err (dev)) + devdbg (dev, "no read resubmitted"); +} + +static void intr_complete (struct urb *urb, struct pt_regs *regs) +{ + struct usbnet *dev = urb->context; + int status = urb->status; + + switch (status) { + /* success */ + case 0: + dev->driver_info->status(dev, urb); + break; + + /* software-driven interface shutdown */ + case -ENOENT: // urb killed + case -ESHUTDOWN: // hardware gone + if (netif_msg_ifdown (dev)) + devdbg (dev, "intr shutdown, code %d", status); + return; + + /* NOTE: not throttling like RX/TX, since this endpoint + * already polls infrequently + */ + default: + devdbg (dev, "intr status %d", status); + break; + } + + if (!netif_running (dev->net)) + return; + + memset(urb->transfer_buffer, 0, urb->transfer_buffer_length); + status = usb_submit_urb (urb, GFP_ATOMIC); + if (status != 0 && netif_msg_timer (dev)) + deverr(dev, "intr resubmit --> %d", status); } /*-------------------------------------------------------------------------*/ @@ -2917,7 +3097,7 @@ netif_stop_queue (net); - if (dev->msg_level >= 2) + if (netif_msg_ifdown (dev)) devinfo (dev, "stop stats: rx/tx %ld/%ld, errs %ld/%ld", dev->stats.rx_packets, dev->stats.tx_packets, dev->stats.rx_errors, dev->stats.tx_errors @@ -2933,11 +3113,14 @@ && skb_queue_len (&dev->txq) && skb_queue_len (&dev->done)) { msleep(UNLINK_TIMEOUT_MS); - devdbg (dev, "waited for %d urb completions", temp); + if (netif_msg_ifdown (dev)) + devdbg (dev, "waited for %d urb completions", temp); } dev->wait = NULL; remove_wait_queue (&unlink_wakeup, &wait); + usb_kill_urb(dev->interrupt); + /* deferred work (task, timer, softirq) must also stop. * can't flush_scheduled_work() until we drop rtnl (later), * else workers could deadlock; so make workers a NOP. @@ -2963,21 +3146,34 @@ // put into "known safe" state if (info->reset && (retval = info->reset (dev)) < 0) { - devinfo (dev, "open reset fail (%d) usbnet usb-%s-%s, %s", - retval, - dev->udev->bus->bus_name, dev->udev->devpath, + if (netif_msg_ifup (dev)) + devinfo (dev, + "open reset fail (%d) usbnet usb-%s-%s, %s", + retval, + dev->udev->bus->bus_name, dev->udev->devpath, info->description); goto done; } // insist peer be connected if (info->check_connect && (retval = info->check_connect (dev)) < 0) { - devdbg (dev, "can't open; %d", retval); + if (netif_msg_ifup (dev)) + devdbg (dev, "can't open; %d", retval); goto done; } + /* start any status interrupt transfer */ + if (dev->interrupt) { + retval = usb_submit_urb (dev->interrupt, GFP_KERNEL); + if (retval < 0) { + if (netif_msg_ifup (dev)) + deverr (dev, "intr submit %d", retval); + goto done; + } + } + netif_start_queue (net); - if (dev->msg_level >= 2) { + if (netif_msg_ifup (dev)) { char *framing; if (dev->driver_info->flags & FLAG_FRAMING_NC) @@ -3034,14 +3230,14 @@ { struct usbnet *dev = netdev_priv(net); - return dev->msg_level; + return dev->msg_enable; } static void usbnet_set_msglevel (struct net_device *net, u32 level) { struct usbnet *dev = netdev_priv(net); - dev->msg_level = level; + dev->msg_enable = level; } static int usbnet_ioctl (struct net_device *net, struct ifreq *rq, int cmd) @@ -3074,10 +3270,11 @@ if (test_bit (EVENT_TX_HALT, &dev->flags)) { unlink_urbs (dev, &dev->txq); status = usb_clear_halt (dev->udev, dev->out); - if (status < 0 && status != -EPIPE) - deverr (dev, "can't clear tx halt, status %d", - status); - else { + if (status < 0 && status != -EPIPE) { + if (netif_msg_tx_err (dev)) + deverr (dev, "can't clear tx halt, status %d", + status); + } else { clear_bit (EVENT_TX_HALT, &dev->flags); netif_wake_queue (dev->net); } @@ -3085,10 +3282,11 @@ if (test_bit (EVENT_RX_HALT, &dev->flags)) { unlink_urbs (dev, &dev->rxq); status = usb_clear_halt (dev->udev, dev->in); - if (status < 0 && status != -EPIPE) - deverr (dev, "can't clear rx halt, status %d", - status); - else { + if (status < 0 && status != -EPIPE) { + if (netif_msg_rx_err (dev)) + deverr (dev, "can't clear rx halt, status %d", + status); + } else { clear_bit (EVENT_RX_HALT, &dev->flags); tasklet_schedule (&dev->bh); } @@ -3133,6 +3331,11 @@ defer_kevent (dev, EVENT_TX_HALT); break; + /* software-driven interface shutdown */ + case -ECONNRESET: // async unlink + case -ESHUTDOWN: // hardware gone + break; + // like rx, tx gets controller i/o faults during khubd delays // and so it uses the same throttling mechanism. case -EPROTO: // ehci @@ -3141,12 +3344,15 @@ if (!timer_pending (&dev->delay)) { mod_timer (&dev->delay, jiffies + THROTTLE_JIFFIES); - devdbg (dev, "tx throttle %d", urb->status); + if (netif_msg_link (dev)) + devdbg (dev, "tx throttle %d", + urb->status); } netif_stop_queue (dev->net); break; default: - devdbg (dev, "tx err %d", entry->urb->status); + if (netif_msg_tx_err (dev)) + devdbg (dev, "tx err %d", entry->urb->status); break; } } @@ -3189,14 +3395,16 @@ if (info->tx_fixup) { skb = info->tx_fixup (dev, skb, GFP_ATOMIC); if (!skb) { - devdbg (dev, "can't tx_fixup skb"); + if (netif_msg_tx_err (dev)) + devdbg (dev, "can't tx_fixup skb"); goto drop; } } length = skb->len; if (!(urb = usb_alloc_urb (0, GFP_ATOMIC))) { - devdbg (dev, "no urb"); + if (netif_msg_tx_err (dev)) + devdbg (dev, "no urb"); goto drop; } @@ -3254,7 +3462,8 @@ defer_kevent (dev, EVENT_TX_HALT); break; default: - devdbg (dev, "tx: submit urb err %d", retval); + if (netif_msg_tx_err (dev)) + devdbg (dev, "tx: submit urb err %d", retval); break; case 0: net->trans_start = jiffies; @@ -3265,18 +3474,17 @@ spin_unlock_irqrestore (&dev->txq.lock, flags); if (retval) { - devdbg (dev, "drop, code %d", retval); + if (netif_msg_tx_err (dev)) + devdbg (dev, "drop, code %d", retval); drop: retval = NET_XMIT_SUCCESS; dev->stats.tx_dropped++; if (skb) dev_kfree_skb_any (skb); usb_free_urb (urb); -#ifdef VERBOSE - } else { + } else if (netif_msg_tx_queued (dev)) { devdbg (dev, "> tx, len %d, type 0x%x", length, skb->protocol); -#endif } return retval; } @@ -3333,7 +3541,7 @@ if (urb != NULL) rx_submit (dev, urb, GFP_ATOMIC); } - if (temp != dev->rxq.qlen) + if (temp != dev->rxq.qlen && netif_msg_link (dev)) devdbg (dev, "rxqlen %d --> %d", temp, dev->rxq.qlen); if (dev->rxq.qlen < qlen) @@ -3367,9 +3575,10 @@ xdev = interface_to_usbdev (intf); - devinfo (dev, "unregister usbnet usb-%s-%s, %s", - xdev->bus->bus_name, xdev->devpath, - dev->driver_info->description); + if (netif_msg_probe (dev)) + devinfo (dev, "unregister usbnet usb-%s-%s, %s", + xdev->bus->bus_name, xdev->devpath, + dev->driver_info->description); net = dev->net; unregister_netdev (net); @@ -3423,7 +3632,8 @@ dev = netdev_priv(net); dev->udev = xdev; dev->driver_info = info; - dev->msg_level = msg_level; + dev->msg_enable = netif_msg_init (msg_level, NETIF_MSG_DRV + | NETIF_MSG_PROBE | NETIF_MSG_LINK); skb_queue_head_init (&dev->rxq); skb_queue_head_init (&dev->txq); skb_queue_head_init (&dev->done); @@ -3442,7 +3652,7 @@ #if 0 // dma_supported() is deeply broken on almost all architectures // possible with some EHCI controllers - if (dma_supported (&udev->dev, 0xffffffffffffffffULL)) + if (dma_supported (&udev->dev, DMA_64BIT_MASK)) net->features |= NETIF_F_HIGHDMA; #endif @@ -3479,6 +3689,9 @@ status = 0; } + + if (status == 0 && dev->status) + status = init_status (dev, udev); if (status < 0) goto out1; @@ -3488,9 +3701,14 @@ status = register_netdev (net); if (status) goto out3; - devinfo (dev, "register usbnet at usb-%s-%s, %s", - xdev->bus->bus_name, xdev->devpath, - dev->driver_info->description); + if (netif_msg_probe (dev)) + devinfo (dev, "register usbnet at usb-%s-%s, %s, " + "%02x:%02x:%02x:%02x:%02x:%02x", + xdev->bus->bus_name, xdev->devpath, + dev->driver_info->description, + net->dev_addr [0], net->dev_addr [1], + net->dev_addr [2], net->dev_addr [3], + net->dev_addr [4], net->dev_addr [5]); // ok, it's ready to go. usb_set_intfdata (udev, dev); @@ -3729,6 +3947,7 @@ * Same idea as above, but different framing. * * PXA-2xx based models are also lying-about-cdc. + * Some models don't even tell the same lies ... * * NOTE: OpenZaurus versions with 2.6 kernels won't use these entries, * unlike the older ones with 2.4 "embedix" kernels. @@ -3786,9 +4005,25 @@ .match_flags = USB_DEVICE_ID_MATCH_INT_INFO | USB_DEVICE_ID_MATCH_DEVICE, .idVendor = 0x04DD, + /* reported with some C860 units */ .idProduct = 0x9050, /* C-860 */ ZAURUS_MASTER_INTERFACE, .driver_info = ZAURUS_PXA_INFO, +#ifdef CONFIG_USB_ZAURUS + /* at least some (reports vary) C-860 units have very different + * lies about their standards support. + */ +}, { + .match_flags = USB_DEVICE_ID_MATCH_INT_INFO + | USB_DEVICE_ID_MATCH_DEVICE, + .idVendor = 0x04DD, + /* reported with some C860 units */ + .idProduct = 0x9031, /* C-860 */ + .bInterfaceClass = USB_CLASS_COMM, + .bInterfaceSubClass = USB_CDC_SUBCLASS_MDLM, + .bInterfaceProtocol = USB_CDC_PROTO_NONE, + .driver_info = (unsigned long) &zaurus_pxa_mdlm_info, +#endif }, /* Olympus has some models with a Zaurus-compatible option. diff -Nru a/drivers/usb/net/zd1201.c b/drivers/usb/net/zd1201.c --- a/drivers/usb/net/zd1201.c 2005-03-24 18:21:08 -08:00 +++ b/drivers/usb/net/zd1201.c 2005-03-24 18:21:08 -08:00 @@ -673,7 +673,7 @@ return 0; err = zd1201_docmd(zd, ZD1201_CMDCODE_ENABLE, 0, 0, 0); - if (!err); + if (!err) zd->mac_enabled = 1; if (zd->monitor) @@ -690,7 +690,7 @@ return 0; if (zd->monitor) { err = zd1201_setconfig16(zd, ZD1201_RID_PROMISCUOUSMODE, 0); - if (err); + if (err) return err; } diff -Nru a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c --- a/drivers/usb/serial/digi_acceleport.c 2005-03-24 18:21:08 -08:00 +++ b/drivers/usb/serial/digi_acceleport.c 2005-03-24 18:21:08 -08:00 @@ -246,6 +246,7 @@ #include #include #include +#include #include "usb-serial.h" /* Defines */ @@ -573,23 +574,14 @@ wait_queue_head_t *q, long timeout, spinlock_t *lock, unsigned long flags ) { + DEFINE_WAIT(wait); - wait_queue_t wait; - - - init_waitqueue_entry( &wait, current ); - - set_current_state( TASK_INTERRUPTIBLE ); - - add_wait_queue( q, &wait ); - - spin_unlock_irqrestore( lock, flags ); - + prepare_to_wait(q, &wait, TASK_UNINTERRUPTIBLE); + spin_unlock_irqrestore(lock, flags); timeout = schedule_timeout(timeout); + finish_wait(q, &wait); - remove_wait_queue( q, &wait ); - - return( timeout ); + return timeout; } @@ -1528,7 +1520,7 @@ static void digi_close( struct usb_serial_port *port, struct file *filp ) { - + DEFINE_WAIT(wait); int ret; unsigned char buf[32]; struct tty_struct *tty = port->tty; @@ -1604,8 +1596,9 @@ dbg( "digi_close: write oob failed, ret=%d", ret ); /* wait for final commands on oob port to complete */ - interruptible_sleep_on_timeout( &priv->dp_flush_wait, - DIGI_CLOSE_TIMEOUT ); + prepare_to_wait(&priv->dp_flush_wait, &wait, TASK_UNINTERRUPTIBLE); + schedule_timeout(DIGI_CLOSE_TIMEOUT); + finish_wait(&priv->dp_flush_wait, &wait); /* shutdown any outstanding bulk writes */ usb_kill_urb(port->write_urb); @@ -2002,7 +1995,7 @@ } else if( opcode == DIGI_CMD_IFLUSH_FIFO ) { - wake_up_interruptible( &priv->dp_flush_wait ); + wake_up( &priv->dp_flush_wait ); } diff -Nru a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c --- a/drivers/usb/serial/ftdi_sio.c 2005-03-24 18:21:08 -08:00 +++ b/drivers/usb/serial/ftdi_sio.c 2005-03-24 18:21:08 -08:00 @@ -1187,7 +1187,7 @@ * *************************************************************************** */ -ssize_t show_latency_timer(struct device *dev, char *buf) +static ssize_t show_latency_timer(struct device *dev, char *buf) { struct usb_serial_port *port = to_usb_serial_port(dev); struct ftdi_private *priv = usb_get_serial_port_data(port); @@ -1214,7 +1214,8 @@ } /* Write a new value of the latency timer, in units of milliseconds. */ -ssize_t store_latency_timer(struct device *dev, const char *valbuf, size_t count) +static ssize_t store_latency_timer(struct device *dev, const char *valbuf, + size_t count) { struct usb_serial_port *port = to_usb_serial_port(dev); struct ftdi_private *priv = usb_get_serial_port_data(port); @@ -1244,7 +1245,8 @@ /* Write an event character directly to the FTDI register. The ASCII value is in the low 8 bits, with the enable bit in the 9th bit. */ -ssize_t store_event_char(struct device *dev, const char *valbuf, size_t count) +static ssize_t store_event_char(struct device *dev, const char *valbuf, + size_t count) { struct usb_serial_port *port = to_usb_serial_port(dev); struct ftdi_private *priv = usb_get_serial_port_data(port); @@ -1275,7 +1277,7 @@ static DEVICE_ATTR(latency_timer, S_IWUGO | S_IRUGO, show_latency_timer, store_latency_timer); static DEVICE_ATTR(event_char, S_IWUGO, NULL, store_event_char); -void create_sysfs_attrs(struct usb_serial *serial) +static void create_sysfs_attrs(struct usb_serial *serial) { struct ftdi_private *priv; struct usb_device *udev; @@ -1292,7 +1294,7 @@ } } -void remove_sysfs_attrs(struct usb_serial *serial) +static void remove_sysfs_attrs(struct usb_serial *serial) { struct ftdi_private *priv; struct usb_device *udev; diff -Nru a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c --- a/drivers/usb/serial/garmin_gps.c 2005-03-24 18:21:08 -08:00 +++ b/drivers/usb/serial/garmin_gps.c 2005-03-24 18:21:08 -08:00 @@ -614,8 +614,8 @@ * * return <0 on error, 0 if packet is incomplete or > 0 if packet was sent */ -int gsp_send(struct garmin_data * garmin_data_p, const unsigned char *buf, - int count) +static int gsp_send(struct garmin_data * garmin_data_p, + const unsigned char *buf, int count) { const unsigned char *src; unsigned char *dst; diff -Nru a/drivers/usb/serial/ipw.c b/drivers/usb/serial/ipw.c --- a/drivers/usb/serial/ipw.c 2005-03-24 18:21:08 -08:00 +++ b/drivers/usb/serial/ipw.c 2005-03-24 18:21:08 -08:00 @@ -457,7 +457,7 @@ -int usb_ipw_init(void) +static int usb_ipw_init(void) { int retval; @@ -473,7 +473,7 @@ return 0; } -void usb_ipw_exit(void) +static void usb_ipw_exit(void) { usb_deregister(&usb_ipw_driver); usb_serial_deregister(&ipw_device); diff -Nru a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c --- a/drivers/usb/serial/mct_u232.c 2005-03-24 18:21:08 -08:00 +++ b/drivers/usb/serial/mct_u232.c 2005-03-24 18:21:08 -08:00 @@ -195,16 +195,16 @@ } } else { switch (value) { - case B300: value = 300; - case B600: value = 600; - case B1200: value = 1200; - case B2400: value = 2400; - case B4800: value = 4800; - case B9600: value = 9600; - case B19200: value = 19200; - case B38400: value = 38400; - case B57600: value = 57600; - case B115200: value = 115200; + case B300: value = 300; break; + case B600: value = 600; break; + case B1200: value = 1200; break; + case B2400: value = 2400; break; + case B4800: value = 4800; break; + case B9600: value = 9600; break; + case B19200: value = 19200; break; + case B38400: value = 38400; break; + case B57600: value = 57600; break; + case B115200: value = 115200; break; default: err("MCT USB-RS232: unsupported baudrate request 0x%x," " using default of B9600", value); @@ -646,7 +646,7 @@ else new_state &= ~(TIOCM_DTR | TIOCM_RTS); if (new_state != control_state) { - mct_u232_set_modem_ctrl(serial, control_state); + mct_u232_set_modem_ctrl(serial, new_state); control_state = new_state; } diff -Nru a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c --- a/drivers/usb/serial/usb-serial.c 2005-03-24 18:21:08 -08:00 +++ b/drivers/usb/serial/usb-serial.c 2005-03-24 18:21:08 -08:00 @@ -1418,11 +1418,11 @@ /* If the usb-serial core is built into the core, the usb-serial drivers need these symbols to load properly as modules. */ -EXPORT_SYMBOL(usb_serial_register); -EXPORT_SYMBOL(usb_serial_deregister); -EXPORT_SYMBOL(usb_serial_probe); -EXPORT_SYMBOL(usb_serial_disconnect); -EXPORT_SYMBOL(usb_serial_port_softint); +EXPORT_SYMBOL_GPL(usb_serial_register); +EXPORT_SYMBOL_GPL(usb_serial_deregister); +EXPORT_SYMBOL_GPL(usb_serial_probe); +EXPORT_SYMBOL_GPL(usb_serial_disconnect); +EXPORT_SYMBOL_GPL(usb_serial_port_softint); /* Module information */ diff -Nru a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c --- a/drivers/usb/serial/visor.c 2005-03-24 18:21:08 -08:00 +++ b/drivers/usb/serial/visor.c 2005-03-24 18:21:08 -08:00 @@ -386,6 +386,7 @@ int bytes_in; int bytes_out; int outstanding_urbs; + int throttled; }; /* number of outstanding urbs to prevent userspace DoS from happening */ @@ -415,6 +416,7 @@ priv->bytes_in = 0; priv->bytes_out = 0; priv->outstanding_urbs = 0; + priv->throttled = 0; spin_unlock_irqrestore(&priv->lock, flags); /* @@ -602,6 +604,7 @@ struct tty_struct *tty; unsigned long flags; int i; + int throttled; int result; dbg("%s - port %d", __FUNCTION__, port->number); @@ -627,18 +630,21 @@ } spin_lock_irqsave(&priv->lock, flags); priv->bytes_in += urb->actual_length; + throttled = priv->throttled; spin_unlock_irqrestore(&priv->lock, flags); - /* Continue trying to always read */ - usb_fill_bulk_urb (port->read_urb, port->serial->dev, - usb_rcvbulkpipe(port->serial->dev, - port->bulk_in_endpointAddress), - port->read_urb->transfer_buffer, - port->read_urb->transfer_buffer_length, - visor_read_bulk_callback, port); - result = usb_submit_urb(port->read_urb, GFP_ATOMIC); - if (result) - dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result); + /* Continue trying to always read if we should */ + if (!throttled) { + usb_fill_bulk_urb (port->read_urb, port->serial->dev, + usb_rcvbulkpipe(port->serial->dev, + port->bulk_in_endpointAddress), + port->read_urb->transfer_buffer, + port->read_urb->transfer_buffer_length, + visor_read_bulk_callback, port); + result = usb_submit_urb(port->read_urb, GFP_ATOMIC); + if (result) + dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result); + } return; } @@ -683,16 +689,26 @@ static void visor_throttle (struct usb_serial_port *port) { + struct visor_private *priv = usb_get_serial_port_data(port); + unsigned long flags; + dbg("%s - port %d", __FUNCTION__, port->number); - usb_kill_urb(port->read_urb); + spin_lock_irqsave(&priv->lock, flags); + priv->throttled = 1; + spin_unlock_irqrestore(&priv->lock, flags); } static void visor_unthrottle (struct usb_serial_port *port) { + struct visor_private *priv = usb_get_serial_port_data(port); + unsigned long flags; int result; dbg("%s - port %d", __FUNCTION__, port->number); + spin_lock_irqsave(&priv->lock, flags); + priv->throttled = 0; + spin_unlock_irqrestore(&priv->lock, flags); port->read_urb->dev = port->serial->dev; result = usb_submit_urb(port->read_urb, GFP_ATOMIC); diff -Nru a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig --- a/drivers/usb/storage/Kconfig 2005-03-24 18:21:08 -08:00 +++ b/drivers/usb/storage/Kconfig 2005-03-24 18:21:08 -08:00 @@ -31,28 +31,6 @@ Say Y here in order to have the USB Mass Storage code generate verbose debugging messages. -config USB_STORAGE_RW_DETECT - bool "USB Mass Storage Write-Protected Media Detection (EXPERIMENTAL)" - depends on USB_STORAGE && EXPERIMENTAL - help - Say Y here in order to have the USB Mass Storage code indicate to - the SCSI layer that using MODE SENSE(6) and MODE SENSE(10) to - determine if the media is write-protected is a good thing to do. - - Many devices have historically had trouble with these commands, - hence the default 2.6.x behavior has been to suppress their use. - 2.4.x used these commands with (at best) mixed results, often - crashing the firmware of the device. However, the SCSI layer now - issues these commands in a manner more consistent with other - "popular" OSes, in an attempt to improve compatibility. - - Saying Y here allows these commands to be sent to a USB device. - If you find a device this doesn't work for, switch to N and let - us know at - - If you say N here, the kernel will assume that all disk-like USB - devices are write-enabled. - config USB_STORAGE_DATAFAB bool "Datafab Compact Flash Reader support (EXPERIMENTAL)" depends on USB_STORAGE && EXPERIMENTAL diff -Nru a/drivers/usb/storage/datafab.c b/drivers/usb/storage/datafab.c --- a/drivers/usb/storage/datafab.c 2005-03-24 18:21:08 -08:00 +++ b/drivers/usb/storage/datafab.c 2005-03-24 18:21:08 -08:00 @@ -57,9 +57,9 @@ #include #include +#include "usb.h" #include "transport.h" #include "protocol.h" -#include "usb.h" #include "debug.h" #include "datafab.h" diff -Nru a/drivers/usb/storage/debug.h b/drivers/usb/storage/debug.h --- a/drivers/usb/storage/debug.h 2005-03-24 18:21:08 -08:00 +++ b/drivers/usb/storage/debug.h 2005-03-24 18:21:08 -08:00 @@ -47,8 +47,6 @@ #include #include -struct scsi_cmnd; - #define USB_STORAGE "usb-storage: " #ifdef CONFIG_USB_STORAGE_DEBUG diff -Nru a/drivers/usb/storage/dpcm.c b/drivers/usb/storage/dpcm.c --- a/drivers/usb/storage/dpcm.c 2005-03-24 18:21:08 -08:00 +++ b/drivers/usb/storage/dpcm.c 2005-03-24 18:21:08 -08:00 @@ -34,9 +34,9 @@ #include #include +#include "usb.h" #include "transport.h" #include "protocol.h" -#include "usb.h" #include "debug.h" #include "dpcm.h" #include "sddr09.h" diff -Nru a/drivers/usb/storage/freecom.c b/drivers/usb/storage/freecom.c --- a/drivers/usb/storage/freecom.c 2005-03-24 18:21:08 -08:00 +++ b/drivers/usb/storage/freecom.c 2005-03-24 18:21:08 -08:00 @@ -34,9 +34,9 @@ #include #include +#include "usb.h" #include "transport.h" #include "protocol.h" -#include "usb.h" #include "debug.h" #include "freecom.h" diff -Nru a/drivers/usb/storage/initializers.c b/drivers/usb/storage/initializers.c --- a/drivers/usb/storage/initializers.c 2005-03-24 18:21:08 -08:00 +++ b/drivers/usb/storage/initializers.c 2005-03-24 18:21:08 -08:00 @@ -39,6 +39,8 @@ #include #include + +#include "usb.h" #include "initializers.h" #include "debug.h" #include "transport.h" diff -Nru a/drivers/usb/storage/isd200.c b/drivers/usb/storage/isd200.c --- a/drivers/usb/storage/isd200.c 2005-03-24 18:21:08 -08:00 +++ b/drivers/usb/storage/isd200.c 2005-03-24 18:21:08 -08:00 @@ -54,9 +54,9 @@ #include #include +#include "usb.h" #include "transport.h" #include "protocol.h" -#include "usb.h" #include "debug.h" #include "scsiglue.h" #include "isd200.h" diff -Nru a/drivers/usb/storage/jumpshot.c b/drivers/usb/storage/jumpshot.c --- a/drivers/usb/storage/jumpshot.c 2005-03-24 18:21:08 -08:00 +++ b/drivers/usb/storage/jumpshot.c 2005-03-24 18:21:08 -08:00 @@ -54,9 +54,9 @@ #include #include +#include "usb.h" #include "transport.h" #include "protocol.h" -#include "usb.h" #include "debug.h" #include "jumpshot.h" diff -Nru a/drivers/usb/storage/protocol.c b/drivers/usb/storage/protocol.c --- a/drivers/usb/storage/protocol.c 2005-03-24 18:21:08 -08:00 +++ b/drivers/usb/storage/protocol.c 2005-03-24 18:21:08 -08:00 @@ -47,8 +47,9 @@ #include #include #include -#include "protocol.h" + #include "usb.h" +#include "protocol.h" #include "debug.h" #include "scsiglue.h" #include "transport.h" diff -Nru a/drivers/usb/storage/protocol.h b/drivers/usb/storage/protocol.h --- a/drivers/usb/storage/protocol.h 2005-03-24 18:21:08 -08:00 +++ b/drivers/usb/storage/protocol.h 2005-03-24 18:21:08 -08:00 @@ -41,9 +41,6 @@ #ifndef _PROTOCOL_H_ #define _PROTOCOL_H_ -struct scsi_cmnd; -struct us_data; - /* Sub Classes */ #define US_SC_RBC 0x01 /* Typically, flash devices */ diff -Nru a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c --- a/drivers/usb/storage/scsiglue.c 2005-03-24 18:21:08 -08:00 +++ b/drivers/usb/storage/scsiglue.c 2005-03-24 18:21:08 -08:00 @@ -53,10 +53,9 @@ #include #include #include -#include -#include "scsiglue.h" #include "usb.h" +#include "scsiglue.h" #include "debug.h" #include "transport.h" #include "protocol.h" @@ -83,7 +82,7 @@ static int slave_configure(struct scsi_device *sdev) { - struct us_data *us = (struct us_data *) sdev->host->hostdata[0]; + struct us_data *us = host_to_us(sdev->host); /* Scatter-gather buffers (all but the last) must have a length * divisible by the bulk maxpacket size. Otherwise a data packet @@ -137,18 +136,20 @@ * 192 bytes (that's what Windows uses). */ sdev->use_192_bytes_for_3f = 1; + /* Some devices don't like MODE SENSE with page=0x3f, + * which is the command used for checking if a device + * is write-protected. Now that we tell the sd driver + * to do a 192-byte transfer with this command the + * majority of devices work fine, but a few still can't + * handle it. The sd driver will simply assume those + * devices are write-enabled. */ + if (us->flags & US_FL_NO_WP_DETECT) + sdev->skip_ms_page_3f = 1; + /* A number of devices have problems with MODE SENSE for * page x08, so we will skip it. */ sdev->skip_ms_page_8 = 1; -#ifndef CONFIG_USB_STORAGE_RW_DETECT - /* Some devices may not like MODE SENSE with page=0x3f. - * Now that we're using 192-byte transfers this may no - * longer be a problem. So this will be a configuration - * option. */ - sdev->skip_ms_page_3f = 1; -#endif - /* Some disks return the total number of blocks in response * to READ CAPACITY rather than the highest block number. * If this device makes that mistake, tell the sd driver. */ @@ -173,14 +174,13 @@ } /* queue a command */ -/* This is always called with scsi_lock(srb->host) held */ +/* This is always called with scsi_lock(host) held */ static int queuecommand(struct scsi_cmnd *srb, void (*done)(struct scsi_cmnd *)) { - struct us_data *us = (struct us_data *)srb->device->host->hostdata[0]; + struct us_data *us = host_to_us(srb->device->host); US_DEBUGP("%s called\n", __FUNCTION__); - srb->host_scribble = (unsigned char *)us; /* check for state-transition errors */ if (us->srb != NULL) { @@ -210,11 +210,10 @@ ***********************************************************************/ /* Command timeout and abort */ -/* This is always called with scsi_lock(srb->host) held */ -static int command_abort(struct scsi_cmnd *srb ) +/* This is always called with scsi_lock(host) held */ +static int command_abort(struct scsi_cmnd *srb) { - struct Scsi_Host *host = srb->device->host; - struct us_data *us = (struct us_data *) host->hostdata[0]; + struct us_data *us = host_to_us(srb->device->host); US_DEBUGP("%s called\n", __FUNCTION__); @@ -234,13 +233,13 @@ set_bit(US_FLIDX_ABORTING, &us->flags); usb_stor_stop_transport(us); } - scsi_unlock(host); + scsi_unlock(us_to_host(us)); /* Wait for the aborted command to finish */ wait_for_completion(&us->notify); /* Reacquire the lock and allow USB transfers to resume */ - scsi_lock(host); + scsi_lock(us_to_host(us)); clear_bit(US_FLIDX_ABORTING, &us->flags); clear_bit(US_FLIDX_TIMED_OUT, &us->flags); return SUCCESS; @@ -248,15 +247,15 @@ /* This invokes the transport reset mechanism to reset the state of the * device */ -/* This is always called with scsi_lock(srb->host) held */ +/* This is always called with scsi_lock(host) held */ static int device_reset(struct scsi_cmnd *srb) { - struct us_data *us = (struct us_data *)srb->device->host->hostdata[0]; + struct us_data *us = host_to_us(srb->device->host); int result; US_DEBUGP("%s called\n", __FUNCTION__); - scsi_unlock(srb->device->host); + scsi_unlock(us_to_host(us)); /* lock the device pointers and do the reset */ down(&(us->dev_semaphore)); @@ -268,22 +267,22 @@ up(&(us->dev_semaphore)); /* lock the host for the return */ - scsi_lock(srb->device->host); + scsi_lock(us_to_host(us)); return result; } /* This resets the device's USB port. */ /* It refuses to work if there's more than one interface in * the device, so that other users are not affected. */ -/* This is always called with scsi_lock(srb->host) held */ +/* This is always called with scsi_lock(host) held */ static int bus_reset(struct scsi_cmnd *srb) { - struct us_data *us = (struct us_data *)srb->device->host->hostdata[0]; + struct us_data *us = host_to_us(srb->device->host); int result, rc; US_DEBUGP("%s called\n", __FUNCTION__); - scsi_unlock(srb->device->host); + scsi_unlock(us_to_host(us)); /* The USB subsystem doesn't handle synchronisation between * a device's several drivers. Therefore we reset only devices @@ -311,7 +310,7 @@ up(&(us->dev_semaphore)); /* lock the host for the return */ - scsi_lock(srb->device->host); + scsi_lock(us_to_host(us)); return result < 0 ? FAILED : SUCCESS; } @@ -321,11 +320,12 @@ void usb_stor_report_device_reset(struct us_data *us) { int i; + struct Scsi_Host *host = us_to_host(us); - scsi_report_device_reset(us->host, 0, 0); + scsi_report_device_reset(host, 0, 0); if (us->flags & US_FL_SCM_MULT_TARG) { - for (i = 1; i < us->host->max_id; ++i) - scsi_report_device_reset(us->host, 0, i); + for (i = 1; i < host->max_id; ++i) + scsi_report_device_reset(host, 0, i); } } @@ -337,41 +337,41 @@ #undef SPRINTF #define SPRINTF(args...) \ do { if (pos < buffer+length) pos += sprintf(pos, ## args); } while (0) -#define DO_FLAG(a) \ - do { if (us->flags & US_FL_##a) pos += sprintf(pos, " " #a); } while(0) -static int proc_info (struct Scsi_Host *hostptr, char *buffer, char **start, off_t offset, - int length, int inout) +static int proc_info (struct Scsi_Host *host, char *buffer, + char **start, off_t offset, int length, int inout) { - struct us_data *us; + struct us_data *us = host_to_us(host); char *pos = buffer; + const char *string; /* if someone is sending us data, just throw it away */ if (inout) return length; - us = (struct us_data*)hostptr->hostdata[0]; - /* print the controller name */ - SPRINTF(" Host scsi%d: usb-storage\n", hostptr->host_no); + SPRINTF(" Host scsi%d: usb-storage\n", host->host_no); /* print product, vendor, and serial number strings */ if (us->pusb_dev->manufacturer) - SPRINTF(" Vendor: %s\n", us->pusb_dev->manufacturer); + string = us->pusb_dev->manufacturer; else if (us->unusual_dev->vendorName) - SPRINTF(" Vendor: %s\n", us->unusual_dev->vendorName); + string = us->unusual_dev->vendorName; else - SPRINTF(" Vendor: Unknown\n"); + string = "Unknown"; + SPRINTF(" Vendor: %s\n", string); if (us->pusb_dev->product) - SPRINTF(" Product: %s\n", us->pusb_dev->product); + string = us->pusb_dev->product; else if (us->unusual_dev->productName) - SPRINTF(" Product: %s\n", us->unusual_dev->productName); + string = us->unusual_dev->productName; else - SPRINTF(" Product: Unknown\n"); + string = "Unknown"; + SPRINTF(" Product: %s\n", string); if (us->pusb_dev->serial) - SPRINTF("Serial Number: %s\n", us->pusb_dev->serial); + string = us->pusb_dev->serial; else - SPRINTF("Serial Number: None\n"); + string = "None"; + SPRINTF("Serial Number: %s\n", string); /* show the protocol and transport */ SPRINTF(" Protocol: %s\n", us->protocol_name); @@ -381,10 +381,10 @@ if (pos < buffer + length) { pos += sprintf(pos, " Quirks:"); - DO_FLAG(SINGLE_LUN); - DO_FLAG(SCM_MULT_TARG); - DO_FLAG(FIX_INQUIRY); - DO_FLAG(FIX_CAPACITY); +#define US_FLAG(name, value) \ + if (us->flags & value) pos += sprintf(pos, " " #name); +US_DO_ALL_FLAGS +#undef US_FLAG *(pos++) = '\n'; } @@ -488,15 +488,6 @@ /* module management */ .module = THIS_MODULE -}; - -/* For a device that is "Not Ready" */ -unsigned char usb_stor_sense_notready[18] = { - [0] = 0x70, /* current error */ - [2] = 0x02, /* not ready */ - [7] = 0x0a, /* additional length */ - [12] = 0x04, /* not ready */ - [13] = 0x03 /* manual intervention */ }; /* To Report "Illegal Request: Invalid Field in CDB */ diff -Nru a/drivers/usb/storage/scsiglue.h b/drivers/usb/storage/scsiglue.h --- a/drivers/usb/storage/scsiglue.h 2005-03-24 18:21:08 -08:00 +++ b/drivers/usb/storage/scsiglue.h 2005-03-24 18:21:08 -08:00 @@ -41,14 +41,8 @@ #ifndef _SCSIGLUE_H_ #define _SCSIGLUE_H_ -#include - -struct us_data; -struct scsi_cmnd; - extern void usb_stor_report_device_reset(struct us_data *us); -extern unsigned char usb_stor_sense_notready[18]; extern unsigned char usb_stor_sense_invalidCDB[18]; extern struct scsi_host_template usb_stor_host_template; diff -Nru a/drivers/usb/storage/sddr09.c b/drivers/usb/storage/sddr09.c --- a/drivers/usb/storage/sddr09.c 2005-03-24 18:21:08 -08:00 +++ b/drivers/usb/storage/sddr09.c 2005-03-24 18:21:08 -08:00 @@ -48,9 +48,9 @@ #include #include +#include "usb.h" #include "transport.h" #include "protocol.h" -#include "usb.h" #include "debug.h" #include "sddr09.h" diff -Nru a/drivers/usb/storage/sddr55.c b/drivers/usb/storage/sddr55.c --- a/drivers/usb/storage/sddr55.c 2005-03-24 18:21:08 -08:00 +++ b/drivers/usb/storage/sddr55.c 2005-03-24 18:21:08 -08:00 @@ -31,9 +31,9 @@ #include #include +#include "usb.h" #include "transport.h" #include "protocol.h" -#include "usb.h" #include "debug.h" #include "sddr55.h" diff -Nru a/drivers/usb/storage/shuttle_usbat.c b/drivers/usb/storage/shuttle_usbat.c --- a/drivers/usb/storage/shuttle_usbat.c 2005-03-24 18:21:08 -08:00 +++ b/drivers/usb/storage/shuttle_usbat.c 2005-03-24 18:21:08 -08:00 @@ -51,9 +51,9 @@ #include #include +#include "usb.h" #include "transport.h" #include "protocol.h" -#include "usb.h" #include "debug.h" #include "shuttle_usbat.h" @@ -61,7 +61,10 @@ #define LSB_of(s) ((s)&0xFF) #define MSB_of(s) ((s)>>8) -int transferred = 0; +static int transferred = 0; + +static int usbat_flash_transport(struct scsi_cmnd * srb, struct us_data *us); +static int usbat_hp8200e_transport(struct scsi_cmnd *srb, struct us_data *us); /* * Convenience function to produce an ATAPI read/write sectors command @@ -872,8 +875,8 @@ /* * Set the transport function based on the device type */ -int usbat_set_transport(struct us_data *us, - struct usbat_info *info) +static int usbat_set_transport(struct us_data *us, + struct usbat_info *info) { int rc; @@ -1417,7 +1420,7 @@ /* * Transport for the HP 8200e */ -int usbat_hp8200e_transport(struct scsi_cmnd *srb, struct us_data *us) +static int usbat_hp8200e_transport(struct scsi_cmnd *srb, struct us_data *us) { int result; unsigned char *status = us->iobuf; @@ -1560,7 +1563,7 @@ /* * Transport for USBAT02-based CompactFlash and similar storage devices */ -int usbat_flash_transport(struct scsi_cmnd * srb, struct us_data *us) +static int usbat_flash_transport(struct scsi_cmnd * srb, struct us_data *us) { int rc; struct usbat_info *info = (struct usbat_info *) (us->extra); diff -Nru a/drivers/usb/storage/shuttle_usbat.h b/drivers/usb/storage/shuttle_usbat.h --- a/drivers/usb/storage/shuttle_usbat.h 2005-03-24 18:21:08 -08:00 +++ b/drivers/usb/storage/shuttle_usbat.h 2005-03-24 18:21:08 -08:00 @@ -105,10 +105,6 @@ #define USBAT_FEAT_ET1 0x02 #define USBAT_FEAT_ET2 0x01 -/* Transport functions */ -int usbat_hp8200e_transport(struct scsi_cmnd *srb, struct us_data *us); -int usbat_flash_transport(struct scsi_cmnd * srb, struct us_data *us); - extern int usbat_transport(struct scsi_cmnd *srb, struct us_data *us); extern int init_usbat(struct us_data *us); diff -Nru a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c --- a/drivers/usb/storage/transport.c 2005-03-24 18:21:08 -08:00 +++ b/drivers/usb/storage/transport.c 2005-03-24 18:21:08 -08:00 @@ -54,10 +54,10 @@ #include #include +#include "usb.h" #include "transport.h" #include "protocol.h" #include "scsiglue.h" -#include "usb.h" #include "debug.h" @@ -383,7 +383,8 @@ * This routine always uses us->recv_intr_pipe as the pipe and * us->ep_bInterval as the interrupt interval. */ -int usb_stor_intr_transfer(struct us_data *us, void *buf, unsigned int length) +static int usb_stor_intr_transfer(struct us_data *us, void *buf, + unsigned int length) { int result; unsigned int pipe = us->recv_intr_pipe; @@ -436,7 +437,7 @@ * This function does basically the same thing as usb_stor_bulk_transfer_buf() * above, but it uses the usbcore scatter-gather library. */ -int usb_stor_bulk_transfer_sglist(struct us_data *us, unsigned int pipe, +static int usb_stor_bulk_transfer_sglist(struct us_data *us, unsigned int pipe, struct scatterlist *sg, int num_sg, unsigned int length, unsigned int *act_len) { @@ -1138,11 +1139,11 @@ * RESETTING bit, and clear the ABORTING bit so that the reset * may proceed. */ - scsi_lock(us->host); + scsi_lock(us_to_host(us)); usb_stor_report_device_reset(us); set_bit(US_FLIDX_RESETTING, &us->flags); clear_bit(US_FLIDX_ABORTING, &us->flags); - scsi_unlock(us->host); + scsi_unlock(us_to_host(us)); /* A 20-second timeout may seem rather long, but a LaCie * StudioDrive USB2 device takes 16+ seconds to get going @@ -1158,7 +1159,7 @@ /* Give the device some time to recover from the reset, * but don't delay disconnect processing. */ - wait_event_interruptible_timeout(us->dev_reset_wait, + wait_event_interruptible_timeout(us->delay_wait, test_bit(US_FLIDX_DISCONNECTING, &us->flags), HZ*6); if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) { diff -Nru a/drivers/usb/storage/transport.h b/drivers/usb/storage/transport.h --- a/drivers/usb/storage/transport.h 2005-03-24 18:21:08 -08:00 +++ b/drivers/usb/storage/transport.h 2005-03-24 18:21:08 -08:00 @@ -43,9 +43,6 @@ #include #include -#include "usb.h" - -struct scsi_cmnd; /* Protocols */ @@ -169,13 +166,8 @@ extern int usb_stor_ctrl_transfer(struct us_data *us, unsigned int pipe, u8 request, u8 requesttype, u16 value, u16 index, void *data, u16 size); -extern int usb_stor_intr_transfer(struct us_data *us, void *buf, - unsigned int length); extern int usb_stor_bulk_transfer_buf(struct us_data *us, unsigned int pipe, void *buf, unsigned int length, unsigned int *act_len); -extern int usb_stor_bulk_transfer_sglist(struct us_data *us, unsigned int pipe, - struct scatterlist *sg, int num_sg, unsigned int length, - unsigned int *act_len); extern int usb_stor_bulk_transfer_sg(struct us_data *us, unsigned int pipe, void *buf, unsigned int length, int use_sg, int *residual); diff -Nru a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h --- a/drivers/usb/storage/unusual_devs.h 2005-03-24 18:21:08 -08:00 +++ b/drivers/usb/storage/unusual_devs.h 2005-03-24 18:21:08 -08:00 @@ -130,6 +130,15 @@ US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_CAPACITY), +/* BENQ DC5330 + * Reported by Manuel Fombuena and + * Frank Copeland */ +UNUSUAL_DEV( 0x04a5, 0x3010, 0x0100, 0x0100, + "Tekom Technologies, Inc", + "300_CAMERA", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_IGNORE_RESIDUE ), + /* Reported by Simon Levitt * This entry needs Sub and Proto fields */ UNUSUAL_DEV( 0x04b8, 0x0601, 0x0100, 0x0100, @@ -340,7 +349,7 @@ "Sony", "DSC-S30/S70/S75/505V/F505/F707/F717/P8", US_SC_SCSI, US_PR_DEVICE, NULL, - US_FL_SINGLE_LUN | US_FL_NOT_LOCKABLE ), + US_FL_SINGLE_LUN | US_FL_NOT_LOCKABLE | US_FL_NO_WP_DETECT ), /* This entry is needed because the device reports Sub=ff */ UNUSUAL_DEV( 0x054c, 0x0010, 0x0500, 0x0500, @@ -365,6 +374,13 @@ 0 ), #endif +/* Submitted by Olaf Hering, SuSE Bugzilla #49049 */ +UNUSUAL_DEV( 0x054c, 0x002c, 0x0501, 0x0501, + "Sony", + "USB Floppy Drive", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_SINGLE_LUN ), + UNUSUAL_DEV( 0x054c, 0x002d, 0x0100, 0x0100, "Sony", "Memorystick MSAC-US1", @@ -508,6 +524,12 @@ US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_CAPACITY ), +UNUSUAL_DEV( 0x05ac, 0x1205, 0x0001, 0x0001, + "Apple", + "iPod", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_FIX_CAPACITY ), + #ifdef CONFIG_USB_STORAGE_JUMPSHOT UNUSUAL_DEV( 0x05dc, 0x0001, 0x0000, 0x0001, "Lexar", @@ -612,20 +634,6 @@ US_SC_SCSI, US_PR_CB, NULL, US_FL_SINGLE_LUN ), -UNUSUAL_DEV( 0x0781, 0x0002, 0x0009, 0x0009, - "Sandisk", - "ImageMate SDDR-31", - US_SC_DEVICE, US_PR_DEVICE, NULL, - US_FL_IGNORE_SER ), - -#ifdef CONFIG_USB_STORAGE_USBAT -UNUSUAL_DEV( 0x0781, 0x0005, 0x0005, 0x0005, - "Sandisk", - "ImageMate SDDR-05b", - US_SC_SCSI, US_PR_SCM_ATAPI, init_usbat, - US_FL_SINGLE_LUN), -#endif - UNUSUAL_DEV( 0x0781, 0x0100, 0x0100, 0x0100, "Sandisk", "ImageMate SDDR-12", @@ -697,6 +705,13 @@ US_SC_SCSI, US_PR_DATAFAB, NULL, 0 ), +/* Reported by Josef Reisinger */ +UNUSUAL_DEV( 0x07c4, 0xa002, 0x0000, 0xffff, + "Datafab/Unknown", + "MD2/MD3 Disk enclosure", + US_SC_SCSI, US_PR_DATAFAB, NULL, + US_FL_SINGLE_LUN ), + UNUSUAL_DEV( 0x07c4, 0xa003, 0x0000, 0xffff, "Datafab/Unknown", "Datafab-based Reader", @@ -930,6 +945,13 @@ "Flash Disk", US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_IGNORE_RESIDUE ), + +/* Reported by Michael Stattmann */ +UNUSUAL_DEV( 0x0fce, 0xd008, 0x0000, 0x0000, + "Sony Ericsson", + "V800-Vodafone 802", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_NO_WP_DETECT ), /* Reported by Kevin Cernekee * Tested on hardware version 1.10. diff -Nru a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c --- a/drivers/usb/storage/usb.c 2005-03-24 18:21:08 -08:00 +++ b/drivers/usb/storage/usb.c 2005-03-24 18:21:08 -08:00 @@ -51,6 +51,9 @@ #include #include #include +#include +#include +#include #include #include @@ -89,10 +92,6 @@ #endif -#include -#include -#include - /* Some informational data */ MODULE_AUTHOR("Matthew Dharm "); MODULE_DESCRIPTION("USB Mass Storage driver for Linux"); @@ -103,6 +102,13 @@ MODULE_PARM_DESC(delay_use, "seconds to delay before using a new device"); +/* These are used to make sure the module doesn't unload before all the + * threads have exited. + */ +static atomic_t total_threads = ATOMIC_INIT(0); +static DECLARE_COMPLETION(threads_gone); + + static int storage_probe(struct usb_interface *iface, const struct usb_device_id *id); @@ -225,7 +231,7 @@ { NULL } }; -struct usb_driver usb_storage_driver = { +static struct usb_driver usb_storage_driver = { .owner = THIS_MODULE, .name = "usb-storage", .probe = storage_probe, @@ -278,7 +284,7 @@ static int usb_stor_control_thread(void * __us) { struct us_data *us = (struct us_data *)__us; - struct Scsi_Host *host = us->host; + struct Scsi_Host *host = us_to_host(us); lock_kernel(); @@ -287,11 +293,13 @@ * so get rid of all our resources. */ daemonize("usb-storage"); - current->flags |= PF_NOFREEZE; - unlock_kernel(); + /* acquire a reference to the host, so it won't be deallocated + * until we're ready to exit */ + scsi_host_get(host); + /* signal that we've started the thread */ complete(&(us->notify)); @@ -305,9 +313,9 @@ /* lock the device pointers */ down(&(us->dev_semaphore)); - /* if us->srb is NULL, we are being asked to exit */ - if (us->srb == NULL) { - US_DEBUGP("-- exit command received\n"); + /* if the device has disconnected, we are free to exit */ + if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) { + US_DEBUGP("-- exiting\n"); up(&(us->dev_semaphore)); break; } @@ -321,12 +329,6 @@ goto SkipForAbort; } - /* don't do anything if we are disconnecting */ - if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) { - US_DEBUGP("No command during disconnect\n"); - goto SkipForDisconnect; - } - scsi_unlock(host); /* reject the command if the direction indicator @@ -394,7 +396,6 @@ complete(&(us->notify)); /* finished working on this command */ -SkipForDisconnect: us->srb = NULL; scsi_unlock(host); @@ -402,6 +403,8 @@ up(&(us->dev_semaphore)); } /* for (;;) */ + scsi_host_put(host); + /* notify the exit routine that we're actually exiting now * * complete()/wait_for_completion() is similar to up()/down(), @@ -416,7 +419,7 @@ * This is important in preemption kernels, which transfer the flow * of execution immediately upon a complete(). */ - complete_and_exit(&(us->notify), 0); + complete_and_exit(&threads_gone, 0); } /*********************************************************************** @@ -757,20 +760,6 @@ up(&us->dev_semaphore); - /* - * Since this is a new device, we need to register a SCSI - * host definition with the higher SCSI layers. - */ - us->host = scsi_host_alloc(&usb_stor_host_template, sizeof(us)); - if (!us->host) { - printk(KERN_WARNING USB_STORAGE - "Unable to allocate the scsi host\n"); - return -EBUSY; - } - - /* Set the hostdata to prepare for scanning */ - us->host->hostdata[0] = (unsigned long) us; - /* Start up our control thread */ p = kernel_thread(usb_stor_control_thread, us, CLONE_VM); if (p < 0) { @@ -779,6 +768,7 @@ return p; } us->pid = p; + atomic_inc(&total_threads); /* Wait for the thread to start */ wait_for_completion(&(us->notify)); @@ -787,37 +777,16 @@ } /* Release all our dynamic resources */ -void usb_stor_release_resources(struct us_data *us) +static void usb_stor_release_resources(struct us_data *us) { US_DEBUGP("-- %s\n", __FUNCTION__); - /* Kill the control thread. The SCSI host must already have been - * removed so it won't try to queue any more commands. + /* Tell the control thread to exit. The SCSI host must + * already have been removed so it won't try to queue + * any more commands. */ - if (us->pid) { - - /* Wait for the thread to be idle */ - down(&us->dev_semaphore); - US_DEBUGP("-- sending exit command to thread\n"); - - /* If the SCSI midlayer queued a final command just before - * scsi_remove_host() was called, us->srb might not be - * NULL. We can overwrite it safely, because the midlayer - * will not wait for the command to finish. Also the - * control thread will already have been awakened. - * That's okay, an extra up() on us->sema won't hurt. - * - * Enqueue the command, wake up the thread, and wait for - * notification that it has exited. - */ - scsi_lock(us->host); - us->srb = NULL; - scsi_unlock(us->host); - up(&us->dev_semaphore); - - up(&us->sema); - wait_for_completion(&us->notify); - } + US_DEBUGP("-- sending exit command to thread\n"); + up(&us->sema); /* Call the destructor routine, if it exists */ if (us->extra_destructor) { @@ -825,16 +794,9 @@ us->extra_destructor(us->extra); } - /* Finish the host removal sequence */ - if (us->host) - scsi_host_put(us->host); - /* Free the extra data and the URB */ - if (us->extra) - kfree(us->extra); - if (us->current_urb) - usb_free_urb(us->current_urb); - + kfree(us->extra); + usb_free_urb(us->current_urb); } /* Dissociate from the USB device */ @@ -852,9 +814,6 @@ /* Remove our private data from the interface */ usb_set_intfdata(us->pusb_intf, NULL); - - /* Free the structure itself */ - kfree(us); } /* Thread to carry out delayed SCSI-device scanning */ @@ -870,6 +829,13 @@ daemonize("usb-stor-scan"); unlock_kernel(); + /* Acquire a reference to the host, so it won't be deallocated + * until we're ready to exit */ + scsi_host_get(us_to_host(us)); + + /* Signal that we've started the thread */ + complete(&(us->notify)); + printk(KERN_DEBUG "usb-storage: device found at %d\n", us->pusb_dev->devnum); @@ -878,7 +844,7 @@ printk(KERN_DEBUG "usb-storage: waiting for device " "to settle before scanning\n"); retry: - wait_event_interruptible_timeout(us->scsi_scan_wait, + wait_event_interruptible_timeout(us->delay_wait, test_bit(US_FLIDX_DISCONNECTING, &us->flags), delay_use * HZ); if (current->flags & PF_FREEZE) { @@ -889,11 +855,14 @@ /* If the device is still connected, perform the scanning */ if (!test_bit(US_FLIDX_DISCONNECTING, &us->flags)) { - scsi_scan_host(us->host); + scsi_scan_host(us_to_host(us)); printk(KERN_DEBUG "usb-storage: device scan complete\n"); + + /* Should we unbind if no devices were detected? */ } - complete_and_exit(&us->scsi_scan_done, 0); + scsi_host_put(us_to_host(us)); + complete_and_exit(&threads_gone, 0); } @@ -901,25 +870,30 @@ static int storage_probe(struct usb_interface *intf, const struct usb_device_id *id) { + struct Scsi_Host *host; struct us_data *us; const int id_index = id - storage_usb_ids; int result; US_DEBUGP("USB Mass Storage device detected\n"); - /* Allocate the us_data structure and initialize the mutexes */ - us = (struct us_data *) kmalloc(sizeof(*us), GFP_KERNEL); - if (!us) { - printk(KERN_WARNING USB_STORAGE "Out of memory\n"); + /* + * Ask the SCSI layer to allocate a host structure, with extra + * space at the end for our private us_data structure. + */ + host = scsi_host_alloc(&usb_stor_host_template, sizeof(*us)); + if (!host) { + printk(KERN_WARNING USB_STORAGE + "Unable to allocate the scsi host\n"); return -ENOMEM; } + + us = host_to_us(host); memset(us, 0, sizeof(struct us_data)); init_MUTEX(&(us->dev_semaphore)); init_MUTEX_LOCKED(&(us->sema)); init_completion(&(us->notify)); - init_waitqueue_head(&us->dev_reset_wait); - init_waitqueue_head(&us->scsi_scan_wait); - init_completion(&us->scsi_scan_done); + init_waitqueue_head(&us->delay_wait); /* Associate the us_data structure with the USB device */ result = associate_dev(us, intf); @@ -972,7 +946,7 @@ result = usb_stor_acquire_resources(us); if (result) goto BadDevice; - result = scsi_add_host(us->host, &intf->dev); + result = scsi_add_host(host, &intf->dev); if (result) { printk(KERN_WARNING USB_STORAGE "Unable to add the scsi host\n"); @@ -984,17 +958,23 @@ if (result < 0) { printk(KERN_WARNING USB_STORAGE "Unable to start the device-scanning thread\n"); - scsi_remove_host(us->host); + scsi_remove_host(host); goto BadDevice; } + atomic_inc(&total_threads); + + /* Wait for the thread to start */ + wait_for_completion(&(us->notify)); return 0; /* We come here if there are any problems */ BadDevice: US_DEBUGP("storage_probe() failed\n"); + set_bit(US_FLIDX_DISCONNECTING, &us->flags); usb_stor_release_resources(us); dissociate_dev(us); + scsi_host_put(host); return result; } @@ -1006,24 +986,26 @@ US_DEBUGP("storage_disconnect() called\n"); /* Prevent new USB transfers, stop the current command, and - * interrupt a device-reset delay */ + * interrupt a SCSI-scan or device-reset delay */ set_bit(US_FLIDX_DISCONNECTING, &us->flags); usb_stor_stop_transport(us); - wake_up(&us->dev_reset_wait); + wake_up(&us->delay_wait); - /* Interrupt the SCSI-device-scanning thread's time delay, and - * wait for the thread to finish */ - wake_up(&us->scsi_scan_wait); - wait_for_completion(&us->scsi_scan_done); + /* It doesn't matter if the SCSI-scanning thread is still running. + * The thread will exit when it sees the DISCONNECTING flag. */ /* Wait for the current command to finish, then remove the host */ down(&us->dev_semaphore); up(&us->dev_semaphore); - scsi_remove_host(us->host); + scsi_remove_host(us_to_host(us)); /* Wait for everything to become idle and release all our resources */ usb_stor_release_resources(us); dissociate_dev(us); + + /* Drop our reference to the host; the SCSI core will free it + * (and "us" along with it) when the refcount becomes 0. */ + scsi_host_put(us_to_host(us)); } /*********************************************************************** @@ -1053,6 +1035,16 @@ */ US_DEBUGP("-- calling usb_deregister()\n"); usb_deregister(&usb_storage_driver) ; + + /* Don't return until all of our control and scanning threads + * have exited. Since each thread signals threads_gone as its + * last act, we have to call wait_for_completion the right number + * of times. + */ + while (atomic_read(&total_threads) > 0) { + wait_for_completion(&threads_gone); + atomic_dec(&total_threads); + } } module_init(usb_stor_init); diff -Nru a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h --- a/drivers/usb/storage/usb.h 2005-03-24 18:21:08 -08:00 +++ b/drivers/usb/storage/usb.h 2005-03-24 18:21:08 -08:00 @@ -48,6 +48,7 @@ #include #include #include +#include struct us_data; struct scsi_cmnd; @@ -65,18 +66,35 @@ unsigned int flags; }; -/* Flag definitions: these entries are static */ -#define US_FL_SINGLE_LUN 0x00000001 /* allow access to only LUN 0 */ -#define US_FL_MODE_XLATE 0 /* [no longer used] */ -#define US_FL_NEED_OVERRIDE 0x00000004 /* unusual_devs entry is necessary */ -#define US_FL_IGNORE_SER 0 /* [no longer used] */ -#define US_FL_SCM_MULT_TARG 0x00000020 /* supports multiple targets */ -#define US_FL_FIX_INQUIRY 0x00000040 /* INQUIRY response needs faking */ -#define US_FL_FIX_CAPACITY 0x00000080 /* READ CAPACITY response too big */ -#define US_FL_IGNORE_RESIDUE 0x00000100 /* reported residue is wrong */ -#define US_FL_BULK32 0x00000200 /* Uses 32-byte CBW length */ -#define US_FL_NOT_LOCKABLE 0x00000400 /* PREVENT/ALLOW not supported */ -#define US_FL_GO_SLOW 0x00000800 /* Need delay after Command phase */ +/* + * Static flag definitions. We use this roundabout technique so that the + * proc_info() routine can automatically display a message for each flag. + */ +#define US_DO_ALL_FLAGS \ + US_FLAG(SINGLE_LUN, 0x00000001) \ + /* allow access to only LUN 0 */ \ + US_FLAG(NEED_OVERRIDE, 0x00000002) \ + /* unusual_devs entry is necessary */ \ + US_FLAG(SCM_MULT_TARG, 0x00000004) \ + /* supports multiple targets */ \ + US_FLAG(FIX_INQUIRY, 0x00000008) \ + /* INQUIRY response needs faking */ \ + US_FLAG(FIX_CAPACITY, 0x00000010) \ + /* READ CAPACITY response too big */ \ + US_FLAG(IGNORE_RESIDUE, 0x00000020) \ + /* reported residue is wrong */ \ + US_FLAG(BULK32, 0x00000040) \ + /* Uses 32-byte CBW length */ \ + US_FLAG(NOT_LOCKABLE, 0x00000080) \ + /* PREVENT/ALLOW not supported */ \ + US_FLAG(GO_SLOW, 0x00000100) \ + /* Need delay after Command phase */ \ + US_FLAG(NO_WP_DETECT, 0x00000200) \ + /* Don't check for write-protect */ \ + +#define US_FLAG(name, value) US_FL_##name = value , +enum { US_DO_ALL_FLAGS }; +#undef US_FLAG /* Dynamic flag definitions: used in set_bit() etc. */ #define US_FLIDX_URB_ACTIVE 18 /* 0x00040000 current_urb is in use */ @@ -139,7 +157,6 @@ proto_cmnd proto_handler; /* protocol handler */ /* SCSI interfaces */ - struct Scsi_Host *host; /* our dummy host data */ struct scsi_cmnd *srb; /* current srb */ /* thread information */ @@ -154,19 +171,22 @@ dma_addr_t iobuf_dma; /* mutual exclusion and synchronization structures */ - struct semaphore sema; /* to sleep thread on */ - struct completion notify; /* thread begin/end */ - wait_queue_head_t dev_reset_wait; /* wait during reset */ - wait_queue_head_t scsi_scan_wait; /* wait before scanning */ - struct completion scsi_scan_done; /* scan thread end */ + struct semaphore sema; /* to sleep thread on */ + struct completion notify; /* thread begin/end */ + wait_queue_head_t delay_wait; /* wait during scan, reset */ /* subdriver information */ void *extra; /* Any extra data */ extra_data_destructor extra_destructor;/* extra data destructor */ }; -/* The structure which defines our driver */ -extern struct usb_driver usb_storage_driver; +/* Convert between us_data and the corresponding Scsi_Host */ +static struct Scsi_Host inline *us_to_host(struct us_data *us) { + return container_of((void *) us, struct Scsi_Host, hostdata); +} +static struct us_data inline *host_to_us(struct Scsi_Host *host) { + return (struct us_data *) host->hostdata; +} /* Function to fill an inquiry response. See usb.c for details */ extern void fill_inquiry_response(struct us_data *us, diff -Nru a/include/linux/usb.h b/include/linux/usb.h --- a/include/linux/usb.h 2005-03-24 18:21:08 -08:00 +++ b/include/linux/usb.h 2005-03-24 18:21:08 -08:00 @@ -949,11 +949,11 @@ void usb_buffer_free (struct usb_device *dev, size_t size, void *addr, dma_addr_t dma); -struct urb *usb_buffer_map (struct urb *urb); #if 0 +struct urb *usb_buffer_map (struct urb *urb); void usb_buffer_dmasync (struct urb *urb); -#endif void usb_buffer_unmap (struct urb *urb); +#endif struct scatterlist; int usb_buffer_map_sg (struct usb_device *dev, unsigned pipe, diff -Nru a/include/linux/usb_cdc.h b/include/linux/usb_cdc.h --- a/include/linux/usb_cdc.h 2005-03-24 18:21:08 -08:00 +++ b/include/linux/usb_cdc.h 2005-03-24 18:21:08 -08:00 @@ -6,8 +6,12 @@ * firmware based USB peripherals. */ -#define USB_CDC_SUBCLASS_ACM 2 -#define USB_CDC_SUBCLASS_ETHERNET 6 +#define USB_CDC_SUBCLASS_ACM 0x02 +#define USB_CDC_SUBCLASS_ETHERNET 0x06 +#define USB_CDC_SUBCLASS_WHCM 0x08 +#define USB_CDC_SUBCLASS_DMM 0x09 +#define USB_CDC_SUBCLASS_MDLM 0x0a +#define USB_CDC_SUBCLASS_OBEX 0x0b #define USB_CDC_PROTO_NONE 0 @@ -31,6 +35,11 @@ #define USB_CDC_UNION_TYPE 0x06 /* union_desc */ #define USB_CDC_COUNTRY_TYPE 0x07 #define USB_CDC_ETHERNET_TYPE 0x0f /* ether_desc */ +#define USB_CDC_WHCM_TYPE 0x11 +#define USB_CDC_MDLM_TYPE 0x12 /* mdlm_desc */ +#define USB_CDC_MDLM_DETAIL_TYPE 0x13 /* mdlm_detail_desc */ +#define USB_CDC_DMM_TYPE 0x14 +#define USB_CDC_OBEX_TYPE 0x15 /* "Header Functional Descriptor" from CDC spec 5.2.3.1 */ struct usb_cdc_header_desc { @@ -85,6 +94,27 @@ __le16 wMaxSegmentSize; __le16 wNumberMCFilters; __u8 bNumberPowerFilters; +} __attribute__ ((packed)); + +/* "MDLM Functional Descriptor" from CDC WMC spec 6.7.2.3 */ +struct usb_cdc_mdlm_desc { + __u8 bLength; + __u8 bDescriptorType; + __u8 bDescriptorSubType; + + __le16 bcdVersion; + __u8 bGUID[16]; +} __attribute__ ((packed)); + +/* "MDLM Detail Functional Descriptor" from CDC WMC spec 6.7.2.4 */ +struct usb_cdc_mdlm_detail_desc { + __u8 bLength; + __u8 bDescriptorType; + __u8 bDescriptorSubType; + + /* type is associated with mdlm_desc.bGUID */ + __u8 bGuidDescriptorType; + __u8 bDetailData[]; } __attribute__ ((packed)); /*-------------------------------------------------------------------------*/