Commit bb0851ff authored by Linus Torvalds's avatar Linus Torvalds

Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6

* git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6: (25 commits)
  USB: s3c2410 gadget: ensure vbus pin in input mode during read
  USB: s3c2410 gadget: allow sharing of vbus irq
  USB: s3c2410 gadget: Header move fixups
  USB: usb-storage: unusual_devs entry for JetFlash TS1GJF2A
  USB: fix up EHCI startup synchronization
  USB: make the microtek driver and HAL cooperate
  USB: uevent environment key fix
  USB: keep track of whether interface sysfs files exist
  USB: sierra: new product id
  USB HCD: avoid duplicate local_irq_disable()
  USB: mailing lists have changed
  USB: remove USB HUB entry from MAINTAINERS
  USB: fix directory references in usb/README
  USB: add support for an older firmware revision for the Nikon D200
  USB: FIx locks and urb->status in adutux (updated)
  USB: power-management documenation update
  USB: Fix signr comment in usbdevice_fs.h
  usbserial: fix inconsistent lock state
  USB: fix usbled disconnect read race #2
  USB: free memory when writing fails in usb/serial/mos7840.c
  ...
parents 34f2c1c3 5f629ad7
......@@ -278,6 +278,14 @@ optional. The methods' jobs are quite simple:
(although the interfaces will be in the same altsettings as
before the suspend).
If the device is disconnected or powered down while it is suspended,
the disconnect method will be called instead of the resume or
reset_resume method. This is also quite likely to happen when
waking up from hibernation, as many systems do not maintain suspend
current to the USB host controllers during hibernation. (It's
possible to work around the hibernation-forces-disconnect problem by
using the USB Persist facility.)
The reset_resume method is used by the USB Persist facility (see
Documentation/usb/persist.txt) and it can also be used under certain
circumstances when CONFIG_USB_PERSIST is not enabled. Currently, if a
......
......@@ -323,8 +323,7 @@ S: Maintained
ALCATEL SPEEDTOUCH USB DRIVER
P: Duncan Sands
M: duncan.sands@free.fr
L: linux-usb-users@lists.sourceforge.net
L: linux-usb-devel@lists.sourceforge.net
L: linux-usb@vger.kernel.org
W: http://www.linux-usb.org/SpeedTouch/
S: Maintained
......@@ -1043,7 +1042,7 @@ S: Maintained
CIRRUS LOGIC EP93XX OHCI USB HOST DRIVER
P: Lennert Buytenhek
M: kernel@wantstofly.org
L: linux-usb-devel@lists.sourceforge.net
L: linux-usb@vger.kernel.org
S: Maintained
CIRRUS LOGIC CS4280/CS461x SOUNDDRIVER
......@@ -1552,7 +1551,7 @@ S: Maintained
FREESCALE HIGHSPEED USB DEVICE DRIVER
P: Li Yang
M: leoli@freescale.com
L: linux-usb-devel@lists.sourceforge.net
L: linux-usb@vger.kernel.org
L: linuxppc-dev@ozlabs.org
S: Maintained
......@@ -3810,22 +3809,20 @@ S: Maintained
USB ACM DRIVER
P: Oliver Neukum
M: oliver@neukum.name
L: linux-usb-users@lists.sourceforge.net
L: linux-usb-devel@lists.sourceforge.net
L: linux-usb@vger.kernel.org
S: Maintained
USB BLOCK DRIVER (UB ub)
P: Pete Zaitcev
M: zaitcev@redhat.com
L: linux-kernel@vger.kernel.org
L: linux-usb-devel@lists.sourceforge.net
L: linux-usb@vger.kernel.org
S: Supported
USB CDC ETHERNET DRIVER
P: Greg Kroah-Hartman
M: greg@kroah.com
L: linux-usb-users@lists.sourceforge.net
L: linux-usb-devel@lists.sourceforge.net
L: linux-usb@vger.kernel.org
S: Maintained
W: http://www.kroah.com/linux-usb/
......@@ -3839,13 +3836,13 @@ S: Maintained
USB EHCI DRIVER
P: David Brownell
M: dbrownell@users.sourceforge.net
L: linux-usb-devel@lists.sourceforge.net
L: linux-usb@vger.kernel.org
S: Odd Fixes
USB ET61X[12]51 DRIVER
P: Luca Risolia
M: luca.risolia@studio.unibo.it
L: linux-usb-devel@lists.sourceforge.net
L: linux-usb@vger.kernel.org
L: video4linux-list@redhat.com
W: http://www.linux-projects.org
S: Maintained
......@@ -3853,41 +3850,33 @@ S: Maintained
USB GADGET/PERIPHERAL SUBSYSTEM
P: David Brownell
M: dbrownell@users.sourceforge.net
L: linux-usb-devel@lists.sourceforge.net
L: linux-usb@vger.kernel.org
W: http://www.linux-usb.org/gadget
S: Maintained
USB HID/HIDBP DRIVERS (USB KEYBOARDS, MICE, REMOTE CONTROLS, ...)
P: Jiri Kosina
M: jkosina@suse.cz
L: linux-usb-devel@lists.sourceforge.net
L: linux-usb@vger.kernel.org
T: git kernel.org:/pub/scm/linux/kernel/git/jikos/hid.git
S: Maintained
USB HUB DRIVER
P: Johannes Erdfelt
M: johannes@erdfelt.com
L: linux-usb-users@lists.sourceforge.net
L: linux-usb-devel@lists.sourceforge.net
S: Maintained
USB ISP116X DRIVER
P: Olav Kongas
M: ok@artecdesign.ee
L: linux-usb-devel@lists.sourceforge.net
L: linux-usb@vger.kernel.org
S: Maintained
USB KAWASAKI LSI DRIVER
P: Oliver Neukum
M: oliver@neukum.name
L: linux-usb-users@lists.sourceforge.net
L: linux-usb-devel@lists.sourceforge.net
L: linux-usb@vger.kernel.org
S: Maintained
USB MASS STORAGE DRIVER
P: Matthew Dharm
M: mdharm-usb@one-eyed-alien.net
L: linux-usb-users@lists.sourceforge.net
L: linux-usb@vger.kernel.org
L: usb-storage@lists.one-eyed-alien.net
S: Maintained
W: http://www.one-eyed-alien.net/~mdharm/linux-usb/
......@@ -3895,28 +3884,26 @@ W: http://www.one-eyed-alien.net/~mdharm/linux-usb/
USB OHCI DRIVER
P: David Brownell
M: dbrownell@users.sourceforge.net
L: linux-usb-users@lists.sourceforge.net
L: linux-usb-devel@lists.sourceforge.net
L: linux-usb@vger.kernel.org
S: Odd Fixes
USB OPTION-CARD DRIVER
P: Matthias Urlichs
M: smurf@smurf.noris.de
L: linux-usb-devel@lists.sourceforge.net
L: linux-usb@vger.kernel.org
S: Maintained
USB OV511 DRIVER
P: Mark McClelland
M: mmcclell@bigfoot.com
L: linux-usb-users@lists.sourceforge.net
L: linux-usb-devel@lists.sourceforge.net
L: linux-usb@vger.kernel.org
W: http://alpha.dyndns.org/ov511/
S: Maintained
USB PEGASUS DRIVER
P: Petko Manolov
M: petkan@users.sourceforge.net
L: linux-usb-devel@lists.sourceforge.net
L: linux-usb@vger.kernel.org
L: netdev@vger.kernel.org
W: http://pegasus2.sourceforge.net/
S: Maintained
......@@ -3924,14 +3911,13 @@ S: Maintained
USB PRINTER DRIVER (usblp)
P: Pete Zaitcev
M: zaitcev@redhat.com
L: linux-usb-users@lists.sourceforge.net
L: linux-usb-devel@lists.sourceforge.net
L: linux-usb@vger.kernel.org
S: Supported
USB RTL8150 DRIVER
P: Petko Manolov
M: petkan@users.sourceforge.net
L: linux-usb-devel@lists.sourceforge.net
L: linux-usb@vger.kernel.org
L: netdev@vger.kernel.org
W: http://pegasus2.sourceforge.net/
S: Maintained
......@@ -3939,8 +3925,7 @@ S: Maintained
USB SE401 DRIVER
P: Jeroen Vreeken
M: pe1rxq@amsat.org
L: linux-usb-users@lists.sourceforge.net
L: linux-usb-devel@lists.sourceforge.net
L: linux-usb@vger.kernel.org
W: http://www.chello.nl/~j.vreeken/se401/
S: Maintained
......@@ -3954,72 +3939,59 @@ USB SERIAL DIGI ACCELEPORT DRIVER
P: Peter Berger and Al Borchers
M: pberger@brimson.com
M: alborchers@steinerpoint.com
L: linux-usb-users@lists.sourceforge.net
L: linux-usb-devel@lists.sourceforge.net
L: linux-usb@vger.kernel.org
S: Maintained
USB SERIAL DRIVER
P: Greg Kroah-Hartman
M: gregkh@suse.de
L: linux-usb-users@lists.sourceforge.net
L: linux-usb-devel@lists.sourceforge.net
L: linux-usb@vger.kernel.org
S: Supported
USB SERIAL BELKIN F5U103 DRIVER
P: William Greathouse
M: wgreathouse@smva.com
L: linux-usb-users@lists.sourceforge.net
L: linux-usb-devel@lists.sourceforge.net
L: linux-usb@vger.kernel.org
S: Maintained
USB SERIAL CYPRESS M8 DRIVER
P: Lonnie Mendez
M: dignome@gmail.com
L: linux-usb-users@lists.sourceforge.net
L: linux-usb-devel@lists.sourceforge.net
L: linux-usb@vger.kernel.org
S: Maintained
W: http://geocities.com/i0xox0i
W: http://firstlight.net/cvs
USB SERIAL CYBERJACK PINPAD/E-COM DRIVER
L: linux-usb-users@lists.sourceforge.net
L: linux-usb-devel@lists.sourceforge.net
S: Maintained
USB AUERSWALD DRIVER
P: Wolfgang Muees
M: wolfgang@iksw-muees.de
L: linux-usb-users@lists.sourceforge.net
L: linux-usb-devel@lists.sourceforge.net
L: linux-usb@vger.kernel.org
S: Maintained
USB SERIAL EMPEG EMPEG-CAR MARK I/II DRIVER
P: Gary Brubaker
M: xavyer@ix.netcom.com
L: linux-usb-users@lists.sourceforge.net
L: linux-usb-devel@lists.sourceforge.net
L: linux-usb@vger.kernel.org
S: Maintained
USB SERIAL KEYSPAN DRIVER
P: Greg Kroah-Hartman
M: greg@kroah.com
L: linux-usb-users@lists.sourceforge.net
L: linux-usb-devel@lists.sourceforge.net
L: linux-usb@vger.kernel.org
W: http://www.kroah.com/linux/
S: Maintained
USB SERIAL WHITEHEAT DRIVER
P: Support Department
M: support@connecttech.com
L: linux-usb-users@lists.sourceforge.net
L: linux-usb-devel@lists.sourceforge.net
L: linux-usb@vger.kernel.org
W: http://www.connecttech.com
S: Supported
USB SN9C1xx DRIVER
P: Luca Risolia
M: luca.risolia@studio.unibo.it
L: linux-usb-devel@lists.sourceforge.net
L: linux-usb@vger.kernel.org
L: video4linux-list@redhat.com
W: http://www.linux-projects.org
S: Maintained
......@@ -4027,8 +3999,7 @@ S: Maintained
USB SUBSYSTEM
P: Greg Kroah-Hartman
M: gregkh@suse.de
L: linux-usb-users@lists.sourceforge.net
L: linux-usb-devel@lists.sourceforge.net
L: linux-usb@vger.kernel.org
W: http://www.linux-usb.org
T: quilt kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/
S: Supported
......@@ -4036,8 +4007,7 @@ S: Supported
USB UHCI DRIVER
P: Alan Stern
M: stern@rowland.harvard.edu
L: linux-usb-users@lists.sourceforge.net
L: linux-usb-devel@lists.sourceforge.net
L: linux-usb@vger.kernel.org
S: Maintained
USB "USBNET" DRIVER FRAMEWORK
......@@ -4050,7 +4020,7 @@ S: Maintained
USB W996[87]CF DRIVER
P: Luca Risolia
M: luca.risolia@studio.unibo.it
L: linux-usb-devel@lists.sourceforge.net
L: linux-usb@vger.kernel.org
L: video4linux-list@redhat.com
W: http://www.linux-projects.org
S: Maintained
......@@ -4058,7 +4028,7 @@ S: Maintained
USB ZC0301 DRIVER
P: Luca Risolia
M: luca.risolia@studio.unibo.it
L: linux-usb-devel@lists.sourceforge.net
L: linux-usb@vger.kernel.org
L: video4linux-list@redhat.com
W: http://www.linux-projects.org
S: Maintained
......@@ -4066,15 +4036,14 @@ S: Maintained
USB ZD1201 DRIVER
P: Jeroen Vreeken
M: pe1rxq@amsat.org
L: linux-usb-users@lists.sourceforge.net
L: linux-usb-devel@lists.sourceforge.net
L: linux-usb@vger.kernel.org
W: http://linux-lc100020.sourceforge.net
S: Maintained
USB ZR364XX DRIVER
P: Antoine Jacquet
M: royale@zerezo.com
L: linux-usb-devel@lists.sourceforge.net
L: linux-usb@vger.kernel.org
L: video4linux-list@redhat.com
W: http://royale.zerezo.com/zr364xx/
S: Maintained
......
......@@ -39,12 +39,12 @@ first subdirectory in the list below that it fits into.
image/ - This is for still image drivers, like scanners or
digital cameras.
input/ - This is for any driver that uses the input subsystem,
../input/ - This is for any driver that uses the input subsystem,
like keyboard, mice, touchscreens, tablets, etc.
media/ - This is for multimedia drivers, like video cameras,
../media/ - This is for multimedia drivers, like video cameras,
radios, and any other drivers that talk to the v4l
subsystem.
net/ - This is for network drivers.
../net/ - This is for network drivers.
serial/ - This is for USB to serial drivers.
storage/ - This is for USB mass-storage drivers.
class/ - This is for all USB device drivers that do not fit
......
......@@ -585,9 +585,6 @@ static int usb_uevent(struct device *dev, struct kobj_uevent_env *env)
{
struct usb_device *usb_dev;
if (!dev)
return -ENODEV;
/* driver is often null here; dev_dbg() would oops */
pr_debug ("usb %s: uevent\n", dev->bus_id);
......@@ -631,14 +628,6 @@ static int usb_uevent(struct device *dev, struct kobj_uevent_env *env)
usb_dev->descriptor.bDeviceProtocol))
return -ENOMEM;
if (add_uevent_var(env, "BUSNUM=%03d",
usb_dev->bus->busnum))
return -ENOMEM;
if (add_uevent_var(env, "DEVNUM=%03d",
usb_dev->devnum))
return -ENOMEM;
return 0;
}
......
......@@ -1311,8 +1311,8 @@ void usb_hcd_flush_endpoint(struct usb_device *udev,
hcd = bus_to_hcd(udev->bus);
/* No more submits can occur */
rescan:
spin_lock_irq(&hcd_urb_list_lock);
rescan:
list_for_each_entry (urb, &ep->urb_list, urb_list) {
int is_in;
......@@ -1345,6 +1345,7 @@ void usb_hcd_flush_endpoint(struct usb_device *udev,
usb_put_urb (urb);
/* list contents may have changed */
spin_lock(&hcd_urb_list_lock);
goto rescan;
}
spin_unlock_irq(&hcd_urb_list_lock);
......
......@@ -335,7 +335,7 @@ static void kick_khubd(struct usb_hub *hub)
to_usb_interface(hub->intfdev)->pm_usage_cnt = 1;
spin_lock_irqsave(&hub_event_lock, flags);
if (!hub->disconnected & list_empty(&hub->event_list)) {
if (!hub->disconnected && list_empty(&hub->event_list)) {
list_add_tail(&hub->event_list, &hub_event_list);
wake_up(&khubd_wait);
}
......
......@@ -1172,7 +1172,6 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
struct usb_host_interface *alt;
int ret;
int manual = 0;
int changed;
if (dev->state == USB_STATE_SUSPENDED)
return -EHOSTUNREACH;
......@@ -1212,8 +1211,7 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
*/
/* prevent submissions using previous endpoint settings */
changed = (iface->cur_altsetting != alt);
if (changed && device_is_registered(&iface->dev))
if (iface->cur_altsetting != alt && device_is_registered(&iface->dev))
usb_remove_sysfs_intf_files(iface);
usb_disable_interface(dev, iface);
......@@ -1250,7 +1248,7 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
* (Likewise, EP0 never "halts" on well designed devices.)
*/
usb_enable_interface(dev, iface);
if (changed && device_is_registered(&iface->dev))
if (device_is_registered(&iface->dev))
usb_create_sysfs_intf_files(iface);
return 0;
......@@ -1348,34 +1346,10 @@ static int usb_if_uevent(struct device *dev, struct kobj_uevent_env *env)
struct usb_interface *intf;
struct usb_host_interface *alt;
if (!dev)
return -ENODEV;
/* driver is often null here; dev_dbg() would oops */
pr_debug ("usb %s: uevent\n", dev->bus_id);
intf = to_usb_interface(dev);
usb_dev = interface_to_usbdev(intf);
alt = intf->cur_altsetting;
#ifdef CONFIG_USB_DEVICEFS
if (add_uevent_var(env, "DEVICE=/proc/bus/usb/%03d/%03d",
usb_dev->bus->busnum, usb_dev->devnum))
return -ENOMEM;
#endif
if (add_uevent_var(env, "PRODUCT=%x/%x/%x",
le16_to_cpu(usb_dev->descriptor.idVendor),
le16_to_cpu(usb_dev->descriptor.idProduct),
le16_to_cpu(usb_dev->descriptor.bcdDevice)))
return -ENOMEM;
if (add_uevent_var(env, "TYPE=%d/%d/%d",
usb_dev->descriptor.bDeviceClass,
usb_dev->descriptor.bDeviceSubClass,
usb_dev->descriptor.bDeviceProtocol))
return -ENOMEM;
if (add_uevent_var(env, "INTERFACE=%d/%d/%d",
alt->desc.bInterfaceClass,
alt->desc.bInterfaceSubClass,
......@@ -1641,12 +1615,6 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
intf->dev.bus_id, ret);
continue;
}
/* The driver's probe method can call usb_set_interface(),
* which would mean the interface's sysfs files are already
* created. Just in case, we'll remove them first.
*/
usb_remove_sysfs_intf_files(intf);
usb_create_sysfs_intf_files(intf);
}
......
......@@ -735,6 +735,8 @@ int usb_create_sysfs_intf_files(struct usb_interface *intf)
struct usb_host_interface *alt = intf->cur_altsetting;
int retval;
if (intf->sysfs_files_created)
return 0;
retval = sysfs_create_group(&dev->kobj, &intf_attr_grp);
if (retval)
return retval;
......@@ -746,6 +748,7 @@ int usb_create_sysfs_intf_files(struct usb_interface *intf)
if (intf->intf_assoc)
retval = sysfs_create_group(&dev->kobj, &intf_assoc_attr_grp);
usb_create_intf_ep_files(intf, udev);
intf->sysfs_files_created = 1;
return 0;
}
......@@ -753,8 +756,11 @@ void usb_remove_sysfs_intf_files(struct usb_interface *intf)
{
struct device *dev = &intf->dev;
if (!intf->sysfs_files_created)
return;
usb_remove_intf_ep_files(intf);
device_remove_file(dev, &dev_attr_interface);
sysfs_remove_group(&dev->kobj, &intf_attr_grp);
sysfs_remove_group(&intf->dev.kobj, &intf_assoc_attr_grp);
intf->sysfs_files_created = 0;
}
......@@ -192,9 +192,34 @@ static void usb_release_dev(struct device *dev)
kfree(udev);
}
#ifdef CONFIG_HOTPLUG
static int usb_dev_uevent(struct device *dev, struct kobj_uevent_env *env)
{
struct usb_device *usb_dev;
usb_dev = to_usb_device(dev);
if (add_uevent_var(env, "BUSNUM=%03d", usb_dev->bus->busnum))
return -ENOMEM;
if (add_uevent_var(env, "DEVNUM=%03d", usb_dev->devnum))
return -ENOMEM;
return 0;
}
#else
static int usb_dev_uevent(struct device *dev, struct kobj_uevent_env *env)
{
return -ENODEV;
}
#endif /* CONFIG_HOTPLUG */
struct device_type usb_device_type = {
.name = "usb_device",
.release = usb_release_dev,
.uevent = usb_dev_uevent,
};
#ifdef CONFIG_PM
......
......@@ -1241,14 +1241,14 @@ static void pullup_enable(struct omap_udc *udc)
udc->gadget.dev.parent->power.power_state = PMSG_ON;
udc->gadget.dev.power.power_state = PMSG_ON;
UDC_SYSCON1_REG |= UDC_PULLUP_EN;
if (!gadget_is_otg(udc->gadget) && !cpu_is_omap15xx())
if (!gadget_is_otg(&udc->gadget) && !cpu_is_omap15xx())
OTG_CTRL_REG |= OTG_BSESSVLD;
UDC_IRQ_EN_REG = UDC_DS_CHG_IE;
}
static void pullup_disable(struct omap_udc *udc)
{
if (!gadget_is_otg(udc->gadget) && !cpu_is_omap15xx())
if (!gadget_is_otg(&udc->gadget) && !cpu_is_omap15xx())
OTG_CTRL_REG &= ~OTG_BSESSVLD;
UDC_IRQ_EN_REG = UDC_DS_CHG_IE;
UDC_SYSCON1_REG &= ~UDC_PULLUP_EN;
......@@ -1386,7 +1386,7 @@ static void update_otg(struct omap_udc *udc)
{
u16 devstat;
if (!gadget_is_otg(udc->gadget))
if (!gadget_is_otg(&udc->gadget))
return;
if (OTG_CTRL_REG & OTG_ID)
......
......@@ -52,10 +52,10 @@
#include <asm/arch/irqs.h>
#include <asm/arch/hardware.h>
#include <asm/arch/regs-clock.h>
#include <asm/arch/regs-gpio.h>
#include <asm/arch/regs-udc.h>
#include <asm/arch/udc.h>
#include <asm/plat-s3c24xx/regs-udc.h>
#include <asm/plat-s3c24xx/udc.h>
#include <asm/mach-types.h>
......@@ -1511,7 +1511,11 @@ static irqreturn_t s3c2410_udc_vbus_irq(int irq, void *_dev)
unsigned int value;
dprintk(DEBUG_NORMAL, "%s()\n", __func__);
/* some cpus cannot read from an line configured to IRQ! */
s3c2410_gpio_cfgpin(udc_info->vbus_pin, S3C2410_GPIO_INPUT);
value = s3c2410_gpio_getpin(udc_info->vbus_pin);
s3c2410_gpio_cfgpin(udc_info->vbus_pin, S3C2410_GPIO_SFN2);
if (udc_info->vbus_pin_inverted)
value = !value;
......@@ -1873,7 +1877,7 @@ static int s3c2410_udc_probe(struct platform_device *pdev)
irq = s3c2410_gpio_getirq(udc_info->vbus_pin);
retval = request_irq(irq, s3c2410_udc_vbus_irq,
IRQF_DISABLED | IRQF_TRIGGER_RISING
| IRQF_TRIGGER_FALLING,
| IRQF_TRIGGER_FALLING | IRQF_SHARED,
gadget_name, udc);
if (retval != 0) {
......
......@@ -156,7 +156,7 @@ config USB_OHCI_HCD_PCI
config USB_OHCI_HCD_SSB
bool "OHCI support for Broadcom SSB OHCI core"
depends on USB_OHCI_HCD && (SSB = y || SSB = CONFIG_USB_OHCI_HCD) && EXPERIMENTAL
depends on USB_OHCI_HCD && (SSB = y || SSB = USB_OHCI_HCD) && EXPERIMENTAL
default n
---help---
Support for the Sonics Silicon Backplane (SSB) attached
......
......@@ -575,12 +575,15 @@ static int ehci_run (struct usb_hcd *hcd)
* from the companions to the EHCI controller. If any of the
* companions are in the middle of a port reset at the time, it
* could cause trouble. Write-locking ehci_cf_port_reset_rwsem
* guarantees that no resets are in progress.
* guarantees that no resets are in progress. After we set CF,
* a short delay lets the hardware catch up; new resets shouldn't
* be started before the port switching actions could complete.
*/
down_write(&ehci_cf_port_reset_rwsem);
hcd->state = HC_STATE_RUNNING;
ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag);
ehci_readl(ehci, &ehci->regs->command); /* unblock posted writes */
msleep(5);
up_write(&ehci_cf_port_reset_rwsem);
temp = HC_VERSION(ehci_readl(ehci, &ehci->caps->hc_capbase));
......
......@@ -819,7 +819,7 @@ static int mts_usb_probe(struct usb_interface *intf,
goto out_kfree2;
new_desc->host->hostdata[0] = (unsigned long)new_desc;
if (scsi_add_host(new_desc->host, NULL)) {
if (scsi_add_host(new_desc->host, &dev->dev)) {
err_retval = -EIO;
goto out_host_put;
}
......
......@@ -79,12 +79,22 @@ MODULE_DEVICE_TABLE(usb, device_table);
#define COMMAND_TIMEOUT (2*HZ) /* 60 second timeout for a command */
/*
* The locking scheme is a vanilla 3-lock:
* adu_device.buflock: A spinlock, covers what IRQs touch.
* adutux_mutex: A Static lock to cover open_count. It would also cover
* any globals, but we don't have them in 2.6.
* adu_device.mtx: A mutex to hold across sleepers like copy_from_user.
* It covers all of adu_device, except the open_count
* and what .buflock covers.
*/
/* Structure to hold all of our device specific stuff */
struct adu_device {
struct mutex mtx; /* locks this structure */
struct mutex mtx;
struct usb_device* udev; /* save off the usb device pointer */
struct usb_interface* interface;
unsigned char minor; /* the starting minor number for this device */
unsigned int minor; /* the starting minor number for this device */
char serial_number[8];
int open_count; /* number of times this port has been opened */
......@@ -107,8 +117,11 @@ struct adu_device {
char* interrupt_out_buffer;
struct usb_endpoint_descriptor* interrupt_out_endpoint;
struct urb* interrupt_out_urb;
int out_urb_finished;
};
static DEFINE_MUTEX(adutux_mutex);
static struct usb_driver adu_driver;
static void adu_debug_data(int level, const char *function, int size,
......@@ -132,27 +145,31 @@ static void adu_debug_data(int level, const char *function, int size,
*/
static void adu_abort_transfers(struct adu_device *dev)
{
dbg(2," %s : enter", __FUNCTION__);
unsigned long flags;
if (dev == NULL) {
dbg(1," %s : dev is null", __FUNCTION__);
goto exit;
}
dbg(2," %s : enter", __FUNCTION__);
if (dev->udev == NULL) {
dbg(1," %s : udev is null", __FUNCTION__);
goto exit;
}
dbg(2," %s : udev state %d", __FUNCTION__, dev->udev->state);
if (dev->udev->state == USB_STATE_NOTATTACHED) {
dbg(1," %s : udev is not attached", __FUNCTION__);
goto exit;
}
/* shutdown transfer */
usb_unlink_urb(dev->interrupt_in_urb);
usb_unlink_urb(dev->interrupt_out_urb);
/* XXX Anchor these instead */
spin_lock_irqsave(&dev->buflock, flags);
if (!dev->read_urb_finished) {
spin_unlock_irqrestore(&dev->buflock, flags);
usb_kill_urb(dev->interrupt_in_urb);
} else
spin_unlock_irqrestore(&dev->buflock, flags);
spin_lock_irqsave(&dev->buflock, flags);
if (!dev->out_urb_finished) {
spin_unlock_irqrestore(&dev->buflock, flags);
usb_kill_urb(dev->interrupt_out_urb);
} else
spin_unlock_irqrestore(&dev->buflock, flags);
exit:
dbg(2," %s : leave", __FUNCTION__);
......@@ -162,8 +179,6 @@ static void adu_delete(struct adu_device *dev)
{
dbg(2, "%s enter", __FUNCTION__);
adu_abort_transfers(dev);
/* free data structures */
usb_free_urb(dev->interrupt_in_urb);
usb_free_urb(dev->interrupt_out_urb);
......@@ -239,7 +254,10 @@ static void adu_interrupt_out_callback(struct urb *urb)
goto exit;
}
wake_up_interruptible(&dev->write_wait);
spin_lock(&dev->buflock);
dev->out_urb_finished = 1;
wake_up(&dev->write_wait);
spin_unlock(&dev->buflock);
exit:
adu_debug_data(5, __FUNCTION__, urb->actual_length,
......@@ -252,12 +270,17 @@ static int adu_open(struct inode *inode, struct file *file)
struct adu_device *dev = NULL;
struct usb_interface *interface;
int subminor;
int retval = 0;
int retval;
dbg(2,"%s : enter", __FUNCTION__);
subminor = iminor(inode);
if ((retval = mutex_lock_interruptible(&adutux_mutex))) {
dbg(2, "%s : mutex lock failed", __FUNCTION__);
goto exit_no_lock;
}
interface = usb_find_interface(&adu_driver, subminor);
if (!interface) {
err("%s - error, can't find device for minor %d",
......@@ -267,25 +290,23 @@ static int adu_open(struct inode *inode, struct file *file)
}
dev = usb_get_intfdata(interface);
if (!dev) {
if (!dev || !dev->udev) {
retval = -ENODEV;
goto exit_no_device;
}
/* lock this device */
if ((retval = mutex_lock_interruptible(&dev->mtx))) {
dbg(2, "%s : mutex lock failed", __FUNCTION__);
/* check that nobody else is using the device */
if (dev->open_count) {
retval = -EBUSY;
goto exit_no_device;
}
/* increment our usage count for the device */
++dev->open_count;
dbg(2,"%s : open count %d", __FUNCTION__, dev->open_count);
/* save device in the file's private structure */
file->private_data = dev;
if (dev->open_count == 1) {
/* initialize in direction */
dev->read_buffer_length = 0;
......@@ -297,24 +318,26 @@ static int adu_open(struct inode *inode, struct file *file)
le16_to_cpu(dev->interrupt_in_endpoint->wMaxPacketSize),
adu_interrupt_in_callback, dev,
dev->interrupt_in_endpoint->bInterval);
/* dev->interrupt_in_urb->transfer_flags |= URB_ASYNC_UNLINK; */
dev->read_urb_finished = 0;
retval = usb_submit_urb(dev->interrupt_in_urb, GFP_KERNEL);
if (retval)
--dev->open_count;
}
mutex_unlock(&dev->mtx);
if (usb_submit_urb(dev->interrupt_in_urb, GFP_KERNEL))
dev->read_urb_finished = 1;
/* we ignore failure */
/* end of fixup for first read */
/* initialize out direction */
dev->out_urb_finished = 1;
retval = 0;
exit_no_device:
mutex_unlock(&adutux_mutex);
exit_no_lock:
dbg(2,"%s : leave, return value %d ", __FUNCTION__, retval);
return retval;
}
static int adu_release_internal(struct adu_device *dev)
static void adu_release_internal(struct adu_device *dev)
{
int retval = 0;
dbg(2," %s : enter", __FUNCTION__);
/* decrement our usage count for the device */
......@@ -326,12 +349,11 @@ static int adu_release_internal(struct adu_device *dev)
}
dbg(2," %s : leave", __FUNCTION__);
return retval;
}
static int adu_release(struct inode *inode, struct file *file)
{
struct adu_device *dev = NULL;
struct adu_device *dev;
int retval = 0;
dbg(2," %s : enter", __FUNCTION__);
......@@ -343,15 +365,13 @@ static int adu_release(struct inode *inode, struct file *file)
}
dev = file->private_data;
if (dev == NULL) {
dbg(1," %s : object is NULL", __FUNCTION__);
retval = -ENODEV;
goto exit;
}
/* lock our device */
mutex_lock(&dev->mtx); /* not interruptible */
mutex_lock(&adutux_mutex); /* not interruptible */
if (dev->open_count <= 0) {
dbg(1," %s : device not opened", __FUNCTION__);
......@@ -359,19 +379,15 @@ static int adu_release(struct inode *inode, struct file *file)
goto exit;
}
adu_release_internal(dev);
if (dev->udev == NULL) {
/* the device was unplugged before the file was released */
mutex_unlock(&dev->mtx);
if (!dev->open_count) /* ... and we're the last user */
adu_delete(dev);
dev = NULL;
} else {
/* do the work */
retval = adu_release_internal(dev);
}
exit:
if (dev)
mutex_unlock(&dev->mtx);
mutex_unlock(&adutux_mutex);
dbg(2," %s : leave, return value %d", __FUNCTION__, retval);
return retval;
}
......@@ -393,12 +409,12 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count,
dev = file->private_data;
dbg(2," %s : dev=%p", __FUNCTION__, dev);
/* lock this object */
if (mutex_lock_interruptible(&dev->mtx))
return -ERESTARTSYS;
/* verify that the device wasn't unplugged */
if (dev->udev == NULL || dev->minor == 0) {
if (dev->udev == NULL) {
retval = -ENODEV;
err("No device or device unplugged %d", retval);
goto exit;
......@@ -452,7 +468,7 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count,
should_submit = 1;
} else {
/* even the primary was empty - we may need to do IO */
if (dev->interrupt_in_urb->status == -EINPROGRESS) {
if (!dev->read_urb_finished) {
/* somebody is doing IO */
spin_unlock_irqrestore(&dev->buflock, flags);
dbg(2," %s : submitted already", __FUNCTION__);
......@@ -460,6 +476,7 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count,
/* we must initiate input */
dbg(2," %s : initiate input", __FUNCTION__);
dev->read_urb_finished = 0;
spin_unlock_irqrestore(&dev->buflock, flags);
usb_fill_int_urb(dev->interrupt_in_urb,dev->udev,
usb_rcvintpipe(dev->udev,
......@@ -469,15 +486,12 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count,
adu_interrupt_in_callback,
dev,
dev->interrupt_in_endpoint->bInterval);
retval = usb_submit_urb(dev->interrupt_in_urb, GFP_ATOMIC);
if (!retval) {
spin_unlock_irqrestore(&dev->buflock, flags);
dbg(2," %s : submitted OK", __FUNCTION__);
} else {
retval = usb_submit_urb(dev->interrupt_in_urb, GFP_KERNEL);
if (retval) {
dev->read_urb_finished = 1;
if (retval == -ENOMEM) {
retval = bytes_read ? bytes_read : -ENOMEM;
}
spin_unlock_irqrestore(&dev->buflock, flags);
dbg(2," %s : submit failed", __FUNCTION__);
goto exit;
}
......@@ -486,10 +500,14 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count,
/* we wait for I/O to complete */
set_current_state(TASK_INTERRUPTIBLE);
add_wait_queue(&dev->read_wait, &wait);
if (!dev->read_urb_finished)
spin_lock_irqsave(&dev->buflock, flags);
if (!dev->read_urb_finished) {
spin_unlock_irqrestore(&dev->buflock, flags);
timeout = schedule_timeout(COMMAND_TIMEOUT);
else
} else {
spin_unlock_irqrestore(&dev->buflock, flags);
set_current_state(TASK_RUNNING);
}
remove_wait_queue(&dev->read_wait, &wait);
if (timeout <= 0) {
......@@ -509,7 +527,10 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count,
retval = bytes_read;
/* if the primary buffer is empty then use it */
if (should_submit && !dev->interrupt_in_urb->status==-EINPROGRESS) {
spin_lock_irqsave(&dev->buflock, flags);
if (should_submit && dev->read_urb_finished) {
dev->read_urb_finished = 0;
spin_unlock_irqrestore(&dev->buflock, flags);
usb_fill_int_urb(dev->interrupt_in_urb,dev->udev,
usb_rcvintpipe(dev->udev,
dev->interrupt_in_endpoint->bEndpointAddress),
......@@ -518,10 +539,11 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count,
adu_interrupt_in_callback,
dev,
dev->interrupt_in_endpoint->bInterval);
/* dev->interrupt_in_urb->transfer_flags |= URB_ASYNC_UNLINK; */
dev->read_urb_finished = 0;
usb_submit_urb(dev->interrupt_in_urb, GFP_KERNEL);
if (usb_submit_urb(dev->interrupt_in_urb, GFP_KERNEL) != 0)
dev->read_urb_finished = 1;
/* we ignore failure */
} else {
spin_unlock_irqrestore(&dev->buflock, flags);
}
exit:
......@@ -535,24 +557,24 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count,
static ssize_t adu_write(struct file *file, const __user char *buffer,
size_t count, loff_t *ppos)
{
DECLARE_WAITQUEUE(waita, current);
struct adu_device *dev;
size_t bytes_written = 0;
size_t bytes_to_write;
size_t buffer_size;
unsigned long flags;
int retval;
int timeout = 0;
dbg(2," %s : enter, count = %Zd", __FUNCTION__, count);
dev = file->private_data;
/* lock this object */
retval = mutex_lock_interruptible(&dev->mtx);
if (retval)
goto exit_nolock;
/* verify that the device wasn't unplugged */
if (dev->udev == NULL || dev->minor == 0) {
if (dev->udev == NULL) {
retval = -ENODEV;
err("No device or device unplugged %d", retval);
goto exit;
......@@ -564,42 +586,37 @@ static ssize_t adu_write(struct file *file, const __user char *buffer,
goto exit;
}
while (count > 0) {
if (dev->interrupt_out_urb->status == -EINPROGRESS) {
timeout = COMMAND_TIMEOUT;
add_wait_queue(&dev->write_wait, &waita);
set_current_state(TASK_INTERRUPTIBLE);
spin_lock_irqsave(&dev->buflock, flags);
if (!dev->out_urb_finished) {
spin_unlock_irqrestore(&dev->buflock, flags);
while (timeout > 0) {
mutex_unlock(&dev->mtx);
if (signal_pending(current)) {
dbg(1," %s : interrupted", __FUNCTION__);
set_current_state(TASK_RUNNING);
retval = -EINTR;
goto exit;
goto exit_onqueue;
}
mutex_unlock(&dev->mtx);
timeout = interruptible_sleep_on_timeout(&dev->write_wait, timeout);
if (schedule_timeout(COMMAND_TIMEOUT) == 0) {
dbg(1, "%s - command timed out.", __FUNCTION__);
retval = -ETIMEDOUT;
goto exit_onqueue;
}
remove_wait_queue(&dev->write_wait, &waita);
retval = mutex_lock_interruptible(&dev->mtx);
if (retval) {
retval = bytes_written ? bytes_written : retval;
goto exit_nolock;
}
if (timeout > 0) {
break;
}
dbg(1," %s : interrupted timeout: %d", __FUNCTION__, timeout);
}
dbg(1," %s : final timeout: %d", __FUNCTION__, timeout);
if (timeout == 0) {
dbg(1, "%s - command timed out.", __FUNCTION__);
retval = -ETIMEDOUT;
goto exit;
}
dbg(4," %s : in progress, count = %Zd", __FUNCTION__, count);
} else {
spin_unlock_irqrestore(&dev->buflock, flags);
set_current_state(TASK_RUNNING);
remove_wait_queue(&dev->write_wait, &waita);
dbg(4," %s : sending, count = %Zd", __FUNCTION__, count);
/* write the data into interrupt_out_buffer from userspace */
......@@ -622,11 +639,12 @@ static ssize_t adu_write(struct file *file, const __user char *buffer,
bytes_to_write,
adu_interrupt_out_callback,
dev,
dev->interrupt_in_endpoint->bInterval);
/* dev->interrupt_in_urb->transfer_flags |= URB_ASYNC_UNLINK; */
dev->interrupt_out_endpoint->bInterval);
dev->interrupt_out_urb->actual_length = bytes_to_write;
dev->out_urb_finished = 0;
retval = usb_submit_urb(dev->interrupt_out_urb, GFP_KERNEL);
if (retval < 0) {
dev->out_urb_finished = 1;
err("Couldn't submit interrupt_out_urb %d", retval);
goto exit;
}
......@@ -637,16 +655,17 @@ static ssize_t adu_write(struct file *file, const __user char *buffer,
bytes_written += bytes_to_write;
}
}
retval = bytes_written;
mutex_unlock(&dev->mtx);
return bytes_written;
exit:
/* unlock the device */
mutex_unlock(&dev->mtx);
exit_nolock:
dbg(2," %s : leave, return value %d", __FUNCTION__, retval);
return retval;
exit_onqueue:
remove_wait_queue(&dev->write_wait, &waita);
return retval;
}
......@@ -831,25 +850,22 @@ static void adu_disconnect(struct usb_interface *interface)
dbg(2," %s : enter", __FUNCTION__);
dev = usb_get_intfdata(interface);
usb_set_intfdata(interface, NULL);
mutex_lock(&dev->mtx); /* not interruptible */
dev->udev = NULL; /* poison */
minor = dev->minor;
/* give back our minor */
usb_deregister_dev(interface, &adu_class);
dev->minor = 0;
mutex_unlock(&dev->mtx);
mutex_lock(&dev->mtx); /* not interruptible */
mutex_lock(&adutux_mutex);
usb_set_intfdata(interface, NULL);
/* if the device is not opened, then we clean up right now */
dbg(2," %s : open count %d", __FUNCTION__, dev->open_count);
if (!dev->open_count) {
mutex_unlock(&dev->mtx);
if (!dev->open_count)
adu_delete(dev);
} else {
dev->udev = NULL;
mutex_unlock(&dev->mtx);
}
mutex_unlock(&adutux_mutex);
dev_info(&interface->dev, "ADU device adutux%d now disconnected\n",
(minor - ADU_MINOR_BASE));
......
......@@ -144,12 +144,14 @@ static void led_disconnect(struct usb_interface *interface)
struct usb_led *dev;
dev = usb_get_intfdata (interface);
usb_set_intfdata (interface, NULL);
device_remove_file(&interface->dev, &dev_attr_blue);
device_remove_file(&interface->dev, &dev_attr_red);
device_remove_file(&interface->dev, &dev_attr_green);
/* first remove the files, then set the pointer to NULL */
usb_set_intfdata (interface, NULL);
usb_put_dev(dev->udev);
kfree(dev);
......
......@@ -327,6 +327,7 @@ void usb_serial_generic_read_bulk_callback (struct urb *urb)
struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
unsigned char *data = urb->transfer_buffer;
int status = urb->status;
unsigned long flags;
dbg("%s - port %d", __FUNCTION__, port->number);
......@@ -339,11 +340,11 @@ void usb_serial_generic_read_bulk_callback (struct urb *urb)
usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
/* Throttle the device if requested by tty */
spin_lock(&port->lock);
spin_lock_irqsave(&port->lock, flags);
if (!(port->throttled = port->throttle_req))
/* Handle data and continue reading from device */
flush_and_resubmit_read_urb(port);
spin_unlock(&port->lock);
spin_unlock_irqrestore(&port->lock, flags);
}
EXPORT_SYMBOL_GPL(usb_serial_generic_read_bulk_callback);
......
......@@ -2711,7 +2711,7 @@ static int mos7840_startup(struct usb_serial *serial)
status = mos7840_set_reg_sync(serial->port[0], ZLP_REG5, Data);
if (status < 0) {
dbg("Writing ZLP_REG5 failed status-0x%x\n", status);
return -1;
goto error;
} else
dbg("ZLP_REG5 Writing success status%d\n", status);
......
......@@ -86,6 +86,7 @@ static struct usb_device_id id_table [] = {
{ USB_DEVICE(ALCOR_VENDOR_ID, ALCOR_PRODUCT_ID) },
{ USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_ID) },
{ USB_DEVICE(WS002IN_VENDOR_ID, WS002IN_PRODUCT_ID) },
{ USB_DEVICE(COREGA_VENDOR_ID, COREGA_PRODUCT_ID) },
{ } /* Terminating entry */
};
......
......@@ -104,3 +104,6 @@
#define WS002IN_VENDOR_ID 0x11f6
#define WS002IN_PRODUCT_ID 0x2001
/* Corega CG-USBRS232R Serial Adapter */
#define COREGA_VENDOR_ID 0x07aa
#define COREGA_PRODUCT_ID 0x002a
......@@ -136,6 +136,8 @@ static struct usb_device_id id_table_3port [] = {
{ USB_DEVICE(0x0f30, 0x1b1d) }, /* Sierra Wireless MC5720 */
{ USB_DEVICE(0x1199, 0x0218) }, /* Sierra Wireless MC5720 */
{ USB_DEVICE(0x1199, 0x0020) }, /* Sierra Wireless MC5725 */
{ USB_DEVICE(0x1199, 0x0220) }, /* Sierra Wireless MC5725 */
{ USB_DEVICE(0x1199, 0x0220) }, /* Sierra Wireless MC5725 */
{ USB_DEVICE(0x1199, 0x0019) }, /* Sierra Wireless AirCard 595 */
{ USB_DEVICE(0x1199, 0x0021) }, /* Sierra Wireless AirCard 597E */
{ USB_DEVICE(0x1199, 0x0120) }, /* Sierra Wireless USB Dongle 595U*/
......
......@@ -177,6 +177,10 @@ static int slave_configure(struct scsi_device *sdev)
* is an occasional series of retries that will all fail. */
sdev->retry_hwerror = 1;
/* USB disks should allow restart. Some drives spin down
* automatically, requiring a START-STOP UNIT command. */
sdev->allow_restart = 1;
} else {
/* Non-disk-type devices don't need to blacklist any pages
......
......@@ -342,7 +342,7 @@ UNUSUAL_DEV( 0x04b0, 0x040d, 0x0100, 0x0100,
US_FL_FIX_CAPACITY),
/* Reported by Graber and Mike Pagano <mpagano-kernel@mpagano.com> */
UNUSUAL_DEV( 0x04b0, 0x040f, 0x0200, 0x0200,
UNUSUAL_DEV( 0x04b0, 0x040f, 0x0100, 0x0200,
"NIKON",
"NIKON DSC D200",
US_SC_DEVICE, US_PR_DEVICE, NULL,
......@@ -731,6 +731,13 @@ UNUSUAL_DEV( 0x0584, 0x0008, 0x0102, 0x0102,
US_SC_SCSI, US_PR_ALAUDA, init_alauda, 0 ),
#endif
/* Reported by RTE <raszilki@yandex.ru> */
UNUSUAL_DEV( 0x058f, 0x6387, 0x0141, 0x0141,
"JetFlash",
"TS1GJF2A/120",
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_MAX_SECTORS_64 ),
/* Fabrizio Fellini <fello@libero.it> */
UNUSUAL_DEV( 0x0595, 0x4343, 0x0000, 0x2210,
"Fujifilm",
......
......@@ -157,6 +157,7 @@ struct usb_interface {
* bound to */
enum usb_interface_condition condition; /* state of binding */
unsigned is_active:1; /* the interface is not suspended */
unsigned sysfs_files_created:1; /* the sysfs attributes exist */
unsigned needs_remote_wakeup:1; /* driver requires remote wakeup */
struct device dev; /* interface specific device info */
......
......@@ -102,7 +102,8 @@ struct usbdevfs_urb {
int start_frame;
int number_of_packets;
int error_count;
unsigned int signr; /* signal to be sent on error, -1 if none should be sent */
unsigned int signr; /* signal to be sent on completion,
or 0 if none should be sent. */
void *usercontext;
struct usbdevfs_iso_packet_desc iso_frame_desc[0];
};
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment