bk://kernel.bkbits.net/gregkh/linux/usb-2.6 stern@rowland.harvard.edu|ChangeSet|20040702225747|56493 stern # This is a BitKeeper generated diff -Nru style patch. # # ChangeSet # 2004/07/03 13:36:37-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb # # MAINTAINERS # 2004/07/03 13:36:33-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/07/02 22:36:07-07:00 akpm@bix.(none) # Merge bk://kernel.bkbits.net/gregkh/linux/usb-2.6 # into bix.(none):/usr/src/bk-usb # # include/linux/usb.h # 2004/07/02 22:36:04-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/usb/storage/scsiglue.c # 2004/07/02 22:36:04-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/usb/core/usb.c # 2004/07/02 22:36:04-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/usb/core/message.c # 2004/07/02 22:36:04-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/usb/core/devio.c # 2004/07/02 22:36:04-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/07/02 15:33:56-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb # # ChangeSet # 2004/07/02 15:57:47-07:00 stern@rowland.harvard.edu # [PATCH] USB: Remove hub's children upon unbinding # # This patch fixes a logical hole in the hub driver. It's possible for the # driver to be unbound from a hub without physically unplugging the hub. # For example, writing 0 into the bConfigurationValue attribute file will # have this effect. When this happens, we need to make sure that all the # child devices of the hub are logically disconnected and their ports # disabled. # # That's what this patch does. It's a little bit tricky because we can't # simply call usb_disconnect() from within the hub driver's disconnect() # routine. While that routine is running it holds the usb bus writelock, # but usb_disconnect() would try to acquire it again. Instead # schedule_work() is used, so after a brief delay the children will be # removed. # # Signed-off-by: Alan Stern # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/core/hub.c # 2004/07/01 07:53:20-07:00 stern@rowland.harvard.edu +41 -2 # USB: Remove hub's children upon unbinding # # ChangeSet # 2004/07/02 15:56:49-07:00 stern@rowland.harvard.edu # [PATCH] USB: Store pointer to usb_device in private hub structure # # This patch adds a pointer to the hub's usb_device into the usb_hub private # structure. It's a small change, and permits a small amount of # simplification in a few spots, i.e., avoid calling interface_to_usbdev(). # This doesn't really do much in itself, but it's a prerequisite for the # next patch. (A situation arises where we can't use the interface pointer # to find the usb_device because the interface might not exist.) # # Signed-off-by: Alan Stern # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/core/hub.h # 2004/07/01 04:48:09-07:00 stern@rowland.harvard.edu +1 -0 # USB: Store pointer to usb_device in private hub structure # # drivers/usb/core/hub.c # 2004/07/01 07:26:05-07:00 stern@rowland.harvard.edu +17 -18 # USB: Store pointer to usb_device in private hub structure # # ChangeSet # 2004/07/02 15:54:11-07:00 stern@rowland.harvard.edu # [PATCH] USB: Disallow probing etc. for suspended devices # # One of the few points from the recent discussion that all participants # agreed on was that we should not allow probing or config changes to be # attempted on suspended devices. This patch implements that policy, and it # also prevents attempts to change altsettings. That's just for # consistency's sake; even without the patch an attempted altsetting change # on a suspended device would simply fail without doing any harm. By # contrast, a configuration change would unbind all the existing drivers # before encountering an error, something we don't want to happen. # # Signed-off-by: Alan Stern # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/core/usb.c # 2004/06/30 06:44:26-07:00 stern@rowland.harvard.edu +2 -0 # USB: Disallow probing etc. for suspended devices # # drivers/usb/core/message.c # 2004/06/30 06:48:12-07:00 stern@rowland.harvard.edu +9 -0 # USB: Disallow probing etc. for suspended devices # # include/linux/pci_ids.h # 2004/07/02 15:33:52-07:00 akpm@bix.(none) +0 -0 # Auto merged # # MAINTAINERS # 2004/07/02 15:33:52-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/07/02 15:25:25-07:00 stern@rowland.harvard.edu # [PATCH] USB: Don't ask for string descriptor lengths # # Okay, here's a revised patch (as332b). This tries first to ask for 255 # bytes, and if that fails then it asks for the length and the full # descriptor. Hopefully nobody will object to applying this version... # # You know, it occurs to me that the have_langid field in usb_device could # easily be eliminated. Just set string_langid to -1 during initialization # and test for whether or not it is >= 0. I'll do that some other time. # # # Signed-off-by: Alan Stern # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/core/message.c # 2004/06/25 08:04:06-07:00 stern@rowland.harvard.edu +121 -101 # USB: Don't ask for string descriptor lengths # # ChangeSet # 2004/07/02 15:24:44-07:00 stern@rowland.harvard.edu # [PATCH] USB: Don't track endpoint halts in usbcore # # The current mechanism for keeping track of which endpoints in a device are # halted is both flawed and unnecessary. It's flawed because devices are # free to change the endpoint status whenever they want without telling us, # and it's unnecessary because an URB submitted for a halted endpoint will # quickly receive an error indication. # # This patch removes the code associated with tracking halts: the halted[] # member of usb_device, the usb_endpoint_halt, usb_endpoint_halted, and # usb_endpoint_running macros, all the places where they are used or # checked, and the places in the host controller drivers where they get set. # # This is part of my ongoing program for cleaning up usbcore. Please apply. # # # Signed-off-by: Alan Stern # Signed-off-by: Greg Kroah-Hartman # # include/linux/usb.h # 2004/06/24 09:44:16-07:00 stern@rowland.harvard.edu +0 -6 # USB: Don't track endpoint halts in usbcore # # drivers/usb/storage/transport.c # 2004/06/24 09:44:16-07:00 stern@rowland.harvard.edu +1 -3 # USB: Don't track endpoint halts in usbcore # # drivers/usb/image/microtek.c # 2004/06/24 09:44:16-07:00 stern@rowland.harvard.edu +2 -2 # USB: Don't track endpoint halts in usbcore # # drivers/usb/host/uhci-hcd.c # 2004/06/24 09:44:16-07:00 stern@rowland.harvard.edu +0 -4 # USB: Don't track endpoint halts in usbcore # # drivers/usb/host/ohci-q.c # 2004/06/24 09:44:16-07:00 stern@rowland.harvard.edu +0 -6 # USB: Don't track endpoint halts in usbcore # # drivers/usb/host/hc_simple.c # 2004/06/24 09:44:15-07:00 stern@rowland.harvard.edu +0 -5 # USB: Don't track endpoint halts in usbcore # # drivers/usb/host/ehci-q.c # 2004/06/24 09:44:16-07:00 stern@rowland.harvard.edu +2 -10 # USB: Don't track endpoint halts in usbcore # # drivers/usb/core/urb.c # 2004/06/24 09:44:16-07:00 stern@rowland.harvard.edu +0 -7 # USB: Don't track endpoint halts in usbcore # # drivers/usb/core/message.c # 2004/06/24 09:44:15-07:00 stern@rowland.harvard.edu +7 -17 # USB: Don't track endpoint halts in usbcore # # drivers/usb/core/hub.c # 2004/06/24 09:44:16-07:00 stern@rowland.harvard.edu +1 -5 # USB: Don't track endpoint halts in usbcore # # drivers/usb/core/hcd.h # 2004/06/24 09:44:16-07:00 stern@rowland.harvard.edu +0 -2 # USB: Don't track endpoint halts in usbcore # # drivers/usb/core/hcd.c # 2004/06/24 09:44:16-07:00 stern@rowland.harvard.edu +2 -5 # USB: Don't track endpoint halts in usbcore # # drivers/usb/core/devices.c # 2004/06/24 09:44:16-07:00 stern@rowland.harvard.edu +1 -2 # USB: Don't track endpoint halts in usbcore # # drivers/isdn/hisax/st5481_usb.c # 2004/06/24 09:44:15-07:00 stern@rowland.harvard.edu +0 -3 # USB: Don't track endpoint halts in usbcore # # ChangeSet # 2004/07/02 15:23:56-07:00 stern@rowland.harvard.edu # [PATCH] USB: Implement usb_lock_device_for_reset() # # This patch creates a special locking routine intended specifically for use # when calling usb_reset_device(). A special routine like this is needed to # avoid deadlocks with disconnect(). Symbolically: # # Khubd Driver # ----- ------ # Wants to reset a device, so calls # its own do_reset() function # Receives connect-change # notification and calls # usb_disconnect() # # Locks the device and calls # driver->disconnect() # do_reset() tries to lock the # device for the reset, and blocks # disconnect() can't return # until do_reset() is finished # # One simple-minded way out would be for the driver's do_reset routine to # use usb_trylock_device(). I don't like this because it will fail if the # device happens to be locked for some innocuous reason, like somebody # reading its entry in /proc/bus/usb/devices. # # Instead, usb_lock_device_for_reset() calls usb_trylock_device() # repeatedly, in a polling loop. It is careful to check that the device # state isn't NOTATTACHED and that the driver's interface isn't being # unbound; this will allow the lock-and-reset sequence to fail in scenarios # like the one above. # # For the new routine to be able to tell when an interface is being unbound, # I had to add an additional field to struct usb_interface. It's a simple # enumeration with four possible values: # # USB_INTERFACE_UNBOUND, USB_INTERFACE_BINDING, # USB_INTERFACE_BOUND, USB_INTERFACE_UNBINDING # # The extra overhead of the new field is not large enough to matter. # # A quick summary: # # Rename __usb_reset_device to usb_reset_device and get rid of # the alternate entry point. # # Notify the HCD that endpoint-0's maxpacket size may change # during a device reset (should have been written earlier). # # Add the new usb_interface_condition enumeration field to # struct usb_interface. # # Set the new field appropriately as interfaces are bound, # unbound, claimed, and released. # # Add usb_lock_device_for_reset(). # # Change the usb-storage, microtek, and stir4200 IRDA drivers # to make them use the new locking routine. # # With this patch applied, and using an altered gadget driver that forces # usb-storage to request a device reset, I've been able to go through a # large number of different tests successfully. Reset during probe(), # reset after probe(), disconnect during reset(), reset with device # descriptor changing... They all work beautifully. # # Signed-off-by: Alan Stern # Signed-off-by: Greg Kroah-Hartman # # include/linux/usb.h # 2004/06/24 07:09:11-07:00 stern@rowland.harvard.edu +13 -2 # USB: Implement usb_lock_device_for_reset() # # drivers/usb/storage/scsiglue.c # 2004/06/24 07:09:11-07:00 stern@rowland.harvard.edu +11 -3 # USB: Implement usb_lock_device_for_reset() # # drivers/usb/image/microtek.h # 2004/06/24 07:09:11-07:00 stern@rowland.harvard.edu +1 -0 # USB: Implement usb_lock_device_for_reset() # # drivers/usb/image/microtek.c # 2004/06/24 07:09:11-07:00 stern@rowland.harvard.edu +9 -2 # USB: Implement usb_lock_device_for_reset() # # drivers/usb/core/usb.c # 2004/06/24 07:09:11-07:00 stern@rowland.harvard.edu +53 -0 # USB: Implement usb_lock_device_for_reset() # # drivers/usb/core/hub.c # 2004/06/24 07:09:11-07:00 stern@rowland.harvard.edu +10 -13 # USB: Implement usb_lock_device_for_reset() # # drivers/usb/core/devio.c # 2004/06/24 07:09:11-07:00 stern@rowland.harvard.edu +1 -1 # USB: Implement usb_lock_device_for_reset() # # drivers/net/irda/stir4200.c # 2004/06/24 07:09:11-07:00 stern@rowland.harvard.edu +10 -0 # USB: Implement usb_lock_device_for_reset() # # ChangeSet # 2004/07/02 15:22:54-07:00 stern@rowland.harvard.edu # [PATCH] USB: Implement usb_lock_device() and friends # # This patch plugs a major hole in USB device locking. Whenever a new # driver is loaded and the matching unbound interfaces are probed, no # devices are locked! Similarly, when a driver is unloaded and its # interfaces are unbound, nothing is locked. # # The patch fixes the problem by introducing a new rwsem and encapsulating # the locking procedures. To lock a single device, the new routine # usb_lock_device() gets a readlock on the rwsem and a lock on the device's # ->serialize. When drivers are loaded or removed, all devices are # effectively locked by getting a writelock on the rwsem. The rwsem is # also writelocked in one other oddball circumstance: when telling the # driver-model core to reprobe all the unbound interfaces on a bus. # # Details of the patch: # # Implement usb_lock_device(), usb_unlock_device(), # usb_lock_all_devices(), usb_unlock_all_devices(), and # usb_trylock_device(). # # Call usb_(un)lock_all_devices() when registering and # deregistering USB drivers and when calling bus_rescan_devices(). # # Convert all existing places that access usbdev->serialize # directly to make them call the appropriate locking routine. # # Add comments warning about the need to use the new routines, # and change the terminology in existing comments to talk about # locking a device rather than owning usbdev->serialize. # # Add proper locking to usb_find_device() and match_device(), # to protect against topology changes while scanning the # device tree. # # With this change, the USB device locking model is almost complete. There # remains only the need for appropriate locking for routines that call # usb_reset_device(). That patch will come next. # # # Signed-off-by: Alan Stern # Signed-off-by: Greg Kroah-Hartman # # include/linux/usb.h # 2004/06/24 03:41:12-07:00 stern@rowland.harvard.edu +16 -0 # USB: Implement usb_lock_device() and friends # # drivers/usb/host/ohci-pci.c # 2004/06/24 03:41:12-07:00 stern@rowland.harvard.edu +4 -4 # USB: Implement usb_lock_device() and friends # # drivers/usb/host/ohci-hub.c # 2004/06/24 03:41:12-07:00 stern@rowland.harvard.edu +5 -5 # USB: Implement usb_lock_device() and friends # # drivers/usb/host/ehci-hub.c # 2004/06/24 03:41:12-07:00 stern@rowland.harvard.edu +1 -1 # USB: Implement usb_lock_device() and friends # # drivers/usb/core/usb.h # 2004/06/24 03:41:12-07:00 stern@rowland.harvard.edu +3 -0 # USB: Implement usb_lock_device() and friends # # drivers/usb/core/usb.c # 2004/06/24 03:41:12-07:00 stern@rowland.harvard.edu +88 -7 # USB: Implement usb_lock_device() and friends # # drivers/usb/core/sysfs.c # 2004/06/24 03:41:12-07:00 stern@rowland.harvard.edu +2 -2 # USB: Implement usb_lock_device() and friends # # drivers/usb/core/message.c # 2004/06/24 03:41:12-07:00 stern@rowland.harvard.edu +7 -7 # USB: Implement usb_lock_device() and friends # # drivers/usb/core/hub.c # 2004/06/24 03:41:12-07:00 stern@rowland.harvard.edu +7 -7 # USB: Implement usb_lock_device() and friends # # drivers/usb/core/hcd.c # 2004/06/24 03:41:12-07:00 stern@rowland.harvard.edu +4 -4 # USB: Implement usb_lock_device() and friends # # drivers/usb/core/devio.c # 2004/06/24 03:41:12-07:00 stern@rowland.harvard.edu +13 -9 # USB: Implement usb_lock_device() and friends # # drivers/usb/core/devices.c # 2004/06/24 03:41:12-07:00 stern@rowland.harvard.edu +5 -5 # USB: Implement usb_lock_device() and friends # # ChangeSet # 2004/07/02 15:22:14-07:00 stern@rowland.harvard.edu # [PATCH] USB: Make hub driver use usb_kill_urb() # # This is a rerun of as278, updated to match the current source. It changes # the hub driver, replacing calls to synchronous usb_unlink_urb() with # usb_kill_urb() and removing the machinery formerly needed to synchronize # the status URB handler with the rest of the driver. # # # Signed-off-by: Alan Stern # Signed-off-by: Greg Kroah-Hartman # # drivers/usb/core/hub.h # 2004/06/23 07:02:05-07:00 stern@rowland.harvard.edu +0 -2 # USB: Make hub driver use usb_kill_urb() # # drivers/usb/core/hub.c # 2004/06/23 07:07:26-07:00 stern@rowland.harvard.edu +12 -28 # USB: Make hub driver use usb_kill_urb() # # ChangeSet # 2004/07/02 15:21:04-07:00 stern@rowland.harvard.edu # [PATCH] USB: Add usb_kill_urb() # # This patch is a slightly revised version of as277c, updated to match the # current source. The only difference from the older version is that this # makes urb->use_count into an atomic_t, to avoid the overhead of an extra # locking step each time an URB is submitted and given back. The important # features of this patch are: # # -EPERM added to Documentation/usb/error-codes.txt. # # Failure to use URB_ASYNC_UNLINK with usb_unlink_urb() is # deprecated in the documentation. # # New ->reject and ->use_count fields added to struct urb. # The reject field is protected by urb->lock, and locking is # required only in usb_kill_urb() which doesn't have to be fast. # # Single wait_queue used for all processes waiting inside # usb_kill_urb(). The wait queue is woken up only when an URB # is given back with ->reject set. # # usb_rh_status_dequeue() changed to return int. It looks like # this function should be declared static; it's not used outside # the hcd.c file. # # Prototype for unlink_urb() in struct usb_operations is changed # to include a status code argument. This is necessary so that # the different unlink paths can return -ENOENT and -ECONNRESET # as appropriate. # # Support for synchronous usb_unlink_urb() has been removed; # such calls are passed to usb_kill_urb(). # # Kerneldoc for usb_unlink_urb() is updated. # # usb_kill_urb() added to urb.c. # # hc_simple() host driver is partially updated -- it should # compile but it won't really work right. # # # Signed-off-by: Alan Stern # Signed-off-by: Greg Kroah-Hartman # # include/linux/usb.h # 2004/06/23 08:00:50-07:00 stern@rowland.harvard.edu +7 -2 # USB: Add usb_kill_urb() # # drivers/usb/host/hc_simple.c # 2004/06/23 08:00:50-07:00 stern@rowland.harvard.edu +10 -34 # USB: Add usb_kill_urb() # # drivers/usb/core/urb.c # 2004/06/23 08:00:50-07:00 stern@rowland.harvard.edu +56 -18 # USB: Add usb_kill_urb() # # drivers/usb/core/hcd.h # 2004/06/23 08:00:50-07:00 stern@rowland.harvard.edu +3 -2 # USB: Add usb_kill_urb() # # drivers/usb/core/hcd.c # 2004/06/23 08:00:50-07:00 stern@rowland.harvard.edu +43 -96 # USB: Add usb_kill_urb() # # Documentation/usb/error-codes.txt # 2004/06/23 08:00:50-07:00 stern@rowland.harvard.edu +2 -0 # USB: Add usb_kill_urb() # # ChangeSet # 2004/07/01 01:50:59-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb # # include/linux/pci_ids.h # 2004/07/01 01:50:55-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/usb/core/usb.c # 2004/07/01 01:50:55-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/usb/core/message.c # 2004/07/01 01:50:55-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/usb/core/devio.c # 2004/07/01 01:50:55-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/06/30 11:38:35-07:00 akpm@bix.(none) # Merge bk://kernel.bkbits.net/gregkh/linux/usb-2.6 # into bix.(none):/usr/src/bk-usb # # drivers/usb/input/hid-core.c # 2004/06/30 11:38:31-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/06/30 10:48:26-07:00 greg@kroah.com # [PATCH] USB: add 3 Phidget device ids to the HID blacklist. # # drivers/usb/input/hid-core.c # 2004/06/30 10:25:19-07:00 greg@kroah.com +8 -0 # USB: add 3 Phidget device ids to the HID blacklist. # # ChangeSet # 2004/06/29 21:31:17-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb # # fs/aio.c # 2004/06/29 21:31:13-07:00 akpm@bix.(none) +0 -0 # Auto merged # # MAINTAINERS # 2004/06/29 21:31:13-07:00 akpm@bix.(none) +0 -0 # Auto merged # # CREDITS # 2004/06/29 21:31:13-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/06/28 19:30:55-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb # # fs/aio.c # 2004/06/28 19:30:52-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/06/28 00:43:18-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb # # arch/ppc/defconfig # 2004/06/28 00:43:14-07:00 akpm@bix.(none) +0 -0 # Auto merged # # arch/ia64/defconfig # 2004/06/28 00:43:14-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/06/24 18:40:41-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb # # include/linux/pci_ids.h # 2004/06/24 18:40:37-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/06/24 13:02:42-07:00 akpm@bix.(none) # Merge bk://kernel.bkbits.net/gregkh/linux/usb-2.6 # into bix.(none):/usr/src/bk-usb # # drivers/usb/media/pwc-if.c # 2004/06/24 13:02:39-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/usb/media/Kconfig # 2004/06/24 13:02:39-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/usb/gadget/ether.c # 2004/06/24 13:02:39-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/06/24 13:01:44-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb # # include/linux/pci_ids.h # 2004/06/24 13:01:40-07:00 akpm@bix.(none) +0 -0 # Auto merged # # MAINTAINERS # 2004/06/24 13:01:40-07:00 akpm@bix.(none) +0 -0 # Auto merged # # CREDITS # 2004/06/24 13:01:40-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/06/22 12:28:34-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb # # drivers/usb/core/devio.c # 2004/06/22 12:28:30-07:00 akpm@bix.(none) +0 -0 # Auto merged # # MAINTAINERS # 2004/06/22 12:28:30-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/06/20 23:36:26-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb # # CREDITS # 2004/06/20 23:36:01-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/06/19 15:38:35-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb # # arch/ia64/defconfig # 2004/06/19 15:38:31-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/06/18 12:32:27-07:00 akpm@bix.(none) # Merge bk://kernel.bkbits.net/gregkh/linux/usb-2.6 # into bix.(none):/usr/src/bk-usb # # drivers/usb/storage/scsiglue.c # 2004/06/18 12:32:23-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/usb/media/Kconfig # 2004/06/18 12:32:23-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/06/18 12:31:30-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb # # include/linux/pci_ids.h # 2004/06/18 12:31:26-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/usb/storage/scsiglue.c # 2004/06/18 12:31:26-07:00 akpm@bix.(none) +0 -0 # Auto merged # # MAINTAINERS # 2004/06/18 12:31:26-07:00 akpm@bix.(none) +0 -0 # Auto merged # # CREDITS # 2004/06/18 12:31:26-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/06/15 22:24:54-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb # # include/linux/pci_ids.h # 2004/06/15 22:24:51-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/06/13 11:33:57-07:00 akpm@bix.(none) # Merge bk://kernel.bkbits.net/gregkh/linux/usb-2.6 # into bix.(none):/usr/src/bk-usb # # drivers/usb/input/hiddev.c # 2004/06/13 11:33:54-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/usb/core/message.c # 2004/06/13 11:33:54-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/06/13 11:33:07-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb # # MAINTAINERS # 2004/06/13 11:33:04-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/06/10 13:10:48-07:00 akpm@bix.(none) # Merge bk://kernel.bkbits.net/gregkh/linux/usb-2.6 # into bix.(none):/usr/src/bk-usb # # drivers/usb/media/pwc-if.c # 2004/06/10 13:10:45-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/usb/input/hiddev.c # 2004/06/10 13:10:45-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/usb/input/hid-core.c # 2004/06/10 13:10:45-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/usb/core/devio.c # 2004/06/10 13:10:44-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/06/09 12:17:34-07:00 akpm@bix.(none) # Merge bk://kernel.bkbits.net/gregkh/linux/usb-2.6 # into bix.(none):/usr/src/bk-usb # # drivers/usb/core/usb.c # 2004/06/09 12:17:31-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/06/08 22:02:51-07:00 akpm@bix.(none) # Merge bk://kernel.bkbits.net/gregkh/linux/usb-2.6 # into bix.(none):/usr/src/bk-usb # # include/linux/usb.h # 2004/06/08 22:02:48-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/usb/serial/cyberjack.c # 2004/06/08 22:02:48-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/usb/media/pwc-if.c # 2004/06/08 22:02:48-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/usb/media/Kconfig # 2004/06/08 22:02:48-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/usb/gadget/ether.c # 2004/06/08 22:02:48-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/usb/core/devio.c # 2004/06/08 22:02:48-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/06/08 12:41:28-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb # # include/linux/usb.h # 2004/06/08 12:41:24-07:00 akpm@bix.(none) +0 -1 # Auto merged # # drivers/usb/serial/cyberjack.c # 2004/06/08 12:41:24-07:00 akpm@bix.(none) +0 -6 # Auto merged # # drivers/usb/media/pwc-if.c # 2004/06/08 12:41:24-07:00 akpm@bix.(none) +0 -1 # Auto merged # # drivers/usb/media/Kconfig # 2004/06/08 12:41:24-07:00 akpm@bix.(none) +0 -1 # Auto merged # # drivers/usb/core/devio.c # 2004/06/08 12:41:24-07:00 akpm@bix.(none) +0 -1 # Auto merged # # ChangeSet # 2004/06/07 20:07:13-07:00 akpm@bix.(none) # Merge bk://kernel.bkbits.net/gregkh/linux/usb-2.6 # into bix.(none):/usr/src/bk-usb # # include/linux/usb.h # 2004/06/07 20:07:10-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/usb/gadget/ether.c # 2004/06/07 20:07:10-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/06/07 14:23:17-07:00 akpm@bix.(none) # Merge bk://kernel.bkbits.net/gregkh/linux/usb-2.6 # into bix.(none):/usr/src/bk-usb # # drivers/usb/gadget/ether.c # 2004/06/07 14:23:13-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/usb/core/message.c # 2004/06/07 14:23:13-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/06/07 14:22:27-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb # # drivers/usb/input/hiddev.c # 2004/06/07 14:22:24-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/06/05 17:09:11-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb # # MAINTAINERS # 2004/06/05 17:09:08-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/06/04 02:41:08-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb # # drivers/usb/gadget/ether.c # 2004/06/04 02:41:05-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/06/03 10:45:02-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb # # include/linux/pci_ids.h # 2004/06/03 10:44:58-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/06/02 23:58:29-07:00 akpm@bix.(none) # Merge bk://kernel.bkbits.net/gregkh/linux/usb-2.6 # into bix.(none):/usr/src/bk-usb # # drivers/usb/core/usb.c # 2004/06/02 23:58:25-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/06/02 13:38:13-07:00 akpm@bix.(none) # Merge bk://kernel.bkbits.net/gregkh/linux/usb-2.6 # into bix.(none):/usr/src/bk-usb # # drivers/usb/core/message.c # 2004/06/02 13:38:09-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/06/02 13:37:23-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb # # include/linux/pci_ids.h # 2004/06/02 13:37:20-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/06/01 13:57:49-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb # # MAINTAINERS # 2004/06/01 13:57:45-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/05/30 00:23:52-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb # # MAINTAINERS # 2004/05/30 00:23:48-07:00 akpm@bix.(none) +0 -0 # Auto merged # # CREDITS # 2004/05/30 00:23:48-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/05/28 17:18:45-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb # # include/linux/pci_ids.h # 2004/05/28 17:18:42-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/05/28 14:16:41-07:00 akpm@bix.(none) # Merge bk://kernel.bkbits.net/gregkh/linux/usb-2.6 # into bix.(none):/usr/src/bk-usb # # drivers/usb/input/hiddev.c # 2004/05/28 14:16:37-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/05/28 14:15:52-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb # # include/linux/pci_ids.h # 2004/05/28 14:15:49-07:00 akpm@bix.(none) +0 -0 # Auto merged # # MAINTAINERS # 2004/05/28 14:15:48-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/05/25 13:48:31-07:00 akpm@bix.(none) # Merge bk://kernel.bkbits.net/gregkh/linux/usb-2.6 # into bix.(none):/usr/src/bk-usb # # drivers/usb/input/hiddev.c # 2004/05/25 13:48:27-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/usb/core/usb.c # 2004/05/25 13:48:27-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/usb/core/message.c # 2004/05/25 13:48:27-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/05/25 13:47:38-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb # # MAINTAINERS # 2004/05/25 13:47:34-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/05/24 11:48:01-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb # # include/linux/pci_ids.h # 2004/05/24 11:47:57-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/05/22 23:48:51-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb # # include/linux/pci_ids.h # 2004/05/22 23:48:48-07:00 akpm@bix.(none) +0 -0 # Auto merged # # MAINTAINERS # 2004/05/22 23:48:48-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/05/21 19:09:03-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb # # arch/ia64/defconfig # 2004/05/21 19:09:00-07:00 akpm@bix.(none) +0 -0 # Auto merged # # MAINTAINERS # 2004/05/21 19:09:00-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/05/19 18:31:55-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb # # MAINTAINERS # 2004/05/19 18:31:52-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/05/19 00:07:04-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb # # include/linux/usb.h # 2004/05/19 00:07:01-07:00 akpm@bix.(none) +0 -0 # Auto merged # # include/linux/pci_ids.h # 2004/05/19 00:07:01-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/usb/core/usb.c # 2004/05/19 00:07:01-07:00 akpm@bix.(none) +0 -0 # Auto merged # # arch/ppc/defconfig # 2004/05/19 00:07:01-07:00 akpm@bix.(none) +0 -0 # Auto merged # # arch/ppc/configs/pmac_defconfig # 2004/05/19 00:07:01-07:00 akpm@bix.(none) +0 -0 # Auto merged # # arch/ppc/configs/common_defconfig # 2004/05/19 00:07:01-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/05/18 14:54:09-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb # # include/linux/usb.h # 2004/05/18 14:54:06-07:00 akpm@bix.(none) +0 -0 # Auto merged # # include/linux/pci_ids.h # 2004/05/18 14:54:06-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/usb/input/hid-core.c # 2004/05/18 14:54:06-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/usb/core/usb.c # 2004/05/18 14:54:06-07:00 akpm@bix.(none) +0 -0 # Auto merged # # CREDITS # 2004/05/18 14:54:06-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/05/16 01:52:25-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb # # include/linux/pci_ids.h # 2004/05/16 01:52:22-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/05/14 21:45:47-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb # # include/linux/pci_ids.h # 2004/05/14 21:45:43-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/05/14 09:41:12-07:00 akpm@bix.(none) # Merge bk://kernel.bkbits.net/gregkh/linux/usb-2.6 # into bix.(none):/usr/src/bk-usb # # drivers/usb/input/hid-core.c # 2004/05/14 09:41:09-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/usb/core/usb.c # 2004/05/14 09:41:09-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/usb/core/message.c # 2004/05/14 09:41:09-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/05/12 20:32:44-07:00 akpm@bix.(none) # Merge bk://kernel.bkbits.net/gregkh/linux/usb-2.6 # into bix.(none):/usr/src/bk-usb # # drivers/usb/core/inode.c # 2004/05/12 20:32:41-07:00 akpm@bix.(none) +0 -0 # Auto merged # # MAINTAINERS # 2004/05/12 20:32:41-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/05/12 01:26:11-07:00 akpm@bix.(none) # Merge bk://kernel.bkbits.net/gregkh/linux/usb-2.6 # into bix.(none):/usr/src/bk-usb # # drivers/usb/input/wacom.c # 2004/05/12 01:26:08-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/usb/input/hid-core.c # 2004/05/12 01:26:08-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/05/12 01:25:17-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb # # include/linux/pci_ids.h # 2004/05/12 01:25:14-07:00 akpm@bix.(none) +0 -0 # Auto merged # # arch/parisc/configs/c3000_defconfig # 2004/05/12 01:25:14-07:00 akpm@bix.(none) +0 -0 # Auto merged # # MAINTAINERS # 2004/05/12 01:25:14-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/05/05 14:52:58-07:00 akpm@bix.(none) # Merge bk://kernel.bkbits.net/gregkh/linux/usb-2.6 # into bix.(none):/usr/src/bk-usb # # drivers/usb/core/message.c # 2004/05/05 14:52:55-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/05/05 14:52:11-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb # # CREDITS # 2004/05/05 14:52:08-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/05/04 14:13:11-07:00 akpm@bix.(none) # Merge bk://kernel.bkbits.net/gregkh/linux/usb-2.6 # into bix.(none):/usr/src/bk-usb # # include/linux/usb.h # 2004/05/04 14:13:08-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/05/01 15:23:25-07:00 akpm@bix.(none) # Merge bk://kernel.bkbits.net/gregkh/linux/usb-2.6 # into bix.(none):/usr/src/bk-usb # # MAINTAINERS # 2004/05/01 15:23:22-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/04/30 22:06:45-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb # # drivers/usb/core/inode.c # 2004/04/30 22:06:42-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/04/29 16:00:47-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb # # include/linux/pci_ids.h # 2004/04/29 16:00:44-07:00 akpm@bix.(none) +0 -0 # Auto merged # # MAINTAINERS # 2004/04/29 16:00:44-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/04/28 13:38:52-07:00 akpm@bix.(none) # Merge bk://kernel.bkbits.net/gregkh/linux/usb-2.6 # into bix.(none):/usr/src/bk-usb # # drivers/usb/input/hid-core.c # 2004/04/28 13:38:49-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/04/27 19:39:13-07:00 akpm@bix.(none) # Merge bk://kernel.bkbits.net/gregkh/linux/usb-2.6 # into bix.(none):/usr/src/bk-usb # # include/linux/usb.h # 2004/04/27 19:39:10-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/usb/core/usb.c # 2004/04/27 19:39:10-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/usb/core/message.c # 2004/04/27 19:39:10-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/04/26 18:31:48-07:00 akpm@bix.(none) # Merge bk://kernel.bkbits.net/gregkh/linux/usb-2.6 # into bix.(none):/usr/src/bk-usb # # include/linux/usb.h # 2004/04/26 18:31:45-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/usb/core/usb.c # 2004/04/26 18:31:45-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/04/25 23:06:05-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb # # include/linux/pci_ids.h # 2004/04/25 23:06:02-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/04/24 23:51:05-07:00 akpm@bix.(none) # Merge bk://kernel.bkbits.net/gregkh/linux/usb-2.6 # into bix.(none):/usr/src/bk-usb # # drivers/usb/core/usb.c # 2004/04/24 23:51:02-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/04/23 12:58:38-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb # # CREDITS # 2004/04/23 12:58:35-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/04/19 19:45:10-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb # # include/linux/pci_ids.h # 2004/04/19 19:45:07-07:00 akpm@bix.(none) +0 -0 # Auto merged # # MAINTAINERS # 2004/04/19 19:45:07-07:00 akpm@bix.(none) +0 -0 # Auto merged # # CREDITS # 2004/04/19 19:45:06-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/04/07 20:17:13-07:00 akpm@bix.(none) # Merge bk://kernel.bkbits.net/gregkh/linux/usb-2.6 # into bix.(none):/usr/src/bk-usb # # drivers/usb/core/message.c # 2004/04/07 20:17:11-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/04/02 11:35:28-08:00 akpm@bix.(none) # Merge bk://kernel.bkbits.net/gregkh/linux/usb-2.6 # into bix.(none):/usr/src/bk-usb # # include/linux/pci_ids.h # 2004/04/02 11:35:25-08:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/04/01 15:16:14-08:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb # # CREDITS # 2004/04/01 15:16:11-08:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/03/31 19:24:39-08:00 akpm@bix.(none) # Merge bk://kernel.bkbits.net/gregkh/linux/usb-2.6 # into bix.(none):/usr/src/bk-usb # # include/linux/usb.h # 2004/03/31 19:24:37-08:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/usb/core/usb.c # 2004/03/31 19:24:37-08:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/usb/core/message.c # 2004/03/31 19:24:37-08:00 akpm@bix.(none) +0 -0 # Auto merged # # arch/ppc64/defconfig # 2004/03/31 19:24:36-08:00 akpm@bix.(none) +0 -0 # Auto merged # # arch/ppc64/configs/pSeries_defconfig # 2004/03/31 19:24:36-08:00 akpm@bix.(none) +0 -0 # Auto merged # # arch/ppc/defconfig # 2004/03/31 19:24:36-08:00 akpm@bix.(none) +0 -0 # Auto merged # # arch/ppc/configs/pmac_defconfig # 2004/03/31 19:24:36-08:00 akpm@bix.(none) +0 -0 # Auto merged # # arch/ppc/configs/common_defconfig # 2004/03/31 19:24:36-08:00 akpm@bix.(none) +0 -0 # Auto merged # # arch/parisc/configs/c3000_defconfig # 2004/03/31 19:24:36-08:00 akpm@bix.(none) +0 -0 # Auto merged # # arch/ia64/defconfig # 2004/03/31 19:24:36-08:00 akpm@bix.(none) +0 -0 # Auto merged # # arch/ia64/configs/zx1_defconfig # 2004/03/31 19:24:36-08:00 akpm@bix.(none) +0 -0 # Auto merged # # arch/ia64/configs/generic_defconfig # 2004/03/31 19:24:36-08:00 akpm@bix.(none) +0 -0 # Auto merged # # arch/arm/configs/neponset_defconfig # 2004/03/31 19:24:36-08:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/03/30 20:18:36-08:00 akpm@bix.(none) # Merge bk://kernel.bkbits.net/gregkh/linux/usb-2.6 # into bix.(none):/usr/src/bk-usb # # arch/ppc64/defconfig # 2004/03/30 20:18:33-08:00 akpm@bix.(none) +0 -0 # Auto merged # # arch/ppc64/configs/pSeries_defconfig # 2004/03/30 20:18:33-08:00 akpm@bix.(none) +0 -0 # Auto merged # # arch/ppc/defconfig # 2004/03/30 20:18:33-08:00 akpm@bix.(none) +0 -0 # Auto merged # # arch/ppc/configs/pmac_defconfig # 2004/03/30 20:18:33-08:00 akpm@bix.(none) +0 -0 # Auto merged # # arch/ppc/configs/common_defconfig # 2004/03/30 20:18:33-08:00 akpm@bix.(none) +0 -0 # Auto merged # # arch/parisc/configs/c3000_defconfig # 2004/03/30 20:18:33-08:00 akpm@bix.(none) +0 -0 # Auto merged # # arch/ia64/defconfig # 2004/03/30 20:18:33-08:00 akpm@bix.(none) +0 -0 # Auto merged # # arch/ia64/configs/zx1_defconfig # 2004/03/30 20:18:33-08:00 akpm@bix.(none) +0 -0 # Auto merged # # arch/ia64/configs/generic_defconfig # 2004/03/30 20:18:33-08:00 akpm@bix.(none) +0 -0 # Auto merged # # arch/arm/configs/neponset_defconfig # 2004/03/30 20:18:32-08:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/03/30 12:09:32-08:00 akpm@bix.(none) # Merge bk://kernel.bkbits.net/gregkh/linux/usb-2.6 # into bix.(none):/usr/src/bk-usb # # include/linux/usb.h # 2004/03/30 12:09:29-08:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/usb/core/usb.c # 2004/03/30 12:09:29-08:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/usb/core/message.c # 2004/03/30 12:09:29-08:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/03/29 18:05:43-08:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb # # MAINTAINERS # 2004/03/29 18:05:41-08:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/03/29 13:51:58-08:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb # # CREDITS # 2004/03/29 13:51:56-08:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/03/28 12:29:41-08:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb # # drivers/usb/core/message.c # 2004/03/28 12:29:38-08:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/03/27 02:28:18-08:00 akpm@bix.(none) # Merge bk://kernel.bkbits.net/gregkh/linux/usb-2.6 # into bix.(none):/usr/src/bk-usb # # drivers/usb/input/wacom.c # 2004/03/27 02:28:16-08:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/03/26 12:24:49-08:00 akpm@bix.(none) # Merge bk://kernel.bkbits.net/gregkh/linux/usb-2.6 # into bix.(none):/usr/src/bk-usb # # include/linux/usb_gadget.h # 2004/03/26 12:24:46-08:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/usb/core/usb.c # 2004/03/26 12:24:46-08:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/03/20 13:26:55-08:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb # # CREDITS # 2004/03/20 13:26:53-08:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/03/16 21:53:42-08:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb # # drivers/usb/input/wacom.c # 2004/03/16 21:53:39-08:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/usb/input/hid-core.c # 2004/03/16 21:53:39-08:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/03/16 12:59:58-08:00 akpm@bix.(none) # Merge bk://kernel.bkbits.net/gregkh/linux/usb-2.6 # into bix.(none):/usr/src/bk-usb # # include/linux/usb_gadget.h # 2004/03/16 12:59:47-08:00 akpm@bix.(none) +0 -0 # Auto merged # # include/linux/usb.h # 2004/03/16 12:59:47-08:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/usb/core/usb.c # 2004/03/16 12:59:46-08:00 akpm@bix.(none) +0 -0 # Auto merged # # MAINTAINERS # 2004/03/16 12:59:46-08:00 akpm@bix.(none) +0 -0 # Auto merged # # CREDITS # 2004/03/16 12:59:46-08:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/03/16 12:58:57-08:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb # # drivers/usb/input/wacom.c # 2004/03/16 12:58:47-08:00 akpm@bix.(none) +0 -4 # Auto merged # # drivers/usb/input/hid-core.c # 2004/03/16 12:58:47-08:00 akpm@bix.(none) +0 -0 # Auto merged # # CREDITS # 2004/03/16 12:58:46-08:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/03/14 11:03:00-08:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb # # include/linux/usb_gadget.h # 2004/03/14 11:02:47-08:00 akpm@bix.(none) +0 -0 # Auto merged # # include/linux/usb.h # 2004/03/14 11:02:47-08:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/usb/core/usb.c # 2004/03/14 11:02:47-08:00 akpm@bix.(none) +0 -0 # Auto merged # # MAINTAINERS # 2004/03/14 11:02:47-08:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/03/12 10:57:17-08:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-usb # # MAINTAINERS # 2004/03/12 10:57:02-08:00 akpm@bix.(none) +0 -0 # Auto merged # # CREDITS # 2004/03/12 10:57:01-08:00 akpm@bix.(none) +0 -0 # Auto merged # diff -Nru a/Documentation/usb/error-codes.txt b/Documentation/usb/error-codes.txt --- a/Documentation/usb/error-codes.txt 2004-07-04 23:02:39 -07:00 +++ b/Documentation/usb/error-codes.txt 2004-07-04 23:02:39 -07:00 @@ -47,6 +47,8 @@ -ESHUTDOWN The host controller has been disabled due to some problem that could not be worked around. +-EPERM Submission failed because urb->reject was set. + ************************************************************************** * Error codes returned by in urb->status * diff -Nru a/drivers/isdn/hisax/st5481_usb.c b/drivers/isdn/hisax/st5481_usb.c --- a/drivers/isdn/hisax/st5481_usb.c 2004-07-04 23:02:39 -07:00 +++ b/drivers/isdn/hisax/st5481_usb.c 2004-07-04 23:02:39 -07:00 @@ -143,9 +143,6 @@ if (ctrl_msg->dr.bRequest == USB_REQ_CLEAR_FEATURE) { /* Special case handling for pipe reset */ le16_to_cpus(&ctrl_msg->dr.wIndex); - usb_endpoint_running(adapter->usb_dev, - ctrl_msg->dr.wIndex & ~USB_DIR_IN, - (ctrl_msg->dr.wIndex & USB_DIR_IN) == 0); /* toggle is reset on clear */ usb_settoggle(adapter->usb_dev, diff -Nru a/drivers/net/irda/stir4200.c b/drivers/net/irda/stir4200.c --- a/drivers/net/irda/stir4200.c 2004-07-04 23:02:39 -07:00 +++ b/drivers/net/irda/stir4200.c 2004-07-04 23:02:39 -07:00 @@ -168,6 +168,7 @@ struct stir_cb { struct usb_device *usbdev; /* init: probe_irda */ + struct usb_interface *usbintf; struct net_device *netdev; /* network layer */ struct irlap_cb *irlap; /* The link layer we are binded to */ struct net_device_stats stats; /* network statistics */ @@ -508,6 +509,7 @@ { int i, err; __u8 mode; + int rc; for (i = 0; i < ARRAY_SIZE(stir_modes); ++i) { if (speed == stir_modes[i].speed) @@ -521,7 +523,14 @@ pr_debug("speed change from %d to %d\n", stir->speed, speed); /* sometimes needed to get chip out of stuck state */ + rc = usb_lock_device_for_reset(stir->usbdev, stir->usbintf); + if (rc < 0) { + err = rc; + goto out; + } err = usb_reset_device(stir->usbdev); + if (rc) + usb_unlock_device(stir->usbdev); if (err) goto out; @@ -1066,6 +1075,7 @@ stir = net->priv; stir->netdev = net; stir->usbdev = dev; + stir->usbintf = intf; ret = usb_reset_configuration(dev); if (ret != 0) { diff -Nru a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c --- a/drivers/usb/core/devices.c 2004-07-04 23:02:39 -07:00 +++ b/drivers/usb/core/devices.c 2004-07-04 23:02:39 -07:00 @@ -283,9 +283,8 @@ /* TBD: * 0. TBDs - * 1. marking active config and ifaces (code lists all, but should mark + * 1. marking active interface altsettings (code lists all, but should mark * which ones are active, if any) - * 2. add status to each endpoint line */ static char *usb_dump_config_descriptor(char *start, char *end, const struct usb_config_descriptor *desc, int active) @@ -452,7 +451,7 @@ * nbytes - the maximum number of bytes to write * skip_bytes - the number of bytes to skip before writing anything * file_offset - the offset into the devices file on completion - * The caller must own the usbdev->serialize semaphore. + * The caller must have locked the device. */ static ssize_t usb_device_dump(char __user **buffer, size_t *nbytes, loff_t *skip_bytes, loff_t *file_offset, struct usb_device *usbdev, struct usb_bus *bus, int level, int index, int count) @@ -556,10 +555,10 @@ struct usb_device *childdev = usbdev->children[chix]; if (childdev) { - down(&childdev->serialize); + usb_lock_device(childdev); ret = usb_device_dump(buffer, nbytes, skip_bytes, file_offset, childdev, bus, level + 1, chix, ++cnt); - up(&childdev->serialize); + usb_unlock_device(childdev); if (ret == -EFAULT) return total_written; total_written += ret; @@ -591,9 +590,9 @@ /* recurse through all children of the root hub */ if (!bus->root_hub) continue; - down(&bus->root_hub->serialize); + usb_lock_device(bus->root_hub); ret = usb_device_dump(&buf, &nbytes, &skip_bytes, ppos, bus->root_hub, bus, 0, 0, 0); - up(&bus->root_hub->serialize); + usb_unlock_device(bus->root_hub); if (ret < 0) { up(&usb_bus_list_lock); return ret; diff -Nru a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c --- a/drivers/usb/core/devio.c 2004-07-04 23:02:39 -07:00 +++ b/drivers/usb/core/devio.c 2004-07-04 23:02:39 -07:00 @@ -111,7 +111,7 @@ int i; pos = *ppos; - down(&dev->serialize); + usb_lock_device(dev); if (!connected(dev)) { ret = -ENODEV; goto err; @@ -173,7 +173,7 @@ } err: - up(&dev->serialize); + usb_unlock_device(dev); return ret; } @@ -514,7 +514,7 @@ struct usb_device *dev = ps->dev; unsigned int ifnum; - down(&dev->serialize); + usb_lock_device(dev); list_del_init(&ps->list); if (connected(dev)) { @@ -523,7 +523,7 @@ releaseintf(ps, ifnum); destroy_all_async(ps); } - up(&dev->serialize); + usb_unlock_device(dev); usb_put_dev(dev); ps->dev = NULL; kfree(ps); @@ -722,7 +722,7 @@ static int proc_resetdevice(struct dev_state *ps) { - return __usb_reset_device(ps->dev); + return usb_reset_device(ps->dev); } @@ -1012,9 +1012,9 @@ break; if (signal_pending(current)) break; - up(&dev->serialize); + usb_unlock_device(dev); schedule(); - down(&dev->serialize); + usb_lock_device(dev); } remove_wait_queue(&ps->wait, &wait); set_current_state(TASK_RUNNING); @@ -1137,7 +1137,11 @@ /* let kernel drivers try to (re)bind to the interface */ case USBDEVFS_CONNECT: + usb_unlock_device(ps->dev); + usb_lock_all_devices(); bus_rescan_devices(intf->dev.bus); + usb_unlock_all_devices(); + usb_lock_device(ps->dev); break; /* talk directly to the interface's driver */ @@ -1180,9 +1184,9 @@ if (!(file->f_mode & FMODE_WRITE)) return -EPERM; - down(&dev->serialize); + usb_lock_device(dev); if (!connected(dev)) { - up(&dev->serialize); + usb_unlock_device(dev); return -ENODEV; } @@ -1282,7 +1286,7 @@ ret = proc_ioctl(ps, p); break; } - up(&dev->serialize); + usb_unlock_device(dev); if (ret >= 0) inode->i_atime = CURRENT_TIME; return ret; diff -Nru a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c --- a/drivers/usb/core/hcd.c 2004-07-04 23:02:39 -07:00 +++ b/drivers/usb/core/hcd.c 2004-07-04 23:02:39 -07:00 @@ -102,6 +102,9 @@ /* used when updating hcd data */ static spinlock_t hcd_data_lock = SPIN_LOCK_UNLOCKED; +/* wait queue for synchronous unlinks */ +DECLARE_WAIT_QUEUE_HEAD(usb_kill_urb_queue); + /*-------------------------------------------------------------------------*/ /* @@ -569,7 +572,7 @@ /*-------------------------------------------------------------------------*/ -void usb_rh_status_dequeue (struct usb_hcd *hcd, struct urb *urb) +int usb_rh_status_dequeue (struct usb_hcd *hcd, struct urb *urb) { unsigned long flags; @@ -581,6 +584,7 @@ urb->hcpriv = NULL; usb_hcd_giveback_urb (hcd, urb, NULL); local_irq_restore (flags); + return 0; } /*-------------------------------------------------------------------------*/ @@ -791,9 +795,9 @@ return (retval < 0) ? retval : -EMSGSIZE; } - down (&usb_dev->serialize); + usb_lock_device (usb_dev); retval = usb_new_device (usb_dev); - up (&usb_dev->serialize); + usb_unlock_device (usb_dev); if (retval) { usb_dev->bus->root_hub = NULL; dev_err (parent_dev, "can't register root hub for %s, %d\n", @@ -1029,7 +1033,6 @@ static void urb_unlink (struct urb *urb) { unsigned long flags; - struct usb_device *dev; /* Release any periodic transfer bandwidth */ if (urb->bandwidth) @@ -1040,9 +1043,8 @@ spin_lock_irqsave (&hcd_data_lock, flags); list_del_init (&urb->urb_list); - dev = urb->dev; spin_unlock_irqrestore (&hcd_data_lock, flags); - usb_put_dev (dev); + usb_put_dev (urb->dev); } @@ -1079,23 +1081,28 @@ // FIXME: verify that quiescing hc works right (RH cleans up) spin_lock_irqsave (&hcd_data_lock, flags); - if (HCD_IS_RUNNING (hcd->state) && hcd->state != USB_STATE_QUIESCING) { + if (unlikely (urb->reject)) + status = -EPERM; + else if (HCD_IS_RUNNING (hcd->state) && + hcd->state != USB_STATE_QUIESCING) { usb_get_dev (urb->dev); list_add_tail (&urb->urb_list, &dev->urb_list); status = 0; - } else { - INIT_LIST_HEAD (&urb->urb_list); + } else status = -ESHUTDOWN; - } spin_unlock_irqrestore (&hcd_data_lock, flags); - if (status) + if (status) { + INIT_LIST_HEAD (&urb->urb_list); return status; + } /* increment urb's reference count as part of giving it to the HCD * (which now controls it). HCD guarantees that it either returns * an error or calls giveback(), but not both. */ urb = usb_get_urb (urb); + atomic_inc (&urb->use_count); + if (urb->dev == hcd->self.root_hub) { /* NOTE: requirement on hub callers (usbfs and the hub * driver, for now) that URBs' urb->transfer_buffer be @@ -1132,9 +1139,12 @@ status = hcd->driver->urb_enqueue (hcd, urb, mem_flags); done: - if (status) { - usb_put_urb (urb); + if (unlikely (status)) { urb_unlink (urb); + atomic_dec (&urb->use_count); + if (urb->reject) + wake_up (&usb_kill_urb_queue); + usb_put_urb (urb); } return status; } @@ -1157,60 +1167,39 @@ * soon as practical. we've already set up the urb's return status, * but we can't know if the callback completed already. */ -static void +static int unlink1 (struct usb_hcd *hcd, struct urb *urb) { + int value; + if (urb == (struct urb *) hcd->rh_timer.data) - usb_rh_status_dequeue (hcd, urb); + value = usb_rh_status_dequeue (hcd, urb); else { - int value; - /* failures "should" be harmless */ + /* The only reason an HCD might fail this call is if + * it has not yet fully queued the urb to begin with. + * Such failures should be harmless. */ value = hcd->driver->urb_dequeue (hcd, urb); - if (value != 0) - dev_dbg (hcd->self.controller, - "dequeue %p --> %d\n", - urb, value); } -} - -struct completion_splice { // modified urb context: - /* did we complete? */ - struct completion done; - - /* original urb data */ - usb_complete_t complete; - void *context; -}; - -static void unlink_complete (struct urb *urb, struct pt_regs *regs) -{ - struct completion_splice *splice; - - splice = (struct completion_splice *) urb->context; - /* issue original completion call */ - urb->complete = splice->complete; - urb->context = splice->context; - urb->complete (urb, regs); - - /* then let the synchronous unlink call complete */ - complete (&splice->done); + if (value != 0) + dev_dbg (hcd->self.controller, "dequeue %p --> %d\n", + urb, value); + return value; } /* - * called in any context; note ASYNC_UNLINK restrictions + * called in any context * * caller guarantees urb won't be recycled till both unlink() * and the urb's completion function return */ -static int hcd_unlink_urb (struct urb *urb) +static int hcd_unlink_urb (struct urb *urb, int status) { struct hcd_dev *dev; struct usb_hcd *hcd = NULL; struct device *sys = NULL; unsigned long flags; - struct completion_splice splice; struct list_head *tmp; int retval; @@ -1262,8 +1251,6 @@ /* Any status except -EINPROGRESS means something already started to * unlink this URB from the hardware. So there's no more work to do. - * - * FIXME use better explicit urb state */ if (urb->status != -EINPROGRESS) { retval = -EBUSY; @@ -1281,62 +1268,19 @@ hcd->saw_irq = 1; } - /* maybe set up to block until the urb's completion fires. the - * lower level hcd code is always async, locking on urb->status - * updates; an intercepted completion unblocks us. - */ - if (!(urb->transfer_flags & URB_ASYNC_UNLINK)) { - if (in_interrupt ()) { - dev_dbg (hcd->self.controller, - "non-async unlink in_interrupt"); - retval = -EWOULDBLOCK; - goto done; - } - /* synchronous unlink: block till we see the completion */ - init_completion (&splice.done); - splice.complete = urb->complete; - splice.context = urb->context; - urb->complete = unlink_complete; - urb->context = &splice; - urb->status = -ENOENT; - } else { - /* asynchronous unlink */ - urb->status = -ECONNRESET; - } + urb->status = status; + spin_unlock (&hcd_data_lock); spin_unlock_irqrestore (&urb->lock, flags); - // FIXME remove splicing, so this becomes unlink1 (hcd, urb); - if (urb == (struct urb *) hcd->rh_timer.data) { - usb_rh_status_dequeue (hcd, urb); - retval = 0; - } else { - retval = hcd->driver->urb_dequeue (hcd, urb); - - /* hcds shouldn't really fail these calls, but... */ - if (retval) { - dev_dbg (sys, "dequeue %p --> %d\n", urb, retval); - if (!(urb->transfer_flags & URB_ASYNC_UNLINK)) { - spin_lock_irqsave (&urb->lock, flags); - urb->complete = splice.complete; - urb->context = splice.context; - spin_unlock_irqrestore (&urb->lock, flags); - } - goto bye; - } - } - - /* block till giveback, if needed */ - if (urb->transfer_flags & URB_ASYNC_UNLINK) - return -EINPROGRESS; - - wait_for_completion (&splice.done); - return 0; + retval = unlink1 (hcd, urb); + if (retval == 0) + retval = -EINPROGRESS; + return retval; done: spin_unlock (&hcd_data_lock); spin_unlock_irqrestore (&urb->lock, flags); -bye: if (retval != -EIDRM && sys && sys->driver) dev_dbg (sys, "hcd_unlink_urb %p fail %d\n", urb, retval); return retval; @@ -1367,13 +1311,10 @@ rescan: /* (re)block new requests, as best we can */ - if (endpoint & USB_DIR_IN) { - usb_endpoint_halt (udev, epnum, 0); + if (endpoint & USB_DIR_IN) udev->epmaxpacketin [epnum] = 0; - } else { - usb_endpoint_halt (udev, epnum, 1); + else udev->epmaxpacketout [epnum] = 0; - } /* then kill any current requests */ spin_lock (&hcd_data_lock); @@ -1536,6 +1477,9 @@ /* pass ownership to the completion handler */ urb->complete (urb, regs); + atomic_dec (&urb->use_count); + if (unlikely (urb->reject)) + wake_up (&usb_kill_urb_queue); usb_put_urb (urb); } EXPORT_SYMBOL (usb_hcd_giveback_urb); @@ -1579,13 +1523,13 @@ unsigned i; /* hc's root hub is removed later removed in hcd->stop() */ - down (&hub->serialize); usb_set_device_state(hub, USB_STATE_NOTATTACHED); + usb_lock_device (hub); for (i = 0; i < hub->maxchild; i++) { if (hub->children [i]) usb_disconnect (&hub->children [i]); } - up (&hub->serialize); + usb_unlock_device (hub); } /** diff -Nru a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h --- a/drivers/usb/core/hcd.h 2004-07-04 23:02:39 -07:00 +++ b/drivers/usb/core/hcd.h 2004-07-04 23:02:39 -07:00 @@ -142,7 +142,7 @@ int (*deallocate)(struct usb_device *); int (*get_frame_number) (struct usb_device *usb_dev); int (*submit_urb) (struct urb *urb, int mem_flags); - int (*unlink_urb) (struct urb *urb); + int (*unlink_urb) (struct urb *urb, int status); /* allocate dma-consistent buffer for URB_DMA_NOMAPPING */ void *(*buffer_alloc)(struct usb_bus *bus, size_t size, @@ -207,7 +207,7 @@ 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 void usb_rh_status_dequeue (struct usb_hcd *hcd, struct urb *urb); +extern int usb_rh_status_dequeue (struct usb_hcd *hcd, struct urb *urb); #ifdef CONFIG_PCI struct pci_dev; @@ -359,14 +359,13 @@ extern struct list_head usb_bus_list; extern struct semaphore usb_bus_list_lock; +extern wait_queue_head_t usb_kill_urb_queue; extern struct usb_bus *usb_bus_get (struct usb_bus *bus); extern void usb_bus_put (struct usb_bus *bus); extern int usb_find_interface_driver (struct usb_device *dev, struct usb_interface *interface); - -#define usb_endpoint_halt(dev, ep, out) ((dev)->halted[out] |= (1 << (ep))) #define usb_endpoint_out(ep_dir) (!((ep_dir) & USB_DIR_IN)) diff -Nru a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c --- a/drivers/usb/core/hub.c 2004-07-04 23:02:39 -07:00 +++ b/drivers/usb/core/hub.c 2004-07-04 23:02:39 -07:00 @@ -53,6 +53,8 @@ module_param (blinkenlights, bool, S_IRUGO); MODULE_PARM_DESC (blinkenlights, "true to cycle leds on hubs"); +static int hub_port_disable(struct usb_device *hdev, int port); + #ifdef DEBUG static inline char *portspeed (int portstatus) @@ -138,7 +140,7 @@ static void led_work (void *__hub) { struct usb_hub *hub = __hub; - struct usb_device *hdev = interface_to_usbdev (hub->intf); + struct usb_device *hdev = hub->hdev; unsigned i; unsigned changed = 0; int cursor = -1; @@ -234,18 +236,11 @@ int i; unsigned long bits; - spin_lock(&hub_event_lock); - hub->urb_active = 0; - if (hub->urb_complete) { /* disconnect or rmmod */ - complete(hub->urb_complete); - goto done; - } - switch (urb->status) { case -ENOENT: /* synchronous unlink */ case -ECONNRESET: /* async unlink */ case -ESHUTDOWN: /* hardware going away */ - goto done; + return; default: /* presumably an error */ /* Cause a hub reset after 10 consecutive errors */ @@ -268,20 +263,17 @@ hub->nerrors = 0; /* Something happened, let khubd figure it out */ + spin_lock(&hub_event_lock); if (list_empty(&hub->event_list)) { list_add_tail(&hub->event_list, &hub_event_list); wake_up(&khubd_wait); } + spin_unlock(&hub_event_lock); resubmit: if ((status = usb_submit_urb (hub->urb, GFP_ATOMIC)) != 0 - /* ENODEV means we raced disconnect() */ - && status != -ENODEV) + && status != -ENODEV && status != -EPERM) dev_err (&hub->intf->dev, "resubmit --> %d\n", status); - if (status == 0) - hub->urb_active = 1; -done: - spin_unlock(&hub_event_lock); } /* USB 2.0 spec Section 11.24.2.3 */ @@ -308,7 +300,7 @@ while (!list_empty (&hub->tt.clear_list)) { struct list_head *temp; struct usb_tt_clear *clear; - struct usb_device *hdev; + struct usb_device *hdev = hub->hdev; int status; temp = hub->tt.clear_list.next; @@ -317,7 +309,6 @@ /* drop lock so HCD can concurrently report other TT errors */ spin_unlock_irqrestore (&hub->tt.lock, flags); - hdev = interface_to_usbdev (hub->intf); status = hub_clear_tt_buffer (hdev, clear->devinfo, clear->tt); spin_lock_irqsave (&hub->tt.lock, flags); @@ -378,15 +369,14 @@ static void hub_power_on(struct usb_hub *hub) { - struct usb_device *hdev; int i; /* if hub supports power switching, enable power on each port */ if ((hub->descriptor->wHubCharacteristics & HUB_CHAR_LPSM) < 2) { dev_dbg(&hub->intf->dev, "enabling power on all ports\n"); - hdev = interface_to_usbdev(hub->intf); for (i = 0; i < hub->descriptor->bNbrPorts; i++) - set_port_feature(hdev, i + 1, USB_PORT_FEAT_POWER); + set_port_feature(hub->hdev, i + 1, + USB_PORT_FEAT_POWER); } /* Wait for power to be enabled */ @@ -396,10 +386,9 @@ static int hub_hub_status(struct usb_hub *hub, u16 *status, u16 *change) { - struct usb_device *hdev = interface_to_usbdev (hub->intf); int ret; - ret = get_hub_status(hdev, &hub->status->hub); + ret = get_hub_status(hub->hdev, &hub->status->hub); if (ret < 0) dev_err (&hub->intf->dev, "%s failed (err = %d)\n", __FUNCTION__, ret); @@ -414,7 +403,7 @@ static int hub_configure(struct usb_hub *hub, struct usb_endpoint_descriptor *endpoint) { - struct usb_device *hdev = interface_to_usbdev (hub->intf); + struct usb_device *hdev = hub->hdev; struct device *hub_dev = &hub->intf->dev; u16 hubstatus, hubchange; unsigned int pipe; @@ -612,7 +601,6 @@ message = "couldn't submit status urb"; goto fail; } - hub->urb_active = 1; /* Wake up khubd */ wake_up(&khubd_wait); @@ -635,26 +623,48 @@ return ret; } +static void hub_remove_children_work(void *__hub) +{ + struct usb_hub *hub = __hub; + struct usb_device *hdev = hub->hdev; + int i; + + kfree(hub); + + usb_lock_device(hdev); + for (i = 0; i < hdev->maxchild; ++i) { + if (hdev->children[i]) + usb_disconnect(&hdev->children[i]); + } + usb_unlock_device(hdev); + usb_put_dev(hdev); +} + static unsigned highspeed_hubs; static void hub_disconnect(struct usb_interface *intf) { struct usb_hub *hub = usb_get_intfdata (intf); - DECLARE_COMPLETION(urb_complete); + struct usb_device *hdev; + int i, n; if (!hub) return; + hdev = hub->hdev; - if (interface_to_usbdev(intf)->speed == USB_SPEED_HIGH) + if (hdev->speed == USB_SPEED_HIGH) highspeed_hubs--; usb_set_intfdata (intf, NULL); - spin_lock_irq(&hub_event_lock); - hub->urb_complete = &urb_complete; - /* Delete it and then reset it */ - list_del_init(&hub->event_list); + if (hub->urb) { + usb_kill_urb(hub->urb); + usb_free_urb(hub->urb); + hub->urb = NULL; + } + spin_lock_irq(&hub_event_lock); + list_del_init(&hub->event_list); spin_unlock_irq(&hub_event_lock); /* assuming we used keventd, it must quiesce too */ @@ -663,14 +673,6 @@ if (hub->has_indicators || hub->tt.hub) flush_scheduled_work (); - if (hub->urb) { - usb_unlink_urb(hub->urb); - if (hub->urb_active) - wait_for_completion(&urb_complete); - usb_free_urb(hub->urb); - hub->urb = NULL; - } - if (hub->descriptor) { kfree(hub->descriptor); hub->descriptor = NULL; @@ -682,14 +684,32 @@ } if (hub->buffer) { - usb_buffer_free(interface_to_usbdev(intf), - sizeof(*hub->buffer), hub->buffer, + usb_buffer_free(hdev, sizeof(*hub->buffer), hub->buffer, hub->buffer_dma); hub->buffer = NULL; } - /* Free the memory */ - kfree(hub); + /* If there are any children then this is unbind only, not a + * physical disconnection. The active ports must be disabled + * and later on we must call usb_disconnect(). We can't call + * it here because we already own the usb bus writelock. + */ + n = 0; + for (i = 0; i < hdev->maxchild; ++i) { + if (hdev->children[i]) { + ++n; + hub_port_disable(hdev, i); + } + } + + if (n == 0) + kfree(hub); + else { + /* Reuse hub->leds to disconnect the children */ + INIT_WORK(&hub->leds, hub_remove_children_work, hub); + schedule_work(&hub->leds); + usb_get_dev(hdev); + } } static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id) @@ -741,6 +761,7 @@ INIT_LIST_HEAD(&hub->event_list); hub->intf = intf; + hub->hdev = hdev; INIT_WORK(&hub->leds, led_work, hub); usb_set_intfdata (intf, hub); @@ -792,7 +813,7 @@ static int hub_reset(struct usb_hub *hub) { - struct usb_device *hdev = interface_to_usbdev(hub->intf); + struct usb_device *hdev = hub->hdev; int i; /* Disconnect any attached devices */ @@ -803,7 +824,7 @@ /* Attempt to reset the hub */ if (hub->urb) - usb_unlink_urb(hub->urb); + usb_kill_urb(hub->urb); else return -1; @@ -855,7 +876,7 @@ * @udev: pointer to device whose state should be changed * @new_state: new state value to be stored * - * udev->state is _not_ protected by the udev->serialize semaphore. This + * udev->state is _not_ protected by the device lock. This * is so that devices can be marked as disconnected as soon as possible, * without having to wait for the semaphore to be released. Instead, * changes to the state must be protected by the device_state_lock spinlock. @@ -946,7 +967,7 @@ /* lock the bus list on behalf of HCDs unregistering their root hubs */ if (!udev->parent) down(&usb_bus_list_lock); - down(&udev->serialize); + usb_lock_device(udev); dev_info (&udev->dev, "USB disconnect, address %d\n", udev->devnum); @@ -975,7 +996,7 @@ *pdev = NULL; spin_unlock_irq(&device_state_lock); - up(&udev->serialize); + usb_unlock_device(udev); if (!udev->parent) up(&usb_bus_list_lock); @@ -1467,8 +1488,6 @@ != udev->descriptor.bMaxPacketSize0)) { usb_disable_endpoint(udev, 0 + USB_DIR_IN); usb_disable_endpoint(udev, 0 + USB_DIR_OUT); - usb_endpoint_running(udev, 0, 1); - usb_endpoint_running(udev, 0, 0); udev->epmaxpacketin [0] = udev->descriptor.bMaxPacketSize0; udev->epmaxpacketout[0] = udev->descriptor.bMaxPacketSize0; } @@ -1514,8 +1533,9 @@ } static unsigned -hub_power_remaining (struct usb_hub *hub, struct usb_device *hdev) +hub_power_remaining (struct usb_hub *hub) { + struct usb_device *hdev = hub->hdev; int remaining; unsigned i; @@ -1556,7 +1576,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port, u16 portstatus, u16 portchange) { - struct usb_device *hdev = interface_to_usbdev(hub->intf); + struct usb_device *hdev = hub->hdev; struct device *hub_dev = &hub->intf->dev; int status, i; @@ -1673,7 +1693,7 @@ * udev becomes globally accessible, although presumably * no one will look at it until hdev is unlocked. */ - down (&udev->serialize); + usb_lock_device (udev); status = 0; /* We mustn't add new devices if the parent hub has @@ -1697,11 +1717,11 @@ } } - up (&udev->serialize); + usb_unlock_device (udev); if (status) goto loop; - status = hub_power_remaining(hub, hdev); + status = hub_power_remaining(hub); if (status) dev_dbg(hub_dev, "%dmA power budget left\n", @@ -1755,7 +1775,7 @@ list_del_init(tmp); hub = list_entry(tmp, struct usb_hub, event_list); - hdev = interface_to_usbdev(hub->intf); + hdev = hub->hdev; hub_dev = &hub->intf->dev; usb_get_dev(hdev); @@ -1763,7 +1783,7 @@ /* Lock the device, then check to see if we were * disconnected while waiting for the lock to succeed. */ - down(&hdev->serialize); + usb_lock_device(hdev); if (hdev->state != USB_STATE_CONFIGURED || !hdev->actconfig || hub != usb_get_intfdata( @@ -1879,7 +1899,7 @@ } loop: - up(&hdev->serialize); + usb_unlock_device(hdev); usb_put_dev(hdev); } /* end while (1) */ @@ -2030,8 +2050,10 @@ * * The caller must own the device lock. For example, it's safe to use * this from a driver probe() routine after downloading new firmware. + * For calls that might not occur during probe(), drivers should lock + * the device using usb_lock_device_for_reset(). */ -int __usb_reset_device(struct usb_device *udev) +int usb_reset_device(struct usb_device *udev) { struct usb_device *parent = udev->parent; struct usb_device_descriptor descriptor = udev->descriptor; @@ -2067,6 +2089,11 @@ return -ENOENT; } + /* ep0 maxpacket size may change; let the HCD know about it. + * Other endpoints will be handled by re-enumeration. */ + usb_disable_endpoint(udev, 0); + usb_disable_endpoint(udev, 0 + USB_DIR_IN); + ret = hub_port_init(parent, udev, port); if (ret < 0) goto re_enumerate; @@ -2098,7 +2125,7 @@ struct usb_interface *intf = udev->actconfig->interface[i]; struct usb_interface_descriptor *desc; - /* set_interface resets host side toggle and halt status even + /* set_interface resets host side toggle even * for altsetting zero. the interface may have no driver. */ desc = &intf->cur_altsetting->desc; @@ -2130,16 +2157,4 @@ spin_unlock_irq(&hub_event_lock); return -ENODEV; -} -EXPORT_SYMBOL(__usb_reset_device); - -int usb_reset_device(struct usb_device *udev) -{ - int r; - - down(&udev->serialize); - r = __usb_reset_device(udev); - up(&udev->serialize); - - return r; } diff -Nru a/drivers/usb/core/hub.h b/drivers/usb/core/hub.h --- a/drivers/usb/core/hub.h 2004-07-04 23:02:39 -07:00 +++ b/drivers/usb/core/hub.h 2004-07-04 23:02:39 -07:00 @@ -187,9 +187,8 @@ struct usb_hub { struct usb_interface *intf; /* the "real" device */ + struct usb_device *hdev; struct urb *urb; /* for interrupt polling pipe */ - struct completion *urb_complete; /* wait for urb to end */ - unsigned int urb_active:1; /* buffer for urb ... 1 bit each for hub and children, rounded up */ char (*buffer)[(USB_MAXCHILDREN + 1 + 7) / 8]; diff -Nru a/drivers/usb/core/message.c b/drivers/usb/core/message.c --- a/drivers/usb/core/message.c 2004-07-04 23:02:39 -07:00 +++ b/drivers/usb/core/message.c 2004-07-04 23:02:39 -07:00 @@ -605,12 +605,128 @@ * Returns the number of bytes received on success, or else the status code * returned by the underlying usb_control_msg() call. */ -int usb_get_string(struct usb_device *dev, unsigned short langid, unsigned char index, void *buf, int size) +int usb_get_string(struct usb_device *dev, unsigned short langid, + unsigned char index, void *buf, int size) { - return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), - USB_REQ_GET_DESCRIPTOR, USB_DIR_IN, - (USB_DT_STRING << 8) + index, langid, buf, size, - HZ * USB_CTRL_GET_TIMEOUT); + int i; + int result; + + for (i = 0; i < 3; ++i) { + /* retry on length 0 or stall; some devices are flakey */ + result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), + USB_REQ_GET_DESCRIPTOR, USB_DIR_IN, + (USB_DT_STRING << 8) + index, langid, buf, size, + HZ * USB_CTRL_GET_TIMEOUT); + if (!(result == 0 || result == -EPIPE)) + break; + } + return result; +} + +static int usb_string_sub(struct usb_device *dev, unsigned int langid, + unsigned int index, unsigned char *buf) +{ + int rc; + + /* Try to read the string descriptor by asking for the maximum + * possible number of bytes */ + rc = usb_get_string(dev, langid, index, buf, 255); + + /* If that failed try to read the descriptor length, then + * ask for just that many bytes */ + if (rc < 0) { + rc = usb_get_string(dev, langid, index, buf, 2); + if (rc == 2) + rc = usb_get_string(dev, langid, index, buf, buf[0]); + } + + if (rc >= 0) { + /* There might be extra junk at the end of the descriptor */ + if (buf[0] < rc) + rc = buf[0]; + if (rc < 2) + rc = -EINVAL; + } + return rc; +} + +/** + * usb_string - returns ISO 8859-1 version of a string descriptor + * @dev: the device whose string descriptor is being retrieved + * @index: the number of the descriptor + * @buf: where to put the string + * @size: how big is "buf"? + * Context: !in_interrupt () + * + * This converts the UTF-16LE encoded strings returned by devices, from + * usb_get_string_descriptor(), to null-terminated ISO-8859-1 encoded ones + * that are more usable in most kernel contexts. Note that all characters + * in the chosen descriptor that can't be encoded using ISO-8859-1 + * are converted to the question mark ("?") character, and this function + * chooses strings in the first language supported by the device. + * + * The ASCII (or, redundantly, "US-ASCII") character set is the seven-bit + * subset of ISO 8859-1. ISO-8859-1 is the eight-bit subset of Unicode, + * and is appropriate for use many uses of English and several other + * Western European languages. (But it doesn't include the "Euro" symbol.) + * + * This call is synchronous, and may not be used in an interrupt context. + * + * Returns length of the string (>= 0) or usb_control_msg status (< 0). + */ +int usb_string(struct usb_device *dev, int index, char *buf, size_t size) +{ + unsigned char *tbuf; + int err; + unsigned int u, idx; + + if (size <= 0 || !buf || !index) + return -EINVAL; + buf[0] = 0; + tbuf = kmalloc(256, GFP_KERNEL); + if (!tbuf) + return -ENOMEM; + + /* get langid for strings if it's not yet known */ + if (!dev->have_langid) { + err = usb_string_sub(dev, 0, 0, tbuf); + if (err < 0) { + dev_err (&dev->dev, + "string descriptor 0 read error: %d\n", + err); + goto errout; + } else if (err < 4) { + dev_err (&dev->dev, "string descriptor 0 too short\n"); + err = -EINVAL; + goto errout; + } else { + dev->have_langid = -1; + dev->string_langid = tbuf[2] | (tbuf[3]<< 8); + /* always use the first langid listed */ + dev_dbg (&dev->dev, "default language 0x%04x\n", + dev->string_langid); + } + } + + err = usb_string_sub(dev, dev->string_langid, index, tbuf); + if (err < 0) + goto errout; + + size--; /* leave room for trailing NULL char in output buffer */ + for (idx = 0, u = 2; u < err; u += 2) { + if (idx >= size) + break; + if (tbuf[u+1]) /* high byte */ + buf[idx++] = '?'; /* non ISO-8859-1 character */ + else + buf[idx++] = tbuf[u]; + } + buf[idx] = 0; + err = idx; + + errout: + kfree(tbuf); + return err; } /** @@ -738,9 +854,8 @@ * the copy in usb-storage, for as long as we need two copies. */ - /* toggle was reset by the clear, then ep was reactivated */ + /* toggle was reset by the clear */ usb_settoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe), 0); - usb_endpoint_running(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe)); return 0; } @@ -754,9 +869,8 @@ * Deallocates hcd/hardware state for this endpoint ... and nukes all * pending urbs. * - * If the HCD hasn't registered a disable() function, this marks the - * endpoint as halted and sets its maxpacket size to 0 to prevent - * further submissions. + * If the HCD hasn't registered a disable() function, this sets the + * endpoint's maxpacket size to 0 to prevent further submissions. */ void usb_disable_endpoint(struct usb_device *dev, unsigned int epaddr) { @@ -765,13 +879,10 @@ else { unsigned int epnum = epaddr & USB_ENDPOINT_NUMBER_MASK; - if (usb_endpoint_out(epaddr)) { - usb_endpoint_halt(dev, epnum, 1); + if (usb_endpoint_out(epaddr)) dev->epmaxpacketout[epnum] = 0; - } else { - usb_endpoint_halt(dev, epnum, 0); + else dev->epmaxpacketin[epnum] = 0; - } } } @@ -814,7 +925,6 @@ usb_disable_endpoint(dev, i + USB_DIR_IN); } dev->toggle[0] = dev->toggle[1] = 0; - dev->halted[0] = dev->halted[1] = 0; /* getting rid of interfaces will disconnect * any drivers bound to them (a key side effect) @@ -850,9 +960,8 @@ * @dev: the device whose interface is being enabled * @epd: pointer to the endpoint descriptor * - * Marks the endpoint as running, resets its toggle, and stores - * its maxpacket value. For control endpoints, both the input - * and output sides are handled. + * Resets the endpoint toggle and stores its maxpacket value. + * For control endpoints, both the input and output sides are handled. */ void usb_enable_endpoint(struct usb_device *dev, struct usb_endpoint_descriptor *epd) @@ -864,12 +973,10 @@ USB_ENDPOINT_XFER_CONTROL); if (usb_endpoint_out(epaddr) || is_control) { - usb_endpoint_running(dev, epnum, 1); usb_settoggle(dev, epnum, 1, 0); dev->epmaxpacketout[epnum] = maxsize; } if (!usb_endpoint_out(epaddr) || is_control) { - usb_endpoint_running(dev, epnum, 0); usb_settoggle(dev, epnum, 0, 0); dev->epmaxpacketin[epnum] = maxsize; } @@ -932,6 +1039,9 @@ int ret; int manual = 0; + if (dev->state == USB_STATE_SUSPENDED) + return -EHOSTUNREACH; + iface = usb_ifnum_to_if(dev, interface); if (!iface) { dev_dbg(&dev->dev, "selecting invalid interface %d\n", @@ -1022,6 +1132,8 @@ * use usb_set_interface() on the interfaces it claims. Resetting the whole * configuration would affect other drivers' interfaces. * + * The caller must have locked the device. + * * Returns zero on success, else a negative error code. */ int usb_reset_configuration(struct usb_device *dev) @@ -1029,8 +1141,11 @@ int i, retval; struct usb_host_config *config; - /* caller must own dev->serialize (config won't change) - * and the usb bus readlock (so driver bindings are stable); + if (dev->state == USB_STATE_SUSPENDED) + return -EHOSTUNREACH; + + /* caller must have locked the device and must own + * the usb bus readlock (so driver bindings are stable); * so calls during probe() are fine */ @@ -1050,7 +1165,6 @@ } dev->toggle[0] = dev->toggle[1] = 0; - dev->halted[0] = dev->halted[1] = 0; /* re-init hc/hcd interface/endpoint state */ for (i = 0; i < config->desc.bNumInterfaces; i++) { @@ -1087,7 +1201,7 @@ * usb_set_configuration - Makes a particular device setting be current * @dev: the device whose configuration is being updated * @configuration: the configuration being chosen. - * Context: !in_interrupt(), caller holds dev->serialize + * Context: !in_interrupt(), caller has locked the device * * This is used to enable non-default device modes. Not all devices * use this kind of configurability; many devices only have one @@ -1108,8 +1222,8 @@ * usb_set_interface(). * * This call is synchronous. The calling context must be able to sleep, - * and must not hold the driver model lock for USB; usb device driver - * probe() methods may not use this routine. + * must have locked the device, and must not hold the driver model lock + * for USB; usb device driver probe() methods cannot use this routine. * * Returns zero on success, or else the status code returned by the * underlying call that failed. On succesful completion, each interface @@ -1124,8 +1238,6 @@ struct usb_interface **new_interfaces = NULL; int n, nintf; - /* dev->serialize guards all config changes */ - for (i = 0; i < dev->descriptor.bNumConfigurations; i++) { if (dev->config[i].desc.bConfigurationValue == configuration) { cp = &dev->config[i]; @@ -1142,6 +1254,9 @@ if (cp && configuration == 0) dev_warn(&dev->dev, "config 0 descriptor??\n"); + if (dev->state == USB_STATE_SUSPENDED) + return -EHOSTUNREACH; + /* Allocate memory for new interfaces before doing anything else, * so that if we run out then nothing will have changed. */ n = nintf = 0; @@ -1255,102 +1370,6 @@ } return ret; -} - -/** - * usb_string - returns ISO 8859-1 version of a string descriptor - * @dev: the device whose string descriptor is being retrieved - * @index: the number of the descriptor - * @buf: where to put the string - * @size: how big is "buf"? - * Context: !in_interrupt () - * - * This converts the UTF-16LE encoded strings returned by devices, from - * usb_get_string_descriptor(), to null-terminated ISO-8859-1 encoded ones - * that are more usable in most kernel contexts. Note that all characters - * in the chosen descriptor that can't be encoded using ISO-8859-1 - * are converted to the question mark ("?") character, and this function - * chooses strings in the first language supported by the device. - * - * The ASCII (or, redundantly, "US-ASCII") character set is the seven-bit - * subset of ISO 8859-1. ISO-8859-1 is the eight-bit subset of Unicode, - * and is appropriate for use many uses of English and several other - * Western European languages. (But it doesn't include the "Euro" symbol.) - * - * This call is synchronous, and may not be used in an interrupt context. - * - * Returns length of the string (>= 0) or usb_control_msg status (< 0). - */ -int usb_string(struct usb_device *dev, int index, char *buf, size_t size) -{ - unsigned char *tbuf; - int err, len; - unsigned int u, idx; - - if (size <= 0 || !buf || !index) - return -EINVAL; - buf[0] = 0; - tbuf = kmalloc(256, GFP_KERNEL); - if (!tbuf) - return -ENOMEM; - - /* get langid for strings if it's not yet known */ - if (!dev->have_langid) { - err = usb_get_descriptor(dev, USB_DT_STRING, 0, tbuf, 4); - if (err < 0) { - dev_err (&dev->dev, - "string descriptor 0 read error: %d\n", - err); - goto errout; - } else if (err < 4 || tbuf[0] < 4) { - dev_err (&dev->dev, "string descriptor 0 too short\n"); - err = -EINVAL; - goto errout; - } else { - dev->have_langid = -1; - dev->string_langid = tbuf[2] | (tbuf[3]<< 8); - /* always use the first langid listed */ - dev_dbg (&dev->dev, "default language 0x%04x\n", - dev->string_langid); - } - } - - /* - * ask for the length of the string - */ - - err = usb_get_string(dev, dev->string_langid, index, tbuf, 2); - if (err == -EPIPE || err == 0) { - dev_dbg(&dev->dev, "RETRY string %d read/%d\n", index, 2); - err = usb_get_string(dev, dev->string_langid, index, tbuf, 2); - } - if(err<2) - goto errout; - len=tbuf[0]; - - err = usb_get_string(dev, dev->string_langid, index, tbuf, len); - if (err == -EPIPE || err == 0) { - dev_dbg(&dev->dev, "RETRY string %d read/%d\n", index, len); - err = usb_get_string(dev, dev->string_langid, index, tbuf, len); - } - if (err < 0) - goto errout; - - size--; /* leave room for trailing NULL char in output buffer */ - for (idx = 0, u = 2; u < err; u += 2) { - if (idx >= size) - break; - if (tbuf[u+1]) /* high byte */ - buf[idx++] = '?'; /* non ISO-8859-1 character */ - else - buf[idx++] = tbuf[u]; - } - buf[idx] = 0; - err = idx; - - errout: - kfree(tbuf); - return err; } // synchronous request completion model diff -Nru a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c --- a/drivers/usb/core/sysfs.c 2004-07-04 23:02:39 -07:00 +++ b/drivers/usb/core/sysfs.c 2004-07-04 23:02:39 -07:00 @@ -55,9 +55,9 @@ if (sscanf (buf, "%u", &config) != 1 || config > 255) return -EINVAL; - down(&udev->serialize); + usb_lock_device(udev); value = usb_set_configuration (udev, config); - up(&udev->serialize); + usb_unlock_device(udev); return (value < 0) ? value : count; } diff -Nru a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c --- a/drivers/usb/core/urb.c 2004-07-04 23:02:39 -07:00 +++ b/drivers/usb/core/urb.c 2004-07-04 23:02:39 -07:00 @@ -256,13 +256,6 @@ if (!usb_pipecontrol (pipe) && dev->state < USB_STATE_CONFIGURED) return -ENODEV; - /* (actually HCDs may need to duplicate this, endpoint might yet - * stall due to queued bulk/intr transactions that complete after - * we check) - */ - if (usb_endpoint_halted (dev, usb_pipeendpoint (pipe), is_out)) - return -EPIPE; - /* FIXME there should be a sharable lock protecting us against * config/altsetting changes and disconnects, kicking in here. * (here == before maxpacket, and eventually endpoint type, @@ -407,26 +400,25 @@ * canceled (rather than any other code) and will quickly be removed * from host controller data structures. * - * When the URB_ASYNC_UNLINK transfer flag for the URB is clear, this - * request is synchronous. Success is indicated by returning zero, - * at which time the urb will have been unlinked and its completion - * handler will have been called with urb->status == -ENOENT. Failure is - * indicated by any other return value. - * - * The synchronous cancelation mode may not be used - * when unlinking an urb from an interrupt context, such as a bottom - * half or a completion handler; or when holding a spinlock; or in - * other cases when the caller can't schedule(). + * In the past, clearing the URB_ASYNC_UNLINK transfer flag for the + * URB indicated that the request was synchronous. This usage is now + * deprecated; if the flag is clear the call will be forwarded to + * usb_kill_urb() and the return value will be 0. In the future, drivers + * should call usb_kill_urb() directly for synchronous unlinking. * * When the URB_ASYNC_UNLINK transfer flag for the URB is set, this * request is asynchronous. Success is indicated by returning -EINPROGRESS, - * at which time the urb will normally not have been unlinked. - * The completion function will see urb->status == -ECONNRESET. Failure - * is indicated by any other return value. + * at which time the URB will normally have been unlinked but not yet + * given back to the device driver. When it is called, the completion + * function will see urb->status == -ECONNRESET. Failure is indicated + * by any other return value. Unlinking will fail when the URB is not + * currently "linked" (i.e., it was never submitted, or it was unlinked + * before, or the hardware is already finished with it), even if the + * completion handler has not yet run. * * Unlinking and Endpoint Queues: * - * Host Controller Driver (HCDs) place all the URBs for a particular + * Host Controller Drivers (HCDs) place all the URBs for a particular * endpoint in a queue. Normally the queue advances as the controller * hardware processes each request. But when an URB terminates with any * fault (such as an error, or being unlinked) its queue stops, at least @@ -449,16 +441,54 @@ * An unlinked URB may leave a gap in the stream of packets. It is undefined * whether such gaps can be filled in. * - * When control URBs terminates with an error, it is likely that the + * When a control URB terminates with an error, it is likely that the * status stage of the transfer will not take place, even if it is merely * a soft error resulting from a short-packet with URB_SHORT_NOT_OK set. */ int usb_unlink_urb(struct urb *urb) { - if (urb && urb->dev && urb->dev->bus && urb->dev->bus->op) - return urb->dev->bus->op->unlink_urb(urb); - else + if (!(urb->transfer_flags & URB_ASYNC_UNLINK)) { + usb_kill_urb(urb); + return 0; + } + if (!(urb->dev && urb->dev->bus && urb->dev->bus->op)) return -ENODEV; + return urb->dev->bus->op->unlink_urb(urb, -ECONNRESET); +} + +/** + * usb_kill_urb - cancel a transfer request and wait for it to finish + * @urb: pointer to URB describing a previously submitted request + * + * This routine cancels an in-progress request. It is guaranteed that + * upon return all completion handlers will have finished and the URB + * will be totally idle and available for reuse. These features make + * this an ideal way to stop I/O in a disconnect() callback or close() + * function. If the request has not already finished or been unlinked + * the completion handler will see urb->status == -ENOENT. + * + * While the routine is running, attempts to resubmit the URB will fail + * with error -EPERM. Thus even if the URB's completion handler always + * tries to resubmit, it will not succeed and the URB will become idle. + * + * This routine may not be used in an interrupt context (such as a bottom + * half or a completion handler), or when holding a spinlock, or in other + * situations where the caller can't schedule(). + */ +void usb_kill_urb(struct urb *urb) +{ + if (!(urb->dev && urb->dev->bus && urb->dev->bus->op)) + return; + spin_lock_irq(&urb->lock); + ++urb->reject; + spin_unlock_irq(&urb->lock); + + urb->dev->bus->op->unlink_urb(urb, -ENOENT); + wait_event(usb_kill_urb_queue, atomic_read(&urb->use_count) == 0); + + spin_lock_irq(&urb->lock); + --urb->reject; + spin_unlock_irq(&urb->lock); } EXPORT_SYMBOL(usb_init_urb); @@ -467,4 +497,5 @@ EXPORT_SYMBOL(usb_get_urb); EXPORT_SYMBOL(usb_submit_urb); EXPORT_SYMBOL(usb_unlink_urb); +EXPORT_SYMBOL(usb_kill_urb); diff -Nru a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c --- a/drivers/usb/core/usb.c 2004-07-04 23:02:39 -07:00 +++ b/drivers/usb/core/usb.c 2004-07-04 23:02:39 -07:00 @@ -39,6 +39,7 @@ #include #include #include +#include #include #include @@ -62,6 +63,8 @@ int nousb; /* Disable USB when built into kernel image */ /* Not honored on modular build */ +static DECLARE_RWSEM(usb_all_devices_rwsem); + static int generic_probe (struct device *dev) { @@ -93,11 +96,16 @@ if (!driver->probe) return error; + if (interface_to_usbdev(intf)->state == USB_STATE_SUSPENDED) + return -EHOSTUNREACH; id = usb_match_id (intf, driver->id_table); if (id) { dev_dbg (dev, "%s - got id\n", __FUNCTION__); + intf->condition = USB_INTERFACE_BINDING; error = driver->probe (intf, id); + intf->condition = error ? USB_INTERFACE_UNBOUND : + USB_INTERFACE_BOUND; } return error; @@ -109,6 +117,8 @@ struct usb_interface *intf = to_usb_interface(dev); struct usb_driver *driver = to_usb_driver(intf->dev.driver); + intf->condition = USB_INTERFACE_UNBINDING; + /* release all urbs for this interface */ usb_disable_interface(interface_to_usbdev(intf), intf); @@ -120,6 +130,7 @@ intf->altsetting[0].desc.bInterfaceNumber, 0); usb_set_intfdata(intf, NULL); + intf->condition = USB_INTERFACE_UNBOUND; return 0; } @@ -149,7 +160,9 @@ new_driver->driver.probe = usb_probe_interface; new_driver->driver.remove = usb_unbind_interface; + usb_lock_all_devices(); retval = driver_register(&new_driver->driver); + usb_unlock_all_devices(); if (!retval) { pr_info("%s: registered new driver %s\n", @@ -178,7 +191,9 @@ { pr_info("%s: deregistering driver %s\n", usbcore_name, driver->name); + usb_lock_all_devices(); driver_unregister (&driver->driver); + usb_unlock_all_devices(); usbfs_update_special(); } @@ -200,7 +215,7 @@ * alternate settings available for this interfaces. * * Don't call this function unless you are bound to one of the interfaces - * on this device or you own the dev->serialize semaphore! + * on this device or you have locked the device! */ struct usb_interface *usb_ifnum_to_if(struct usb_device *dev, unsigned ifnum) { @@ -233,7 +248,7 @@ * drivers avoid such mistakes. * * Don't call this function unless you are bound to the intf interface - * or you own the device's ->serialize semaphore! + * or you have locked the device! */ struct usb_host_interface *usb_altnum_to_altsetting(struct usb_interface *intf, unsigned int altnum) @@ -301,9 +316,9 @@ * way to bind to an interface is to return the private data from * the driver's probe() method. * - * Callers must own the driver model's usb bus writelock. So driver - * probe() entries don't need extra locking, but other call contexts - * may need to explicitly claim that lock. + * Callers must lock the device and own the driver model's usb bus writelock. + * So driver probe() entries don't need extra locking, but other call contexts + * may need to explicitly claim those locks. */ int usb_driver_claim_interface(struct usb_driver *driver, struct usb_interface *iface, void* priv) { @@ -314,6 +329,7 @@ dev->driver = &driver->driver; usb_set_intfdata(iface, priv); + iface->condition = USB_INTERFACE_BOUND; /* if interface was already added, bind now; else let * the future device_add() bind it, bypassing probe() @@ -334,8 +350,8 @@ * also causes the driver disconnect() method to be called. * * This call is synchronous, and may not be used in an interrupt context. - * Callers must own the usb_device serialize semaphore and the driver model's - * usb bus writelock. So driver disconnect() entries don't need extra locking, + * Callers must lock the device and own the driver model's usb bus writelock. + * So driver disconnect() entries don't need extra locking, * but other call contexts may need to explicitly claim those locks. */ void usb_driver_release_interface(struct usb_driver *driver, @@ -353,6 +369,7 @@ dev->driver = NULL; usb_set_intfdata(iface, NULL); + iface->condition = USB_INTERFACE_UNBOUND; } /** @@ -828,6 +845,116 @@ put_device(&intf->dev); } +/** + * usb_lock_device - acquire the lock for a usb device structure + * @udev: device that's being locked + * + * Use this routine rather than manipulating udev->serialize directly. + * This is necessary for proper interaction with usb_lock_all_devices(). + */ +void usb_lock_device(struct usb_device *udev) +{ + down_read(&usb_all_devices_rwsem); + down(&udev->serialize); +} + +/** + * usb_trylock_device - attempt to acquire the lock for a usb device structure + * @udev: device that's being locked + * + * Use this routine rather than manipulating udev->serialize directly. + * This is necessary for proper interaction with usb_lock_all_devices(). + * + * Returns 1 if successful, 0 if contention. + */ +int usb_trylock_device(struct usb_device *udev) +{ + if (!down_read_trylock(&usb_all_devices_rwsem)) + return 0; + if (!down_trylock(&udev->serialize)) { + up_read(&usb_all_devices_rwsem); + return 0; + } + return 1; +} + +/** + * usb_lock_device_for_reset - cautiously acquire the lock for a + * usb device structure + * @udev: device that's being locked + * @iface: interface bound to the driver making the request (optional) + * + * Attempts to acquire the device lock, but fails if the device is + * NOTATTACHED or SUSPENDED, or if iface is specified and the interface + * is neither BINDING nor BOUND. Rather than sleeping to wait for the + * lock, the routine polls repeatedly. This is to prevent deadlock with + * disconnect; in some drivers (such as usb-storage) the disconnect() + * callback will block waiting for a device reset to complete. + * + * Returns a negative error code for failure, otherwise 1 or 0 to indicate + * that the device will or will not have to be unlocked. (0 can be + * returned when an interface is given and is BINDING, because in that + * case the driver already owns the device lock.) + */ +int usb_lock_device_for_reset(struct usb_device *udev, + struct usb_interface *iface) +{ + if (udev->state == USB_STATE_NOTATTACHED) + return -ENODEV; + if (iface) { + switch (iface->condition) { + case USB_INTERFACE_BINDING: + return 0; + case USB_INTERFACE_BOUND: + break; + default: + return -EINTR; + } + } + + while (!usb_trylock_device(udev)) { + msleep(15); + if (udev->state == USB_STATE_NOTATTACHED) + return -ENODEV; + if (iface && iface->condition != USB_INTERFACE_BOUND) + return -EINTR; + } + return 1; +} + +/** + * usb_unlock_device - release the lock for a usb device structure + * @udev: device that's being unlocked + * + * Use this routine rather than manipulating udev->serialize directly. + * This is necessary for proper interaction with usb_lock_all_devices(). + */ +void usb_unlock_device(struct usb_device *udev) +{ + up(&udev->serialize); + up_read(&usb_all_devices_rwsem); +} + +/** + * usb_lock_all_devices - acquire the lock for all usb device structures + * + * This is necessary when registering a new driver or probing a bus, + * since the driver-model core may try to use any usb_device. + */ +void usb_lock_all_devices(void) +{ + down_write(&usb_all_devices_rwsem); +} + +/** + * usb_unlock_all_devices - release the lock for all usb device structures + */ +void usb_unlock_all_devices(void) +{ + up_write(&usb_all_devices_rwsem); +} + + static struct usb_device *match_device(struct usb_device *dev, u16 vendor_id, u16 product_id) { @@ -849,8 +976,10 @@ /* look through all of the children of this device */ for (child = 0; child < dev->maxchild; ++child) { if (dev->children[child]) { + usb_lock_device(dev->children[child]); ret_dev = match_device(dev->children[child], vendor_id, product_id); + usb_unlock_device(dev->children[child]); if (ret_dev) goto exit; } @@ -885,7 +1014,9 @@ bus = container_of(buslist, struct usb_bus, bus_list); if (!bus->root_hub) continue; + usb_lock_device(bus->root_hub); dev = match_device(bus->root_hub, vendor_id, product_id); + usb_unlock_device(bus->root_hub); if (dev) goto exit; } @@ -1362,6 +1493,11 @@ EXPORT_SYMBOL(usb_put_dev); EXPORT_SYMBOL(usb_get_dev); EXPORT_SYMBOL(usb_hub_tt_clear_buffer); + +EXPORT_SYMBOL(usb_lock_device); +EXPORT_SYMBOL(usb_trylock_device); +EXPORT_SYMBOL(usb_lock_device_for_reset); +EXPORT_SYMBOL(usb_unlock_device); EXPORT_SYMBOL(usb_driver_claim_interface); EXPORT_SYMBOL(usb_driver_release_interface); diff -Nru a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h --- a/drivers/usb/core/usb.h 2004-07-04 23:02:39 -07:00 +++ b/drivers/usb/core/usb.h 2004-07-04 23:02:39 -07:00 @@ -24,5 +24,8 @@ extern void usb_set_device_state(struct usb_device *udev, enum usb_device_state new_state); +extern void usb_lock_all_devices(void); +extern void usb_unlock_all_devices(void); + /* for labeling diagnostics */ extern const char *usbcore_name; diff -Nru a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c --- a/drivers/usb/host/ehci-hub.c 2004-07-04 23:02:39 -07:00 +++ b/drivers/usb/host/ehci-hub.c 2004-07-04 23:02:39 -07:00 @@ -81,7 +81,7 @@ } -/* caller owns root->serialize, and should reset/reinit on error */ +/* caller has locked the root hub, and should reset/reinit on error */ static int ehci_hub_resume (struct usb_hcd *hcd) { struct ehci_hcd *ehci = hcd_to_ehci (hcd); diff -Nru a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c --- a/drivers/usb/host/ehci-q.c 2004-07-04 23:02:39 -07:00 +++ b/drivers/usb/host/ehci-q.c 2004-07-04 23:02:39 -07:00 @@ -153,17 +153,9 @@ usb_pipein (urb->pipe) ? "in" : "out", token, urb->status); - /* stall indicates some recovery action is needed */ - if (urb->status == -EPIPE) { - int pipe = urb->pipe; - - if (!usb_pipecontrol (pipe)) - usb_endpoint_halt (urb->dev, - usb_pipeendpoint (pipe), - usb_pipeout (pipe)); - /* if async CSPLIT failed, try cleaning out the TT buffer */ - } else if (urb->dev->tt && !usb_pipeint (urb->pipe) + if (urb->status != -EPIPE + && urb->dev->tt && !usb_pipeint (urb->pipe) && ((token & QTD_STS_MMF) != 0 || QTD_CERR(token) == 0) && (!ehci_is_ARC(ehci) diff -Nru a/drivers/usb/host/hc_simple.c b/drivers/usb/host/hc_simple.c --- a/drivers/usb/host/hc_simple.c 2004-07-04 23:02:39 -07:00 +++ b/drivers/usb/host/hc_simple.c 2004-07-04 23:02:39 -07:00 @@ -146,11 +146,6 @@ if (!urb->dev || !urb->dev->bus || urb->hcpriv) return -EINVAL; - if (usb_endpoint_halted - (urb->dev, usb_pipeendpoint (pipe), usb_pipeout (pipe))) { - printk ("hci_submit_urb: endpoint_halted\n"); - return -EPIPE; - } hci = (hci_t *) urb->dev->bus->hcpriv; /* a request to the virtual root hub */ @@ -189,7 +184,7 @@ * * Return: 0 if success or error code **************************************************************************/ -static int hci_unlink_urb (struct urb * urb) +static int hci_unlink_urb (struct urb * urb, int status) { unsigned long flags; hci_t *hci; @@ -219,45 +214,21 @@ if (!list_empty (&urb->urb_list) && urb->status == -EINPROGRESS) { /* URB active? */ - if (urb->transfer_flags & URB_ASYNC_UNLINK) { - /* asynchronous with callback */ - /* relink the urb to the del list */ - list_move (&urb->urb_list, &hci->del_list); - spin_unlock_irqrestore (&usb_urb_lock, flags); - } else { - /* synchronous without callback */ - - add_wait_queue (&hci->waitq, &wait); - - set_current_state (TASK_UNINTERRUPTIBLE); - comp = urb->complete; - urb->complete = NULL; - - /* relink the urb to the del list */ - list_move(&urb->urb_list, &hci->del_list); - - spin_unlock_irqrestore (&usb_urb_lock, flags); - - schedule_timeout (HZ / 50); - - if (!list_empty (&urb->urb_list)) - list_del (&urb->urb_list); - - urb->complete = comp; - urb->hcpriv = NULL; - remove_wait_queue (&hci->waitq, &wait); - } + /* asynchronous with callback */ + /* relink the urb to the del list */ + list_move (&urb->urb_list, &hci->del_list); + urb->status = status; + spin_unlock_irqrestore (&usb_urb_lock, flags); } else { /* hcd does not own URB but we keep the driver happy anyway */ spin_unlock_irqrestore (&usb_urb_lock, flags); - if (urb->complete && (urb->transfer_flags & URB_ASYNC_UNLINK)) { - urb->status = -ENOENT; + if (urb->complete) { + urb->status = status; urb->actual_length = 0; urb->complete (urb, NULL); - urb->status = 0; - } else { - urb->status = -ENOENT; + if (urb->reject) + wake_up (&usb_kill_urb_queue); } } diff -Nru a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c --- a/drivers/usb/host/ohci-hub.c 2004-07-04 23:02:39 -07:00 +++ b/drivers/usb/host/ohci-hub.c 2004-07-04 23:02:39 -07:00 @@ -165,7 +165,7 @@ static int hc_restart (struct ohci_hcd *ohci); -/* caller owns root->serialize */ +/* caller has locked the root hub */ static int ohci_hub_resume (struct usb_hcd *hcd) { struct ohci_hcd *ohci = hcd_to_ohci (hcd); @@ -301,9 +301,9 @@ { struct usb_hcd *hcd = _hcd; - down (&hcd->self.root_hub->serialize); + usb_lock_device (hcd->self.root_hub); (void) ohci_hub_resume (hcd); - up (&hcd->self.root_hub->serialize); + usb_unlock_device (hcd->self.root_hub); } #else @@ -381,12 +381,12 @@ && ((OHCI_CTRL_HCFS | OHCI_SCHED_ENABLES) & ohci->hc_control) == OHCI_USB_OPER - && down_trylock (&hcd->self.root_hub->serialize) == 0 + && usb_trylock_device (hcd->self.root_hub) == 0 ) { ohci_vdbg (ohci, "autosuspend\n"); (void) ohci_hub_suspend (&ohci->hcd); ohci->hcd.state = USB_STATE_RUNNING; - up (&hcd->self.root_hub->serialize); + usb_unlock_device (hcd->self.root_hub); } #endif diff -Nru a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c --- a/drivers/usb/host/ohci-pci.c 2004-07-04 23:02:39 -07:00 +++ b/drivers/usb/host/ohci-pci.c 2004-07-04 23:02:39 -07:00 @@ -127,9 +127,9 @@ #ifdef CONFIG_USB_SUSPEND (void) usb_suspend_device (hcd->self.root_hub); #else - down (&hcd->self.root_hub->serialize); + usb_lock_device (hcd->self.root_hub); (void) ohci_hub_suspend (hcd); - up (&hcd->self.root_hub->serialize); + usb_unlock_device (hcd->self.root_hub); #endif /* let things settle down a bit */ @@ -175,9 +175,9 @@ /* get extra cleanup even if remote wakeup isn't in use */ retval = usb_resume_device (hcd->self.root_hub); #else - down (&hcd->self.root_hub->serialize); + usb_lock_device (hcd->self.root_hub); retval = ohci_hub_resume (hcd); - up (&hcd->self.root_hub->serialize); + usb_unlock_device (hcd->self.root_hub); #endif if (retval == 0) { diff -Nru a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c --- a/drivers/usb/host/ohci-q.c 2004-07-04 23:02:39 -07:00 +++ b/drivers/usb/host/ohci-q.c 2004-07-04 23:02:39 -07:00 @@ -751,12 +751,6 @@ cc = TD_CC_GET (tdINFO); - /* control endpoints only have soft stalls */ - if (type != PIPE_CONTROL && cc == TD_CC_STALL) - usb_endpoint_halt (urb->dev, - usb_pipeendpoint (urb->pipe), - usb_pipeout (urb->pipe)); - /* update packet status if needed (short is normally ok) */ if (cc == TD_DATAUNDERRUN && !(urb->transfer_flags & URB_SHORT_NOT_OK)) diff -Nru a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c --- a/drivers/usb/host/uhci-hcd.c 2004-07-04 23:02:39 -07:00 +++ b/drivers/usb/host/uhci-hcd.c 2004-07-04 23:02:39 -07:00 @@ -1120,10 +1120,6 @@ td_error: ret = uhci_map_status(status, uhci_packetout(td_token(td))); - if (ret == -EPIPE) - /* endpoint has stalled - mark it halted */ - usb_endpoint_halt(urb->dev, uhci_endpoint(td_token(td)), - uhci_packetout(td_token(td))); err: /* diff -Nru a/drivers/usb/image/microtek.c b/drivers/usb/image/microtek.c --- a/drivers/usb/image/microtek.c 2004-07-04 23:02:39 -07:00 +++ b/drivers/usb/image/microtek.c 2004-07-04 23:02:39 -07:00 @@ -214,8 +214,8 @@ #ifdef MTS_DO_DEBUG static inline void mts_debug_dump(struct mts_desc* desc) { - MTS_DEBUG("desc at 0x%x: halted = %02x%02x, toggle = %02x%02x\n", - (int)desc,(int)desc->usb_dev->halted[1],(int)desc->usb_dev->halted[0], + MTS_DEBUG("desc at 0x%x: toggle = %02x%02x\n", + (int)desc, (int)desc->usb_dev->toggle[1],(int)desc->usb_dev->toggle[0] ); MTS_DEBUG("ep_out=%x ep_response=%x ep_image=%x\n", @@ -341,12 +341,18 @@ static int mts_scsi_host_reset (Scsi_Cmnd *srb) { struct mts_desc* desc = (struct mts_desc*)(srb->device->host->hostdata[0]); + int result, rc; MTS_DEBUG_GOT_HERE(); mts_debug_dump(desc); - usb_reset_device(desc->usb_dev); /*FIXME: untested on new reset code */ - return 0; /* RANT why here 0 and not SUCCESS */ + rc = usb_lock_device_for_reset(desc->usb_dev, desc->usb_intf); + if (rc < 0) + return FAILED; + result = usb_reset_device(desc->usb_dev);; + if (rc) + usb_unlock_device(desc->usb_dev); + return result ? FAILED : SUCCESS; } static @@ -777,6 +783,7 @@ goto out_kfree; new_desc->usb_dev = dev; + new_desc->usb_intf = intf; init_MUTEX(&new_desc->lock); /* endpoints */ diff -Nru a/drivers/usb/image/microtek.h b/drivers/usb/image/microtek.h --- a/drivers/usb/image/microtek.h 2004-07-04 23:02:39 -07:00 +++ b/drivers/usb/image/microtek.h 2004-07-04 23:02:39 -07:00 @@ -31,6 +31,7 @@ struct mts_desc *prev; struct usb_device *usb_dev; + struct usb_interface *usb_intf; /* Endpoint addresses */ u8 ep_out; diff -Nru a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c --- a/drivers/usb/input/hid-core.c 2004-07-04 23:02:39 -07:00 +++ b/drivers/usb/input/hid-core.c 2004-07-04 23:02:39 -07:00 @@ -1425,6 +1425,9 @@ #define USB_VENDOR_ID_GLAB 0x06c2 #define USB_DEVICE_ID_4_PHIDGETSERVO_30 0x0038 #define USB_DEVICE_ID_1_PHIDGETSERVO_30 0x0039 +#define USB_DEVICE_ID_8_8_8_IF_KIT 0x0045 +#define USB_DEVICE_ID_0_0_4_IF_KIT 0x0040 +#define USB_DEVICE_ID_0_8_8_IF_KIT 0x0053 #define USB_VENDOR_ID_WISEGROUP 0x0925 #define USB_DEVICE_ID_1_PHIDGETSERVO_20 0x8101 @@ -1483,8 +1486,13 @@ { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS2 + 7, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_VOLITO, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PTU, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_4_PHIDGETSERVO_30, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_1_PHIDGETSERVO_30, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_8_8_8_IF_KIT, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_0_4_IF_KIT, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_8_8_IF_KIT, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_4_PHIDGETSERVO_20, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_1_PHIDGETSERVO_20, HID_QUIRK_IGNORE }, diff -Nru a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c --- a/drivers/usb/storage/scsiglue.c 2004-07-04 23:02:39 -07:00 +++ b/drivers/usb/storage/scsiglue.c 2004-07-04 23:02:39 -07:00 @@ -261,7 +261,7 @@ static int bus_reset( Scsi_Cmnd *srb ) { struct us_data *us = (struct us_data *)srb->device->host->hostdata[0]; - int result; + int result, rc; US_DEBUGP("%s called\n", __FUNCTION__); if (us->sm_state != US_STATE_IDLE) { @@ -286,8 +286,16 @@ result = -EBUSY; US_DEBUGP("Refusing to reset a multi-interface device\n"); } else { - result = usb_reset_device(us->pusb_dev); - US_DEBUGP("usb_reset_device returns %d\n", result); + rc = usb_lock_device_for_reset(us->pusb_dev, us->pusb_intf); + if (rc < 0) { + US_DEBUGP("unable to lock device for reset: %d\n", rc); + result = rc; + } else { + result = usb_reset_device(us->pusb_dev); + if (rc) + usb_unlock_device(us->pusb_dev); + US_DEBUGP("usb_reset_device returns %d\n", result); + } } up(&(us->dev_semaphore)); diff -Nru a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c --- a/drivers/usb/storage/transport.c 2004-07-04 23:02:39 -07:00 +++ b/drivers/usb/storage/transport.c 2004-07-04 23:02:39 -07:00 @@ -260,9 +260,7 @@ USB_ENDPOINT_HALT, endp, NULL, 0, 3*HZ); - /* reset the toggles and endpoint flags */ - usb_endpoint_running(us->pusb_dev, usb_pipeendpoint(pipe), - usb_pipeout(pipe)); + /* reset the endpoint toggle */ usb_settoggle(us->pusb_dev, usb_pipeendpoint(pipe), usb_pipeout(pipe), 0); diff -Nru a/include/linux/usb.h b/include/linux/usb.h --- a/include/linux/usb.h 2004-07-04 23:02:39 -07:00 +++ b/include/linux/usb.h 2004-07-04 23:02:39 -07:00 @@ -61,6 +61,13 @@ int extralen; }; +enum usb_interface_condition { + USB_INTERFACE_UNBOUND = 0, + USB_INTERFACE_BINDING, + USB_INTERFACE_BOUND, + USB_INTERFACE_UNBINDING, +}; + /** * struct usb_interface - what usb device drivers talk to * @altsetting: array of interface structures, one for each alternate @@ -75,6 +82,8 @@ * be unused. The driver should set this value in the probe() * function of the driver, after it has been assigned a minor * number from the USB core by calling usb_register_dev(). + * @condition: binding state of the interface: not bound, binding + * (in probe()), bound to a driver, or unbinding (in disconnect()) * @dev: driver model's view of this device * @class_dev: driver model's class view of this device. * @@ -113,6 +122,7 @@ unsigned num_altsetting; /* number of alternate settings */ int minor; /* minor number this interface is bound to */ + enum usb_interface_condition condition; /* state of binding */ struct device dev; /* interface specific device info */ struct class_device *class_dev; }; @@ -279,6 +289,17 @@ struct usb_tt; +/** + * struct usb_device - kernel's representation of a USB device + * + * FIXME: Write the kerneldoc! + * + * WARNING: Drivers should not attempt to manipulate usbdev->serialize + * directly. Instead use usb_lock_device() and usb_unlock_device(). + * + * Usbcore drivers should not set usbdev->state directly. Instead use + * usb_set_device_state(). + */ struct usb_device { int devnum; /* Address on USB bus */ char devpath [16]; /* Use in messages: /port/port/... */ @@ -291,8 +312,6 @@ struct semaphore serialize; unsigned int toggle[2]; /* one bit for each endpoint ([0] = IN, [1] = OUT) */ - unsigned int halted[2]; /* endpoint halts; one bit per endpoint # & direction; */ - /* [0] = IN, [1] = OUT */ int epmaxpacketin[16]; /* INput endpoint specific maximums */ int epmaxpacketout[16]; /* OUTput endpoint specific maximums */ @@ -332,9 +351,15 @@ extern struct usb_device *usb_get_dev(struct usb_device *dev); extern void usb_put_dev(struct usb_device *dev); -/* mostly for devices emulating SCSI over USB */ +/* for device locking -- don't manipulate usbdev->serialize directly! */ +extern void usb_lock_device(struct usb_device *udev); +extern int usb_trylock_device(struct usb_device *udev); +extern int usb_lock_device_for_reset(struct usb_device *udev, + struct usb_interface *iface); +extern void usb_unlock_device(struct usb_device *udev); + +/* USB port reset for device reinitialization */ extern int usb_reset_device(struct usb_device *dev); -extern int __usb_reset_device(struct usb_device *dev); extern struct usb_device *usb_find_device(u16 vendor_id, u16 product_id); @@ -657,7 +682,7 @@ * calling usb_alloc_urb() and freed with a call to usb_free_urb(). * Initialization may be done using various usb_fill_*_urb() functions. URBs * are submitted using usb_submit_urb(), and pending requests may be canceled - * using usb_unlink_urb(). + * using usb_unlink_urb() or usb_kill_urb(). * * Data Transfer Buffers: * @@ -684,7 +709,9 @@ * All URBs submitted must initialize dev, pipe, * transfer_flags (may be zero), complete, timeout (may be zero). * The URB_ASYNC_UNLINK transfer flag affects later invocations of - * the usb_unlink_urb() routine. + * the usb_unlink_urb() routine. Note: Failure to set URB_ASYNC_UNLINK + * with usb_unlink_urb() is deprecated. For synchronous unlinks use + * usb_kill_urb() instead. * * All URBs must also initialize * transfer_buffer and transfer_buffer_length. They may provide the @@ -762,6 +789,8 @@ void *hcpriv; /* private data for host controller */ struct list_head urb_list; /* list pointer to all active urbs */ int bandwidth; /* bandwidth for INT/ISO request */ + atomic_t use_count; /* concurrent submissions counter */ + u8 reject; /* submissions will fail */ /* public, documented fields in the urb that can be used by drivers */ struct usb_device *dev; /* (in) pointer to associated device */ @@ -897,6 +926,7 @@ extern struct urb *usb_get_urb(struct urb *urb); extern int usb_submit_urb(struct urb *urb, int mem_flags); extern int usb_unlink_urb(struct urb *urb); +extern void usb_kill_urb(struct urb *urb); #define HAVE_USB_BUFFERS void *usb_buffer_alloc (struct usb_device *dev, size_t size, @@ -1070,10 +1100,6 @@ #define usb_gettoggle(dev, ep, out) (((dev)->toggle[out] >> (ep)) & 1) #define usb_dotoggle(dev, ep, out) ((dev)->toggle[out] ^= (1 << (ep))) #define usb_settoggle(dev, ep, out, bit) ((dev)->toggle[out] = ((dev)->toggle[out] & ~(1 << (ep))) | ((bit) << (ep))) - -/* Endpoint halt control/status ... likewise USE WITH CAUTION */ -#define usb_endpoint_running(dev, ep, out) ((dev)->halted[out] &= ~(1 << (ep))) -#define usb_endpoint_halted(dev, ep, out) ((dev)->halted[out] & (1 << (ep))) static inline unsigned int __create_pipe(struct usb_device *dev, unsigned int endpoint)