Commit fbf4d7ff 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:
  Revert "USB: EHCI: fix performance regression"
  USB: fsl_usb2_udc: fix recursive lock
  USB: usb-serial: option: Don't match Huawei driver CD images
  USB: pl2303: another product ID
  USB: add another scanner quirk
  USB: Add support for ROKR W5 in unusual_devs.h
  USB: Fix M600i unusual_devs entry
  USB: usb-storage: unusual_devs update for Cypress ATACB
  USB: EHCI: fix performance regression
  USB: EHCI: fix bug in Iso scheduling
  USB: EHCI: fix remote-wakeup regression
  USB: EHCI: suppress unwanted error messages
  USB: EHCI: fix up root-hub TT mess
  USB: add all configs to the "descriptors" attribute
  USB: fix possible deadlock involving sysfs attributes
  USB: Firmware loader driver for USB Apple iSight camera
  USB: FTDI_SIO : Add support for Matrix Orbital PID Range
parents 4bd27972 bb7e6984
...@@ -155,9 +155,6 @@ static int generic_probe(struct usb_device *udev) ...@@ -155,9 +155,6 @@ static int generic_probe(struct usb_device *udev)
{ {
int err, c; int err, c;
/* put device-specific files into sysfs */
usb_create_sysfs_dev_files(udev);
/* Choose and set the configuration. This registers the interfaces /* Choose and set the configuration. This registers the interfaces
* with the driver core and lets interface drivers bind to them. * with the driver core and lets interface drivers bind to them.
*/ */
...@@ -189,8 +186,6 @@ static void generic_disconnect(struct usb_device *udev) ...@@ -189,8 +186,6 @@ static void generic_disconnect(struct usb_device *udev)
* unconfigure the device */ * unconfigure the device */
if (udev->actconfig) if (udev->actconfig)
usb_set_configuration(udev, -1); usb_set_configuration(udev, -1);
usb_remove_sysfs_dev_files(udev);
} }
#ifdef CONFIG_PM #ifdef CONFIG_PM
......
...@@ -213,6 +213,8 @@ struct hc_driver { ...@@ -213,6 +213,8 @@ struct hc_driver {
/* force handover of high-speed port to full-speed companion */ /* force handover of high-speed port to full-speed companion */
void (*relinquish_port)(struct usb_hcd *, int); 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); extern int usb_hcd_link_urb_to_ep(struct usb_hcd *hcd, struct urb *urb);
......
...@@ -1326,6 +1326,12 @@ void usb_disconnect(struct usb_device **pdev) ...@@ -1326,6 +1326,12 @@ void usb_disconnect(struct usb_device **pdev)
usb_unlock_device(udev); 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 /* Unregister the device. The device driver is responsible
* for removing the device files from usbfs and sysfs and for * for removing the device files from usbfs and sysfs and for
* de-configuring the device. * de-configuring the device.
...@@ -1541,6 +1547,9 @@ int usb_new_device(struct usb_device *udev) ...@@ -1541,6 +1547,9 @@ int usb_new_device(struct usb_device *udev)
goto fail; goto fail;
} }
/* put device-specific files into sysfs */
usb_create_sysfs_dev_files(udev);
/* Tell the world! */ /* Tell the world! */
announce_device(udev); announce_device(udev);
return err; return err;
...@@ -2744,7 +2753,11 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1, ...@@ -2744,7 +2753,11 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
if ((status == -ENOTCONN) || (status == -ENOTSUPP)) if ((status == -ENOTCONN) || (status == -ENOTSUPP))
break; 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: done:
hub_port_disable(hub, port1, 1); hub_port_disable(hub, port1, 1);
......
...@@ -47,6 +47,10 @@ static const struct usb_device_id usb_quirk_list[] = { ...@@ -47,6 +47,10 @@ static const struct usb_device_id usb_quirk_list[] = {
/* Edirol SD-20 */ /* Edirol SD-20 */
{ USB_DEVICE(0x0582, 0x0027), .driver_info = USB_QUIRK_RESET_RESUME }, { USB_DEVICE(0x0582, 0x0027), .driver_info = USB_QUIRK_RESET_RESUME },
/* Avision AV600U */
{ USB_DEVICE(0x0638, 0x0a13), .driver_info =
USB_QUIRK_STRING_FETCH_255 },
/* M-Systems Flash Disk Pioneers */ /* M-Systems Flash Disk Pioneers */
{ USB_DEVICE(0x08ec, 0x1000), .driver_info = USB_QUIRK_RESET_RESUME }, { USB_DEVICE(0x08ec, 0x1000), .driver_info = USB_QUIRK_RESET_RESUME },
......
...@@ -588,35 +588,33 @@ read_descriptors(struct kobject *kobj, struct bin_attribute *attr, ...@@ -588,35 +588,33 @@ read_descriptors(struct kobject *kobj, struct bin_attribute *attr,
container_of(kobj, struct device, kobj)); container_of(kobj, struct device, kobj));
size_t nleft = count; size_t nleft = count;
size_t srclen, n; size_t srclen, n;
int cfgno;
void *src;
usb_lock_device(udev); /* The binary attribute begins with the device descriptor.
* Following that are the raw descriptor entries for all the
/* The binary attribute begins with the device descriptor */ * configurations (config plus subsidiary descriptors).
*/
for (cfgno = -1; cfgno < udev->descriptor.bNumConfigurations &&
nleft > 0; ++cfgno) {
if (cfgno < 0) {
src = &udev->descriptor;
srclen = sizeof(struct usb_device_descriptor); srclen = sizeof(struct usb_device_descriptor);
} else {
src = udev->rawdescriptors[cfgno];
srclen = __le16_to_cpu(udev->config[cfgno].desc.
wTotalLength);
}
if (off < srclen) { if (off < srclen) {
n = min_t(size_t, nleft, srclen - off); n = min(nleft, srclen - (size_t) off);
memcpy(buf, off + (char *) &udev->descriptor, n); memcpy(buf, src + off, n);
nleft -= n; nleft -= n;
buf += n; buf += n;
off = 0; off = 0;
} else { } else {
off -= srclen; off -= srclen;
} }
/* Then follows the raw descriptor entry for the current
* configuration (config plus subsidiary descriptors).
*/
if (udev->actconfig) {
int cfgno = udev->actconfig - udev->config;
srclen = __le16_to_cpu(udev->actconfig->desc.wTotalLength);
if (off < srclen) {
n = min_t(size_t, nleft, srclen - off);
memcpy(buf, off + udev->rawdescriptors[cfgno], n);
nleft -= n;
}
} }
usb_unlock_device(udev);
return count - nleft; return count - nleft;
} }
......
...@@ -1627,7 +1627,9 @@ static int reset_queues(struct fsl_udc *udc) ...@@ -1627,7 +1627,9 @@ static int reset_queues(struct fsl_udc *udc)
udc_reset_ep_queue(udc, pipe); udc_reset_ep_queue(udc, pipe);
/* report disconnect; the driver is already quiesced */ /* report disconnect; the driver is already quiesced */
spin_unlock(&udc->lock);
udc->driver->disconnect(&udc->gadget); udc->driver->disconnect(&udc->gadget);
spin_lock(&udc->lock);
return 0; return 0;
} }
......
...@@ -223,6 +223,7 @@ static const struct hc_driver ehci_au1xxx_hc_driver = { ...@@ -223,6 +223,7 @@ static const struct hc_driver ehci_au1xxx_hc_driver = {
.bus_suspend = ehci_bus_suspend, .bus_suspend = ehci_bus_suspend,
.bus_resume = ehci_bus_resume, .bus_resume = ehci_bus_resume,
.relinquish_port = ehci_relinquish_port, .relinquish_port = ehci_relinquish_port,
.port_handed_over = ehci_port_handed_over,
}; };
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
......
...@@ -269,7 +269,7 @@ static int ehci_fsl_setup(struct usb_hcd *hcd) ...@@ -269,7 +269,7 @@ static int ehci_fsl_setup(struct usb_hcd *hcd)
if (retval) if (retval)
return retval; return retval;
ehci->is_tdi_rh_tt = 1; hcd->has_tt = 1;
ehci->sbrn = 0x20; ehci->sbrn = 0x20;
...@@ -295,10 +295,6 @@ static const struct hc_driver ehci_fsl_hc_driver = { ...@@ -295,10 +295,6 @@ static const struct hc_driver ehci_fsl_hc_driver = {
*/ */
.reset = ehci_fsl_setup, .reset = ehci_fsl_setup,
.start = ehci_run, .start = ehci_run,
#ifdef CONFIG_PM
.suspend = ehci_bus_suspend,
.resume = ehci_bus_resume,
#endif
.stop = ehci_stop, .stop = ehci_stop,
.shutdown = ehci_shutdown, .shutdown = ehci_shutdown,
...@@ -322,6 +318,7 @@ static const struct hc_driver ehci_fsl_hc_driver = { ...@@ -322,6 +318,7 @@ static const struct hc_driver ehci_fsl_hc_driver = {
.bus_suspend = ehci_bus_suspend, .bus_suspend = ehci_bus_suspend,
.bus_resume = ehci_bus_resume, .bus_resume = ehci_bus_resume,
.relinquish_port = ehci_relinquish_port, .relinquish_port = ehci_relinquish_port,
.port_handed_over = ehci_port_handed_over,
}; };
static int ehci_fsl_drv_probe(struct platform_device *pdev) static int ehci_fsl_drv_probe(struct platform_device *pdev)
......
...@@ -609,7 +609,7 @@ static int ehci_hub_control ( ...@@ -609,7 +609,7 @@ static int ehci_hub_control (
} }
break; break;
case USB_PORT_FEAT_C_SUSPEND: case USB_PORT_FEAT_C_SUSPEND:
/* we auto-clear this feature */ clear_bit(wIndex, &ehci->port_c_suspend);
break; break;
case USB_PORT_FEAT_POWER: case USB_PORT_FEAT_POWER:
if (HCS_PPC (ehci->hcs_params)) if (HCS_PPC (ehci->hcs_params))
...@@ -688,7 +688,7 @@ static int ehci_hub_control ( ...@@ -688,7 +688,7 @@ static int ehci_hub_control (
/* resume completed? */ /* resume completed? */
else if (time_after_eq(jiffies, else if (time_after_eq(jiffies,
ehci->reset_done[wIndex])) { ehci->reset_done[wIndex])) {
status |= 1 << USB_PORT_FEAT_C_SUSPEND; set_bit(wIndex, &ehci->port_c_suspend);
ehci->reset_done[wIndex] = 0; ehci->reset_done[wIndex] = 0;
/* stop resume signaling */ /* stop resume signaling */
...@@ -765,6 +765,8 @@ static int ehci_hub_control ( ...@@ -765,6 +765,8 @@ static int ehci_hub_control (
status |= 1 << USB_PORT_FEAT_RESET; status |= 1 << USB_PORT_FEAT_RESET;
if (temp & PORT_POWER) if (temp & PORT_POWER)
status |= 1 << USB_PORT_FEAT_POWER; status |= 1 << USB_PORT_FEAT_POWER;
if (test_bit(wIndex, &ehci->port_c_suspend))
status |= 1 << USB_PORT_FEAT_C_SUSPEND;
#ifndef VERBOSE_DEBUG #ifndef VERBOSE_DEBUG
if (status & ~0xffff) /* only if wPortChange is interesting */ if (status & ~0xffff) /* only if wPortChange is interesting */
...@@ -875,3 +877,13 @@ static void ehci_relinquish_port(struct usb_hcd *hcd, int portnum) ...@@ -875,3 +877,13 @@ static void ehci_relinquish_port(struct usb_hcd *hcd, int portnum)
set_owner(ehci, --portnum, PORT_OWNER); set_owner(ehci, --portnum, PORT_OWNER);
} }
static int ehci_port_handed_over(struct usb_hcd *hcd, int portnum)
{
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
u32 __iomem *reg;
if (ehci_is_TDI(ehci))
return 0;
reg = &ehci->regs->port_status[portnum - 1];
return ehci_readl(ehci, reg) & PORT_OWNER;
}
...@@ -26,7 +26,7 @@ static int ixp4xx_ehci_init(struct usb_hcd *hcd) ...@@ -26,7 +26,7 @@ static int ixp4xx_ehci_init(struct usb_hcd *hcd)
+ HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase)); + HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase));
ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
ehci->is_tdi_rh_tt = 1; hcd->has_tt = 1;
ehci_reset(ehci); ehci_reset(ehci);
retval = ehci_init(hcd); retval = ehci_init(hcd);
...@@ -58,6 +58,8 @@ static const struct hc_driver ixp4xx_ehci_hc_driver = { ...@@ -58,6 +58,8 @@ static const struct hc_driver ixp4xx_ehci_hc_driver = {
.bus_suspend = ehci_bus_suspend, .bus_suspend = ehci_bus_suspend,
.bus_resume = ehci_bus_resume, .bus_resume = ehci_bus_resume,
#endif #endif
.relinquish_port = ehci_relinquish_port,
.port_handed_over = ehci_port_handed_over,
}; };
static int ixp4xx_ehci_probe(struct platform_device *pdev) static int ixp4xx_ehci_probe(struct platform_device *pdev)
......
...@@ -139,10 +139,6 @@ static const struct hc_driver ehci_orion_hc_driver = { ...@@ -139,10 +139,6 @@ static const struct hc_driver ehci_orion_hc_driver = {
*/ */
.reset = ehci_orion_setup, .reset = ehci_orion_setup,
.start = ehci_run, .start = ehci_run,
#ifdef CONFIG_PM
.suspend = ehci_bus_suspend,
.resume = ehci_bus_resume,
#endif
.stop = ehci_stop, .stop = ehci_stop,
.shutdown = ehci_shutdown, .shutdown = ehci_shutdown,
...@@ -165,6 +161,8 @@ static const struct hc_driver ehci_orion_hc_driver = { ...@@ -165,6 +161,8 @@ static const struct hc_driver ehci_orion_hc_driver = {
.hub_control = ehci_hub_control, .hub_control = ehci_hub_control,
.bus_suspend = ehci_bus_suspend, .bus_suspend = ehci_bus_suspend,
.bus_resume = ehci_bus_resume, .bus_resume = ehci_bus_resume,
.relinquish_port = ehci_relinquish_port,
.port_handed_over = ehci_port_handed_over,
}; };
static void __init static void __init
...@@ -250,7 +248,7 @@ static int __init ehci_orion_drv_probe(struct platform_device *pdev) ...@@ -250,7 +248,7 @@ static int __init ehci_orion_drv_probe(struct platform_device *pdev)
ehci->regs = hcd->regs + 0x100 + ehci->regs = hcd->regs + 0x100 +
HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase)); HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase));
ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
ehci->is_tdi_rh_tt = 1; hcd->has_tt = 1;
ehci->sbrn = 0x20; ehci->sbrn = 0x20;
/* /*
......
...@@ -129,7 +129,6 @@ static int ehci_pci_setup(struct usb_hcd *hcd) ...@@ -129,7 +129,6 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
switch (pdev->vendor) { switch (pdev->vendor) {
case PCI_VENDOR_ID_TDI: case PCI_VENDOR_ID_TDI:
if (pdev->device == PCI_DEVICE_ID_TDI_EHCI) { if (pdev->device == PCI_DEVICE_ID_TDI_EHCI) {
ehci->is_tdi_rh_tt = 1;
hcd->has_tt = 1; hcd->has_tt = 1;
tdi_reset(ehci); tdi_reset(ehci);
} }
...@@ -380,6 +379,7 @@ static const struct hc_driver ehci_pci_hc_driver = { ...@@ -380,6 +379,7 @@ static const struct hc_driver ehci_pci_hc_driver = {
.bus_suspend = ehci_bus_suspend, .bus_suspend = ehci_bus_suspend,
.bus_resume = ehci_bus_resume, .bus_resume = ehci_bus_resume,
.relinquish_port = ehci_relinquish_port, .relinquish_port = ehci_relinquish_port,
.port_handed_over = ehci_port_handed_over,
}; };
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
......
...@@ -76,6 +76,8 @@ static const struct hc_driver ehci_ppc_of_hc_driver = { ...@@ -76,6 +76,8 @@ static const struct hc_driver ehci_ppc_of_hc_driver = {
.bus_suspend = ehci_bus_suspend, .bus_suspend = ehci_bus_suspend,
.bus_resume = ehci_bus_resume, .bus_resume = ehci_bus_resume,
#endif #endif
.relinquish_port = ehci_relinquish_port,
.port_handed_over = ehci_port_handed_over,
}; };
......
...@@ -163,6 +163,7 @@ static const struct hc_driver ehci_ppc_soc_hc_driver = { ...@@ -163,6 +163,7 @@ static const struct hc_driver ehci_ppc_soc_hc_driver = {
.bus_suspend = ehci_bus_suspend, .bus_suspend = ehci_bus_suspend,
.bus_resume = ehci_bus_resume, .bus_resume = ehci_bus_resume,
.relinquish_port = ehci_relinquish_port, .relinquish_port = ehci_relinquish_port,
.port_handed_over = ehci_port_handed_over,
}; };
static int ehci_hcd_ppc_soc_drv_probe(struct platform_device *pdev) static int ehci_hcd_ppc_soc_drv_probe(struct platform_device *pdev)
......
...@@ -73,6 +73,7 @@ static const struct hc_driver ps3_ehci_hc_driver = { ...@@ -73,6 +73,7 @@ static const struct hc_driver ps3_ehci_hc_driver = {
.bus_resume = ehci_bus_resume, .bus_resume = ehci_bus_resume,
#endif #endif
.relinquish_port = ehci_relinquish_port, .relinquish_port = ehci_relinquish_port,
.port_handed_over = ehci_port_handed_over,
}; };
static int ps3_ehci_probe(struct ps3_system_bus_device *dev) static int ps3_ehci_probe(struct ps3_system_bus_device *dev)
......
...@@ -1349,19 +1349,28 @@ iso_stream_schedule ( ...@@ -1349,19 +1349,28 @@ iso_stream_schedule (
/* when's the last uframe this urb could start? */ /* when's the last uframe this urb could start? */
max = now + mod; max = now + mod;
/* typical case: reuse current schedule. stream is still active, /* Typical case: reuse current schedule, stream is still active.
* and no gaps from host falling behind (irq delays etc) * Hopefully there are no gaps from the host falling behind
* (irq delays etc), but if there are we'll take the next
* slot in the schedule, implicitly assuming URB_ISO_ASAP.
*/ */
if (likely (!list_empty (&stream->td_list))) { if (likely (!list_empty (&stream->td_list))) {
start = stream->next_uframe; start = stream->next_uframe;
if (start < now) if (start < now)
start += mod; start += mod;
if (likely ((start + sched->span) < max))
goto ready; /* Fell behind (by up to twice the slop amount)? */
/* else fell behind; someday, try to reschedule */ if (start >= max - 2 * 8 * SCHEDULE_SLOP)
status = -EL2NSYNC; start += stream->interval * DIV_ROUND_UP(
max - start, stream->interval) - mod;
/* Tried to schedule too far into the future? */
if (unlikely((start + sched->span) >= max)) {
status = -EFBIG;
goto fail; goto fail;
} }
goto ready;
}
/* need to schedule; when's the next (u)frame we could start? /* need to schedule; when's the next (u)frame we could start?
* this is bigger than ehci->i_thresh allows; scheduling itself * this is bigger than ehci->i_thresh allows; scheduling itself
...@@ -1613,6 +1622,9 @@ itd_complete ( ...@@ -1613,6 +1622,9 @@ itd_complete (
} else if (likely ((t & EHCI_ISOC_ACTIVE) == 0)) { } else if (likely ((t & EHCI_ISOC_ACTIVE) == 0)) {
desc->status = 0; desc->status = 0;
desc->actual_length = EHCI_ITD_LENGTH (t); desc->actual_length = EHCI_ITD_LENGTH (t);
} else {
/* URB was too late */
desc->status = -EXDEV;
} }
} }
...@@ -2095,7 +2107,7 @@ static int sitd_submit (struct ehci_hcd *ehci, struct urb *urb, ...@@ -2095,7 +2107,7 @@ static int sitd_submit (struct ehci_hcd *ehci, struct urb *urb,
static void static void
scan_periodic (struct ehci_hcd *ehci) scan_periodic (struct ehci_hcd *ehci)
{ {
unsigned frame, clock, now_uframe, mod; unsigned now_uframe, frame, clock, clock_frame, mod;
unsigned modified; unsigned modified;
mod = ehci->periodic_size << 3; mod = ehci->periodic_size << 3;
...@@ -2111,6 +2123,7 @@ scan_periodic (struct ehci_hcd *ehci) ...@@ -2111,6 +2123,7 @@ scan_periodic (struct ehci_hcd *ehci)
else else
clock = now_uframe + mod - 1; clock = now_uframe + mod - 1;
clock %= mod; clock %= mod;
clock_frame = clock >> 3;
for (;;) { for (;;) {
union ehci_shadow q, *q_p; union ehci_shadow q, *q_p;
...@@ -2157,12 +2170,17 @@ scan_periodic (struct ehci_hcd *ehci) ...@@ -2157,12 +2170,17 @@ scan_periodic (struct ehci_hcd *ehci)
case Q_TYPE_ITD: case Q_TYPE_ITD:
/* If this ITD is still active, leave it for /* If this ITD is still active, leave it for
* later processing ... check the next entry. * later processing ... check the next entry.
* No need to check for activity unless the
* frame is current.
*/ */
rmb (); if (frame == clock_frame && live) {
for (uf = 0; uf < 8 && live; uf++) { rmb();
if (0 == (q.itd->hw_transaction [uf] for (uf = 0; uf < 8; uf++) {
& ITD_ACTIVE(ehci))) if (q.itd->hw_transaction[uf] &
continue; ITD_ACTIVE(ehci))
break;
}
if (uf < 8) {
incomplete = true; incomplete = true;
q_p = &q.itd->itd_next; q_p = &q.itd->itd_next;
hw_p = &q.itd->hw_next; hw_p = &q.itd->hw_next;
...@@ -2171,8 +2189,7 @@ scan_periodic (struct ehci_hcd *ehci) ...@@ -2171,8 +2189,7 @@ scan_periodic (struct ehci_hcd *ehci)
q = *q_p; q = *q_p;
break; break;
} }
if (uf < 8 && live) }
break;
/* Take finished ITDs out of the schedule /* Take finished ITDs out of the schedule
* and process them: recycle, maybe report * and process them: recycle, maybe report
...@@ -2189,9 +2206,12 @@ scan_periodic (struct ehci_hcd *ehci) ...@@ -2189,9 +2206,12 @@ scan_periodic (struct ehci_hcd *ehci)
case Q_TYPE_SITD: case Q_TYPE_SITD:
/* If this SITD is still active, leave it for /* If this SITD is still active, leave it for
* later processing ... check the next entry. * later processing ... check the next entry.
* No need to check for activity unless the
* frame is current.
*/ */
if ((q.sitd->hw_results & SITD_ACTIVE(ehci)) if (frame == clock_frame && live &&
&& live) { (q.sitd->hw_results &
SITD_ACTIVE(ehci))) {
incomplete = true; incomplete = true;
q_p = &q.sitd->sitd_next; q_p = &q.sitd->sitd_next;
hw_p = &q.sitd->hw_next; hw_p = &q.sitd->hw_next;
...@@ -2260,6 +2280,7 @@ scan_periodic (struct ehci_hcd *ehci) ...@@ -2260,6 +2280,7 @@ scan_periodic (struct ehci_hcd *ehci)
/* rescan the rest of this frame, then ... */ /* rescan the rest of this frame, then ... */
clock = now; clock = now;
clock_frame = clock >> 3;
} else { } else {
now_uframe++; now_uframe++;
now_uframe %= mod; now_uframe %= mod;
......
...@@ -97,6 +97,8 @@ struct ehci_hcd { /* one per controller */ ...@@ -97,6 +97,8 @@ struct ehci_hcd { /* one per controller */
dedicated to the companion controller */ dedicated to the companion controller */
unsigned long owned_ports; /* which ports are unsigned long owned_ports; /* which ports are
owned by the companion during a bus suspend */ owned by the companion during a bus suspend */
unsigned long port_c_suspend; /* which ports have
the change-suspend feature turned on */
/* per-HC memory pools (could be per-bus, but ...) */ /* per-HC memory pools (could be per-bus, but ...) */
struct dma_pool *qh_pool; /* qh per active urb */ struct dma_pool *qh_pool; /* qh per active urb */
...@@ -112,7 +114,6 @@ struct ehci_hcd { /* one per controller */ ...@@ -112,7 +114,6 @@ struct ehci_hcd { /* one per controller */
u32 command; u32 command;
/* SILICON QUIRKS */ /* SILICON QUIRKS */
unsigned is_tdi_rh_tt:1; /* TDI roothub with TT */
unsigned no_selective_suspend:1; unsigned no_selective_suspend:1;
unsigned has_fsl_port_bug:1; /* FreeScale */ unsigned has_fsl_port_bug:1; /* FreeScale */
unsigned big_endian_mmio:1; unsigned big_endian_mmio:1;
...@@ -678,7 +679,7 @@ struct ehci_fstn { ...@@ -678,7 +679,7 @@ struct ehci_fstn {
* needed (mostly in root hub code). * needed (mostly in root hub code).
*/ */
#define ehci_is_TDI(e) ((e)->is_tdi_rh_tt) #define ehci_is_TDI(e) (ehci_to_hcd(e)->has_tt)
/* Returns the speed of a device attached to a port on the root hub. */ /* Returns the speed of a device attached to a port on the root hub. */
static inline unsigned int static inline unsigned int
......
...@@ -269,3 +269,14 @@ config USB_TEST ...@@ -269,3 +269,14 @@ config USB_TEST
See <http://www.linux-usb.org/usbtest/> for more information, See <http://www.linux-usb.org/usbtest/> for more information,
including sample test device firmware and "how to use it". including sample test device firmware and "how to use it".
config USB_ISIGHTFW
tristate "iSight firmware loading support"
depends on USB
help
This driver loads firmware for USB Apple iSight cameras, allowing
them to be driven by the USB video class driver available at
http://linux-uvc.berlios.de
The firmware for this driver must be extracted from the MacOS
driver beforehand. Tools for doing so are available at
http://bersace03.free.fr
...@@ -14,6 +14,7 @@ obj-$(CONFIG_USB_EMI62) += emi62.o ...@@ -14,6 +14,7 @@ obj-$(CONFIG_USB_EMI62) += emi62.o
obj-$(CONFIG_USB_FTDI_ELAN) += ftdi-elan.o obj-$(CONFIG_USB_FTDI_ELAN) += ftdi-elan.o
obj-$(CONFIG_USB_IDMOUSE) += idmouse.o obj-$(CONFIG_USB_IDMOUSE) += idmouse.o
obj-$(CONFIG_USB_IOWARRIOR) += iowarrior.o obj-$(CONFIG_USB_IOWARRIOR) += iowarrior.o
obj-$(CONFIG_USB_ISIGHTFW) += isight_firmware.o
obj-$(CONFIG_USB_LCD) += usblcd.o obj-$(CONFIG_USB_LCD) += usblcd.o
obj-$(CONFIG_USB_LD) += ldusb.o obj-$(CONFIG_USB_LD) += ldusb.o
obj-$(CONFIG_USB_LED) += usbled.o obj-$(CONFIG_USB_LED) += usbled.o
......
/*
* Driver for loading USB isight firmware
*
* Copyright (C) 2008 Matthew Garrett <mjg@redhat.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, version 2.
*
* The USB isight cameras in recent Apples are roughly compatible with the USB
* video class specification, and can be driven by uvcvideo. However, they
* need firmware to be loaded beforehand. After firmware loading, the device
* detaches from the USB bus and reattaches with a new device ID. It can then
* be claimed by the uvc driver.
*
* The firmware is non-free and must be extracted by the user. Tools to do this
* are available at http://bersace03.free.fr/ift/
*
* The isight firmware loading was reverse engineered by Johannes Berg
* <johannes@sipsolutions.de>, and this driver is based on code by Ronald
* Bultje <rbultje@ronald.bitfreak.net>
*/
#include <linux/usb.h>
#include <linux/firmware.h>
#include <linux/errno.h>
#include <linux/module.h>
static struct usb_device_id id_table[] = {
{USB_DEVICE(0x05ac, 0x8300)},
{},
};
MODULE_DEVICE_TABLE(usb, id_table);
static int isight_firmware_load(struct usb_interface *intf,
const struct usb_device_id *id)
{
struct usb_device *dev = interface_to_usbdev(intf);
int llen, len, req, ret = 0;
const struct firmware *firmware;
unsigned char *buf;
unsigned char data[4];
char *ptr;
if (request_firmware(&firmware, "isight.fw", &dev->dev) != 0) {
printk(KERN_ERR "Unable to load isight firmware\n");
return -ENODEV;
}
ptr = firmware->data;
if (usb_control_msg
(dev, usb_sndctrlpipe(dev, 0), 0xa0, 0x40, 0xe600, 0, "\1", 1,
300) != 1) {
printk(KERN_ERR
"Failed to initialise isight firmware loader\n");
ret = -ENODEV;
goto out;
}
while (1) {
memcpy(data, ptr, 4);
len = (data[0] << 8 | data[1]);
req = (data[2] << 8 | data[3]);
ptr += 4;
if (len == 0x8001)
break; /* success */
else if (len == 0)
continue;
for (; len > 0; req += 50) {
llen = len > 50 ? 50 : len;
len -= llen;
buf = kmalloc(llen, GFP_KERNEL);
memcpy(buf, ptr, llen);
ptr += llen;
if (usb_control_msg
(dev, usb_sndctrlpipe(dev, 0), 0xa0, 0x40, req, 0,
buf, llen, 300) != llen) {
printk(KERN_ERR
"Failed to load isight firmware\n");
kfree(buf);
ret = -ENODEV;
goto out;
}
kfree(buf);
}
}
if (usb_control_msg
(dev, usb_sndctrlpipe(dev, 0), 0xa0, 0x40, 0xe600, 0, "\0", 1,
300) != 1) {
printk(KERN_ERR "isight firmware loading completion failed\n");
ret = -ENODEV;
}
out:
release_firmware(firmware);
return ret;
}
static void isight_firmware_disconnect(struct usb_interface *intf)
{
}
static struct usb_driver isight_firmware_driver = {
.name = "isight_firmware",
.probe = isight_firmware_load,
.disconnect = isight_firmware_disconnect,
.id_table = id_table,
};
static int __init isight_firmware_init(void)
{
return usb_register(&isight_firmware_driver);
}
static void __exit isight_firmware_exit(void)
{
usb_deregister(&isight_firmware_driver);
}
module_init(isight_firmware_init);
module_exit(isight_firmware_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Matthew Garrett <mjg@redhat.com>");
This diff is collapsed.
This diff is collapsed.
...@@ -236,25 +236,25 @@ static struct usb_device_id option_ids[] = { ...@@ -236,25 +236,25 @@ static struct usb_device_id option_ids[] = {
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_NETWORK_EX) }, { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_NETWORK_EX) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_KOI_MODEM) }, { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_KOI_MODEM) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_KOI_NETWORK) }, { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_KOI_NETWORK) },
{ USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600) }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220BIS, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220BIS, 0xff, 0xff, 0xff) },
{ USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1401) }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1401, 0xff, 0xff, 0xff) },
{ USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1403) }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1403, 0xff, 0xff, 0xff) },
{ USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1405) }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1405, 0xff, 0xff, 0xff) },
{ USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1406) }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1406, 0xff, 0xff, 0xff) },
{ USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1408) }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1408, 0xff, 0xff, 0xff) },
{ USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1409) }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1409, 0xff, 0xff, 0xff) },
{ USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1410) }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1410, 0xff, 0xff, 0xff) },
{ USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1411) }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1411, 0xff, 0xff, 0xff) },
{ USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1412) }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1412, 0xff, 0xff, 0xff) },
{ USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1413) }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1413, 0xff, 0xff, 0xff) },
{ USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1414) }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1414, 0xff, 0xff, 0xff) },
{ USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1415) }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1415, 0xff, 0xff, 0xff) },
{ USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1416) }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1416, 0xff, 0xff, 0xff) },
{ USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1417) }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1417, 0xff, 0xff, 0xff) },
{ USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1418) }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1418, 0xff, 0xff, 0xff) },
{ USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1419) }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1419, 0xff, 0xff, 0xff) },
{ USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_9508) }, { USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_9508) },
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V640) }, /* Novatel Merlin V640/XV620 */ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V640) }, /* Novatel Merlin V640/XV620 */
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V620) }, /* Novatel Merlin V620/S620 */ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V620) }, /* Novatel Merlin V620/S620 */
......
...@@ -56,6 +56,7 @@ static struct usb_device_id id_table [] = { ...@@ -56,6 +56,7 @@ static struct usb_device_id id_table [] = {
{ USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_RSAQ3) }, { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_RSAQ3) },
{ USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_PHAROS) }, { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_PHAROS) },
{ USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_ALDIGA) }, { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_ALDIGA) },
{ USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_MMX) },
{ USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID) }, { USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID) },
{ USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID_RSAQ5) }, { USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID_RSAQ5) },
{ USB_DEVICE(ATEN_VENDOR_ID, ATEN_PRODUCT_ID) }, { USB_DEVICE(ATEN_VENDOR_ID, ATEN_PRODUCT_ID) },
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#define PL2303_PRODUCT_ID_PHAROS 0xaaa0 #define PL2303_PRODUCT_ID_PHAROS 0xaaa0
#define PL2303_PRODUCT_ID_RSAQ3 0xaaa2 #define PL2303_PRODUCT_ID_RSAQ3 0xaaa2
#define PL2303_PRODUCT_ID_ALDIGA 0x0611 #define PL2303_PRODUCT_ID_ALDIGA 0x0611
#define PL2303_PRODUCT_ID_MMX 0x0612
#define ATEN_VENDOR_ID 0x0557 #define ATEN_VENDOR_ID 0x0557
#define ATEN_VENDOR_ID2 0x0547 #define ATEN_VENDOR_ID2 0x0547
......
...@@ -405,7 +405,7 @@ UNUSUAL_DEV( 0x04a5, 0x3010, 0x0100, 0x0100, ...@@ -405,7 +405,7 @@ UNUSUAL_DEV( 0x04a5, 0x3010, 0x0100, 0x0100,
UNUSUAL_DEV( 0x04b4, 0x6830, 0x0000, 0x9999, UNUSUAL_DEV( 0x04b4, 0x6830, 0x0000, 0x9999,
"Cypress", "Cypress",
"Cypress AT2LP", "Cypress AT2LP",
US_SC_CYP_ATACB, US_PR_BULK, NULL, US_SC_CYP_ATACB, US_PR_DEVICE, NULL,
0), 0),
#endif #endif
...@@ -1522,7 +1522,7 @@ UNUSUAL_DEV( 0x0fce, 0xe031, 0x0000, 0x0000, ...@@ -1522,7 +1522,7 @@ UNUSUAL_DEV( 0x0fce, 0xe031, 0x0000, 0x0000,
"Sony Ericsson", "Sony Ericsson",
"M600i", "M600i",
US_SC_DEVICE, US_PR_DEVICE, NULL, US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_FIX_CAPACITY ), US_FL_IGNORE_RESIDUE | US_FL_FIX_CAPACITY ),
/* Reported by Kevin Cernekee <kpc-usbdev@gelato.uiuc.edu> /* Reported by Kevin Cernekee <kpc-usbdev@gelato.uiuc.edu>
* Tested on hardware version 1.10. * Tested on hardware version 1.10.
...@@ -1716,10 +1716,12 @@ UNUSUAL_DEV( 0x22b8, 0x3010, 0x0001, 0x0001, ...@@ -1716,10 +1716,12 @@ UNUSUAL_DEV( 0x22b8, 0x3010, 0x0001, 0x0001,
/* /*
* Patch by Pete Zaitcev <zaitcev@redhat.com> * Patch by Pete Zaitcev <zaitcev@redhat.com>
* Report by Mark Patton. Red Hat bz#208928. * Report by Mark Patton. Red Hat bz#208928.
* Added support for rev 0x0002 (Motorola ROKR W5)
* by Javier Smaldone <javier@smaldone.com.ar>
*/ */
UNUSUAL_DEV( 0x22b8, 0x4810, 0x0001, 0x0001, UNUSUAL_DEV( 0x22b8, 0x4810, 0x0001, 0x0002,
"Motorola", "Motorola",
"RAZR V3i", "RAZR V3i/ROKR W5",
US_SC_DEVICE, US_PR_DEVICE, NULL, US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_FIX_CAPACITY), US_FL_FIX_CAPACITY),
......
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