Merge commit 'v2.6.26' into bkl-removal
This commit is contained in:
@@ -155,9 +155,6 @@ static int generic_probe(struct usb_device *udev)
|
||||
{
|
||||
int err, c;
|
||||
|
||||
/* put device-specific files into sysfs */
|
||||
usb_create_sysfs_dev_files(udev);
|
||||
|
||||
/* Choose and set the configuration. This registers the interfaces
|
||||
* with the driver core and lets interface drivers bind to them.
|
||||
*/
|
||||
@@ -189,8 +186,6 @@ static void generic_disconnect(struct usb_device *udev)
|
||||
* unconfigure the device */
|
||||
if (udev->actconfig)
|
||||
usb_set_configuration(udev, -1);
|
||||
|
||||
usb_remove_sysfs_dev_files(udev);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
@@ -818,12 +818,12 @@ static int usb_register_bus(struct usb_bus *bus)
|
||||
set_bit (busnum, busmap.busmap);
|
||||
bus->busnum = busnum;
|
||||
|
||||
bus->dev = device_create(usb_host_class, bus->controller, MKDEV(0, 0),
|
||||
"usb_host%d", busnum);
|
||||
bus->dev = device_create_drvdata(usb_host_class, bus->controller,
|
||||
MKDEV(0, 0), bus,
|
||||
"usb_host%d", busnum);
|
||||
result = PTR_ERR(bus->dev);
|
||||
if (IS_ERR(bus->dev))
|
||||
goto error_create_class_dev;
|
||||
dev_set_drvdata(bus->dev, bus);
|
||||
|
||||
/* Add it to the local list of buses */
|
||||
list_add (&bus->bus_list, &usb_bus_list);
|
||||
@@ -924,6 +924,15 @@ static int register_root_hub(struct usb_hcd *hcd)
|
||||
return retval;
|
||||
}
|
||||
|
||||
void usb_enable_root_hub_irq (struct usb_bus *bus)
|
||||
{
|
||||
struct usb_hcd *hcd;
|
||||
|
||||
hcd = container_of (bus, struct usb_hcd, self);
|
||||
if (hcd->driver->hub_irq_enable && hcd->state != HC_STATE_HALT)
|
||||
hcd->driver->hub_irq_enable (hcd);
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
@@ -1684,19 +1693,30 @@ EXPORT_SYMBOL_GPL(usb_bus_start_enum);
|
||||
irqreturn_t usb_hcd_irq (int irq, void *__hcd)
|
||||
{
|
||||
struct usb_hcd *hcd = __hcd;
|
||||
int start = hcd->state;
|
||||
unsigned long flags;
|
||||
irqreturn_t rc;
|
||||
|
||||
if (unlikely(start == HC_STATE_HALT ||
|
||||
!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)))
|
||||
return IRQ_NONE;
|
||||
if (hcd->driver->irq (hcd) == IRQ_NONE)
|
||||
return IRQ_NONE;
|
||||
/* IRQF_DISABLED doesn't work correctly with shared IRQs
|
||||
* when the first handler doesn't use it. So let's just
|
||||
* assume it's never used.
|
||||
*/
|
||||
local_irq_save(flags);
|
||||
|
||||
set_bit(HCD_FLAG_SAW_IRQ, &hcd->flags);
|
||||
if (unlikely(hcd->state == HC_STATE_HALT ||
|
||||
!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))) {
|
||||
rc = IRQ_NONE;
|
||||
} else if (hcd->driver->irq(hcd) == IRQ_NONE) {
|
||||
rc = IRQ_NONE;
|
||||
} else {
|
||||
set_bit(HCD_FLAG_SAW_IRQ, &hcd->flags);
|
||||
|
||||
if (unlikely(hcd->state == HC_STATE_HALT))
|
||||
usb_hc_died (hcd);
|
||||
return IRQ_HANDLED;
|
||||
if (unlikely(hcd->state == HC_STATE_HALT))
|
||||
usb_hc_died(hcd);
|
||||
rc = IRQ_HANDLED;
|
||||
}
|
||||
|
||||
local_irq_restore(flags);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
@@ -1860,6 +1880,13 @@ int usb_add_hcd(struct usb_hcd *hcd,
|
||||
|
||||
/* enable irqs just before we start the controller */
|
||||
if (hcd->driver->irq) {
|
||||
|
||||
/* IRQF_DISABLED doesn't work as advertised when used together
|
||||
* with IRQF_SHARED. As usb_hcd_irq() will always disable
|
||||
* interrupts we can remove it here.
|
||||
*/
|
||||
irqflags &= ~IRQF_DISABLED;
|
||||
|
||||
snprintf(hcd->irq_descr, sizeof(hcd->irq_descr), "%s:usb%d",
|
||||
hcd->driver->description, hcd->self.busnum);
|
||||
if ((retval = request_irq(irqnum, &usb_hcd_irq, irqflags,
|
||||
|
@@ -210,9 +210,13 @@ struct hc_driver {
|
||||
int (*bus_suspend)(struct usb_hcd *);
|
||||
int (*bus_resume)(struct usb_hcd *);
|
||||
int (*start_port_reset)(struct usb_hcd *, unsigned port_num);
|
||||
void (*hub_irq_enable)(struct usb_hcd *);
|
||||
/* Needed only if port-change IRQs are level-triggered */
|
||||
|
||||
/* force handover of high-speed port to full-speed companion */
|
||||
void (*relinquish_port)(struct usb_hcd *, int);
|
||||
/* has a port been handed over to a companion? */
|
||||
int (*port_handed_over)(struct usb_hcd *, int);
|
||||
};
|
||||
|
||||
extern int usb_hcd_link_urb_to_ep(struct usb_hcd *hcd, struct urb *urb);
|
||||
|
@@ -644,6 +644,48 @@ static void hub_stop(struct usb_hub *hub)
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
||||
/* Try to identify which devices need USB-PERSIST handling */
|
||||
static int persistent_device(struct usb_device *udev)
|
||||
{
|
||||
int i;
|
||||
int retval;
|
||||
struct usb_host_config *actconfig;
|
||||
|
||||
/* Explicitly not marked persistent? */
|
||||
if (!udev->persist_enabled)
|
||||
return 0;
|
||||
|
||||
/* No active config? */
|
||||
actconfig = udev->actconfig;
|
||||
if (!actconfig)
|
||||
return 0;
|
||||
|
||||
/* FIXME! We should check whether it's open here or not! */
|
||||
|
||||
/*
|
||||
* Check that all the interface drivers have a
|
||||
* 'reset_resume' entrypoint
|
||||
*/
|
||||
retval = 0;
|
||||
for (i = 0; i < actconfig->desc.bNumInterfaces; i++) {
|
||||
struct usb_interface *intf;
|
||||
struct usb_driver *driver;
|
||||
|
||||
intf = actconfig->interface[i];
|
||||
if (!intf->dev.driver)
|
||||
continue;
|
||||
driver = to_usb_driver(intf->dev.driver);
|
||||
if (!driver->reset_resume)
|
||||
return 0;
|
||||
/*
|
||||
* We have at least one driver, and that one
|
||||
* has a reset_resume method.
|
||||
*/
|
||||
retval = 1;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void hub_restart(struct usb_hub *hub, int type)
|
||||
{
|
||||
struct usb_device *hdev = hub->hdev;
|
||||
@@ -671,26 +713,19 @@ static void hub_restart(struct usb_hub *hub, int type)
|
||||
}
|
||||
|
||||
/* Was the power session lost while we were suspended? */
|
||||
switch (type) {
|
||||
case HUB_RESET_RESUME:
|
||||
portstatus = 0;
|
||||
portchange = USB_PORT_STAT_C_CONNECTION;
|
||||
break;
|
||||
status = hub_port_status(hub, port1, &portstatus, &portchange);
|
||||
|
||||
case HUB_RESET:
|
||||
case HUB_RESUME:
|
||||
status = hub_port_status(hub, port1,
|
||||
&portstatus, &portchange);
|
||||
break;
|
||||
}
|
||||
/* If the device is gone, khubd will handle it later */
|
||||
if (status == 0 && !(portstatus & USB_PORT_STAT_CONNECTION))
|
||||
continue;
|
||||
|
||||
/* For "USB_PERSIST"-enabled children we must
|
||||
* mark the child device for reset-resume and
|
||||
* turn off the various status changes to prevent
|
||||
* khubd from disconnecting it later.
|
||||
*/
|
||||
if (udev->persist_enabled && status == 0 &&
|
||||
!(portstatus & USB_PORT_STAT_ENABLE)) {
|
||||
if (status == 0 && !(portstatus & USB_PORT_STAT_ENABLE) &&
|
||||
persistent_device(udev)) {
|
||||
if (portchange & USB_PORT_STAT_C_ENABLE)
|
||||
clear_port_feature(hub->hdev, port1,
|
||||
USB_PORT_FEAT_C_ENABLE);
|
||||
@@ -1326,6 +1361,12 @@ void usb_disconnect(struct usb_device **pdev)
|
||||
|
||||
usb_unlock_device(udev);
|
||||
|
||||
/* Remove the device-specific files from sysfs. This must be
|
||||
* done with udev unlocked, because some of the attribute
|
||||
* routines try to acquire the device lock.
|
||||
*/
|
||||
usb_remove_sysfs_dev_files(udev);
|
||||
|
||||
/* Unregister the device. The device driver is responsible
|
||||
* for removing the device files from usbfs and sysfs and for
|
||||
* de-configuring the device.
|
||||
@@ -1541,6 +1582,9 @@ int usb_new_device(struct usb_device *udev)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* put device-specific files into sysfs */
|
||||
usb_create_sysfs_dev_files(udev);
|
||||
|
||||
/* Tell the world! */
|
||||
announce_device(udev);
|
||||
return err;
|
||||
@@ -2029,6 +2073,8 @@ int usb_port_resume(struct usb_device *udev)
|
||||
}
|
||||
|
||||
clear_bit(port1, hub->busy_bits);
|
||||
if (!hub->hdev->parent && !hub->busy_bits[0])
|
||||
usb_enable_root_hub_irq(hub->hdev->bus);
|
||||
|
||||
if (status == 0)
|
||||
status = finish_port_resume(udev);
|
||||
@@ -2744,7 +2790,11 @@ loop:
|
||||
if ((status == -ENOTCONN) || (status == -ENOTSUPP))
|
||||
break;
|
||||
}
|
||||
dev_err(hub_dev, "unable to enumerate USB device on port %d\n", port1);
|
||||
if (hub->hdev->parent ||
|
||||
!hcd->driver->port_handed_over ||
|
||||
!(hcd->driver->port_handed_over)(hcd, port1))
|
||||
dev_err(hub_dev, "unable to enumerate USB device on port %d\n",
|
||||
port1);
|
||||
|
||||
done:
|
||||
hub_port_disable(hub, port1, 1);
|
||||
@@ -2954,6 +3004,11 @@ static void hub_events(void)
|
||||
|
||||
hub->activating = 0;
|
||||
|
||||
/* If this is a root hub, tell the HCD it's okay to
|
||||
* re-enable port-change interrupts now. */
|
||||
if (!hdev->parent && !hub->busy_bits[0])
|
||||
usb_enable_root_hub_irq(hdev->bus);
|
||||
|
||||
loop_autopm:
|
||||
/* Allow autosuspend if we're not going to run again */
|
||||
if (list_empty(&hub->event_list))
|
||||
@@ -3179,6 +3234,8 @@ int usb_reset_device(struct usb_device *udev)
|
||||
break;
|
||||
}
|
||||
clear_bit(port1, parent_hub->busy_bits);
|
||||
if (!parent_hdev->parent && !parent_hub->busy_bits[0])
|
||||
usb_enable_root_hub_irq(parent_hdev->bus);
|
||||
|
||||
if (ret < 0)
|
||||
goto re_enumerate;
|
||||
|
@@ -47,6 +47,13 @@ static const struct usb_device_id usb_quirk_list[] = {
|
||||
/* Edirol SD-20 */
|
||||
{ USB_DEVICE(0x0582, 0x0027), .driver_info = USB_QUIRK_RESET_RESUME },
|
||||
|
||||
/* appletouch */
|
||||
{ USB_DEVICE(0x05ac, 0x021a), .driver_info = USB_QUIRK_RESET_RESUME },
|
||||
|
||||
/* Avision AV600U */
|
||||
{ USB_DEVICE(0x0638, 0x0a13), .driver_info =
|
||||
USB_QUIRK_STRING_FETCH_255 },
|
||||
|
||||
/* M-Systems Flash Disk Pioneers */
|
||||
{ USB_DEVICE(0x08ec, 0x1000), .driver_info = USB_QUIRK_RESET_RESUME },
|
||||
|
||||
|
@@ -588,35 +588,33 @@ read_descriptors(struct kobject *kobj, struct bin_attribute *attr,
|
||||
container_of(kobj, struct device, kobj));
|
||||
size_t nleft = count;
|
||||
size_t srclen, n;
|
||||
int cfgno;
|
||||
void *src;
|
||||
|
||||
usb_lock_device(udev);
|
||||
|
||||
/* The binary attribute begins with the device descriptor */
|
||||
srclen = sizeof(struct usb_device_descriptor);
|
||||
if (off < srclen) {
|
||||
n = min_t(size_t, nleft, srclen - off);
|
||||
memcpy(buf, off + (char *) &udev->descriptor, n);
|
||||
nleft -= n;
|
||||
buf += n;
|
||||
off = 0;
|
||||
} else {
|
||||
off -= srclen;
|
||||
}
|
||||
|
||||
/* Then follows the raw descriptor entry for the current
|
||||
* configuration (config plus subsidiary descriptors).
|
||||
/* The binary attribute begins with the device descriptor.
|
||||
* Following that are the raw descriptor entries for all the
|
||||
* configurations (config plus subsidiary descriptors).
|
||||
*/
|
||||
if (udev->actconfig) {
|
||||
int cfgno = udev->actconfig - udev->config;
|
||||
|
||||
srclen = __le16_to_cpu(udev->actconfig->desc.wTotalLength);
|
||||
for (cfgno = -1; cfgno < udev->descriptor.bNumConfigurations &&
|
||||
nleft > 0; ++cfgno) {
|
||||
if (cfgno < 0) {
|
||||
src = &udev->descriptor;
|
||||
srclen = sizeof(struct usb_device_descriptor);
|
||||
} else {
|
||||
src = udev->rawdescriptors[cfgno];
|
||||
srclen = __le16_to_cpu(udev->config[cfgno].desc.
|
||||
wTotalLength);
|
||||
}
|
||||
if (off < srclen) {
|
||||
n = min_t(size_t, nleft, srclen - off);
|
||||
memcpy(buf, off + udev->rawdescriptors[cfgno], n);
|
||||
n = min(nleft, srclen - (size_t) off);
|
||||
memcpy(buf, src + off, n);
|
||||
nleft -= n;
|
||||
buf += n;
|
||||
off = 0;
|
||||
} else {
|
||||
off -= srclen;
|
||||
}
|
||||
}
|
||||
usb_unlock_device(udev);
|
||||
return count - nleft;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user