mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-27 03:10:12 +00:00
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 ...
This commit is contained in:
commit
8fdb7e9f61
32 changed files with 336 additions and 149 deletions
|
@ -160,7 +160,7 @@ Description:
|
|||
match the driver to the device. For example:
|
||||
# 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
|
||||
Contact: Oliver Neukum <oliver@neukum.org>
|
||||
Description:
|
||||
|
|
|
@ -1441,7 +1441,7 @@ static int acm_resume(struct usb_interface *intf)
|
|||
wb = acm->delayed_wb;
|
||||
acm->delayed_wb = NULL;
|
||||
spin_unlock_irq(&acm->write_lock);
|
||||
acm_start_wb(acm, acm->delayed_wb);
|
||||
acm_start_wb(acm, wb);
|
||||
} else {
|
||||
spin_unlock_irq(&acm->write_lock);
|
||||
}
|
||||
|
|
|
@ -52,7 +52,8 @@ MODULE_DEVICE_TABLE (usb, wdm_ids);
|
|||
#define WDM_READ 4
|
||||
#define WDM_INT_STALL 5
|
||||
#define WDM_POLL_RUNNING 6
|
||||
|
||||
#define WDM_RESPONDING 7
|
||||
#define WDM_SUSPENDING 8
|
||||
|
||||
#define WDM_MAX 16
|
||||
|
||||
|
@ -87,9 +88,7 @@ struct wdm_device {
|
|||
int count;
|
||||
dma_addr_t shandle;
|
||||
dma_addr_t ihandle;
|
||||
struct mutex wlock;
|
||||
struct mutex rlock;
|
||||
struct mutex plock;
|
||||
struct mutex lock;
|
||||
wait_queue_head_t wait;
|
||||
struct work_struct rxwork;
|
||||
int werr;
|
||||
|
@ -117,21 +116,22 @@ static void wdm_in_callback(struct urb *urb)
|
|||
int status = urb->status;
|
||||
|
||||
spin_lock(&desc->iuspin);
|
||||
clear_bit(WDM_RESPONDING, &desc->flags);
|
||||
|
||||
if (status) {
|
||||
switch (status) {
|
||||
case -ENOENT:
|
||||
dev_dbg(&desc->intf->dev,
|
||||
"nonzero urb status received: -ENOENT");
|
||||
break;
|
||||
goto skip_error;
|
||||
case -ECONNRESET:
|
||||
dev_dbg(&desc->intf->dev,
|
||||
"nonzero urb status received: -ECONNRESET");
|
||||
break;
|
||||
goto skip_error;
|
||||
case -ESHUTDOWN:
|
||||
dev_dbg(&desc->intf->dev,
|
||||
"nonzero urb status received: -ESHUTDOWN");
|
||||
break;
|
||||
goto skip_error;
|
||||
case -EPIPE:
|
||||
dev_err(&desc->intf->dev,
|
||||
"nonzero urb status received: -EPIPE\n");
|
||||
|
@ -147,6 +147,7 @@ static void wdm_in_callback(struct urb *urb)
|
|||
desc->reslength = urb->actual_length;
|
||||
memmove(desc->ubuf + desc->length, desc->inbuf, desc->reslength);
|
||||
desc->length += desc->reslength;
|
||||
skip_error:
|
||||
wake_up(&desc->wait);
|
||||
|
||||
set_bit(WDM_READ, &desc->flags);
|
||||
|
@ -229,13 +230,16 @@ static void wdm_int_callback(struct urb *urb)
|
|||
desc->response->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
|
||||
spin_lock(&desc->iuspin);
|
||||
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);
|
||||
dev_dbg(&desc->intf->dev, "%s: usb_submit_urb %d",
|
||||
__func__, rv);
|
||||
}
|
||||
spin_unlock(&desc->iuspin);
|
||||
if (rv < 0) {
|
||||
clear_bit(WDM_RESPONDING, &desc->flags);
|
||||
if (rv == -EPERM)
|
||||
return;
|
||||
if (rv == -ENOMEM) {
|
||||
|
@ -305,14 +309,38 @@ static ssize_t wdm_write
|
|||
if (we < 0)
|
||||
return -EIO;
|
||||
|
||||
r = mutex_lock_interruptible(&desc->wlock); /* concurrent writes */
|
||||
rv = -ERESTARTSYS;
|
||||
if (r)
|
||||
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;
|
||||
if (r) {
|
||||
kfree(buf);
|
||||
goto outnl;
|
||||
}
|
||||
|
||||
if (test_bit(WDM_DISCONNECTING, &desc->flags)) {
|
||||
kfree(buf);
|
||||
rv = -ENODEV;
|
||||
goto outnp;
|
||||
}
|
||||
|
||||
r = usb_autopm_get_interface(desc->intf);
|
||||
if (r < 0)
|
||||
if (r < 0) {
|
||||
kfree(buf);
|
||||
goto outnp;
|
||||
}
|
||||
|
||||
if (!file->f_flags && O_NONBLOCK)
|
||||
r = wait_event_interruptible(desc->wait, !test_bit(WDM_IN_USE,
|
||||
|
@ -320,24 +348,8 @@ static ssize_t wdm_write
|
|||
else
|
||||
if (test_bit(WDM_IN_USE, &desc->flags))
|
||||
r = -EAGAIN;
|
||||
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) {
|
||||
if (r < 0) {
|
||||
kfree(buf);
|
||||
rv = -EFAULT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
@ -374,7 +386,7 @@ static ssize_t wdm_write
|
|||
out:
|
||||
usb_autopm_put_interface(desc->intf);
|
||||
outnp:
|
||||
mutex_unlock(&desc->wlock);
|
||||
mutex_unlock(&desc->lock);
|
||||
outnl:
|
||||
return rv < 0 ? rv : count;
|
||||
}
|
||||
|
@ -387,7 +399,7 @@ static ssize_t wdm_read
|
|||
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)
|
||||
return -ERESTARTSYS;
|
||||
|
||||
|
@ -424,11 +436,8 @@ static ssize_t wdm_read
|
|||
spin_lock_irq(&desc->iuspin);
|
||||
|
||||
if (desc->rerr) { /* read completed, error happened */
|
||||
int t = desc->rerr;
|
||||
desc->rerr = 0;
|
||||
spin_unlock_irq(&desc->iuspin);
|
||||
dev_err(&desc->intf->dev,
|
||||
"reading had resulted in %d\n", t);
|
||||
rv = -EIO;
|
||||
goto err;
|
||||
}
|
||||
|
@ -465,9 +474,7 @@ static ssize_t wdm_read
|
|||
rv = cntr;
|
||||
|
||||
err:
|
||||
mutex_unlock(&desc->rlock);
|
||||
if (rv < 0 && rv != -EAGAIN)
|
||||
dev_err(&desc->intf->dev, "wdm_read: exit error\n");
|
||||
mutex_unlock(&desc->lock);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -533,7 +540,7 @@ static int wdm_open(struct inode *inode, struct file *file)
|
|||
}
|
||||
intf->needs_remote_wakeup = 1;
|
||||
|
||||
mutex_lock(&desc->plock);
|
||||
mutex_lock(&desc->lock);
|
||||
if (!desc->count++) {
|
||||
rv = usb_submit_urb(desc->validity, GFP_KERNEL);
|
||||
if (rv < 0) {
|
||||
|
@ -544,7 +551,7 @@ static int wdm_open(struct inode *inode, struct file *file)
|
|||
} else {
|
||||
rv = 0;
|
||||
}
|
||||
mutex_unlock(&desc->plock);
|
||||
mutex_unlock(&desc->lock);
|
||||
usb_autopm_put_interface(desc->intf);
|
||||
out:
|
||||
mutex_unlock(&wdm_mutex);
|
||||
|
@ -556,9 +563,9 @@ static int wdm_release(struct inode *inode, struct file *file)
|
|||
struct wdm_device *desc = file->private_data;
|
||||
|
||||
mutex_lock(&wdm_mutex);
|
||||
mutex_lock(&desc->plock);
|
||||
mutex_lock(&desc->lock);
|
||||
desc->count--;
|
||||
mutex_unlock(&desc->plock);
|
||||
mutex_unlock(&desc->lock);
|
||||
|
||||
if (!desc->count) {
|
||||
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)
|
|||
desc = kzalloc(sizeof(struct wdm_device), GFP_KERNEL);
|
||||
if (!desc)
|
||||
goto out;
|
||||
mutex_init(&desc->wlock);
|
||||
mutex_init(&desc->rlock);
|
||||
mutex_init(&desc->plock);
|
||||
mutex_init(&desc->lock);
|
||||
spin_lock_init(&desc->iuspin);
|
||||
init_waitqueue_head(&desc->wait);
|
||||
desc->wMaxCommand = maxcom;
|
||||
|
@ -771,14 +776,17 @@ static void wdm_disconnect(struct usb_interface *intf)
|
|||
/* to terminate pending flushes */
|
||||
clear_bit(WDM_IN_USE, &desc->flags);
|
||||
spin_unlock_irqrestore(&desc->iuspin, flags);
|
||||
cancel_work_sync(&desc->rxwork);
|
||||
mutex_lock(&desc->lock);
|
||||
kill_urbs(desc);
|
||||
cancel_work_sync(&desc->rxwork);
|
||||
mutex_unlock(&desc->lock);
|
||||
wake_up_all(&desc->wait);
|
||||
if (!desc->count)
|
||||
cleanup(desc);
|
||||
mutex_unlock(&wdm_mutex);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int wdm_suspend(struct usb_interface *intf, pm_message_t message)
|
||||
{
|
||||
struct wdm_device *desc = usb_get_intfdata(intf);
|
||||
|
@ -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);
|
||||
|
||||
mutex_lock(&desc->plock);
|
||||
#ifdef CONFIG_PM
|
||||
/* if this is an autosuspend the caller does the locking */
|
||||
if (!(message.event & PM_EVENT_AUTO))
|
||||
mutex_lock(&desc->lock);
|
||||
spin_lock_irq(&desc->iuspin);
|
||||
|
||||
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;
|
||||
} 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);
|
||||
#ifdef CONFIG_PM
|
||||
cancel_work_sync(&desc->rxwork);
|
||||
}
|
||||
#endif
|
||||
mutex_unlock(&desc->plock);
|
||||
if (!(message.event & PM_EVENT_AUTO))
|
||||
mutex_unlock(&desc->lock);
|
||||
|
||||
return rv;
|
||||
}
|
||||
#endif
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int wdm_resume(struct usb_interface *intf)
|
||||
{
|
||||
struct wdm_device *desc = usb_get_intfdata(intf);
|
||||
int rv;
|
||||
|
||||
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);
|
||||
mutex_unlock(&desc->plock);
|
||||
|
||||
return rv;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int wdm_pre_reset(struct usb_interface *intf)
|
||||
{
|
||||
struct wdm_device *desc = usb_get_intfdata(intf);
|
||||
|
||||
mutex_lock(&desc->plock);
|
||||
mutex_lock(&desc->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -841,7 +861,7 @@ static int wdm_post_reset(struct usb_interface *intf)
|
|||
int rv;
|
||||
|
||||
rv = recover_from_urb_loss(desc);
|
||||
mutex_unlock(&desc->plock);
|
||||
mutex_unlock(&desc->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -849,9 +869,11 @@ static struct usb_driver wdm_driver = {
|
|||
.name = "cdc_wdm",
|
||||
.probe = wdm_probe,
|
||||
.disconnect = wdm_disconnect,
|
||||
#ifdef CONFIG_PM
|
||||
.suspend = wdm_suspend,
|
||||
.resume = wdm_resume,
|
||||
.reset_resume = wdm_resume,
|
||||
#endif
|
||||
.pre_reset = wdm_pre_reset,
|
||||
.post_reset = wdm_post_reset,
|
||||
.id_table = wdm_ids,
|
||||
|
|
|
@ -1207,6 +1207,13 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
|
|||
free_async(as);
|
||||
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->pipe = (uurb->type << 30) |
|
||||
|
@ -1345,10 +1352,14 @@ static int processcompl(struct async *as, void __user * __user *arg)
|
|||
void __user *addr = as->userurb;
|
||||
unsigned int i;
|
||||
|
||||
if (as->userbuffer && urb->actual_length)
|
||||
if (copy_to_user(as->userbuffer, urb->transfer_buffer,
|
||||
urb->actual_length))
|
||||
if (as->userbuffer && urb->actual_length) {
|
||||
if (urb->number_of_packets > 0) /* Isochronous */
|
||||
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;
|
||||
}
|
||||
if (put_user(as->status, &userurb->status))
|
||||
goto err_out;
|
||||
if (put_user(urb->actual_length, &userurb->actual_length))
|
||||
|
|
|
@ -453,6 +453,7 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
|
|||
if (urb->interval > (1 << 15))
|
||||
return -EINVAL;
|
||||
max = 1 << 15;
|
||||
break;
|
||||
case USB_SPEED_WIRELESS:
|
||||
if (urb->interval > 16)
|
||||
return -EINVAL;
|
||||
|
|
|
@ -747,7 +747,7 @@ config USB_MASS_STORAGE
|
|||
which may be used with composite framework.
|
||||
|
||||
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.
|
||||
|
||||
config USB_G_SERIAL
|
||||
|
|
|
@ -266,7 +266,7 @@ struct usb_ep * __init usb_ep_autoconfig (
|
|||
}
|
||||
|
||||
#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) ||
|
||||
(USB_ENDPOINT_XFER_ISOC == type)) {
|
||||
if (USB_DIR_IN & desc->bEndpointAddress)
|
||||
|
|
|
@ -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 usb_gadget *gadget = c->cdev->gadget;
|
||||
|
@ -2954,7 +2954,6 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f)
|
|||
autoconf_fail:
|
||||
ERROR(fsg, "unable to autoconfigure all endpoints\n");
|
||||
rc = -ENOTSUPP;
|
||||
fsg_unbind(c, f);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
|
|
@ -136,6 +136,12 @@
|
|||
#define gadget_is_r8a66597(g) 0
|
||||
#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
|
||||
|
@ -192,6 +198,8 @@ static inline int usb_gadget_controller_number(struct usb_gadget *gadget)
|
|||
return 0x24;
|
||||
else if (gadget_is_r8a66597(gadget))
|
||||
return 0x25;
|
||||
else if (gadget_is_s3c_hsotg(gadget))
|
||||
return 0x26;
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
if (the_controller) {
|
||||
WARNING(dev, "ignoring %s\n", pci_name(pdev));
|
||||
pr_warning("ignoring %s\n", pci_name(pdev));
|
||||
return -EBUSY;
|
||||
}
|
||||
if (!pdev->irq) {
|
||||
|
|
|
@ -211,8 +211,6 @@ static int __init cdc_do_config(struct usb_configuration *c)
|
|||
ret = fsg_add(c->cdev, c, fsg_common);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include <linux/module.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/clk.h>
|
||||
|
|
|
@ -12,7 +12,7 @@ fhci-objs := fhci-hcd.o fhci-hub.o fhci-q.o fhci-mem.o \
|
|||
ifeq ($(CONFIG_FHCI_DEBUG),y)
|
||||
fhci-objs += fhci-dbg.o
|
||||
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/
|
||||
|
||||
|
@ -25,7 +25,7 @@ obj-$(CONFIG_USB_ISP1362_HCD) += isp1362-hcd.o
|
|||
obj-$(CONFIG_USB_OHCI_HCD) += ohci-hcd.o
|
||||
obj-$(CONFIG_USB_UHCI_HCD) += uhci-hcd.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_CS) += sl811_cs.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)
|
|||
/* endpoints can be iso streams. for now, we don't
|
||||
* accelerate iso completions ... so spin a while.
|
||||
*/
|
||||
if (qh->hw->hw_info1 == 0) {
|
||||
if (qh->hw == NULL) {
|
||||
ehci_vdbg (ehci, "iso delay\n");
|
||||
goto idle_timeout;
|
||||
}
|
||||
|
|
|
@ -1123,8 +1123,8 @@ iso_stream_find (struct ehci_hcd *ehci, struct urb *urb)
|
|||
urb->interval);
|
||||
}
|
||||
|
||||
/* if dev->ep [epnum] is a QH, info1.maxpacket is nonzero */
|
||||
} else if (unlikely (stream->hw_info1 != 0)) {
|
||||
/* if dev->ep [epnum] is a QH, hw is set */
|
||||
} else if (unlikely (stream->hw != NULL)) {
|
||||
ehci_dbg (ehci, "dev %s ep%d%s, not iso??\n",
|
||||
urb->dev->devpath, epnum,
|
||||
usb_pipein(urb->pipe) ? "in" : "out");
|
||||
|
@ -1565,13 +1565,27 @@ itd_patch(
|
|||
static inline void
|
||||
itd_link (struct ehci_hcd *ehci, unsigned frame, struct ehci_itd *itd)
|
||||
{
|
||||
/* always prepend ITD/SITD ... only QH tree is order-sensitive */
|
||||
itd->itd_next = ehci->pshadow [frame];
|
||||
itd->hw_next = ehci->periodic [frame];
|
||||
ehci->pshadow [frame].itd = itd;
|
||||
union ehci_shadow *prev = &ehci->pshadow[frame];
|
||||
__hc32 *hw_p = &ehci->periodic[frame];
|
||||
union ehci_shadow here = *prev;
|
||||
__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;
|
||||
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 */
|
||||
|
|
|
@ -394,9 +394,8 @@ struct ehci_iso_sched {
|
|||
* acts like a qh would, if EHCI had them for ISO.
|
||||
*/
|
||||
struct ehci_iso_stream {
|
||||
/* first two fields match QH, but info1 == 0 */
|
||||
__hc32 hw_next;
|
||||
__hc32 hw_info1;
|
||||
/* first field matches ehci_hq, but is NULL */
|
||||
struct ehci_qh_hw *hw;
|
||||
|
||||
u32 refcount;
|
||||
u8 bEndpointAddress;
|
||||
|
|
|
@ -418,7 +418,7 @@ static u8 alloc_usb_address(struct r8a66597 *r8a66597, struct urb *urb)
|
|||
|
||||
/* this function must be called with interrupt disabled */
|
||||
static void free_usb_address(struct r8a66597 *r8a66597,
|
||||
struct r8a66597_device *dev)
|
||||
struct r8a66597_device *dev, int reset)
|
||||
{
|
||||
int port;
|
||||
|
||||
|
@ -430,7 +430,13 @@ static void free_usb_address(struct r8a66597 *r8a66597,
|
|||
dev->state = USB_STATE_DEFAULT;
|
||||
r8a66597->address_map &= ~(1 << dev->address);
|
||||
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);
|
||||
kfree(dev);
|
||||
|
||||
|
@ -1069,7 +1075,7 @@ static void r8a66597_usb_disconnect(struct r8a66597 *r8a66597, int port)
|
|||
struct r8a66597_device *dev = r8a66597->root_hub[port].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);
|
||||
}
|
||||
|
@ -2085,7 +2091,7 @@ static void update_usb_address_map(struct r8a66597 *r8a66597,
|
|||
spin_lock_irqsave(&r8a66597->lock, flags);
|
||||
dev = get_r8a66597_device(r8a66597, addr);
|
||||
disable_r8a66597_pipe_all(r8a66597, dev);
|
||||
free_usb_address(r8a66597, dev);
|
||||
free_usb_address(r8a66597, dev, 0);
|
||||
put_child_connect_map(r8a66597, addr);
|
||||
spin_unlock_irqrestore(&r8a66597->lock, flags);
|
||||
}
|
||||
|
@ -2228,7 +2234,7 @@ static int r8a66597_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
|
|||
rh->port |= (1 << USB_PORT_FEAT_RESET);
|
||||
|
||||
disable_r8a66597_pipe_all(r8a66597, dev);
|
||||
free_usb_address(r8a66597, dev);
|
||||
free_usb_address(r8a66597, dev, 1);
|
||||
|
||||
r8a66597_mdfy(r8a66597, USBRST, USBRST | UACT,
|
||||
get_dvstctr_reg(port));
|
||||
|
|
|
@ -566,8 +566,13 @@ static inline unsigned int xhci_get_endpoint_interval(struct usb_device *udev,
|
|||
if (interval < 3)
|
||||
interval = 3;
|
||||
if ((1 << interval) != 8*ep->desc.bInterval)
|
||||
dev_warn(&udev->dev, "ep %#x - rounding interval to %d microframes\n",
|
||||
ep->desc.bEndpointAddress, 1 << interval);
|
||||
dev_warn(&udev->dev,
|
||||
"ep %#x - rounding interval"
|
||||
" to %d microframes, "
|
||||
"ep desc says %d microframes\n",
|
||||
ep->desc.bEndpointAddress,
|
||||
1 << interval,
|
||||
8*ep->desc.bInterval);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -1173,6 +1173,7 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci,
|
|||
cmd_completion = &virt_dev->cmd_completion;
|
||||
cmd_status = &virt_dev->cmd_status;
|
||||
}
|
||||
init_completion(cmd_completion);
|
||||
|
||||
if (!ctx_change)
|
||||
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,
|
|||
u8 devctl, u8 power)
|
||||
{
|
||||
irqreturn_t handled = IRQ_NONE;
|
||||
void __iomem *mbase = musb->mregs;
|
||||
|
||||
DBG(3, "<== Power=%02x, DevCtl=%02x, int_usb=0x%x\n", power, devctl,
|
||||
int_usb);
|
||||
|
@ -394,6 +393,8 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
|
|||
|
||||
if (devctl & MUSB_DEVCTL_HM) {
|
||||
#ifdef CONFIG_USB_MUSB_HDRC_HCD
|
||||
void __iomem *mbase = musb->mregs;
|
||||
|
||||
switch (musb->xceiv->state) {
|
||||
case OTG_STATE_A_SUSPEND:
|
||||
/* remote wakeup? later, GetPortStatus
|
||||
|
@ -471,6 +472,8 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
|
|||
#ifdef CONFIG_USB_MUSB_HDRC_HCD
|
||||
/* see manual for the order of the tests */
|
||||
if (int_usb & MUSB_INTR_SESSREQ) {
|
||||
void __iomem *mbase = musb->mregs;
|
||||
|
||||
DBG(1, "SESSION_REQUEST (%s)\n", otg_state_string(musb));
|
||||
|
||||
/* 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,
|
|||
case OTG_STATE_A_WAIT_BCON:
|
||||
case OTG_STATE_A_WAIT_VRISE:
|
||||
if (musb->vbuserr_retry) {
|
||||
void __iomem *mbase = musb->mregs;
|
||||
|
||||
musb->vbuserr_retry--;
|
||||
ignore = 1;
|
||||
devctl |= MUSB_DEVCTL_SESSION;
|
||||
|
@ -622,6 +627,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
|
|||
|
||||
if (int_usb & MUSB_INTR_CONNECT) {
|
||||
struct usb_hcd *hcd = musb_to_hcd(musb);
|
||||
void __iomem *mbase = musb->mregs;
|
||||
|
||||
handled = IRQ_HANDLED;
|
||||
musb->is_active = 1;
|
||||
|
@ -2007,7 +2013,6 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
|
|||
/* host side needs more setup */
|
||||
if (is_host_enabled(musb)) {
|
||||
struct usb_hcd *hcd = musb_to_hcd(musb);
|
||||
u8 busctl;
|
||||
|
||||
otg_set_host(musb->xceiv, &hcd->self);
|
||||
|
||||
|
@ -2018,9 +2023,9 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
|
|||
|
||||
/* program PHY to use external vBus if required */
|
||||
if (plat->extvbus) {
|
||||
busctl = musb_readb(musb->mregs, MUSB_ULPI_BUSCONTROL);
|
||||
u8 busctl = musb_read_ulpi_buscontrol(musb->mregs);
|
||||
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 {
|
|||
|
||||
struct musb_context_registers {
|
||||
|
||||
#if defined(CONFIG_ARCH_OMAP34XX) || defined(CONFIG_ARCH_OMAP2430)
|
||||
#ifdef CONFIG_PM
|
||||
u32 otg_sysconfig, otg_forcestandby;
|
||||
#endif
|
||||
u8 power;
|
||||
|
@ -483,7 +483,7 @@ struct musb_context_registers {
|
|||
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,
|
||||
struct musb_context_registers *musb_context);
|
||||
extern void musb_platform_restore_context(struct musb *musb,
|
||||
|
|
|
@ -1689,7 +1689,7 @@ void musb_host_rx(struct musb *musb, u8 epnum)
|
|||
dma->desired_mode = 1;
|
||||
if (rx_count < hw_ep->max_packet_sz_rx) {
|
||||
length = rx_count;
|
||||
dma->bDesiredMode = 0;
|
||||
dma->desired_mode = 0;
|
||||
} else {
|
||||
length = urb->transfer_buffer_length;
|
||||
}
|
||||
|
|
|
@ -326,6 +326,11 @@ static inline void musb_write_rxfifoadd(void __iomem *mbase, u16 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)
|
||||
{
|
||||
return musb_readb(mbase, MUSB_TXFIFOSZ);
|
||||
|
@ -346,6 +351,11 @@ static inline u16 musb_read_rxfifoadd(void __iomem *mbase)
|
|||
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)
|
||||
{
|
||||
musb_writeb(mbase, MUSB_INDEX, 0);
|
||||
|
@ -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)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline u16 musb_read_txfifoadd(void __iomem *mbase)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline u8 musb_read_rxfifosz(void __iomem *mbase)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
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)
|
||||
|
@ -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)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline u8 musb_read_rxhubaddr(void __iomem *mbase, u8 epnum)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline u8 musb_read_rxhubport(void __iomem *mbase, u8 epnum)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline u8 musb_read_txfunaddr(void __iomem *mbase, u8 epnum)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline u8 musb_read_txhubaddr(void __iomem *mbase, u8 epnum)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void musb_read_txhubport(void __iomem *mbase, u8 epnum)
|
||||
|
|
|
@ -474,14 +474,14 @@ config USB_SERIAL_OTI6858
|
|||
|
||||
config USB_SERIAL_QCAUX
|
||||
tristate "USB Qualcomm Auxiliary Serial Port Driver"
|
||||
---help---
|
||||
help
|
||||
Say Y here if you want to use the auxiliary serial ports provided
|
||||
by many modems based on Qualcomm chipsets. These ports often use
|
||||
a proprietary protocol called DM and cannot be used for AT- or
|
||||
PPP-based communication.
|
||||
|
||||
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
|
||||
tristate "USB Qualcomm Serial modem"
|
||||
|
|
|
@ -313,11 +313,6 @@ static int cp210x_set_config(struct usb_serial_port *port, u8 request,
|
|||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -91,7 +91,7 @@ struct ftdi_private {
|
|||
unsigned long tx_outstanding_bytes;
|
||||
unsigned long tx_outstanding_urbs;
|
||||
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. */
|
||||
|
@ -658,6 +658,7 @@ static struct usb_device_id id_table_combined [] = {
|
|||
{ USB_DEVICE(EVOLUTION_VID, EVOLUTION_ER1_PID) },
|
||||
{ USB_DEVICE(EVOLUTION_VID, EVO_HYBRID_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_ATIK_ATK16_PID) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16C_PID) },
|
||||
|
@ -1272,8 +1273,8 @@ static int set_serial_info(struct tty_struct *tty,
|
|||
(priv->flags & ASYNC_SPD_MASK)) ||
|
||||
(((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) &&
|
||||
(old_priv.custom_divisor != priv->custom_divisor))) {
|
||||
mutex_unlock(&priv->cfg_lock);
|
||||
change_speed(tty, port);
|
||||
mutex_unlock(&priv->cfg_lock);
|
||||
}
|
||||
else
|
||||
mutex_unlock(&priv->cfg_lock);
|
||||
|
@ -2264,9 +2265,11 @@ static void ftdi_set_termios(struct tty_struct *tty,
|
|||
clear_mctrl(port, TIOCM_DTR | TIOCM_RTS);
|
||||
} else {
|
||||
/* set the baudrate determined before */
|
||||
mutex_lock(&priv->cfg_lock);
|
||||
if (change_speed(tty, port))
|
||||
dev_err(&port->dev, "%s urb failed to set baudrate\n",
|
||||
__func__);
|
||||
mutex_unlock(&priv->cfg_lock);
|
||||
/* Ensure RTS and DTR are raised when baudrate changed from 0 */
|
||||
if (!old_termios || (old_termios->c_cflag & CBAUD) == B0)
|
||||
set_mctrl(port, TIOCM_DTR | TIOCM_RTS);
|
||||
|
|
|
@ -500,6 +500,13 @@
|
|||
#define CONTEC_VID 0x06CE /* Vendor ID */
|
||||
#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.
|
||||
*/
|
||||
|
|
|
@ -130,7 +130,7 @@ int usb_serial_generic_open(struct tty_struct *tty, struct usb_serial_port *port
|
|||
spin_unlock_irqrestore(&port->lock, flags);
|
||||
|
||||
/* 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 */
|
||||
usb_fill_bulk_urb(port->read_urb, serial->dev,
|
||||
usb_rcvbulkpipe(serial->dev,
|
||||
|
@ -159,10 +159,10 @@ static void generic_cleanup(struct usb_serial_port *port)
|
|||
dbg("%s - port %d", __func__, port->number);
|
||||
|
||||
if (serial->dev) {
|
||||
/* shutdown any bulk reads that might be going on */
|
||||
if (serial->num_bulk_out)
|
||||
/* shutdown any bulk transfers that might be going on */
|
||||
if (port->bulk_out_size)
|
||||
usb_kill_urb(port->write_urb);
|
||||
if (serial->num_bulk_in)
|
||||
if (port->bulk_in_size)
|
||||
usb_kill_urb(port->read_urb);
|
||||
}
|
||||
}
|
||||
|
@ -333,15 +333,15 @@ int usb_serial_generic_write(struct tty_struct *tty,
|
|||
|
||||
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) {
|
||||
dbg("%s - write request of 0 bytes", __func__);
|
||||
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)
|
||||
return usb_serial_multi_urb_write(tty, port,
|
||||
buf, count);
|
||||
|
@ -364,14 +364,19 @@ int usb_serial_generic_write_room(struct tty_struct *tty)
|
|||
int room = 0;
|
||||
|
||||
dbg("%s - port %d", __func__, port->number);
|
||||
|
||||
if (!port->bulk_out_size)
|
||||
return 0;
|
||||
|
||||
spin_lock_irqsave(&port->lock, flags);
|
||||
if (serial->type->max_in_flight_urbs) {
|
||||
if (port->urbs_in_flight < serial->type->max_in_flight_urbs)
|
||||
room = port->bulk_out_size *
|
||||
(serial->type->max_in_flight_urbs -
|
||||
port->urbs_in_flight);
|
||||
} else if (serial->num_bulk_out)
|
||||
} else {
|
||||
room = kfifo_avail(&port->write_fifo);
|
||||
}
|
||||
spin_unlock_irqrestore(&port->lock, flags);
|
||||
|
||||
dbg("%s - returns %d", __func__, room);
|
||||
|
@ -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 *serial = port->serial;
|
||||
int chars = 0;
|
||||
unsigned long flags;
|
||||
int chars;
|
||||
|
||||
dbg("%s - port %d", __func__, port->number);
|
||||
|
||||
if (!port->bulk_out_size)
|
||||
return 0;
|
||||
|
||||
spin_lock_irqsave(&port->lock, flags);
|
||||
if (serial->type->max_in_flight_urbs)
|
||||
chars = port->tx_bytes_flight;
|
||||
else if (serial->num_bulk_out)
|
||||
else
|
||||
chars = kfifo_len(&port->write_fifo);
|
||||
spin_unlock_irqrestore(&port->lock, flags);
|
||||
|
||||
|
@ -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 :
|
||||
usb_serial_generic_read_bulk_callback), port);
|
||||
|
||||
result = usb_submit_urb(urb, mem_flags);
|
||||
if (result)
|
||||
if (result && result != -EPERM) {
|
||||
dev_err(&port->dev,
|
||||
"%s - failed resubmitting read urb, error %d\n",
|
||||
__func__, result);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(usb_serial_generic_resubmit_read_urb);
|
||||
|
||||
|
@ -498,23 +508,18 @@ void usb_serial_generic_write_bulk_callback(struct urb *urb)
|
|||
if (port->urbs_in_flight < 0)
|
||||
port->urbs_in_flight = 0;
|
||||
spin_unlock_irqrestore(&port->lock, flags);
|
||||
|
||||
if (status) {
|
||||
dbg("%s - nonzero multi-urb write bulk status "
|
||||
"received: %d", __func__, status);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
port->write_urb_busy = 0;
|
||||
|
||||
if (status) {
|
||||
dbg("%s - nonzero multi-urb write bulk status "
|
||||
"received: %d", __func__, status);
|
||||
if (status)
|
||||
kfifo_reset_out(&port->write_fifo);
|
||||
} else
|
||||
else
|
||||
usb_serial_generic_write_start(port);
|
||||
}
|
||||
|
||||
if (status)
|
||||
dbg("%s - non-zero urb status: %d", __func__, status);
|
||||
|
||||
usb_serial_port_softint(port);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(usb_serial_generic_write_bulk_callback);
|
||||
|
|
|
@ -288,7 +288,9 @@ static int option_resume(struct usb_serial *serial);
|
|||
|
||||
#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_PRODUCT_UC864E 0x1003
|
||||
|
@ -309,6 +311,7 @@ static int option_resume(struct usb_serial *serial);
|
|||
#define DLINK_VENDOR_ID 0x1186
|
||||
#define DLINK_PRODUCT_DWM_652 0x3e04
|
||||
#define DLINK_PRODUCT_DWM_652_U5 0xce16
|
||||
#define DLINK_PRODUCT_DWM_652_U5A 0xce1e
|
||||
|
||||
#define QISDA_VENDOR_ID 0x1da5
|
||||
#define QISDA_PRODUCT_H21_4512 0x4512
|
||||
|
@ -332,6 +335,24 @@ static int option_resume(struct usb_serial *serial);
|
|||
#define ALCATEL_VENDOR_ID 0x1bbb
|
||||
#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 */
|
||||
#define AIRPLUS_VENDOR_ID 0x1011
|
||||
#define AIRPLUS_PRODUCT_MCD650 0x3198
|
||||
|
@ -547,7 +568,8 @@ static const struct usb_device_id option_ids[] = {
|
|||
{ USB_DEVICE(KYOCERA_VENDOR_ID, KYOCERA_PRODUCT_KPC680) },
|
||||
{ USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6000)}, /* ZTE AC8700 */
|
||||
{ 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_UC864G) },
|
||||
{ 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[] = {
|
|||
{ USB_DEVICE(BENQ_VENDOR_ID, BENQ_PRODUCT_H10) },
|
||||
{ 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_U5A) },
|
||||
{ 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_H20_4515) },
|
||||
|
@ -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_HSDPA_MINICARD ) }, /* Toshiba 3G HSDPA == Novatel Expedite EU870D MiniCard */
|
||||
{ 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(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X060S) },
|
||||
{ USB_DEVICE(AIRPLUS_VENDOR_ID, AIRPLUS_PRODUCT_MCD650) },
|
||||
|
@ -675,6 +697,24 @@ static const struct usb_device_id option_ids[] = {
|
|||
.driver_info = (kernel_ulong_t)&four_g_w14_blacklist
|
||||
},
|
||||
{ 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 */
|
||||
};
|
||||
MODULE_DEVICE_TABLE(usb, option_ids);
|
||||
|
@ -798,12 +838,19 @@ static int option_probe(struct usb_serial *serial,
|
|||
const struct usb_device_id *id)
|
||||
{
|
||||
struct option_intf_private *data;
|
||||
|
||||
/* D-Link DWM 652 still exposes CD-Rom emulation interface in modem mode */
|
||||
if (serial->dev->descriptor.idVendor == DLINK_VENDOR_ID &&
|
||||
serial->dev->descriptor.idProduct == DLINK_PRODUCT_DWM_652 &&
|
||||
serial->interface->cur_altsetting->desc.bInterfaceClass == 0x8)
|
||||
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);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
|
|
@ -47,6 +47,35 @@ static const struct usb_device_id id_table[] = {
|
|||
{USB_DEVICE(0x05c6, 0x9221)}, /* Generic Gobi QDL device */
|
||||
{USB_DEVICE(0x05c6, 0x9231)}, /* Generic 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 */
|
||||
};
|
||||
MODULE_DEVICE_TABLE(usb, id_table);
|
||||
|
|
|
@ -374,6 +374,15 @@ UNUSUAL_DEV( 0x04ce, 0x0002, 0x0074, 0x0074,
|
|||
US_SC_DEVICE, US_PR_DEVICE, NULL,
|
||||
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>
|
||||
* Patch submitted by Sean Millichamp <sean@bruenor.org>
|
||||
* This is to support the Panasonic PalmCam PV-SD4090
|
||||
|
@ -1380,20 +1389,6 @@ UNUSUAL_DEV( 0x0f19, 0x0105, 0x0100, 0x0100,
|
|||
US_SC_DEVICE, US_PR_DEVICE, NULL,
|
||||
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> */
|
||||
UNUSUAL_DEV( 0x0fce, 0xd008, 0x0000, 0x0000,
|
||||
"Sony Ericsson",
|
||||
|
|
|
@ -1055,7 +1055,8 @@ typedef void (*usb_complete_t)(struct urb *);
|
|||
* @number_of_packets: Lists the number of ISO transfer buffers.
|
||||
* @interval: Specifies the polling interval for interrupt or isochronous
|
||||
* 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.
|
||||
* @context: For use in completion functions. This normally points to
|
||||
* request-specific driver context.
|
||||
|
@ -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
|
||||
* it to a device.
|
||||
* Note that high speed interrupt endpoints use a logarithmic encoding of
|
||||
* the endpoint interval, and express polling intervals in microframes
|
||||
* (eight per millisecond) rather than in frames (one per millisecond).
|
||||
*
|
||||
* Note that High Speed and SuperSpeed interrupt endpoints use a logarithmic
|
||||
* 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,
|
||||
struct usb_device *dev,
|
||||
|
@ -1305,7 +1313,7 @@ static inline void usb_fill_int_urb(struct urb *urb,
|
|||
urb->transfer_buffer_length = buffer_length;
|
||||
urb->complete = complete_fn;
|
||||
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);
|
||||
else
|
||||
urb->interval = interval;
|
||||
|
|
Loading…
Reference in a new issue