bk://kernel.bkbits.net/gregkh/linux/usb-2.6 gregkh@suse.de|ChangeSet|20050323232640|61922 gregkh # This is a BitKeeper generated diff -Nru style 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/drivers/block/ub.c b/drivers/block/ub.c --- a/drivers/block/ub.c 2005-03-23 19:58:52 -08:00 +++ b/drivers/block/ub.c 2005-03-23 19:58:52 -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. 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-23 19:58:52 -08:00 +++ b/drivers/media/video/cpia_usb.c 2005-03-23 19:58:52 -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-23 19:58:52 -08:00 +++ b/drivers/usb/Makefile 2005-03-23 19:58:52 -08:00 @@ -51,7 +51,6 @@ obj-$(CONFIG_USB_RTL8150) += net/ obj-$(CONFIG_USB_USBNET) += 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-23 19:58:53 -08:00 +++ b/drivers/usb/class/usb-midi.c 2005-03-23 19:58:53 -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-23 19:58:52 -08:00 +++ b/drivers/usb/core/buffer.c 2005-03-23 19:58:52 -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-23 19:58:52 -08:00 +++ b/drivers/usb/core/config.c 2005-03-23 19:58:52 -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/hcd-pci.c b/drivers/usb/core/hcd-pci.c --- a/drivers/usb/core/hcd-pci.c 2005-03-23 19:58:52 -08:00 +++ b/drivers/usb/core/hcd-pci.c 2005-03-23 19:58:52 -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-23 19:58:52 -08:00 +++ b/drivers/usb/core/hcd.c 2005-03-23 19:58:52 -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-23 19:58:52 -08:00 +++ b/drivers/usb/core/hcd.h 2005-03-23 19:58:52 -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-23 19:58:52 -08:00 +++ b/drivers/usb/core/hub.c 2005-03-23 19:58:52 -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-23 19:58:52 -08:00 +++ b/drivers/usb/core/hub.h 2005-03-23 19:58:52 -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-23 19:58:52 -08:00 +++ b/drivers/usb/core/message.c 2005-03-23 19:58:52 -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-23 19:58:52 -08:00 +++ b/drivers/usb/core/usb.c 2005-03-23 19:58:52 -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); @@ -1148,6 +1148,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 +1178,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 +1223,7 @@ * * Reverses the effect of usb_buffer_map(). */ +#if 0 void usb_buffer_unmap (struct urb *urb) { struct usb_bus *bus; @@ -1247,6 +1250,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 +1531,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-23 19:58:52 -08:00 +++ b/drivers/usb/core/usb.h 2005-03-23 19:58:52 -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-23 19:58:52 -08:00 +++ b/drivers/usb/gadget/Kconfig 2005-03-23 19:58:52 -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 @@ -221,6 +178,38 @@ later, when two dual-role devices talk to each other. 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 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-23 19:58:52 -08:00 +++ b/drivers/usb/gadget/dummy_hcd.c 2005-03-23 19:58:52 -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-23 19:58:52 -08:00 +++ b/drivers/usb/gadget/ether.c 2005-03-23 19:58:52 -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-23 19:58:53 -08:00 +++ b/drivers/usb/gadget/file_storage.c 2005-03-23 19:58:53 -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"}, {} }; @@ -3740,6 +3746,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-23 19:58:52 -08:00 +++ b/drivers/usb/gadget/gadget_chips.h 2005-03-23 19:58:52 -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/net2280.c b/drivers/usb/gadget/net2280.c --- a/drivers/usb/gadget/net2280.c 2005-03-23 19:58:52 -08:00 +++ b/drivers/usb/gadget/net2280.c 2005-03-23 19:58:52 -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/serial.c b/drivers/usb/gadget/serial.c --- a/drivers/usb/gadget/serial.c 2005-03-23 19:58:52 -08:00 +++ b/drivers/usb/gadget/serial.c 2005-03-23 19:58:52 -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/zero.c b/drivers/usb/gadget/zero.c --- a/drivers/usb/gadget/zero.c 2005-03-23 19:58:52 -08:00 +++ b/drivers/usb/gadget/zero.c 2005-03-23 19:58:52 -08:00 @@ -1193,6 +1193,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-23 19:58:53 -08:00 +++ b/drivers/usb/host/ehci-hcd.c 2005-03-23 19:58:53 -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-23 19:58:52 -08:00 +++ b/drivers/usb/host/ehci-hub.c 2005-03-23 19:58:52 -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-23 19:58:52 -08:00 +++ b/drivers/usb/host/ehci-q.c 2005-03-23 19:58:52 -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-23 19:58:53 -08:00 +++ b/drivers/usb/host/ehci-sched.c 2005-03-23 19:58:53 -08:00 @@ -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; } @@ -1864,7 +1864,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 +1898,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 +1987,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/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c --- a/drivers/usb/host/ohci-hcd.c 2005-03-23 19:58:52 -08:00 +++ b/drivers/usb/host/ohci-hcd.c 2005-03-23 19:58:52 -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-23 19:58:52 -08:00 +++ b/drivers/usb/host/ohci-hub.c 2005-03-23 19:58:52 -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-23 19:58:52 -08:00 +++ b/drivers/usb/host/ohci-omap.c 2005-03-23 19:58:52 -08:00 @@ -499,7 +499,7 @@ 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); 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-23 19:58:52 -08:00 +++ b/drivers/usb/host/ohci-q.c 2005-03-23 19:58:52 -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-23 19:58:53 -08:00 +++ b/drivers/usb/host/ohci.h 2005-03-23 19:58:53 -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-23 19:58:52 -08:00 +++ b/drivers/usb/host/sl811-hcd.c 2005-03-23 19:58:52 -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-23 19:58:52 -08:00 +++ b/drivers/usb/host/uhci-debug.c 2005-03-23 19:58:52 -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-23 19:58:53 -08:00 +++ b/drivers/usb/host/uhci-hcd.c 2005-03-23 19:58:53 -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-23 19:58:52 -08:00 +++ b/drivers/usb/host/uhci-hcd.h 2005-03-23 19:58:52 -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-23 19:58:52 -08:00 +++ b/drivers/usb/host/uhci-hub.c 2005-03-23 19:58:52 -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-23 19:58:52 -08:00 +++ b/drivers/usb/host/uhci-q.c 2005-03-23 19:58:52 -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-23 19:58:52 -08:00 +++ b/drivers/usb/image/Kconfig 2005-03-23 19:58:52 -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-23 19:58:53 -08:00 +++ b/drivers/usb/image/Makefile 2005-03-23 19:58:53 -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-23 19:58:53 -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-23 19:58:52 -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-23 19:58:53 -08:00 +++ b/drivers/usb/image/microtek.c 2005-03-23 19:58:53 -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-23 19:58:52 -08:00 +++ b/drivers/usb/input/aiptek.c 2005-03-23 19:58:52 -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-23 19:58:52 -08:00 +++ b/drivers/usb/media/ibmcam.c 2005-03-23 19:58:52 -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-23 19:58:52 -08:00 +++ b/drivers/usb/media/pwc/pwc-if.c 2005-03-23 19:58:52 -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-23 19:58:52 -08:00 +++ b/drivers/usb/misc/emi26.c 2005-03-23 19:58:52 -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-23 19:58:52 -08:00 +++ b/drivers/usb/misc/rio500.c 2005-03-23 19:58:52 -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-23 19:58:52 -08:00 +++ b/drivers/usb/misc/sisusbvga/sisusb.c 2005-03-23 19:58:52 -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/net/catc.c b/drivers/usb/net/catc.c --- a/drivers/usb/net/catc.c 2005-03-23 19:58:52 -08:00 +++ b/drivers/usb/net/catc.c 2005-03-23 19:58:52 -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-23 19:58:52 -08:00 +++ b/drivers/usb/net/kaweth.c 2005-03-23 19:58:52 -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-23 19:58:52 -08:00 +++ b/drivers/usb/net/kawethfw.h 2005-03-23 19:58:52 -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-23 19:58:52 -08:00 +++ b/drivers/usb/net/pegasus.c 2005-03-23 19:58:53 -08:00 @@ -956,7 +956,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); @@ -1156,10 +1157,10 @@ } -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); diff -Nru a/drivers/usb/net/usbnet.c b/drivers/usb/net/usbnet.c --- a/drivers/usb/net/usbnet.c 2005-03-23 19:58:52 -08:00 +++ b/drivers/usb/net/usbnet.c 2005-03-23 19:58:52 -08:00 @@ -185,6 +185,7 @@ // i/o info: pipes etc unsigned in, out; + struct usb_host_endpoint *status; unsigned maxpacket; struct timer_list delay; @@ -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); @@ -312,38 +318,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 +376,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 -ENODEV; + + 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; @@ -1414,6 +1473,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 +1524,51 @@ } } + +static void dumpspeed (struct usbnet *dev, __le32 *speeds) +{ + 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: + 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 */ + 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 +1647,7 @@ // .check_connect = cdc_check_connect, .bind = cdc_bind, .unbind = cdc_unbind, + .status = cdc_status, }; #endif /* CONFIG_USB_CDCETHER */ @@ -2526,11 +2654,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 +2716,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, @@ -2871,6 +3012,42 @@ #endif /* VERBOSE */ } +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 +#ifdef VERBOSE + devdbg (dev, "intr shutdown, code %d", status); +#endif + 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) + deverr(dev, "intr resubmit --> %d", status); +} + /*-------------------------------------------------------------------------*/ // unlink pending rx/tx; completion handlers do all other cleanup @@ -2938,6 +3115,8 @@ 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. @@ -2976,6 +3155,15 @@ goto done; } + /* start any status interrupt transfer */ + if (dev->interrupt) { + retval = usb_submit_urb (dev->interrupt, GFP_KERNEL); + if (retval < 0) { + deverr (dev, "intr submit %d", retval); + goto done; + } + } + netif_start_queue (net); if (dev->msg_level >= 2) { char *framing; @@ -3479,6 +3667,8 @@ status = 0; } + if (status == 0 && dev->status) + status = init_status (dev, udev); if (status < 0) goto out1; @@ -3729,6 +3919,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 +3977,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/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c --- a/drivers/usb/serial/digi_acceleport.c 2005-03-23 19:58:52 -08:00 +++ b/drivers/usb/serial/digi_acceleport.c 2005-03-23 19:58:52 -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-23 19:58:52 -08:00 +++ b/drivers/usb/serial/ftdi_sio.c 2005-03-23 19:58:52 -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-23 19:58:52 -08:00 +++ b/drivers/usb/serial/garmin_gps.c 2005-03-23 19:58:52 -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-23 19:58:52 -08:00 +++ b/drivers/usb/serial/ipw.c 2005-03-23 19:58:52 -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/visor.c b/drivers/usb/serial/visor.c --- a/drivers/usb/serial/visor.c 2005-03-23 19:58:52 -08:00 +++ b/drivers/usb/serial/visor.c 2005-03-23 19:58:52 -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/datafab.c b/drivers/usb/storage/datafab.c --- a/drivers/usb/storage/datafab.c 2005-03-23 19:58:53 -08:00 +++ b/drivers/usb/storage/datafab.c 2005-03-23 19:58:53 -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-23 19:58:53 -08:00 +++ b/drivers/usb/storage/debug.h 2005-03-23 19:58:53 -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-23 19:58:52 -08:00 +++ b/drivers/usb/storage/dpcm.c 2005-03-23 19:58:52 -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-23 19:58:53 -08:00 +++ b/drivers/usb/storage/freecom.c 2005-03-23 19:58:53 -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-23 19:58:52 -08:00 +++ b/drivers/usb/storage/initializers.c 2005-03-23 19:58:52 -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-23 19:58:53 -08:00 +++ b/drivers/usb/storage/isd200.c 2005-03-23 19:58:53 -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-23 19:58:52 -08:00 +++ b/drivers/usb/storage/jumpshot.c 2005-03-23 19:58:52 -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-23 19:58:52 -08:00 +++ b/drivers/usb/storage/protocol.c 2005-03-23 19:58:52 -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-23 19:58:52 -08:00 +++ b/drivers/usb/storage/protocol.h 2005-03-23 19:58:52 -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-23 19:58:52 -08:00 +++ b/drivers/usb/storage/scsiglue.c 2005-03-23 19:58:52 -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" @@ -337,14 +336,13 @@ #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) { struct us_data *us; char *pos = buffer; + const char *string; /* if someone is sending us data, just throw it away */ if (inout) @@ -357,21 +355,24 @@ /* 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 +382,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 +489,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-23 19:58:52 -08:00 +++ b/drivers/usb/storage/scsiglue.h 2005-03-23 19:58:52 -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-23 19:58:53 -08:00 +++ b/drivers/usb/storage/sddr09.c 2005-03-23 19:58:53 -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-23 19:58:52 -08:00 +++ b/drivers/usb/storage/sddr55.c 2005-03-23 19:58:52 -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-23 19:58:52 -08:00 +++ b/drivers/usb/storage/shuttle_usbat.c 2005-03-23 19:58:52 -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-23 19:58:52 -08:00 +++ b/drivers/usb/storage/shuttle_usbat.h 2005-03-23 19:58:52 -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-23 19:58:52 -08:00 +++ b/drivers/usb/storage/transport.c 2005-03-23 19:58:52 -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) { diff -Nru a/drivers/usb/storage/transport.h b/drivers/usb/storage/transport.h --- a/drivers/usb/storage/transport.h 2005-03-23 19:58:52 -08:00 +++ b/drivers/usb/storage/transport.h 2005-03-23 19:58:52 -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-23 19:58:52 -08:00 +++ b/drivers/usb/storage/unusual_devs.h 2005-03-23 19:58:52 -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, @@ -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,12 +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", @@ -696,6 +712,13 @@ "SIIG/Datafab Memory Stick+CF Reader/Writer", 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", diff -Nru a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c --- a/drivers/usb/storage/usb.c 2005-03-23 19:58:52 -08:00 +++ b/drivers/usb/storage/usb.c 2005-03-23 19:58:52 -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"); @@ -225,7 +224,7 @@ { NULL } }; -struct usb_driver usb_storage_driver = { +static struct usb_driver usb_storage_driver = { .owner = THIS_MODULE, .name = "usb-storage", .probe = storage_probe, @@ -787,7 +786,7 @@ } /* 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__); @@ -830,11 +829,8 @@ 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 */ diff -Nru a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h --- a/drivers/usb/storage/usb.h 2005-03-23 19:58:52 -08:00 +++ b/drivers/usb/storage/usb.h 2005-03-23 19:58:52 -08:00 @@ -48,6 +48,7 @@ #include #include #include +#include struct us_data; struct scsi_cmnd; @@ -65,18 +66,33 @@ 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 */ \ + +#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 */ @@ -164,9 +180,6 @@ 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; /* 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-23 19:58:52 -08:00 +++ b/include/linux/usb.h 2005-03-23 19:58:52 -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-23 19:58:52 -08:00 +++ b/include/linux/usb_cdc.h 2005-03-23 19:58:52 -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)); /*-------------------------------------------------------------------------*/