kernel: USB update from stlinux24_217

This commit is contained in:
Jaroslav Kysela 2015-08-03 18:18:03 +02:00
parent 07aa6b0e5a
commit c48033761a
48 changed files with 621 additions and 269 deletions

View File

@ -49,7 +49,8 @@ config USB_ARCH_HAS_OHCI
default y if CPU_SUBTYPE_SH7721 default y if CPU_SUBTYPE_SH7721
default y if CPU_SUBTYPE_SH7763 default y if CPU_SUBTYPE_SH7763
default y if CPU_SUBTYPE_SH7786 default y if CPU_SUBTYPE_SH7786
default y if CPU_SUBTYPE_FLI7510 default y if CPU_SUBTYPE_FLI75XX
default y if CPU_SUBTYPE_STXH205
default y if CPU_SUBTYPE_STX5197 default y if CPU_SUBTYPE_STX5197
default y if CPU_SUBTYPE_STX5206 default y if CPU_SUBTYPE_STX5206
default y if CPU_SUBTYPE_STX7100 default y if CPU_SUBTYPE_STX7100
@ -69,7 +70,8 @@ config USB_ARCH_HAS_EHCI
default y if ARCH_IXP4XX default y if ARCH_IXP4XX
default y if ARCH_W90X900 default y if ARCH_W90X900
default y if ARCH_AT91SAM9G45 default y if ARCH_AT91SAM9G45
default y if CPU_SUBTYPE_FLI7510 default y if CPU_SUBTYPE_FLI75XX
default y if CPU_SUBTYPE_STXH205
default y if CPU_SUBTYPE_STX5197 default y if CPU_SUBTYPE_STX5197
default y if CPU_SUBTYPE_STX5206 default y if CPU_SUBTYPE_STX5206
default y if CPU_SUBTYPE_STX7100 default y if CPU_SUBTYPE_STX7100

View File

@ -1120,7 +1120,8 @@ skip_normal_probe:
} }
if (data_interface->cur_altsetting->desc.bNumEndpoints < 2) if (data_interface->cur_altsetting->desc.bNumEndpoints < 2 ||
control_interface->cur_altsetting->desc.bNumEndpoints == 0)
return -EINVAL; return -EINVAL;
epctrl = &control_interface->cur_altsetting->endpoint[0].desc; epctrl = &control_interface->cur_altsetting->endpoint[0].desc;
@ -1264,6 +1265,8 @@ made_compressed_probe:
i = device_create_file(&intf->dev, &dev_attr_wCountryCodes); i = device_create_file(&intf->dev, &dev_attr_wCountryCodes);
if (i < 0) { if (i < 0) {
kfree(acm->country_codes); kfree(acm->country_codes);
acm->country_codes = NULL;
acm->country_code_size = 0;
goto skip_countries; goto skip_countries;
} }
@ -1272,6 +1275,8 @@ made_compressed_probe:
if (i < 0) { if (i < 0) {
device_remove_file(&intf->dev, &dev_attr_wCountryCodes); device_remove_file(&intf->dev, &dev_attr_wCountryCodes);
kfree(acm->country_codes); kfree(acm->country_codes);
acm->country_codes = NULL;
acm->country_code_size = 0;
goto skip_countries; goto skip_countries;
} }
} }
@ -1528,6 +1533,16 @@ static struct usb_device_id acm_ids[] = {
}, },
{ USB_DEVICE(0x22b8, 0x6425), /* Motorola MOTOMAGX phones */ { USB_DEVICE(0x22b8, 0x6425), /* Motorola MOTOMAGX phones */
}, },
/* Motorola H24 HSPA module: */
{ USB_DEVICE(0x22b8, 0x2d91) }, /* modem */
{ USB_DEVICE(0x22b8, 0x2d92) }, /* modem + diagnostics */
{ USB_DEVICE(0x22b8, 0x2d93) }, /* modem + AT port */
{ USB_DEVICE(0x22b8, 0x2d95) }, /* modem + AT port + diagnostics */
{ USB_DEVICE(0x22b8, 0x2d96) }, /* modem + NMEA */
{ USB_DEVICE(0x22b8, 0x2d97) }, /* modem + diagnostics + NMEA */
{ USB_DEVICE(0x22b8, 0x2d99) }, /* modem + AT port + NMEA */
{ USB_DEVICE(0x22b8, 0x2d9a) }, /* modem + AT port + diagnostics + NMEA */
{ USB_DEVICE(0x0572, 0x1329), /* Hummingbird huc56s (Conexant) */ { USB_DEVICE(0x0572, 0x1329), /* Hummingbird huc56s (Conexant) */
.driver_info = NO_UNION_NORMAL, /* union descriptor misplaced on .driver_info = NO_UNION_NORMAL, /* union descriptor misplaced on
data interface instead of data interface instead of
@ -1606,6 +1621,9 @@ static struct usb_device_id acm_ids[] = {
{ NOKIA_PCSUITE_ACM_INFO(0x03cd), }, /* Nokia C7 */ { NOKIA_PCSUITE_ACM_INFO(0x03cd), }, /* Nokia C7 */
{ SAMSUNG_PCSUITE_ACM_INFO(0x6651), }, /* Samsung GTi8510 (INNOV8) */ { SAMSUNG_PCSUITE_ACM_INFO(0x6651), }, /* Samsung GTi8510 (INNOV8) */
/* Support for Owen devices */
{ USB_DEVICE(0x03eb, 0x0030), }, /* Owen SI30 */
/* NOTE: non-Nokia COMM/ACM/0xff is likely MSFT RNDIS... NOT a modem! */ /* NOTE: non-Nokia COMM/ACM/0xff is likely MSFT RNDIS... NOT a modem! */
/* control interfaces without any protocol set */ /* control interfaces without any protocol set */

View File

@ -52,6 +52,7 @@ MODULE_DEVICE_TABLE (usb, wdm_ids);
#define WDM_READ 4 #define WDM_READ 4
#define WDM_INT_STALL 5 #define WDM_INT_STALL 5
#define WDM_POLL_RUNNING 6 #define WDM_POLL_RUNNING 6
#define WDM_OVERFLOW 10
#define WDM_MAX 16 #define WDM_MAX 16
@ -115,6 +116,7 @@ static void wdm_in_callback(struct urb *urb)
{ {
struct wdm_device *desc = urb->context; struct wdm_device *desc = urb->context;
int status = urb->status; int status = urb->status;
int length = urb->actual_length;
spin_lock(&desc->iuspin); spin_lock(&desc->iuspin);
@ -144,9 +146,17 @@ static void wdm_in_callback(struct urb *urb)
} }
desc->rerr = status; desc->rerr = status;
desc->reslength = urb->actual_length; if (length + desc->length > desc->wMaxCommand) {
memmove(desc->ubuf + desc->length, desc->inbuf, desc->reslength); /* The buffer would overflow */
desc->length += desc->reslength; set_bit(WDM_OVERFLOW, &desc->flags);
} else {
/* we may already be in overflow */
if (!test_bit(WDM_OVERFLOW, &desc->flags)) {
memmove(desc->ubuf + desc->length, desc->inbuf, length);
desc->length += length;
desc->reslength = length;
}
}
wake_up(&desc->wait); wake_up(&desc->wait);
set_bit(WDM_READ, &desc->flags); set_bit(WDM_READ, &desc->flags);
@ -277,7 +287,7 @@ static void cleanup(struct wdm_device *desc)
desc->sbuf, desc->sbuf,
desc->validity->transfer_dma); desc->validity->transfer_dma);
usb_buffer_free(interface_to_usbdev(desc->intf), usb_buffer_free(interface_to_usbdev(desc->intf),
desc->wMaxCommand, desc->bMaxPacketSize0,
desc->inbuf, desc->inbuf,
desc->response->transfer_dma); desc->response->transfer_dma);
kfree(desc->orq); kfree(desc->orq);
@ -314,7 +324,7 @@ static ssize_t wdm_write
if (r < 0) if (r < 0)
goto outnp; goto outnp;
if (!file->f_flags && O_NONBLOCK) if (!(file->f_flags & O_NONBLOCK))
r = wait_event_interruptible(desc->wait, !test_bit(WDM_IN_USE, r = wait_event_interruptible(desc->wait, !test_bit(WDM_IN_USE,
&desc->flags)); &desc->flags));
else else
@ -398,6 +408,11 @@ retry:
rv = -ENODEV; rv = -ENODEV;
goto err; goto err;
} }
if (test_bit(WDM_OVERFLOW, &desc->flags)) {
clear_bit(WDM_OVERFLOW, &desc->flags);
rv = -ENOBUFS;
goto err;
}
i++; i++;
if (file->f_flags & O_NONBLOCK) { if (file->f_flags & O_NONBLOCK) {
if (!test_bit(WDM_READ, &desc->flags)) { if (!test_bit(WDM_READ, &desc->flags)) {
@ -440,7 +455,10 @@ retry:
spin_unlock_irq(&desc->iuspin); spin_unlock_irq(&desc->iuspin);
goto retry; goto retry;
} }
if (!desc->reslength) { /* zero length read */ if (!desc->reslength) { /* zero length read */
dev_dbg(&desc->intf->dev, "%s: zero length - clearing WDM_READ\n", __func__);
clear_bit(WDM_READ, &desc->flags);
spin_unlock_irq(&desc->iuspin); spin_unlock_irq(&desc->iuspin);
goto retry; goto retry;
} }
@ -458,7 +476,9 @@ retry:
for (i = 0; i < desc->length - cntr; i++) for (i = 0; i < desc->length - cntr; i++)
desc->ubuf[i] = desc->ubuf[i + cntr]; desc->ubuf[i] = desc->ubuf[i + cntr];
spin_lock_irq(&desc->iuspin);
desc->length -= cntr; desc->length -= cntr;
spin_unlock_irq(&desc->iuspin);
/* in case we had outstanding data */ /* in case we had outstanding data */
if (!desc->length) if (!desc->length)
clear_bit(WDM_READ, &desc->flags); clear_bit(WDM_READ, &desc->flags);
@ -840,6 +860,7 @@ static int wdm_post_reset(struct usb_interface *intf)
struct wdm_device *desc = usb_get_intfdata(intf); struct wdm_device *desc = usb_get_intfdata(intf);
int rv; int rv;
clear_bit(WDM_OVERFLOW, &desc->flags);
rv = recover_from_urb_loss(desc); rv = recover_from_urb_loss(desc);
mutex_unlock(&desc->plock); mutex_unlock(&desc->plock);
return 0; return 0;

View File

@ -267,7 +267,7 @@ usbtmc_abort_bulk_in_status:
dev_err(dev, "usb_bulk_msg returned %d\n", rv); dev_err(dev, "usb_bulk_msg returned %d\n", rv);
goto exit; goto exit;
} }
} while ((actual = max_size) && } while ((actual == max_size) &&
(n < USBTMC_MAX_READS_TO_CLEAR_BULK_IN)); (n < USBTMC_MAX_READS_TO_CLEAR_BULK_IN));
if (actual == max_size) { if (actual == max_size) {

View File

@ -403,7 +403,7 @@ static void async_completed(struct urb *urb)
sinfo.si_errno = as->status; sinfo.si_errno = as->status;
sinfo.si_code = SI_ASYNCIO; sinfo.si_code = SI_ASYNCIO;
sinfo.si_addr = as->userurb; sinfo.si_addr = as->userurb;
pid = as->pid; pid = get_pid(as->pid);
uid = as->uid; uid = as->uid;
euid = as->euid; euid = as->euid;
secid = as->secid; secid = as->secid;
@ -416,9 +416,11 @@ static void async_completed(struct urb *urb)
cancel_bulk_urbs(ps, as->bulk_addr); cancel_bulk_urbs(ps, as->bulk_addr);
spin_unlock(&ps->lock); spin_unlock(&ps->lock);
if (signr) if (signr) {
kill_pid_info_as_uid(sinfo.si_signo, &sinfo, pid, uid, kill_pid_info_as_uid(sinfo.si_signo, &sinfo, pid, uid,
euid, secid); euid, secid);
put_pid(pid);
}
wake_up(&ps->wait); wake_up(&ps->wait);
} }
@ -1452,10 +1454,14 @@ static int processcompl_compat(struct async *as, void __user * __user *arg)
void __user *addr = as->userurb; void __user *addr = as->userurb;
unsigned int i; unsigned int i;
if (as->userbuffer && urb->actual_length) if (as->userbuffer && urb->actual_length) {
if (copy_to_user(as->userbuffer, urb->transfer_buffer, if (urb->number_of_packets > 0) /* Isochronous */
urb->actual_length)) i = urb->transfer_buffer_length;
else /* Non-Isoc */
i = urb->actual_length;
if (copy_to_user(as->userbuffer, urb->transfer_buffer, i))
return -EFAULT; return -EFAULT;
}
if (put_user(as->status, &userurb->status)) if (put_user(as->status, &userurb->status))
return -EFAULT; return -EFAULT;
if (put_user(urb->actual_length, &userurb->actual_length)) if (put_user(urb->actual_length, &userurb->actual_length))

View File

@ -1187,13 +1187,22 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg)
for (; i < udev->actconfig->desc.bNumInterfaces; i++) { for (; i < udev->actconfig->desc.bNumInterfaces; i++) {
intf = udev->actconfig->interface[i]; intf = udev->actconfig->interface[i];
status = usb_suspend_interface(udev, intf, msg); status = usb_suspend_interface(udev, intf, msg);
/* Ignore errors during system sleep transitions */
if (!(msg.event & PM_EVENT_AUTO))
status = 0;
if (status != 0) if (status != 0)
break; break;
} }
} }
if (status == 0) if (status == 0) {
status = usb_suspend_device(udev, msg); status = usb_suspend_device(udev, msg);
/* Again, ignore errors during system sleep transitions */
if (!(msg.event & PM_EVENT_AUTO))
status = 0;
}
/* If the suspend failed, resume interfaces that did get suspended */ /* If the suspend failed, resume interfaces that did get suspended */
if (status != 0) { if (status != 0) {
pm_message_t msg2; pm_message_t msg2;

View File

@ -23,6 +23,7 @@
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/freezer.h> #include <linux/freezer.h>
#include <linux/usb/quirks.h> #include <linux/usb/quirks.h>
#include <linux/random.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/byteorder.h> #include <asm/byteorder.h>
@ -458,10 +459,8 @@ hub_clear_tt_buffer (struct usb_device *hdev, u16 devinfo, u16 tt)
* talking to TTs must queue control transfers (not just bulk and iso), so * talking to TTs must queue control transfers (not just bulk and iso), so
* both can talk to the same hub concurrently. * both can talk to the same hub concurrently.
*/ */
static void hub_tt_work(struct work_struct *work) void _hub_tt_work(struct usb_hub *hub)
{ {
struct usb_hub *hub =
container_of(work, struct usb_hub, tt.clear_work);
unsigned long flags; unsigned long flags;
int limit = 100; int limit = 100;
@ -496,6 +495,14 @@ static void hub_tt_work(struct work_struct *work)
spin_unlock_irqrestore (&hub->tt.lock, flags); spin_unlock_irqrestore (&hub->tt.lock, flags);
} }
void hub_tt_work(struct work_struct *work)
{
struct usb_hub *hub =
container_of(work, struct usb_hub, tt.clear_work);
_hub_tt_work(hub);
}
/** /**
* usb_hub_clear_tt_buffer - clear control/bulk TT state in high speed hub * usb_hub_clear_tt_buffer - clear control/bulk TT state in high speed hub
* @urb: an URB associated with the failed or incomplete split transaction * @urb: an URB associated with the failed or incomplete split transaction
@ -543,7 +550,20 @@ int usb_hub_clear_tt_buffer(struct urb *urb)
/* tell keventd to clear state for this TT */ /* tell keventd to clear state for this TT */
spin_lock_irqsave (&tt->lock, flags); spin_lock_irqsave (&tt->lock, flags);
list_add_tail (&clear->clear_list, &tt->clear_list); list_add_tail (&clear->clear_list, &tt->clear_list);
schedule_work(&tt->clear_work); /* don't schedule on kevent if we're running on keventd (e.g.,
* in hid_reset we can get here on kevent) unless on >=2.6.36
*/
if (!current_is_keventd())
/* put it on keventd */
schedule_work(&tt->clear_work);
else {
/* let khubd do it */
struct usb_hub *hub =
container_of(&tt->clear_work, struct usb_hub,
tt.clear_work);
kick_khubd(hub);
}
spin_unlock_irqrestore (&tt->lock, flags); spin_unlock_irqrestore (&tt->lock, flags);
return 0; return 0;
} }
@ -1812,6 +1832,16 @@ int usb_new_device(struct usb_device *udev)
/* Tell the world! */ /* Tell the world! */
announce_device(udev); announce_device(udev);
#if 0
if (udev->serial)
add_device_randomness(udev->serial, strlen(udev->serial));
if (udev->product)
add_device_randomness(udev->product, strlen(udev->product));
if (udev->manufacturer)
add_device_randomness(udev->manufacturer,
strlen(udev->manufacturer));
#endif
/* Register the device. The device driver is responsible /* Register the device. The device driver is responsible
* for configuring the device and invoking the add-device * for configuring the device and invoking the add-device
* notifier chain (used by usbfs and possibly others). * notifier chain (used by usbfs and possibly others).
@ -2188,6 +2218,10 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
USB_DEVICE_REMOTE_WAKEUP, 0, USB_DEVICE_REMOTE_WAKEUP, 0,
NULL, 0, NULL, 0,
USB_CTRL_SET_TIMEOUT); USB_CTRL_SET_TIMEOUT);
/* System sleep transitions should never fail */
if (!(msg.event & PM_EVENT_AUTO))
status = 0;
} else { } else {
/* device has up to 10 msec to fully suspend */ /* device has up to 10 msec to fully suspend */
dev_dbg(&udev->dev, "usb %ssuspend\n", dev_dbg(&udev->dev, "usb %ssuspend\n",
@ -2427,16 +2461,15 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
struct usb_device *hdev = hub->hdev; struct usb_device *hdev = hub->hdev;
unsigned port1; unsigned port1;
/* fail if children aren't already suspended */ /* Warn if children aren't already suspended */
for (port1 = 1; port1 <= hdev->maxchild; port1++) { for (port1 = 1; port1 <= hdev->maxchild; port1++) {
struct usb_device *udev; struct usb_device *udev;
udev = hdev->children [port1-1]; udev = hdev->children [port1-1];
if (udev && udev->can_submit) { if (udev && udev->can_submit) {
if (!(msg.event & PM_EVENT_AUTO)) dev_warn(&intf->dev, "port %d nyet suspended\n", port1);
dev_dbg(&intf->dev, "port %d nyet suspended\n", if (msg.event & PM_EVENT_AUTO)
port1); return -EBUSY;
return -EBUSY;
} }
} }
@ -3271,6 +3304,10 @@ static void hub_events(void)
if (hub->quiescing) if (hub->quiescing)
goto loop_autopm; goto loop_autopm;
/* _hub_tt_work usually run on keventd */
if (!list_empty(&hub->tt.clear_list))
_hub_tt_work(hub);
if (hub->error) { if (hub->error) {
dev_dbg (hub_dev, "resetting for error %d\n", dev_dbg (hub_dev, "resetting for error %d\n",
hub->error); hub->error);

View File

@ -38,6 +38,51 @@ static const struct usb_device_id usb_quirk_list[] = {
/* Creative SB Audigy 2 NX */ /* Creative SB Audigy 2 NX */
{ USB_DEVICE(0x041e, 0x3020), .driver_info = USB_QUIRK_RESET_RESUME }, { USB_DEVICE(0x041e, 0x3020), .driver_info = USB_QUIRK_RESET_RESUME },
/* Logitech Webcam C200 */
{ USB_DEVICE(0x046d, 0x0802), .driver_info = USB_QUIRK_RESET_RESUME },
/* Logitech Webcam C250 */
{ USB_DEVICE(0x046d, 0x0804), .driver_info = USB_QUIRK_RESET_RESUME },
/* Logitech Webcam B/C500 */
{ USB_DEVICE(0x046d, 0x0807), .driver_info = USB_QUIRK_RESET_RESUME },
/* Logitech Webcam C600 */
{ USB_DEVICE(0x046d, 0x0808), .driver_info = USB_QUIRK_RESET_RESUME },
/* Logitech Webcam Pro 9000 */
{ USB_DEVICE(0x046d, 0x0809), .driver_info = USB_QUIRK_RESET_RESUME },
/* Logitech Webcam C905 */
{ USB_DEVICE(0x046d, 0x080a), .driver_info = USB_QUIRK_RESET_RESUME },
/* Logitech Webcam C210 */
{ USB_DEVICE(0x046d, 0x0819), .driver_info = USB_QUIRK_RESET_RESUME },
/* Logitech Webcam C260 */
{ USB_DEVICE(0x046d, 0x081a), .driver_info = USB_QUIRK_RESET_RESUME },
/* Logitech Webcam C310 */
{ USB_DEVICE(0x046d, 0x081b), .driver_info = USB_QUIRK_RESET_RESUME },
/* Logitech Webcam C910 */
{ USB_DEVICE(0x046d, 0x0821), .driver_info = USB_QUIRK_RESET_RESUME },
/* Logitech Webcam C160 */
{ USB_DEVICE(0x046d, 0x0824), .driver_info = USB_QUIRK_RESET_RESUME },
/* Logitech Webcam C270 */
{ USB_DEVICE(0x046d, 0x0825), .driver_info = USB_QUIRK_RESET_RESUME },
/* Logitech Quickcam Pro 9000 */
{ USB_DEVICE(0x046d, 0x0990), .driver_info = USB_QUIRK_RESET_RESUME },
/* Logitech Quickcam E3500 */
{ USB_DEVICE(0x046d, 0x09a4), .driver_info = USB_QUIRK_RESET_RESUME },
/* Logitech Quickcam Vision Pro */
{ USB_DEVICE(0x046d, 0x09a6), .driver_info = USB_QUIRK_RESET_RESUME },
/* Logitech Harmony 700-series */ /* Logitech Harmony 700-series */
{ USB_DEVICE(0x046d, 0xc122), .driver_info = USB_QUIRK_DELAY_INIT }, { USB_DEVICE(0x046d, 0xc122), .driver_info = USB_QUIRK_DELAY_INIT },
@ -69,6 +114,12 @@ static const struct usb_device_id usb_quirk_list[] = {
{ USB_DEVICE(0x06a3, 0x0006), .driver_info = { USB_DEVICE(0x06a3, 0x0006), .driver_info =
USB_QUIRK_CONFIG_INTF_STRINGS }, USB_QUIRK_CONFIG_INTF_STRINGS },
/* Guillemot Webcam Hercules Dualpix Exchange (2nd ID) */
{ USB_DEVICE(0x06f8, 0x0804), .driver_info = USB_QUIRK_RESET_RESUME },
/* Guillemot Webcam Hercules Dualpix Exchange*/
{ USB_DEVICE(0x06f8, 0x3005), .driver_info = USB_QUIRK_RESET_RESUME },
/* 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 },

View File

@ -449,7 +449,7 @@ static int dbgp_ehci_startup(void)
writel(FLAG_CF, &ehci_regs->configured_flag); writel(FLAG_CF, &ehci_regs->configured_flag);
/* Wait until the controller is no longer halted */ /* Wait until the controller is no longer halted */
loop = 10; loop = 1000;
do { do {
status = readl(&ehci_regs->status); status = readl(&ehci_regs->status);
if (!(status & STS_HALT)) if (!(status & STS_HALT))

View File

@ -1886,6 +1886,7 @@ static int dummy_hcd_probe(struct platform_device *pdev)
if (!hcd) if (!hcd)
return -ENOMEM; return -ENOMEM;
the_controller = hcd_to_dummy (hcd); the_controller = hcd_to_dummy (hcd);
hcd->has_tt = 1;
retval = usb_add_hcd(hcd, 0, 0); retval = usb_add_hcd(hcd, 0, 0);
if (retval != 0) { if (retval != 0) {

View File

@ -373,7 +373,7 @@ int __init loopback_add(struct usb_composite_dev *cdev, bool autoresume)
/* support autoresume for remote wakeup testing */ /* support autoresume for remote wakeup testing */
if (autoresume) if (autoresume)
sourcesink_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP; loopback_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
/* support OTG systems */ /* support OTG systems */
if (gadget_is_otg(cdev->gadget)) { if (gadget_is_otg(cdev->gadget)) {

View File

@ -41,7 +41,7 @@
* (host controller _Structural_ parameters) * (host controller _Structural_ parameters)
* see EHCI spec, Table 2-4 for each value * see EHCI spec, Table 2-4 for each value
*/ */
static void dbg_hcs_params (struct ehci_hcd *ehci, char *label) static inline void dbg_hcs_params(struct ehci_hcd *ehci, char *label)
{ {
u32 params = ehci_readl(ehci, &ehci->caps->hcs_params); u32 params = ehci_readl(ehci, &ehci->caps->hcs_params);
@ -85,7 +85,7 @@ static inline void dbg_hcs_params (struct ehci_hcd *ehci, char *label) {}
* (host controller _Capability_ parameters) * (host controller _Capability_ parameters)
* see EHCI Spec, Table 2-5 for each value * see EHCI Spec, Table 2-5 for each value
* */ * */
static void dbg_hcc_params (struct ehci_hcd *ehci, char *label) static inline void dbg_hcc_params(struct ehci_hcd *ehci, char *label)
{ {
u32 params = ehci_readl(ehci, &ehci->caps->hcc_params); u32 params = ehci_readl(ehci, &ehci->caps->hcc_params);

View File

@ -84,7 +84,8 @@ static const char hcd_name [] = "ehci_hcd";
#define EHCI_IAA_MSECS 10 /* arbitrary */ #define EHCI_IAA_MSECS 10 /* arbitrary */
#define EHCI_IO_JIFFIES (HZ/10) /* io watchdog > irq_thresh */ #define EHCI_IO_JIFFIES (HZ/10) /* io watchdog > irq_thresh */
#define EHCI_ASYNC_JIFFIES (HZ/20) /* async idle timeout */ #define EHCI_ASYNC_JIFFIES (HZ/20) /* async idle timeout */
#define EHCI_SHRINK_FRAMES 5 /* async qh unlink delay */ #define EHCI_SHRINK_JIFFIES (DIV_ROUND_UP(HZ, 200) + 1)
/* 200-ms async qh unlink delay */
/* Initial IRQ latency: faster than hw default */ /* Initial IRQ latency: faster than hw default */
static int log2_irq_thresh = 0; // 0 to 6 static int log2_irq_thresh = 0; // 0 to 6
@ -139,10 +140,7 @@ timer_action(struct ehci_hcd *ehci, enum ehci_timer_action action)
break; break;
/* case TIMER_ASYNC_SHRINK: */ /* case TIMER_ASYNC_SHRINK: */
default: default:
/* add a jiffie since we synch against the t = EHCI_SHRINK_JIFFIES;
* 8 KHz uframe counter.
*/
t = DIV_ROUND_UP(EHCI_SHRINK_FRAMES * HZ, 1000) + 1;
break; break;
} }
mod_timer(&ehci->watchdog, t + jiffies); mod_timer(&ehci->watchdog, t + jiffies);
@ -432,7 +430,7 @@ static void ehci_shutdown(struct usb_hcd *hcd)
spin_unlock_irq(&ehci->lock); spin_unlock_irq(&ehci->lock);
} }
static void ehci_port_power (struct ehci_hcd *ehci, int is_on) static inline void ehci_port_power(struct ehci_hcd *ehci, int is_on)
{ {
unsigned port; unsigned port;

View File

@ -264,7 +264,7 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
u32 temp; u32 temp;
u32 power_okay; u32 power_okay;
int i; int i;
u8 resume_needed = 0; unsigned long resume_needed = 0;
if (time_before (jiffies, ehci->next_statechange)) if (time_before (jiffies, ehci->next_statechange))
msleep(5); msleep(5);
@ -328,7 +328,7 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
if (test_bit(i, &ehci->bus_suspended) && if (test_bit(i, &ehci->bus_suspended) &&
(temp & PORT_SUSPEND)) { (temp & PORT_SUSPEND)) {
temp |= PORT_RESUME; temp |= PORT_RESUME;
resume_needed = 1; set_bit(i, &resume_needed);
} }
ehci_writel(ehci, temp, &ehci->regs->port_status [i]); ehci_writel(ehci, temp, &ehci->regs->port_status [i]);
} }
@ -343,8 +343,7 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
i = HCS_N_PORTS (ehci->hcs_params); i = HCS_N_PORTS (ehci->hcs_params);
while (i--) { while (i--) {
temp = ehci_readl(ehci, &ehci->regs->port_status [i]); temp = ehci_readl(ehci, &ehci->regs->port_status [i]);
if (test_bit(i, &ehci->bus_suspended) && if (test_bit(i, &resume_needed)) {
(temp & PORT_SUSPEND)) {
temp &= ~(PORT_RWC_BITS | PORT_RESUME); temp &= ~(PORT_RWC_BITS | PORT_RESUME);
ehci_writel(ehci, temp, &ehci->regs->port_status [i]); ehci_writel(ehci, temp, &ehci->regs->port_status [i]);
ehci_vdbg (ehci, "resumed port %d\n", i + 1); ehci_vdbg (ehci, "resumed port %d\n", i + 1);
@ -779,10 +778,11 @@ static int ehci_hub_control (
* power switching; they're allowed to just limit the * power switching; they're allowed to just limit the
* current. khubd will turn the power back on. * current. khubd will turn the power back on.
*/ */
if (HCS_PPC (ehci->hcs_params)){ if ((temp & PORT_OC) && HCS_PPC(ehci->hcs_params)) {
ehci_writel(ehci, ehci_writel(ehci,
temp & ~(PORT_RWC_BITS | PORT_POWER), temp & ~(PORT_RWC_BITS | PORT_POWER),
status_reg); status_reg);
temp = ehci_readl(ehci, status_reg);
} }
} }

View File

@ -103,7 +103,7 @@ qh_update (struct ehci_hcd *ehci, struct ehci_qh *qh, struct ehci_qtd *qtd)
if (!(hw->hw_info1 & cpu_to_hc32(ehci, 1 << 14))) { if (!(hw->hw_info1 & cpu_to_hc32(ehci, 1 << 14))) {
unsigned is_out, epnum; unsigned is_out, epnum;
is_out = !(qtd->hw_token & cpu_to_hc32(ehci, 1 << 8)); is_out = qh->is_out;
epnum = (hc32_to_cpup(ehci, &hw->hw_info1) >> 8) & 0x0f; epnum = (hc32_to_cpup(ehci, &hw->hw_info1) >> 8) & 0x0f;
if (unlikely (!usb_gettoggle (qh->dev, epnum, is_out))) { if (unlikely (!usb_gettoggle (qh->dev, epnum, is_out))) {
hw->hw_token &= ~cpu_to_hc32(ehci, QTD_TOGGLE); hw->hw_token &= ~cpu_to_hc32(ehci, QTD_TOGGLE);
@ -936,6 +936,7 @@ done:
hw = qh->hw; hw = qh->hw;
hw->hw_info1 = cpu_to_hc32(ehci, info1); hw->hw_info1 = cpu_to_hc32(ehci, info1);
hw->hw_info2 = cpu_to_hc32(ehci, info2); hw->hw_info2 = cpu_to_hc32(ehci, info2);
qh->is_out = !is_input;
usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe), !is_input, 1); usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe), !is_input, 1);
qh_refresh (ehci, qh); qh_refresh (ehci, qh);
return qh; return qh;
@ -1216,6 +1217,8 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
prev->hw->hw_next = qh->hw->hw_next; prev->hw->hw_next = qh->hw->hw_next;
prev->qh_next = qh->qh_next; prev->qh_next = qh->qh_next;
if (ehci->qh_scan_next == qh)
ehci->qh_scan_next = qh->qh_next.qh;
wmb (); wmb ();
/* If the controller isn't running, we don't have to wait for it */ /* If the controller isn't running, we don't have to wait for it */
@ -1241,53 +1244,49 @@ static void scan_async (struct ehci_hcd *ehci)
struct ehci_qh *qh; struct ehci_qh *qh;
enum ehci_timer_action action = TIMER_IO_WATCHDOG; enum ehci_timer_action action = TIMER_IO_WATCHDOG;
ehci->stamp = ehci_readl(ehci, &ehci->regs->frame_index);
timer_action_done (ehci, TIMER_ASYNC_SHRINK); timer_action_done (ehci, TIMER_ASYNC_SHRINK);
rescan:
stopped = !HC_IS_RUNNING(ehci_to_hcd(ehci)->state); stopped = !HC_IS_RUNNING(ehci_to_hcd(ehci)->state);
qh = ehci->async->qh_next.qh;
if (likely (qh != NULL)) {
do {
/* clean any finished work for this qh */
if (!list_empty(&qh->qtd_list) && (stopped ||
qh->stamp != ehci->stamp)) {
int temp;
/* unlinks could happen here; completion ehci->qh_scan_next = ehci->async->qh_next.qh;
* reporting drops the lock. rescan using while (ehci->qh_scan_next) {
* the latest schedule, but don't rescan qh = ehci->qh_scan_next;
* qhs we already finished (no looping) ehci->qh_scan_next = qh->qh_next.qh;
* unless the controller is stopped. rescan:
*/ /* clean any finished work for this qh */
qh = qh_get (qh); if (!list_empty(&qh->qtd_list)) {
qh->stamp = ehci->stamp; int temp;
temp = qh_completions (ehci, qh);
if (qh->needs_rescan)
unlink_async(ehci, qh);
qh_put (qh);
if (temp != 0) {
goto rescan;
}
}
/* unlink idle entries, reducing DMA usage as well /*
* as HCD schedule-scanning costs. delay for any qh * Unlinks could happen here; completion reporting
* we just scanned, there's a not-unusual case that it * drops the lock. That's why ehci->qh_scan_next
* doesn't stay idle for long. * always holds the next qh to scan; if the next qh
* (plus, avoids some kind of re-activation race.) * gets unlinked then ehci->qh_scan_next is adjusted
* in start_unlink_async().
*/ */
if (list_empty(&qh->qtd_list) qh = qh_get(qh);
&& qh->qh_state == QH_STATE_LINKED) { temp = qh_completions(ehci, qh);
if (!ehci->reclaim && (stopped || if (qh->needs_rescan)
((ehci->stamp - qh->stamp) & 0x1fff) unlink_async(ehci, qh);
>= EHCI_SHRINK_FRAMES * 8)) qh->unlink_time = jiffies + EHCI_SHRINK_JIFFIES;
start_unlink_async(ehci, qh); qh_put(qh);
else if (temp != 0)
action = TIMER_ASYNC_SHRINK; goto rescan;
} }
qh = qh->qh_next.qh; /* unlink idle entries, reducing DMA usage as well
} while (qh); * as HCD schedule-scanning costs. delay for any qh
* we just scanned, there's a not-unusual case that it
* doesn't stay idle for long.
* (plus, avoids some kind of re-activation race.)
*/
if (list_empty(&qh->qtd_list)
&& qh->qh_state == QH_STATE_LINKED) {
if (!ehci->reclaim && (stopped ||
time_after_eq(jiffies, qh->unlink_time)))
start_unlink_async(ehci, qh);
else
action = TIMER_ASYNC_SHRINK;
}
} }
if (action == TIMER_ASYNC_SHRINK) if (action == TIMER_ASYNC_SHRINK)
timer_action (ehci, TIMER_ASYNC_SHRINK); timer_action (ehci, TIMER_ASYNC_SHRINK);

View File

@ -62,7 +62,7 @@ stm_ehci_bus_resume(struct usb_hcd *hcd)
static const struct hc_driver ehci_stm_hc_driver = { static const struct hc_driver ehci_stm_hc_driver = {
.description = hcd_name, .description = hcd_name,
.product_desc = "st-ehci", .product_desc = "STMicroelectronics EHCI Host Controller",
.hcd_priv_size = sizeof(struct ehci_hcd), .hcd_priv_size = sizeof(struct ehci_hcd),
/* /*
@ -199,6 +199,7 @@ static struct platform_driver ehci_hcd_stm_driver = {
.shutdown = usb_hcd_platform_shutdown, .shutdown = usb_hcd_platform_shutdown,
.driver = { .driver = {
.name = "stm-ehci", .name = "stm-ehci",
.owner = THIS_MODULE,
}, },
}; };
@ -216,7 +217,7 @@ int stm_ehci_hcd_unregister(struct platform_device *dev)
ret = ehci_hcd_stm_remove(dev); ret = ehci_hcd_stm_remove(dev);
mutex_unlock(&stm_ehci_usb_mutex); mutex_unlock(&stm_ehci_usb_mutex);
if (ret) if (ret)
dgb_print("[STM][USB] Error on %s 0x%x\n", __func__, dev); dgb_print("[STM][USB] Error on %s %p\n", __func__, dev);
return ret; return ret;
} }
@ -230,7 +231,7 @@ int stm_ehci_hcd_register(struct platform_device *dev)
ret = ehci_hcd_stm_probe(dev); ret = ehci_hcd_stm_probe(dev);
mutex_unlock(&stm_ehci_usb_mutex); mutex_unlock(&stm_ehci_usb_mutex);
if (ret) if (ret)
dgb_print("[STM][USB] Error on %s 0x%x\n", __func__, dev); dgb_print("[STM][USB] Error on %s %p\n", __func__, dev);
return ret; return ret;
} }
EXPORT_SYMBOL(stm_ehci_hcd_register); EXPORT_SYMBOL(stm_ehci_hcd_register);

View File

@ -74,6 +74,7 @@ struct ehci_hcd { /* one per controller */
/* async schedule support */ /* async schedule support */
struct ehci_qh *async; struct ehci_qh *async;
struct ehci_qh *reclaim; struct ehci_qh *reclaim;
struct ehci_qh *qh_scan_next;
unsigned scanning : 1; unsigned scanning : 1;
/* periodic schedule support */ /* periodic schedule support */
@ -116,7 +117,6 @@ struct ehci_hcd { /* one per controller */
struct timer_list iaa_watchdog; struct timer_list iaa_watchdog;
struct timer_list watchdog; struct timer_list watchdog;
unsigned long actions; unsigned long actions;
unsigned stamp;
unsigned random_frame; unsigned random_frame;
unsigned long next_statechange; unsigned long next_statechange;
ktime_t last_periodic_enable; ktime_t last_periodic_enable;
@ -336,6 +336,7 @@ struct ehci_qh {
struct ehci_qh *reclaim; /* next to reclaim */ struct ehci_qh *reclaim; /* next to reclaim */
struct ehci_hcd *ehci; struct ehci_hcd *ehci;
unsigned long unlink_time;
/* /*
* Do NOT use atomic operations for QH refcounting. On some CPUs * Do NOT use atomic operations for QH refcounting. On some CPUs
@ -367,6 +368,7 @@ struct ehci_qh {
#define NO_FRAME ((unsigned short)~0) /* pick new start */ #define NO_FRAME ((unsigned short)~0) /* pick new start */
struct usb_device *dev; /* access to TT */ struct usb_device *dev; /* access to TT */
unsigned is_out:1; /* bulk or intr OUT */
unsigned clearing_tt:1; /* Clear-TT-Buf in progress */ unsigned clearing_tt:1; /* Clear-TT-Buf in progress */
}; };

View File

@ -1,7 +1,7 @@
/* /*
* Freescale QUICC Engine USB Host Controller Driver * Freescale QUICC Engine USB Host Controller Driver
* *
* Copyright (c) Freescale Semicondutor, Inc. 2006. * Copyright (c) Freescale Semicondutor, Inc. 2006, 2011.
* Shlomi Gridish <gridish@freescale.com> * Shlomi Gridish <gridish@freescale.com>
* Jerry Huang <Chang-Ming.Huang@freescale.com> * Jerry Huang <Chang-Ming.Huang@freescale.com>
* Copyright (c) Logic Product Development, Inc. 2007 * Copyright (c) Logic Product Development, Inc. 2007
@ -810,9 +810,11 @@ void fhci_queue_urb(struct fhci_hcd *fhci, struct urb *urb)
ed->dev_addr = usb_pipedevice(urb->pipe); ed->dev_addr = usb_pipedevice(urb->pipe);
ed->max_pkt_size = usb_maxpacket(urb->dev, urb->pipe, ed->max_pkt_size = usb_maxpacket(urb->dev, urb->pipe,
usb_pipeout(urb->pipe)); usb_pipeout(urb->pipe));
/* setup stage */
td = fhci_td_fill(fhci, urb, urb_priv, ed, cnt++, FHCI_TA_SETUP, td = fhci_td_fill(fhci, urb, urb_priv, ed, cnt++, FHCI_TA_SETUP,
USB_TD_TOGGLE_DATA0, urb->setup_packet, 8, 0, 0, true); USB_TD_TOGGLE_DATA0, urb->setup_packet, 8, 0, 0, true);
/* data stage */
if (data_len > 0) { if (data_len > 0) {
td = fhci_td_fill(fhci, urb, urb_priv, ed, cnt++, td = fhci_td_fill(fhci, urb, urb_priv, ed, cnt++,
usb_pipeout(urb->pipe) ? FHCI_TA_OUT : usb_pipeout(urb->pipe) ? FHCI_TA_OUT :
@ -820,9 +822,18 @@ void fhci_queue_urb(struct fhci_hcd *fhci, struct urb *urb)
USB_TD_TOGGLE_DATA1, data, data_len, 0, 0, USB_TD_TOGGLE_DATA1, data, data_len, 0, 0,
true); true);
} }
td = fhci_td_fill(fhci, urb, urb_priv, ed, cnt++,
usb_pipeout(urb->pipe) ? FHCI_TA_IN : FHCI_TA_OUT, /* status stage */
USB_TD_TOGGLE_DATA1, data, 0, 0, 0, true); if (data_len > 0)
td = fhci_td_fill(fhci, urb, urb_priv, ed, cnt++,
(usb_pipeout(urb->pipe) ? FHCI_TA_IN :
FHCI_TA_OUT),
USB_TD_TOGGLE_DATA1, data, 0, 0, 0, true);
else
td = fhci_td_fill(fhci, urb, urb_priv, ed, cnt++,
FHCI_TA_IN,
USB_TD_TOGGLE_DATA1, data, 0, 0, 0, true);
urb_state = US_CTRL_SETUP; urb_state = US_CTRL_SETUP;
break; break;
case FHCI_TF_ISO: case FHCI_TF_ISO:

View File

@ -71,20 +71,21 @@ static int stm_usb_boot(struct platform_device *pdev)
void *wrapper_base = usb_data->ahb2stbus_wrapper_glue_base; void *wrapper_base = usb_data->ahb2stbus_wrapper_glue_base;
void *protocol_base = usb_data->ahb2stbus_protocol_base; void *protocol_base = usb_data->ahb2stbus_protocol_base;
unsigned long reg, req_reg; unsigned long reg, req_reg;
unsigned long flags = pl_data->flags;
if (pl_data->flags &
(STM_PLAT_USB_FLAGS_STRAP_8BIT | if (flags & (STM_PLAT_USB_FLAGS_STRAP_8BIT |
STM_PLAT_USB_FLAGS_STRAP_16BIT)) { STM_PLAT_USB_FLAGS_STRAP_16BIT)) {
/* Set strap mode */ /* Set strap mode */
reg = readl(wrapper_base + AHB2STBUS_STRAP_OFFSET); reg = readl(wrapper_base + AHB2STBUS_STRAP_OFFSET);
if (pl_data->flags & STM_PLAT_USB_FLAGS_STRAP_16BIT) if (flags & STM_PLAT_USB_FLAGS_STRAP_16BIT)
reg |= AHB2STBUS_STRAP_16_BIT; reg |= AHB2STBUS_STRAP_16_BIT;
else else
reg &= ~AHB2STBUS_STRAP_16_BIT; reg &= ~AHB2STBUS_STRAP_16_BIT;
writel(reg, wrapper_base + AHB2STBUS_STRAP_OFFSET); writel(reg, wrapper_base + AHB2STBUS_STRAP_OFFSET);
} }
if (pl_data->flags & STM_PLAT_USB_FLAGS_STRAP_PLL) { if (flags & STM_PLAT_USB_FLAGS_STRAP_PLL) {
/* Start PLL */ /* Start PLL */
reg = readl(wrapper_base + AHB2STBUS_STRAP_OFFSET); reg = readl(wrapper_base + AHB2STBUS_STRAP_OFFSET);
writel(reg | AHB2STBUS_STRAP_PLL, writel(reg | AHB2STBUS_STRAP_PLL,
@ -95,7 +96,7 @@ static int stm_usb_boot(struct platform_device *pdev)
mdelay(30); mdelay(30);
} }
if (pl_data->flags & STM_PLAT_USB_FLAGS_OPC_MSGSIZE_CHUNKSIZE) { if (flags & STM_PLAT_USB_FLAGS_OPC_MSGSIZE_CHUNKSIZE) {
/* Set the STBus Opcode Config for load/store 32 */ /* Set the STBus Opcode Config for load/store 32 */
writel(AHB2STBUS_STBUS_OPC_32BIT, writel(AHB2STBUS_STBUS_OPC_32BIT,
protocol_base + AHB2STBUS_STBUS_OPC_OFFSET); protocol_base + AHB2STBUS_STBUS_OPC_OFFSET);
@ -109,7 +110,7 @@ static int stm_usb_boot(struct platform_device *pdev)
protocol_base + AHB2STBUS_CHUNKSIZE_OFFSET); protocol_base + AHB2STBUS_CHUNKSIZE_OFFSET);
} }
if (pl_data->flags & if (flags &
(STM_PLAT_USB_FLAGS_STBUS_CONFIG_THRESHOLD128 | (STM_PLAT_USB_FLAGS_STBUS_CONFIG_THRESHOLD128 |
STM_PLAT_USB_FLAGS_STBUS_CONFIG_THRESHOLD256)) { STM_PLAT_USB_FLAGS_STBUS_CONFIG_THRESHOLD256)) {
@ -134,24 +135,14 @@ static int stm_usb_boot(struct platform_device *pdev)
static int stm_usb_remove(struct platform_device *pdev) static int stm_usb_remove(struct platform_device *pdev)
{ {
struct resource *res;
struct device *dev = &pdev->dev;
struct drv_usb_data *dr_data = platform_get_drvdata(pdev); struct drv_usb_data *dr_data = platform_get_drvdata(pdev);
platform_device_unregister(dr_data->ehci_device);
platform_device_unregister(dr_data->ohci_device);
stm_device_power(dr_data->device_state, stm_device_power_off); stm_device_power(dr_data->device_state, stm_device_power_off);
stm_usb_clk_disable(dr_data); stm_usb_clk_disable(dr_data);
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "wrapper");
devm_release_mem_region(dev, res->start, resource_size(res));
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "protocol");
devm_release_mem_region(dev, res->start, resource_size(res));
if (dr_data->ehci_device)
platform_device_unregister(dr_data->ehci_device);
if (dr_data->ohci_device)
platform_device_unregister(dr_data->ohci_device);
return 0; return 0;
} }
@ -191,7 +182,7 @@ static int __init stm_usb_probe(struct platform_device *pdev)
struct drv_usb_data *dr_data; struct drv_usb_data *dr_data;
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct resource *res; struct resource *res;
int ret = 0, i; int i;
static char __initdata *usb_clks_n[USB_CLKS_NR] = { static char __initdata *usb_clks_n[USB_CLKS_NR] = {
[USB_48_CLK] = "usb_48_clk", [USB_48_CLK] = "usb_48_clk",
[USB_IC_CLK] = "usb_ic_clk", [USB_IC_CLK] = "usb_ic_clk",
@ -200,7 +191,7 @@ static int __init stm_usb_probe(struct platform_device *pdev)
resource_size_t len; resource_size_t len;
dgb_print("\n"); dgb_print("\n");
dr_data = kzalloc(sizeof(struct drv_usb_data), GFP_KERNEL); dr_data = devm_kzalloc(dev, sizeof(*dr_data), GFP_KERNEL);
if (!dr_data) if (!dr_data)
return -ENOMEM; return -ENOMEM;
@ -215,57 +206,47 @@ static int __init stm_usb_probe(struct platform_device *pdev)
stm_usb_clk_enable(dr_data); stm_usb_clk_enable(dr_data);
dr_data->device_state = devm_stm_device_init(&pdev->dev, dr_data->device_state =
plat_data->device_config); devm_stm_device_init(&pdev->dev, plat_data->device_config);
if (!dr_data->device_state) { if (!dr_data->device_state)
ret = -EBUSY; return -EBUSY;
goto err_0;
}
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "wrapper"); res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "wrapper");
if (!res) { if (!res)
ret = -ENXIO; return -ENXIO;
goto err_0;
}
len = resource_size(res); len = resource_size(res);
if (devm_request_mem_region(dev, res->start, len, pdev->name) < 0) { if (devm_request_mem_region(dev, res->start, len, pdev->name) < 0)
ret = -EBUSY; return -EBUSY;
goto err_0;
}
dr_data->ahb2stbus_wrapper_glue_base = dr_data->ahb2stbus_wrapper_glue_base =
devm_ioremap_nocache(dev, res->start, len); devm_ioremap_nocache(dev, res->start, len);
if (!dr_data->ahb2stbus_wrapper_glue_base) { if (!dr_data->ahb2stbus_wrapper_glue_base)
ret = -EFAULT; return -EFAULT;
goto err_1;
}
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "protocol"); res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "protocol");
if (!res) { if (!res)
ret = -ENXIO; return -ENXIO;
goto err_2;
}
len = resource_size(res); len = resource_size(res);
if (devm_request_mem_region(dev, res->start, len, pdev->name) < 0) { if (devm_request_mem_region(dev, res->start, len, pdev->name) < 0)
ret = -EBUSY; return -EBUSY;
goto err_2;
}
dr_data->ahb2stbus_protocol_base = dr_data->ahb2stbus_protocol_base =
devm_ioremap_nocache(dev, res->start, len); devm_ioremap_nocache(dev, res->start, len);
if (!dr_data->ahb2stbus_protocol_base) { if (!dr_data->ahb2stbus_protocol_base)
ret = -EFAULT; return -EFAULT;
goto err_3;
}
stm_usb_boot(pdev); stm_usb_boot(pdev);
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ehci"); res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ehci");
if (res) { if (res) {
dr_data->ehci_device = stm_usb_device_create("stm-ehci", dr_data->ehci_device = stm_usb_device_create("stm-ehci",
pdev->id, pdev); pdev->id, pdev);
if (IS_ERR(dr_data->ehci_device)) { if (IS_ERR(dr_data->ehci_device))
ret = (int)dr_data->ehci_device; return PTR_ERR(dr_data->ehci_device);
goto err_4;
}
} }
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ohci"); res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ohci");
@ -273,10 +254,8 @@ static int __init stm_usb_probe(struct platform_device *pdev)
dr_data->ohci_device = dr_data->ohci_device =
stm_usb_device_create("stm-ohci", pdev->id, pdev); stm_usb_device_create("stm-ohci", pdev->id, pdev);
if (IS_ERR(dr_data->ohci_device)) { if (IS_ERR(dr_data->ohci_device)) {
if (dr_data->ehci_device) platform_device_del(dr_data->ehci_device);
platform_device_del(dr_data->ehci_device); return PTR_ERR(dr_data->ohci_device);
ret = (int)dr_data->ohci_device;
goto err_4;
} }
} }
@ -285,21 +264,7 @@ static int __init stm_usb_probe(struct platform_device *pdev)
pm_suspend_ignore_children(&pdev->dev, 1); pm_suspend_ignore_children(&pdev->dev, 1);
pm_runtime_enable(&pdev->dev); pm_runtime_enable(&pdev->dev);
return ret; return 0;
err_4:
devm_iounmap(dev, dr_data->ahb2stbus_protocol_base);
err_3:
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "protocol");
devm_release_mem_region(dev, res->start, resource_size(res));
err_2:
devm_iounmap(dev, dr_data->ahb2stbus_wrapper_glue_base);
err_1:
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "wrapper");
devm_release_mem_region(dev, res->start, resource_size(res));
err_0:
kfree(dr_data);
return ret;
} }
static void stm_usb_shutdown(struct platform_device *pdev) static void stm_usb_shutdown(struct platform_device *pdev)

View File

@ -56,7 +56,7 @@ static int stm_ohci_bus_suspend(struct usb_hcd *hcd)
static const struct hc_driver ohci_st40_hc_driver = { static const struct hc_driver ohci_st40_hc_driver = {
.description = hcd_name, .description = hcd_name,
.product_desc = "stm-ohci", .product_desc = "STMicroelectronics OHCI Host Controller",
.hcd_priv_size = sizeof(struct ohci_hcd), .hcd_priv_size = sizeof(struct ohci_hcd),
/* generic hardware linkage */ /* generic hardware linkage */
@ -165,6 +165,7 @@ static struct platform_driver ohci_hcd_stm_driver = {
.shutdown = usb_hcd_platform_shutdown, .shutdown = usb_hcd_platform_shutdown,
.driver = { .driver = {
.name = "stm-ohci", .name = "stm-ohci",
.owner = THIS_MODULE,
}, },
}; };
@ -183,7 +184,7 @@ int stm_ohci_hcd_unregister(struct platform_device *dev)
ret = ohci_hcd_stm_remove(dev); ret = ohci_hcd_stm_remove(dev);
mutex_unlock(&stm_ohci_usb_mutex); mutex_unlock(&stm_ohci_usb_mutex);
if (ret) if (ret)
dgb_print("[STM][USB] Error on %s 0x%x\n", __func__, dev); dgb_print("[STM][USB] Error on %s %p\n", __func__, dev);
return ret; return ret;
} }
EXPORT_SYMBOL(stm_ohci_hcd_unregister); EXPORT_SYMBOL(stm_ohci_hcd_unregister);
@ -196,7 +197,7 @@ int stm_ohci_hcd_register(struct platform_device *dev)
ret = ohci_hcd_stm_probe(dev); ret = ohci_hcd_stm_probe(dev);
mutex_unlock(&stm_ohci_usb_mutex); mutex_unlock(&stm_ohci_usb_mutex);
if (ret) if (ret)
dgb_print("[STM][USB] Error on %s 0x%x\n", __func__, dev); dgb_print("[STM][USB] Error on %s %p\n", __func__, dev);
return ret; return ret;
} }

View File

@ -34,6 +34,8 @@
#define OHCI_INTRSTATUS 0x0c #define OHCI_INTRSTATUS 0x0c
#define OHCI_INTRENABLE 0x10 #define OHCI_INTRENABLE 0x10
#define OHCI_INTRDISABLE 0x14 #define OHCI_INTRDISABLE 0x14
#define OHCI_FMINTERVAL 0x34
#define OHCI_HCR (1 << 0) /* host controller reset */
#define OHCI_OCR (1 << 3) /* ownership change request */ #define OHCI_OCR (1 << 3) /* ownership change request */
#define OHCI_CTRL_RWC (1 << 9) /* remote wakeup connected */ #define OHCI_CTRL_RWC (1 << 9) /* remote wakeup connected */
#define OHCI_CTRL_IR (1 << 8) /* interrupt routing */ #define OHCI_CTRL_IR (1 << 8) /* interrupt routing */
@ -204,6 +206,32 @@ static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev)
/* reset controller, preserving RWC (and possibly IR) */ /* reset controller, preserving RWC (and possibly IR) */
writel(control & OHCI_CTRL_MASK, base + OHCI_CONTROL); writel(control & OHCI_CTRL_MASK, base + OHCI_CONTROL);
readl(base + OHCI_CONTROL);
/* Some NVIDIA controllers stop working if kept in RESET for too long */
if (pdev->vendor == PCI_VENDOR_ID_NVIDIA) {
u32 fminterval;
int cnt;
/* drive reset for at least 50 ms (7.1.7.5) */
msleep(50);
/* software reset of the controller, preserving HcFmInterval */
fminterval = readl(base + OHCI_FMINTERVAL);
writel(OHCI_HCR, base + OHCI_CMDSTATUS);
/* reset requires max 10 us delay */
for (cnt = 30; cnt > 0; --cnt) { /* ... allow extra time */
if ((readl(base + OHCI_CMDSTATUS) & OHCI_HCR) == 0)
break;
udelay(1);
}
writel(fminterval, base + OHCI_FMINTERVAL);
/* Now we're in the SUSPEND state with all devices reset
* and wakeups and interrupts disabled
*/
}
/* /*
* disable interrupts * disable interrupts
@ -390,12 +418,12 @@ static void __devinit quirk_usb_handoff_xhci(struct pci_dev *pdev)
void __iomem *op_reg_base; void __iomem *op_reg_base;
u32 val; u32 val;
int timeout; int timeout;
int len = pci_resource_len(pdev, 0);
if (!mmio_resource_enabled(pdev, 0)) if (!mmio_resource_enabled(pdev, 0))
return; return;
base = ioremap_nocache(pci_resource_start(pdev, 0), base = ioremap_nocache(pci_resource_start(pdev, 0), len);
pci_resource_len(pdev, 0));
if (base == NULL) if (base == NULL)
return; return;
@ -405,9 +433,17 @@ static void __devinit quirk_usb_handoff_xhci(struct pci_dev *pdev)
*/ */
ext_cap_offset = xhci_find_next_cap_offset(base, XHCI_HCC_PARAMS_OFFSET); ext_cap_offset = xhci_find_next_cap_offset(base, XHCI_HCC_PARAMS_OFFSET);
do { do {
if ((ext_cap_offset + sizeof(val)) > len) {
/* We're reading garbage from the controller */
dev_warn(&pdev->dev,
"xHCI controller failing to respond");
return;
}
if (!ext_cap_offset) if (!ext_cap_offset)
/* We've reached the end of the extended capabilities */ /* We've reached the end of the extended capabilities */
goto hc_init; goto hc_init;
val = readl(base + ext_cap_offset); val = readl(base + ext_cap_offset);
if (XHCI_EXT_CAPS_ID(val) == XHCI_EXT_CAPS_LEGACY) if (XHCI_EXT_CAPS_ID(val) == XHCI_EXT_CAPS_LEGACY)
break; break;
@ -416,7 +452,7 @@ static void __devinit quirk_usb_handoff_xhci(struct pci_dev *pdev)
/* If the BIOS owns the HC, signal that the OS wants it, and wait */ /* If the BIOS owns the HC, signal that the OS wants it, and wait */
if (val & XHCI_HC_BIOS_OWNED) { if (val & XHCI_HC_BIOS_OWNED) {
writel(val & XHCI_HC_OS_OWNED, base + ext_cap_offset); writel(val | XHCI_HC_OS_OWNED, base + ext_cap_offset);
/* Wait for 5 seconds with 10 microsecond polling interval */ /* Wait for 5 seconds with 10 microsecond polling interval */
timeout = handshake(base + ext_cap_offset, XHCI_HC_BIOS_OWNED, timeout = handshake(base + ext_cap_offset, XHCI_HC_BIOS_OWNED,
@ -430,9 +466,13 @@ static void __devinit quirk_usb_handoff_xhci(struct pci_dev *pdev)
} }
} }
/* Disable any BIOS SMIs */ val = readl(base + ext_cap_offset + XHCI_LEGACY_CONTROL_OFFSET);
writel(XHCI_LEGACY_DISABLE_SMI, /* Mask off (turn off) any enabled SMIs */
base + ext_cap_offset + XHCI_LEGACY_CONTROL_OFFSET); val &= XHCI_LEGACY_DISABLE_SMI;
/* Mask all SMI events bits, RW1C */
val |= XHCI_LEGACY_SMI_EVENTS;
/* Disable any BIOS SMIs and clear all SMI events*/
writel(val, base + ext_cap_offset + XHCI_LEGACY_CONTROL_OFFSET);
hc_init: hc_init:
op_reg_base = base + XHCI_HC_LENGTH(readl(base)); op_reg_base = base + XHCI_HC_LENGTH(readl(base));
@ -470,6 +510,22 @@ hc_init:
static void __devinit quirk_usb_early_handoff(struct pci_dev *pdev) static void __devinit quirk_usb_early_handoff(struct pci_dev *pdev)
{ {
/* Skip Netlogic mips SoC's internal PCI USB controller.
* This device does not need/support EHCI/OHCI handoff
*/
if (pdev->vendor == 0x184e) /* vendor Netlogic */
return;
if (pdev->class != PCI_CLASS_SERIAL_USB_UHCI &&
pdev->class != PCI_CLASS_SERIAL_USB_OHCI &&
pdev->class != PCI_CLASS_SERIAL_USB_EHCI &&
pdev->class != PCI_CLASS_SERIAL_USB_XHCI)
return;
if (pci_enable_device(pdev) < 0) {
dev_warn(&pdev->dev, "Can't enable PCI device, "
"BIOS handoff failed.\n");
return;
}
if (pdev->class == PCI_CLASS_SERIAL_USB_UHCI) if (pdev->class == PCI_CLASS_SERIAL_USB_UHCI)
quirk_usb_handoff_uhci(pdev); quirk_usb_handoff_uhci(pdev);
else if (pdev->class == PCI_CLASS_SERIAL_USB_OHCI) else if (pdev->class == PCI_CLASS_SERIAL_USB_OHCI)
@ -478,5 +534,6 @@ static void __devinit quirk_usb_early_handoff(struct pci_dev *pdev)
quirk_usb_disable_ehci(pdev); quirk_usb_disable_ehci(pdev);
else if (pdev->class == PCI_CLASS_SERIAL_USB_XHCI) else if (pdev->class == PCI_CLASS_SERIAL_USB_XHCI)
quirk_usb_handoff_xhci(pdev); quirk_usb_handoff_xhci(pdev);
pci_disable_device(pdev);
} }
DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, quirk_usb_early_handoff); DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, quirk_usb_early_handoff);

View File

@ -104,7 +104,7 @@ void qset_clear(struct whc *whc, struct whc_qset *qset)
{ {
qset->td_start = qset->td_end = qset->ntds = 0; qset->td_start = qset->td_end = qset->ntds = 0;
qset->qh.link = cpu_to_le32(QH_LINK_NTDS(8) | QH_LINK_T); qset->qh.link = cpu_to_le64(QH_LINK_NTDS(8) | QH_LINK_T);
qset->qh.status = qset->qh.status & QH_STATUS_SEQ_MASK; qset->qh.status = qset->qh.status & QH_STATUS_SEQ_MASK;
qset->qh.err_count = 0; qset->qh.err_count = 0;
qset->qh.scratch[0] = 0; qset->qh.scratch[0] = 0;

View File

@ -62,8 +62,9 @@
/* USB Legacy Support Control and Status Register - section 7.1.2 */ /* USB Legacy Support Control and Status Register - section 7.1.2 */
/* Add this offset, plus the value of xECP in HCCPARAMS to the base address */ /* Add this offset, plus the value of xECP in HCCPARAMS to the base address */
#define XHCI_LEGACY_CONTROL_OFFSET (0x04) #define XHCI_LEGACY_CONTROL_OFFSET (0x04)
/* bits 1:2, 5:12, and 17:19 need to be preserved; bits 21:28 should be zero */ /* bits 1:3, 5:12, and 17:19 need to be preserved; bits 21:28 should be zero */
#define XHCI_LEGACY_DISABLE_SMI ((0x3 << 1) + (0xff << 5) + (0x7 << 17)) #define XHCI_LEGACY_DISABLE_SMI ((0x7 << 1) + (0xff << 5) + (0x7 << 17))
#define XHCI_LEGACY_SMI_EVENTS (0x7 << 29)
/* command register values to disable interrupts and halt the HC */ /* command register values to disable interrupts and halt the HC */
/* start/stop HC execution - do not write unless HC is halted*/ /* start/stop HC execution - do not write unless HC is halted*/

View File

@ -150,7 +150,7 @@ int xhci_reset(struct xhci_hcd *xhci)
xhci_to_hcd(xhci)->state = HC_STATE_HALT; xhci_to_hcd(xhci)->state = HC_STATE_HALT;
ret = handshake(xhci, &xhci->op_regs->command, ret = handshake(xhci, &xhci->op_regs->command,
CMD_RESET, 0, 250 * 1000); CMD_RESET, 0, 10 * 1000 * 1000);
if (ret) if (ret)
return ret; return ret;
@ -979,6 +979,7 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
u32 added_ctxs; u32 added_ctxs;
unsigned int last_ctx; unsigned int last_ctx;
u32 new_add_flags, new_drop_flags, new_slot_info; u32 new_add_flags, new_drop_flags, new_slot_info;
struct xhci_virt_device *virt_dev;
int ret = 0; int ret = 0;
ret = xhci_check_args(hcd, udev, ep, 1, __func__); ret = xhci_check_args(hcd, udev, ep, 1, __func__);
@ -1007,11 +1008,25 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
return -EINVAL; return -EINVAL;
} }
in_ctx = xhci->devs[udev->slot_id]->in_ctx; virt_dev = xhci->devs[udev->slot_id];
out_ctx = xhci->devs[udev->slot_id]->out_ctx; in_ctx = virt_dev->in_ctx;
out_ctx = virt_dev->out_ctx;
ctrl_ctx = xhci_get_input_control_ctx(xhci, in_ctx); ctrl_ctx = xhci_get_input_control_ctx(xhci, in_ctx);
ep_index = xhci_get_endpoint_index(&ep->desc); ep_index = xhci_get_endpoint_index(&ep->desc);
ep_ctx = xhci_get_ep_ctx(xhci, out_ctx, ep_index); ep_ctx = xhci_get_ep_ctx(xhci, out_ctx, ep_index);
/* If this endpoint is already in use, and the upper layers are trying
* to add it again without dropping it, reject the addition.
*/
if (virt_dev->eps[ep_index].ring &&
!(le32_to_cpu(ctrl_ctx->drop_flags) &
xhci_get_endpoint_flag(&ep->desc))) {
xhci_warn(xhci, "Trying to add endpoint 0x%x "
"without dropping it.\n",
(unsigned int) ep->desc.bEndpointAddress);
return -EINVAL;
}
/* If the HCD has already noted the endpoint is enabled, /* If the HCD has already noted the endpoint is enabled,
* ignore this request. * ignore this request.
*/ */
@ -1026,8 +1041,7 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
* process context, not interrupt context (or so documenation * process context, not interrupt context (or so documenation
* for usb_set_interface() and usb_set_configuration() claim). * for usb_set_interface() and usb_set_configuration() claim).
*/ */
if (xhci_endpoint_init(xhci, xhci->devs[udev->slot_id], if (xhci_endpoint_init(xhci, virt_dev, udev, ep, GFP_NOIO) < 0) {
udev, ep, GFP_KERNEL) < 0) {
dev_dbg(&udev->dev, "%s - could not initialize ep %#x\n", dev_dbg(&udev->dev, "%s - could not initialize ep %#x\n",
__func__, ep->desc.bEndpointAddress); __func__, ep->desc.bEndpointAddress);
return -ENOMEM; return -ENOMEM;

View File

@ -110,18 +110,20 @@ void xhci_ring_free(struct xhci_hcd *xhci, struct xhci_ring *ring)
struct xhci_segment *seg; struct xhci_segment *seg;
struct xhci_segment *first_seg; struct xhci_segment *first_seg;
if (!ring || !ring->first_seg) if (!ring)
return; return;
first_seg = ring->first_seg; if (ring->first_seg) {
seg = first_seg->next; first_seg = ring->first_seg;
xhci_dbg(xhci, "Freeing ring at %p\n", ring); seg = first_seg->next;
while (seg != first_seg) { xhci_dbg(xhci, "Freeing ring at %p\n", ring);
struct xhci_segment *next = seg->next; while (seg != first_seg) {
xhci_segment_free(xhci, seg); struct xhci_segment *next = seg->next;
seg = next; xhci_segment_free(xhci, seg);
seg = next;
}
xhci_segment_free(xhci, first_seg);
ring->first_seg = NULL;
} }
xhci_segment_free(xhci, first_seg);
ring->first_seg = NULL;
kfree(ring); kfree(ring);
} }
@ -470,26 +472,42 @@ static unsigned int xhci_parse_exponent_interval(struct usb_device *udev,
} }
/* /*
* Convert bInterval expressed in frames (in 1-255 range) to exponent of * Convert bInterval expressed in microframes (in 1-255 range) to exponent of
* microframes, rounded down to nearest power of 2. * microframes, rounded down to nearest power of 2.
*/ */
static unsigned int xhci_parse_frame_interval(struct usb_device *udev, static unsigned int xhci_microframes_to_exponent(struct usb_device *udev,
struct usb_host_endpoint *ep) struct usb_host_endpoint *ep, unsigned int desc_interval,
unsigned int min_exponent, unsigned int max_exponent)
{ {
unsigned int interval; unsigned int interval;
interval = fls(8 * ep->desc.bInterval) - 1; interval = fls(desc_interval) - 1;
interval = clamp_val(interval, 3, 10); interval = clamp_val(interval, min_exponent, max_exponent);
if ((1 << interval) != 8 * ep->desc.bInterval) if ((1 << interval) != desc_interval)
dev_warn(&udev->dev, dev_warn(&udev->dev,
"ep %#x - rounding interval to %d microframes, ep desc says %d microframes\n", "ep %#x - rounding interval to %d microframes, ep desc says %d microframes\n",
ep->desc.bEndpointAddress, ep->desc.bEndpointAddress,
1 << interval, 1 << interval,
8 * ep->desc.bInterval); desc_interval);
return interval; return interval;
} }
static unsigned int xhci_parse_microframe_interval(struct usb_device *udev,
struct usb_host_endpoint *ep)
{
return xhci_microframes_to_exponent(udev, ep,
ep->desc.bInterval, 0, 15);
}
static unsigned int xhci_parse_frame_interval(struct usb_device *udev,
struct usb_host_endpoint *ep)
{
return xhci_microframes_to_exponent(udev, ep,
ep->desc.bInterval * 8, 3, 10);
}
/* Return the polling or NAK interval. /* Return the polling or NAK interval.
* *
* The polling interval is expressed in "microframes". If xHCI's Interval field * The polling interval is expressed in "microframes". If xHCI's Interval field
@ -508,7 +526,7 @@ static inline unsigned int xhci_get_endpoint_interval(struct usb_device *udev,
/* Max NAK rate */ /* Max NAK rate */
if (usb_endpoint_xfer_control(&ep->desc) || if (usb_endpoint_xfer_control(&ep->desc) ||
usb_endpoint_xfer_bulk(&ep->desc)) { usb_endpoint_xfer_bulk(&ep->desc)) {
interval = ep->desc.bInterval; interval = xhci_parse_microframe_interval(udev, ep);
break; break;
} }
/* Fall through - SS and HS isoc/int have same decoding */ /* Fall through - SS and HS isoc/int have same decoding */
@ -916,11 +934,6 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)
int i; int i;
/* Free the Event Ring Segment Table and the actual Event Ring */ /* Free the Event Ring Segment Table and the actual Event Ring */
if (xhci->ir_set) {
xhci_writel(xhci, 0, &xhci->ir_set->erst_size);
xhci_write_64(xhci, 0, &xhci->ir_set->erst_base);
xhci_write_64(xhci, 0, &xhci->ir_set->erst_dequeue);
}
size = sizeof(struct xhci_erst_entry)*(xhci->erst.num_entries); size = sizeof(struct xhci_erst_entry)*(xhci->erst.num_entries);
if (xhci->erst.entries) if (xhci->erst.entries)
pci_free_consistent(pdev, size, pci_free_consistent(pdev, size,
@ -932,7 +945,7 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)
xhci->event_ring = NULL; xhci->event_ring = NULL;
xhci_dbg(xhci, "Freed event ring\n"); xhci_dbg(xhci, "Freed event ring\n");
xhci_write_64(xhci, 0, &xhci->op_regs->cmd_ring); xhci->cmd_ring_reserved_trbs = 0;
if (xhci->cmd_ring) if (xhci->cmd_ring)
xhci_ring_free(xhci, xhci->cmd_ring); xhci_ring_free(xhci, xhci->cmd_ring);
xhci->cmd_ring = NULL; xhci->cmd_ring = NULL;
@ -951,7 +964,6 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)
xhci->device_pool = NULL; xhci->device_pool = NULL;
xhci_dbg(xhci, "Freed device context pool\n"); xhci_dbg(xhci, "Freed device context pool\n");
xhci_write_64(xhci, 0, &xhci->op_regs->dcbaa_ptr);
if (xhci->dcbaa) if (xhci->dcbaa)
pci_free_consistent(pdev, sizeof(*xhci->dcbaa), pci_free_consistent(pdev, sizeof(*xhci->dcbaa),
xhci->dcbaa, xhci->dcbaa->dma); xhci->dcbaa, xhci->dcbaa->dma);
@ -1128,6 +1140,8 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
fail: fail:
xhci_warn(xhci, "Couldn't initialize memory\n"); xhci_warn(xhci, "Couldn't initialize memory\n");
xhci_halt(xhci);
xhci_reset(xhci);
xhci_mem_cleanup(xhci); xhci_mem_cleanup(xhci);
return -ENOMEM; return -ENOMEM;
} }

View File

@ -54,8 +54,9 @@ static int isight_firmware_load(struct usb_interface *intf,
ptr = firmware->data; ptr = firmware->data;
buf[0] = 0x01;
if (usb_control_msg if (usb_control_msg
(dev, usb_sndctrlpipe(dev, 0), 0xa0, 0x40, 0xe600, 0, "\1", 1, (dev, usb_sndctrlpipe(dev, 0), 0xa0, 0x40, 0xe600, 0, buf, 1,
300) != 1) { 300) != 1) {
printk(KERN_ERR printk(KERN_ERR
"Failed to initialise isight firmware loader\n"); "Failed to initialise isight firmware loader\n");
@ -99,8 +100,9 @@ static int isight_firmware_load(struct usb_interface *intf,
} }
} }
buf[0] = 0x00;
if (usb_control_msg if (usb_control_msg
(dev, usb_sndctrlpipe(dev, 0), 0xa0, 0x40, 0xe600, 0, "\0", 1, (dev, usb_sndctrlpipe(dev, 0), 0xa0, 0x40, 0xe600, 0, buf, 1,
300) != 1) { 300) != 1) {
printk(KERN_ERR "isight firmware loading completion failed\n"); printk(KERN_ERR "isight firmware loading completion failed\n");
ret = -ENODEV; ret = -ENODEV;

View File

@ -24,7 +24,7 @@
#define VENDOR_ID 0x0fc5 #define VENDOR_ID 0x0fc5
#define PRODUCT_ID 0x1227 #define PRODUCT_ID 0x1227
#define MAXLEN 6 #define MAXLEN 8
/* table of devices that work with this driver */ /* table of devices that work with this driver */
static struct usb_device_id id_table[] = { static struct usb_device_id id_table[] = {

View File

@ -1041,7 +1041,7 @@ static int mon_bin_ioctl(struct inode *inode, struct file *file,
nevents = mon_bin_queued(rp); nevents = mon_bin_queued(rp);
sp = (struct mon_bin_stats __user *)arg; sp = (struct mon_bin_stats __user *)arg;
if (put_user(rp->cnt_lost, &sp->dropped)) if (put_user(ndropped, &sp->dropped))
return -EFAULT; return -EFAULT;
if (put_user(nevents, &sp->queued)) if (put_user(nevents, &sp->queued))
return -EFAULT; return -EFAULT;

View File

@ -94,6 +94,7 @@ static struct usb_device_id id_table [] = {
{ USB_DEVICE(0x10C4, 0x818B) }, /* AVIT Research USB to TTL */ { USB_DEVICE(0x10C4, 0x818B) }, /* AVIT Research USB to TTL */
{ USB_DEVICE(0x10C4, 0x819F) }, /* MJS USB Toslink Switcher */ { USB_DEVICE(0x10C4, 0x819F) }, /* MJS USB Toslink Switcher */
{ USB_DEVICE(0x10C4, 0x81A6) }, /* ThinkOptics WavIt */ { USB_DEVICE(0x10C4, 0x81A6) }, /* ThinkOptics WavIt */
{ USB_DEVICE(0x10C4, 0x81A9) }, /* Multiplex RC Interface */
{ USB_DEVICE(0x10C4, 0x81AC) }, /* MSD Dash Hawk */ { USB_DEVICE(0x10C4, 0x81AC) }, /* MSD Dash Hawk */
{ USB_DEVICE(0x10C4, 0x81AD) }, /* INSYS USB Modem */ { USB_DEVICE(0x10C4, 0x81AD) }, /* INSYS USB Modem */
{ USB_DEVICE(0x10C4, 0x81C8) }, /* Lipowsky Industrie Elektronik GmbH, Baby-JTAG */ { USB_DEVICE(0x10C4, 0x81C8) }, /* Lipowsky Industrie Elektronik GmbH, Baby-JTAG */
@ -135,10 +136,13 @@ static struct usb_device_id id_table [] = {
{ USB_DEVICE(0x16DC, 0x0011) }, /* W-IE-NE-R Plein & Baus GmbH RCM Remote Control for MARATON Power Supply */ { USB_DEVICE(0x16DC, 0x0011) }, /* W-IE-NE-R Plein & Baus GmbH RCM Remote Control for MARATON Power Supply */
{ USB_DEVICE(0x16DC, 0x0012) }, /* W-IE-NE-R Plein & Baus GmbH MPOD Multi Channel Power Supply */ { USB_DEVICE(0x16DC, 0x0012) }, /* W-IE-NE-R Plein & Baus GmbH MPOD Multi Channel Power Supply */
{ USB_DEVICE(0x16DC, 0x0015) }, /* W-IE-NE-R Plein & Baus GmbH CML Control, Monitoring and Data Logger */ { USB_DEVICE(0x16DC, 0x0015) }, /* W-IE-NE-R Plein & Baus GmbH CML Control, Monitoring and Data Logger */
{ USB_DEVICE(0x17A8, 0x0001) }, /* Kamstrup Optical Eye/3-wire */
{ USB_DEVICE(0x17A8, 0x0005) }, /* Kamstrup M-Bus Master MultiPort 250D */
{ USB_DEVICE(0x17F4, 0xAAAA) }, /* Wavesense Jazz blood glucose meter */ { USB_DEVICE(0x17F4, 0xAAAA) }, /* Wavesense Jazz blood glucose meter */
{ USB_DEVICE(0x1843, 0x0200) }, /* Vaisala USB Instrument Cable */ { USB_DEVICE(0x1843, 0x0200) }, /* Vaisala USB Instrument Cable */
{ USB_DEVICE(0x18EF, 0xE00F) }, /* ELV USB-I2C-Interface */ { USB_DEVICE(0x18EF, 0xE00F) }, /* ELV USB-I2C-Interface */
{ USB_DEVICE(0x1BE3, 0x07A6) }, /* WAGO 750-923 USB Service Cable */ { USB_DEVICE(0x1BE3, 0x07A6) }, /* WAGO 750-923 USB Service Cable */
{ USB_DEVICE(0x3195, 0xF190) }, /* Link Instruments MSO-19 */
{ USB_DEVICE(0x413C, 0x9500) }, /* DW700 GPS USB interface */ { USB_DEVICE(0x413C, 0x9500) }, /* DW700 GPS USB interface */
{ } /* Terminating Entry */ { } /* Terminating Entry */
}; };
@ -359,8 +363,8 @@ static inline int cp210x_set_config_single(struct usb_serial_port *port,
* Quantises the baud rate as per AN205 Table 1 * Quantises the baud rate as per AN205 Table 1
*/ */
static unsigned int cp210x_quantise_baudrate(unsigned int baud) { static unsigned int cp210x_quantise_baudrate(unsigned int baud) {
if (baud <= 56) baud = 0; if (baud <= 300)
else if (baud <= 300) baud = 300; baud = 300;
else if (baud <= 600) baud = 600; else if (baud <= 600) baud = 600;
else if (baud <= 1200) baud = 1200; else if (baud <= 1200) baud = 1200;
else if (baud <= 1800) baud = 1800; else if (baud <= 1800) baud = 1800;

View File

@ -105,6 +105,7 @@ static int ftdi_jtag_probe(struct usb_serial *serial);
static int ftdi_mtxorb_hack_setup(struct usb_serial *serial); static int ftdi_mtxorb_hack_setup(struct usb_serial *serial);
static int ftdi_NDI_device_setup(struct usb_serial *serial); static int ftdi_NDI_device_setup(struct usb_serial *serial);
static int ftdi_stmclite_probe(struct usb_serial *serial); static int ftdi_stmclite_probe(struct usb_serial *serial);
static int ftdi_8u2232c_probe(struct usb_serial *serial);
static void ftdi_USB_UIRT_setup(struct ftdi_private *priv); static void ftdi_USB_UIRT_setup(struct ftdi_private *priv);
static void ftdi_HE_TIRA1_setup(struct ftdi_private *priv); static void ftdi_HE_TIRA1_setup(struct ftdi_private *priv);
@ -132,6 +133,10 @@ static struct ftdi_sio_quirk ftdi_stmclite_quirk = {
.probe = ftdi_stmclite_probe, .probe = ftdi_stmclite_probe,
}; };
static struct ftdi_sio_quirk ftdi_8u2232c_quirk = {
.probe = ftdi_8u2232c_probe,
};
/* /*
* The 8U232AM has the same API as the sio except for: * The 8U232AM has the same API as the sio except for:
* - it can support MUCH higher baudrates; up to: * - it can support MUCH higher baudrates; up to:
@ -155,6 +160,7 @@ static struct ftdi_sio_quirk ftdi_stmclite_quirk = {
* /sys/bus/usb/ftdi_sio/new_id, then send patch/report! * /sys/bus/usb/ftdi_sio/new_id, then send patch/report!
*/ */
static struct usb_device_id id_table_combined [] = { static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(FTDI_VID, FTDI_ZEITCONTROL_TAGTRACE_MIFARE_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_CTI_MINI_PID) }, { USB_DEVICE(FTDI_VID, FTDI_CTI_MINI_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_CTI_NANO_PID) }, { USB_DEVICE(FTDI_VID, FTDI_CTI_NANO_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_AMC232_PID) }, { USB_DEVICE(FTDI_VID, FTDI_AMC232_PID) },
@ -181,7 +187,8 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(FTDI_VID, FTDI_8U232AM_PID) }, { USB_DEVICE(FTDI_VID, FTDI_8U232AM_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_8U232AM_ALT_PID) }, { USB_DEVICE(FTDI_VID, FTDI_8U232AM_ALT_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_232RL_PID) }, { USB_DEVICE(FTDI_VID, FTDI_232RL_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_8U2232C_PID) }, { USB_DEVICE(FTDI_VID, FTDI_8U2232C_PID) ,
.driver_info = (kernel_ulong_t)&ftdi_8u2232c_quirk },
{ USB_DEVICE(FTDI_VID, FTDI_4232H_PID) }, { USB_DEVICE(FTDI_VID, FTDI_4232H_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_MICRO_CHAMELEON_PID) }, { USB_DEVICE(FTDI_VID, FTDI_MICRO_CHAMELEON_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_RELAIS_PID) }, { USB_DEVICE(FTDI_VID, FTDI_RELAIS_PID) },
@ -203,6 +210,8 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(FTDI_VID, FTDI_XF_640_PID) }, { USB_DEVICE(FTDI_VID, FTDI_XF_640_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_XF_642_PID) }, { USB_DEVICE(FTDI_VID, FTDI_XF_642_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_DSS20_PID) }, { USB_DEVICE(FTDI_VID, FTDI_DSS20_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_URBAN_0_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_URBAN_1_PID) },
{ USB_DEVICE(FTDI_NF_RIC_VID, FTDI_NF_RIC_PID) }, { USB_DEVICE(FTDI_NF_RIC_VID, FTDI_NF_RIC_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_VNHCPCUSB_D_PID) }, { USB_DEVICE(FTDI_VID, FTDI_VNHCPCUSB_D_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_MTXORB_0_PID) }, { USB_DEVICE(FTDI_VID, FTDI_MTXORB_0_PID) },
@ -730,6 +739,7 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(TML_VID, TML_USB_SERIAL_PID) }, { USB_DEVICE(TML_VID, TML_USB_SERIAL_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_ELSTER_UNICOM_PID) }, { USB_DEVICE(FTDI_VID, FTDI_ELSTER_UNICOM_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_PROPOX_JTAGCABLEII_PID) }, { USB_DEVICE(FTDI_VID, FTDI_PROPOX_JTAGCABLEII_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_PROPOX_ISPCABLEIII_PID) },
{ USB_DEVICE(OLIMEX_VID, OLIMEX_ARM_USB_OCD_PID), { USB_DEVICE(OLIMEX_VID, OLIMEX_ARM_USB_OCD_PID),
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
{ USB_DEVICE(FIC_VID, FIC_NEO1973_DEBUG_PID), { USB_DEVICE(FIC_VID, FIC_NEO1973_DEBUG_PID),
@ -740,6 +750,8 @@ static struct usb_device_id id_table_combined [] = {
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
{ USB_DEVICE(FTDI_VID, LMI_LM3S_EVAL_BOARD_PID), { USB_DEVICE(FTDI_VID, LMI_LM3S_EVAL_BOARD_PID),
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
{ USB_DEVICE(FTDI_VID, LMI_LM3S_ICDI_BOARD_PID),
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
{ USB_DEVICE(FTDI_VID, FTDI_TURTELIZER_PID), { USB_DEVICE(FTDI_VID, FTDI_TURTELIZER_PID),
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
{ USB_DEVICE(RATOC_VENDOR_ID, RATOC_PRODUCT_ID_USB60F) }, { USB_DEVICE(RATOC_VENDOR_ID, RATOC_PRODUCT_ID_USB60F) },
@ -786,6 +798,7 @@ static struct usb_device_id id_table_combined [] = {
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
{ USB_DEVICE(ADI_VID, ADI_GNICEPLUS_PID), { USB_DEVICE(ADI_VID, ADI_GNICEPLUS_PID),
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
{ USB_DEVICE(HORNBY_VID, HORNBY_ELITE_PID) },
{ USB_DEVICE(JETI_VID, JETI_SPC1201_PID) }, { USB_DEVICE(JETI_VID, JETI_SPC1201_PID) },
{ USB_DEVICE(MARVELL_VID, MARVELL_SHEEVAPLUG_PID), { USB_DEVICE(MARVELL_VID, MARVELL_SHEEVAPLUG_PID),
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
@ -794,6 +807,8 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(BAYER_VID, BAYER_CONTOUR_CABLE_PID) }, { USB_DEVICE(BAYER_VID, BAYER_CONTOUR_CABLE_PID) },
{ USB_DEVICE(FTDI_VID, MARVELL_OPENRD_PID), { USB_DEVICE(FTDI_VID, MARVELL_OPENRD_PID),
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
{ USB_DEVICE(FTDI_VID, TI_XDS100V2_PID),
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
{ USB_DEVICE(FTDI_VID, HAMEG_HO820_PID) }, { USB_DEVICE(FTDI_VID, HAMEG_HO820_PID) },
{ USB_DEVICE(FTDI_VID, HAMEG_HO720_PID) }, { USB_DEVICE(FTDI_VID, HAMEG_HO720_PID) },
{ USB_DEVICE(FTDI_VID, HAMEG_HO730_PID) }, { USB_DEVICE(FTDI_VID, HAMEG_HO730_PID) },
@ -825,11 +840,13 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(FTDI_VID, FTDI_SCIENCESCOPE_LOGBOOKML_PID) }, { USB_DEVICE(FTDI_VID, FTDI_SCIENCESCOPE_LOGBOOKML_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_SCIENCESCOPE_LS_LOGBOOK_PID) }, { USB_DEVICE(FTDI_VID, FTDI_SCIENCESCOPE_LS_LOGBOOK_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_SCIENCESCOPE_HS_LOGBOOK_PID) }, { USB_DEVICE(FTDI_VID, FTDI_SCIENCESCOPE_HS_LOGBOOK_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_CINTERION_MC55I_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_DOTEC_PID) }, { USB_DEVICE(FTDI_VID, FTDI_DOTEC_PID) },
{ USB_DEVICE(QIHARDWARE_VID, MILKYMISTONE_JTAGSERIAL_PID), { USB_DEVICE(QIHARDWARE_VID, MILKYMISTONE_JTAGSERIAL_PID),
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
{ USB_DEVICE(ST_VID, ST_STMCLT1030_PID), { USB_DEVICE(ST_VID, ST_STMCLT1030_PID),
.driver_info = (kernel_ulong_t)&ftdi_stmclite_quirk }, .driver_info = (kernel_ulong_t)&ftdi_stmclite_quirk },
{ USB_DEVICE(FTDI_VID, FTDI_RF_R106) },
{ }, /* Optional parameter entry */ { }, /* Optional parameter entry */
{ } /* Terminating entry */ { } /* Terminating entry */
}; };
@ -1339,8 +1356,7 @@ static int set_serial_info(struct tty_struct *tty,
goto check_and_exit; goto check_and_exit;
} }
if ((new_serial.baud_base != priv->baud_base) && if (new_serial.baud_base != priv->baud_base) {
(new_serial.baud_base < 9600)) {
unlock_kernel(); unlock_kernel();
return -EINVAL; return -EINVAL;
} }
@ -1762,6 +1778,19 @@ static int ftdi_jtag_probe(struct usb_serial *serial)
return 0; return 0;
} }
static int ftdi_8u2232c_probe(struct usb_serial *serial)
{
struct usb_device *udev = serial->dev;
dbg("%s", __func__);
if ((udev->manufacturer) &&
(strcmp(udev->manufacturer, "CALAO Systems") == 0))
return ftdi_jtag_probe(serial);
return 0;
}
/* /*
* First and second port on STMCLiteadaptors is reserved for JTAG interface * First and second port on STMCLiteadaptors is reserved for JTAG interface
* and the forth port for pio * and the forth port for pio
@ -1841,6 +1870,7 @@ static int ftdi_submit_read_urb(struct usb_serial_port *port, gfp_t mem_flags)
static int ftdi_open(struct tty_struct *tty, struct usb_serial_port *port) static int ftdi_open(struct tty_struct *tty, struct usb_serial_port *port)
{ /* ftdi_open */ { /* ftdi_open */
struct ktermios dummy;
struct usb_device *dev = port->serial->dev; struct usb_device *dev = port->serial->dev;
struct ftdi_private *priv = usb_get_serial_port_data(port); struct ftdi_private *priv = usb_get_serial_port_data(port);
unsigned long flags; unsigned long flags;
@ -1868,8 +1898,10 @@ static int ftdi_open(struct tty_struct *tty, struct usb_serial_port *port)
This is same behaviour as serial.c/rs_open() - Kuba */ This is same behaviour as serial.c/rs_open() - Kuba */
/* ftdi_set_termios will send usb control messages */ /* ftdi_set_termios will send usb control messages */
if (tty) if (tty) {
ftdi_set_termios(tty, port, tty->termios); memset(&dummy, 0, sizeof(dummy));
ftdi_set_termios(tty, port, &dummy);
}
/* Not throttled */ /* Not throttled */
spin_lock_irqsave(&port->lock, flags); spin_lock_irqsave(&port->lock, flags);
@ -2332,13 +2364,23 @@ static void ftdi_set_termios(struct tty_struct *tty,
cflag = termios->c_cflag; cflag = termios->c_cflag;
/* FIXME -For this cut I don't care if the line is really changing or if (!old_termios)
not - so just do the change regardless - should be able to goto no_skip;
compare old_termios and tty->termios */
if (old_termios->c_cflag == termios->c_cflag
&& old_termios->c_ispeed == termios->c_ispeed
&& old_termios->c_ospeed == termios->c_ospeed)
goto no_c_cflag_changes;
/* NOTE These routines can get interrupted by /* NOTE These routines can get interrupted by
ftdi_sio_read_bulk_callback - need to examine what this means - ftdi_sio_read_bulk_callback - need to examine what this means -
don't see any problems yet */ don't see any problems yet */
if ((old_termios->c_cflag & (CSIZE|PARODD|PARENB|CMSPAR|CSTOPB)) ==
(termios->c_cflag & (CSIZE|PARODD|PARENB|CMSPAR|CSTOPB)))
goto no_data_parity_stop_changes;
no_skip:
/* Set number of data bits, parity, stop bits */ /* Set number of data bits, parity, stop bits */
termios->c_cflag &= ~CMSPAR; termios->c_cflag &= ~CMSPAR;
@ -2375,6 +2417,7 @@ static void ftdi_set_termios(struct tty_struct *tty,
} }
/* Now do the baudrate */ /* Now do the baudrate */
no_data_parity_stop_changes:
if ((cflag & CBAUD) == B0) { if ((cflag & CBAUD) == B0) {
/* Disable flow control */ /* Disable flow control */
if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
@ -2400,6 +2443,7 @@ static void ftdi_set_termios(struct tty_struct *tty,
/* Set flow control */ /* Set flow control */
/* Note device also supports DTR/CD (ugh) and Xon/Xoff in hardware */ /* Note device also supports DTR/CD (ugh) and Xon/Xoff in hardware */
no_c_cflag_changes:
if (cflag & CRTSCTS) { if (cflag & CRTSCTS) {
dbg("%s Setting to CRTSCTS flow control", __func__); dbg("%s Setting to CRTSCTS flow control", __func__);
if (usb_control_msg(dev, if (usb_control_msg(dev,

View File

@ -38,6 +38,13 @@
/* www.candapter.com Ewert Energy Systems CANdapter device */ /* www.candapter.com Ewert Energy Systems CANdapter device */
#define FTDI_CANDAPTER_PID 0x9F80 /* Product Id */ #define FTDI_CANDAPTER_PID 0x9F80 /* Product Id */
/*
* Texas Instruments XDS100v2 JTAG / BeagleBone A3
* http://processors.wiki.ti.com/index.php/XDS100
* http://beagleboard.org/bone
*/
#define TI_XDS100V2_PID 0xa6d0
#define FTDI_NXTCAM_PID 0xABB8 /* NXTCam for Mindstorms NXT */ #define FTDI_NXTCAM_PID 0xABB8 /* NXTCam for Mindstorms NXT */
/* US Interface Navigator (http://www.usinterface.com/) */ /* US Interface Navigator (http://www.usinterface.com/) */
@ -53,6 +60,7 @@
/* FTDI 2332C Dual channel device, side A=245 FIFO (JTAG), Side B=RS232 UART */ /* FTDI 2332C Dual channel device, side A=245 FIFO (JTAG), Side B=RS232 UART */
#define LMI_LM3S_DEVEL_BOARD_PID 0xbcd8 #define LMI_LM3S_DEVEL_BOARD_PID 0xbcd8
#define LMI_LM3S_EVAL_BOARD_PID 0xbcd9 #define LMI_LM3S_EVAL_BOARD_PID 0xbcd9
#define LMI_LM3S_ICDI_BOARD_PID 0xbcda
#define FTDI_TURTELIZER_PID 0xBDC8 /* JTAG/RS-232 adapter by egnite GmBH */ #define FTDI_TURTELIZER_PID 0xBDC8 /* JTAG/RS-232 adapter by egnite GmBH */
@ -110,6 +118,7 @@
/* Propox devices */ /* Propox devices */
#define FTDI_PROPOX_JTAGCABLEII_PID 0xD738 #define FTDI_PROPOX_JTAGCABLEII_PID 0xD738
#define FTDI_PROPOX_ISPCABLEIII_PID 0xD739
/* Lenz LI-USB Computer Interface. */ /* Lenz LI-USB Computer Interface. */
#define FTDI_LENZ_LIUSB_PID 0xD780 #define FTDI_LENZ_LIUSB_PID 0xD780
@ -419,9 +428,11 @@
#define PROTEGO_SPECIAL_4 0xFC73 /* special/unknown device */ #define PROTEGO_SPECIAL_4 0xFC73 /* special/unknown device */
/* /*
* DSS-20 Sync Station for Sony Ericsson P800 * Sony Ericsson product ids
*/ */
#define FTDI_DSS20_PID 0xFC82 #define FTDI_DSS20_PID 0xFC82 /* DSS-20 Sync Station for Sony Ericsson P800 */
#define FTDI_URBAN_0_PID 0xFC8A /* Sony Ericsson Urban, uart #0 */
#define FTDI_URBAN_1_PID 0xFC8B /* Sony Ericsson Urban, uart #1 */
/* www.irtrans.de device */ /* www.irtrans.de device */
#define FTDI_IRTRANS_PID 0xFC60 /* Product Id */ #define FTDI_IRTRANS_PID 0xFC60 /* Product Id */
@ -519,6 +530,12 @@
#define ADI_GNICE_PID 0xF000 #define ADI_GNICE_PID 0xF000
#define ADI_GNICEPLUS_PID 0xF001 #define ADI_GNICEPLUS_PID 0xF001
/*
* Hornby Elite
*/
#define HORNBY_VID 0x04D8
#define HORNBY_ELITE_PID 0x000A
/* /*
* RATOC REX-USB60F * RATOC REX-USB60F
*/ */
@ -1164,4 +1181,21 @@
/* USB-Nano-485*/ /* USB-Nano-485*/
#define FTDI_CTI_NANO_PID 0xF60B #define FTDI_CTI_NANO_PID 0xF60B
/*
* ZeitControl cardsystems GmbH rfid-readers http://zeitconrol.de
*/
/* TagTracer MIFARE*/
#define FTDI_ZEITCONTROL_TAGTRACE_MIFARE_PID 0xF7C0
/*
* Rainforest Automation
*/
/* ZigBee controller */
#define FTDI_RF_R106 0x8A28
/*
* Product: HCP HIT GPRS modem
* Manufacturer: HCP d.o.o.
* ATI command output: Cinterion MC55i
*/
#define FTDI_CINTERION_MC55I_PID 0xA951

View File

@ -974,10 +974,7 @@ static void garmin_close(struct usb_serial_port *port)
if (!serial) if (!serial)
return; return;
mutex_lock(&port->serial->disc_mutex); garmin_clear(garmin_data_p);
if (!port->serial->disconnected)
garmin_clear(garmin_data_p);
/* shutdown our urbs */ /* shutdown our urbs */
usb_kill_urb(port->read_urb); usb_kill_urb(port->read_urb);
@ -986,8 +983,6 @@ static void garmin_close(struct usb_serial_port *port)
/* keep reset state so we know that we must start a new session */ /* keep reset state so we know that we must start a new session */
if (garmin_data_p->state != STATE_RESET) if (garmin_data_p->state != STATE_RESET)
garmin_data_p->state = STATE_DISCONNECTED; garmin_data_p->state = STATE_DISCONNECTED;
mutex_unlock(&port->serial->disc_mutex);
} }

View File

@ -574,6 +574,9 @@ static void chase_port(struct edgeport_port *port, unsigned long timeout,
wait_queue_t wait; wait_queue_t wait;
unsigned long flags; unsigned long flags;
if (!tty)
return;
if (!timeout) if (!timeout)
timeout = (HZ * EDGE_CLOSING_WAIT)/100; timeout = (HZ * EDGE_CLOSING_WAIT)/100;
@ -2664,15 +2667,7 @@ cleanup:
static void edge_disconnect(struct usb_serial *serial) static void edge_disconnect(struct usb_serial *serial)
{ {
int i;
struct edgeport_port *edge_port;
dbg("%s", __func__); dbg("%s", __func__);
for (i = 0; i < serial->num_ports; ++i) {
edge_port = usb_get_serial_port_data(serial->port[i]);
edge_remove_sysfs_attrs(edge_port->port);
}
} }
static void edge_release(struct usb_serial *serial) static void edge_release(struct usb_serial *serial)
@ -2927,6 +2922,7 @@ static struct usb_serial_driver edgeport_1port_device = {
.disconnect = edge_disconnect, .disconnect = edge_disconnect,
.release = edge_release, .release = edge_release,
.port_probe = edge_create_sysfs_attrs, .port_probe = edge_create_sysfs_attrs,
.port_remove = edge_remove_sysfs_attrs,
.ioctl = edge_ioctl, .ioctl = edge_ioctl,
.set_termios = edge_set_termios, .set_termios = edge_set_termios,
.tiocmget = edge_tiocmget, .tiocmget = edge_tiocmget,
@ -2957,6 +2953,7 @@ static struct usb_serial_driver edgeport_2port_device = {
.disconnect = edge_disconnect, .disconnect = edge_disconnect,
.release = edge_release, .release = edge_release,
.port_probe = edge_create_sysfs_attrs, .port_probe = edge_create_sysfs_attrs,
.port_remove = edge_remove_sysfs_attrs,
.ioctl = edge_ioctl, .ioctl = edge_ioctl,
.set_termios = edge_set_termios, .set_termios = edge_set_termios,
.tiocmget = edge_tiocmget, .tiocmget = edge_tiocmget,

View File

@ -1181,9 +1181,12 @@ static int mos7840_chars_in_buffer(struct tty_struct *tty)
} }
spin_lock_irqsave(&mos7840_port->pool_lock, flags); spin_lock_irqsave(&mos7840_port->pool_lock, flags);
for (i = 0; i < NUM_URBS; ++i) for (i = 0; i < NUM_URBS; ++i) {
if (mos7840_port->busy[i]) if (mos7840_port->busy[i]) {
chars += URB_TRANSFER_BUFFER_SIZE; struct urb *urb = mos7840_port->write_urb_pool[i];
chars += urb->transfer_buffer_length;
}
}
spin_unlock_irqrestore(&mos7840_port->pool_lock, flags); spin_unlock_irqrestore(&mos7840_port->pool_lock, flags);
dbg("%s - returns %d", __func__, chars); dbg("%s - returns %d", __func__, chars);
return chars; return chars;
@ -2566,7 +2569,6 @@ error:
kfree(mos7840_port->ctrl_buf); kfree(mos7840_port->ctrl_buf);
usb_free_urb(mos7840_port->control_urb); usb_free_urb(mos7840_port->control_urb);
kfree(mos7840_port); kfree(mos7840_port);
serial->port[i] = NULL;
} }
return status; return status;
} }
@ -2633,6 +2635,7 @@ static void mos7840_release(struct usb_serial *serial)
mos7840_port = mos7840_get_port_private(serial->port[i]); mos7840_port = mos7840_get_port_private(serial->port[i]);
dbg("mos7840_port %d = %p", i, mos7840_port); dbg("mos7840_port %d = %p", i, mos7840_port);
if (mos7840_port) { if (mos7840_port) {
usb_free_urb(mos7840_port->control_urb);
kfree(mos7840_port->ctrl_buf); kfree(mos7840_port->ctrl_buf);
kfree(mos7840_port->dr); kfree(mos7840_port->dr);
kfree(mos7840_port); kfree(mos7840_port);

View File

@ -317,7 +317,7 @@ static int omninet_write_room(struct tty_struct *tty)
int room = 0; /* Default: no room */ int room = 0; /* Default: no room */
/* FIXME: no consistent locking for write_urb_busy */ /* FIXME: no consistent locking for write_urb_busy */
if (wport->write_urb_busy) if (!wport->write_urb_busy)
room = wport->bulk_out_size - OMNINET_HEADERLEN; room = wport->bulk_out_size - OMNINET_HEADERLEN;
dbg("%s - returns %d", __func__, room); dbg("%s - returns %d", __func__, room);

View File

@ -618,6 +618,7 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE(KYOCERA_VENDOR_ID, KYOCERA_PRODUCT_KPC680) }, { USB_DEVICE(KYOCERA_VENDOR_ID, KYOCERA_PRODUCT_KPC680) },
{ USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6000)}, /* ZTE AC8700 */ { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6000)}, /* ZTE AC8700 */
{ USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6613)}, /* Onda H600/ZTE MF330 */ { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6613)}, /* Onda H600/ZTE MF330 */
{ USB_DEVICE(QUALCOMM_VENDOR_ID, 0x9000)}, /* SIMCom SIM5218 */
{ USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6280) }, /* BP3-USB & BP3-EXT HSDPA */ { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6280) }, /* BP3-USB & BP3-EXT HSDPA */
{ USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6008) }, { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6008) },
{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_UC864E) }, { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_UC864E) },

View File

@ -100,6 +100,8 @@ static struct usb_device_id id_table [] = {
{ USB_DEVICE(ZEAGLE_VENDOR_ID, ZEAGLE_N2ITION3_PRODUCT_ID) }, { USB_DEVICE(ZEAGLE_VENDOR_ID, ZEAGLE_N2ITION3_PRODUCT_ID) },
{ USB_DEVICE(SONY_VENDOR_ID, SONY_QN3USB_PRODUCT_ID) }, { USB_DEVICE(SONY_VENDOR_ID, SONY_QN3USB_PRODUCT_ID) },
{ USB_DEVICE(SANWA_VENDOR_ID, SANWA_PRODUCT_ID) }, { USB_DEVICE(SANWA_VENDOR_ID, SANWA_PRODUCT_ID) },
{ USB_DEVICE(ADLINK_VENDOR_ID, ADLINK_ND6530_PRODUCT_ID) },
{ USB_DEVICE(SMART_VENDOR_ID, SMART_PRODUCT_ID) },
{ } /* Terminating entry */ { } /* Terminating entry */
}; };
@ -615,10 +617,28 @@ static void pl2303_set_termios(struct tty_struct *tty,
baud = 6000000; baud = 6000000;
} }
dbg("%s - baud set = %d", __func__, baud); dbg("%s - baud set = %d", __func__, baud);
buf[0] = baud & 0xff; if (baud <= 115200) {
buf[1] = (baud >> 8) & 0xff; buf[0] = baud & 0xff;
buf[2] = (baud >> 16) & 0xff; buf[1] = (baud >> 8) & 0xff;
buf[3] = (baud >> 24) & 0xff; buf[2] = (baud >> 16) & 0xff;
buf[3] = (baud >> 24) & 0xff;
} else {
/* apparently the formula for higher speeds is:
* baudrate = 12M * 32 / (2^buf[1]) / buf[0]
*/
unsigned tmp = 12*1000*1000*32 / baud;
buf[3] = 0x80;
buf[2] = 0;
buf[1] = (tmp >= 256);
while (tmp >= 256) {
tmp >>= 2;
buf[1] <<= 1;
}
if (tmp > 256) {
tmp %= 256;
}
buf[0] = tmp;
}
} }
/* For reference buf[4]=0 is 1 stop bits */ /* For reference buf[4]=0 is 1 stop bits */

View File

@ -140,3 +140,12 @@
/* Sanwa KB-USB2 multimeter cable (ID: 11ad:0001) */ /* Sanwa KB-USB2 multimeter cable (ID: 11ad:0001) */
#define SANWA_VENDOR_ID 0x11ad #define SANWA_VENDOR_ID 0x11ad
#define SANWA_PRODUCT_ID 0x0001 #define SANWA_PRODUCT_ID 0x0001
/* ADLINK ND-6530 RS232,RS485 and RS422 adapter */
#define ADLINK_VENDOR_ID 0x0b63
#define ADLINK_ND6530_PRODUCT_ID 0x6530
/* SMART USB Serial Adapter */
#define SMART_VENDOR_ID 0x0b8c
#define SMART_PRODUCT_ID 0x2303

View File

@ -28,6 +28,7 @@ static const struct usb_device_id id_table[] = {
{USB_DEVICE(0x05c6, 0x9212)}, /* Acer Gobi Modem Device */ {USB_DEVICE(0x05c6, 0x9212)}, /* Acer Gobi Modem Device */
{USB_DEVICE(0x03f0, 0x1f1d)}, /* HP un2400 Gobi Modem Device */ {USB_DEVICE(0x03f0, 0x1f1d)}, /* HP un2400 Gobi Modem Device */
{USB_DEVICE(0x03f0, 0x201d)}, /* HP un2400 Gobi QDL Device */ {USB_DEVICE(0x03f0, 0x201d)}, /* HP un2400 Gobi QDL Device */
{USB_DEVICE(0x03f0, 0x371d)}, /* HP un2430 Mobile Broadband Module */
{USB_DEVICE(0x04da, 0x250d)}, /* Panasonic Gobi Modem device */ {USB_DEVICE(0x04da, 0x250d)}, /* Panasonic Gobi Modem device */
{USB_DEVICE(0x04da, 0x250c)}, /* Panasonic Gobi QDL device */ {USB_DEVICE(0x04da, 0x250c)}, /* Panasonic Gobi QDL device */
{USB_DEVICE(0x413c, 0x8172)}, /* Dell Gobi Modem device */ {USB_DEVICE(0x413c, 0x8172)}, /* Dell Gobi Modem device */
@ -45,6 +46,7 @@ static const struct usb_device_id id_table[] = {
{USB_DEVICE(0x05c6, 0x9203)}, /* Generic Gobi Modem device */ {USB_DEVICE(0x05c6, 0x9203)}, /* Generic Gobi Modem device */
{USB_DEVICE(0x05c6, 0x9222)}, /* Generic Gobi Modem device */ {USB_DEVICE(0x05c6, 0x9222)}, /* Generic Gobi Modem device */
{USB_DEVICE(0x05c6, 0x9008)}, /* Generic Gobi QDL device */ {USB_DEVICE(0x05c6, 0x9008)}, /* Generic Gobi QDL device */
{USB_DEVICE(0x05c6, 0x9009)}, /* Generic Gobi Modem device */
{USB_DEVICE(0x05c6, 0x9201)}, /* Generic Gobi QDL device */ {USB_DEVICE(0x05c6, 0x9201)}, /* Generic Gobi QDL device */
{USB_DEVICE(0x05c6, 0x9221)}, /* Generic Gobi QDL device */ {USB_DEVICE(0x05c6, 0x9221)}, /* Generic Gobi QDL device */
{USB_DEVICE(0x05c6, 0x9231)}, /* Generic Gobi QDL device */ {USB_DEVICE(0x05c6, 0x9231)}, /* Generic Gobi QDL device */
@ -78,6 +80,7 @@ static const struct usb_device_id id_table[] = {
{USB_DEVICE(0x1199, 0x9008)}, /* Sierra Wireless Gobi 2000 Modem device (VT773) */ {USB_DEVICE(0x1199, 0x9008)}, /* Sierra Wireless Gobi 2000 Modem device (VT773) */
{USB_DEVICE(0x1199, 0x9009)}, /* Sierra Wireless Gobi 2000 Modem device (VT773) */ {USB_DEVICE(0x1199, 0x9009)}, /* Sierra Wireless Gobi 2000 Modem device (VT773) */
{USB_DEVICE(0x1199, 0x900a)}, /* Sierra Wireless Gobi 2000 Modem device (VT773) */ {USB_DEVICE(0x1199, 0x900a)}, /* Sierra Wireless Gobi 2000 Modem device (VT773) */
{USB_DEVICE(0x1199, 0x9011)}, /* Sierra Wireless Gobi 2000 Modem device (MC8305) */
{USB_DEVICE(0x16d8, 0x8001)}, /* CMDTech Gobi 2000 QDL device (VU922) */ {USB_DEVICE(0x16d8, 0x8001)}, /* CMDTech Gobi 2000 QDL device (VU922) */
{USB_DEVICE(0x16d8, 0x8002)}, /* CMDTech Gobi 2000 Modem device (VU922) */ {USB_DEVICE(0x16d8, 0x8002)}, /* CMDTech Gobi 2000 Modem device (VU922) */
{USB_DEVICE(0x05c6, 0x9204)}, /* Gobi 2000 QDL device */ {USB_DEVICE(0x05c6, 0x9204)}, /* Gobi 2000 QDL device */

View File

@ -925,6 +925,7 @@ static void sierra_release(struct usb_serial *serial)
continue; continue;
kfree(portdata); kfree(portdata);
} }
kfree(serial->private);
} }
#ifdef CONFIG_PM #ifdef CONFIG_PM

View File

@ -1071,6 +1071,12 @@ int usb_serial_probe(struct usb_interface *interface,
serial->attached = 1; serial->attached = 1;
} }
/* Avoid race with tty_open and serial_install by setting the
* disconnected flag and not clearing it until all ports have been
* registered.
*/
serial->disconnected = 1;
if (get_free_serial(serial, num_ports, &minor) == NULL) { if (get_free_serial(serial, num_ports, &minor) == NULL) {
dev_err(&interface->dev, "No more free serial devices\n"); dev_err(&interface->dev, "No more free serial devices\n");
goto probe_error; goto probe_error;
@ -1093,6 +1099,8 @@ int usb_serial_probe(struct usb_interface *interface,
} }
} }
serial->disconnected = 0;
usb_serial_console_init(debug, minor); usb_serial_console_init(debug, minor);
exit: exit:

View File

@ -576,6 +576,7 @@ no_firmware:
"%s: please contact support@connecttech.com\n", "%s: please contact support@connecttech.com\n",
serial->type->description); serial->type->description);
kfree(result); kfree(result);
kfree(command);
return -ENODEV; return -ENODEV;
no_command_private: no_command_private:

View File

@ -58,7 +58,9 @@
void usb_stor_pad12_command(struct scsi_cmnd *srb, struct us_data *us) void usb_stor_pad12_command(struct scsi_cmnd *srb, struct us_data *us)
{ {
/* Pad the SCSI command with zeros out to 12 bytes /*
* Pad the SCSI command with zeros out to 12 bytes. If the
* command already is 12 bytes or longer, leave it alone.
* *
* NOTE: This only works because a scsi_cmnd struct field contains * NOTE: This only works because a scsi_cmnd struct field contains
* a unsigned char cmnd[16], so we know we have storage available * a unsigned char cmnd[16], so we know we have storage available
@ -66,9 +68,6 @@ void usb_stor_pad12_command(struct scsi_cmnd *srb, struct us_data *us)
for (; srb->cmd_len<12; srb->cmd_len++) for (; srb->cmd_len<12; srb->cmd_len++)
srb->cmnd[srb->cmd_len] = 0; srb->cmnd[srb->cmd_len] = 0;
/* set command length to 12 bytes */
srb->cmd_len = 12;
/* send the command to the transport layer */ /* send the command to the transport layer */
usb_stor_invoke_transport(srb, us); usb_stor_invoke_transport(srb, us);
} }

View File

@ -693,6 +693,9 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
int temp_result; int temp_result;
struct scsi_eh_save ses; struct scsi_eh_save ses;
int sense_size = US_SENSE_SIZE; int sense_size = US_SENSE_SIZE;
struct scsi_sense_hdr sshdr;
const u8 *scdd;
u8 fm_ili;
/* device supports and needs bigger sense buffer */ /* device supports and needs bigger sense buffer */
if (us->fflags & US_FL_SANE_SENSE) if (us->fflags & US_FL_SANE_SENSE)
@ -776,32 +779,30 @@ Retry_Sense:
srb->sense_buffer[7] = (US_SENSE_SIZE - 8); srb->sense_buffer[7] = (US_SENSE_SIZE - 8);
} }
scsi_normalize_sense(srb->sense_buffer, SCSI_SENSE_BUFFERSIZE,
&sshdr);
US_DEBUGP("-- Result from auto-sense is %d\n", temp_result); US_DEBUGP("-- Result from auto-sense is %d\n", temp_result);
US_DEBUGP("-- code: 0x%x, key: 0x%x, ASC: 0x%x, ASCQ: 0x%x\n", US_DEBUGP("-- code: 0x%x, key: 0x%x, ASC: 0x%x, ASCQ: 0x%x\n",
srb->sense_buffer[0], sshdr.response_code, sshdr.sense_key,
srb->sense_buffer[2] & 0xf, sshdr.asc, sshdr.ascq);
srb->sense_buffer[12],
srb->sense_buffer[13]);
#ifdef CONFIG_USB_STORAGE_DEBUG #ifdef CONFIG_USB_STORAGE_DEBUG
usb_stor_show_sense( usb_stor_show_sense(sshdr.sense_key, sshdr.asc, sshdr.ascq);
srb->sense_buffer[2] & 0xf,
srb->sense_buffer[12],
srb->sense_buffer[13]);
#endif #endif
/* set the result so the higher layers expect this data */ /* set the result so the higher layers expect this data */
srb->result = SAM_STAT_CHECK_CONDITION; srb->result = SAM_STAT_CHECK_CONDITION;
scdd = scsi_sense_desc_find(srb->sense_buffer,
SCSI_SENSE_BUFFERSIZE, 4);
fm_ili = (scdd ? scdd[3] : srb->sense_buffer[2]) & 0xA0;
/* We often get empty sense data. This could indicate that /* We often get empty sense data. This could indicate that
* everything worked or that there was an unspecified * everything worked or that there was an unspecified
* problem. We have to decide which. * problem. We have to decide which.
*/ */
if ( /* Filemark 0, ignore EOM, ILI 0, no sense */ if (sshdr.sense_key == 0 && sshdr.asc == 0 && sshdr.ascq == 0 &&
(srb->sense_buffer[2] & 0xaf) == 0 && fm_ili == 0) {
/* No ASC or ASCQ */
srb->sense_buffer[12] == 0 &&
srb->sense_buffer[13] == 0) {
/* If things are really okay, then let's show that. /* If things are really okay, then let's show that.
* Zero out the sense buffer so the higher layers * Zero out the sense buffer so the higher layers
* won't realize we did an unsolicited auto-sense. * won't realize we did an unsolicited auto-sense.
@ -816,7 +817,10 @@ Retry_Sense:
*/ */
} else { } else {
srb->result = DID_ERROR << 16; srb->result = DID_ERROR << 16;
srb->sense_buffer[2] = HARDWARE_ERROR; if ((sshdr.response_code & 0x72) == 0x72)
srb->sense_buffer[1] = HARDWARE_ERROR;
else
srb->sense_buffer[2] = HARDWARE_ERROR;
} }
} }
} }

View File

@ -1857,6 +1857,13 @@ UNUSUAL_DEV( 0x1370, 0x6828, 0x0110, 0x0110,
US_SC_DEVICE, US_PR_DEVICE, NULL, US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_IGNORE_RESIDUE ), US_FL_IGNORE_RESIDUE ),
/* Reported by Qinglin Ye <yestyle@gmail.com> */
UNUSUAL_DEV( 0x13fe, 0x3600, 0x0100, 0x0100,
"Kingston",
"DT 101 G2",
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_BULK_IGNORE_TAG ),
/* Reported by Francesco Foresti <frafore@tiscali.it> */ /* Reported by Francesco Foresti <frafore@tiscali.it> */
UNUSUAL_DEV( 0x14cd, 0x6600, 0x0201, 0x0201, UNUSUAL_DEV( 0x14cd, 0x6600, 0x0201, 0x0201,
"Super Top", "Super Top",
@ -1977,6 +1984,16 @@ UNUSUAL_DEV( 0x4146, 0xba01, 0x0100, 0x0100,
"Micro Mini 1GB", "Micro Mini 1GB",
US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_NOT_LOCKABLE ), US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_NOT_LOCKABLE ),
/*
* Nick Bowler <nbowler@elliptictech.com>
* SCSI stack spams (otherwise harmless) error messages.
*/
UNUSUAL_DEV( 0xc251, 0x4003, 0x0100, 0x0100,
"Keil Software, Inc.",
"V2M MotherBoard",
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_NOT_LOCKABLE),
/* Reported by Andrew Simmons <andrew.simmons@gmail.com> */ /* Reported by Andrew Simmons <andrew.simmons@gmail.com> */
UNUSUAL_DEV( 0xed06, 0x4500, 0x0001, 0x0001, UNUSUAL_DEV( 0xed06, 0x4500, 0x0001, 0x0001,
"DataStor", "DataStor",

View File

@ -1025,6 +1025,7 @@ static struct usb_driver usb_storage_driver = {
.post_reset = usb_stor_post_reset, .post_reset = usb_stor_post_reset,
.id_table = usb_storage_usb_ids, .id_table = usb_storage_usb_ids,
.soft_unbind = 1, .soft_unbind = 1,
.no_dynamic_id = 1,
}; };
static int __init usb_stor_init(void) static int __init usb_stor_init(void)

View File

@ -46,7 +46,7 @@ struct ehci_caps {
#define HCC_PGM_FRAMELISTLEN(p) ((p)&(1 << 1)) /* true: periodic_size changes*/ #define HCC_PGM_FRAMELISTLEN(p) ((p)&(1 << 1)) /* true: periodic_size changes*/
#define HCC_64BIT_ADDR(p) ((p)&(1)) /* true: can use 64-bit addr */ #define HCC_64BIT_ADDR(p) ((p)&(1)) /* true: can use 64-bit addr */
u8 portroute [8]; /* nibbles for routing - offset 0xC */ u8 portroute [8]; /* nibbles for routing - offset 0xC */
} __attribute__ ((packed)); };
/* Section 2.3 Host Controller Operational Registers */ /* Section 2.3 Host Controller Operational Registers */
@ -125,7 +125,7 @@ struct ehci_regs {
#define PORT_CSC (1<<1) /* connect status change */ #define PORT_CSC (1<<1) /* connect status change */
#define PORT_CONNECT (1<<0) /* device connected */ #define PORT_CONNECT (1<<0) /* device connected */
#define PORT_RWC_BITS (PORT_CSC | PORT_PEC | PORT_OCC) #define PORT_RWC_BITS (PORT_CSC | PORT_PEC | PORT_OCC)
} __attribute__ ((packed)); };
#define USBMODE 0x68 /* USB Device mode */ #define USBMODE 0x68 /* USB Device mode */
#define USBMODE_SDIS (1<<3) /* Stream disable */ #define USBMODE_SDIS (1<<3) /* Stream disable */
@ -169,7 +169,7 @@ struct ehci_dbg_port {
u32 data47; u32 data47;
u32 address; u32 address;
#define DBGP_EPADDR(dev, ep) (((dev)<<8)|(ep)) #define DBGP_EPADDR(dev, ep) (((dev)<<8)|(ep))
} __attribute__ ((packed)); };
#ifdef CONFIG_EARLY_PRINTK_DBGP #ifdef CONFIG_EARLY_PRINTK_DBGP
#include <linux/init.h> #include <linux/init.h>

View File

@ -171,7 +171,8 @@ extern void usbnet_cdc_unbind (struct usbnet *, struct usb_interface *);
enum skb_state { enum skb_state {
illegal = 0, illegal = 0,
tx_start, tx_done, tx_start, tx_done,
rx_start, rx_done, rx_cleanup rx_start, rx_done, rx_cleanup,
unlink_start
}; };
struct skb_data { /* skb->cb is one of these */ struct skb_data { /* skb->cb is one of these */