Commit 8fdb7e9f authored by Linus Torvalds's avatar Linus Torvalds

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

* git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6: (45 commits)
  USB: gadget/multi: cdc_do_config: remove redundant check
  usb: r8a66597-hcd: fix removed from an attached hub
  USB: xhci: Make endpoint interval debugging clearer.
  USB: Fix usb_fill_int_urb for SuperSpeed devices
  USB: cp210x: Remove double usb_control_msg from cp210x_set_config
  USB: Remove last bit of CONFIG_USB_BERRY_CHARGE
  USB: gadget: add gadget controller number for s3c-hsotg driver
  USB: ftdi_sio: Fix locking for change_speed() function
  USB: g_mass_storage: fixed module name in Kconfig
  USB: gadget: f_mass_storage::fsg_bind(): fix error handling
  USB: g_mass_storage: fix section mismatch warnings
  USB: gadget: fix Blackfin builds after gadget cleansing
  USB: goku_udc: remove potential null dereference
  USB: option.c: Add Pirelli VID/PID and indicate Pirelli's modem interface is 0xff
  USB: serial: Fix module name typo for qcaux Kconfig entry.
  usb: cdc-wdm: Fix deadlock between write and resume
  usb: cdc-wdm: Fix order in disconnect and fix locking
  usb: cdc-wdm:Fix loss of data due to autosuspend
  usb: cdc-wdm: Fix submission of URB after suspension
  usb: cdc-wdm: Fix race between disconnect and debug messages
  ...
parents fc7f99cf 4cb80cda
...@@ -160,7 +160,7 @@ Description: ...@@ -160,7 +160,7 @@ Description:
match the driver to the device. For example: match the driver to the device. For example:
# echo "046d c315" > /sys/bus/usb/drivers/foo/remove_id # echo "046d c315" > /sys/bus/usb/drivers/foo/remove_id
What: /sys/bus/usb/device/.../avoid_reset What: /sys/bus/usb/device/.../avoid_reset_quirk
Date: December 2009 Date: December 2009
Contact: Oliver Neukum <oliver@neukum.org> Contact: Oliver Neukum <oliver@neukum.org>
Description: Description:
......
...@@ -1441,7 +1441,7 @@ static int acm_resume(struct usb_interface *intf) ...@@ -1441,7 +1441,7 @@ static int acm_resume(struct usb_interface *intf)
wb = acm->delayed_wb; wb = acm->delayed_wb;
acm->delayed_wb = NULL; acm->delayed_wb = NULL;
spin_unlock_irq(&acm->write_lock); spin_unlock_irq(&acm->write_lock);
acm_start_wb(acm, acm->delayed_wb); acm_start_wb(acm, wb);
} else { } else {
spin_unlock_irq(&acm->write_lock); spin_unlock_irq(&acm->write_lock);
} }
......
...@@ -52,7 +52,8 @@ MODULE_DEVICE_TABLE (usb, wdm_ids); ...@@ -52,7 +52,8 @@ 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_RESPONDING 7
#define WDM_SUSPENDING 8
#define WDM_MAX 16 #define WDM_MAX 16
...@@ -87,9 +88,7 @@ struct wdm_device { ...@@ -87,9 +88,7 @@ struct wdm_device {
int count; int count;
dma_addr_t shandle; dma_addr_t shandle;
dma_addr_t ihandle; dma_addr_t ihandle;
struct mutex wlock; struct mutex lock;
struct mutex rlock;
struct mutex plock;
wait_queue_head_t wait; wait_queue_head_t wait;
struct work_struct rxwork; struct work_struct rxwork;
int werr; int werr;
...@@ -117,21 +116,22 @@ static void wdm_in_callback(struct urb *urb) ...@@ -117,21 +116,22 @@ static void wdm_in_callback(struct urb *urb)
int status = urb->status; int status = urb->status;
spin_lock(&desc->iuspin); spin_lock(&desc->iuspin);
clear_bit(WDM_RESPONDING, &desc->flags);
if (status) { if (status) {
switch (status) { switch (status) {
case -ENOENT: case -ENOENT:
dev_dbg(&desc->intf->dev, dev_dbg(&desc->intf->dev,
"nonzero urb status received: -ENOENT"); "nonzero urb status received: -ENOENT");
break; goto skip_error;
case -ECONNRESET: case -ECONNRESET:
dev_dbg(&desc->intf->dev, dev_dbg(&desc->intf->dev,
"nonzero urb status received: -ECONNRESET"); "nonzero urb status received: -ECONNRESET");
break; goto skip_error;
case -ESHUTDOWN: case -ESHUTDOWN:
dev_dbg(&desc->intf->dev, dev_dbg(&desc->intf->dev,
"nonzero urb status received: -ESHUTDOWN"); "nonzero urb status received: -ESHUTDOWN");
break; goto skip_error;
case -EPIPE: case -EPIPE:
dev_err(&desc->intf->dev, dev_err(&desc->intf->dev,
"nonzero urb status received: -EPIPE\n"); "nonzero urb status received: -EPIPE\n");
...@@ -147,6 +147,7 @@ static void wdm_in_callback(struct urb *urb) ...@@ -147,6 +147,7 @@ static void wdm_in_callback(struct urb *urb)
desc->reslength = urb->actual_length; desc->reslength = urb->actual_length;
memmove(desc->ubuf + desc->length, desc->inbuf, desc->reslength); memmove(desc->ubuf + desc->length, desc->inbuf, desc->reslength);
desc->length += desc->reslength; desc->length += desc->reslength;
skip_error:
wake_up(&desc->wait); wake_up(&desc->wait);
set_bit(WDM_READ, &desc->flags); set_bit(WDM_READ, &desc->flags);
...@@ -229,13 +230,16 @@ static void wdm_int_callback(struct urb *urb) ...@@ -229,13 +230,16 @@ static void wdm_int_callback(struct urb *urb)
desc->response->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; desc->response->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
spin_lock(&desc->iuspin); spin_lock(&desc->iuspin);
clear_bit(WDM_READ, &desc->flags); clear_bit(WDM_READ, &desc->flags);
if (!test_bit(WDM_DISCONNECTING, &desc->flags)) { set_bit(WDM_RESPONDING, &desc->flags);
if (!test_bit(WDM_DISCONNECTING, &desc->flags)
&& !test_bit(WDM_SUSPENDING, &desc->flags)) {
rv = usb_submit_urb(desc->response, GFP_ATOMIC); rv = usb_submit_urb(desc->response, GFP_ATOMIC);
dev_dbg(&desc->intf->dev, "%s: usb_submit_urb %d", dev_dbg(&desc->intf->dev, "%s: usb_submit_urb %d",
__func__, rv); __func__, rv);
} }
spin_unlock(&desc->iuspin); spin_unlock(&desc->iuspin);
if (rv < 0) { if (rv < 0) {
clear_bit(WDM_RESPONDING, &desc->flags);
if (rv == -EPERM) if (rv == -EPERM)
return; return;
if (rv == -ENOMEM) { if (rv == -ENOMEM) {
...@@ -305,14 +309,38 @@ static ssize_t wdm_write ...@@ -305,14 +309,38 @@ static ssize_t wdm_write
if (we < 0) if (we < 0)
return -EIO; return -EIO;
r = mutex_lock_interruptible(&desc->wlock); /* concurrent writes */ desc->outbuf = buf = kmalloc(count, GFP_KERNEL);
if (!buf) {
rv = -ENOMEM;
goto outnl;
}
r = copy_from_user(buf, buffer, count);
if (r > 0) {
kfree(buf);
rv = -EFAULT;
goto outnl;
}
/* concurrent writes and disconnect */
r = mutex_lock_interruptible(&desc->lock);
rv = -ERESTARTSYS; rv = -ERESTARTSYS;
if (r) if (r) {
kfree(buf);
goto outnl; goto outnl;
}
if (test_bit(WDM_DISCONNECTING, &desc->flags)) {
kfree(buf);
rv = -ENODEV;
goto outnp;
}
r = usb_autopm_get_interface(desc->intf); r = usb_autopm_get_interface(desc->intf);
if (r < 0) if (r < 0) {
kfree(buf);
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,
...@@ -320,24 +348,8 @@ static ssize_t wdm_write ...@@ -320,24 +348,8 @@ static ssize_t wdm_write
else else
if (test_bit(WDM_IN_USE, &desc->flags)) if (test_bit(WDM_IN_USE, &desc->flags))
r = -EAGAIN; r = -EAGAIN;
if (r < 0) if (r < 0) {
goto out;
if (test_bit(WDM_DISCONNECTING, &desc->flags)) {
rv = -ENODEV;
goto out;
}
desc->outbuf = buf = kmalloc(count, GFP_KERNEL);
if (!buf) {
rv = -ENOMEM;
goto out;
}
r = copy_from_user(buf, buffer, count);
if (r > 0) {
kfree(buf); kfree(buf);
rv = -EFAULT;
goto out; goto out;
} }
...@@ -374,7 +386,7 @@ static ssize_t wdm_write ...@@ -374,7 +386,7 @@ static ssize_t wdm_write
out: out:
usb_autopm_put_interface(desc->intf); usb_autopm_put_interface(desc->intf);
outnp: outnp:
mutex_unlock(&desc->wlock); mutex_unlock(&desc->lock);
outnl: outnl:
return rv < 0 ? rv : count; return rv < 0 ? rv : count;
} }
...@@ -387,7 +399,7 @@ static ssize_t wdm_read ...@@ -387,7 +399,7 @@ static ssize_t wdm_read
struct wdm_device *desc = file->private_data; struct wdm_device *desc = file->private_data;
rv = mutex_lock_interruptible(&desc->rlock); /*concurrent reads */ rv = mutex_lock_interruptible(&desc->lock); /*concurrent reads */
if (rv < 0) if (rv < 0)
return -ERESTARTSYS; return -ERESTARTSYS;
...@@ -424,11 +436,8 @@ static ssize_t wdm_read ...@@ -424,11 +436,8 @@ static ssize_t wdm_read
spin_lock_irq(&desc->iuspin); spin_lock_irq(&desc->iuspin);
if (desc->rerr) { /* read completed, error happened */ if (desc->rerr) { /* read completed, error happened */
int t = desc->rerr;
desc->rerr = 0; desc->rerr = 0;
spin_unlock_irq(&desc->iuspin); spin_unlock_irq(&desc->iuspin);
dev_err(&desc->intf->dev,
"reading had resulted in %d\n", t);
rv = -EIO; rv = -EIO;
goto err; goto err;
} }
...@@ -465,9 +474,7 @@ static ssize_t wdm_read ...@@ -465,9 +474,7 @@ static ssize_t wdm_read
rv = cntr; rv = cntr;
err: err:
mutex_unlock(&desc->rlock); mutex_unlock(&desc->lock);
if (rv < 0 && rv != -EAGAIN)
dev_err(&desc->intf->dev, "wdm_read: exit error\n");
return rv; return rv;
} }
...@@ -533,7 +540,7 @@ static int wdm_open(struct inode *inode, struct file *file) ...@@ -533,7 +540,7 @@ static int wdm_open(struct inode *inode, struct file *file)
} }
intf->needs_remote_wakeup = 1; intf->needs_remote_wakeup = 1;
mutex_lock(&desc->plock); mutex_lock(&desc->lock);
if (!desc->count++) { if (!desc->count++) {
rv = usb_submit_urb(desc->validity, GFP_KERNEL); rv = usb_submit_urb(desc->validity, GFP_KERNEL);
if (rv < 0) { if (rv < 0) {
...@@ -544,7 +551,7 @@ static int wdm_open(struct inode *inode, struct file *file) ...@@ -544,7 +551,7 @@ static int wdm_open(struct inode *inode, struct file *file)
} else { } else {
rv = 0; rv = 0;
} }
mutex_unlock(&desc->plock); mutex_unlock(&desc->lock);
usb_autopm_put_interface(desc->intf); usb_autopm_put_interface(desc->intf);
out: out:
mutex_unlock(&wdm_mutex); mutex_unlock(&wdm_mutex);
...@@ -556,9 +563,9 @@ static int wdm_release(struct inode *inode, struct file *file) ...@@ -556,9 +563,9 @@ static int wdm_release(struct inode *inode, struct file *file)
struct wdm_device *desc = file->private_data; struct wdm_device *desc = file->private_data;
mutex_lock(&wdm_mutex); mutex_lock(&wdm_mutex);
mutex_lock(&desc->plock); mutex_lock(&desc->lock);
desc->count--; desc->count--;
mutex_unlock(&desc->plock); mutex_unlock(&desc->lock);
if (!desc->count) { if (!desc->count) {
dev_dbg(&desc->intf->dev, "wdm_release: cleanup"); dev_dbg(&desc->intf->dev, "wdm_release: cleanup");
...@@ -655,9 +662,7 @@ static int wdm_probe(struct usb_interface *intf, const struct usb_device_id *id) ...@@ -655,9 +662,7 @@ static int wdm_probe(struct usb_interface *intf, const struct usb_device_id *id)
desc = kzalloc(sizeof(struct wdm_device), GFP_KERNEL); desc = kzalloc(sizeof(struct wdm_device), GFP_KERNEL);
if (!desc) if (!desc)
goto out; goto out;
mutex_init(&desc->wlock); mutex_init(&desc->lock);
mutex_init(&desc->rlock);
mutex_init(&desc->plock);
spin_lock_init(&desc->iuspin); spin_lock_init(&desc->iuspin);
init_waitqueue_head(&desc->wait); init_waitqueue_head(&desc->wait);
desc->wMaxCommand = maxcom; desc->wMaxCommand = maxcom;
...@@ -771,14 +776,17 @@ static void wdm_disconnect(struct usb_interface *intf) ...@@ -771,14 +776,17 @@ static void wdm_disconnect(struct usb_interface *intf)
/* to terminate pending flushes */ /* to terminate pending flushes */
clear_bit(WDM_IN_USE, &desc->flags); clear_bit(WDM_IN_USE, &desc->flags);
spin_unlock_irqrestore(&desc->iuspin, flags); spin_unlock_irqrestore(&desc->iuspin, flags);
cancel_work_sync(&desc->rxwork); mutex_lock(&desc->lock);
kill_urbs(desc); kill_urbs(desc);
cancel_work_sync(&desc->rxwork);
mutex_unlock(&desc->lock);
wake_up_all(&desc->wait); wake_up_all(&desc->wait);
if (!desc->count) if (!desc->count)
cleanup(desc); cleanup(desc);
mutex_unlock(&wdm_mutex); mutex_unlock(&wdm_mutex);
} }
#ifdef CONFIG_PM
static int wdm_suspend(struct usb_interface *intf, pm_message_t message) static int wdm_suspend(struct usb_interface *intf, pm_message_t message)
{ {
struct wdm_device *desc = usb_get_intfdata(intf); struct wdm_device *desc = usb_get_intfdata(intf);
...@@ -786,22 +794,30 @@ static int wdm_suspend(struct usb_interface *intf, pm_message_t message) ...@@ -786,22 +794,30 @@ static int wdm_suspend(struct usb_interface *intf, pm_message_t message)
dev_dbg(&desc->intf->dev, "wdm%d_suspend\n", intf->minor); dev_dbg(&desc->intf->dev, "wdm%d_suspend\n", intf->minor);
mutex_lock(&desc->plock); /* if this is an autosuspend the caller does the locking */
#ifdef CONFIG_PM if (!(message.event & PM_EVENT_AUTO))
mutex_lock(&desc->lock);
spin_lock_irq(&desc->iuspin);
if ((message.event & PM_EVENT_AUTO) && if ((message.event & PM_EVENT_AUTO) &&
test_bit(WDM_IN_USE, &desc->flags)) { (test_bit(WDM_IN_USE, &desc->flags)
|| test_bit(WDM_RESPONDING, &desc->flags))) {
spin_unlock_irq(&desc->iuspin);
rv = -EBUSY; rv = -EBUSY;
} else { } else {
#endif
cancel_work_sync(&desc->rxwork); set_bit(WDM_SUSPENDING, &desc->flags);
spin_unlock_irq(&desc->iuspin);
/* callback submits work - order is essential */
kill_urbs(desc); kill_urbs(desc);
#ifdef CONFIG_PM cancel_work_sync(&desc->rxwork);
} }
#endif if (!(message.event & PM_EVENT_AUTO))
mutex_unlock(&desc->plock); mutex_unlock(&desc->lock);
return rv; return rv;
} }
#endif
static int recover_from_urb_loss(struct wdm_device *desc) static int recover_from_urb_loss(struct wdm_device *desc)
{ {
...@@ -815,23 +831,27 @@ static int recover_from_urb_loss(struct wdm_device *desc) ...@@ -815,23 +831,27 @@ static int recover_from_urb_loss(struct wdm_device *desc)
} }
return rv; return rv;
} }
#ifdef CONFIG_PM
static int wdm_resume(struct usb_interface *intf) static int wdm_resume(struct usb_interface *intf)
{ {
struct wdm_device *desc = usb_get_intfdata(intf); struct wdm_device *desc = usb_get_intfdata(intf);
int rv; int rv;
dev_dbg(&desc->intf->dev, "wdm%d_resume\n", intf->minor); dev_dbg(&desc->intf->dev, "wdm%d_resume\n", intf->minor);
mutex_lock(&desc->plock);
clear_bit(WDM_SUSPENDING, &desc->flags);
rv = recover_from_urb_loss(desc); rv = recover_from_urb_loss(desc);
mutex_unlock(&desc->plock);
return rv; return rv;
} }
#endif
static int wdm_pre_reset(struct usb_interface *intf) static int wdm_pre_reset(struct usb_interface *intf)
{ {
struct wdm_device *desc = usb_get_intfdata(intf); struct wdm_device *desc = usb_get_intfdata(intf);
mutex_lock(&desc->plock); mutex_lock(&desc->lock);
return 0; return 0;
} }
...@@ -841,7 +861,7 @@ static int wdm_post_reset(struct usb_interface *intf) ...@@ -841,7 +861,7 @@ static int wdm_post_reset(struct usb_interface *intf)
int rv; int rv;
rv = recover_from_urb_loss(desc); rv = recover_from_urb_loss(desc);
mutex_unlock(&desc->plock); mutex_unlock(&desc->lock);
return 0; return 0;
} }
...@@ -849,9 +869,11 @@ static struct usb_driver wdm_driver = { ...@@ -849,9 +869,11 @@ static struct usb_driver wdm_driver = {
.name = "cdc_wdm", .name = "cdc_wdm",
.probe = wdm_probe, .probe = wdm_probe,
.disconnect = wdm_disconnect, .disconnect = wdm_disconnect,
#ifdef CONFIG_PM
.suspend = wdm_suspend, .suspend = wdm_suspend,
.resume = wdm_resume, .resume = wdm_resume,
.reset_resume = wdm_resume, .reset_resume = wdm_resume,
#endif
.pre_reset = wdm_pre_reset, .pre_reset = wdm_pre_reset,
.post_reset = wdm_post_reset, .post_reset = wdm_post_reset,
.id_table = wdm_ids, .id_table = wdm_ids,
......
...@@ -1207,6 +1207,13 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, ...@@ -1207,6 +1207,13 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
free_async(as); free_async(as);
return -ENOMEM; return -ENOMEM;
} }
/* Isochronous input data may end up being discontiguous
* if some of the packets are short. Clear the buffer so
* that the gaps don't leak kernel data to userspace.
*/
if (is_in && uurb->type == USBDEVFS_URB_TYPE_ISO)
memset(as->urb->transfer_buffer, 0,
uurb->buffer_length);
} }
as->urb->dev = ps->dev; as->urb->dev = ps->dev;
as->urb->pipe = (uurb->type << 30) | as->urb->pipe = (uurb->type << 30) |
...@@ -1345,10 +1352,14 @@ static int processcompl(struct async *as, void __user * __user *arg) ...@@ -1345,10 +1352,14 @@ static int processcompl(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))
goto err_out; goto err_out;
}
if (put_user(as->status, &userurb->status)) if (put_user(as->status, &userurb->status))
goto err_out; goto err_out;
if (put_user(urb->actual_length, &userurb->actual_length)) if (put_user(urb->actual_length, &userurb->actual_length))
......
...@@ -453,6 +453,7 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags) ...@@ -453,6 +453,7 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
if (urb->interval > (1 << 15)) if (urb->interval > (1 << 15))
return -EINVAL; return -EINVAL;
max = 1 << 15; max = 1 << 15;
break;
case USB_SPEED_WIRELESS: case USB_SPEED_WIRELESS:
if (urb->interval > 16) if (urb->interval > 16)
return -EINVAL; return -EINVAL;
......
...@@ -747,7 +747,7 @@ config USB_MASS_STORAGE ...@@ -747,7 +747,7 @@ config USB_MASS_STORAGE
which may be used with composite framework. which may be used with composite framework.
Say "y" to link the driver statically, or "m" to build Say "y" to link the driver statically, or "m" to build
a dynamically linked module called "g_file_storage". If unsure, a dynamically linked module called "g_mass_storage". If unsure,
consider File-backed Storage Gadget. consider File-backed Storage Gadget.
config USB_G_SERIAL config USB_G_SERIAL
......
...@@ -266,7 +266,7 @@ struct usb_ep * __init usb_ep_autoconfig ( ...@@ -266,7 +266,7 @@ struct usb_ep * __init usb_ep_autoconfig (
} }
#ifdef CONFIG_BLACKFIN #ifdef CONFIG_BLACKFIN
} else if (gadget_is_musbhsfc(gadget) || gadget_is_musbhdrc(gadget)) { } else if (gadget_is_musbhdrc(gadget)) {
if ((USB_ENDPOINT_XFER_BULK == type) || if ((USB_ENDPOINT_XFER_BULK == type) ||
(USB_ENDPOINT_XFER_ISOC == type)) { (USB_ENDPOINT_XFER_ISOC == type)) {
if (USB_DIR_IN & desc->bEndpointAddress) if (USB_DIR_IN & desc->bEndpointAddress)
......
...@@ -2910,7 +2910,7 @@ static void fsg_unbind(struct usb_configuration *c, struct usb_function *f) ...@@ -2910,7 +2910,7 @@ static void fsg_unbind(struct usb_configuration *c, struct usb_function *f)
} }
static int fsg_bind(struct usb_configuration *c, struct usb_function *f) static int __init fsg_bind(struct usb_configuration *c, struct usb_function *f)
{ {
struct fsg_dev *fsg = fsg_from_func(f); struct fsg_dev *fsg = fsg_from_func(f);
struct usb_gadget *gadget = c->cdev->gadget; struct usb_gadget *gadget = c->cdev->gadget;
...@@ -2954,7 +2954,6 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f) ...@@ -2954,7 +2954,6 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f)
autoconf_fail: autoconf_fail:
ERROR(fsg, "unable to autoconfigure all endpoints\n"); ERROR(fsg, "unable to autoconfigure all endpoints\n");
rc = -ENOTSUPP; rc = -ENOTSUPP;
fsg_unbind(c, f);
return rc; return rc;
} }
......
...@@ -136,6 +136,12 @@ ...@@ -136,6 +136,12 @@
#define gadget_is_r8a66597(g) 0 #define gadget_is_r8a66597(g) 0
#endif #endif
#ifdef CONFIG_USB_S3C_HSOTG
#define gadget_is_s3c_hsotg(g) (!strcmp("s3c-hsotg", (g)->name))
#else
#define gadget_is_s3c_hsotg(g) 0
#endif
/** /**
* usb_gadget_controller_number - support bcdDevice id convention * usb_gadget_controller_number - support bcdDevice id convention
...@@ -192,6 +198,8 @@ static inline int usb_gadget_controller_number(struct usb_gadget *gadget) ...@@ -192,6 +198,8 @@ static inline int usb_gadget_controller_number(struct usb_gadget *gadget)
return 0x24; return 0x24;
else if (gadget_is_r8a66597(gadget)) else if (gadget_is_r8a66597(gadget))
return 0x25; return 0x25;
else if (gadget_is_s3c_hsotg(gadget))
return 0x26;
return -ENOENT; return -ENOENT;
} }
......
...@@ -1768,7 +1768,7 @@ static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -1768,7 +1768,7 @@ static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id)
* usb_gadget_driver_{register,unregister}() must change. * usb_gadget_driver_{register,unregister}() must change.
*/ */
if (the_controller) { if (the_controller) {
WARNING(dev, "ignoring %s\n", pci_name(pdev)); pr_warning("ignoring %s\n", pci_name(pdev));
return -EBUSY; return -EBUSY;
} }
if (!pdev->irq) { if (!pdev->irq) {
......
...@@ -211,8 +211,6 @@ static int __init cdc_do_config(struct usb_configuration *c) ...@@ -211,8 +211,6 @@ static int __init cdc_do_config(struct usb_configuration *c)
ret = fsg_add(c->cdev, c, fsg_common); ret = fsg_add(c->cdev, c, fsg_common);
if (ret < 0) if (ret < 0)
return ret; return ret;
if (ret < 0)
return ret;
return 0; return 0;
} }
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/err.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/clk.h> #include <linux/clk.h>
......
...@@ -12,7 +12,7 @@ fhci-objs := fhci-hcd.o fhci-hub.o fhci-q.o fhci-mem.o \ ...@@ -12,7 +12,7 @@ fhci-objs := fhci-hcd.o fhci-hub.o fhci-q.o fhci-mem.o \
ifeq ($(CONFIG_FHCI_DEBUG),y) ifeq ($(CONFIG_FHCI_DEBUG),y)
fhci-objs += fhci-dbg.o fhci-objs += fhci-dbg.o
endif endif
xhci-objs := xhci-hcd.o xhci-mem.o xhci-pci.o xhci-ring.o xhci-hub.o xhci-dbg.o xhci-hcd-objs := xhci.o xhci-mem.o xhci-pci.o xhci-ring.o xhci-hub.o xhci-dbg.o
obj-$(CONFIG_USB_WHCI_HCD) += whci/ obj-$(CONFIG_USB_WHCI_HCD) += whci/
...@@ -25,7 +25,7 @@ obj-$(CONFIG_USB_ISP1362_HCD) += isp1362-hcd.o ...@@ -25,7 +25,7 @@ obj-$(CONFIG_USB_ISP1362_HCD) += isp1362-hcd.o
obj-$(CONFIG_USB_OHCI_HCD) += ohci-hcd.o obj-$(CONFIG_USB_OHCI_HCD) += ohci-hcd.o
obj-$(CONFIG_USB_UHCI_HCD) += uhci-hcd.o obj-$(CONFIG_USB_UHCI_HCD) += uhci-hcd.o
obj-$(CONFIG_USB_FHCI_HCD) += fhci.o obj-$(CONFIG_USB_FHCI_HCD) += fhci.o
obj-$(CONFIG_USB_XHCI_HCD) += xhci.o obj-$(CONFIG_USB_XHCI_HCD) += xhci-hcd.o
obj-$(CONFIG_USB_SL811_HCD) += sl811-hcd.o obj-$(CONFIG_USB_SL811_HCD) += sl811-hcd.o
obj-$(CONFIG_USB_SL811_CS) += sl811_cs.o obj-$(CONFIG_USB_SL811_CS) += sl811_cs.o
obj-$(CONFIG_USB_U132_HCD) += u132-hcd.o obj-$(CONFIG_USB_U132_HCD) += u132-hcd.o
......
...@@ -995,7 +995,7 @@ ehci_endpoint_disable (struct usb_hcd *hcd, struct usb_host_endpoint *ep) ...@@ -995,7 +995,7 @@ ehci_endpoint_disable (struct usb_hcd *hcd, struct usb_host_endpoint *ep)
/* endpoints can be iso streams. for now, we don't /* endpoints can be iso streams. for now, we don't
* accelerate iso completions ... so spin a while. * accelerate iso completions ... so spin a while.
*/ */
if (qh->hw->hw_info1 == 0) { if (qh->hw == NULL) {
ehci_vdbg (ehci, "iso delay\n"); ehci_vdbg (ehci, "iso delay\n");
goto idle_timeout; goto idle_timeout;
} }
......
...@@ -1123,8 +1123,8 @@ iso_stream_find (struct ehci_hcd *ehci, struct urb *urb) ...@@ -1123,8 +1123,8 @@ iso_stream_find (struct ehci_hcd *ehci, struct urb *urb)
urb->interval); urb->interval);
} }
/* if dev->ep [epnum] is a QH, info1.maxpacket is nonzero */ /* if dev->ep [epnum] is a QH, hw is set */
} else if (unlikely (stream->hw_info1 != 0)) { } else if (unlikely (stream->hw != NULL)) {
ehci_dbg (ehci, "dev %s ep%d%s, not iso??\n", ehci_dbg (ehci, "dev %s ep%d%s, not iso??\n",
urb->dev->devpath, epnum, urb->dev->devpath, epnum,
usb_pipein(urb->pipe) ? "in" : "out"); usb_pipein(urb->pipe) ? "in" : "out");
...@@ -1565,13 +1565,27 @@ itd_patch( ...@@ -1565,13 +1565,27 @@ itd_patch(
static inline void static inline void
itd_link (struct ehci_hcd *ehci, unsigned frame, struct ehci_itd *itd) itd_link (struct ehci_hcd *ehci, unsigned frame, struct ehci_itd *itd)
{ {
/* always prepend ITD/SITD ... only QH tree is order-sensitive */ union ehci_shadow *prev = &ehci->pshadow[frame];
itd->itd_next = ehci->pshadow [frame]; __hc32 *hw_p = &ehci->periodic[frame];
itd->hw_next = ehci->periodic [frame]; union ehci_shadow here = *prev;
ehci->pshadow [frame].itd = itd; __hc32 type = 0;
/* skip any iso nodes which might belong to previous microframes */
while (here.ptr) {
type = Q_NEXT_TYPE(ehci, *hw_p);
if (type == cpu_to_hc32(ehci, Q_TYPE_QH))
break;
prev = periodic_next_shadow(ehci, prev, type);
hw_p = shadow_next_periodic(ehci, &here, type);
here = *prev;
}
itd->itd_next = here;
itd->hw_next = *hw_p;
prev->itd = itd;
itd->frame = frame; itd->frame = frame;
wmb (); wmb ();
ehci->periodic[frame] = cpu_to_hc32(ehci, itd->itd_dma | Q_TYPE_ITD); *hw_p = cpu_to_hc32(ehci, itd->itd_dma | Q_TYPE_ITD);
} }
/* fit urb's itds into the selected schedule slot; activate as needed */ /* fit urb's itds into the selected schedule slot; activate as needed */
......
...@@ -394,9 +394,8 @@ struct ehci_iso_sched { ...@@ -394,9 +394,8 @@ struct ehci_iso_sched {
* acts like a qh would, if EHCI had them for ISO. * acts like a qh would, if EHCI had them for ISO.
*/ */
struct ehci_iso_stream { struct ehci_iso_stream {
/* first two fields match QH, but info1 == 0 */ /* first field matches ehci_hq, but is NULL */
__hc32 hw_next; struct ehci_qh_hw *hw;
__hc32 hw_info1;
u32 refcount; u32 refcount;
u8 bEndpointAddress; u8 bEndpointAddress;
......
...@@ -418,7 +418,7 @@ static u8 alloc_usb_address(struct r8a66597 *r8a66597, struct urb *urb) ...@@ -418,7 +418,7 @@ static u8 alloc_usb_address(struct r8a66597 *r8a66597, struct urb *urb)
/* this function must be called with interrupt disabled */ /* this function must be called with interrupt disabled */
static void free_usb_address(struct r8a66597 *r8a66597, static void free_usb_address(struct r8a66597 *r8a66597,
struct r8a66597_device *dev) struct r8a66597_device *dev, int reset)
{ {
int port; int port;
...@@ -430,7 +430,13 @@ static void free_usb_address(struct r8a66597 *r8a66597, ...@@ -430,7 +430,13 @@ static void free_usb_address(struct r8a66597 *r8a66597,
dev->state = USB_STATE_DEFAULT; dev->state = USB_STATE_DEFAULT;
r8a66597->address_map &= ~(1 << dev->address); r8a66597->address_map &= ~(1 << dev->address);
dev->address = 0; dev->address = 0;
dev_set_drvdata(&dev->udev->dev, NULL); /*
* Only when resetting USB, it is necessary to erase drvdata. When
* a usb device with usb hub is disconnect, "dev->udev" is already
* freed on usb_desconnect(). So we cannot access the data.
*/
if (reset)
dev_set_drvdata(&dev->udev->dev, NULL);
list_del(&dev->device_list); list_del(&dev->device_list);
kfree(dev); kfree(dev);
...@@ -1069,7 +1075,7 @@ static void r8a66597_usb_disconnect(struct r8a66597 *r8a66597, int port) ...@@ -1069,7 +1075,7 @@ static void r8a66597_usb_disconnect(struct r8a66597 *r8a66597, int port)
struct r8a66597_device *dev = r8a66597->root_hub[port].dev; struct r8a66597_device *dev = r8a66597->root_hub[port].dev;
disable_r8a66597_pipe_all(r8a66597, dev); disable_r8a66597_pipe_all(r8a66597, dev);
free_usb_address(r8a66597, dev); free_usb_address(r8a66597, dev, 0);
start_root_hub_sampling(r8a66597, port, 0); start_root_hub_sampling(r8a66597, port, 0);
} }
...@@ -2085,7 +2091,7 @@ static void update_usb_address_map(struct r8a66597 *r8a66597, ...@@ -2085,7 +2091,7 @@ static void update_usb_address_map(struct r8a66597 *r8a66597,
spin_lock_irqsave(&r8a66597->lock, flags); spin_lock_irqsave(&r8a66597->lock, flags);
dev = get_r8a66597_device(r8a66597, addr); dev = get_r8a66597_device(r8a66597, addr);
disable_r8a66597_pipe_all(r8a66597, dev); disable_r8a66597_pipe_all(r8a66597, dev);
free_usb_address(r8a66597, dev); free_usb_address(r8a66597, dev, 0);
put_child_connect_map(r8a66597, addr); put_child_connect_map(r8a66597, addr);
spin_unlock_irqrestore(&r8a66597->lock, flags); spin_unlock_irqrestore(&r8a66597->lock, flags);
} }
...@@ -2228,7 +2234,7 @@ static int r8a66597_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, ...@@ -2228,7 +2234,7 @@ static int r8a66597_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
rh->port |= (1 << USB_PORT_FEAT_RESET); rh->port |= (1 << USB_PORT_FEAT_RESET);
disable_r8a66597_pipe_all(r8a66597, dev); disable_r8a66597_pipe_all(r8a66597, dev);
free_usb_address(r8a66597, dev); free_usb_address(r8a66597, dev, 1);
r8a66597_mdfy(r8a66597, USBRST, USBRST | UACT, r8a66597_mdfy(r8a66597, USBRST, USBRST | UACT,
get_dvstctr_reg(port)); get_dvstctr_reg(port));
......
...@@ -566,8 +566,13 @@ static inline unsigned int xhci_get_endpoint_interval(struct usb_device *udev, ...@@ -566,8 +566,13 @@ static inline unsigned int xhci_get_endpoint_interval(struct usb_device *udev,
if (interval < 3) if (interval < 3)
interval = 3; interval = 3;
if ((1 << interval) != 8*ep->desc.bInterval) if ((1 << interval) != 8*ep->desc.bInterval)
dev_warn(&udev->dev, "ep %#x - rounding interval to %d microframes\n", dev_warn(&udev->dev,
ep->desc.bEndpointAddress, 1 << interval); "ep %#x - rounding interval"
" to %d microframes, "
"ep desc says %d microframes\n",
ep->desc.bEndpointAddress,
1 << interval,
8*ep->desc.bInterval);
} }
break; break;
default: default:
......
...@@ -1173,6 +1173,7 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci, ...@@ -1173,6 +1173,7 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci,
cmd_completion = &virt_dev->cmd_completion; cmd_completion = &virt_dev->cmd_completion;
cmd_status = &virt_dev->cmd_status; cmd_status = &virt_dev->cmd_status;
} }
init_completion(cmd_completion);
if (!ctx_change) if (!ctx_change)
ret = xhci_queue_configure_endpoint(xhci, in_ctx->dma, ret = xhci_queue_configure_endpoint(xhci, in_ctx->dma,
......
...@@ -379,7 +379,6 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, ...@@ -379,7 +379,6 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
u8 devctl, u8 power) u8 devctl, u8 power)
{ {
irqreturn_t handled = IRQ_NONE; irqreturn_t handled = IRQ_NONE;
void __iomem *mbase = musb->mregs;
DBG(3, "<== Power=%02x, DevCtl=%02x, int_usb=0x%x\n", power, devctl, DBG(3, "<== Power=%02x, DevCtl=%02x, int_usb=0x%x\n", power, devctl,
int_usb); int_usb);
...@@ -394,6 +393,8 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, ...@@ -394,6 +393,8 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
if (devctl & MUSB_DEVCTL_HM) { if (devctl & MUSB_DEVCTL_HM) {
#ifdef CONFIG_USB_MUSB_HDRC_HCD #ifdef CONFIG_USB_MUSB_HDRC_HCD
void __iomem *mbase = musb->mregs;
switch (musb->xceiv->state) { switch (musb->xceiv->state) {
case OTG_STATE_A_SUSPEND: case OTG_STATE_A_SUSPEND:
/* remote wakeup? later, GetPortStatus /* remote wakeup? later, GetPortStatus
...@@ -471,6 +472,8 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, ...@@ -471,6 +472,8 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
#ifdef CONFIG_USB_MUSB_HDRC_HCD #ifdef CONFIG_USB_MUSB_HDRC_HCD
/* see manual for the order of the tests */ /* see manual for the order of the tests */
if (int_usb & MUSB_INTR_SESSREQ) { if (int_usb & MUSB_INTR_SESSREQ) {
void __iomem *mbase = musb->mregs;
DBG(1, "SESSION_REQUEST (%s)\n", otg_state_string(musb)); DBG(1, "SESSION_REQUEST (%s)\n", otg_state_string(musb));
/* IRQ arrives from ID pin sense or (later, if VBUS power /* IRQ arrives from ID pin sense or (later, if VBUS power
...@@ -519,6 +522,8 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, ...@@ -519,6 +522,8 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
case OTG_STATE_A_WAIT_BCON: case OTG_STATE_A_WAIT_BCON:
case OTG_STATE_A_WAIT_VRISE: case OTG_STATE_A_WAIT_VRISE:
if (musb->vbuserr_retry) { if (musb->vbuserr_retry) {
void __iomem *mbase = musb->mregs;
musb->vbuserr_retry--; musb->vbuserr_retry--;
ignore = 1; ignore = 1;
devctl |= MUSB_DEVCTL_SESSION; devctl |= MUSB_DEVCTL_SESSION;
...@@ -622,6 +627,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, ...@@ -622,6 +627,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
if (int_usb & MUSB_INTR_CONNECT) { if (int_usb & MUSB_INTR_CONNECT) {
struct usb_hcd *hcd = musb_to_hcd(musb); struct usb_hcd *hcd = musb_to_hcd(musb);
void __iomem *mbase = musb->mregs;
handled = IRQ_HANDLED; handled = IRQ_HANDLED;
musb->is_active = 1; musb->is_active = 1;
...@@ -2007,7 +2013,6 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) ...@@ -2007,7 +2013,6 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
/* host side needs more setup */ /* host side needs more setup */
if (is_host_enabled(musb)) { if (is_host_enabled(musb)) {
struct usb_hcd *hcd = musb_to_hcd(musb); struct usb_hcd *hcd = musb_to_hcd(musb);
u8 busctl;
otg_set_host(musb->xceiv, &hcd->self); otg_set_host(musb->xceiv, &hcd->self);
...@@ -2018,9 +2023,9 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) ...@@ -2018,9 +2023,9 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
/* program PHY to use external vBus if required */ /* program PHY to use external vBus if required */
if (plat->extvbus) { if (plat->extvbus) {
busctl = musb_readb(musb->mregs, MUSB_ULPI_BUSCONTROL); u8 busctl = musb_read_ulpi_buscontrol(musb->mregs);
busctl |= MUSB_ULPI_USE_EXTVBUS; busctl |= MUSB_ULPI_USE_EXTVBUS;
musb_writeb(musb->mregs, MUSB_ULPI_BUSCONTROL, busctl); musb_write_ulpi_buscontrol(musb->mregs, busctl);
} }
} }
......
...@@ -469,7 +469,7 @@ struct musb_csr_regs { ...@@ -469,7 +469,7 @@ struct musb_csr_regs {
struct musb_context_registers { struct musb_context_registers {
#if defined(CONFIG_ARCH_OMAP34XX) || defined(CONFIG_ARCH_OMAP2430) #ifdef CONFIG_PM
u32 otg_sysconfig, otg_forcestandby; u32 otg_sysconfig, otg_forcestandby;
#endif #endif
u8 power; u8 power;
...@@ -483,7 +483,7 @@ struct musb_context_registers { ...@@ -483,7 +483,7 @@ struct musb_context_registers {
struct musb_csr_regs index_regs[MUSB_C_NUM_EPS]; struct musb_csr_regs index_regs[MUSB_C_NUM_EPS];
}; };
#if defined(CONFIG_ARCH_OMAP34XX) || defined(CONFIG_ARCH_OMAP2430) #ifdef CONFIG_PM
extern void musb_platform_save_context(struct musb *musb, extern void musb_platform_save_context(struct musb *musb,
struct musb_context_registers *musb_context); struct musb_context_registers *musb_context);
extern void musb_platform_restore_context(struct musb *musb, extern void musb_platform_restore_context(struct musb *musb,
......
...@@ -1689,7 +1689,7 @@ void musb_host_rx(struct musb *musb, u8 epnum) ...@@ -1689,7 +1689,7 @@ void musb_host_rx(struct musb *musb, u8 epnum)
dma->desired_mode = 1; dma->desired_mode = 1;
if (rx_count < hw_ep->max_packet_sz_rx) { if (rx_count < hw_ep->max_packet_sz_rx) {
length = rx_count; length = rx_count;
dma->bDesiredMode = 0; dma->desired_mode = 0;
} else { } else {
length = urb->transfer_buffer_length; length = urb->transfer_buffer_length;
} }
......
...@@ -326,6 +326,11 @@ static inline void musb_write_rxfifoadd(void __iomem *mbase, u16 c_off) ...@@ -326,6 +326,11 @@ static inline void musb_write_rxfifoadd(void __iomem *mbase, u16 c_off)
musb_writew(mbase, MUSB_RXFIFOADD, c_off); musb_writew(mbase, MUSB_RXFIFOADD, c_off);
} }
static inline void musb_write_ulpi_buscontrol(void __iomem *mbase, u8 val)
{
musb_writeb(mbase, MUSB_ULPI_BUSCONTROL, val);
}
static inline u8 musb_read_txfifosz(void __iomem *mbase) static inline u8 musb_read_txfifosz(void __iomem *mbase)
{ {
return musb_readb(mbase, MUSB_TXFIFOSZ); return musb_readb(mbase, MUSB_TXFIFOSZ);
...@@ -346,6 +351,11 @@ static inline u16 musb_read_rxfifoadd(void __iomem *mbase) ...@@ -346,6 +351,11 @@ static inline u16 musb_read_rxfifoadd(void __iomem *mbase)
return musb_readw(mbase, MUSB_RXFIFOADD); return musb_readw(mbase, MUSB_RXFIFOADD);
} }
static inline u8 musb_read_ulpi_buscontrol(void __iomem *mbase)
{
return musb_readb(mbase, MUSB_ULPI_BUSCONTROL);
}
static inline u8 musb_read_configdata(void __iomem *mbase) static inline u8 musb_read_configdata(void __iomem *mbase)
{ {
musb_writeb(mbase, MUSB_INDEX, 0); musb_writeb(mbase, MUSB_INDEX, 0);
...@@ -510,20 +520,33 @@ static inline void musb_write_rxfifoadd(void __iomem *mbase, u16 c_off) ...@@ -510,20 +520,33 @@ static inline void musb_write_rxfifoadd(void __iomem *mbase, u16 c_off)
{ {
} }
static inline void musb_write_ulpi_buscontrol(void __iomem *mbase, u8 val)
{
}
static inline u8 musb_read_txfifosz(void __iomem *mbase) static inline u8 musb_read_txfifosz(void __iomem *mbase)
{ {
return 0;
} }
static inline u16 musb_read_txfifoadd(void __iomem *mbase) static inline u16 musb_read_txfifoadd(void __iomem *mbase)
{ {
return 0;
} }
static inline u8 musb_read_rxfifosz(void __iomem *mbase) static inline u8 musb_read_rxfifosz(void __iomem *mbase)
{ {
return 0;
} }
static inline u16 musb_read_rxfifoadd(void __iomem *mbase) static inline u16 musb_read_rxfifoadd(void __iomem *mbase)
{ {
return 0;
}
static inline u8 musb_read_ulpi_buscontrol(void __iomem *mbase)
{
return 0;
} }
static inline u8 musb_read_configdata(void __iomem *mbase) static inline u8 musb_read_configdata(void __iomem *mbase)
...@@ -577,22 +600,27 @@ static inline void musb_write_txhubport(void __iomem *mbase, u8 epnum, ...@@ -577,22 +600,27 @@ static inline void musb_write_txhubport(void __iomem *mbase, u8 epnum,
static inline u8 musb_read_rxfunaddr(void __iomem *mbase, u8 epnum) static inline u8 musb_read_rxfunaddr(void __iomem *mbase, u8 epnum)
{ {
return 0;
} }
static inline u8 musb_read_rxhubaddr(void __iomem *mbase, u8 epnum) static inline u8 musb_read_rxhubaddr(void __iomem *mbase, u8 epnum)
{ {
return 0;
} }
static inline u8 musb_read_rxhubport(void __iomem *mbase, u8 epnum) static inline u8 musb_read_rxhubport(void __iomem *mbase, u8 epnum)
{ {
return 0;
} }
static inline u8 musb_read_txfunaddr(void __iomem *mbase, u8 epnum) static inline u8 musb_read_txfunaddr(void __iomem *mbase, u8 epnum)
{ {
return 0;
} }
static inline u8 musb_read_txhubaddr(void __iomem *mbase, u8 epnum) static inline u8 musb_read_txhubaddr(void __iomem *mbase, u8 epnum)
{ {
return 0;
} }
static inline void musb_read_txhubport(void __iomem *mbase, u8 epnum) static inline void musb_read_txhubport(void __iomem *mbase, u8 epnum)
......
...@@ -474,14 +474,14 @@ config USB_SERIAL_OTI6858 ...@@ -474,14 +474,14 @@ config USB_SERIAL_OTI6858
config USB_SERIAL_QCAUX config USB_SERIAL_QCAUX
tristate "USB Qualcomm Auxiliary Serial Port Driver" tristate "USB Qualcomm Auxiliary Serial Port Driver"
---help--- help
Say Y here if you want to use the auxiliary serial ports provided Say Y here if you want to use the auxiliary serial ports provided
by many modems based on Qualcomm chipsets. These ports often use by many modems based on Qualcomm chipsets. These ports often use
a proprietary protocol called DM and cannot be used for AT- or a proprietary protocol called DM and cannot be used for AT- or
PPP-based communication. PPP-based communication.
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
module will be called moto_modem. If unsure, choose N. module will be called qcaux. If unsure, choose N.
config USB_SERIAL_QUALCOMM config USB_SERIAL_QUALCOMM
tristate "USB Qualcomm Serial modem" tristate "USB Qualcomm Serial modem"
......
...@@ -313,11 +313,6 @@ static int cp210x_set_config(struct usb_serial_port *port, u8 request, ...@@ -313,11 +313,6 @@ static int cp210x_set_config(struct usb_serial_port *port, u8 request,
return -EPROTO; return -EPROTO;
} }
/* Single data value */
result = usb_control_msg(serial->dev,
usb_sndctrlpipe(serial->dev, 0),
request, REQTYPE_HOST_TO_DEVICE, data[0],
0, NULL, 0, 300);
return 0; return 0;
} }
......
...@@ -91,7 +91,7 @@ struct ftdi_private { ...@@ -91,7 +91,7 @@ struct ftdi_private {
unsigned long tx_outstanding_bytes; unsigned long tx_outstanding_bytes;
unsigned long tx_outstanding_urbs; unsigned long tx_outstanding_urbs;
unsigned short max_packet_size; unsigned short max_packet_size;
struct mutex cfg_lock; /* Avoid mess by parallel calls of config ioctl() */ struct mutex cfg_lock; /* Avoid mess by parallel calls of config ioctl() and change_speed() */
}; };
/* struct ftdi_sio_quirk is used by devices requiring special attention. */ /* struct ftdi_sio_quirk is used by devices requiring special attention. */
...@@ -658,6 +658,7 @@ static struct usb_device_id id_table_combined [] = { ...@@ -658,6 +658,7 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(EVOLUTION_VID, EVOLUTION_ER1_PID) }, { USB_DEVICE(EVOLUTION_VID, EVOLUTION_ER1_PID) },
{ USB_DEVICE(EVOLUTION_VID, EVO_HYBRID_PID) }, { USB_DEVICE(EVOLUTION_VID, EVO_HYBRID_PID) },
{ USB_DEVICE(EVOLUTION_VID, EVO_RCM4_PID) }, { USB_DEVICE(EVOLUTION_VID, EVO_RCM4_PID) },
{ USB_DEVICE(CONTEC_VID, CONTEC_COM1USBH_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_ARTEMIS_PID) }, { USB_DEVICE(FTDI_VID, FTDI_ARTEMIS_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16_PID) }, { USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16C_PID) }, { USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16C_PID) },
...@@ -1272,8 +1273,8 @@ static int set_serial_info(struct tty_struct *tty, ...@@ -1272,8 +1273,8 @@ static int set_serial_info(struct tty_struct *tty,
(priv->flags & ASYNC_SPD_MASK)) || (priv->flags & ASYNC_SPD_MASK)) ||
(((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) && (((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) &&
(old_priv.custom_divisor != priv->custom_divisor))) { (old_priv.custom_divisor != priv->custom_divisor))) {
mutex_unlock(&priv->cfg_lock);
change_speed(tty, port); change_speed(tty, port);
mutex_unlock(&priv->cfg_lock);
} }
else else
mutex_unlock(&priv->cfg_lock); mutex_unlock(&priv->cfg_lock);
...@@ -2264,9 +2265,11 @@ static void ftdi_set_termios(struct tty_struct *tty, ...@@ -2264,9 +2265,11 @@ static void ftdi_set_termios(struct tty_struct *tty,
clear_mctrl(port, TIOCM_DTR | TIOCM_RTS); clear_mctrl(port, TIOCM_DTR | TIOCM_RTS);
} else { } else {
/* set the baudrate determined before */ /* set the baudrate determined before */
mutex_lock(&priv->cfg_lock);
if (change_speed(tty, port)) if (change_speed(tty, port))
dev_err(&port->dev, "%s urb failed to set baudrate\n", dev_err(&port->dev, "%s urb failed to set baudrate\n",
__func__); __func__);
mutex_unlock(&priv->cfg_lock);
/* Ensure RTS and DTR are raised when baudrate changed from 0 */ /* Ensure RTS and DTR are raised when baudrate changed from 0 */
if (!old_termios || (old_termios->c_cflag & CBAUD) == B0) if (!old_termios || (old_termios->c_cflag & CBAUD) == B0)
set_mctrl(port, TIOCM_DTR | TIOCM_RTS); set_mctrl(port, TIOCM_DTR | TIOCM_RTS);
......
...@@ -500,6 +500,13 @@ ...@@ -500,6 +500,13 @@
#define CONTEC_VID 0x06CE /* Vendor ID */ #define CONTEC_VID 0x06CE /* Vendor ID */
#define CONTEC_COM1USBH_PID 0x8311 /* COM-1(USB)H */ #define CONTEC_COM1USBH_PID 0x8311 /* COM-1(USB)H */
/*
* Contec products (http://www.contec.com)
* Submitted by Daniel Sangorrin
*/
#define CONTEC_VID 0x06CE /* Vendor ID */
#define CONTEC_COM1USBH_PID 0x8311 /* COM-1(USB)H */
/* /*
* Definitions for B&B Electronics products. * Definitions for B&B Electronics products.
*/ */
......
...@@ -130,7 +130,7 @@ int usb_serial_generic_open(struct tty_struct *tty, struct usb_serial_port *port ...@@ -130,7 +130,7 @@ int usb_serial_generic_open(struct tty_struct *tty, struct usb_serial_port *port
spin_unlock_irqrestore(&port->lock, flags); spin_unlock_irqrestore(&port->lock, flags);
/* if we have a bulk endpoint, start reading from it */ /* if we have a bulk endpoint, start reading from it */
if (serial->num_bulk_in) { if (port->bulk_in_size) {
/* Start reading from the device */ /* Start reading from the device */
usb_fill_bulk_urb(port->read_urb, serial->dev, usb_fill_bulk_urb(port->read_urb, serial->dev,
usb_rcvbulkpipe(serial->dev, usb_rcvbulkpipe(serial->dev,
...@@ -159,10 +159,10 @@ static void generic_cleanup(struct usb_serial_port *port) ...@@ -159,10 +159,10 @@ static void generic_cleanup(struct usb_serial_port *port)
dbg("%s - port %d", __func__, port->number); dbg("%s - port %d", __func__, port->number);
if (serial->dev) { if (serial->dev) {
/* shutdown any bulk reads that might be going on */ /* shutdown any bulk transfers that might be going on */
if (serial->num_bulk_out) if (port->bulk_out_size)
usb_kill_urb(port->write_urb); usb_kill_urb(port->write_urb);
if (serial->num_bulk_in) if (port->bulk_in_size)
usb_kill_urb(port->read_urb); usb_kill_urb(port->read_urb);
} }
} }
...@@ -333,15 +333,15 @@ int usb_serial_generic_write(struct tty_struct *tty, ...@@ -333,15 +333,15 @@ int usb_serial_generic_write(struct tty_struct *tty,
dbg("%s - port %d", __func__, port->number); dbg("%s - port %d", __func__, port->number);
/* only do something if we have a bulk out endpoint */
if (!port->bulk_out_size)
return -ENODEV;
if (count == 0) { if (count == 0) {
dbg("%s - write request of 0 bytes", __func__); dbg("%s - write request of 0 bytes", __func__);
return 0; return 0;
} }
/* only do something if we have a bulk out endpoint */
if (!serial->num_bulk_out)
return 0;
if (serial->type->max_in_flight_urbs) if (serial->type->max_in_flight_urbs)
return usb_serial_multi_urb_write(tty, port, return usb_serial_multi_urb_write(tty, port,
buf, count); buf, count);
...@@ -364,14 +364,19 @@ int usb_serial_generic_write_room(struct tty_struct *tty) ...@@ -364,14 +364,19 @@ int usb_serial_generic_write_room(struct tty_struct *tty)
int room = 0; int room = 0;
dbg("%s - port %d", __func__, port->number); dbg("%s - port %d", __func__, port->number);
if (!port->bulk_out_size)
return 0;
spin_lock_irqsave(&port->lock, flags); spin_lock_irqsave(&port->lock, flags);
if (serial->type->max_in_flight_urbs) { if (serial->type->max_in_flight_urbs) {
if (port->urbs_in_flight < serial->type->max_in_flight_urbs) if (port->urbs_in_flight < serial->type->max_in_flight_urbs)
room = port->bulk_out_size * room = port->bulk_out_size *
(serial->type->max_in_flight_urbs - (serial->type->max_in_flight_urbs -
port->urbs_in_flight); port->urbs_in_flight);
} else if (serial->num_bulk_out) } else {
room = kfifo_avail(&port->write_fifo); room = kfifo_avail(&port->write_fifo);
}
spin_unlock_irqrestore(&port->lock, flags); spin_unlock_irqrestore(&port->lock, flags);
dbg("%s - returns %d", __func__, room); dbg("%s - returns %d", __func__, room);
...@@ -382,15 +387,18 @@ int usb_serial_generic_chars_in_buffer(struct tty_struct *tty) ...@@ -382,15 +387,18 @@ int usb_serial_generic_chars_in_buffer(struct tty_struct *tty)
{ {
struct usb_serial_port *port = tty->driver_data; struct usb_serial_port *port = tty->driver_data;
struct usb_serial *serial = port->serial; struct usb_serial *serial = port->serial;
int chars = 0;
unsigned long flags; unsigned long flags;
int chars;
dbg("%s - port %d", __func__, port->number); dbg("%s - port %d", __func__, port->number);
if (!port->bulk_out_size)
return 0;
spin_lock_irqsave(&port->lock, flags); spin_lock_irqsave(&port->lock, flags);
if (serial->type->max_in_flight_urbs) if (serial->type->max_in_flight_urbs)
chars = port->tx_bytes_flight; chars = port->tx_bytes_flight;
else if (serial->num_bulk_out) else
chars = kfifo_len(&port->write_fifo); chars = kfifo_len(&port->write_fifo);
spin_unlock_irqrestore(&port->lock, flags); spin_unlock_irqrestore(&port->lock, flags);
...@@ -415,11 +423,13 @@ void usb_serial_generic_resubmit_read_urb(struct usb_serial_port *port, ...@@ -415,11 +423,13 @@ void usb_serial_generic_resubmit_read_urb(struct usb_serial_port *port,
((serial->type->read_bulk_callback) ? ((serial->type->read_bulk_callback) ?
serial->type->read_bulk_callback : serial->type->read_bulk_callback :
usb_serial_generic_read_bulk_callback), port); usb_serial_generic_read_bulk_callback), port);
result = usb_submit_urb(urb, mem_flags); result = usb_submit_urb(urb, mem_flags);
if (result) if (result && result != -EPERM) {
dev_err(&port->dev, dev_err(&port->dev,
"%s - failed resubmitting read urb, error %d\n", "%s - failed resubmitting read urb, error %d\n",
__func__, result); __func__, result);
}
} }
EXPORT_SYMBOL_GPL(usb_serial_generic_resubmit_read_urb); EXPORT_SYMBOL_GPL(usb_serial_generic_resubmit_read_urb);
...@@ -498,23 +508,18 @@ void usb_serial_generic_write_bulk_callback(struct urb *urb) ...@@ -498,23 +508,18 @@ void usb_serial_generic_write_bulk_callback(struct urb *urb)
if (port->urbs_in_flight < 0) if (port->urbs_in_flight < 0)
port->urbs_in_flight = 0; port->urbs_in_flight = 0;
spin_unlock_irqrestore(&port->lock, flags); spin_unlock_irqrestore(&port->lock, flags);
if (status) {
dbg("%s - nonzero multi-urb write bulk status "
"received: %d", __func__, status);
return;
}
} else { } else {
port->write_urb_busy = 0; port->write_urb_busy = 0;
if (status) { if (status)
dbg("%s - nonzero multi-urb write bulk status "
"received: %d", __func__, status);
kfifo_reset_out(&port->write_fifo); kfifo_reset_out(&port->write_fifo);
} else else
usb_serial_generic_write_start(port); usb_serial_generic_write_start(port);
} }
if (status)
dbg("%s - non-zero urb status: %d", __func__, status);
usb_serial_port_softint(port); usb_serial_port_softint(port);
} }
EXPORT_SYMBOL_GPL(usb_serial_generic_write_bulk_callback); EXPORT_SYMBOL_GPL(usb_serial_generic_write_bulk_callback);
......
...@@ -288,7 +288,9 @@ static int option_resume(struct usb_serial *serial); ...@@ -288,7 +288,9 @@ static int option_resume(struct usb_serial *serial);
#define QUALCOMM_VENDOR_ID 0x05C6 #define QUALCOMM_VENDOR_ID 0x05C6
#define MAXON_VENDOR_ID 0x16d8 #define CMOTECH_VENDOR_ID 0x16d8
#define CMOTECH_PRODUCT_6008 0x6008
#define CMOTECH_PRODUCT_6280 0x6280
#define TELIT_VENDOR_ID 0x1bc7 #define TELIT_VENDOR_ID 0x1bc7
#define TELIT_PRODUCT_UC864E 0x1003 #define TELIT_PRODUCT_UC864E 0x1003
...@@ -309,6 +311,7 @@ static int option_resume(struct usb_serial *serial); ...@@ -309,6 +311,7 @@ static int option_resume(struct usb_serial *serial);
#define DLINK_VENDOR_ID 0x1186 #define DLINK_VENDOR_ID 0x1186
#define DLINK_PRODUCT_DWM_652 0x3e04 #define DLINK_PRODUCT_DWM_652 0x3e04
#define DLINK_PRODUCT_DWM_652_U5 0xce16 #define DLINK_PRODUCT_DWM_652_U5 0xce16
#define DLINK_PRODUCT_DWM_652_U5A 0xce1e
#define QISDA_VENDOR_ID 0x1da5 #define QISDA_VENDOR_ID 0x1da5
#define QISDA_PRODUCT_H21_4512 0x4512 #define QISDA_PRODUCT_H21_4512 0x4512
...@@ -332,6 +335,24 @@ static int option_resume(struct usb_serial *serial); ...@@ -332,6 +335,24 @@ static int option_resume(struct usb_serial *serial);
#define ALCATEL_VENDOR_ID 0x1bbb #define ALCATEL_VENDOR_ID 0x1bbb
#define ALCATEL_PRODUCT_X060S 0x0000 #define ALCATEL_PRODUCT_X060S 0x0000
#define PIRELLI_VENDOR_ID 0x1266
#define PIRELLI_PRODUCT_C100_1 0x1002
#define PIRELLI_PRODUCT_C100_2 0x1003
#define PIRELLI_PRODUCT_1004 0x1004
#define PIRELLI_PRODUCT_1005 0x1005
#define PIRELLI_PRODUCT_1006 0x1006
#define PIRELLI_PRODUCT_1007 0x1007
#define PIRELLI_PRODUCT_1008 0x1008
#define PIRELLI_PRODUCT_1009 0x1009
#define PIRELLI_PRODUCT_100A 0x100a
#define PIRELLI_PRODUCT_100B 0x100b
#define PIRELLI_PRODUCT_100C 0x100c
#define PIRELLI_PRODUCT_100D 0x100d
#define PIRELLI_PRODUCT_100E 0x100e
#define PIRELLI_PRODUCT_100F 0x100f
#define PIRELLI_PRODUCT_1011 0x1011
#define PIRELLI_PRODUCT_1012 0x1012
/* Airplus products */ /* Airplus products */
#define AIRPLUS_VENDOR_ID 0x1011 #define AIRPLUS_VENDOR_ID 0x1011
#define AIRPLUS_PRODUCT_MCD650 0x3198 #define AIRPLUS_PRODUCT_MCD650 0x3198
...@@ -547,7 +568,8 @@ static const struct usb_device_id option_ids[] = { ...@@ -547,7 +568,8 @@ 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(MAXON_VENDOR_ID, 0x6280) }, /* 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(TELIT_VENDOR_ID, TELIT_PRODUCT_UC864E) }, { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_UC864E) },
{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_UC864G) }, { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_UC864G) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MF622, 0xff, 0xff, 0xff) }, /* ZTE WCDMA products */ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MF622, 0xff, 0xff, 0xff) }, /* ZTE WCDMA products */
...@@ -659,6 +681,7 @@ static const struct usb_device_id option_ids[] = { ...@@ -659,6 +681,7 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE(BENQ_VENDOR_ID, BENQ_PRODUCT_H10) }, { USB_DEVICE(BENQ_VENDOR_ID, BENQ_PRODUCT_H10) },
{ USB_DEVICE(DLINK_VENDOR_ID, DLINK_PRODUCT_DWM_652) }, { USB_DEVICE(DLINK_VENDOR_ID, DLINK_PRODUCT_DWM_652) },
{ USB_DEVICE(ALINK_VENDOR_ID, DLINK_PRODUCT_DWM_652_U5) }, /* Yes, ALINK_VENDOR_ID */ { USB_DEVICE(ALINK_VENDOR_ID, DLINK_PRODUCT_DWM_652_U5) }, /* Yes, ALINK_VENDOR_ID */
{ USB_DEVICE(ALINK_VENDOR_ID, DLINK_PRODUCT_DWM_652_U5A) },
{ USB_DEVICE(QISDA_VENDOR_ID, QISDA_PRODUCT_H21_4512) }, { USB_DEVICE(QISDA_VENDOR_ID, QISDA_PRODUCT_H21_4512) },
{ USB_DEVICE(QISDA_VENDOR_ID, QISDA_PRODUCT_H21_4523) }, { USB_DEVICE(QISDA_VENDOR_ID, QISDA_PRODUCT_H21_4523) },
{ USB_DEVICE(QISDA_VENDOR_ID, QISDA_PRODUCT_H20_4515) }, { USB_DEVICE(QISDA_VENDOR_ID, QISDA_PRODUCT_H20_4515) },
...@@ -666,7 +689,6 @@ static const struct usb_device_id option_ids[] = { ...@@ -666,7 +689,6 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE(TOSHIBA_VENDOR_ID, TOSHIBA_PRODUCT_G450) }, { USB_DEVICE(TOSHIBA_VENDOR_ID, TOSHIBA_PRODUCT_G450) },
{ USB_DEVICE(TOSHIBA_VENDOR_ID, TOSHIBA_PRODUCT_HSDPA_MINICARD ) }, /* Toshiba 3G HSDPA == Novatel Expedite EU870D MiniCard */ { USB_DEVICE(TOSHIBA_VENDOR_ID, TOSHIBA_PRODUCT_HSDPA_MINICARD ) }, /* Toshiba 3G HSDPA == Novatel Expedite EU870D MiniCard */
{ USB_DEVICE(ALINK_VENDOR_ID, 0x9000) }, { USB_DEVICE(ALINK_VENDOR_ID, 0x9000) },
{ USB_DEVICE(ALINK_VENDOR_ID, 0xce16) },
{ USB_DEVICE_AND_INTERFACE_INFO(ALINK_VENDOR_ID, ALINK_PRODUCT_3GU, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ALINK_VENDOR_ID, ALINK_PRODUCT_3GU, 0xff, 0xff, 0xff) },
{ USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X060S) }, { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X060S) },
{ USB_DEVICE(AIRPLUS_VENDOR_ID, AIRPLUS_PRODUCT_MCD650) }, { USB_DEVICE(AIRPLUS_VENDOR_ID, AIRPLUS_PRODUCT_MCD650) },
...@@ -675,6 +697,24 @@ static const struct usb_device_id option_ids[] = { ...@@ -675,6 +697,24 @@ static const struct usb_device_id option_ids[] = {
.driver_info = (kernel_ulong_t)&four_g_w14_blacklist .driver_info = (kernel_ulong_t)&four_g_w14_blacklist
}, },
{ USB_DEVICE(HAIER_VENDOR_ID, HAIER_PRODUCT_CE100) }, { USB_DEVICE(HAIER_VENDOR_ID, HAIER_PRODUCT_CE100) },
/* Pirelli */
{ USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_C100_1)},
{ USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_C100_2)},
{ USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1004)},
{ USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1005)},
{ USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1006)},
{ USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1007)},
{ USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1008)},
{ USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1009)},
{ USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100A)},
{ USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100B) },
{ USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100C) },
{ USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100D) },
{ USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100E) },
{ USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100F) },
{ USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1011)},
{ USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1012)},
{ } /* Terminating entry */ { } /* Terminating entry */
}; };
MODULE_DEVICE_TABLE(usb, option_ids); MODULE_DEVICE_TABLE(usb, option_ids);
...@@ -798,12 +838,19 @@ static int option_probe(struct usb_serial *serial, ...@@ -798,12 +838,19 @@ static int option_probe(struct usb_serial *serial,
const struct usb_device_id *id) const struct usb_device_id *id)
{ {
struct option_intf_private *data; struct option_intf_private *data;
/* D-Link DWM 652 still exposes CD-Rom emulation interface in modem mode */ /* D-Link DWM 652 still exposes CD-Rom emulation interface in modem mode */
if (serial->dev->descriptor.idVendor == DLINK_VENDOR_ID && if (serial->dev->descriptor.idVendor == DLINK_VENDOR_ID &&
serial->dev->descriptor.idProduct == DLINK_PRODUCT_DWM_652 && serial->dev->descriptor.idProduct == DLINK_PRODUCT_DWM_652 &&
serial->interface->cur_altsetting->desc.bInterfaceClass == 0x8) serial->interface->cur_altsetting->desc.bInterfaceClass == 0x8)
return -ENODEV; return -ENODEV;
/* Bandrich modem and AT command interface is 0xff */
if ((serial->dev->descriptor.idVendor == BANDRICH_VENDOR_ID ||
serial->dev->descriptor.idVendor == PIRELLI_VENDOR_ID) &&
serial->interface->cur_altsetting->desc.bInterfaceClass != 0xff)
return -ENODEV;
data = serial->private = kzalloc(sizeof(struct option_intf_private), GFP_KERNEL); data = serial->private = kzalloc(sizeof(struct option_intf_private), GFP_KERNEL);
if (!data) if (!data)
return -ENOMEM; return -ENOMEM;
......
...@@ -47,6 +47,35 @@ static const struct usb_device_id id_table[] = { ...@@ -47,6 +47,35 @@ static const struct usb_device_id id_table[] = {
{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 */
{USB_DEVICE(0x1f45, 0x0001)}, /* Unknown Gobi QDL device */ {USB_DEVICE(0x1f45, 0x0001)}, /* Unknown Gobi QDL device */
{USB_DEVICE(0x413c, 0x8185)}, /* Dell Gobi 2000 QDL device (N0218, VU936) */
{USB_DEVICE(0x413c, 0x8186)}, /* Dell Gobi 2000 Modem device (N0218, VU936) */
{USB_DEVICE(0x05c6, 0x9224)}, /* Sony Gobi 2000 QDL device (N0279, VU730) */
{USB_DEVICE(0x05c6, 0x9225)}, /* Sony Gobi 2000 Modem device (N0279, VU730) */
{USB_DEVICE(0x05c6, 0x9244)}, /* Samsung Gobi 2000 QDL device (VL176) */
{USB_DEVICE(0x05c6, 0x9245)}, /* Samsung Gobi 2000 Modem device (VL176) */
{USB_DEVICE(0x03f0, 0x241d)}, /* HP Gobi 2000 QDL device (VP412) */
{USB_DEVICE(0x03f0, 0x251d)}, /* HP Gobi 2000 Modem device (VP412) */
{USB_DEVICE(0x05c6, 0x9214)}, /* Acer Gobi 2000 QDL device (VP413) */
{USB_DEVICE(0x05c6, 0x9215)}, /* Acer Gobi 2000 Modem device (VP413) */
{USB_DEVICE(0x05c6, 0x9264)}, /* Asus Gobi 2000 QDL device (VR305) */
{USB_DEVICE(0x05c6, 0x9265)}, /* Asus Gobi 2000 Modem device (VR305) */
{USB_DEVICE(0x05c6, 0x9234)}, /* Top Global Gobi 2000 QDL device (VR306) */
{USB_DEVICE(0x05c6, 0x9235)}, /* Top Global Gobi 2000 Modem device (VR306) */
{USB_DEVICE(0x05c6, 0x9274)}, /* iRex Technologies Gobi 2000 QDL device (VR307) */
{USB_DEVICE(0x05c6, 0x9275)}, /* iRex Technologies Gobi 2000 Modem device (VR307) */
{USB_DEVICE(0x1199, 0x9000)}, /* Sierra Wireless Gobi 2000 QDL device (VT773) */
{USB_DEVICE(0x1199, 0x9001)}, /* Sierra Wireless Gobi 2000 Modem device (VT773) */
{USB_DEVICE(0x1199, 0x9002)}, /* Sierra Wireless Gobi 2000 Modem device (VT773) */
{USB_DEVICE(0x1199, 0x9003)}, /* Sierra Wireless Gobi 2000 Modem device (VT773) */
{USB_DEVICE(0x1199, 0x9004)}, /* Sierra Wireless Gobi 2000 Modem device (VT773) */
{USB_DEVICE(0x1199, 0x9005)}, /* Sierra Wireless Gobi 2000 Modem device (VT773) */
{USB_DEVICE(0x1199, 0x9006)}, /* Sierra Wireless Gobi 2000 Modem device (VT773) */
{USB_DEVICE(0x1199, 0x9007)}, /* 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, 0x900a)}, /* Sierra Wireless Gobi 2000 Modem device (VT773) */
{USB_DEVICE(0x16d8, 0x8001)}, /* CMDTech Gobi 2000 QDL device (VU922) */
{USB_DEVICE(0x16d8, 0x8002)}, /* CMDTech Gobi 2000 Modem device (VU922) */
{ } /* Terminating entry */ { } /* Terminating entry */
}; };
MODULE_DEVICE_TABLE(usb, id_table); MODULE_DEVICE_TABLE(usb, id_table);
......
...@@ -374,6 +374,15 @@ UNUSUAL_DEV( 0x04ce, 0x0002, 0x0074, 0x0074, ...@@ -374,6 +374,15 @@ UNUSUAL_DEV( 0x04ce, 0x0002, 0x0074, 0x0074,
US_SC_DEVICE, US_PR_DEVICE, NULL, US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_FIX_INQUIRY), US_FL_FIX_INQUIRY),
/* Reported by Ondrej Zary <linux@rainbow-software.org>
* The device reports one sector more and breaks when that sector is accessed
*/
UNUSUAL_DEV( 0x04ce, 0x0002, 0x026c, 0x026c,
"ScanLogic",
"SL11R-IDE",
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_FIX_CAPACITY),
/* Reported by Kriston Fincher <kriston@airmail.net> /* Reported by Kriston Fincher <kriston@airmail.net>
* Patch submitted by Sean Millichamp <sean@bruenor.org> * Patch submitted by Sean Millichamp <sean@bruenor.org>
* This is to support the Panasonic PalmCam PV-SD4090 * This is to support the Panasonic PalmCam PV-SD4090
...@@ -1380,20 +1389,6 @@ UNUSUAL_DEV( 0x0f19, 0x0105, 0x0100, 0x0100, ...@@ -1380,20 +1389,6 @@ UNUSUAL_DEV( 0x0f19, 0x0105, 0x0100, 0x0100,
US_SC_DEVICE, US_PR_DEVICE, NULL, US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_IGNORE_RESIDUE ), US_FL_IGNORE_RESIDUE ),
/* Jeremy Katz <katzj@redhat.com>:
* The Blackberry Pearl can run in two modes; a usb-storage only mode
* and a mode that allows access via mass storage and to its database.
* The berry_charge module will set the device to dual mode and thus we
* should ignore its native mode if that module is built
*/
#ifdef CONFIG_USB_BERRY_CHARGE
UNUSUAL_DEV( 0x0fca, 0x0006, 0x0001, 0x0001,
"RIM",
"Blackberry Pearl",
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_IGNORE_DEVICE ),
#endif
/* Reported by Michael Stattmann <michael@stattmann.com> */ /* Reported by Michael Stattmann <michael@stattmann.com> */
UNUSUAL_DEV( 0x0fce, 0xd008, 0x0000, 0x0000, UNUSUAL_DEV( 0x0fce, 0xd008, 0x0000, 0x0000,
"Sony Ericsson", "Sony Ericsson",
......
...@@ -1055,7 +1055,8 @@ typedef void (*usb_complete_t)(struct urb *); ...@@ -1055,7 +1055,8 @@ typedef void (*usb_complete_t)(struct urb *);
* @number_of_packets: Lists the number of ISO transfer buffers. * @number_of_packets: Lists the number of ISO transfer buffers.
* @interval: Specifies the polling interval for interrupt or isochronous * @interval: Specifies the polling interval for interrupt or isochronous
* transfers. The units are frames (milliseconds) for full and low * transfers. The units are frames (milliseconds) for full and low
* speed devices, and microframes (1/8 millisecond) for highspeed ones. * speed devices, and microframes (1/8 millisecond) for highspeed
* and SuperSpeed devices.
* @error_count: Returns the number of ISO transfers that reported errors. * @error_count: Returns the number of ISO transfers that reported errors.
* @context: For use in completion functions. This normally points to * @context: For use in completion functions. This normally points to
* request-specific driver context. * request-specific driver context.
...@@ -1286,9 +1287,16 @@ static inline void usb_fill_bulk_urb(struct urb *urb, ...@@ -1286,9 +1287,16 @@ static inline void usb_fill_bulk_urb(struct urb *urb,
* *
* Initializes a interrupt urb with the proper information needed to submit * Initializes a interrupt urb with the proper information needed to submit
* it to a device. * it to a device.
* Note that high speed interrupt endpoints use a logarithmic encoding of *
* the endpoint interval, and express polling intervals in microframes * Note that High Speed and SuperSpeed interrupt endpoints use a logarithmic
* (eight per millisecond) rather than in frames (one per millisecond). * encoding of the endpoint interval, and express polling intervals in
* microframes (eight per millisecond) rather than in frames (one per
* millisecond).
*
* Wireless USB also uses the logarithmic encoding, but specifies it in units of
* 128us instead of 125us. For Wireless USB devices, the interval is passed
* through to the host controller, rather than being translated into microframe
* units.
*/ */
static inline void usb_fill_int_urb(struct urb *urb, static inline void usb_fill_int_urb(struct urb *urb,
struct usb_device *dev, struct usb_device *dev,
...@@ -1305,7 +1313,7 @@ static inline void usb_fill_int_urb(struct urb *urb, ...@@ -1305,7 +1313,7 @@ static inline void usb_fill_int_urb(struct urb *urb,
urb->transfer_buffer_length = buffer_length; urb->transfer_buffer_length = buffer_length;
urb->complete = complete_fn; urb->complete = complete_fn;
urb->context = context; urb->context = context;
if (dev->speed == USB_SPEED_HIGH) if (dev->speed == USB_SPEED_HIGH || dev->speed == USB_SPEED_SUPER)
urb->interval = 1 << (interval - 1); urb->interval = 1 << (interval - 1);
else else
urb->interval = interval; urb->interval = interval;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment