summaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/Kconfig1
-rw-r--r--drivers/usb/class/cdc-acm.c30
-rw-r--r--drivers/usb/class/cdc-wdm.c185
-rw-r--r--drivers/usb/core/driver.c120
-rw-r--r--drivers/usb/core/hcd-pci.c7
-rw-r--r--drivers/usb/core/hcd.c6
-rw-r--r--drivers/usb/core/hub.c232
-rw-r--r--drivers/usb/core/sysfs.c23
-rw-r--r--drivers/usb/core/urb.c21
-rw-r--r--drivers/usb/core/usb.c2
-rw-r--r--drivers/usb/core/usb.h1
-rw-r--r--drivers/usb/dwc3/ep0.c15
-rw-r--r--drivers/usb/dwc3/gadget.c2
-rw-r--r--drivers/usb/gadget/composite.c7
-rw-r--r--drivers/usb/gadget/epautoconf.c2
-rw-r--r--drivers/usb/gadget/f_loopback.c2
-rw-r--r--drivers/usb/gadget/f_mass_storage.c36
-rw-r--r--drivers/usb/gadget/file_storage.c26
-rw-r--r--drivers/usb/gadget/fsl_udc_core.c4
-rw-r--r--drivers/usb/gadget/langwell_udc.c107
-rw-r--r--drivers/usb/gadget/langwell_udc.h1
-rw-r--r--drivers/usb/gadget/storage_common.c46
-rw-r--r--drivers/usb/host/Kconfig17
-rw-r--r--drivers/usb/host/ehci-dbg.c2
-rw-r--r--drivers/usb/host/ehci-fsl.c54
-rw-r--r--drivers/usb/host/ehci-fsl.h4
-rw-r--r--drivers/usb/host/ehci-hcd.c10
-rw-r--r--drivers/usb/host/ehci-hub.c8
-rw-r--r--drivers/usb/host/ehci-ls1x.c159
-rw-r--r--drivers/usb/host/ehci-pci.c6
-rw-r--r--drivers/usb/host/ehci-pxa168.c363
-rw-r--r--drivers/usb/host/ehci-spear.c83
-rw-r--r--drivers/usb/host/fsl-mph-dr-of.c1
-rw-r--r--drivers/usb/host/imx21-dbg.c2
-rw-r--r--drivers/usb/host/isp1362-hcd.c20
-rw-r--r--drivers/usb/host/ohci-at91.c24
-rw-r--r--drivers/usb/host/ohci-dbg.c12
-rw-r--r--drivers/usb/host/ohci-exynos.c6
-rw-r--r--drivers/usb/host/ohci-pci.c4
-rw-r--r--drivers/usb/host/pci-quirks.c17
-rw-r--r--drivers/usb/host/uhci-hcd.c3
-rw-r--r--drivers/usb/host/xhci-hub.c43
-rw-r--r--drivers/usb/host/xhci-mem.c43
-rw-r--r--drivers/usb/host/xhci-ring.c78
-rw-r--r--drivers/usb/host/xhci.c5
-rw-r--r--drivers/usb/host/xhci.h1
-rw-r--r--drivers/usb/misc/emi26.c3
-rw-r--r--drivers/usb/misc/emi62.c3
-rw-r--r--drivers/usb/misc/usbsevseg.c2
-rw-r--r--drivers/usb/musb/davinci.c3
-rw-r--r--drivers/usb/musb/musb_core.c5
-rw-r--r--drivers/usb/musb/musb_io.h3
-rw-r--r--drivers/usb/musb/omap2430.c4
-rw-r--r--drivers/usb/otg/Kconfig18
-rw-r--r--drivers/usb/otg/Makefile1
-rw-r--r--drivers/usb/otg/langwell_otg.c2347
-rw-r--r--drivers/usb/otg/mv_otg.c2
-rw-r--r--drivers/usb/renesas_usbhs/mod_gadget.c2
-rw-r--r--drivers/usb/serial/Kconfig9
-rw-r--r--drivers/usb/serial/Makefile1
-rw-r--r--drivers/usb/serial/aircable.c30
-rw-r--r--drivers/usb/serial/ark3116.c30
-rw-r--r--drivers/usb/serial/belkin_sa.c35
-rw-r--r--drivers/usb/serial/ch341.c27
-rw-r--r--drivers/usb/serial/cp210x.c156
-rw-r--r--drivers/usb/serial/cyberjack.c36
-rw-r--r--drivers/usb/serial/cypress_m8.c64
-rw-r--r--drivers/usb/serial/digi_acceleport.c45
-rw-r--r--drivers/usb/serial/empeg.c34
-rw-r--r--drivers/usb/serial/f81232.c405
-rw-r--r--drivers/usb/serial/ftdi_sio.c48
-rw-r--r--drivers/usb/serial/ftdi_sio_ids.h30
-rw-r--r--drivers/usb/serial/funsoft.c25
-rw-r--r--drivers/usb/serial/garmin_gps.c40
-rw-r--r--drivers/usb/serial/generic.c19
-rw-r--r--drivers/usb/serial/hp4x.c31
-rw-r--r--drivers/usb/serial/io_edgeport.c66
-rw-r--r--drivers/usb/serial/io_tables.h10
-rw-r--r--drivers/usb/serial/io_ti.c54
-rw-r--r--drivers/usb/serial/ipaq.c28
-rw-r--r--drivers/usb/serial/ipw.c32
-rw-r--r--drivers/usb/serial/ir-usb.c30
-rw-r--r--drivers/usb/serial/iuu_phoenix.c31
-rw-r--r--drivers/usb/serial/keyspan.c48
-rw-r--r--drivers/usb/serial/keyspan.h10
-rw-r--r--drivers/usb/serial/keyspan_pda.c62
-rw-r--r--drivers/usb/serial/kl5kusb105.c37
-rw-r--r--drivers/usb/serial/kobil_sct.c37
-rw-r--r--drivers/usb/serial/mct_u232.c34
-rw-r--r--drivers/usb/serial/mos7720.c46
-rw-r--r--drivers/usb/serial/mos7840.c59
-rw-r--r--drivers/usb/serial/moto_modem.c26
-rw-r--r--drivers/usb/serial/navman.c25
-rw-r--r--drivers/usb/serial/omninet.c38
-rw-r--r--drivers/usb/serial/opticon.c25
-rw-r--r--drivers/usb/serial/option.c89
-rw-r--r--drivers/usb/serial/oti6858.c36
-rw-r--r--drivers/usb/serial/pl2303.c31
-rw-r--r--drivers/usb/serial/qcaux.c33
-rw-r--r--drivers/usb/serial/qcserial.c140
-rw-r--r--drivers/usb/serial/safe_serial.c24
-rw-r--r--drivers/usb/serial/siemens_mpi.c30
-rw-r--r--drivers/usb/serial/sierra.c37
-rw-r--r--drivers/usb/serial/spcp8x5.c31
-rw-r--r--drivers/usb/serial/ssu100.c40
-rw-r--r--drivers/usb/serial/symbolserial.c25
-rw-r--r--drivers/usb/serial/ti_usb_3410_5052.c46
-rw-r--r--drivers/usb/serial/ti_usb_3410_5052.h4
-rw-r--r--drivers/usb/serial/usb-serial.c77
-rw-r--r--drivers/usb/serial/usb_debug.c26
-rw-r--r--drivers/usb/serial/visor.c37
-rw-r--r--drivers/usb/serial/vivopay-serial.c31
-rw-r--r--drivers/usb/serial/whiteheat.c47
-rw-r--r--drivers/usb/serial/zio.c26
-rw-r--r--drivers/usb/storage/alauda.c1
-rw-r--r--drivers/usb/storage/cypress_atacb.c1
-rw-r--r--drivers/usb/storage/datafab.c1
-rw-r--r--drivers/usb/storage/ene_ub6250.c27
-rw-r--r--drivers/usb/storage/freecom.c1
-rw-r--r--drivers/usb/storage/isd200.c1
-rw-r--r--drivers/usb/storage/jumpshot.c1
-rw-r--r--drivers/usb/storage/karma.c1
-rw-r--r--drivers/usb/storage/onetouch.c1
-rw-r--r--drivers/usb/storage/realtek_cr.c15
-rw-r--r--drivers/usb/storage/scsiglue.c55
-rw-r--r--drivers/usb/storage/sddr09.c1
-rw-r--r--drivers/usb/storage/sddr55.c1
-rw-r--r--drivers/usb/storage/shuttle_usbat.c1
-rw-r--r--drivers/usb/storage/transport.c3
-rw-r--r--drivers/usb/storage/transport.h39
-rw-r--r--drivers/usb/storage/uas.c328
-rw-r--r--drivers/usb/storage/usb.c111
-rw-r--r--drivers/usb/storage/usb.h7
-rw-r--r--drivers/usb/usb-skeleton.c18
-rw-r--r--drivers/usb/wusbcore/Kconfig2
135 files changed, 2350 insertions, 5073 deletions
diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig
index 75823a1abeb..0b0afc81a54 100644
--- a/drivers/usb/Kconfig
+++ b/drivers/usb/Kconfig
@@ -76,6 +76,7 @@ config USB_ARCH_HAS_EHCI
default y if MICROBLAZE
default y if SPARC_LEON
default y if ARCH_MMP
+ default y if MACH_LOONGSON1
default PCI
# some non-PCI HCDs implement xHCI
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index 9543b19d410..6dcc3a3fe6d 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -39,6 +39,7 @@
#include <linux/serial.h>
#include <linux/tty_driver.h>
#include <linux/tty_flip.h>
+#include <linux/serial.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/uaccess.h>
@@ -773,10 +774,37 @@ static int acm_tty_tiocmset(struct tty_struct *tty,
return acm_set_control(acm, acm->ctrlout = newctrl);
}
+static int get_serial_info(struct acm *acm, struct serial_struct __user *info)
+{
+ struct serial_struct tmp;
+
+ if (!info)
+ return -EINVAL;
+
+ memset(&tmp, 0, sizeof(tmp));
+ tmp.flags = ASYNC_LOW_LATENCY;
+ tmp.xmit_fifo_size = acm->writesize;
+ tmp.baud_base = le32_to_cpu(acm->line.dwDTERate);
+
+ if (copy_to_user(info, &tmp, sizeof(tmp)))
+ return -EFAULT;
+ else
+ return 0;
+}
+
static int acm_tty_ioctl(struct tty_struct *tty,
unsigned int cmd, unsigned long arg)
{
- return -ENOIOCTLCMD;
+ struct acm *acm = tty->driver_data;
+ int rv = -ENOIOCTLCMD;
+
+ switch (cmd) {
+ case TIOCGSERIAL: /* gets serial port data */
+ rv = get_serial_info(acm, (struct serial_struct __user *) arg);
+ break;
+ }
+
+ return rv;
}
static const __u32 acm_tty_speed[] = {
diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c
index 1c50baff772..6037b503153 100644
--- a/drivers/usb/class/cdc-wdm.c
+++ b/drivers/usb/class/cdc-wdm.c
@@ -31,6 +31,8 @@
#define DRIVER_AUTHOR "Oliver Neukum"
#define DRIVER_DESC "USB Abstract Control Model driver for USB WCM Device Management"
+#define HUAWEI_VENDOR_ID 0x12D1
+
static const struct usb_device_id wdm_ids[] = {
{
.match_flags = USB_DEVICE_ID_MATCH_INT_CLASS |
@@ -38,6 +40,20 @@ static const struct usb_device_id wdm_ids[] = {
.bInterfaceClass = USB_CLASS_COMM,
.bInterfaceSubClass = USB_CDC_SUBCLASS_DMM
},
+ {
+ /*
+ * Huawei E392, E398 and possibly other Qualcomm based modems
+ * embed the Qualcomm QMI protocol inside CDC on CDC ECM like
+ * control interfaces. Userspace access to this is required
+ * to configure the accompanying data interface
+ */
+ .match_flags = USB_DEVICE_ID_MATCH_VENDOR |
+ USB_DEVICE_ID_MATCH_INT_INFO,
+ .idVendor = HUAWEI_VENDOR_ID,
+ .bInterfaceClass = USB_CLASS_VENDOR_SPEC,
+ .bInterfaceSubClass = 1,
+ .bInterfaceProtocol = 9, /* NOTE: CDC ECM control interface! */
+ },
{ }
};
@@ -54,9 +70,12 @@ MODULE_DEVICE_TABLE (usb, wdm_ids);
#define WDM_POLL_RUNNING 6
#define WDM_RESPONDING 7
#define WDM_SUSPENDING 8
+#define WDM_RESETTING 9
#define WDM_MAX 16
+/* CDC-WMC r1.1 requires wMaxCommand to be "at least 256 decimal (0x100)" */
+#define WDM_DEFAULT_BUFSIZE 256
static DEFINE_MUTEX(wdm_mutex);
@@ -80,7 +99,6 @@ struct wdm_device {
u16 bufsize;
u16 wMaxCommand;
u16 wMaxPacketSize;
- u16 bMaxPacketSize0;
__le16 inum;
int reslength;
int length;
@@ -88,7 +106,8 @@ struct wdm_device {
int count;
dma_addr_t shandle;
dma_addr_t ihandle;
- struct mutex lock;
+ struct mutex wlock;
+ struct mutex rlock;
wait_queue_head_t wait;
struct work_struct rxwork;
int werr;
@@ -159,11 +178,9 @@ static void wdm_int_callback(struct urb *urb)
int rv = 0;
int status = urb->status;
struct wdm_device *desc;
- struct usb_ctrlrequest *req;
struct usb_cdc_notification *dr;
desc = urb->context;
- req = desc->irq;
dr = (struct usb_cdc_notification *)desc->sbuf;
if (status) {
@@ -210,24 +227,6 @@ static void wdm_int_callback(struct urb *urb)
goto exit;
}
- req->bRequestType = (USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE);
- req->bRequest = USB_CDC_GET_ENCAPSULATED_RESPONSE;
- req->wValue = 0;
- req->wIndex = desc->inum;
- req->wLength = cpu_to_le16(desc->wMaxCommand);
-
- usb_fill_control_urb(
- desc->response,
- interface_to_usbdev(desc->intf),
- /* using common endpoint 0 */
- usb_rcvctrlpipe(interface_to_usbdev(desc->intf), 0),
- (unsigned char *)req,
- desc->inbuf,
- desc->wMaxCommand,
- wdm_in_callback,
- desc
- );
- desc->response->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
spin_lock(&desc->iuspin);
clear_bit(WDM_READ, &desc->flags);
set_bit(WDM_RESPONDING, &desc->flags);
@@ -276,14 +275,8 @@ static void free_urbs(struct wdm_device *desc)
static void cleanup(struct wdm_device *desc)
{
- usb_free_coherent(interface_to_usbdev(desc->intf),
- desc->wMaxPacketSize,
- desc->sbuf,
- desc->validity->transfer_dma);
- usb_free_coherent(interface_to_usbdev(desc->intf),
- desc->bMaxPacketSize0,
- desc->inbuf,
- desc->response->transfer_dma);
+ kfree(desc->sbuf);
+ kfree(desc->inbuf);
kfree(desc->orq);
kfree(desc->irq);
kfree(desc->ubuf);
@@ -323,7 +316,7 @@ static ssize_t wdm_write
}
/* concurrent writes and disconnect */
- r = mutex_lock_interruptible(&desc->lock);
+ r = mutex_lock_interruptible(&desc->wlock);
rv = -ERESTARTSYS;
if (r) {
kfree(buf);
@@ -348,6 +341,10 @@ static ssize_t wdm_write
else
if (test_bit(WDM_IN_USE, &desc->flags))
r = -EAGAIN;
+
+ if (test_bit(WDM_RESETTING, &desc->flags))
+ r = -EIO;
+
if (r < 0) {
kfree(buf);
goto out;
@@ -386,7 +383,7 @@ static ssize_t wdm_write
out:
usb_autopm_put_interface(desc->intf);
outnp:
- mutex_unlock(&desc->lock);
+ mutex_unlock(&desc->wlock);
outnl:
return rv < 0 ? rv : count;
}
@@ -394,16 +391,17 @@ outnl:
static ssize_t wdm_read
(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
{
- int rv, cntr = 0;
+ int rv, cntr;
int i = 0;
struct wdm_device *desc = file->private_data;
- rv = mutex_lock_interruptible(&desc->lock); /*concurrent reads */
+ rv = mutex_lock_interruptible(&desc->rlock); /*concurrent reads */
if (rv < 0)
return -ERESTARTSYS;
- if (desc->length == 0) {
+ cntr = ACCESS_ONCE(desc->length);
+ if (cntr == 0) {
desc->read = 0;
retry:
if (test_bit(WDM_DISCONNECTING, &desc->flags)) {
@@ -427,6 +425,10 @@ retry:
rv = -ENODEV;
goto err;
}
+ if (test_bit(WDM_RESETTING, &desc->flags)) {
+ rv = -EIO;
+ goto err;
+ }
usb_mark_last_busy(interface_to_usbdev(desc->intf));
if (rv < 0) {
rv = -ERESTARTSYS;
@@ -453,17 +455,20 @@ retry:
spin_unlock_irq(&desc->iuspin);
goto retry;
}
- clear_bit(WDM_READ, &desc->flags);
+ cntr = desc->length;
spin_unlock_irq(&desc->iuspin);
}
- cntr = count > desc->length ? desc->length : count;
+ if (cntr > count)
+ cntr = count;
rv = copy_to_user(buffer, desc->ubuf, cntr);
if (rv > 0) {
rv = -EFAULT;
goto err;
}
+ spin_lock_irq(&desc->iuspin);
+
for (i = 0; i < desc->length - cntr; i++)
desc->ubuf[i] = desc->ubuf[i + cntr];
@@ -471,10 +476,13 @@ retry:
/* in case we had outstanding data */
if (!desc->length)
clear_bit(WDM_READ, &desc->flags);
+
+ spin_unlock_irq(&desc->iuspin);
+
rv = cntr;
err:
- mutex_unlock(&desc->lock);
+ mutex_unlock(&desc->rlock);
return rv;
}
@@ -540,7 +548,8 @@ static int wdm_open(struct inode *inode, struct file *file)
}
intf->needs_remote_wakeup = 1;
- mutex_lock(&desc->lock);
+ /* using write lock to protect desc->count */
+ mutex_lock(&desc->wlock);
if (!desc->count++) {
desc->werr = 0;
desc->rerr = 0;
@@ -553,7 +562,7 @@ static int wdm_open(struct inode *inode, struct file *file)
} else {
rv = 0;
}
- mutex_unlock(&desc->lock);
+ mutex_unlock(&desc->wlock);
usb_autopm_put_interface(desc->intf);
out:
mutex_unlock(&wdm_mutex);
@@ -565,9 +574,11 @@ static int wdm_release(struct inode *inode, struct file *file)
struct wdm_device *desc = file->private_data;
mutex_lock(&wdm_mutex);
- mutex_lock(&desc->lock);
+
+ /* using write lock to protect desc->count */
+ mutex_lock(&desc->wlock);
desc->count--;
- mutex_unlock(&desc->lock);
+ mutex_unlock(&desc->wlock);
if (!desc->count) {
dev_dbg(&desc->intf->dev, "wdm_release: cleanup");
@@ -623,14 +634,13 @@ static void wdm_rxwork(struct work_struct *work)
static int wdm_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
int rv = -EINVAL;
- struct usb_device *udev = interface_to_usbdev(intf);
struct wdm_device *desc;
struct usb_host_interface *iface;
struct usb_endpoint_descriptor *ep;
struct usb_cdc_dmm_desc *dmhd;
u8 *buffer = intf->altsetting->extra;
int buflen = intf->altsetting->extralen;
- u16 maxcom = 0;
+ u16 maxcom = WDM_DEFAULT_BUFSIZE;
if (!buffer)
goto out;
@@ -665,7 +675,8 @@ next_desc:
desc = kzalloc(sizeof(struct wdm_device), GFP_KERNEL);
if (!desc)
goto out;
- mutex_init(&desc->lock);
+ mutex_init(&desc->rlock);
+ mutex_init(&desc->wlock);
spin_lock_init(&desc->iuspin);
init_waitqueue_head(&desc->wait);
desc->wMaxCommand = maxcom;
@@ -683,7 +694,6 @@ next_desc:
goto err;
desc->wMaxPacketSize = usb_endpoint_maxp(ep);
- desc->bMaxPacketSize0 = udev->descriptor.bMaxPacketSize0;
desc->orq = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL);
if (!desc->orq)
@@ -708,19 +718,13 @@ next_desc:
if (!desc->ubuf)
goto err;
- desc->sbuf = usb_alloc_coherent(interface_to_usbdev(intf),
- desc->wMaxPacketSize,
- GFP_KERNEL,
- &desc->validity->transfer_dma);
+ desc->sbuf = kmalloc(desc->wMaxPacketSize, GFP_KERNEL);
if (!desc->sbuf)
goto err;
- desc->inbuf = usb_alloc_coherent(interface_to_usbdev(intf),
- desc->bMaxPacketSize0,
- GFP_KERNEL,
- &desc->response->transfer_dma);
+ desc->inbuf = kmalloc(desc->wMaxCommand, GFP_KERNEL);
if (!desc->inbuf)
- goto err2;
+ goto err;
usb_fill_int_urb(
desc->validity,
@@ -732,30 +736,39 @@ next_desc:
desc,
ep->bInterval
);
- desc->validity->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+ desc->irq->bRequestType = (USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE);
+ desc->irq->bRequest = USB_CDC_GET_ENCAPSULATED_RESPONSE;
+ desc->irq->wValue = 0;
+ desc->irq->wIndex = desc->inum;
+ desc->irq->wLength = cpu_to_le16(desc->wMaxCommand);
+
+ usb_fill_control_urb(
+ desc->response,
+ interface_to_usbdev(intf),
+ /* using common endpoint 0 */
+ usb_rcvctrlpipe(interface_to_usbdev(desc->intf), 0),
+ (unsigned char *)desc->irq,
+ desc->inbuf,
+ desc->wMaxCommand,
+ wdm_in_callback,
+ desc
+ );
usb_set_intfdata(intf, desc);
rv = usb_register_dev(intf, &wdm_class);
if (rv < 0)
- goto err3;
+ goto err2;
else
- dev_info(&intf->dev, "cdc-wdm%d: USB WDM device\n",
- intf->minor - WDM_MINOR_BASE);
+ dev_info(&intf->dev, "%s: USB WDM device\n", dev_name(intf->usb_dev));
out:
return rv;
-err3:
- usb_set_intfdata(intf, NULL);
- usb_free_coherent(interface_to_usbdev(desc->intf),
- desc->bMaxPacketSize0,
- desc->inbuf,
- desc->response->transfer_dma);
err2:
- usb_free_coherent(interface_to_usbdev(desc->intf),
- desc->wMaxPacketSize,
- desc->sbuf,
- desc->validity->transfer_dma);
+ usb_set_intfdata(intf, NULL);
err:
free_urbs(desc);
+ kfree(desc->inbuf);
+ kfree(desc->sbuf);
kfree(desc->ubuf);
kfree(desc->orq);
kfree(desc->irq);
@@ -779,11 +792,13 @@ 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);
- mutex_lock(&desc->lock);
+ wake_up_all(&desc->wait);
+ mutex_lock(&desc->rlock);
+ mutex_lock(&desc->wlock);
kill_urbs(desc);
cancel_work_sync(&desc->rxwork);
- mutex_unlock(&desc->lock);
- wake_up_all(&desc->wait);
+ mutex_unlock(&desc->wlock);
+ mutex_unlock(&desc->rlock);
if (!desc->count)
cleanup(desc);
mutex_unlock(&wdm_mutex);
@@ -798,8 +813,10 @@ static int wdm_suspend(struct usb_interface *intf, pm_message_t message)
dev_dbg(&desc->intf->dev, "wdm%d_suspend\n", intf->minor);
/* if this is an autosuspend the caller does the locking */
- if (!PMSG_IS_AUTO(message))
- mutex_lock(&desc->lock);
+ if (!PMSG_IS_AUTO(message)) {
+ mutex_lock(&desc->rlock);
+ mutex_lock(&desc->wlock);
+ }
spin_lock_irq(&desc->iuspin);
if (PMSG_IS_AUTO(message) &&
@@ -815,8 +832,10 @@ static int wdm_suspend(struct usb_interface *intf, pm_message_t message)
kill_urbs(desc);
cancel_work_sync(&desc->rxwork);
}
- if (!PMSG_IS_AUTO(message))
- mutex_unlock(&desc->lock);
+ if (!PMSG_IS_AUTO(message)) {
+ mutex_unlock(&desc->wlock);
+ mutex_unlock(&desc->rlock);
+ }
return rv;
}
@@ -854,9 +873,6 @@ static int wdm_pre_reset(struct usb_interface *intf)
{
struct wdm_device *desc = usb_get_intfdata(intf);
- mutex_lock(&desc->lock);
- kill_urbs(desc);
-
/*
* we notify everybody using poll of
* an exceptional situation
@@ -864,9 +880,16 @@ static int wdm_pre_reset(struct usb_interface *intf)
* message from the device is lost
*/
spin_lock_irq(&desc->iuspin);
+ set_bit(WDM_RESETTING, &desc->flags); /* inform read/write */
+ set_bit(WDM_READ, &desc->flags); /* unblock read */
+ clear_bit(WDM_IN_USE, &desc->flags); /* unblock write */
desc->rerr = -EINTR;
spin_unlock_irq(&desc->iuspin);
wake_up_all(&desc->wait);
+ mutex_lock(&desc->rlock);
+ mutex_lock(&desc->wlock);
+ kill_urbs(desc);
+ cancel_work_sync(&desc->rxwork);
return 0;
}
@@ -875,8 +898,10 @@ static int wdm_post_reset(struct usb_interface *intf)
struct wdm_device *desc = usb_get_intfdata(intf);
int rv;
+ clear_bit(WDM_RESETTING, &desc->flags);
rv = recover_from_urb_loss(desc);
- mutex_unlock(&desc->lock);
+ mutex_unlock(&desc->wlock);
+ mutex_unlock(&desc->rlock);
return 0;
}
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index d40ff956881..d77daf3683d 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -958,13 +958,8 @@ void usb_rebind_intf(struct usb_interface *intf)
int rc;
/* Delayed unbind of an existing driver */
- if (intf->dev.driver) {
- struct usb_driver *driver =
- to_usb_driver(intf->dev.driver);
-
- dev_dbg(&intf->dev, "forced unbind\n");
- usb_driver_release_interface(driver, intf);
- }
+ if (intf->dev.driver)
+ usb_forced_unbind_intf(intf);
/* Try to rebind the interface */
if (!intf->dev.power.is_prepared) {
@@ -977,15 +972,13 @@ void usb_rebind_intf(struct usb_interface *intf)
#ifdef CONFIG_PM
-#define DO_UNBIND 0
-#define DO_REBIND 1
-
-/* Unbind drivers for @udev's interfaces that don't support suspend/resume,
- * or rebind interfaces that have been unbound, according to @action.
+/* Unbind drivers for @udev's interfaces that don't support suspend/resume
+ * There is no check for reset_resume here because it can be determined
+ * only during resume whether reset_resume is needed.
*
* The caller must hold @udev's device lock.
*/
-static void do_unbind_rebind(struct usb_device *udev, int action)
+static void unbind_no_pm_drivers_interfaces(struct usb_device *udev)
{
struct usb_host_config *config;
int i;
@@ -996,23 +989,53 @@ static void do_unbind_rebind(struct usb_device *udev, int action)
if (config) {
for (i = 0; i < config->desc.bNumInterfaces; ++i) {
intf = config->interface[i];
- switch (action) {
- case DO_UNBIND:
- if (intf->dev.driver) {
- drv = to_usb_driver(intf->dev.driver);
- if (!drv->suspend || !drv->resume)
- usb_forced_unbind_intf(intf);
- }
- break;
- case DO_REBIND:
- if (intf->needs_binding)
- usb_rebind_intf(intf);
- break;
+
+ if (intf->dev.driver) {
+ drv = to_usb_driver(intf->dev.driver);
+ if (!drv->suspend || !drv->resume)
+ usb_forced_unbind_intf(intf);
}
}
}
}
+/* Unbind drivers for @udev's interfaces that failed to support reset-resume.
+ * These interfaces have the needs_binding flag set by usb_resume_interface().
+ *
+ * The caller must hold @udev's device lock.
+ */
+static void unbind_no_reset_resume_drivers_interfaces(struct usb_device *udev)
+{
+ struct usb_host_config *config;
+ int i;
+ struct usb_interface *intf;
+
+ config = udev->actconfig;
+ if (config) {
+ for (i = 0; i < config->desc.bNumInterfaces; ++i) {
+ intf = config->interface[i];
+ if (intf->dev.driver && intf->needs_binding)
+ usb_forced_unbind_intf(intf);
+ }
+ }
+}
+
+static void do_rebind_interfaces(struct usb_device *udev)
+{
+ struct usb_host_config *config;
+ int i;
+ struct usb_interface *intf;
+
+ config = udev->actconfig;
+ if (config) {
+ for (i = 0; i < config->desc.bNumInterfaces; ++i) {
+ intf = config->interface[i];
+ if (intf->needs_binding)
+ usb_rebind_intf(intf);
+ }
+ }
+}
+
static int usb_suspend_device(struct usb_device *udev, pm_message_t msg)
{
struct usb_device_driver *udriver;
@@ -1302,35 +1325,48 @@ int usb_suspend(struct device *dev, pm_message_t msg)
{
struct usb_device *udev = to_usb_device(dev);
- do_unbind_rebind(udev, DO_UNBIND);
+ unbind_no_pm_drivers_interfaces(udev);
+
+ /* From now on we are sure all drivers support suspend/resume
+ * but not necessarily reset_resume()
+ * so we may still need to unbind and rebind upon resume
+ */
choose_wakeup(udev, msg);
return usb_suspend_both(udev, msg);
}
/* The device lock is held by the PM core */
+int usb_resume_complete(struct device *dev)
+{
+ struct usb_device *udev = to_usb_device(dev);
+
+ /* For PM complete calls, all we do is rebind interfaces
+ * whose needs_binding flag is set
+ */
+ if (udev->state != USB_STATE_NOTATTACHED)
+ do_rebind_interfaces(udev);
+ return 0;
+}
+
+/* The device lock is held by the PM core */
int usb_resume(struct device *dev, pm_message_t msg)
{
struct usb_device *udev = to_usb_device(dev);
int status;
- /* For PM complete calls, all we do is rebind interfaces */
- if (msg.event == PM_EVENT_ON) {
- if (udev->state != USB_STATE_NOTATTACHED)
- do_unbind_rebind(udev, DO_REBIND);
- status = 0;
-
- /* For all other calls, take the device back to full power and
+ /* For all calls, take the device back to full power and
* tell the PM core in case it was autosuspended previously.
- * Unbind the interfaces that will need rebinding later.
+ * Unbind the interfaces that will need rebinding later,
+ * because they fail to support reset_resume.
+ * (This can't be done in usb_resume_interface()
+ * above because it doesn't own the right set of locks.)
*/
- } else {
- status = usb_resume_both(udev, msg);
- if (status == 0) {
- pm_runtime_disable(dev);
- pm_runtime_set_active(dev);
- pm_runtime_enable(dev);
- do_unbind_rebind(udev, DO_REBIND);
- }
+ status = usb_resume_both(udev, msg);
+ if (status == 0) {
+ pm_runtime_disable(dev);
+ pm_runtime_set_active(dev);
+ pm_runtime_enable(dev);
+ unbind_no_reset_resume_drivers_interfaces(udev);
}
/* Avoid PM error messages for devices disconnected while suspended
diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
index d136b8f4c8a..622b4a48e73 100644
--- a/drivers/usb/core/hcd-pci.c
+++ b/drivers/usb/core/hcd-pci.c
@@ -187,7 +187,10 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
return -ENODEV;
dev->current_state = PCI_D0;
- if (!dev->irq) {
+ /* The xHCI driver supports MSI and MSI-X,
+ * so don't fail if the BIOS doesn't provide a legacy IRQ.
+ */
+ if (!dev->irq && (driver->flags & HCD_MASK) != HCD_USB3) {
dev_err(&dev->dev,
"Found HC with no IRQ. Check BIOS/PCI %s setup!\n",
pci_name(dev));
@@ -377,6 +380,7 @@ static int check_root_hub_suspended(struct device *dev)
return 0;
}
+#if defined(CONFIG_PM_SLEEP) || defined(CONFIG_PM_RUNTIME)
static int suspend_common(struct device *dev, bool do_wakeup)
{
struct pci_dev *pci_dev = to_pci_dev(dev);
@@ -468,6 +472,7 @@ static int resume_common(struct device *dev, int event)
}
return retval;
}
+#endif /* SLEEP || RUNTIME */
#ifdef CONFIG_PM_SLEEP
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index eb19cba34ac..e1282328fc2 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -2447,8 +2447,10 @@ int usb_add_hcd(struct usb_hcd *hcd,
&& device_can_wakeup(&hcd->self.root_hub->dev))
dev_dbg(hcd->self.controller, "supports USB remote wakeup\n");
- /* enable irqs just before we start the controller */
- if (usb_hcd_is_primary_hcd(hcd)) {
+ /* enable irqs just before we start the controller,
+ * if the BIOS provides legacy PCI irqs.
+ */
+ if (usb_hcd_is_primary_hcd(hcd) && irqnum) {
retval = usb_hcd_request_irqs(hcd, irqnum, irqflags);
if (retval)
goto err_request_irq;
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index a0613d8f9be..72c51cdce90 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -62,6 +62,8 @@ struct usb_hub {
resumed */
unsigned long removed_bits[1]; /* ports with a "removed"
device present */
+ unsigned long wakeup_bits[1]; /* ports that have signaled
+ remote wakeup */
#if USB_MAXCHILDREN > 31 /* 8*sizeof(unsigned long) - 1 */
#error event_bits[] is too short!
#endif
@@ -411,6 +413,29 @@ void usb_kick_khubd(struct usb_device *hdev)
kick_khubd(hub);
}
+/*
+ * Let the USB core know that a USB 3.0 device has sent a Function Wake Device
+ * Notification, which indicates it had initiated remote wakeup.
+ *
+ * USB 3.0 hubs do not report the port link state change from U3 to U0 when the
+ * device initiates resume, so the USB core will not receive notice of the
+ * resume through the normal hub interrupt URB.
+ */
+void usb_wakeup_notification(struct usb_device *hdev,
+ unsigned int portnum)
+{
+ struct usb_hub *hub;
+
+ if (!hdev)
+ return;
+
+ hub = hdev_to_hub(hdev);
+ if (hub) {
+ set_bit(portnum, hub->wakeup_bits);
+ kick_khubd(hub);
+ }
+}
+EXPORT_SYMBOL_GPL(usb_wakeup_notification);
/* completion function, fires on port status changes and various faults */
static void hub_irq(struct urb *urb)
@@ -705,10 +730,26 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
if (type == HUB_INIT3)
goto init3;
- /* After a resume, port power should still be on.
+ /* The superspeed hub except for root hub has to use Hub Depth
+ * value as an offset into the route string to locate the bits
+ * it uses to determine the downstream port number. So hub driver
+ * should send a set hub depth request to superspeed hub after
+ * the superspeed hub is set configuration in initialization or
+ * reset procedure.
+ *
+ * After a resume, port power should still be on.
* For any other type of activation, turn it on.
*/
if (type != HUB_RESUME) {
+ if (hdev->parent && hub_is_superspeed(hdev)) {
+ ret = usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
+ HUB_SET_DEPTH, USB_RT_HUB,
+ hdev->level - 1, 0, NULL, 0,
+ USB_CTRL_SET_TIMEOUT);
+ if (ret < 0)
+ dev_err(hub->intfdev,
+ "set hub depth failed\n");
+ }
/* Speed up system boot by using a delayed_work for the
* hub's initial power-up delays. This is pretty awkward
@@ -807,12 +848,6 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
clear_port_feature(hub->hdev, port1,
USB_PORT_FEAT_C_ENABLE);
}
- if (portchange & USB_PORT_STAT_C_LINK_STATE) {
- need_debounce_delay = true;
- clear_port_feature(hub->hdev, port1,
- USB_PORT_FEAT_C_PORT_LINK_STATE);
- }
-
if ((portchange & USB_PORT_STAT_C_BH_RESET) &&
hub_is_superspeed(hub->hdev)) {
need_debounce_delay = true;
@@ -834,12 +869,19 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
set_bit(port1, hub->change_bits);
} else if (portstatus & USB_PORT_STAT_ENABLE) {
+ bool port_resumed = (portstatus &
+ USB_PORT_STAT_LINK_STATE) ==
+ USB_SS_PORT_LS_U0;
/* The power session apparently survived the resume.
* If there was an overcurrent or suspend change
* (i.e., remote wakeup request), have khubd
- * take care of it.
+ * take care of it. Look at the port link state
+ * for USB 3.0 hubs, since they don't have a suspend
+ * change bit, and they don't set the port link change
+ * bit on device-initiated resume.
*/
- if (portchange)
+ if (portchange || (hub_is_superspeed(hub->hdev) &&
+ port_resumed))
set_bit(port1, hub->change_bits);
} else if (udev->persist_enabled) {
@@ -987,18 +1029,6 @@ static int hub_configure(struct usb_hub *hub,
goto fail;
}
- if (hub_is_superspeed(hdev) && (hdev->parent != NULL)) {
- ret = usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
- HUB_SET_DEPTH, USB_RT_HUB,
- hdev->level - 1, 0, NULL, 0,
- USB_CTRL_SET_TIMEOUT);
-
- if (ret < 0) {
- message = "can't set hub depth";
- goto fail;
- }
- }
-
/* Request the entire hub descriptor.
* hub->descriptor can handle USB_MAXCHILDREN ports,
* but the hub can/will return fewer bytes here.
@@ -1289,14 +1319,8 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id)
desc = intf->cur_altsetting;
hdev = interface_to_usbdev(intf);
- /* Hubs have proper suspend/resume support. USB 3.0 device suspend is
- * different from USB 2.0/1.1 device suspend, and unfortunately we
- * don't support it yet. So leave autosuspend disabled for USB 3.0
- * external hubs for now. Enable autosuspend for USB 3.0 roothubs,
- * since that isn't a "real" hub.
- */
- if (!hub_is_superspeed(hdev) || !hdev->parent)
- usb_enable_autosuspend(hdev);
+ /* Hubs have proper suspend/resume support. */
+ usb_enable_autosuspend(hdev);
if (hdev->level == MAX_TOPO_LEVEL) {
dev_err(&intf->dev,
@@ -1838,6 +1862,37 @@ fail:
return err;
}
+static void set_usb_port_removable(struct usb_device *udev)
+{
+ struct usb_device *hdev = udev->parent;
+ struct usb_hub *hub;
+ u8 port = udev->portnum;
+ u16 wHubCharacteristics;
+ bool removable = true;
+
+ if (!hdev)
+ return;
+
+ hub = hdev_to_hub(udev->parent);
+
+ wHubCharacteristics = le16_to_cpu(hub->descriptor->wHubCharacteristics);
+
+ if (!(wHubCharacteristics & HUB_CHAR_COMPOUND))
+ return;
+
+ if (hub_is_superspeed(hdev)) {
+ if (hub->descriptor->u.ss.DeviceRemovable & (1 << port))
+ removable = false;
+ } else {
+ if (hub->descriptor->u.hs.DeviceRemovable[port / 8] & (1 << (port % 8)))
+ removable = false;
+ }
+
+ if (removable)
+ udev->removable = USB_DEVICE_REMOVABLE;
+ else
+ udev->removable = USB_DEVICE_FIXED;
+}
/**
* usb_new_device - perform initial device setup (usbcore-internal)
@@ -1896,6 +1951,15 @@ int usb_new_device(struct usb_device *udev)
announce_device(udev);
device_enable_async_suspend(&udev->dev);
+
+ /*
+ * check whether the hub marks this port as non-removable. Do it
+ * now so that platform-specific data can override it in
+ * device_add()
+ */
+ if (udev->parent)
+ set_usb_port_removable(udev);
+
/* Register the device. The device driver is responsible
* for configuring the device and invoking the add-device
* notifier chain (used by usbfs and possibly others).
@@ -2381,11 +2445,27 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
* we don't explicitly enable it here.
*/
if (udev->do_remote_wakeup) {
- status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
- USB_REQ_SET_FEATURE, USB_RECIP_DEVICE,
- USB_DEVICE_REMOTE_WAKEUP, 0,
- NULL, 0,
- USB_CTRL_SET_TIMEOUT);
+ if (!hub_is_superspeed(hub->hdev)) {
+ status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+ USB_REQ_SET_FEATURE, USB_RECIP_DEVICE,
+ USB_DEVICE_REMOTE_WAKEUP, 0,
+ NULL, 0,
+ USB_CTRL_SET_TIMEOUT);
+ } else {
+ /* Assume there's only one function on the USB 3.0
+ * device and enable remote wake for the first
+ * interface. FIXME if the interface association
+ * descriptor shows there's more than one function.
+ */
+ status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+ USB_REQ_SET_FEATURE,
+ USB_RECIP_INTERFACE,
+ USB_INTRF_FUNC_SUSPEND,
+ USB_INTRF_FUNC_SUSPEND_RW |
+ USB_INTRF_FUNC_SUSPEND_LP,
+ NULL, 0,
+ USB_CTRL_SET_TIMEOUT);
+ }
if (status) {
dev_dbg(&udev->dev, "won't remote wakeup, status %d\n",
status);
@@ -2675,6 +2755,7 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
struct usb_hub *hub = usb_get_intfdata (intf);
struct usb_device *hdev = hub->hdev;
unsigned port1;
+ int status;
/* Warn if children aren't already suspended */
for (port1 = 1; port1 <= hdev->maxchild; port1++) {
@@ -2687,6 +2768,17 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
return -EBUSY;
}
}
+ if (hub_is_superspeed(hdev) && hdev->do_remote_wakeup) {
+ /* Enable hub to send remote wakeup for all ports. */
+ for (port1 = 1; port1 <= hdev->maxchild; port1++) {
+ status = set_port_feature(hdev,
+ port1 |
+ USB_PORT_FEAT_REMOTE_WAKE_CONNECT |
+ USB_PORT_FEAT_REMOTE_WAKE_DISCONNECT |
+ USB_PORT_FEAT_REMOTE_WAKE_OVER_CURRENT,
+ USB_PORT_FEAT_REMOTE_WAKE_MASK);
+ }
+ }
dev_dbg(&intf->dev, "%s\n", __func__);
@@ -3420,6 +3512,46 @@ done:
hcd->driver->relinquish_port(hcd, port1);
}
+/* Returns 1 if there was a remote wakeup and a connect status change. */
+static int hub_handle_remote_wakeup(struct usb_hub *hub, unsigned int port,
+ u16 portstatus, u16 portchange)
+{
+ struct usb_device *hdev;
+ struct usb_device *udev;
+ int connect_change = 0;
+ int ret;
+
+ hdev = hub->hdev;
+ udev = hdev->children[port-1];
+ if (!hub_is_superspeed(hdev)) {
+ if (!(portchange & USB_PORT_STAT_C_SUSPEND))
+ return 0;
+ clear_port_feature(hdev, port, USB_PORT_FEAT_C_SUSPEND);
+ } else {
+ if (!udev || udev->state != USB_STATE_SUSPENDED ||
+ (portstatus & USB_PORT_STAT_LINK_STATE) !=
+ USB_SS_PORT_LS_U0)
+ return 0;
+ }
+
+ if (udev) {
+ /* TRSMRCY = 10 msec */
+ msleep(10);
+
+ usb_lock_device(udev);
+ ret = usb_remote_wakeup(udev);
+ usb_unlock_device(udev);
+ if (ret < 0)
+ connect_change = 1;
+ } else {
+ ret = -ENODEV;
+ hub_port_disable(hub, port, 1);
+ }
+ dev_dbg(hub->intfdev, "resume on port %d, status %d\n",
+ port, ret);
+ return connect_change;
+}
+
static void hub_events(void)
{
struct list_head *tmp;
@@ -3432,7 +3564,7 @@ static void hub_events(void)
u16 portstatus;
u16 portchange;
int i, ret;
- int connect_change;
+ int connect_change, wakeup_change;
/*
* We restart the list every time to avoid a deadlock with
@@ -3511,8 +3643,9 @@ static void hub_events(void)
if (test_bit(i, hub->busy_bits))
continue;
connect_change = test_bit(i, hub->change_bits);
+ wakeup_change = test_and_clear_bit(i, hub->wakeup_bits);
if (!test_and_clear_bit(i, hub->event_bits) &&
- !connect_change)
+ !connect_change && !wakeup_change)
continue;
ret = hub_port_status(hub, i,
@@ -3553,31 +3686,10 @@ static void hub_events(void)
}
}
- if (portchange & USB_PORT_STAT_C_SUSPEND) {
- struct usb_device *udev;
+ if (hub_handle_remote_wakeup(hub, i,
+ portstatus, portchange))
+ connect_change = 1;
- clear_port_feature(hdev, i,
- USB_PORT_FEAT_C_SUSPEND);
- udev = hdev->children[i-1];
- if (udev) {
- /* TRSMRCY = 10 msec */
- msleep(10);
-
- usb_lock_device(udev);
- ret = usb_remote_wakeup(hdev->
- children[i-1]);
- usb_unlock_device(udev);
- if (ret < 0)
- connect_change = 1;
- } else {
- ret = -ENODEV;
- hub_port_disable(hub, i, 1);
- }
- dev_dbg (hub_dev,
- "resume on port %d, status %d\n",
- i, ret);
- }
-
if (portchange & USB_PORT_STAT_C_OVERCURRENT) {
u16 status = 0;
u16 unused;
diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
index 9e491ca2e5c..566d9f94f73 100644
--- a/drivers/usb/core/sysfs.c
+++ b/drivers/usb/core/sysfs.c
@@ -230,6 +230,28 @@ show_urbnum(struct device *dev, struct device_attribute *attr, char *buf)
}
static DEVICE_ATTR(urbnum, S_IRUGO, show_urbnum, NULL);
+static ssize_t
+show_removable(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct usb_device *udev;
+ char *state;
+
+ udev = to_usb_device(dev);
+
+ switch (udev->removable) {
+ case USB_DEVICE_REMOVABLE:
+ state = "removable";
+ break;
+ case USB_DEVICE_FIXED:
+ state = "fixed";
+ break;
+ default:
+ state = "unknown";
+ }
+
+ return sprintf(buf, "%s\n", state);
+}
+static DEVICE_ATTR(removable, S_IRUGO, show_removable, NULL);
#ifdef CONFIG_PM
@@ -626,6 +648,7 @@ static struct attribute *dev_attrs[] = {
&dev_attr_avoid_reset_quirk.attr,
&dev_attr_authorized.attr,
&dev_attr_remove.attr,
+ &dev_attr_removable.attr,
NULL,
};
static struct attribute_group dev_attr_grp = {
diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
index 909625b91eb..f4f20c7b776 100644
--- a/drivers/usb/core/urb.c
+++ b/drivers/usb/core/urb.c
@@ -403,20 +403,17 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
* cause problems in HCDs if they get it wrong.
*/
{
- unsigned int orig_flags = urb->transfer_flags;
unsigned int allowed;
static int pipetypes[4] = {
PIPE_CONTROL, PIPE_ISOCHRONOUS, PIPE_BULK, PIPE_INTERRUPT
};
/* Check that the pipe's type matches the endpoint's type */
- if (usb_pipetype(urb->pipe) != pipetypes[xfertype]) {
- dev_err(&dev->dev, "BOGUS urb xfer, pipe %x != type %x\n",
+ if (usb_pipetype(urb->pipe) != pipetypes[xfertype])
+ dev_WARN(&dev->dev, "BOGUS urb xfer, pipe %x != type %x\n",
usb_pipetype(urb->pipe), pipetypes[xfertype]);
- return -EPIPE; /* The most suitable error code :-) */
- }
- /* enforce simple/standard policy */
+ /* Check against a simple/standard policy */
allowed = (URB_NO_TRANSFER_DMA_MAP | URB_NO_INTERRUPT | URB_DIR_MASK |
URB_FREE_BUFFER);
switch (xfertype) {
@@ -435,14 +432,12 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
allowed |= URB_ISO_ASAP;
break;
}
- urb->transfer_flags &= allowed;
+ allowed &= urb->transfer_flags;
- /* fail if submitter gave bogus flags */
- if (urb->transfer_flags != orig_flags) {
- dev_err(&dev->dev, "BOGUS urb flags, %x --> %x\n",
- orig_flags, urb->transfer_flags);
- return -EINVAL;
- }
+ /* warn if submitter gave bogus flags */
+ if (allowed != urb->transfer_flags)
+ dev_WARN(&dev->dev, "BOGUS urb flags, %x --> %x\n",
+ urb->transfer_flags, allowed);
}
#endif
/*
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index 8ca9f994a28..c74ba7bbc74 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -274,7 +274,7 @@ static int usb_dev_prepare(struct device *dev)
static void usb_dev_complete(struct device *dev)
{
/* Currently used only for rebinding interfaces */
- usb_resume(dev, PMSG_ON); /* FIXME: change to PMSG_COMPLETE */
+ usb_resume_complete(dev);
}
static int usb_dev_suspend(struct device *dev)
diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
index 45e8479c377..71648dcbe43 100644
--- a/drivers/usb/core/usb.h
+++ b/drivers/usb/core/usb.h
@@ -56,6 +56,7 @@ extern void usb_major_cleanup(void);
extern int usb_suspend(struct device *dev, pm_message_t msg);
extern int usb_resume(struct device *dev, pm_message_t msg);
+extern int usb_resume_complete(struct device *dev);
extern int usb_port_suspend(struct usb_device *dev, pm_message_t msg);
extern int usb_port_resume(struct usb_device *dev, pm_message_t msg);
diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
index 2f51de57593..c8df1dd967e 100644
--- a/drivers/usb/dwc3/ep0.c
+++ b/drivers/usb/dwc3/ep0.c
@@ -126,7 +126,6 @@ static int __dwc3_gadget_ep0_queue(struct dwc3_ep *dep,
struct dwc3_request *req)
{
struct dwc3 *dwc = dep->dwc;
- u32 type;
int ret = 0;
req->request.actual = 0;
@@ -149,20 +148,14 @@ static int __dwc3_gadget_ep0_queue(struct dwc3_ep *dep,
direction = !!(dep->flags & DWC3_EP0_DIR_IN);
- if (dwc->ep0state == EP0_STATUS_PHASE) {
- type = dwc->three_stage_setup
- ? DWC3_TRBCTL_CONTROL_STATUS3
- : DWC3_TRBCTL_CONTROL_STATUS2;
- } else if (dwc->ep0state == EP0_DATA_PHASE) {
- type = DWC3_TRBCTL_CONTROL_DATA;
- } else {
- /* should never happen */
- WARN_ON(1);
+ if (dwc->ep0state != EP0_DATA_PHASE) {
+ dev_WARN(dwc->dev, "Unexpected pending request\n");
return 0;
}
ret = dwc3_ep0_start_trans(dwc, direction,
- req->request.dma, req->request.length, type);
+ req->request.dma, req->request.length,
+ DWC3_TRBCTL_CONTROL_DATA);
dep->flags &= ~(DWC3_EP_PENDING_REQUEST |
DWC3_EP0_DIR_IN);
} else if (dwc->delayed_status) {
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index a696bde5322..064b6e2cd41 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -101,7 +101,7 @@ void dwc3_unmap_buffer_from_dma(struct dwc3_request *req)
if (req->request.num_mapped_sgs) {
req->request.dma = DMA_ADDR_INVALID;
dma_unmap_sg(dwc->dev, req->request.sg,
- req->request.num_sgs,
+ req->request.num_mapped_sgs,
req->direction ? DMA_TO_DEVICE
: DMA_FROM_DEVICE);
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index a95de6a4a13..baaebf2830f 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -175,13 +175,12 @@ ep_found:
_ep->comp_desc = comp_desc;
if (g->speed == USB_SPEED_SUPER) {
switch (usb_endpoint_type(_ep->desc)) {
- case USB_ENDPOINT_XFER_BULK:
- case USB_ENDPOINT_XFER_INT:
- _ep->maxburst = comp_desc->bMaxBurst;
- break;
case USB_ENDPOINT_XFER_ISOC:
/* mult: bits 1:0 of bmAttributes */
_ep->mult = comp_desc->bmAttributes & 0x3;
+ case USB_ENDPOINT_XFER_BULK:
+ case USB_ENDPOINT_XFER_INT:
+ _ep->maxburst = comp_desc->bMaxBurst;
break;
default:
/* Do nothing for control endpoints */
diff --git a/drivers/usb/gadget/epautoconf.c b/drivers/usb/gadget/epautoconf.c
index 753aa0683ac..e0e6375ef5d 100644
--- a/drivers/usb/gadget/epautoconf.c
+++ b/drivers/usb/gadget/epautoconf.c
@@ -126,7 +126,7 @@ ep_matches (
* descriptor and see if the EP matches it
*/
if (usb_endpoint_xfer_bulk(desc)) {
- if (ep_comp) {
+ if (ep_comp && gadget->max_speed >= USB_SPEED_SUPER) {
num_req_streams = ep_comp->bmAttributes & 0x1f;
if (num_req_streams > ep->max_streams)
return 0;
diff --git a/drivers/usb/gadget/f_loopback.c b/drivers/usb/gadget/f_loopback.c
index 6d87f288df4..2c0cd824c66 100644
--- a/drivers/usb/gadget/f_loopback.c
+++ b/drivers/usb/gadget/f_loopback.c
@@ -418,7 +418,7 @@ int __init loopback_add(struct usb_composite_dev *cdev, bool autoresume)
/* support autoresume for remote wakeup testing */
if (autoresume)
- sourcesink_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
+ loopback_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
/* support OTG systems */
if (gadget_is_otg(cdev->gadget)) {
diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c
index 6353eca1e85..84e6573ea74 100644
--- a/drivers/usb/gadget/f_mass_storage.c
+++ b/drivers/usb/gadget/f_mass_storage.c
@@ -620,7 +620,7 @@ static int fsg_setup(struct usb_function *f,
switch (ctrl->bRequest) {
- case USB_BULK_RESET_REQUEST:
+ case US_BULK_RESET_REQUEST:
if (ctrl->bRequestType !=
(USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE))
break;
@@ -636,7 +636,7 @@ static int fsg_setup(struct usb_function *f,
raise_exception(fsg->common, FSG_STATE_RESET);
return DELAYED_STATUS;
- case USB_BULK_GET_MAX_LUN_REQUEST:
+ case US_BULK_GET_MAX_LUN:
if (ctrl->bRequestType !=
(USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE))
break;
@@ -1742,7 +1742,7 @@ static int send_status(struct fsg_common *common)
struct fsg_buffhd *bh;
struct bulk_cs_wrap *csw;
int rc;
- u8 status = USB_STATUS_PASS;
+ u8 status = US_BULK_STAT_OK;
u32 sd, sdinfo = 0;
/* Wait for the next buffer to become available */
@@ -1763,11 +1763,11 @@ static int send_status(struct fsg_common *common)
if (common->phase_error) {
DBG(common, "sending phase-error status\n");
- status = USB_STATUS_PHASE_ERROR;
+ status = US_BULK_STAT_PHASE;
sd = SS_INVALID_COMMAND;
} else if (sd != SS_NO_SENSE) {
DBG(common, "sending command-failure status\n");
- status = USB_STATUS_FAIL;
+ status = US_BULK_STAT_FAIL;
VDBG(common, " sense data: SK x%02x, ASC x%02x, ASCQ x%02x;"
" info x%x\n",
SK(sd), ASC(sd), ASCQ(sd), sdinfo);
@@ -1776,12 +1776,12 @@ static int send_status(struct fsg_common *common)
/* Store and send the Bulk-only CSW */
csw = (void *)bh->buf;
- csw->Signature = cpu_to_le32(USB_BULK_CS_SIG);
+ csw->Signature = cpu_to_le32(US_BULK_CS_SIGN);
csw->Tag = common->tag;
csw->Residue = cpu_to_le32(common->residue);
csw->Status = status;
- bh->inreq->length = USB_BULK_CS_WRAP_LEN;
+ bh->inreq->length = US_BULK_CS_WRAP_LEN;
bh->inreq->zero = 0;
if (!start_in_transfer(common, bh))
/* Don't know what to do if common->fsg is NULL */
@@ -2221,7 +2221,7 @@ unknown_cmnd:
static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh)
{
struct usb_request *req = bh->outreq;
- struct fsg_bulk_cb_wrap *cbw = req->buf;
+ struct bulk_cb_wrap *cbw = req->buf;
struct fsg_common *common = fsg->common;
/* Was this a real packet? Should it be ignored? */
@@ -2229,9 +2229,9 @@ static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh)
return -EINVAL;
/* Is the CBW valid? */
- if (req->actual != USB_BULK_CB_WRAP_LEN ||
+ if (req->actual != US_BULK_CB_WRAP_LEN ||
cbw->Signature != cpu_to_le32(
- USB_BULK_CB_SIG)) {
+ US_BULK_CB_SIGN)) {
DBG(fsg, "invalid CBW: len %u sig 0x%x\n",
req->actual,
le32_to_cpu(cbw->Signature));
@@ -2253,7 +2253,7 @@ static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh)
}
/* Is the CBW meaningful? */
- if (cbw->Lun >= FSG_MAX_LUNS || cbw->Flags & ~USB_BULK_IN_FLAG ||
+ if (cbw->Lun >= FSG_MAX_LUNS || cbw->Flags & ~US_BULK_FLAG_IN ||
cbw->Length <= 0 || cbw->Length > MAX_COMMAND_SIZE) {
DBG(fsg, "non-meaningful CBW: lun = %u, flags = 0x%x, "
"cmdlen %u\n",
@@ -2273,7 +2273,7 @@ static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh)
/* Save the command for later */
common->cmnd_size = cbw->Length;
memcpy(common->cmnd, cbw->CDB, common->cmnd_size);
- if (cbw->Flags & USB_BULK_IN_FLAG)
+ if (cbw->Flags & US_BULK_FLAG_IN)
common->data_dir = DATA_DIR_TO_HOST;
else
common->data_dir = DATA_DIR_FROM_HOST;
@@ -2303,7 +2303,7 @@ static int get_next_command(struct fsg_common *common)
}
/* Queue a request to read a Bulk-only CBW */
- set_bulk_out_req_length(common, bh, USB_BULK_CB_WRAP_LEN);
+ set_bulk_out_req_length(common, bh, US_BULK_CB_WRAP_LEN);
if (!start_out_transfer(common, bh))
/* Don't know what to do if common->fsg is NULL */
return -EIO;
@@ -3123,15 +3123,15 @@ fsg_add(struct usb_composite_dev *cdev, struct usb_configuration *c,
struct fsg_module_parameters {
char *file[FSG_MAX_LUNS];
- int ro[FSG_MAX_LUNS];
- int removable[FSG_MAX_LUNS];
- int cdrom[FSG_MAX_LUNS];
- int nofua[FSG_MAX_LUNS];
+ bool ro[FSG_MAX_LUNS];
+ bool removable[FSG_MAX_LUNS];
+ bool cdrom[FSG_MAX_LUNS];
+ bool nofua[FSG_MAX_LUNS];
unsigned int file_count, ro_count, removable_count, cdrom_count;
unsigned int nofua_count;
unsigned int luns; /* nluns */
- int stall; /* can_stall */
+ bool stall; /* can_stall */
};
#define _FSG_MODULE_PARAM_ARRAY(prefix, params, name, type, desc) \
diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
index 47766f0e7ca..4fac5692774 100644
--- a/drivers/usb/gadget/file_storage.c
+++ b/drivers/usb/gadget/file_storage.c
@@ -855,7 +855,7 @@ static int class_setup_req(struct fsg_dev *fsg,
if (transport_is_bbb()) {
switch (ctrl->bRequest) {
- case USB_BULK_RESET_REQUEST:
+ case US_BULK_RESET_REQUEST:
if (ctrl->bRequestType != (USB_DIR_OUT |
USB_TYPE_CLASS | USB_RECIP_INTERFACE))
break;
@@ -871,7 +871,7 @@ static int class_setup_req(struct fsg_dev *fsg,
value = DELAYED_STATUS;
break;
- case USB_BULK_GET_MAX_LUN_REQUEST:
+ case US_BULK_GET_MAX_LUN:
if (ctrl->bRequestType != (USB_DIR_IN |
USB_TYPE_CLASS | USB_RECIP_INTERFACE))
break;
@@ -2125,7 +2125,7 @@ static int send_status(struct fsg_dev *fsg)
struct fsg_lun *curlun = fsg->curlun;
struct fsg_buffhd *bh;
int rc;
- u8 status = USB_STATUS_PASS;
+ u8 status = US_BULK_STAT_OK;
u32 sd, sdinfo = 0;
/* Wait for the next buffer to become available */
@@ -2146,11 +2146,11 @@ static int send_status(struct fsg_dev *fsg)
if (fsg->phase_error) {
DBG(fsg, "sending phase-error status\n");
- status = USB_STATUS_PHASE_ERROR;
+ status = US_BULK_STAT_PHASE;
sd = SS_INVALID_COMMAND;
} else if (sd != SS_NO_SENSE) {
DBG(fsg, "sending command-failure status\n");
- status = USB_STATUS_FAIL;
+ status = US_BULK_STAT_FAIL;
VDBG(fsg, " sense data: SK x%02x, ASC x%02x, ASCQ x%02x;"
" info x%x\n",
SK(sd), ASC(sd), ASCQ(sd), sdinfo);
@@ -2160,12 +2160,12 @@ static int send_status(struct fsg_dev *fsg)
struct bulk_cs_wrap *csw = bh->buf;
/* Store and send the Bulk-only CSW */
- csw->Signature = cpu_to_le32(USB_BULK_CS_SIG);
+ csw->Signature = cpu_to_le32(US_BULK_CS_SIGN);
csw->Tag = fsg->tag;
csw->Residue = cpu_to_le32(fsg->residue);
csw->Status = status;
- bh->inreq->length = USB_BULK_CS_WRAP_LEN;
+ bh->inreq->length = US_BULK_CS_WRAP_LEN;
bh->inreq->zero = 0;
start_transfer(fsg, fsg->bulk_in, bh->inreq,
&bh->inreq_busy, &bh->state);
@@ -2609,16 +2609,16 @@ static int do_scsi_command(struct fsg_dev *fsg)
static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh)
{
struct usb_request *req = bh->outreq;
- struct fsg_bulk_cb_wrap *cbw = req->buf;
+ struct bulk_cb_wrap *cbw = req->buf;
/* Was this a real packet? Should it be ignored? */
if (req->status || test_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags))
return -EINVAL;
/* Is the CBW valid? */
- if (req->actual != USB_BULK_CB_WRAP_LEN ||
+ if (req->actual != US_BULK_CB_WRAP_LEN ||
cbw->Signature != cpu_to_le32(
- USB_BULK_CB_SIG)) {
+ US_BULK_CB_SIGN)) {
DBG(fsg, "invalid CBW: len %u sig 0x%x\n",
req->actual,
le32_to_cpu(cbw->Signature));
@@ -2638,7 +2638,7 @@ static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh)
}
/* Is the CBW meaningful? */
- if (cbw->Lun >= FSG_MAX_LUNS || cbw->Flags & ~USB_BULK_IN_FLAG ||
+ if (cbw->Lun >= FSG_MAX_LUNS || cbw->Flags & ~US_BULK_FLAG_IN ||
cbw->Length <= 0 || cbw->Length > MAX_COMMAND_SIZE) {
DBG(fsg, "non-meaningful CBW: lun = %u, flags = 0x%x, "
"cmdlen %u\n",
@@ -2656,7 +2656,7 @@ static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh)
/* Save the command for later */
fsg->cmnd_size = cbw->Length;
memcpy(fsg->cmnd, cbw->CDB, fsg->cmnd_size);
- if (cbw->Flags & USB_BULK_IN_FLAG)
+ if (cbw->Flags & US_BULK_FLAG_IN)
fsg->data_dir = DATA_DIR_TO_HOST;
else
fsg->data_dir = DATA_DIR_FROM_HOST;
@@ -2685,7 +2685,7 @@ static int get_next_command(struct fsg_dev *fsg)
}
/* Queue a request to read a Bulk-only CBW */
- set_bulk_out_req_length(fsg, bh, USB_BULK_CB_WRAP_LEN);
+ set_bulk_out_req_length(fsg, bh, US_BULK_CB_WRAP_LEN);
start_transfer(fsg, fsg->bulk_out, bh->outreq,
&bh->outreq_busy, &bh->state);
diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c
index d7ea6c076ce..b04712f19f1 100644
--- a/drivers/usb/gadget/fsl_udc_core.c
+++ b/drivers/usb/gadget/fsl_udc_core.c
@@ -1430,7 +1430,7 @@ static void setup_received_irq(struct fsl_udc *udc,
int pipe = get_pipe_by_windex(wIndex);
struct fsl_ep *ep;
- if (wValue != 0 || wLength != 0 || pipe > udc->max_ep)
+ if (wValue != 0 || wLength != 0 || pipe >= udc->max_ep)
break;
ep = get_ep_by_pipe(udc, pipe);
@@ -1673,7 +1673,7 @@ static void dtd_complete_irq(struct fsl_udc *udc)
if (!bit_pos)
return;
- for (i = 0; i < udc->max_ep * 2; i++) {
+ for (i = 0; i < udc->max_ep; i++) {
ep_num = i >> 1;
direction = i % 2;
diff --git a/drivers/usb/gadget/langwell_udc.c b/drivers/usb/gadget/langwell_udc.c
index fa0fcc11263..e2293c1588e 100644
--- a/drivers/usb/gadget/langwell_udc.c
+++ b/drivers/usb/gadget/langwell_udc.c
@@ -11,11 +11,6 @@
/* #undef DEBUG */
/* #undef VERBOSE_DEBUG */
-#if defined(CONFIG_USB_LANGWELL_OTG)
-#define OTG_TRANSCEIVER
-#endif
-
-
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/dma-mapping.h>
@@ -1522,8 +1517,7 @@ static void langwell_udc_stop(struct langwell_udc *dev)
/* stop all USB activities */
-static void stop_activity(struct langwell_udc *dev,
- struct usb_gadget_driver *driver)
+static void stop_activity(struct langwell_udc *dev)
{
struct langwell_ep *ep;
dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__);
@@ -1535,9 +1529,9 @@ static void stop_activity(struct langwell_udc *dev,
}
/* report disconnect; the driver is already quiesced */
- if (driver) {
+ if (dev->driver) {
spin_unlock(&dev->lock);
- driver->disconnect(&dev->gadget);
+ dev->driver->disconnect(&dev->gadget);
spin_lock(&dev->lock);
}
@@ -1925,11 +1919,10 @@ static int langwell_stop(struct usb_gadget *g,
/* stop all usb activities */
dev->gadget.speed = USB_SPEED_UNKNOWN;
- stop_activity(dev, driver);
- spin_unlock_irqrestore(&dev->lock, flags);
-
dev->gadget.dev.driver = NULL;
dev->driver = NULL;
+ stop_activity(dev);
+ spin_unlock_irqrestore(&dev->lock, flags);
device_remove_file(&dev->pdev->dev, &dev_attr_function);
@@ -2315,13 +2308,9 @@ static void handle_setup_packet(struct langwell_udc *dev,
if (!gadget_is_otg(&dev->gadget))
break;
- else if (setup->bRequest == USB_DEVICE_B_HNP_ENABLE) {
+ else if (setup->bRequest == USB_DEVICE_B_HNP_ENABLE)
dev->gadget.b_hnp_enable = 1;
-#ifdef OTG_TRANSCEIVER
- if (!dev->lotg->otg.default_a)
- dev->lotg->hsm.b_hnp_enable = 1;
-#endif
- } else if (setup->bRequest == USB_DEVICE_A_HNP_SUPPORT)
+ else if (setup->bRequest == USB_DEVICE_A_HNP_SUPPORT)
dev->gadget.a_hnp_support = 1;
else if (setup->bRequest ==
USB_DEVICE_A_ALT_HNP_SUPPORT)
@@ -2733,7 +2722,7 @@ static void handle_usb_reset(struct langwell_udc *dev)
dev->bus_reset = 1;
/* reset all the queues, stop all USB activities */
- stop_activity(dev, dev->driver);
+ stop_activity(dev);
dev->usb_state = USB_STATE_DEFAULT;
} else {
dev_vdbg(&dev->pdev->dev, "device controller reset\n");
@@ -2741,7 +2730,7 @@ static void handle_usb_reset(struct langwell_udc *dev)
langwell_udc_reset(dev);
/* reset all the queues, stop all USB activities */
- stop_activity(dev, dev->driver);
+ stop_activity(dev);
/* reset ep0 dQH and endptctrl */
ep0_reset(dev);
@@ -2752,12 +2741,6 @@ static void handle_usb_reset(struct langwell_udc *dev)
dev->usb_state = USB_STATE_ATTACHED;
}
-#ifdef OTG_TRANSCEIVER
- /* refer to USB OTG 6.6.2.3 b_hnp_en is cleared */
- if (!dev->lotg->otg.default_a)
- dev->lotg->hsm.b_hnp_enable = 0;
-#endif
-
dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
}
@@ -2770,29 +2753,6 @@ static void handle_bus_suspend(struct langwell_udc *dev)
dev->resume_state = dev->usb_state;
dev->usb_state = USB_STATE_SUSPENDED;
-#ifdef OTG_TRANSCEIVER
- if (dev->lotg->otg.default_a) {
- if (dev->lotg->hsm.b_bus_suspend_vld == 1) {
- dev->lotg->hsm.b_bus_suspend = 1;
- /* notify transceiver the state changes */
- if (spin_trylock(&dev->lotg->wq_lock)) {
- langwell_update_transceiver();
- spin_unlock(&dev->lotg->wq_lock);
- }
- }
- dev->lotg->hsm.b_bus_suspend_vld++;
- } else {
- if (!dev->lotg->hsm.a_bus_suspend) {
- dev->lotg->hsm.a_bus_suspend = 1;
- /* notify transceiver the state changes */
- if (spin_trylock(&dev->lotg->wq_lock)) {
- langwell_update_transceiver();
- spin_unlock(&dev->lotg->wq_lock);
- }
- }
- }
-#endif
-
/* report suspend to the driver */
if (dev->driver) {
if (dev->driver->suspend) {
@@ -2823,11 +2783,6 @@ static void handle_bus_resume(struct langwell_udc *dev)
if (dev->pdev->device != 0x0829)
langwell_phy_low_power(dev, 0);
-#ifdef OTG_TRANSCEIVER
- if (dev->lotg->otg.default_a == 0)
- dev->lotg->hsm.a_bus_suspend = 0;
-#endif
-
/* report resume to the driver */
if (dev->driver) {
if (dev->driver->resume) {
@@ -3020,7 +2975,6 @@ static void langwell_udc_remove(struct pci_dev *pdev)
dev->done = &done;
-#ifndef OTG_TRANSCEIVER
/* free dTD dma_pool and dQH */
if (dev->dtd_pool)
dma_pool_destroy(dev->dtd_pool);
@@ -3032,7 +2986,6 @@ static void langwell_udc_remove(struct pci_dev *pdev)
/* release SRAM caching */
if (dev->has_sram && dev->got_sram)
sram_deinit(dev);
-#endif
if (dev->status_req) {
kfree(dev->status_req->req.buf);
@@ -3045,7 +2998,6 @@ static void langwell_udc_remove(struct pci_dev *pdev)
if (dev->got_irq)
free_irq(pdev->irq, dev);
-#ifndef OTG_TRANSCEIVER
if (dev->cap_regs)
iounmap(dev->cap_regs);
@@ -3055,13 +3007,6 @@ static void langwell_udc_remove(struct pci_dev *pdev)
if (dev->enabled)
pci_disable_device(pdev);
-#else
- if (dev->transceiver) {
- otg_put_transceiver(dev->transceiver);
- dev->transceiver = NULL;
- dev->lotg = NULL;
- }
-#endif
dev->cap_regs = NULL;
@@ -3072,9 +3017,7 @@ static void langwell_udc_remove(struct pci_dev *pdev)
device_remove_file(&pdev->dev, &dev_attr_langwell_udc);
device_remove_file(&pdev->dev, &dev_attr_remote_wakeup);
-#ifndef OTG_TRANSCEIVER
pci_set_drvdata(pdev, NULL);
-#endif
/* free dev, wait for the release() finished */
wait_for_completion(&done);
@@ -3089,9 +3032,7 @@ static int langwell_udc_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
struct langwell_udc *dev;
-#ifndef OTG_TRANSCEIVER
unsigned long resource, len;
-#endif
void __iomem *base = NULL;
size_t size;
int retval;
@@ -3109,16 +3050,6 @@ static int langwell_udc_probe(struct pci_dev *pdev,
dev->pdev = pdev;
dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__);
-#ifdef OTG_TRANSCEIVER
- /* PCI device is already enabled by otg_transceiver driver */
- dev->enabled = 1;
-
- /* mem region and register base */
- dev->region = 1;
- dev->transceiver = otg_get_transceiver();
- dev->lotg = otg_to_langwell(dev->transceiver);
- base = dev->lotg->regs;
-#else
pci_set_drvdata(pdev, dev);
/* now all the pci goodies ... */
@@ -3139,7 +3070,6 @@ static int langwell_udc_probe(struct pci_dev *pdev,
dev->region = 1;
base = ioremap_nocache(resource, len);
-#endif
if (base == NULL) {
dev_err(&dev->pdev->dev, "can't map memory\n");
retval = -EFAULT;
@@ -3163,7 +3093,6 @@ static int langwell_udc_probe(struct pci_dev *pdev,
dev->got_sram = 0;
dev_vdbg(&dev->pdev->dev, "dev->has_sram: %d\n", dev->has_sram);
-#ifndef OTG_TRANSCEIVER
/* enable SRAM caching if detected */
if (dev->has_sram && !dev->got_sram)
sram_init(dev);
@@ -3182,7 +3111,6 @@ static int langwell_udc_probe(struct pci_dev *pdev,
goto error;
}
dev->got_irq = 1;
-#endif
/* set stopped bit */
dev->stopped = 1;
@@ -3257,10 +3185,8 @@ static int langwell_udc_probe(struct pci_dev *pdev,
dev->remote_wakeup = 0;
dev->dev_status = 1 << USB_DEVICE_SELF_POWERED;
-#ifndef OTG_TRANSCEIVER
/* reset device controller */
langwell_udc_reset(dev);
-#endif
/* initialize gadget structure */
dev->gadget.ops = &langwell_ops; /* usb_gadget_ops */
@@ -3268,9 +3194,6 @@ static int langwell_udc_probe(struct pci_dev *pdev,
INIT_LIST_HEAD(&dev->gadget.ep_list); /* ep_list */
dev->gadget.speed = USB_SPEED_UNKNOWN; /* speed */
dev->gadget.max_speed = USB_SPEED_HIGH; /* support dual speed */
-#ifdef OTG_TRANSCEIVER
- dev->gadget.is_otg = 1; /* support otg mode */
-#endif
/* the "gadget" abstracts/virtualizes the controller */
dev_set_name(&dev->gadget.dev, "gadget");
@@ -3282,10 +3205,8 @@ static int langwell_udc_probe(struct pci_dev *pdev,
/* controller endpoints reinit */
eps_reinit(dev);
-#ifndef OTG_TRANSCEIVER
/* reset ep0 dQH and endptctrl */
ep0_reset(dev);
-#endif
/* create dTD dma_pool resource */
dev->dtd_pool = dma_pool_create("langwell_dtd",
@@ -3367,7 +3288,7 @@ static int langwell_udc_suspend(struct pci_dev *pdev, pm_message_t state)
spin_lock_irq(&dev->lock);
/* stop all usb activities */
- stop_activity(dev, dev->driver);
+ stop_activity(dev);
spin_unlock_irq(&dev->lock);
/* free dTD dma_pool and dQH */
@@ -3525,22 +3446,14 @@ static struct pci_driver langwell_pci_driver = {
static int __init init(void)
{
-#ifdef OTG_TRANSCEIVER
- return langwell_register_peripheral(&langwell_pci_driver);
-#else
return pci_register_driver(&langwell_pci_driver);
-#endif
}
module_init(init);
static void __exit cleanup(void)
{
-#ifdef OTG_TRANSCEIVER
- return langwell_unregister_peripheral(&langwell_pci_driver);
-#else
pci_unregister_driver(&langwell_pci_driver);
-#endif
}
module_exit(cleanup);
diff --git a/drivers/usb/gadget/langwell_udc.h b/drivers/usb/gadget/langwell_udc.h
index ef79e242b7b..d6e78accaff 100644
--- a/drivers/usb/gadget/langwell_udc.h
+++ b/drivers/usb/gadget/langwell_udc.h
@@ -8,7 +8,6 @@
*/
#include <linux/usb/langwell_udc.h>
-#include <linux/usb/langwell_otg.h>
/*-------------------------------------------------------------------------*/
diff --git a/drivers/usb/gadget/storage_common.c b/drivers/usb/gadget/storage_common.c
index c7f291a331d..52ab4098b3c 100644
--- a/drivers/usb/gadget/storage_common.c
+++ b/drivers/usb/gadget/storage_common.c
@@ -145,48 +145,8 @@
#endif /* DUMP_MSGS */
-
-
-
-
/*-------------------------------------------------------------------------*/
-/* Bulk-only data structures */
-
-/* Command Block Wrapper */
-struct fsg_bulk_cb_wrap {
- __le32 Signature; /* Contains 'USBC' */
- u32 Tag; /* Unique per command id */
- __le32 DataTransferLength; /* Size of the data */
- u8 Flags; /* Direction in bit 7 */
- u8 Lun; /* LUN (normally 0) */
- u8 Length; /* Of the CDB, <= MAX_COMMAND_SIZE */
- u8 CDB[16]; /* Command Data Block */
-};
-
-#define USB_BULK_CB_WRAP_LEN 31
-#define USB_BULK_CB_SIG 0x43425355 /* Spells out USBC */
-#define USB_BULK_IN_FLAG 0x80
-
-/* Command Status Wrapper */
-struct bulk_cs_wrap {
- __le32 Signature; /* Should = 'USBS' */
- u32 Tag; /* Same as original command */
- __le32 Residue; /* Amount not transferred */
- u8 Status; /* See below */
-};
-
-#define USB_BULK_CS_WRAP_LEN 13
-#define USB_BULK_CS_SIG 0x53425355 /* Spells out 'USBS' */
-#define USB_STATUS_PASS 0
-#define USB_STATUS_FAIL 1
-#define USB_STATUS_PHASE_ERROR 2
-
-/* Bulk-only class specific requests */
-#define USB_BULK_RESET_REQUEST 0xff
-#define USB_BULK_GET_MAX_LUN_REQUEST 0xfe
-
-
/* CBI Interrupt data structure */
struct interrupt_data {
u8 bType;
@@ -598,16 +558,16 @@ static __maybe_unused struct usb_ss_cap_descriptor fsg_ss_cap_desc = {
| USB_5GBPS_OPERATION),
.bFunctionalitySupport = USB_LOW_SPEED_OPERATION,
.bU1devExitLat = USB_DEFAULT_U1_DEV_EXIT_LAT,
- .bU2DevExitLat = USB_DEFAULT_U2_DEV_EXIT_LAT,
+ .bU2DevExitLat = cpu_to_le16(USB_DEFAULT_U2_DEV_EXIT_LAT),
};
static __maybe_unused struct usb_bos_descriptor fsg_bos_desc = {
.bLength = USB_DT_BOS_SIZE,
.bDescriptorType = USB_DT_BOS,
- .wTotalLength = USB_DT_BOS_SIZE
+ .wTotalLength = cpu_to_le16(USB_DT_BOS_SIZE
+ USB_DT_USB_EXT_CAP_SIZE
- + USB_DT_USB_SS_CAP_SIZE,
+ + USB_DT_USB_SS_CAP_SIZE),
.bNumDeviceCaps = 2,
};
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 91413cac97b..dd045173ab7 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -130,7 +130,7 @@ config USB_FSL_MPH_DR_OF
tristate
config USB_EHCI_FSL
- bool "Support for Freescale on-chip EHCI USB controller"
+ bool "Support for Freescale PPC on-chip EHCI USB controller"
depends on USB_EHCI_HCD && FSL_SOC
select USB_EHCI_ROOT_HUB_TT
select USB_FSL_MPH_DR_OF if OF
@@ -138,7 +138,7 @@ config USB_EHCI_FSL
Variation of ARC USB block used in some Freescale chips.
config USB_EHCI_MXC
- bool "Support for Freescale on-chip EHCI USB controller"
+ bool "Support for Freescale i.MX on-chip EHCI USB controller"
depends on USB_EHCI_HCD && ARCH_MXC
select USB_EHCI_ROOT_HUB_TT
---help---
@@ -196,7 +196,7 @@ config USB_EHCI_S5P
config USB_EHCI_MV
bool "EHCI support for Marvell on-chip controller"
- depends on USB_EHCI_HCD
+ depends on USB_EHCI_HCD && (ARCH_PXA || ARCH_MMP)
select USB_EHCI_ROOT_HUB_TT
---help---
Enables support for Marvell (including PXA and MMP series) on-chip
@@ -546,7 +546,7 @@ config USB_RENESAS_USBHS_HCD
config USB_WHCI_HCD
tristate "Wireless USB Host Controller Interface (WHCI) driver (EXPERIMENTAL)"
depends on EXPERIMENTAL
- depends on PCI && USB
+ depends on PCI && USB && UWB
select USB_WUSB
select UWB_WHCI
help
@@ -559,7 +559,7 @@ config USB_WHCI_HCD
config USB_HWA_HCD
tristate "Host Wire Adapter (HWA) driver (EXPERIMENTAL)"
depends on EXPERIMENTAL
- depends on USB
+ depends on USB && UWB
select USB_WUSB
select UWB_HWA
help
@@ -606,10 +606,3 @@ config USB_OCTEON_OHCI
config USB_OCTEON2_COMMON
bool
default y if USB_OCTEON_EHCI || USB_OCTEON_OHCI
-
-config USB_PXA168_EHCI
- bool "Marvell PXA168 on-chip EHCI HCD support"
- depends on USB_EHCI_HCD && ARCH_MMP
- help
- Enable support for Marvell PXA168 SoC's on-chip EHCI
- host controller
diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c
index d6d74d2e09f..fd9109d7eb0 100644
--- a/drivers/usb/host/ehci-dbg.c
+++ b/drivers/usb/host/ehci-dbg.c
@@ -107,7 +107,7 @@ static void dbg_hcc_params (struct ehci_hcd *ehci, char *label)
HCC_PER_PORT_CHANGE_EVENT(params) ? " ppce" : "",
HCC_HW_PREFETCH(params) ? " hw prefetch" : "",
HCC_32FRAME_PERIODIC_LIST(params) ?
- " 32 peridic list" : "");
+ " 32 periodic list" : "");
}
}
#else
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
index e90344a1763..7a15c223575 100644
--- a/drivers/usb/host/ehci-fsl.c
+++ b/drivers/usb/host/ehci-fsl.c
@@ -125,7 +125,7 @@ static int usb_hcd_fsl_probe(const struct hc_driver *driver,
*/
if (pdata->init && pdata->init(pdev)) {
retval = -ENODEV;
- goto err3;
+ goto err4;
}
/* Enable USB controller, 83xx or 8536 */
@@ -216,6 +216,8 @@ static void ehci_fsl_setup_phy(struct ehci_hcd *ehci,
unsigned int port_offset)
{
u32 portsc;
+ struct usb_hcd *hcd = ehci_to_hcd(ehci);
+ void __iomem *non_ehci = hcd->regs;
portsc = ehci_readl(ehci, &ehci->regs->port_status[port_offset]);
portsc &= ~(PORT_PTS_MSK | PORT_PTS_PTW);
@@ -231,6 +233,8 @@ static void ehci_fsl_setup_phy(struct ehci_hcd *ehci,
portsc |= PORT_PTS_PTW;
/* fall through */
case FSL_USB2_PHY_UTMI:
+ /* enable UTMI PHY */
+ setbits32(non_ehci + FSL_SOC_USB_CTRL, CTRL_UTMI_PHY_EN);
portsc |= PORT_PTS_UTMI;
break;
case FSL_USB2_PHY_NONE:
@@ -239,7 +243,7 @@ static void ehci_fsl_setup_phy(struct ehci_hcd *ehci,
ehci_writel(ehci, portsc, &ehci->regs->port_status[port_offset]);
}
-static void ehci_fsl_usb_setup(struct ehci_hcd *ehci)
+static int ehci_fsl_usb_setup(struct ehci_hcd *ehci)
{
struct usb_hcd *hcd = ehci_to_hcd(ehci);
struct fsl_usb2_platform_data *pdata;
@@ -252,21 +256,18 @@ static void ehci_fsl_usb_setup(struct ehci_hcd *ehci)
if (pdata->have_sysif_regs) {
temp = in_be32(non_ehci + FSL_SOC_USB_CTRL);
out_be32(non_ehci + FSL_SOC_USB_CTRL, temp | 0x00000004);
- out_be32(non_ehci + FSL_SOC_USB_SNOOP1, 0x0000001b);
- }
-#if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
- /*
- * Turn on cache snooping hardware, since some PowerPC platforms
- * wholly rely on hardware to deal with cache coherent
- */
+ /*
+ * Turn on cache snooping hardware, since some PowerPC platforms
+ * wholly rely on hardware to deal with cache coherent
+ */
- /* Setup Snooping for all the 4GB space */
- /* SNOOP1 starts from 0x0, size 2G */
- out_be32(non_ehci + FSL_SOC_USB_SNOOP1, 0x0 | SNOOP_SIZE_2GB);
- /* SNOOP2 starts from 0x80000000, size 2G */
- out_be32(non_ehci + FSL_SOC_USB_SNOOP2, 0x80000000 | SNOOP_SIZE_2GB);
-#endif
+ /* Setup Snooping for all the 4GB space */
+ /* SNOOP1 starts from 0x0, size 2G */
+ out_be32(non_ehci + FSL_SOC_USB_SNOOP1, 0x0 | SNOOP_SIZE_2GB);
+ /* SNOOP2 starts from 0x80000000, size 2G */
+ out_be32(non_ehci + FSL_SOC_USB_SNOOP2, 0x80000000 | SNOOP_SIZE_2GB);
+ }
if ((pdata->operating_mode == FSL_USB2_DR_HOST) ||
(pdata->operating_mode == FSL_USB2_DR_OTG))
@@ -299,12 +300,19 @@ static void ehci_fsl_usb_setup(struct ehci_hcd *ehci)
#endif
out_be32(non_ehci + FSL_SOC_USB_SICTRL, 0x00000001);
}
+
+ if (!(in_be32(non_ehci + FSL_SOC_USB_CTRL) & CTRL_PHY_CLK_VALID)) {
+ printk(KERN_WARNING "fsl-ehci: USB PHY clock invalid\n");
+ return -ENODEV;
+ }
+ return 0;
}
/* called after powerup, by probe or system-pm "wakeup" */
static int ehci_fsl_reinit(struct ehci_hcd *ehci)
{
- ehci_fsl_usb_setup(ehci);
+ if (ehci_fsl_usb_setup(ehci))
+ return -ENODEV;
ehci_port_power(ehci, 0);
return 0;
@@ -316,7 +324,9 @@ static int ehci_fsl_setup(struct usb_hcd *hcd)
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
int retval;
struct fsl_usb2_platform_data *pdata;
+ struct device *dev;
+ dev = hcd->self.controller;
pdata = hcd->self.controller->platform_data;
ehci->big_endian_desc = pdata->big_endian_desc;
ehci->big_endian_mmio = pdata->big_endian_mmio;
@@ -346,6 +356,16 @@ static int ehci_fsl_setup(struct usb_hcd *hcd)
ehci_reset(ehci);
+ if (of_device_is_compatible(dev->parent->of_node,
+ "fsl,mpc5121-usb2-dr")) {
+ /*
+ * set SBUSCFG:AHBBRST so that control msgs don't
+ * fail when doing heavy PATA writes.
+ */
+ ehci_writel(ehci, SBUSCFG_INCR8,
+ hcd->regs + FSL_SOC_USB_SBUSCFG);
+ }
+
retval = ehci_fsl_reinit(ehci);
return retval;
}
@@ -469,6 +489,8 @@ static int ehci_fsl_mpc512x_drv_resume(struct device *dev)
ehci_writel(ehci, ISIPHYCTRL_PXE | ISIPHYCTRL_PHYE,
hcd->regs + FSL_SOC_USB_ISIPHYCTRL);
+ ehci_writel(ehci, SBUSCFG_INCR8, hcd->regs + FSL_SOC_USB_SBUSCFG);
+
/* restore EHCI registers */
ehci_writel(ehci, pdata->pm_command, &ehci->regs->command);
ehci_writel(ehci, pdata->pm_intr_enable, &ehci->regs->intr_enable);
diff --git a/drivers/usb/host/ehci-fsl.h b/drivers/usb/host/ehci-fsl.h
index 49180622116..863fb0c080d 100644
--- a/drivers/usb/host/ehci-fsl.h
+++ b/drivers/usb/host/ehci-fsl.h
@@ -19,6 +19,8 @@
#define _EHCI_FSL_H
/* offsets for the non-ehci registers in the FSL SOC USB controller */
+#define FSL_SOC_USB_SBUSCFG 0x90
+#define SBUSCFG_INCR8 0x02 /* INCR8, specified */
#define FSL_SOC_USB_ULPIVP 0x170
#define FSL_SOC_USB_PORTSC1 0x184
#define PORT_PTS_MSK (3<<30)
@@ -45,5 +47,7 @@
#define FSL_SOC_USB_PRICTRL 0x40c /* NOTE: big-endian */
#define FSL_SOC_USB_SICTRL 0x410 /* NOTE: big-endian */
#define FSL_SOC_USB_CTRL 0x500 /* NOTE: big-endian */
+#define CTRL_UTMI_PHY_EN (1<<9)
+#define CTRL_PHY_CLK_VALID (1 << 17)
#define SNOOP_SIZE_2GB 0x1e
#endif /* _EHCI_FSL_H */
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index a007a9fe0f8..06e2548b549 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -1361,11 +1361,6 @@ MODULE_LICENSE ("GPL");
#define PLATFORM_DRIVER ehci_grlib_driver
#endif
-#ifdef CONFIG_USB_PXA168_EHCI
-#include "ehci-pxa168.c"
-#define PLATFORM_DRIVER ehci_pxa168_driver
-#endif
-
#ifdef CONFIG_CPU_XLR
#include "ehci-xls.c"
#define PLATFORM_DRIVER ehci_xls_driver
@@ -1376,6 +1371,11 @@ MODULE_LICENSE ("GPL");
#define PLATFORM_DRIVER ehci_mv_driver
#endif
+#ifdef CONFIG_MACH_LOONGSON1
+#include "ehci-ls1x.c"
+#define PLATFORM_DRIVER ehci_ls1x_driver
+#endif
+
#if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \
!defined(PS3_SYSTEM_BUS_DRIVER) && !defined(OF_PLATFORM_DRIVER) && \
!defined(XILINX_OF_PLATFORM_DRIVER)
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index 77bbb2357e4..01011dd0cb5 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -107,7 +107,7 @@ static void ehci_handover_companion_ports(struct ehci_hcd *ehci)
ehci->owned_ports = 0;
}
-static int ehci_port_change(struct ehci_hcd *ehci)
+static int __maybe_unused ehci_port_change(struct ehci_hcd *ehci)
{
int i = HCS_N_PORTS(ehci->hcs_params);
@@ -1076,7 +1076,8 @@ error_exit:
return retval;
}
-static void ehci_relinquish_port(struct usb_hcd *hcd, int portnum)
+static void __maybe_unused ehci_relinquish_port(struct usb_hcd *hcd,
+ int portnum)
{
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
@@ -1085,7 +1086,8 @@ static void ehci_relinquish_port(struct usb_hcd *hcd, int portnum)
set_owner(ehci, --portnum, PORT_OWNER);
}
-static int ehci_port_handed_over(struct usb_hcd *hcd, int portnum)
+static int __maybe_unused ehci_port_handed_over(struct usb_hcd *hcd,
+ int portnum)
{
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
u32 __iomem *reg;
diff --git a/drivers/usb/host/ehci-ls1x.c b/drivers/usb/host/ehci-ls1x.c
new file mode 100644
index 00000000000..a283e59709d
--- /dev/null
+++ b/drivers/usb/host/ehci-ls1x.c
@@ -0,0 +1,159 @@
+/*
+ * Bus Glue for Loongson LS1X built-in EHCI controller.
+ *
+ * Copyright (c) 2012 Zhang, Keguang <keguang.zhang@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ */
+
+
+#include <linux/platform_device.h>
+
+static int ehci_ls1x_reset(struct usb_hcd *hcd)
+{
+ struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+ int ret;
+
+ ehci->caps = hcd->regs;
+
+ ret = ehci_setup(hcd);
+ if (ret)
+ return ret;
+
+ ehci_port_power(ehci, 0);
+
+ return 0;
+}
+
+static const struct hc_driver ehci_ls1x_hc_driver = {
+ .description = hcd_name,
+ .product_desc = "LOONGSON1 EHCI",
+ .hcd_priv_size = sizeof(struct ehci_hcd),
+
+ /*
+ * generic hardware linkage
+ */
+ .irq = ehci_irq,
+ .flags = HCD_MEMORY | HCD_USB2,
+
+ /*
+ * basic lifecycle operations
+ */
+ .reset = ehci_ls1x_reset,
+ .start = ehci_run,
+ .stop = ehci_stop,
+ .shutdown = ehci_shutdown,
+
+ /*
+ * managing i/o requests and associated device resources
+ */
+ .urb_enqueue = ehci_urb_enqueue,
+ .urb_dequeue = ehci_urb_dequeue,
+ .endpoint_disable = ehci_endpoint_disable,
+ .endpoint_reset = ehci_endpoint_reset,
+
+ /*
+ * scheduling support
+ */
+ .get_frame_number = ehci_get_frame,
+
+ /*
+ * root hub support
+ */
+ .hub_status_data = ehci_hub_status_data,
+ .hub_control = ehci_hub_control,
+ .relinquish_port = ehci_relinquish_port,
+ .port_handed_over = ehci_port_handed_over,
+
+ .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
+};
+
+static int ehci_hcd_ls1x_probe(struct platform_device *pdev)
+{
+ struct usb_hcd *hcd;
+ struct resource *res;
+ int irq;
+ int ret;
+
+ pr_debug("initializing loongson1 ehci USB Controller\n");
+
+ if (usb_disabled())
+ return -ENODEV;
+
+ res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ if (!res) {
+ dev_err(&pdev->dev,
+ "Found HC with no IRQ. Check %s setup!\n",
+ dev_name(&pdev->dev));
+ return -ENODEV;
+ }
+ irq = res->start;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(&pdev->dev,
+ "Found HC with no register addr. Check %s setup!\n",
+ dev_name(&pdev->dev));
+ return -ENODEV;
+ }
+
+ hcd = usb_create_hcd(&ehci_ls1x_hc_driver, &pdev->dev,
+ dev_name(&pdev->dev));
+ if (!hcd)
+ return -ENOMEM;
+ hcd->rsrc_start = res->start;
+ hcd->rsrc_len = resource_size(res);
+
+ if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
+ dev_dbg(&pdev->dev, "controller already in use\n");
+ ret = -EBUSY;
+ goto err_put_hcd;
+ }
+
+ hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
+ if (hcd->regs == NULL) {
+ dev_dbg(&pdev->dev, "error mapping memory\n");
+ ret = -EFAULT;
+ goto err_release_region;
+ }
+
+ ret = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED);
+ if (ret)
+ goto err_iounmap;
+
+ return ret;
+
+err_iounmap:
+ iounmap(hcd->regs);
+err_release_region:
+ release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+err_put_hcd:
+ usb_put_hcd(hcd);
+ return ret;
+}
+
+static int ehci_hcd_ls1x_remove(struct platform_device *pdev)
+{
+ struct usb_hcd *hcd = platform_get_drvdata(pdev);
+
+ usb_remove_hcd(hcd);
+ iounmap(hcd->regs);
+ release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+ usb_put_hcd(hcd);
+
+ return 0;
+}
+
+static struct platform_driver ehci_ls1x_driver = {
+ .probe = ehci_hcd_ls1x_probe,
+ .remove = ehci_hcd_ls1x_remove,
+ .shutdown = usb_hcd_platform_shutdown,
+ .driver = {
+ .name = "ls1x-ehci",
+ .owner = THIS_MODULE,
+ },
+};
+
+MODULE_ALIAS(PLATFORM_MODULE_PREFIX "ls1x-ehci");
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
index f4b627d343a..01bb7241d6e 100644
--- a/drivers/usb/host/ehci-pci.c
+++ b/drivers/usb/host/ehci-pci.c
@@ -276,6 +276,9 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
/* Serial Bus Release Number is at PCI 0x60 offset */
pci_read_config_byte(pdev, 0x60, &ehci->sbrn);
+ if (pdev->vendor == PCI_VENDOR_ID_STMICRO
+ && pdev->device == PCI_DEVICE_ID_STMICRO_USB_HOST)
+ ehci->sbrn = 0x20; /* ConneXT has no sbrn register */
/* Keep this around for a while just in case some EHCI
* implementation uses legacy PCI PM support. This test
@@ -526,6 +529,9 @@ static const struct pci_device_id pci_ids [] = { {
/* handle any USB 2.0 EHCI controller */
PCI_DEVICE_CLASS(PCI_CLASS_SERIAL_USB_EHCI, ~0),
.driver_data = (unsigned long) &ehci_pci_hc_driver,
+ }, {
+ PCI_VDEVICE(STMICRO, PCI_DEVICE_ID_STMICRO_USB_HOST),
+ .driver_data = (unsigned long) &ehci_pci_hc_driver,
},
{ /* end: all zeroes */ }
};
diff --git a/drivers/usb/host/ehci-pxa168.c b/drivers/usb/host/ehci-pxa168.c
deleted file mode 100644
index 8d0e7a22e71..00000000000
--- a/drivers/usb/host/ehci-pxa168.c
+++ /dev/null
@@ -1,363 +0,0 @@
-/*
- * drivers/usb/host/ehci-pxa168.c
- *
- * Tanmay Upadhyay <tanmay.upadhyay@einfochips.com>
- *
- * Based on drivers/usb/host/ehci-orion.c
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/clk.h>
-#include <mach/pxa168.h>
-
-#define USB_PHY_CTRL_REG 0x4
-#define USB_PHY_PLL_REG 0x8
-#define USB_PHY_TX_REG 0xc
-
-#define FBDIV_SHIFT 4
-
-#define ICP_SHIFT 12
-#define ICP_15 2
-#define ICP_20 3
-#define ICP_25 4
-
-#define KVCO_SHIFT 15
-
-#define PLLCALI12_SHIFT 25
-#define CALI12_VDD 0
-#define CALI12_09 1
-#define CALI12_10 2
-#define CALI12_11 3
-
-#define PLLVDD12_SHIFT 27
-#define VDD12_VDD 0
-#define VDD12_10 1
-#define VDD12_11 2
-#define VDD12_12 3
-
-#define PLLVDD18_SHIFT 29
-#define VDD18_19 0
-#define VDD18_20 1
-#define VDD18_21 2
-#define VDD18_22 3
-
-
-#define PLL_READY (1 << 23)
-#define VCOCAL_START (1 << 21)
-#define REG_RCAL_START (1 << 12)
-
-struct pxa168_usb_drv_data {
- struct ehci_hcd ehci;
- struct clk *pxa168_usb_clk;
- struct resource *usb_phy_res;
- void __iomem *usb_phy_reg_base;
-};
-
-static int ehci_pxa168_setup(struct usb_hcd *hcd)
-{
- struct ehci_hcd *ehci = hcd_to_ehci(hcd);
- int retval;
-
- ehci_reset(ehci);
- retval = ehci_halt(ehci);
- if (retval)
- return retval;
-
- /*
- * data structure init
- */
- retval = ehci_init(hcd);
- if (retval)
- return retval;
-
- hcd->has_tt = 1;
-
- ehci_port_power(ehci, 0);
-
- return retval;
-}
-
-static const struct hc_driver ehci_pxa168_hc_driver = {
- .description = hcd_name,
- .product_desc = "Marvell PXA168 EHCI",
- .hcd_priv_size = sizeof(struct pxa168_usb_drv_data),
-
- /*
- * generic hardware linkage
- */
- .irq = ehci_irq,
- .flags = HCD_MEMORY | HCD_USB2,
-
- /*
- * basic lifecycle operations
- */
- .reset = ehci_pxa168_setup,
- .start = ehci_run,
- .stop = ehci_stop,
- .shutdown = ehci_shutdown,
-
- /*
- * managing i/o requests and associated device resources
- */
- .urb_enqueue = ehci_urb_enqueue,
- .urb_dequeue = ehci_urb_dequeue,
- .endpoint_disable = ehci_endpoint_disable,
- .endpoint_reset = ehci_endpoint_reset,
-
- /*
- * scheduling support
- */
- .get_frame_number = ehci_get_frame,
-
- /*
- * root hub support
- */
- .hub_status_data = ehci_hub_status_data,
- .hub_control = ehci_hub_control,
- .bus_suspend = ehci_bus_suspend,
- .bus_resume = ehci_bus_resume,
- .relinquish_port = ehci_relinquish_port,
- .port_handed_over = ehci_port_handed_over,
-
- .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
-};
-
-static int pxa168_usb_phy_init(struct platform_device *pdev)
-{
- struct resource *res;
- void __iomem *usb_phy_reg_base;
- struct pxa168_usb_pdata *pdata;
- struct pxa168_usb_drv_data *drv_data;
- struct usb_hcd *hcd = platform_get_drvdata(pdev);
- unsigned long reg_val;
- int pll_retry_cont = 10000, err = 0;
-
- drv_data = (struct pxa168_usb_drv_data *)hcd->hcd_priv;
- pdata = (struct pxa168_usb_pdata *)pdev->dev.platform_data;
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
- if (!res) {
- dev_err(&pdev->dev,
- "Found HC with no PHY register addr. Check %s setup!\n",
- dev_name(&pdev->dev));
- return -ENODEV;
- }
-
- if (!request_mem_region(res->start, resource_size(res),
- ehci_pxa168_hc_driver.description)) {
- dev_dbg(&pdev->dev, "controller already in use\n");
- return -EBUSY;
- }
-
- usb_phy_reg_base = ioremap(res->start, resource_size(res));
- if (usb_phy_reg_base == NULL) {
- dev_dbg(&pdev->dev, "error mapping memory\n");
- err = -EFAULT;
- goto err1;
- }
- drv_data->usb_phy_reg_base = usb_phy_reg_base;
- drv_data->usb_phy_res = res;
-
- /* If someone wants to init USB phy in board specific way */
- if (pdata && pdata->phy_init)
- return pdata->phy_init(usb_phy_reg_base);
-
- /* Power up the PHY and PLL */
- writel(readl(usb_phy_reg_base + USB_PHY_CTRL_REG) | 0x3,
- usb_phy_reg_base + USB_PHY_CTRL_REG);
-
- /* Configure PHY PLL */
- reg_val = readl(usb_phy_reg_base + USB_PHY_PLL_REG) & ~(0x7e03ffff);
- reg_val |= (VDD18_22 << PLLVDD18_SHIFT | VDD12_12 << PLLVDD12_SHIFT |
- CALI12_11 << PLLCALI12_SHIFT | 3 << KVCO_SHIFT |
- ICP_15 << ICP_SHIFT | 0xee << FBDIV_SHIFT | 0xb);
- writel(reg_val, usb_phy_reg_base + USB_PHY_PLL_REG);
-
- /* Make sure PHY PLL is ready */
- while (!(readl(usb_phy_reg_base + USB_PHY_PLL_REG) & PLL_READY)) {
- if (!(pll_retry_cont--)) {
- dev_dbg(&pdev->dev, "USB PHY PLL not ready\n");
- err = -EIO;
- goto err2;
- }
- }
-
- /* Toggle VCOCAL_START bit of U2PLL for PLL calibration */
- udelay(200);
- writel(readl(usb_phy_reg_base + USB_PHY_PLL_REG) | VCOCAL_START,
- usb_phy_reg_base + USB_PHY_PLL_REG);
- udelay(40);
- writel(readl(usb_phy_reg_base + USB_PHY_PLL_REG) & ~VCOCAL_START,
- usb_phy_reg_base + USB_PHY_PLL_REG);
-
- /* Toggle REG_RCAL_START bit of U2PTX for impedance calibration */
- udelay(400);
- writel(readl(usb_phy_reg_base + USB_PHY_TX_REG) | REG_RCAL_START,
- usb_phy_reg_base + USB_PHY_TX_REG);
- udelay(40);
- writel(readl(usb_phy_reg_base + USB_PHY_TX_REG) & ~REG_RCAL_START,
- usb_phy_reg_base + USB_PHY_TX_REG);
-
- /* Make sure PHY PLL is ready again */
- pll_retry_cont = 0;
- while (!(readl(usb_phy_reg_base + USB_PHY_PLL_REG) & PLL_READY)) {
- if (!(pll_retry_cont--)) {
- dev_dbg(&pdev->dev, "USB PHY PLL not ready\n");
- err = -EIO;
- goto err2;
- }
- }
-
- return 0;
-err2:
- iounmap(usb_phy_reg_base);
-err1:
- release_mem_region(res->start, resource_size(res));
- return err;
-}
-
-static int __devinit ehci_pxa168_drv_probe(struct platform_device *pdev)
-{
- struct resource *res;
- struct usb_hcd *hcd;
- struct ehci_hcd *ehci;
- struct pxa168_usb_drv_data *drv_data;
- void __iomem *regs;
- int irq, err = 0;
-
- if (usb_disabled())
- return -ENODEV;
-
- pr_debug("Initializing pxa168-SoC USB Host Controller\n");
-
- irq = platform_get_irq(pdev, 0);
- if (irq <= 0) {
- dev_err(&pdev->dev,
- "Found HC with no IRQ. Check %s setup!\n",
- dev_name(&pdev->dev));
- err = -ENODEV;
- goto err1;
- }
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res) {
- dev_err(&pdev->dev,
- "Found HC with no register addr. Check %s setup!\n",
- dev_name(&pdev->dev));
- err = -ENODEV;
- goto err1;
- }
-
- if (!request_mem_region(res->start, resource_size(res),
- ehci_pxa168_hc_driver.description)) {
- dev_dbg(&pdev->dev, "controller already in use\n");
- err = -EBUSY;
- goto err1;
- }
-
- regs = ioremap(res->start, resource_size(res));
- if (regs == NULL) {
- dev_dbg(&pdev->dev, "error mapping memory\n");
- err = -EFAULT;
- goto err2;
- }
-
- hcd = usb_create_hcd(&ehci_pxa168_hc_driver,
- &pdev->dev, dev_name(&pdev->dev));
- if (!hcd) {
- err = -ENOMEM;
- goto err3;
- }
-
- drv_data = (struct pxa168_usb_drv_data *)hcd->hcd_priv;
-
- /* Enable USB clock */
- drv_data->pxa168_usb_clk = clk_get(&pdev->dev, "PXA168-USBCLK");
- if (IS_ERR(drv_data->pxa168_usb_clk)) {
- dev_err(&pdev->dev, "Couldn't get USB clock\n");
- err = PTR_ERR(drv_data->pxa168_usb_clk);
- goto err4;
- }
- clk_enable(drv_data->pxa168_usb_clk);
-
- err = pxa168_usb_phy_init(pdev);
- if (err) {
- dev_err(&pdev->dev, "USB PHY initialization failed\n");
- goto err5;
- }
-
- hcd->rsrc_start = res->start;
- hcd->rsrc_len = resource_size(res);
- hcd->regs = regs;
-
- ehci = hcd_to_ehci(hcd);
- ehci->caps = hcd->regs + 0x100;
- ehci->regs = hcd->regs + 0x100 +
- HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
- ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
- hcd->has_tt = 1;
- ehci->sbrn = 0x20;
-
- err = usb_add_hcd(hcd, irq, IRQF_SHARED | IRQF_DISABLED);
- if (err)
- goto err5;
-
- return 0;
-
-err5:
- clk_disable(drv_data->pxa168_usb_clk);
- clk_put(drv_data->pxa168_usb_clk);
-err4:
- usb_put_hcd(hcd);
-err3:
- iounmap(regs);
-err2:
- release_mem_region(res->start, resource_size(res));
-err1:
- dev_err(&pdev->dev, "init %s fail, %d\n",
- dev_name(&pdev->dev), err);
-
- return err;
-}
-
-static int __exit ehci_pxa168_drv_remove(struct platform_device *pdev)
-{
- struct usb_hcd *hcd = platform_get_drvdata(pdev);
- struct pxa168_usb_drv_data *drv_data =
- (struct pxa168_usb_drv_data *)hcd->hcd_priv;
-
- usb_remove_hcd(hcd);
-
- /* Power down PHY & PLL */
- writel(readl(drv_data->usb_phy_reg_base + USB_PHY_CTRL_REG) & (~0x3),
- drv_data->usb_phy_reg_base + USB_PHY_CTRL_REG);
-
- clk_disable(drv_data->pxa168_usb_clk);
- clk_put(drv_data->pxa168_usb_clk);
-
- iounmap(hcd->regs);
- release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
-
- iounmap(drv_data->usb_phy_reg_base);
- release_mem_region(drv_data->usb_phy_res->start,
- resource_size(drv_data->usb_phy_res));
-
- usb_put_hcd(hcd);
-
- return 0;
-}
-
-MODULE_ALIAS("platform:pxa168-ehci");
-
-static struct platform_driver ehci_pxa168_driver = {
- .probe = ehci_pxa168_drv_probe,
- .remove = __exit_p(ehci_pxa168_drv_remove),
- .shutdown = usb_hcd_platform_shutdown,
- .driver.name = "pxa168-ehci",
-};
diff --git a/drivers/usb/host/ehci-spear.c b/drivers/usb/host/ehci-spear.c
index b115b0b76e3..6e928559169 100644
--- a/drivers/usb/host/ehci-spear.c
+++ b/drivers/usb/host/ehci-spear.c
@@ -11,8 +11,10 @@
* more details.
*/
-#include <linux/platform_device.h>
#include <linux/clk.h>
+#include <linux/jiffies.h>
+#include <linux/platform_device.h>
+#include <linux/pm.h>
struct spear_ehci {
struct ehci_hcd ehci;
@@ -90,6 +92,82 @@ static const struct hc_driver ehci_spear_hc_driver = {
.clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
};
+#ifdef CONFIG_PM
+static int ehci_spear_drv_suspend(struct device *dev)
+{
+ struct usb_hcd *hcd = dev_get_drvdata(dev);
+ struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+ unsigned long flags;
+ int rc = 0;
+
+ if (time_before(jiffies, ehci->next_statechange))
+ msleep(10);
+
+ /*
+ * Root hub was already suspended. Disable irq emission and mark HW
+ * unaccessible. The PM and USB cores make sure that the root hub is
+ * either suspended or stopped.
+ */
+ spin_lock_irqsave(&ehci->lock, flags);
+ ehci_prepare_ports_for_controller_suspend(ehci, device_may_wakeup(dev));
+ ehci_writel(ehci, 0, &ehci->regs->intr_enable);
+ ehci_readl(ehci, &ehci->regs->intr_enable);
+ spin_unlock_irqrestore(&ehci->lock, flags);
+
+ return rc;
+}
+
+static int ehci_spear_drv_resume(struct device *dev)
+{
+ struct usb_hcd *hcd = dev_get_drvdata(dev);
+ struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+
+ if (time_before(jiffies, ehci->next_statechange))
+ msleep(100);
+
+ if (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF) {
+ int mask = INTR_MASK;
+
+ ehci_prepare_ports_for_controller_resume(ehci);
+
+ if (!hcd->self.root_hub->do_remote_wakeup)
+ mask &= ~STS_PCD;
+
+ ehci_writel(ehci, mask, &ehci->regs->intr_enable);
+ ehci_readl(ehci, &ehci->regs->intr_enable);
+ return 0;
+ }
+
+ usb_root_hub_lost_power(hcd->self.root_hub);
+
+ /*
+ * Else reset, to cope with power loss or flush-to-storage style
+ * "resume" having let BIOS kick in during reboot.
+ */
+ ehci_halt(ehci);
+ ehci_reset(ehci);
+
+ /* emptying the schedule aborts any urbs */
+ spin_lock_irq(&ehci->lock);
+ if (ehci->reclaim)
+ end_unlink_async(ehci);
+
+ ehci_work(ehci);
+ spin_unlock_irq(&ehci->lock);
+
+ ehci_writel(ehci, ehci->command, &ehci->regs->command);
+ ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag);
+ ehci_readl(ehci, &ehci->regs->command); /* unblock posted writes */
+
+ /* here we "know" root ports should always stay powered */
+ ehci_port_power(ehci, 1);
+ return 0;
+}
+#endif /* CONFIG_PM */
+
+static SIMPLE_DEV_PM_OPS(ehci_spear_pm_ops, ehci_spear_drv_suspend,
+ ehci_spear_drv_resume);
+
static int spear_ehci_hcd_drv_probe(struct platform_device *pdev)
{
struct usb_hcd *hcd ;
@@ -205,7 +283,8 @@ static struct platform_driver spear_ehci_hcd_driver = {
.shutdown = usb_hcd_platform_shutdown,
.driver = {
.name = "spear-ehci",
- .bus = &platform_bus_type
+ .bus = &platform_bus_type,
+ .pm = &ehci_spear_pm_ops,
}
};
diff --git a/drivers/usb/host/fsl-mph-dr-of.c b/drivers/usb/host/fsl-mph-dr-of.c
index 7916e56a725..ab333ac6071 100644
--- a/drivers/usb/host/fsl-mph-dr-of.c
+++ b/drivers/usb/host/fsl-mph-dr-of.c
@@ -94,7 +94,6 @@ struct platform_device * __devinit fsl_usb2_device_register(
pdev->dev.parent = &ofdev->dev;
pdev->dev.coherent_dma_mask = ofdev->dev.coherent_dma_mask;
- pdev->dev.dma_mask = &pdev->archdata.dma_mask;
*pdev->dev.dma_mask = *ofdev->dev.dma_mask;
retval = platform_device_add_data(pdev, pdata, sizeof(*pdata));
diff --git a/drivers/usb/host/imx21-dbg.c b/drivers/usb/host/imx21-dbg.c
index 6d753342716..ec98ecee351 100644
--- a/drivers/usb/host/imx21-dbg.c
+++ b/drivers/usb/host/imx21-dbg.c
@@ -239,7 +239,7 @@ static int debug_status_show(struct seq_file *s, void *v)
"ETDs allocated: %d/%d (max=%d)\n"
"ETDs in use sw: %d\n"
"ETDs in use hw: %d\n"
- "DMEM alocated: %d/%d (max=%d)\n"
+ "DMEM allocated: %d/%d (max=%d)\n"
"DMEM blocks: %d\n"
"Queued waiting for ETD: %d\n"
"Queued waiting for DMEM: %d\n",
diff --git a/drivers/usb/host/isp1362-hcd.c b/drivers/usb/host/isp1362-hcd.c
index e5fd8aa57af..9e63cdf1ab7 100644
--- a/drivers/usb/host/isp1362-hcd.c
+++ b/drivers/usb/host/isp1362-hcd.c
@@ -2693,6 +2693,9 @@ static int __devinit isp1362_probe(struct platform_device *pdev)
struct resource *irq_res;
unsigned int irq_flags = 0;
+ if (usb_disabled())
+ return -ENODEV;
+
/* basic sanity checks first. board-specific init logic should
* have initialized this the three resources and probably board
* specific platform_data. we don't probe for IRQs, and do only
@@ -2864,19 +2867,4 @@ static struct platform_driver isp1362_driver = {
},
};
-/*-------------------------------------------------------------------------*/
-
-static int __init isp1362_init(void)
-{
- if (usb_disabled())
- return -ENODEV;
- pr_info("driver %s, %s\n", hcd_name, DRIVER_VERSION);
- return platform_driver_register(&isp1362_driver);
-}
-module_init(isp1362_init);
-
-static void __exit isp1362_cleanup(void)
-{
- platform_driver_unregister(&isp1362_driver);
-}
-module_exit(isp1362_cleanup);
+module_platform_driver(isp1362_driver);
diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c
index 5df0b0e3392..77afabc77f9 100644
--- a/drivers/usb/host/ohci-at91.c
+++ b/drivers/usb/host/ohci-at91.c
@@ -139,8 +139,23 @@ static int usb_hcd_at91_probe(const struct hc_driver *driver,
}
iclk = clk_get(&pdev->dev, "ohci_clk");
+ if (IS_ERR(iclk)) {
+ dev_err(&pdev->dev, "failed to get ohci_clk\n");
+ retval = PTR_ERR(iclk);
+ goto err3;
+ }
fclk = clk_get(&pdev->dev, "uhpck");
+ if (IS_ERR(fclk)) {
+ dev_err(&pdev->dev, "failed to get uhpck\n");
+ retval = PTR_ERR(fclk);
+ goto err4;
+ }
hclk = clk_get(&pdev->dev, "hclk");
+ if (IS_ERR(hclk)) {
+ dev_err(&pdev->dev, "failed to get hclk\n");
+ retval = PTR_ERR(hclk);
+ goto err5;
+ }
at91_start_hc(pdev);
ohci_hcd_init(hcd_to_ohci(hcd));
@@ -153,9 +168,12 @@ static int usb_hcd_at91_probe(const struct hc_driver *driver,
at91_stop_hc(pdev);
clk_put(hclk);
+ err5:
clk_put(fclk);
+ err4:
clk_put(iclk);
+ err3:
iounmap(hcd->regs);
err2:
@@ -226,7 +244,8 @@ static void ohci_at91_usb_set_power(struct at91_usbh_data *pdata, int port, int
if (!gpio_is_valid(pdata->vbus_pin[port]))
return;
- gpio_set_value(pdata->vbus_pin[port], !pdata->vbus_pin_inverted ^ enable);
+ gpio_set_value(pdata->vbus_pin[port],
+ !pdata->vbus_pin_active_low[port] ^ enable);
}
static int ohci_at91_usb_get_power(struct at91_usbh_data *pdata, int port)
@@ -237,7 +256,8 @@ static int ohci_at91_usb_get_power(struct at91_usbh_data *pdata, int port)
if (!gpio_is_valid(pdata->vbus_pin[port]))
return -EINVAL;
- return gpio_get_value(pdata->vbus_pin[port]) ^ !pdata->vbus_pin_inverted;
+ return gpio_get_value(pdata->vbus_pin[port]) ^
+ !pdata->vbus_pin_active_low[port];
}
/*
diff --git a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c
index 5179fcd73d8..e4bcb62b930 100644
--- a/drivers/usb/host/ohci-dbg.c
+++ b/drivers/usb/host/ohci-dbg.c
@@ -82,6 +82,14 @@ urb_print(struct urb * urb, char * str, int small, int status)
ohci_dbg(ohci,format, ## arg ); \
} while (0);
+/* Version for use where "next" is the address of a local variable */
+#define ohci_dbg_nosw(ohci, next, size, format, arg...) \
+ do { \
+ unsigned s_len; \
+ s_len = scnprintf(*next, *size, format, ## arg); \
+ *size -= s_len; *next += s_len; \
+ } while (0);
+
static void ohci_dump_intr_mask (
struct ohci_hcd *ohci,
@@ -653,7 +661,7 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf)
/* dump driver info, then registers in spec order */
- ohci_dbg_sw (ohci, &next, &size,
+ ohci_dbg_nosw(ohci, &next, &size,
"bus %s, device %s\n"
"%s\n"
"%s\n",
@@ -672,7 +680,7 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf)
/* hcca */
if (ohci->hcca)
- ohci_dbg_sw (ohci, &next, &size,
+ ohci_dbg_nosw(ohci, &next, &size,
"hcca frame 0x%04x\n", ohci_frame_no(ohci));
/* other registers mostly affect frame timings */
diff --git a/drivers/usb/host/ohci-exynos.c b/drivers/usb/host/ohci-exynos.c
index 55aa35aa3d7..37bb20ebb6f 100644
--- a/drivers/usb/host/ohci-exynos.c
+++ b/drivers/usb/host/ohci-exynos.c
@@ -212,12 +212,10 @@ static int exynos_ohci_suspend(struct device *dev)
* mark HW unaccessible, bail out if RH has been resumed. Use
* the spinlock to properly synchronize with possible pending
* RH suspend or resume activity.
- *
- * This is still racy as hcd->state is manipulated outside of
- * any locks =P But that will be a different fix.
*/
spin_lock_irqsave(&ohci->lock, flags);
- if (hcd->state != HC_STATE_SUSPENDED && hcd->state != HC_STATE_HALT) {
+ if (ohci->rh_state != OHCI_RH_SUSPENDED &&
+ ohci->rh_state != OHCI_RH_HALTED) {
rc = -EINVAL;
goto fail;
}
diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c
index 6109810cc2d..1843bb68ac7 100644
--- a/drivers/usb/host/ohci-pci.c
+++ b/drivers/usb/host/ohci-pci.c
@@ -397,6 +397,10 @@ static const struct pci_device_id pci_ids [] = { {
/* handle any USB OHCI controller */
PCI_DEVICE_CLASS(PCI_CLASS_SERIAL_USB_OHCI, ~0),
.driver_data = (unsigned long) &ohci_pci_hc_driver,
+ }, {
+ /* The device in the ConneXT I/O hub has no class reg */
+ PCI_VDEVICE(STMICRO, PCI_DEVICE_ID_STMICRO_USB_OHCI),
+ .driver_data = (unsigned long) &ohci_pci_hc_driver,
}, { /* end: all zeroes */ }
};
MODULE_DEVICE_TABLE (pci, pci_ids);
diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c
index caf87428ca4..7732d69e49e 100644
--- a/drivers/usb/host/pci-quirks.c
+++ b/drivers/usb/host/pci-quirks.c
@@ -867,6 +867,22 @@ hc_init:
static void __devinit quirk_usb_early_handoff(struct pci_dev *pdev)
{
+ /* Skip Netlogic mips SoC's internal PCI USB controller.
+ * This device does not need/support EHCI/OHCI handoff
+ */
+ if (pdev->vendor == 0x184e) /* vendor Netlogic */
+ return;
+ if (pdev->class != PCI_CLASS_SERIAL_USB_UHCI &&
+ pdev->class != PCI_CLASS_SERIAL_USB_OHCI &&
+ pdev->class != PCI_CLASS_SERIAL_USB_EHCI &&
+ pdev->class != PCI_CLASS_SERIAL_USB_XHCI)
+ return;
+
+ if (pci_enable_device(pdev) < 0) {
+ dev_warn(&pdev->dev, "Can't enable PCI device, "
+ "BIOS handoff failed.\n");
+ return;
+ }
if (pdev->class == PCI_CLASS_SERIAL_USB_UHCI)
quirk_usb_handoff_uhci(pdev);
else if (pdev->class == PCI_CLASS_SERIAL_USB_OHCI)
@@ -875,5 +891,6 @@ static void __devinit quirk_usb_early_handoff(struct pci_dev *pdev)
quirk_usb_disable_ehci(pdev);
else if (pdev->class == PCI_CLASS_SERIAL_USB_XHCI)
quirk_usb_handoff_xhci(pdev);
+ pci_disable_device(pdev);
}
DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, quirk_usb_early_handoff);
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
index 6b5eb1017e2..e37dea87bb5 100644
--- a/drivers/usb/host/uhci-hcd.c
+++ b/drivers/usb/host/uhci-hcd.c
@@ -565,6 +565,9 @@ static int uhci_start(struct usb_hcd *hcd)
struct dentry __maybe_unused *dentry;
hcd->uses_new_polling = 1;
+ /* Accept arbitrarily long scatter-gather lists */
+ if (!(hcd->driver->flags & HCD_LOCAL_MEM))
+ hcd->self.sg_tablesize = ~0;
spin_lock_init(&uhci->lock);
setup_timer(&uhci->fsbr_timer, uhci_fsbr_timeout,
diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
index 35e257f79c7..673ad120c43 100644
--- a/drivers/usb/host/xhci-hub.c
+++ b/drivers/usb/host/xhci-hub.c
@@ -93,7 +93,7 @@ static void xhci_usb2_hub_descriptor(struct usb_hcd *hcd, struct xhci_hcd *xhci,
*/
memset(port_removable, 0, sizeof(port_removable));
for (i = 0; i < ports; i++) {
- portsc = xhci_readl(xhci, xhci->usb3_ports[i]);
+ portsc = xhci_readl(xhci, xhci->usb2_ports[i]);
/* If a device is removable, PORTSC reports a 0, same as in the
* hub descriptor DeviceRemovable bits.
*/
@@ -422,6 +422,32 @@ void xhci_set_link_state(struct xhci_hcd *xhci, __le32 __iomem **port_array,
xhci_writel(xhci, temp, port_array[port_id]);
}
+void xhci_set_remote_wake_mask(struct xhci_hcd *xhci,
+ __le32 __iomem **port_array, int port_id, u16 wake_mask)
+{
+ u32 temp;
+
+ temp = xhci_readl(xhci, port_array[port_id]);
+ temp = xhci_port_state_to_neutral(temp);
+
+ if (wake_mask & USB_PORT_FEAT_REMOTE_WAKE_CONNECT)
+ temp |= PORT_WKCONN_E;
+ else
+ temp &= ~PORT_WKCONN_E;
+
+ if (wake_mask & USB_PORT_FEAT_REMOTE_WAKE_DISCONNECT)
+ temp |= PORT_WKDISC_E;
+ else
+ temp &= ~PORT_WKDISC_E;
+
+ if (wake_mask & USB_PORT_FEAT_REMOTE_WAKE_OVER_CURRENT)
+ temp |= PORT_WKOC_E;
+ else
+ temp &= ~PORT_WKOC_E;
+
+ xhci_writel(xhci, temp, port_array[port_id]);
+}
+
/* Test and clear port RWC bit */
void xhci_test_and_clear_bit(struct xhci_hcd *xhci, __le32 __iomem **port_array,
int port_id, u32 port_bit)
@@ -448,6 +474,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
int slot_id;
struct xhci_bus_state *bus_state;
u16 link_state = 0;
+ u16 wake_mask = 0;
max_ports = xhci_get_ports(hcd, &port_array);
bus_state = &xhci->bus_state[hcd_index(hcd)];
@@ -593,6 +620,8 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
case SetPortFeature:
if (wValue == USB_PORT_FEAT_LINK_STATE)
link_state = (wIndex & 0xff00) >> 3;
+ if (wValue == USB_PORT_FEAT_REMOTE_WAKE_MASK)
+ wake_mask = wIndex & 0xff00;
wIndex &= 0xff;
if (!wIndex || wIndex > max_ports)
goto error;
@@ -703,6 +732,14 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
temp = xhci_readl(xhci, port_array[wIndex]);
xhci_dbg(xhci, "set port reset, actual port %d status = 0x%x\n", wIndex, temp);
break;
+ case USB_PORT_FEAT_REMOTE_WAKE_MASK:
+ xhci_set_remote_wake_mask(xhci, port_array,
+ wIndex, wake_mask);
+ temp = xhci_readl(xhci, port_array[wIndex]);
+ xhci_dbg(xhci, "set port remote wake mask, "
+ "actual port %d status = 0x%x\n",
+ wIndex, temp);
+ break;
case USB_PORT_FEAT_BH_PORT_RESET:
temp |= PORT_WR;
xhci_writel(xhci, temp, port_array[wIndex]);
@@ -883,6 +920,10 @@ int xhci_bus_suspend(struct usb_hcd *hcd)
t2 |= PORT_LINK_STROBE | XDEV_U3;
set_bit(port_index, &bus_state->bus_suspended);
}
+ /* USB core sets remote wake mask for USB 3.0 hubs,
+ * including the USB 3.0 roothub, but only if CONFIG_USB_SUSPEND
+ * is enabled, so also enable remote wake here.
+ */
if (hcd->self.root_hub->do_remote_wakeup) {
if (t1 & PORT_CONNECT) {
t2 |= PORT_WKOC_E | PORT_WKDISC_E;
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index 36cbe2226a4..8339d826ce5 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -1126,26 +1126,42 @@ static unsigned int xhci_parse_exponent_interval(struct usb_device *udev,
}
/*
- * Convert bInterval expressed in frames (in 1-255 range) to exponent of
+ * Convert bInterval expressed in microframes (in 1-255 range) to exponent of
* microframes, rounded down to nearest power of 2.
*/
-static unsigned int xhci_parse_frame_interval(struct usb_device *udev,
- struct usb_host_endpoint *ep)
+static unsigned int xhci_microframes_to_exponent(struct usb_device *udev,
+ struct usb_host_endpoint *ep, unsigned int desc_interval,
+ unsigned int min_exponent, unsigned int max_exponent)
{
unsigned int interval;
- interval = fls(8 * ep->desc.bInterval) - 1;
- interval = clamp_val(interval, 3, 10);
- if ((1 << interval) != 8 * ep->desc.bInterval)
+ interval = fls(desc_interval) - 1;
+ interval = clamp_val(interval, min_exponent, max_exponent);
+ if ((1 << interval) != desc_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);
+ desc_interval);
return interval;
}
+static unsigned int xhci_parse_microframe_interval(struct usb_device *udev,
+ struct usb_host_endpoint *ep)
+{
+ return xhci_microframes_to_exponent(udev, ep,
+ ep->desc.bInterval, 0, 15);
+}
+
+
+static unsigned int xhci_parse_frame_interval(struct usb_device *udev,
+ struct usb_host_endpoint *ep)
+{
+ return xhci_microframes_to_exponent(udev, ep,
+ ep->desc.bInterval * 8, 3, 10);
+}
+
/* Return the polling or NAK interval.
*
* The polling interval is expressed in "microframes". If xHCI's Interval field
@@ -1164,7 +1180,7 @@ static unsigned int xhci_get_endpoint_interval(struct usb_device *udev,
/* Max NAK rate */
if (usb_endpoint_xfer_control(&ep->desc) ||
usb_endpoint_xfer_bulk(&ep->desc)) {
- interval = ep->desc.bInterval;
+ interval = xhci_parse_microframe_interval(udev, ep);
break;
}
/* Fall through - SS and HS isoc/int have same decoding */
@@ -2141,7 +2157,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
unsigned int val, val2;
u64 val_64;
struct xhci_segment *seg;
- u32 page_size;
+ u32 page_size, temp;
int i;
page_size = xhci_readl(xhci, &xhci->op_regs->page_size);
@@ -2324,6 +2340,15 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
INIT_LIST_HEAD(&xhci->lpm_failed_devs);
+ /* Enable USB 3.0 device notifications for function remote wake, which
+ * is necessary for allowing USB 3.0 devices to do remote wakeup from
+ * U3 (device suspend).
+ */
+ temp = xhci_readl(xhci, &xhci->op_regs->dev_notification);
+ temp &= ~DEV_NOTE_MASK;
+ temp |= DEV_NOTE_FWAKE;
+ xhci_writel(xhci, temp, &xhci->op_regs->dev_notification);
+
return 0;
fail:
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index b90e1386418..3a033240ec6 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -1204,6 +1204,7 @@ static void handle_vendor_event(struct xhci_hcd *xhci,
*
* Returns a zero-based port number, which is suitable for indexing into each of
* the split roothubs' port arrays and bus state arrays.
+ * Add one to it in order to call xhci_find_slot_id_by_port.
*/
static unsigned int find_faked_portnum_from_hw_portnum(struct usb_hcd *hcd,
struct xhci_hcd *xhci, u32 port_id)
@@ -1236,6 +1237,26 @@ static unsigned int find_faked_portnum_from_hw_portnum(struct usb_hcd *hcd,
return num_similar_speed_ports;
}
+static void handle_device_notification(struct xhci_hcd *xhci,
+ union xhci_trb *event)
+{
+ u32 slot_id;
+ struct usb_device *udev;
+
+ slot_id = TRB_TO_SLOT_ID(event->generic.field[3]);
+ if (!xhci->devs[slot_id]) {
+ xhci_warn(xhci, "Device Notification event for "
+ "unused slot %u\n", slot_id);
+ return;
+ }
+
+ xhci_dbg(xhci, "Device Wake Notification event for slot ID %u\n",
+ slot_id);
+ udev = xhci->devs[slot_id]->udev;
+ if (udev && udev->parent)
+ usb_wakeup_notification(udev->parent, udev->portnum);
+}
+
static void handle_port_status(struct xhci_hcd *xhci,
union xhci_trb *event)
{
@@ -1320,20 +1341,21 @@ static void handle_port_status(struct xhci_hcd *xhci,
}
if (DEV_SUPERSPEED(temp)) {
- xhci_dbg(xhci, "resume SS port %d\n", port_id);
+ xhci_dbg(xhci, "remote wake SS port %d\n", port_id);
+ /* Set a flag to say the port signaled remote wakeup,
+ * so we can tell the difference between the end of
+ * device and host initiated resume.
+ */
+ bus_state->port_remote_wakeup |= 1 << faked_port_index;
+ xhci_test_and_clear_bit(xhci, port_array,
+ faked_port_index, PORT_PLC);
xhci_set_link_state(xhci, port_array, faked_port_index,
XDEV_U0);
- slot_id = xhci_find_slot_id_by_port(hcd, xhci,
- faked_port_index);
- if (!slot_id) {
- xhci_dbg(xhci, "slot_id is zero\n");
- goto cleanup;
- }
- xhci_ring_device(xhci, slot_id);
- xhci_dbg(xhci, "resume SS port %d finished\n", port_id);
- /* Clear PORT_PLC */
- xhci_test_and_clear_bit(xhci, port_array,
- faked_port_index, PORT_PLC);
+ /* Need to wait until the next link state change
+ * indicates the device is actually in U0.
+ */
+ bogus_port_status = true;
+ goto cleanup;
} else {
xhci_dbg(xhci, "resume HS port %d\n", port_id);
bus_state->resume_done[faked_port_index] = jiffies +
@@ -1344,6 +1366,32 @@ static void handle_port_status(struct xhci_hcd *xhci,
}
}
+ if ((temp & PORT_PLC) && (temp & PORT_PLS_MASK) == XDEV_U0 &&
+ DEV_SUPERSPEED(temp)) {
+ xhci_dbg(xhci, "resume SS port %d finished\n", port_id);
+ /* We've just brought the device into U0 through either the
+ * Resume state after a device remote wakeup, or through the
+ * U3Exit state after a host-initiated resume. If it's a device
+ * initiated remote wake, don't pass up the link state change,
+ * so the roothub behavior is consistent with external
+ * USB 3.0 hub behavior.
+ */
+ slot_id = xhci_find_slot_id_by_port(hcd, xhci,
+ faked_port_index + 1);
+ if (slot_id && xhci->devs[slot_id])
+ xhci_ring_device(xhci, slot_id);
+ if (bus_state->port_remote_wakeup && (1 << faked_port_index)) {
+ bus_state->port_remote_wakeup &=
+ ~(1 << faked_port_index);
+ xhci_test_and_clear_bit(xhci, port_array,
+ faked_port_index, PORT_PLC);
+ usb_wakeup_notification(hcd->self.root_hub,
+ faked_port_index + 1);
+ bogus_port_status = true;
+ goto cleanup;
+ }
+ }
+
if (hcd->speed != HCD_USB3)
xhci_test_and_clear_bit(xhci, port_array, faked_port_index,
PORT_PLC);
@@ -2276,6 +2324,9 @@ static int xhci_handle_event(struct xhci_hcd *xhci)
else
update_ptrs = 0;
break;
+ case TRB_TYPE(TRB_DEV_NOTE):
+ handle_device_notification(xhci, event);
+ break;
default:
if ((le32_to_cpu(event->event_cmd.flags) & TRB_TYPE_BITMASK) >=
TRB_TYPE(48))
@@ -3323,7 +3374,8 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
/* Check TD length */
if (running_total != td_len) {
xhci_err(xhci, "ISOC TD length unmatch\n");
- return -EINVAL;
+ ret = -EINVAL;
+ goto cleanup;
}
}
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 6bbe3c3a711..c939f5fdef9 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -352,6 +352,11 @@ static int xhci_try_enable_msi(struct usb_hcd *hcd)
/* hcd->irq is -1, we have MSI */
return 0;
+ if (!pdev->irq) {
+ xhci_err(xhci, "No msi-x/msi found and no IRQ in BIOS\n");
+ return -EINVAL;
+ }
+
/* fall back to legacy interrupt*/
ret = request_irq(pdev->irq, &usb_hcd_irq, IRQF_SHARED,
hcd->irq_descr, hcd);
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index fb99c837914..0f493695610 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -1344,6 +1344,7 @@ struct xhci_bus_state {
/* ports suspend status arrays - max 31 ports for USB2, 15 for USB3 */
u32 port_c_suspend;
u32 suspended_ports;
+ u32 port_remote_wakeup;
unsigned long resume_done[USB_MAXCHILDREN];
};
diff --git a/drivers/usb/misc/emi26.c b/drivers/usb/misc/emi26.c
index d9b6a035544..da97dcec1f3 100644
--- a/drivers/usb/misc/emi26.c
+++ b/drivers/usb/misc/emi26.c
@@ -37,9 +37,6 @@ static int emi26_set_reset(struct usb_device *dev, unsigned char reset_bit);
static int emi26_load_firmware (struct usb_device *dev);
static int emi26_probe(struct usb_interface *intf, const struct usb_device_id *id);
static void emi26_disconnect(struct usb_interface *intf);
-static int __init emi26_init (void);
-static void __exit emi26_exit (void);
-
/* thanks to drivers/usb/serial/keyspan_pda.c code */
static int emi26_writememory (struct usb_device *dev, int address,
diff --git a/drivers/usb/misc/emi62.c b/drivers/usb/misc/emi62.c
index 9f39062ebb0..4e0f167a6c4 100644
--- a/drivers/usb/misc/emi62.c
+++ b/drivers/usb/misc/emi62.c
@@ -46,9 +46,6 @@ static int emi62_set_reset(struct usb_device *dev, unsigned char reset_bit);
static int emi62_load_firmware (struct usb_device *dev);
static int emi62_probe(struct usb_interface *intf, const struct usb_device_id *id);
static void emi62_disconnect(struct usb_interface *intf);
-static int __init emi62_init (void);
-static void __exit emi62_exit (void);
-
/* thanks to drivers/usb/serial/keyspan_pda.c code */
static int emi62_writememory(struct usb_device *dev, int address,
diff --git a/drivers/usb/misc/usbsevseg.c b/drivers/usb/misc/usbsevseg.c
index 107bf13b1cf..b2d82b93739 100644
--- a/drivers/usb/misc/usbsevseg.c
+++ b/drivers/usb/misc/usbsevseg.c
@@ -24,7 +24,7 @@
#define VENDOR_ID 0x0fc5
#define PRODUCT_ID 0x1227
-#define MAXLEN 6
+#define MAXLEN 8
/* table of devices that work with this driver */
static const struct usb_device_id id_table[] = {
diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c
index 7802c7ec43f..0ba3e75285c 100644
--- a/drivers/usb/musb/davinci.c
+++ b/drivers/usb/musb/davinci.c
@@ -33,9 +33,6 @@
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
-#include <mach/hardware.h>
-#include <mach/memory.h>
-#include <asm/gpio.h>
#include <mach/cputype.h>
#include <asm/mach-types.h>
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index d6134b39e8f..3746fff628b 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -981,6 +981,9 @@ static void musb_shutdown(struct platform_device *pdev)
unsigned long flags;
pm_runtime_get_sync(musb->controller);
+
+ musb_gadget_cleanup(musb);
+
spin_lock_irqsave(&musb->lock, flags);
musb_platform_disable(musb);
musb_generic_disable(musb);
@@ -1827,8 +1830,6 @@ static void musb_free(struct musb *musb)
sysfs_remove_group(&musb->controller->kobj, &musb_attr_group);
#endif
- musb_gadget_cleanup(musb);
-
if (musb->nIrq >= 0) {
if (musb->irq_wake)
disable_irq_wake(musb->nIrq);
diff --git a/drivers/usb/musb/musb_io.h b/drivers/usb/musb/musb_io.h
index e61aa95f2d2..1d5eda26fbd 100644
--- a/drivers/usb/musb/musb_io.h
+++ b/drivers/usb/musb/musb_io.h
@@ -39,7 +39,8 @@
#if !defined(CONFIG_ARM) && !defined(CONFIG_SUPERH) \
&& !defined(CONFIG_AVR32) && !defined(CONFIG_PPC32) \
- && !defined(CONFIG_PPC64) && !defined(CONFIG_BLACKFIN)
+ && !defined(CONFIG_PPC64) && !defined(CONFIG_BLACKFIN) \
+ && !defined(CONFIG_MIPS)
static inline void readsl(const void __iomem *addr, void *buf, int len)
{ insl((unsigned long)addr, buf, len); }
static inline void readsw(const void __iomem *addr, void *buf, int len)
diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c
index b254173e7e8..da430c31ebe 100644
--- a/drivers/usb/musb/omap2430.c
+++ b/drivers/usb/musb/omap2430.c
@@ -222,7 +222,6 @@ static inline void omap2430_low_level_init(struct musb *musb)
musb_writel(musb->mregs, OTG_FORCESTDBY, l);
}
-/* blocking notifier support */
static int musb_otg_notifications(struct notifier_block *nb,
unsigned long event, void *unused)
{
@@ -231,7 +230,7 @@ static int musb_otg_notifications(struct notifier_block *nb,
musb->xceiv_event = event;
schedule_work(&musb->otg_notifier_work);
- return 0;
+ return NOTIFY_OK;
}
static void musb_otg_notifier_work(struct work_struct *data_notifier_work)
@@ -386,6 +385,7 @@ static void omap2430_musb_disable(struct musb *musb)
static int omap2430_musb_exit(struct musb *musb)
{
del_timer_sync(&musb_idle_timer);
+ cancel_work_sync(&musb->otg_notifier_work);
omap2430_low_level_exit(musb);
otg_put_transceiver(musb->xceiv);
diff --git a/drivers/usb/otg/Kconfig b/drivers/usb/otg/Kconfig
index 2a25955881f..735ef4c2339 100644
--- a/drivers/usb/otg/Kconfig
+++ b/drivers/usb/otg/Kconfig
@@ -86,20 +86,6 @@ config NOP_USB_XCEIV
built-in with usb ip or which are autonomous and doesn't require any
phy programming such as ISP1x04 etc.
-config USB_LANGWELL_OTG
- tristate "Intel Langwell USB OTG dual-role support"
- depends on USB && PCI && INTEL_SCU_IPC
- select USB_OTG
- select USB_OTG_UTILS
- help
- Say Y here if you want to build Intel Langwell USB OTG
- transciever driver in kernel. This driver implements role
- switch between EHCI host driver and Langwell USB OTG
- client driver.
-
- To compile this driver as a module, choose M here: the
- module will be called langwell_otg.
-
config USB_MSM_OTG
tristate "OTG support for Qualcomm on-chip USB controller"
depends on (USB || USB_GADGET) && ARCH_MSM
@@ -124,7 +110,7 @@ config AB8500_USB
config FSL_USB2_OTG
bool "Freescale USB OTG Transceiver Driver"
- depends on USB_EHCI_FSL && USB_GADGET_FSL_USB2
+ depends on USB_EHCI_FSL && USB_GADGET_FSL_USB2 && USB_SUSPEND
select USB_OTG
select USB_OTG_UTILS
help
@@ -132,7 +118,7 @@ config FSL_USB2_OTG
config USB_MV_OTG
tristate "Marvell USB OTG support"
- depends on USB_MV_UDC
+ depends on USB_EHCI_MV && USB_MV_UDC && USB_SUSPEND
select USB_OTG
select USB_OTG_UTILS
help
diff --git a/drivers/usb/otg/Makefile b/drivers/usb/otg/Makefile
index b2c5a959863..41aa5098b13 100644
--- a/drivers/usb/otg/Makefile
+++ b/drivers/usb/otg/Makefile
@@ -13,7 +13,6 @@ obj-$(CONFIG_USB_GPIO_VBUS) += gpio_vbus.o
obj-$(CONFIG_ISP1301_OMAP) += isp1301_omap.o
obj-$(CONFIG_TWL4030_USB) += twl4030-usb.o
obj-$(CONFIG_TWL6030_USB) += twl6030-usb.o
-obj-$(CONFIG_USB_LANGWELL_OTG) += langwell_otg.o
obj-$(CONFIG_NOP_USB_XCEIV) += nop-usb-xceiv.o
obj-$(CONFIG_USB_ULPI) += ulpi.o
obj-$(CONFIG_USB_ULPI_VIEWPORT) += ulpi_viewport.o
diff --git a/drivers/usb/otg/langwell_otg.c b/drivers/usb/otg/langwell_otg.c
deleted file mode 100644
index f08f784086f..00000000000
--- a/drivers/usb/otg/langwell_otg.c
+++ /dev/null
@@ -1,2347 +0,0 @@
-/*
- * Intel Langwell USB OTG transceiver driver
- * Copyright (C) 2008 - 2010, Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-/* This driver helps to switch Langwell OTG controller function between host
- * and peripheral. It works with EHCI driver and Langwell client controller
- * driver together.
- */
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/device.h>
-#include <linux/moduleparam.h>
-#include <linux/usb/ch9.h>
-#include <linux/usb/gadget.h>
-#include <linux/usb.h>
-#include <linux/usb/otg.h>
-#include <linux/usb/hcd.h>
-#include <linux/notifier.h>
-#include <linux/delay.h>
-#include <asm/intel_scu_ipc.h>
-
-#include <linux/usb/langwell_otg.h>
-
-#define DRIVER_DESC "Intel Langwell USB OTG transceiver driver"
-#define DRIVER_VERSION "July 10, 2010"
-
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_AUTHOR("Henry Yuan <hang.yuan@intel.com>, Hao Wu <hao.wu@intel.com>");
-MODULE_VERSION(DRIVER_VERSION);
-MODULE_LICENSE("GPL");
-
-static const char driver_name[] = "langwell_otg";
-
-static int langwell_otg_probe(struct pci_dev *pdev,
- const struct pci_device_id *id);
-static void langwell_otg_remove(struct pci_dev *pdev);
-static int langwell_otg_suspend(struct pci_dev *pdev, pm_message_t message);
-static int langwell_otg_resume(struct pci_dev *pdev);
-
-static int langwell_otg_set_host(struct otg_transceiver *otg,
- struct usb_bus *host);
-static int langwell_otg_set_peripheral(struct otg_transceiver *otg,
- struct usb_gadget *gadget);
-static int langwell_otg_start_srp(struct otg_transceiver *otg);
-
-static const struct pci_device_id pci_ids[] = {{
- .class = ((PCI_CLASS_SERIAL_USB << 8) | 0xfe),
- .class_mask = ~0,
- .vendor = 0x8086,
- .device = 0x0811,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
-}, { /* end: all zeroes */ }
-};
-
-static struct pci_driver otg_pci_driver = {
- .name = (char *) driver_name,
- .id_table = pci_ids,
-
- .probe = langwell_otg_probe,
- .remove = langwell_otg_remove,
-
- .suspend = langwell_otg_suspend,
- .resume = langwell_otg_resume,
-};
-
-/* HSM timers */
-static inline struct langwell_otg_timer *otg_timer_initializer
-(void (*function)(unsigned long), unsigned long expires, unsigned long data)
-{
- struct langwell_otg_timer *timer;
- timer = kmalloc(sizeof(struct langwell_otg_timer), GFP_KERNEL);
- if (timer == NULL)
- return timer;
-
- timer->function = function;
- timer->expires = expires;
- timer->data = data;
- return timer;
-}
-
-static struct langwell_otg_timer *a_wait_vrise_tmr, *a_aidl_bdis_tmr,
- *b_se0_srp_tmr, *b_srp_init_tmr;
-
-static struct list_head active_timers;
-
-static struct langwell_otg *the_transceiver;
-
-/* host/client notify transceiver when event affects HNP state */
-void langwell_update_transceiver(void)
-{
- struct langwell_otg *lnw = the_transceiver;
-
- dev_dbg(lnw->dev, "transceiver is updated\n");
-
- if (!lnw->qwork)
- return ;
-
- queue_work(lnw->qwork, &lnw->work);
-}
-EXPORT_SYMBOL(langwell_update_transceiver);
-
-static int langwell_otg_set_host(struct otg_transceiver *otg,
- struct usb_bus *host)
-{
- otg->host = host;
-
- return 0;
-}
-
-static int langwell_otg_set_peripheral(struct otg_transceiver *otg,
- struct usb_gadget *gadget)
-{
- otg->gadget = gadget;
-
- return 0;
-}
-
-static int langwell_otg_set_power(struct otg_transceiver *otg,
- unsigned mA)
-{
- return 0;
-}
-
-/* A-device drives vbus, controlled through IPC commands */
-static int langwell_otg_set_vbus(struct otg_transceiver *otg, bool enabled)
-{
- struct langwell_otg *lnw = the_transceiver;
- u8 sub_id;
-
- dev_dbg(lnw->dev, "%s <--- %s\n", __func__, enabled ? "on" : "off");
-
- if (enabled)
- sub_id = 0x8; /* Turn on the VBus */
- else
- sub_id = 0x9; /* Turn off the VBus */
-
- if (intel_scu_ipc_simple_command(0xef, sub_id)) {
- dev_dbg(lnw->dev, "Failed to set Vbus via IPC commands\n");
- return -EBUSY;
- }
-
- dev_dbg(lnw->dev, "%s --->\n", __func__);
-
- return 0;
-}
-
-/* charge vbus or discharge vbus through a resistor to ground */
-static void langwell_otg_chrg_vbus(int on)
-{
- struct langwell_otg *lnw = the_transceiver;
- u32 val;
-
- val = readl(lnw->iotg.base + CI_OTGSC);
-
- if (on)
- writel((val & ~OTGSC_INTSTS_MASK) | OTGSC_VC,
- lnw->iotg.base + CI_OTGSC);
- else
- writel((val & ~OTGSC_INTSTS_MASK) | OTGSC_VD,
- lnw->iotg.base + CI_OTGSC);
-}
-
-/* Start SRP */
-static int langwell_otg_start_srp(struct otg_transceiver *otg)
-{
- struct langwell_otg *lnw = the_transceiver;
- struct intel_mid_otg_xceiv *iotg = &lnw->iotg;
- u32 val;
-
- dev_dbg(lnw->dev, "%s --->\n", __func__);
-
- val = readl(iotg->base + CI_OTGSC);
-
- writel((val & ~OTGSC_INTSTS_MASK) | OTGSC_HADP,
- iotg->base + CI_OTGSC);
-
- /* Check if the data plus is finished or not */
- msleep(8);
- val = readl(iotg->base + CI_OTGSC);
- if (val & (OTGSC_HADP | OTGSC_DP))
- dev_dbg(lnw->dev, "DataLine SRP Error\n");
-
- /* Disable interrupt - b_sess_vld */
- val = readl(iotg->base + CI_OTGSC);
- val &= (~(OTGSC_BSVIE | OTGSC_BSEIE));
- writel(val, iotg->base + CI_OTGSC);
-
- /* Start VBus SRP, drive vbus to generate VBus pulse */
- iotg->otg.set_vbus(&iotg->otg, true);
- msleep(15);
- iotg->otg.set_vbus(&iotg->otg, false);
-
- /* Enable interrupt - b_sess_vld*/
- val = readl(iotg->base + CI_OTGSC);
- dev_dbg(lnw->dev, "after VBUS pulse otgsc = %x\n", val);
-
- val |= (OTGSC_BSVIE | OTGSC_BSEIE);
- writel(val, iotg->base + CI_OTGSC);
-
- /* If Vbus is valid, then update the hsm */
- if (val & OTGSC_BSV) {
- dev_dbg(lnw->dev, "no b_sess_vld interrupt\n");
-
- lnw->iotg.hsm.b_sess_vld = 1;
- langwell_update_transceiver();
- }
-
- dev_dbg(lnw->dev, "%s <---\n", __func__);
- return 0;
-}
-
-/* stop SOF via bus_suspend */
-static void langwell_otg_loc_sof(int on)
-{
- struct langwell_otg *lnw = the_transceiver;
- struct usb_hcd *hcd;
- int err;
-
- dev_dbg(lnw->dev, "%s ---> %s\n", __func__, on ? "suspend" : "resume");
-
- hcd = bus_to_hcd(lnw->iotg.otg.host);
- if (on)
- err = hcd->driver->bus_resume(hcd);
- else
- err = hcd->driver->bus_suspend(hcd);
-
- if (err)
- dev_dbg(lnw->dev, "Fail to resume/suspend USB bus - %d\n", err);
-
- dev_dbg(lnw->dev, "%s <---\n", __func__);
-}
-
-static int langwell_otg_check_otgsc(void)
-{
- struct langwell_otg *lnw = the_transceiver;
- u32 otgsc, usbcfg;
-
- dev_dbg(lnw->dev, "check sync OTGSC and USBCFG registers\n");
-
- otgsc = readl(lnw->iotg.base + CI_OTGSC);
- usbcfg = readl(lnw->usbcfg);
-
- dev_dbg(lnw->dev, "OTGSC = %08x, USBCFG = %08x\n",
- otgsc, usbcfg);
- dev_dbg(lnw->dev, "OTGSC_AVV = %d\n", !!(otgsc & OTGSC_AVV));
- dev_dbg(lnw->dev, "USBCFG.VBUSVAL = %d\n",
- !!(usbcfg & USBCFG_VBUSVAL));
- dev_dbg(lnw->dev, "OTGSC_ASV = %d\n", !!(otgsc & OTGSC_ASV));
- dev_dbg(lnw->dev, "USBCFG.AVALID = %d\n",
- !!(usbcfg & USBCFG_AVALID));
- dev_dbg(lnw->dev, "OTGSC_BSV = %d\n", !!(otgsc & OTGSC_BSV));
- dev_dbg(lnw->dev, "USBCFG.BVALID = %d\n",
- !!(usbcfg & USBCFG_BVALID));
- dev_dbg(lnw->dev, "OTGSC_BSE = %d\n", !!(otgsc & OTGSC_BSE));
- dev_dbg(lnw->dev, "USBCFG.SESEND = %d\n",
- !!(usbcfg & USBCFG_SESEND));
-
- /* Check USBCFG VBusValid/AValid/BValid/SessEnd */
- if (!!(otgsc & OTGSC_AVV) ^ !!(usbcfg & USBCFG_VBUSVAL)) {
- dev_dbg(lnw->dev, "OTGSC.AVV != USBCFG.VBUSVAL\n");
- goto err;
- }
- if (!!(otgsc & OTGSC_ASV) ^ !!(usbcfg & USBCFG_AVALID)) {
- dev_dbg(lnw->dev, "OTGSC.ASV != USBCFG.AVALID\n");
- goto err;
- }
- if (!!(otgsc & OTGSC_BSV) ^ !!(usbcfg & USBCFG_BVALID)) {
- dev_dbg(lnw->dev, "OTGSC.BSV != USBCFG.BVALID\n");
- goto err;
- }
- if (!!(otgsc & OTGSC_BSE) ^ !!(usbcfg & USBCFG_SESEND)) {
- dev_dbg(lnw->dev, "OTGSC.BSE != USBCFG.SESSEN\n");
- goto err;
- }
-
- dev_dbg(lnw->dev, "OTGSC and USBCFG are synced\n");
-
- return 0;
-
-err:
- dev_warn(lnw->dev, "OTGSC isn't equal to USBCFG\n");
- return -EPIPE;
-}
-
-
-static void langwell_otg_phy_low_power(int on)
-{
- struct langwell_otg *lnw = the_transceiver;
- struct intel_mid_otg_xceiv *iotg = &lnw->iotg;
- u8 val, phcd;
- int retval;
-
- dev_dbg(lnw->dev, "%s ---> %s mode\n",
- __func__, on ? "Low power" : "Normal");
-
- phcd = 0x40;
-
- val = readb(iotg->base + CI_HOSTPC1 + 2);
-
- if (on) {
- /* Due to hardware issue, after set PHCD, sync will failed
- * between USBCFG and OTGSC, so before set PHCD, check if
- * sync is in process now. If the answer is "yes", then do
- * not touch PHCD bit */
- retval = langwell_otg_check_otgsc();
- if (retval) {
- dev_dbg(lnw->dev, "Skip PHCD programming..\n");
- return ;
- }
-
- writeb(val | phcd, iotg->base + CI_HOSTPC1 + 2);
- } else
- writeb(val & ~phcd, iotg->base + CI_HOSTPC1 + 2);
-
- dev_dbg(lnw->dev, "%s <--- done\n", __func__);
-}
-
-/* After drv vbus, add 5 ms delay to set PHCD */
-static void langwell_otg_phy_low_power_wait(int on)
-{
- struct langwell_otg *lnw = the_transceiver;
-
- dev_dbg(lnw->dev, "add 5ms delay before programing PHCD\n");
-
- mdelay(5);
- langwell_otg_phy_low_power(on);
-}
-
-/* Enable/Disable OTG interrupt */
-static void langwell_otg_intr(int on)
-{
- struct langwell_otg *lnw = the_transceiver;
- struct intel_mid_otg_xceiv *iotg = &lnw->iotg;
- u32 val;
-
- dev_dbg(lnw->dev, "%s ---> %s\n", __func__, on ? "on" : "off");
-
- val = readl(iotg->base + CI_OTGSC);
-
- /* OTGSC_INT_MASK doesn't contains 1msInt */
- if (on) {
- val = val | (OTGSC_INT_MASK);
- writel(val, iotg->base + CI_OTGSC);
- } else {
- val = val & ~(OTGSC_INT_MASK);
- writel(val, iotg->base + CI_OTGSC);
- }
-
- dev_dbg(lnw->dev, "%s <---\n", __func__);
-}
-
-/* set HAAR: Hardware Assist Auto-Reset */
-static void langwell_otg_HAAR(int on)
-{
- struct langwell_otg *lnw = the_transceiver;
- struct intel_mid_otg_xceiv *iotg = &lnw->iotg;
- u32 val;
-
- dev_dbg(lnw->dev, "%s ---> %s\n", __func__, on ? "on" : "off");
-
- val = readl(iotg->base + CI_OTGSC);
- if (on)
- writel((val & ~OTGSC_INTSTS_MASK) | OTGSC_HAAR,
- iotg->base + CI_OTGSC);
- else
- writel((val & ~OTGSC_INTSTS_MASK) & ~OTGSC_HAAR,
- iotg->base + CI_OTGSC);
-
- dev_dbg(lnw->dev, "%s <---\n", __func__);
-}
-
-/* set HABA: Hardware Assist B-Disconnect to A-Connect */
-static void langwell_otg_HABA(int on)
-{
- struct langwell_otg *lnw = the_transceiver;
- struct intel_mid_otg_xceiv *iotg = &lnw->iotg;
- u32 val;
-
- dev_dbg(lnw->dev, "%s ---> %s\n", __func__, on ? "on" : "off");
-
- val = readl(iotg->base + CI_OTGSC);
- if (on)
- writel((val & ~OTGSC_INTSTS_MASK) | OTGSC_HABA,
- iotg->base + CI_OTGSC);
- else
- writel((val & ~OTGSC_INTSTS_MASK) & ~OTGSC_HABA,
- iotg->base + CI_OTGSC);
-
- dev_dbg(lnw->dev, "%s <---\n", __func__);
-}
-
-static int langwell_otg_check_se0_srp(int on)
-{
- struct langwell_otg *lnw = the_transceiver;
- int delay_time = TB_SE0_SRP * 10;
- u32 val;
-
- dev_dbg(lnw->dev, "%s --->\n", __func__);
-
- do {
- udelay(100);
- if (!delay_time--)
- break;
- val = readl(lnw->iotg.base + CI_PORTSC1);
- val &= PORTSC_LS;
- } while (!val);
-
- dev_dbg(lnw->dev, "%s <---\n", __func__);
- return val;
-}
-
-/* The timeout callback function to set time out bit */
-static void set_tmout(unsigned long indicator)
-{
- *(int *)indicator = 1;
-}
-
-void langwell_otg_nsf_msg(unsigned long indicator)
-{
- struct langwell_otg *lnw = the_transceiver;
-
- switch (indicator) {
- case 2:
- case 4:
- case 6:
- case 7:
- dev_warn(lnw->dev,
- "OTG:NSF-%lu - deivce not responding\n", indicator);
- break;
- case 3:
- dev_warn(lnw->dev,
- "OTG:NSF-%lu - deivce not supported\n", indicator);
- break;
- default:
- dev_warn(lnw->dev, "Do not have this kind of NSF\n");
- break;
- }
-}
-
-/* Initialize timers */
-static int langwell_otg_init_timers(struct otg_hsm *hsm)
-{
- /* HSM used timers */
- a_wait_vrise_tmr = otg_timer_initializer(&set_tmout, TA_WAIT_VRISE,
- (unsigned long)&hsm->a_wait_vrise_tmout);
- if (a_wait_vrise_tmr == NULL)
- return -ENOMEM;
- a_aidl_bdis_tmr = otg_timer_initializer(&set_tmout, TA_AIDL_BDIS,
- (unsigned long)&hsm->a_aidl_bdis_tmout);
- if (a_aidl_bdis_tmr == NULL)
- return -ENOMEM;
- b_se0_srp_tmr = otg_timer_initializer(&set_tmout, TB_SE0_SRP,
- (unsigned long)&hsm->b_se0_srp);
- if (b_se0_srp_tmr == NULL)
- return -ENOMEM;
- b_srp_init_tmr = otg_timer_initializer(&set_tmout, TB_SRP_INIT,
- (unsigned long)&hsm->b_srp_init_tmout);
- if (b_srp_init_tmr == NULL)
- return -ENOMEM;
-
- return 0;
-}
-
-/* Free timers */
-static void langwell_otg_free_timers(void)
-{
- kfree(a_wait_vrise_tmr);
- kfree(a_aidl_bdis_tmr);
- kfree(b_se0_srp_tmr);
- kfree(b_srp_init_tmr);
-}
-
-/* The timeout callback function to set time out bit */
-static void langwell_otg_timer_fn(unsigned long indicator)
-{
- struct langwell_otg *lnw = the_transceiver;
-
- *(int *)indicator = 1;
-
- dev_dbg(lnw->dev, "kernel timer - timeout\n");
-
- langwell_update_transceiver();
-}
-
-/* kernel timer used instead of HW based interrupt */
-static void langwell_otg_add_ktimer(enum langwell_otg_timer_type timers)
-{
- struct langwell_otg *lnw = the_transceiver;
- struct intel_mid_otg_xceiv *iotg = &lnw->iotg;
- unsigned long j = jiffies;
- unsigned long data, time;
-
- switch (timers) {
- case TA_WAIT_VRISE_TMR:
- iotg->hsm.a_wait_vrise_tmout = 0;
- data = (unsigned long)&iotg->hsm.a_wait_vrise_tmout;
- time = TA_WAIT_VRISE;
- break;
- case TA_WAIT_BCON_TMR:
- iotg->hsm.a_wait_bcon_tmout = 0;
- data = (unsigned long)&iotg->hsm.a_wait_bcon_tmout;
- time = TA_WAIT_BCON;
- break;
- case TA_AIDL_BDIS_TMR:
- iotg->hsm.a_aidl_bdis_tmout = 0;
- data = (unsigned long)&iotg->hsm.a_aidl_bdis_tmout;
- time = TA_AIDL_BDIS;
- break;
- case TB_ASE0_BRST_TMR:
- iotg->hsm.b_ase0_brst_tmout = 0;
- data = (unsigned long)&iotg->hsm.b_ase0_brst_tmout;
- time = TB_ASE0_BRST;
- break;
- case TB_SRP_INIT_TMR:
- iotg->hsm.b_srp_init_tmout = 0;
- data = (unsigned long)&iotg->hsm.b_srp_init_tmout;
- time = TB_SRP_INIT;
- break;
- case TB_SRP_FAIL_TMR:
- iotg->hsm.b_srp_fail_tmout = 0;
- data = (unsigned long)&iotg->hsm.b_srp_fail_tmout;
- time = TB_SRP_FAIL;
- break;
- case TB_BUS_SUSPEND_TMR:
- iotg->hsm.b_bus_suspend_tmout = 0;
- data = (unsigned long)&iotg->hsm.b_bus_suspend_tmout;
- time = TB_BUS_SUSPEND;
- break;
- default:
- dev_dbg(lnw->dev, "unknown timer, cannot enable it\n");
- return;
- }
-
- lnw->hsm_timer.data = data;
- lnw->hsm_timer.function = langwell_otg_timer_fn;
- lnw->hsm_timer.expires = j + time * HZ / 1000; /* milliseconds */
-
- add_timer(&lnw->hsm_timer);
-
- dev_dbg(lnw->dev, "add timer successfully\n");
-}
-
-/* Add timer to timer list */
-static void langwell_otg_add_timer(void *gtimer)
-{
- struct langwell_otg_timer *timer = (struct langwell_otg_timer *)gtimer;
- struct langwell_otg_timer *tmp_timer;
- struct intel_mid_otg_xceiv *iotg = &the_transceiver->iotg;
- u32 val32;
-
- /* Check if the timer is already in the active list,
- * if so update timer count
- */
- list_for_each_entry(tmp_timer, &active_timers, list)
- if (tmp_timer == timer) {
- timer->count = timer->expires;
- return;
- }
- timer->count = timer->expires;
-
- if (list_empty(&active_timers)) {
- val32 = readl(iotg->base + CI_OTGSC);
- writel(val32 | OTGSC_1MSE, iotg->base + CI_OTGSC);
- }
-
- list_add_tail(&timer->list, &active_timers);
-}
-
-/* Remove timer from the timer list; clear timeout status */
-static void langwell_otg_del_timer(void *gtimer)
-{
- struct langwell_otg *lnw = the_transceiver;
- struct langwell_otg_timer *timer = (struct langwell_otg_timer *)gtimer;
- struct langwell_otg_timer *tmp_timer, *del_tmp;
- u32 val32;
-
- list_for_each_entry_safe(tmp_timer, del_tmp, &active_timers, list)
- if (tmp_timer == timer)
- list_del(&timer->list);
-
- if (list_empty(&active_timers)) {
- val32 = readl(lnw->iotg.base + CI_OTGSC);
- writel(val32 & ~OTGSC_1MSE, lnw->iotg.base + CI_OTGSC);
- }
-}
-
-/* Reduce timer count by 1, and find timeout conditions.*/
-static int langwell_otg_tick_timer(u32 *int_sts)
-{
- struct langwell_otg *lnw = the_transceiver;
- struct langwell_otg_timer *tmp_timer, *del_tmp;
- int expired = 0;
-
- list_for_each_entry_safe(tmp_timer, del_tmp, &active_timers, list) {
- tmp_timer->count--;
- /* check if timer expires */
- if (!tmp_timer->count) {
- list_del(&tmp_timer->list);
- tmp_timer->function(tmp_timer->data);
- expired = 1;
- }
- }
-
- if (list_empty(&active_timers)) {
- dev_dbg(lnw->dev, "tick timer: disable 1ms int\n");
- *int_sts = *int_sts & ~OTGSC_1MSE;
- }
- return expired;
-}
-
-static void reset_otg(void)
-{
- struct langwell_otg *lnw = the_transceiver;
- int delay_time = 1000;
- u32 val;
-
- dev_dbg(lnw->dev, "reseting OTG controller ...\n");
- val = readl(lnw->iotg.base + CI_USBCMD);
- writel(val | USBCMD_RST, lnw->iotg.base + CI_USBCMD);
- do {
- udelay(100);
- if (!delay_time--)
- dev_dbg(lnw->dev, "reset timeout\n");
- val = readl(lnw->iotg.base + CI_USBCMD);
- val &= USBCMD_RST;
- } while (val != 0);
- dev_dbg(lnw->dev, "reset done.\n");
-}
-
-static void set_host_mode(void)
-{
- struct langwell_otg *lnw = the_transceiver;
- u32 val;
-
- reset_otg();
- val = readl(lnw->iotg.base + CI_USBMODE);
- val = (val & (~USBMODE_CM)) | USBMODE_HOST;
- writel(val, lnw->iotg.base + CI_USBMODE);
-}
-
-static void set_client_mode(void)
-{
- struct langwell_otg *lnw = the_transceiver;
- u32 val;
-
- reset_otg();
- val = readl(lnw->iotg.base + CI_USBMODE);
- val = (val & (~USBMODE_CM)) | USBMODE_DEVICE;
- writel(val, lnw->iotg.base + CI_USBMODE);
-}
-
-static void init_hsm(void)
-{
- struct langwell_otg *lnw = the_transceiver;
- struct intel_mid_otg_xceiv *iotg = &lnw->iotg;
- u32 val32;
-
- /* read OTGSC after reset */
- val32 = readl(lnw->iotg.base + CI_OTGSC);
- dev_dbg(lnw->dev, "%s: OTGSC init value = 0x%x\n", __func__, val32);
-
- /* set init state */
- if (val32 & OTGSC_ID) {
- iotg->hsm.id = 1;
- iotg->otg.default_a = 0;
- set_client_mode();
- iotg->otg.state = OTG_STATE_B_IDLE;
- } else {
- iotg->hsm.id = 0;
- iotg->otg.default_a = 1;
- set_host_mode();
- iotg->otg.state = OTG_STATE_A_IDLE;
- }
-
- /* set session indicator */
- if (val32 & OTGSC_BSE)
- iotg->hsm.b_sess_end = 1;
- if (val32 & OTGSC_BSV)
- iotg->hsm.b_sess_vld = 1;
- if (val32 & OTGSC_ASV)
- iotg->hsm.a_sess_vld = 1;
- if (val32 & OTGSC_AVV)
- iotg->hsm.a_vbus_vld = 1;
-
- /* defautly power the bus */
- iotg->hsm.a_bus_req = 1;
- iotg->hsm.a_bus_drop = 0;
- /* defautly don't request bus as B device */
- iotg->hsm.b_bus_req = 0;
- /* no system error */
- iotg->hsm.a_clr_err = 0;
-
- langwell_otg_phy_low_power_wait(1);
-}
-
-static void update_hsm(void)
-{
- struct langwell_otg *lnw = the_transceiver;
- struct intel_mid_otg_xceiv *iotg = &lnw->iotg;
- u32 val32;
-
- /* read OTGSC */
- val32 = readl(lnw->iotg.base + CI_OTGSC);
- dev_dbg(lnw->dev, "%s: OTGSC value = 0x%x\n", __func__, val32);
-
- iotg->hsm.id = !!(val32 & OTGSC_ID);
- iotg->hsm.b_sess_end = !!(val32 & OTGSC_BSE);
- iotg->hsm.b_sess_vld = !!(val32 & OTGSC_BSV);
- iotg->hsm.a_sess_vld = !!(val32 & OTGSC_ASV);
- iotg->hsm.a_vbus_vld = !!(val32 & OTGSC_AVV);
-}
-
-static irqreturn_t otg_dummy_irq(int irq, void *_dev)
-{
- struct langwell_otg *lnw = the_transceiver;
- void __iomem *reg_base = _dev;
- u32 val;
- u32 int_mask = 0;
-
- val = readl(reg_base + CI_USBMODE);
- if ((val & USBMODE_CM) != USBMODE_DEVICE)
- return IRQ_NONE;
-
- val = readl(reg_base + CI_USBSTS);
- int_mask = val & INTR_DUMMY_MASK;
-
- if (int_mask == 0)
- return IRQ_NONE;
-
- /* clear hsm.b_conn here since host driver can't detect it
- * otg_dummy_irq called means B-disconnect happened.
- */
- if (lnw->iotg.hsm.b_conn) {
- lnw->iotg.hsm.b_conn = 0;
- if (spin_trylock(&lnw->wq_lock)) {
- langwell_update_transceiver();
- spin_unlock(&lnw->wq_lock);
- }
- }
-
- /* Clear interrupts */
- writel(int_mask, reg_base + CI_USBSTS);
- return IRQ_HANDLED;
-}
-
-static irqreturn_t otg_irq(int irq, void *_dev)
-{
- struct langwell_otg *lnw = _dev;
- struct intel_mid_otg_xceiv *iotg = &lnw->iotg;
- u32 int_sts, int_en;
- u32 int_mask = 0;
- int flag = 0;
-
- int_sts = readl(lnw->iotg.base + CI_OTGSC);
- int_en = (int_sts & OTGSC_INTEN_MASK) >> 8;
- int_mask = int_sts & int_en;
- if (int_mask == 0)
- return IRQ_NONE;
-
- if (int_mask & OTGSC_IDIS) {
- dev_dbg(lnw->dev, "%s: id change int\n", __func__);
- iotg->hsm.id = (int_sts & OTGSC_ID) ? 1 : 0;
- dev_dbg(lnw->dev, "id = %d\n", iotg->hsm.id);
- flag = 1;
- }
- if (int_mask & OTGSC_DPIS) {
- dev_dbg(lnw->dev, "%s: data pulse int\n", __func__);
- iotg->hsm.a_srp_det = (int_sts & OTGSC_DPS) ? 1 : 0;
- dev_dbg(lnw->dev, "data pulse = %d\n", iotg->hsm.a_srp_det);
- flag = 1;
- }
- if (int_mask & OTGSC_BSEIS) {
- dev_dbg(lnw->dev, "%s: b session end int\n", __func__);
- iotg->hsm.b_sess_end = (int_sts & OTGSC_BSE) ? 1 : 0;
- dev_dbg(lnw->dev, "b_sess_end = %d\n", iotg->hsm.b_sess_end);
- flag = 1;
- }
- if (int_mask & OTGSC_BSVIS) {
- dev_dbg(lnw->dev, "%s: b session valid int\n", __func__);
- iotg->hsm.b_sess_vld = (int_sts & OTGSC_BSV) ? 1 : 0;
- dev_dbg(lnw->dev, "b_sess_vld = %d\n", iotg->hsm.b_sess_end);
- flag = 1;
- }
- if (int_mask & OTGSC_ASVIS) {
- dev_dbg(lnw->dev, "%s: a session valid int\n", __func__);
- iotg->hsm.a_sess_vld = (int_sts & OTGSC_ASV) ? 1 : 0;
- dev_dbg(lnw->dev, "a_sess_vld = %d\n", iotg->hsm.a_sess_vld);
- flag = 1;
- }
- if (int_mask & OTGSC_AVVIS) {
- dev_dbg(lnw->dev, "%s: a vbus valid int\n", __func__);
- iotg->hsm.a_vbus_vld = (int_sts & OTGSC_AVV) ? 1 : 0;
- dev_dbg(lnw->dev, "a_vbus_vld = %d\n", iotg->hsm.a_vbus_vld);
- flag = 1;
- }
-
- if (int_mask & OTGSC_1MSS) {
- /* need to schedule otg_work if any timer is expired */
- if (langwell_otg_tick_timer(&int_sts))
- flag = 1;
- }
-
- writel((int_sts & ~OTGSC_INTSTS_MASK) | int_mask,
- lnw->iotg.base + CI_OTGSC);
- if (flag)
- langwell_update_transceiver();
-
- return IRQ_HANDLED;
-}
-
-static int langwell_otg_iotg_notify(struct notifier_block *nb,
- unsigned long action, void *data)
-{
- struct langwell_otg *lnw = the_transceiver;
- struct intel_mid_otg_xceiv *iotg = data;
- int flag = 0;
-
- if (iotg == NULL)
- return NOTIFY_BAD;
-
- if (lnw == NULL)
- return NOTIFY_BAD;
-
- switch (action) {
- case MID_OTG_NOTIFY_CONNECT:
- dev_dbg(lnw->dev, "Lnw OTG Notify Connect Event\n");
- if (iotg->otg.default_a == 1)
- iotg->hsm.b_conn = 1;
- else
- iotg->hsm.a_conn = 1;
- flag = 1;
- break;
- case MID_OTG_NOTIFY_DISCONN:
- dev_dbg(lnw->dev, "Lnw OTG Notify Disconnect Event\n");
- if (iotg->otg.default_a == 1)
- iotg->hsm.b_conn = 0;
- else
- iotg->hsm.a_conn = 0;
- flag = 1;
- break;
- case MID_OTG_NOTIFY_HSUSPEND:
- dev_dbg(lnw->dev, "Lnw OTG Notify Host Bus suspend Event\n");
- if (iotg->otg.default_a == 1)
- iotg->hsm.a_suspend_req = 1;
- else
- iotg->hsm.b_bus_req = 0;
- flag = 1;
- break;
- case MID_OTG_NOTIFY_HRESUME:
- dev_dbg(lnw->dev, "Lnw OTG Notify Host Bus resume Event\n");
- if (iotg->otg.default_a == 1)
- iotg->hsm.b_bus_resume = 1;
- flag = 1;
- break;
- case MID_OTG_NOTIFY_CSUSPEND:
- dev_dbg(lnw->dev, "Lnw OTG Notify Client Bus suspend Event\n");
- if (iotg->otg.default_a == 1) {
- if (iotg->hsm.b_bus_suspend_vld == 2) {
- iotg->hsm.b_bus_suspend = 1;
- iotg->hsm.b_bus_suspend_vld = 0;
- flag = 1;
- } else {
- iotg->hsm.b_bus_suspend_vld++;
- flag = 0;
- }
- } else {
- if (iotg->hsm.a_bus_suspend == 0) {
- iotg->hsm.a_bus_suspend = 1;
- flag = 1;
- }
- }
- break;
- case MID_OTG_NOTIFY_CRESUME:
- dev_dbg(lnw->dev, "Lnw OTG Notify Client Bus resume Event\n");
- if (iotg->otg.default_a == 0)
- iotg->hsm.a_bus_suspend = 0;
- flag = 0;
- break;
- case MID_OTG_NOTIFY_HOSTADD:
- dev_dbg(lnw->dev, "Lnw OTG Nofity Host Driver Add\n");
- flag = 1;
- break;
- case MID_OTG_NOTIFY_HOSTREMOVE:
- dev_dbg(lnw->dev, "Lnw OTG Nofity Host Driver remove\n");
- flag = 1;
- break;
- case MID_OTG_NOTIFY_CLIENTADD:
- dev_dbg(lnw->dev, "Lnw OTG Nofity Client Driver Add\n");
- flag = 1;
- break;
- case MID_OTG_NOTIFY_CLIENTREMOVE:
- dev_dbg(lnw->dev, "Lnw OTG Nofity Client Driver remove\n");
- flag = 1;
- break;
- default:
- dev_dbg(lnw->dev, "Lnw OTG Nofity unknown notify message\n");
- return NOTIFY_DONE;
- }
-
- if (flag)
- langwell_update_transceiver();
-
- return NOTIFY_OK;
-}
-
-static void langwell_otg_work(struct work_struct *work)
-{
- struct langwell_otg *lnw;
- struct intel_mid_otg_xceiv *iotg;
- int retval;
- struct pci_dev *pdev;
-
- lnw = container_of(work, struct langwell_otg, work);
- iotg = &lnw->iotg;
- pdev = to_pci_dev(lnw->dev);
-
- dev_dbg(lnw->dev, "%s: old state = %s\n", __func__,
- otg_state_string(iotg->otg.state));
-
- switch (iotg->otg.state) {
- case OTG_STATE_UNDEFINED:
- case OTG_STATE_B_IDLE:
- if (!iotg->hsm.id) {
- langwell_otg_del_timer(b_srp_init_tmr);
- del_timer_sync(&lnw->hsm_timer);
-
- iotg->otg.default_a = 1;
- iotg->hsm.a_srp_det = 0;
-
- langwell_otg_chrg_vbus(0);
- set_host_mode();
- langwell_otg_phy_low_power(1);
-
- iotg->otg.state = OTG_STATE_A_IDLE;
- langwell_update_transceiver();
- } else if (iotg->hsm.b_sess_vld) {
- langwell_otg_del_timer(b_srp_init_tmr);
- del_timer_sync(&lnw->hsm_timer);
- iotg->hsm.b_sess_end = 0;
- iotg->hsm.a_bus_suspend = 0;
- langwell_otg_chrg_vbus(0);
-
- if (lnw->iotg.start_peripheral) {
- lnw->iotg.start_peripheral(&lnw->iotg);
- iotg->otg.state = OTG_STATE_B_PERIPHERAL;
- } else
- dev_dbg(lnw->dev, "client driver not loaded\n");
-
- } else if (iotg->hsm.b_srp_init_tmout) {
- iotg->hsm.b_srp_init_tmout = 0;
- dev_warn(lnw->dev, "SRP init timeout\n");
- } else if (iotg->hsm.b_srp_fail_tmout) {
- iotg->hsm.b_srp_fail_tmout = 0;
- iotg->hsm.b_bus_req = 0;
-
- /* No silence failure */
- langwell_otg_nsf_msg(6);
- } else if (iotg->hsm.b_bus_req && iotg->hsm.b_sess_end) {
- del_timer_sync(&lnw->hsm_timer);
- /* workaround for b_se0_srp detection */
- retval = langwell_otg_check_se0_srp(0);
- if (retval) {
- iotg->hsm.b_bus_req = 0;
- dev_dbg(lnw->dev, "LS isn't SE0, try later\n");
- } else {
- /* clear the PHCD before start srp */
- langwell_otg_phy_low_power(0);
-
- /* Start SRP */
- langwell_otg_add_timer(b_srp_init_tmr);
- iotg->otg.start_srp(&iotg->otg);
- langwell_otg_del_timer(b_srp_init_tmr);
- langwell_otg_add_ktimer(TB_SRP_FAIL_TMR);
-
- /* reset PHY low power mode here */
- langwell_otg_phy_low_power_wait(1);
- }
- }
- break;
- case OTG_STATE_B_SRP_INIT:
- if (!iotg->hsm.id) {
- iotg->otg.default_a = 1;
- iotg->hsm.a_srp_det = 0;
-
- /* Turn off VBus */
- iotg->otg.set_vbus(&iotg->otg, false);
- langwell_otg_chrg_vbus(0);
- set_host_mode();
- langwell_otg_phy_low_power(1);
- iotg->otg.state = OTG_STATE_A_IDLE;
- langwell_update_transceiver();
- } else if (iotg->hsm.b_sess_vld) {
- langwell_otg_chrg_vbus(0);
- if (lnw->iotg.start_peripheral) {
- lnw->iotg.start_peripheral(&lnw->iotg);
- iotg->otg.state = OTG_STATE_B_PERIPHERAL;
- } else
- dev_dbg(lnw->dev, "client driver not loaded\n");
- }
- break;
- case OTG_STATE_B_PERIPHERAL:
- if (!iotg->hsm.id) {
- iotg->otg.default_a = 1;
- iotg->hsm.a_srp_det = 0;
-
- langwell_otg_chrg_vbus(0);
-
- if (lnw->iotg.stop_peripheral)
- lnw->iotg.stop_peripheral(&lnw->iotg);
- else
- dev_dbg(lnw->dev,
- "client driver has been removed.\n");
-
- set_host_mode();
- langwell_otg_phy_low_power(1);
- iotg->otg.state = OTG_STATE_A_IDLE;
- langwell_update_transceiver();
- } else if (!iotg->hsm.b_sess_vld) {
- iotg->hsm.b_hnp_enable = 0;
-
- if (lnw->iotg.stop_peripheral)
- lnw->iotg.stop_peripheral(&lnw->iotg);
- else
- dev_dbg(lnw->dev,
- "client driver has been removed.\n");
-
- iotg->otg.state = OTG_STATE_B_IDLE;
- } else if (iotg->hsm.b_bus_req && iotg->otg.gadget &&
- iotg->otg.gadget->b_hnp_enable &&
- iotg->hsm.a_bus_suspend) {
-
- if (lnw->iotg.stop_peripheral)
- lnw->iotg.stop_peripheral(&lnw->iotg);
- else
- dev_dbg(lnw->dev,
- "client driver has been removed.\n");
-
- langwell_otg_HAAR(1);
- iotg->hsm.a_conn = 0;
-
- if (lnw->iotg.start_host) {
- lnw->iotg.start_host(&lnw->iotg);
- iotg->otg.state = OTG_STATE_B_WAIT_ACON;
- } else
- dev_dbg(lnw->dev,
- "host driver not loaded.\n");
-
- iotg->hsm.a_bus_resume = 0;
- langwell_otg_add_ktimer(TB_ASE0_BRST_TMR);
- }
- break;
-
- case OTG_STATE_B_WAIT_ACON:
- if (!iotg->hsm.id) {
- /* delete hsm timer for b_ase0_brst_tmr */
- del_timer_sync(&lnw->hsm_timer);
-
- iotg->otg.default_a = 1;
- iotg->hsm.a_srp_det = 0;
-
- langwell_otg_chrg_vbus(0);
-
- langwell_otg_HAAR(0);
- if (lnw->iotg.stop_host)
- lnw->iotg.stop_host(&lnw->iotg);
- else
- dev_dbg(lnw->dev,
- "host driver has been removed.\n");
-
- set_host_mode();
- langwell_otg_phy_low_power(1);
- iotg->otg.state = OTG_STATE_A_IDLE;
- langwell_update_transceiver();
- } else if (!iotg->hsm.b_sess_vld) {
- /* delete hsm timer for b_ase0_brst_tmr */
- del_timer_sync(&lnw->hsm_timer);
-
- iotg->hsm.b_hnp_enable = 0;
- iotg->hsm.b_bus_req = 0;
-
- langwell_otg_chrg_vbus(0);
- langwell_otg_HAAR(0);
-
- if (lnw->iotg.stop_host)
- lnw->iotg.stop_host(&lnw->iotg);
- else
- dev_dbg(lnw->dev,
- "host driver has been removed.\n");
-
- set_client_mode();
- langwell_otg_phy_low_power(1);
- iotg->otg.state = OTG_STATE_B_IDLE;
- } else if (iotg->hsm.a_conn) {
- /* delete hsm timer for b_ase0_brst_tmr */
- del_timer_sync(&lnw->hsm_timer);
-
- langwell_otg_HAAR(0);
- iotg->otg.state = OTG_STATE_B_HOST;
- langwell_update_transceiver();
- } else if (iotg->hsm.a_bus_resume ||
- iotg->hsm.b_ase0_brst_tmout) {
- /* delete hsm timer for b_ase0_brst_tmr */
- del_timer_sync(&lnw->hsm_timer);
-
- langwell_otg_HAAR(0);
- langwell_otg_nsf_msg(7);
-
- if (lnw->iotg.stop_host)
- lnw->iotg.stop_host(&lnw->iotg);
- else
- dev_dbg(lnw->dev,
- "host driver has been removed.\n");
-
- iotg->hsm.a_bus_suspend = 0;
- iotg->hsm.b_bus_req = 0;
-
- if (lnw->iotg.start_peripheral)
- lnw->iotg.start_peripheral(&lnw->iotg);
- else
- dev_dbg(lnw->dev,
- "client driver not loaded.\n");
-
- iotg->otg.state = OTG_STATE_B_PERIPHERAL;
- }
- break;
-
- case OTG_STATE_B_HOST:
- if (!iotg->hsm.id) {
- iotg->otg.default_a = 1;
- iotg->hsm.a_srp_det = 0;
-
- langwell_otg_chrg_vbus(0);
-
- if (lnw->iotg.stop_host)
- lnw->iotg.stop_host(&lnw->iotg);
- else
- dev_dbg(lnw->dev,
- "host driver has been removed.\n");
-
- set_host_mode();
- langwell_otg_phy_low_power(1);
- iotg->otg.state = OTG_STATE_A_IDLE;
- langwell_update_transceiver();
- } else if (!iotg->hsm.b_sess_vld) {
- iotg->hsm.b_hnp_enable = 0;
- iotg->hsm.b_bus_req = 0;
-
- langwell_otg_chrg_vbus(0);
- if (lnw->iotg.stop_host)
- lnw->iotg.stop_host(&lnw->iotg);
- else
- dev_dbg(lnw->dev,
- "host driver has been removed.\n");
-
- set_client_mode();
- langwell_otg_phy_low_power(1);
- iotg->otg.state = OTG_STATE_B_IDLE;
- } else if ((!iotg->hsm.b_bus_req) ||
- (!iotg->hsm.a_conn)) {
- iotg->hsm.b_bus_req = 0;
- langwell_otg_loc_sof(0);
-
- if (lnw->iotg.stop_host)
- lnw->iotg.stop_host(&lnw->iotg);
- else
- dev_dbg(lnw->dev,
- "host driver has been removed.\n");
-
- iotg->hsm.a_bus_suspend = 0;
-
- if (lnw->iotg.start_peripheral)
- lnw->iotg.start_peripheral(&lnw->iotg);
- else
- dev_dbg(lnw->dev,
- "client driver not loaded.\n");
-
- iotg->otg.state = OTG_STATE_B_PERIPHERAL;
- }
- break;
-
- case OTG_STATE_A_IDLE:
- iotg->otg.default_a = 1;
- if (iotg->hsm.id) {
- iotg->otg.default_a = 0;
- iotg->hsm.b_bus_req = 0;
- iotg->hsm.vbus_srp_up = 0;
-
- langwell_otg_chrg_vbus(0);
- set_client_mode();
- langwell_otg_phy_low_power(1);
- iotg->otg.state = OTG_STATE_B_IDLE;
- langwell_update_transceiver();
- } else if (!iotg->hsm.a_bus_drop &&
- (iotg->hsm.a_srp_det || iotg->hsm.a_bus_req)) {
- langwell_otg_phy_low_power(0);
-
- /* Turn on VBus */
- iotg->otg.set_vbus(&iotg->otg, true);
-
- iotg->hsm.vbus_srp_up = 0;
- iotg->hsm.a_wait_vrise_tmout = 0;
- langwell_otg_add_timer(a_wait_vrise_tmr);
- iotg->otg.state = OTG_STATE_A_WAIT_VRISE;
- langwell_update_transceiver();
- } else if (!iotg->hsm.a_bus_drop && iotg->hsm.a_sess_vld) {
- iotg->hsm.vbus_srp_up = 1;
- } else if (!iotg->hsm.a_sess_vld && iotg->hsm.vbus_srp_up) {
- msleep(10);
- langwell_otg_phy_low_power(0);
-
- /* Turn on VBus */
- iotg->otg.set_vbus(&iotg->otg, true);
- iotg->hsm.a_srp_det = 1;
- iotg->hsm.vbus_srp_up = 0;
- iotg->hsm.a_wait_vrise_tmout = 0;
- langwell_otg_add_timer(a_wait_vrise_tmr);
- iotg->otg.state = OTG_STATE_A_WAIT_VRISE;
- langwell_update_transceiver();
- } else if (!iotg->hsm.a_sess_vld &&
- !iotg->hsm.vbus_srp_up) {
- langwell_otg_phy_low_power(1);
- }
- break;
- case OTG_STATE_A_WAIT_VRISE:
- if (iotg->hsm.id) {
- langwell_otg_del_timer(a_wait_vrise_tmr);
- iotg->hsm.b_bus_req = 0;
- iotg->otg.default_a = 0;
-
- /* Turn off VBus */
- iotg->otg.set_vbus(&iotg->otg, false);
- set_client_mode();
- langwell_otg_phy_low_power_wait(1);
- iotg->otg.state = OTG_STATE_B_IDLE;
- } else if (iotg->hsm.a_vbus_vld) {
- langwell_otg_del_timer(a_wait_vrise_tmr);
- iotg->hsm.b_conn = 0;
- if (lnw->iotg.start_host)
- lnw->iotg.start_host(&lnw->iotg);
- else {
- dev_dbg(lnw->dev, "host driver not loaded.\n");
- break;
- }
-
- langwell_otg_add_ktimer(TA_WAIT_BCON_TMR);
- iotg->otg.state = OTG_STATE_A_WAIT_BCON;
- } else if (iotg->hsm.a_wait_vrise_tmout) {
- iotg->hsm.b_conn = 0;
- if (iotg->hsm.a_vbus_vld) {
- if (lnw->iotg.start_host)
- lnw->iotg.start_host(&lnw->iotg);
- else {
- dev_dbg(lnw->dev,
- "host driver not loaded.\n");
- break;
- }
- langwell_otg_add_ktimer(TA_WAIT_BCON_TMR);
- iotg->otg.state = OTG_STATE_A_WAIT_BCON;
- } else {
-
- /* Turn off VBus */
- iotg->otg.set_vbus(&iotg->otg, false);
- langwell_otg_phy_low_power_wait(1);
- iotg->otg.state = OTG_STATE_A_VBUS_ERR;
- }
- }
- break;
- case OTG_STATE_A_WAIT_BCON:
- if (iotg->hsm.id) {
- /* delete hsm timer for a_wait_bcon_tmr */
- del_timer_sync(&lnw->hsm_timer);
-
- iotg->otg.default_a = 0;
- iotg->hsm.b_bus_req = 0;
-
- if (lnw->iotg.stop_host)
- lnw->iotg.stop_host(&lnw->iotg);
- else
- dev_dbg(lnw->dev,
- "host driver has been removed.\n");
-
- /* Turn off VBus */
- iotg->otg.set_vbus(&iotg->otg, false);
- set_client_mode();
- langwell_otg_phy_low_power_wait(1);
- iotg->otg.state = OTG_STATE_B_IDLE;
- langwell_update_transceiver();
- } else if (!iotg->hsm.a_vbus_vld) {
- /* delete hsm timer for a_wait_bcon_tmr */
- del_timer_sync(&lnw->hsm_timer);
-
- if (lnw->iotg.stop_host)
- lnw->iotg.stop_host(&lnw->iotg);
- else
- dev_dbg(lnw->dev,
- "host driver has been removed.\n");
-
- /* Turn off VBus */
- iotg->otg.set_vbus(&iotg->otg, false);
- langwell_otg_phy_low_power_wait(1);
- iotg->otg.state = OTG_STATE_A_VBUS_ERR;
- } else if (iotg->hsm.a_bus_drop ||
- (iotg->hsm.a_wait_bcon_tmout &&
- !iotg->hsm.a_bus_req)) {
- /* delete hsm timer for a_wait_bcon_tmr */
- del_timer_sync(&lnw->hsm_timer);
-
- if (lnw->iotg.stop_host)
- lnw->iotg.stop_host(&lnw->iotg);
- else
- dev_dbg(lnw->dev,
- "host driver has been removed.\n");
-
- /* Turn off VBus */
- iotg->otg.set_vbus(&iotg->otg, false);
- iotg->otg.state = OTG_STATE_A_WAIT_VFALL;
- } else if (iotg->hsm.b_conn) {
- /* delete hsm timer for a_wait_bcon_tmr */
- del_timer_sync(&lnw->hsm_timer);
-
- iotg->hsm.a_suspend_req = 0;
- iotg->otg.state = OTG_STATE_A_HOST;
- if (iotg->hsm.a_srp_det && iotg->otg.host &&
- !iotg->otg.host->b_hnp_enable) {
- /* SRP capable peripheral-only device */
- iotg->hsm.a_bus_req = 1;
- iotg->hsm.a_srp_det = 0;
- } else if (!iotg->hsm.a_bus_req && iotg->otg.host &&
- iotg->otg.host->b_hnp_enable) {
- /* It is not safe enough to do a fast
- * transition from A_WAIT_BCON to
- * A_SUSPEND */
- msleep(10000);
- if (iotg->hsm.a_bus_req)
- break;
-
- if (request_irq(pdev->irq,
- otg_dummy_irq, IRQF_SHARED,
- driver_name, iotg->base) != 0) {
- dev_dbg(lnw->dev,
- "request interrupt %d fail\n",
- pdev->irq);
- }
-
- langwell_otg_HABA(1);
- iotg->hsm.b_bus_resume = 0;
- iotg->hsm.a_aidl_bdis_tmout = 0;
-
- langwell_otg_loc_sof(0);
- /* clear PHCD to enable HW timer */
- langwell_otg_phy_low_power(0);
- langwell_otg_add_timer(a_aidl_bdis_tmr);
- iotg->otg.state = OTG_STATE_A_SUSPEND;
- } else if (!iotg->hsm.a_bus_req && iotg->otg.host &&
- !iotg->otg.host->b_hnp_enable) {
- if (lnw->iotg.stop_host)
- lnw->iotg.stop_host(&lnw->iotg);
- else
- dev_dbg(lnw->dev,
- "host driver removed.\n");
-
- /* Turn off VBus */
- iotg->otg.set_vbus(&iotg->otg, false);
- iotg->otg.state = OTG_STATE_A_WAIT_VFALL;
- }
- }
- break;
- case OTG_STATE_A_HOST:
- if (iotg->hsm.id) {
- iotg->otg.default_a = 0;
- iotg->hsm.b_bus_req = 0;
-
- if (lnw->iotg.stop_host)
- lnw->iotg.stop_host(&lnw->iotg);
- else
- dev_dbg(lnw->dev,
- "host driver has been removed.\n");
-
- /* Turn off VBus */
- iotg->otg.set_vbus(&iotg->otg, false);
- set_client_mode();
- langwell_otg_phy_low_power_wait(1);
- iotg->otg.state = OTG_STATE_B_IDLE;
- langwell_update_transceiver();
- } else if (iotg->hsm.a_bus_drop ||
- (iotg->otg.host &&
- !iotg->otg.host->b_hnp_enable &&
- !iotg->hsm.a_bus_req)) {
- if (lnw->iotg.stop_host)
- lnw->iotg.stop_host(&lnw->iotg);
- else
- dev_dbg(lnw->dev,
- "host driver has been removed.\n");
-
- /* Turn off VBus */
- iotg->otg.set_vbus(&iotg->otg, false);
- iotg->otg.state = OTG_STATE_A_WAIT_VFALL;
- } else if (!iotg->hsm.a_vbus_vld) {
- if (lnw->iotg.stop_host)
- lnw->iotg.stop_host(&lnw->iotg);
- else
- dev_dbg(lnw->dev,
- "host driver has been removed.\n");
-
- /* Turn off VBus */
- iotg->otg.set_vbus(&iotg->otg, false);
- langwell_otg_phy_low_power_wait(1);
- iotg->otg.state = OTG_STATE_A_VBUS_ERR;
- } else if (iotg->otg.host &&
- iotg->otg.host->b_hnp_enable &&
- !iotg->hsm.a_bus_req) {
- /* Set HABA to enable hardware assistance to signal
- * A-connect after receiver B-disconnect. Hardware
- * will then set client mode and enable URE, SLE and
- * PCE after the assistance. otg_dummy_irq is used to
- * clean these ints when client driver is not resumed.
- */
- if (request_irq(pdev->irq, otg_dummy_irq, IRQF_SHARED,
- driver_name, iotg->base) != 0) {
- dev_dbg(lnw->dev,
- "request interrupt %d failed\n",
- pdev->irq);
- }
-
- /* set HABA */
- langwell_otg_HABA(1);
- iotg->hsm.b_bus_resume = 0;
- iotg->hsm.a_aidl_bdis_tmout = 0;
- langwell_otg_loc_sof(0);
- /* clear PHCD to enable HW timer */
- langwell_otg_phy_low_power(0);
- langwell_otg_add_timer(a_aidl_bdis_tmr);
- iotg->otg.state = OTG_STATE_A_SUSPEND;
- } else if (!iotg->hsm.b_conn || !iotg->hsm.a_bus_req) {
- langwell_otg_add_ktimer(TA_WAIT_BCON_TMR);
- iotg->otg.state = OTG_STATE_A_WAIT_BCON;
- }
- break;
- case OTG_STATE_A_SUSPEND:
- if (iotg->hsm.id) {
- langwell_otg_del_timer(a_aidl_bdis_tmr);
- langwell_otg_HABA(0);
- free_irq(pdev->irq, iotg->base);
- iotg->otg.default_a = 0;
- iotg->hsm.b_bus_req = 0;
-
- if (lnw->iotg.stop_host)
- lnw->iotg.stop_host(&lnw->iotg);
- else
- dev_dbg(lnw->dev,
- "host driver has been removed.\n");
-
- /* Turn off VBus */
- iotg->otg.set_vbus(&iotg->otg, false);
- set_client_mode();
- langwell_otg_phy_low_power(1);
- iotg->otg.state = OTG_STATE_B_IDLE;
- langwell_update_transceiver();
- } else if (iotg->hsm.a_bus_req ||
- iotg->hsm.b_bus_resume) {
- langwell_otg_del_timer(a_aidl_bdis_tmr);
- langwell_otg_HABA(0);
- free_irq(pdev->irq, iotg->base);
- iotg->hsm.a_suspend_req = 0;
- langwell_otg_loc_sof(1);
- iotg->otg.state = OTG_STATE_A_HOST;
- } else if (iotg->hsm.a_aidl_bdis_tmout ||
- iotg->hsm.a_bus_drop) {
- langwell_otg_del_timer(a_aidl_bdis_tmr);
- langwell_otg_HABA(0);
- free_irq(pdev->irq, iotg->base);
- if (lnw->iotg.stop_host)
- lnw->iotg.stop_host(&lnw->iotg);
- else
- dev_dbg(lnw->dev,
- "host driver has been removed.\n");
-
- /* Turn off VBus */
- iotg->otg.set_vbus(&iotg->otg, false);
- iotg->otg.state = OTG_STATE_A_WAIT_VFALL;
- } else if (!iotg->hsm.b_conn && iotg->otg.host &&
- iotg->otg.host->b_hnp_enable) {
- langwell_otg_del_timer(a_aidl_bdis_tmr);
- langwell_otg_HABA(0);
- free_irq(pdev->irq, iotg->base);
-
- if (lnw->iotg.stop_host)
- lnw->iotg.stop_host(&lnw->iotg);
- else
- dev_dbg(lnw->dev,
- "host driver has been removed.\n");
-
- iotg->hsm.b_bus_suspend = 0;
- iotg->hsm.b_bus_suspend_vld = 0;
-
- /* msleep(200); */
- if (lnw->iotg.start_peripheral)
- lnw->iotg.start_peripheral(&lnw->iotg);
- else
- dev_dbg(lnw->dev,
- "client driver not loaded.\n");
-
- langwell_otg_add_ktimer(TB_BUS_SUSPEND_TMR);
- iotg->otg.state = OTG_STATE_A_PERIPHERAL;
- break;
- } else if (!iotg->hsm.a_vbus_vld) {
- langwell_otg_del_timer(a_aidl_bdis_tmr);
- langwell_otg_HABA(0);
- free_irq(pdev->irq, iotg->base);
- if (lnw->iotg.stop_host)
- lnw->iotg.stop_host(&lnw->iotg);
- else
- dev_dbg(lnw->dev,
- "host driver has been removed.\n");
-
- /* Turn off VBus */
- iotg->otg.set_vbus(&iotg->otg, false);
- langwell_otg_phy_low_power_wait(1);
- iotg->otg.state = OTG_STATE_A_VBUS_ERR;
- }
- break;
- case OTG_STATE_A_PERIPHERAL:
- if (iotg->hsm.id) {
- /* delete hsm timer for b_bus_suspend_tmr */
- del_timer_sync(&lnw->hsm_timer);
- iotg->otg.default_a = 0;
- iotg->hsm.b_bus_req = 0;
- if (lnw->iotg.stop_peripheral)
- lnw->iotg.stop_peripheral(&lnw->iotg);
- else
- dev_dbg(lnw->dev,
- "client driver has been removed.\n");
-
- /* Turn off VBus */
- iotg->otg.set_vbus(&iotg->otg, false);
- set_client_mode();
- langwell_otg_phy_low_power_wait(1);
- iotg->otg.state = OTG_STATE_B_IDLE;
- langwell_update_transceiver();
- } else if (!iotg->hsm.a_vbus_vld) {
- /* delete hsm timer for b_bus_suspend_tmr */
- del_timer_sync(&lnw->hsm_timer);
-
- if (lnw->iotg.stop_peripheral)
- lnw->iotg.stop_peripheral(&lnw->iotg);
- else
- dev_dbg(lnw->dev,
- "client driver has been removed.\n");
-
- /* Turn off VBus */
- iotg->otg.set_vbus(&iotg->otg, false);
- langwell_otg_phy_low_power_wait(1);
- iotg->otg.state = OTG_STATE_A_VBUS_ERR;
- } else if (iotg->hsm.a_bus_drop) {
- /* delete hsm timer for b_bus_suspend_tmr */
- del_timer_sync(&lnw->hsm_timer);
-
- if (lnw->iotg.stop_peripheral)
- lnw->iotg.stop_peripheral(&lnw->iotg);
- else
- dev_dbg(lnw->dev,
- "client driver has been removed.\n");
-
- /* Turn off VBus */
- iotg->otg.set_vbus(&iotg->otg, false);
- iotg->otg.state = OTG_STATE_A_WAIT_VFALL;
- } else if (iotg->hsm.b_bus_suspend) {
- /* delete hsm timer for b_bus_suspend_tmr */
- del_timer_sync(&lnw->hsm_timer);
-
- if (lnw->iotg.stop_peripheral)
- lnw->iotg.stop_peripheral(&lnw->iotg);
- else
- dev_dbg(lnw->dev,
- "client driver has been removed.\n");
-
- if (lnw->iotg.start_host)
- lnw->iotg.start_host(&lnw->iotg);
- else
- dev_dbg(lnw->dev,
- "host driver not loaded.\n");
- langwell_otg_add_ktimer(TA_WAIT_BCON_TMR);
- iotg->otg.state = OTG_STATE_A_WAIT_BCON;
- } else if (iotg->hsm.b_bus_suspend_tmout) {
- u32 val;
- val = readl(lnw->iotg.base + CI_PORTSC1);
- if (!(val & PORTSC_SUSP))
- break;
-
- if (lnw->iotg.stop_peripheral)
- lnw->iotg.stop_peripheral(&lnw->iotg);
- else
- dev_dbg(lnw->dev,
- "client driver has been removed.\n");
-
- if (lnw->iotg.start_host)
- lnw->iotg.start_host(&lnw->iotg);
- else
- dev_dbg(lnw->dev,
- "host driver not loaded.\n");
- langwell_otg_add_ktimer(TA_WAIT_BCON_TMR);
- iotg->otg.state = OTG_STATE_A_WAIT_BCON;
- }
- break;
- case OTG_STATE_A_VBUS_ERR:
- if (iotg->hsm.id) {
- iotg->otg.default_a = 0;
- iotg->hsm.a_clr_err = 0;
- iotg->hsm.a_srp_det = 0;
- set_client_mode();
- langwell_otg_phy_low_power(1);
- iotg->otg.state = OTG_STATE_B_IDLE;
- langwell_update_transceiver();
- } else if (iotg->hsm.a_clr_err) {
- iotg->hsm.a_clr_err = 0;
- iotg->hsm.a_srp_det = 0;
- reset_otg();
- init_hsm();
- if (iotg->otg.state == OTG_STATE_A_IDLE)
- langwell_update_transceiver();
- } else {
- /* FW will clear PHCD bit when any VBus
- * event detected. Reset PHCD to 1 again */
- langwell_otg_phy_low_power(1);
- }
- break;
- case OTG_STATE_A_WAIT_VFALL:
- if (iotg->hsm.id) {
- iotg->otg.default_a = 0;
- set_client_mode();
- langwell_otg_phy_low_power(1);
- iotg->otg.state = OTG_STATE_B_IDLE;
- langwell_update_transceiver();
- } else if (iotg->hsm.a_bus_req) {
-
- /* Turn on VBus */
- iotg->otg.set_vbus(&iotg->otg, true);
- iotg->hsm.a_wait_vrise_tmout = 0;
- langwell_otg_add_timer(a_wait_vrise_tmr);
- iotg->otg.state = OTG_STATE_A_WAIT_VRISE;
- } else if (!iotg->hsm.a_sess_vld) {
- iotg->hsm.a_srp_det = 0;
- set_host_mode();
- langwell_otg_phy_low_power(1);
- iotg->otg.state = OTG_STATE_A_IDLE;
- }
- break;
- default:
- ;
- }
-
- dev_dbg(lnw->dev, "%s: new state = %s\n", __func__,
- otg_state_string(iotg->otg.state));
-}
-
-static ssize_t
-show_registers(struct device *_dev, struct device_attribute *attr, char *buf)
-{
- struct langwell_otg *lnw = the_transceiver;
- char *next;
- unsigned size, t;
-
- next = buf;
- size = PAGE_SIZE;
-
- t = scnprintf(next, size,
- "\n"
- "USBCMD = 0x%08x\n"
- "USBSTS = 0x%08x\n"
- "USBINTR = 0x%08x\n"
- "ASYNCLISTADDR = 0x%08x\n"
- "PORTSC1 = 0x%08x\n"
- "HOSTPC1 = 0x%08x\n"
- "OTGSC = 0x%08x\n"
- "USBMODE = 0x%08x\n",
- readl(lnw->iotg.base + 0x30),
- readl(lnw->iotg.base + 0x34),
- readl(lnw->iotg.base + 0x38),
- readl(lnw->iotg.base + 0x48),
- readl(lnw->iotg.base + 0x74),
- readl(lnw->iotg.base + 0xb4),
- readl(lnw->iotg.base + 0xf4),
- readl(lnw->iotg.base + 0xf8)
- );
- size -= t;
- next += t;
-
- return PAGE_SIZE - size;
-}
-static DEVICE_ATTR(registers, S_IRUGO, show_registers, NULL);
-
-static ssize_t
-show_hsm(struct device *_dev, struct device_attribute *attr, char *buf)
-{
- struct langwell_otg *lnw = the_transceiver;
- struct intel_mid_otg_xceiv *iotg = &lnw->iotg;
- char *next;
- unsigned size, t;
-
- next = buf;
- size = PAGE_SIZE;
-
- if (iotg->otg.host)
- iotg->hsm.a_set_b_hnp_en = iotg->otg.host->b_hnp_enable;
-
- if (iotg->otg.gadget)
- iotg->hsm.b_hnp_enable = iotg->otg.gadget->b_hnp_enable;
-
- t = scnprintf(next, size,
- "\n"
- "current state = %s\n"
- "a_bus_resume = \t%d\n"
- "a_bus_suspend = \t%d\n"
- "a_conn = \t%d\n"
- "a_sess_vld = \t%d\n"
- "a_srp_det = \t%d\n"
- "a_vbus_vld = \t%d\n"
- "b_bus_resume = \t%d\n"
- "b_bus_suspend = \t%d\n"
- "b_conn = \t%d\n"
- "b_se0_srp = \t%d\n"
- "b_sess_end = \t%d\n"
- "b_sess_vld = \t%d\n"
- "id = \t%d\n"
- "a_set_b_hnp_en = \t%d\n"
- "b_srp_done = \t%d\n"
- "b_hnp_enable = \t%d\n"
- "a_wait_vrise_tmout = \t%d\n"
- "a_wait_bcon_tmout = \t%d\n"
- "a_aidl_bdis_tmout = \t%d\n"
- "b_ase0_brst_tmout = \t%d\n"
- "a_bus_drop = \t%d\n"
- "a_bus_req = \t%d\n"
- "a_clr_err = \t%d\n"
- "a_suspend_req = \t%d\n"
- "b_bus_req = \t%d\n"
- "b_bus_suspend_tmout = \t%d\n"
- "b_bus_suspend_vld = \t%d\n",
- otg_state_string(iotg->otg.state),
- iotg->hsm.a_bus_resume,
- iotg->hsm.a_bus_suspend,
- iotg->hsm.a_conn,
- iotg->hsm.a_sess_vld,
- iotg->hsm.a_srp_det,
- iotg->hsm.a_vbus_vld,
- iotg->hsm.b_bus_resume,
- iotg->hsm.b_bus_suspend,
- iotg->hsm.b_conn,
- iotg->hsm.b_se0_srp,
- iotg->hsm.b_sess_end,
- iotg->hsm.b_sess_vld,
- iotg->hsm.id,
- iotg->hsm.a_set_b_hnp_en,
- iotg->hsm.b_srp_done,
- iotg->hsm.b_hnp_enable,
- iotg->hsm.a_wait_vrise_tmout,
- iotg->hsm.a_wait_bcon_tmout,
- iotg->hsm.a_aidl_bdis_tmout,
- iotg->hsm.b_ase0_brst_tmout,
- iotg->hsm.a_bus_drop,
- iotg->hsm.a_bus_req,
- iotg->hsm.a_clr_err,
- iotg->hsm.a_suspend_req,
- iotg->hsm.b_bus_req,
- iotg->hsm.b_bus_suspend_tmout,
- iotg->hsm.b_bus_suspend_vld
- );
- size -= t;
- next += t;
-
- return PAGE_SIZE - size;
-}
-static DEVICE_ATTR(hsm, S_IRUGO, show_hsm, NULL);
-
-static ssize_t
-get_a_bus_req(struct device *dev, struct device_attribute *attr, char *buf)
-{
- struct langwell_otg *lnw = the_transceiver;
- char *next;
- unsigned size, t;
-
- next = buf;
- size = PAGE_SIZE;
-
- t = scnprintf(next, size, "%d", lnw->iotg.hsm.a_bus_req);
- size -= t;
- next += t;
-
- return PAGE_SIZE - size;
-}
-
-static ssize_t
-set_a_bus_req(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct langwell_otg *lnw = the_transceiver;
- struct intel_mid_otg_xceiv *iotg = &lnw->iotg;
-
- if (!iotg->otg.default_a)
- return -1;
- if (count > 2)
- return -1;
-
- if (buf[0] == '0') {
- iotg->hsm.a_bus_req = 0;
- dev_dbg(lnw->dev, "User request: a_bus_req = 0\n");
- } else if (buf[0] == '1') {
- /* If a_bus_drop is TRUE, a_bus_req can't be set */
- if (iotg->hsm.a_bus_drop)
- return -1;
- iotg->hsm.a_bus_req = 1;
- dev_dbg(lnw->dev, "User request: a_bus_req = 1\n");
- }
- if (spin_trylock(&lnw->wq_lock)) {
- langwell_update_transceiver();
- spin_unlock(&lnw->wq_lock);
- }
- return count;
-}
-static DEVICE_ATTR(a_bus_req, S_IRUGO | S_IWUSR, get_a_bus_req, set_a_bus_req);
-
-static ssize_t
-get_a_bus_drop(struct device *dev, struct device_attribute *attr, char *buf)
-{
- struct langwell_otg *lnw = the_transceiver;
- char *next;
- unsigned size, t;
-
- next = buf;
- size = PAGE_SIZE;
-
- t = scnprintf(next, size, "%d", lnw->iotg.hsm.a_bus_drop);
- size -= t;
- next += t;
-
- return PAGE_SIZE - size;
-}
-
-static ssize_t
-set_a_bus_drop(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct langwell_otg *lnw = the_transceiver;
- struct intel_mid_otg_xceiv *iotg = &lnw->iotg;
-
- if (!iotg->otg.default_a)
- return -1;
- if (count > 2)
- return -1;
-
- if (buf[0] == '0') {
- iotg->hsm.a_bus_drop = 0;
- dev_dbg(lnw->dev, "User request: a_bus_drop = 0\n");
- } else if (buf[0] == '1') {
- iotg->hsm.a_bus_drop = 1;
- iotg->hsm.a_bus_req = 0;
- dev_dbg(lnw->dev, "User request: a_bus_drop = 1\n");
- dev_dbg(lnw->dev, "User request: and a_bus_req = 0\n");
- }
- if (spin_trylock(&lnw->wq_lock)) {
- langwell_update_transceiver();
- spin_unlock(&lnw->wq_lock);
- }
- return count;
-}
-static DEVICE_ATTR(a_bus_drop, S_IRUGO | S_IWUSR, get_a_bus_drop, set_a_bus_drop);
-
-static ssize_t
-get_b_bus_req(struct device *dev, struct device_attribute *attr, char *buf)
-{
- struct langwell_otg *lnw = the_transceiver;
- char *next;
- unsigned size, t;
-
- next = buf;
- size = PAGE_SIZE;
-
- t = scnprintf(next, size, "%d", lnw->iotg.hsm.b_bus_req);
- size -= t;
- next += t;
-
- return PAGE_SIZE - size;
-}
-
-static ssize_t
-set_b_bus_req(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct langwell_otg *lnw = the_transceiver;
- struct intel_mid_otg_xceiv *iotg = &lnw->iotg;
-
- if (iotg->otg.default_a)
- return -1;
-
- if (count > 2)
- return -1;
-
- if (buf[0] == '0') {
- iotg->hsm.b_bus_req = 0;
- dev_dbg(lnw->dev, "User request: b_bus_req = 0\n");
- } else if (buf[0] == '1') {
- iotg->hsm.b_bus_req = 1;
- dev_dbg(lnw->dev, "User request: b_bus_req = 1\n");
- }
- if (spin_trylock(&lnw->wq_lock)) {
- langwell_update_transceiver();
- spin_unlock(&lnw->wq_lock);
- }
- return count;
-}
-static DEVICE_ATTR(b_bus_req, S_IRUGO | S_IWUSR, get_b_bus_req, set_b_bus_req);
-
-static ssize_t
-set_a_clr_err(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct langwell_otg *lnw = the_transceiver;
- struct intel_mid_otg_xceiv *iotg = &lnw->iotg;
-
- if (!iotg->otg.default_a)
- return -1;
- if (count > 2)
- return -1;
-
- if (buf[0] == '1') {
- iotg->hsm.a_clr_err = 1;
- dev_dbg(lnw->dev, "User request: a_clr_err = 1\n");
- }
- if (spin_trylock(&lnw->wq_lock)) {
- langwell_update_transceiver();
- spin_unlock(&lnw->wq_lock);
- }
- return count;
-}
-static DEVICE_ATTR(a_clr_err, S_IWUSR, NULL, set_a_clr_err);
-
-static struct attribute *inputs_attrs[] = {
- &dev_attr_a_bus_req.attr,
- &dev_attr_a_bus_drop.attr,
- &dev_attr_b_bus_req.attr,
- &dev_attr_a_clr_err.attr,
- NULL,
-};
-
-static struct attribute_group debug_dev_attr_group = {
- .name = "inputs",
- .attrs = inputs_attrs,
-};
-
-static int langwell_otg_probe(struct pci_dev *pdev,
- const struct pci_device_id *id)
-{
- unsigned long resource, len;
- void __iomem *base = NULL;
- int retval;
- u32 val32;
- struct langwell_otg *lnw;
- char qname[] = "langwell_otg_queue";
-
- retval = 0;
- dev_dbg(&pdev->dev, "\notg controller is detected.\n");
- if (pci_enable_device(pdev) < 0) {
- retval = -ENODEV;
- goto done;
- }
-
- lnw = kzalloc(sizeof *lnw, GFP_KERNEL);
- if (lnw == NULL) {
- retval = -ENOMEM;
- goto done;
- }
- the_transceiver = lnw;
-
- /* control register: BAR 0 */
- resource = pci_resource_start(pdev, 0);
- len = pci_resource_len(pdev, 0);
- if (!request_mem_region(resource, len, driver_name)) {
- retval = -EBUSY;
- goto err;
- }
- lnw->region = 1;
-
- base = ioremap_nocache(resource, len);
- if (base == NULL) {
- retval = -EFAULT;
- goto err;
- }
- lnw->iotg.base = base;
-
- if (!request_mem_region(USBCFG_ADDR, USBCFG_LEN, driver_name)) {
- retval = -EBUSY;
- goto err;
- }
- lnw->cfg_region = 1;
-
- /* For the SCCB.USBCFG register */
- base = ioremap_nocache(USBCFG_ADDR, USBCFG_LEN);
- if (base == NULL) {
- retval = -EFAULT;
- goto err;
- }
- lnw->usbcfg = base;
-
- if (!pdev->irq) {
- dev_dbg(&pdev->dev, "No IRQ.\n");
- retval = -ENODEV;
- goto err;
- }
-
- lnw->qwork = create_singlethread_workqueue(qname);
- if (!lnw->qwork) {
- dev_dbg(&pdev->dev, "cannot create workqueue %s\n", qname);
- retval = -ENOMEM;
- goto err;
- }
- INIT_WORK(&lnw->work, langwell_otg_work);
-
- /* OTG common part */
- lnw->dev = &pdev->dev;
- lnw->iotg.otg.dev = lnw->dev;
- lnw->iotg.otg.label = driver_name;
- lnw->iotg.otg.set_host = langwell_otg_set_host;
- lnw->iotg.otg.set_peripheral = langwell_otg_set_peripheral;
- lnw->iotg.otg.set_power = langwell_otg_set_power;
- lnw->iotg.otg.set_vbus = langwell_otg_set_vbus;
- lnw->iotg.otg.start_srp = langwell_otg_start_srp;
- lnw->iotg.otg.state = OTG_STATE_UNDEFINED;
-
- if (otg_set_transceiver(&lnw->iotg.otg)) {
- dev_dbg(lnw->dev, "can't set transceiver\n");
- retval = -EBUSY;
- goto err;
- }
-
- reset_otg();
- init_hsm();
-
- spin_lock_init(&lnw->lock);
- spin_lock_init(&lnw->wq_lock);
- INIT_LIST_HEAD(&active_timers);
- retval = langwell_otg_init_timers(&lnw->iotg.hsm);
- if (retval) {
- dev_dbg(&pdev->dev, "Failed to init timers\n");
- goto err;
- }
-
- init_timer(&lnw->hsm_timer);
- ATOMIC_INIT_NOTIFIER_HEAD(&lnw->iotg.iotg_notifier);
-
- lnw->iotg_notifier.notifier_call = langwell_otg_iotg_notify;
-
- retval = intel_mid_otg_register_notifier(&lnw->iotg,
- &lnw->iotg_notifier);
- if (retval) {
- dev_dbg(lnw->dev, "Failed to register notifier\n");
- goto err;
- }
-
- if (request_irq(pdev->irq, otg_irq, IRQF_SHARED,
- driver_name, lnw) != 0) {
- dev_dbg(lnw->dev, "request interrupt %d failed\n", pdev->irq);
- retval = -EBUSY;
- goto err;
- }
-
- /* enable OTGSC int */
- val32 = OTGSC_DPIE | OTGSC_BSEIE | OTGSC_BSVIE |
- OTGSC_ASVIE | OTGSC_AVVIE | OTGSC_IDIE | OTGSC_IDPU;
- writel(val32, lnw->iotg.base + CI_OTGSC);
-
- retval = device_create_file(&pdev->dev, &dev_attr_registers);
- if (retval < 0) {
- dev_dbg(lnw->dev,
- "Can't register sysfs attribute: %d\n", retval);
- goto err;
- }
-
- retval = device_create_file(&pdev->dev, &dev_attr_hsm);
- if (retval < 0) {
- dev_dbg(lnw->dev, "Can't hsm sysfs attribute: %d\n", retval);
- goto err;
- }
-
- retval = sysfs_create_group(&pdev->dev.kobj, &debug_dev_attr_group);
- if (retval < 0) {
- dev_dbg(lnw->dev,
- "Can't register sysfs attr group: %d\n", retval);
- goto err;
- }
-
- if (lnw->iotg.otg.state == OTG_STATE_A_IDLE)
- langwell_update_transceiver();
-
- return 0;
-
-err:
- if (the_transceiver)
- langwell_otg_remove(pdev);
-done:
- return retval;
-}
-
-static void langwell_otg_remove(struct pci_dev *pdev)
-{
- struct langwell_otg *lnw = the_transceiver;
-
- if (lnw->qwork) {
- flush_workqueue(lnw->qwork);
- destroy_workqueue(lnw->qwork);
- }
- intel_mid_otg_unregister_notifier(&lnw->iotg, &lnw->iotg_notifier);
- langwell_otg_free_timers();
-
- /* disable OTGSC interrupt as OTGSC doesn't change in reset */
- writel(0, lnw->iotg.base + CI_OTGSC);
-
- if (pdev->irq)
- free_irq(pdev->irq, lnw);
- if (lnw->usbcfg)
- iounmap(lnw->usbcfg);
- if (lnw->cfg_region)
- release_mem_region(USBCFG_ADDR, USBCFG_LEN);
- if (lnw->iotg.base)
- iounmap(lnw->iotg.base);
- if (lnw->region)
- release_mem_region(pci_resource_start(pdev, 0),
- pci_resource_len(pdev, 0));
-
- otg_set_transceiver(NULL);
- pci_disable_device(pdev);
- sysfs_remove_group(&pdev->dev.kobj, &debug_dev_attr_group);
- device_remove_file(&pdev->dev, &dev_attr_hsm);
- device_remove_file(&pdev->dev, &dev_attr_registers);
- kfree(lnw);
- lnw = NULL;
-}
-
-static void transceiver_suspend(struct pci_dev *pdev)
-{
- pci_save_state(pdev);
- pci_set_power_state(pdev, PCI_D3hot);
- langwell_otg_phy_low_power(1);
-}
-
-static int langwell_otg_suspend(struct pci_dev *pdev, pm_message_t message)
-{
- struct langwell_otg *lnw = the_transceiver;
- struct intel_mid_otg_xceiv *iotg = &lnw->iotg;
- int ret = 0;
-
- /* Disbale OTG interrupts */
- langwell_otg_intr(0);
-
- if (pdev->irq)
- free_irq(pdev->irq, lnw);
-
- /* Prevent more otg_work */
- flush_workqueue(lnw->qwork);
- destroy_workqueue(lnw->qwork);
- lnw->qwork = NULL;
-
- /* start actions */
- switch (iotg->otg.state) {
- case OTG_STATE_A_WAIT_VFALL:
- iotg->otg.state = OTG_STATE_A_IDLE;
- case OTG_STATE_A_IDLE:
- case OTG_STATE_B_IDLE:
- case OTG_STATE_A_VBUS_ERR:
- transceiver_suspend(pdev);
- break;
- case OTG_STATE_A_WAIT_VRISE:
- langwell_otg_del_timer(a_wait_vrise_tmr);
- iotg->hsm.a_srp_det = 0;
-
- /* Turn off VBus */
- iotg->otg.set_vbus(&iotg->otg, false);
- iotg->otg.state = OTG_STATE_A_IDLE;
- transceiver_suspend(pdev);
- break;
- case OTG_STATE_A_WAIT_BCON:
- del_timer_sync(&lnw->hsm_timer);
- if (lnw->iotg.stop_host)
- lnw->iotg.stop_host(&lnw->iotg);
- else
- dev_dbg(&pdev->dev, "host driver has been removed.\n");
-
- iotg->hsm.a_srp_det = 0;
-
- /* Turn off VBus */
- iotg->otg.set_vbus(&iotg->otg, false);
- iotg->otg.state = OTG_STATE_A_IDLE;
- transceiver_suspend(pdev);
- break;
- case OTG_STATE_A_HOST:
- if (lnw->iotg.stop_host)
- lnw->iotg.stop_host(&lnw->iotg);
- else
- dev_dbg(&pdev->dev, "host driver has been removed.\n");
-
- iotg->hsm.a_srp_det = 0;
-
- /* Turn off VBus */
- iotg->otg.set_vbus(&iotg->otg, false);
-
- iotg->otg.state = OTG_STATE_A_IDLE;
- transceiver_suspend(pdev);
- break;
- case OTG_STATE_A_SUSPEND:
- langwell_otg_del_timer(a_aidl_bdis_tmr);
- langwell_otg_HABA(0);
- if (lnw->iotg.stop_host)
- lnw->iotg.stop_host(&lnw->iotg);
- else
- dev_dbg(lnw->dev, "host driver has been removed.\n");
- iotg->hsm.a_srp_det = 0;
-
- /* Turn off VBus */
- iotg->otg.set_vbus(&iotg->otg, false);
- iotg->otg.state = OTG_STATE_A_IDLE;
- transceiver_suspend(pdev);
- break;
- case OTG_STATE_A_PERIPHERAL:
- del_timer_sync(&lnw->hsm_timer);
-
- if (lnw->iotg.stop_peripheral)
- lnw->iotg.stop_peripheral(&lnw->iotg);
- else
- dev_dbg(&pdev->dev,
- "client driver has been removed.\n");
- iotg->hsm.a_srp_det = 0;
-
- /* Turn off VBus */
- iotg->otg.set_vbus(&iotg->otg, false);
- iotg->otg.state = OTG_STATE_A_IDLE;
- transceiver_suspend(pdev);
- break;
- case OTG_STATE_B_HOST:
- if (lnw->iotg.stop_host)
- lnw->iotg.stop_host(&lnw->iotg);
- else
- dev_dbg(&pdev->dev, "host driver has been removed.\n");
- iotg->hsm.b_bus_req = 0;
- iotg->otg.state = OTG_STATE_B_IDLE;
- transceiver_suspend(pdev);
- break;
- case OTG_STATE_B_PERIPHERAL:
- if (lnw->iotg.stop_peripheral)
- lnw->iotg.stop_peripheral(&lnw->iotg);
- else
- dev_dbg(&pdev->dev,
- "client driver has been removed.\n");
- iotg->otg.state = OTG_STATE_B_IDLE;
- transceiver_suspend(pdev);
- break;
- case OTG_STATE_B_WAIT_ACON:
- /* delete hsm timer for b_ase0_brst_tmr */
- del_timer_sync(&lnw->hsm_timer);
-
- langwell_otg_HAAR(0);
-
- if (lnw->iotg.stop_host)
- lnw->iotg.stop_host(&lnw->iotg);
- else
- dev_dbg(&pdev->dev, "host driver has been removed.\n");
- iotg->hsm.b_bus_req = 0;
- iotg->otg.state = OTG_STATE_B_IDLE;
- transceiver_suspend(pdev);
- break;
- default:
- dev_dbg(lnw->dev, "error state before suspend\n");
- break;
- }
-
- return ret;
-}
-
-static void transceiver_resume(struct pci_dev *pdev)
-{
- pci_restore_state(pdev);
- pci_set_power_state(pdev, PCI_D0);
-}
-
-static int langwell_otg_resume(struct pci_dev *pdev)
-{
- struct langwell_otg *lnw = the_transceiver;
- int ret = 0;
-
- transceiver_resume(pdev);
-
- lnw->qwork = create_singlethread_workqueue("langwell_otg_queue");
- if (!lnw->qwork) {
- dev_dbg(&pdev->dev, "cannot create langwell otg workqueuen");
- ret = -ENOMEM;
- goto error;
- }
-
- if (request_irq(pdev->irq, otg_irq, IRQF_SHARED,
- driver_name, lnw) != 0) {
- dev_dbg(&pdev->dev, "request interrupt %d failed\n", pdev->irq);
- ret = -EBUSY;
- goto error;
- }
-
- /* enable OTG interrupts */
- langwell_otg_intr(1);
-
- update_hsm();
-
- langwell_update_transceiver();
-
- return ret;
-error:
- langwell_otg_intr(0);
- transceiver_suspend(pdev);
- return ret;
-}
-
-static int __init langwell_otg_init(void)
-{
- return pci_register_driver(&otg_pci_driver);
-}
-module_init(langwell_otg_init);
-
-static void __exit langwell_otg_cleanup(void)
-{
- pci_unregister_driver(&otg_pci_driver);
-}
-module_exit(langwell_otg_cleanup);
diff --git a/drivers/usb/otg/mv_otg.c b/drivers/usb/otg/mv_otg.c
index db0d4fcdc8e..b5fbe1452ab 100644
--- a/drivers/usb/otg/mv_otg.c
+++ b/drivers/usb/otg/mv_otg.c
@@ -202,6 +202,7 @@ static void mv_otg_init_irq(struct mv_otg *mvotg)
static void mv_otg_start_host(struct mv_otg *mvotg, int on)
{
+#ifdef CONFIG_USB
struct otg_transceiver *otg = &mvotg->otg;
struct usb_hcd *hcd;
@@ -216,6 +217,7 @@ static void mv_otg_start_host(struct mv_otg *mvotg, int on)
usb_add_hcd(hcd, hcd->irq, IRQF_SHARED);
else
usb_remove_hcd(hcd);
+#endif /* CONFIG_USB */
}
static void mv_otg_start_periphrals(struct mv_otg *mvotg, int on)
diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c b/drivers/usb/renesas_usbhs/mod_gadget.c
index 528691d5f3e..7542aa94a46 100644
--- a/drivers/usb/renesas_usbhs/mod_gadget.c
+++ b/drivers/usb/renesas_usbhs/mod_gadget.c
@@ -425,7 +425,7 @@ static int usbhsg_recip_run_handle(struct usbhs_priv *priv,
struct usbhs_pipe *pipe;
int recip = ctrl->bRequestType & USB_RECIP_MASK;
int nth = le16_to_cpu(ctrl->wIndex) & USB_ENDPOINT_NUMBER_MASK;
- int ret;
+ int ret = 0;
int (*func)(struct usbhs_priv *priv, struct usbhsg_uep *uep,
struct usb_ctrlrequest *ctrl);
char *msg;
diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig
index 677f577c024..434df7f2a4b 100644
--- a/drivers/usb/serial/Kconfig
+++ b/drivers/usb/serial/Kconfig
@@ -238,6 +238,15 @@ config USB_SERIAL_EDGEPORT_TI
To compile this driver as a module, choose M here: the
module will be called io_ti.
+config USB_SERIAL_F81232
+ tristate "USB Fintek F81232 Single Port Serial Driver"
+ help
+ Say Y here if you want to use the Fintek F81232 single
+ port usb to serial adapter.
+
+ To compile this driver as a module, choose M here: the
+ module will be called f81232.
+
config USB_SERIAL_GARMIN
tristate "USB Garmin GPS driver"
help
diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile
index 9e536eefb32..5ac438b4027 100644
--- a/drivers/usb/serial/Makefile
+++ b/drivers/usb/serial/Makefile
@@ -23,6 +23,7 @@ obj-$(CONFIG_USB_SERIAL_DIGI_ACCELEPORT) += digi_acceleport.o
obj-$(CONFIG_USB_SERIAL_EDGEPORT) += io_edgeport.o
obj-$(CONFIG_USB_SERIAL_EDGEPORT_TI) += io_ti.o
obj-$(CONFIG_USB_SERIAL_EMPEG) += empeg.o
+obj-$(CONFIG_USB_SERIAL_F81232) += f81232.o
obj-$(CONFIG_USB_SERIAL_FTDI_SIO) += ftdi_sio.o
obj-$(CONFIG_USB_SERIAL_FUNSOFT) += funsoft.o
obj-$(CONFIG_USB_SERIAL_GARMIN) += garmin_gps.o
diff --git a/drivers/usb/serial/aircable.c b/drivers/usb/serial/aircable.c
index 123bf915533..eec4fb9a35c 100644
--- a/drivers/usb/serial/aircable.c
+++ b/drivers/usb/serial/aircable.c
@@ -175,7 +175,6 @@ static struct usb_driver aircable_driver = {
.probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
.id_table = id_table,
- .no_dynamic_id = 1,
};
static struct usb_serial_driver aircable_device = {
@@ -183,7 +182,6 @@ static struct usb_serial_driver aircable_device = {
.owner = THIS_MODULE,
.name = "aircable",
},
- .usb_driver = &aircable_driver,
.id_table = id_table,
.num_ports = 1,
.bulk_out_size = HCI_COMPLETE_FRAME,
@@ -194,36 +192,16 @@ static struct usb_serial_driver aircable_device = {
.unthrottle = usb_serial_generic_unthrottle,
};
-static int __init aircable_init(void)
-{
- int retval;
- retval = usb_serial_register(&aircable_device);
- if (retval)
- goto failed_serial_register;
- retval = usb_register(&aircable_driver);
- if (retval)
- goto failed_usb_register;
- return 0;
-
-failed_usb_register:
- usb_serial_deregister(&aircable_device);
-failed_serial_register:
- return retval;
-}
+static struct usb_serial_driver * const serial_drivers[] = {
+ &aircable_device, NULL
+};
-static void __exit aircable_exit(void)
-{
- usb_deregister(&aircable_driver);
- usb_serial_deregister(&aircable_device);
-}
+module_usb_serial_driver(aircable_driver, serial_drivers);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_VERSION(DRIVER_VERSION);
MODULE_LICENSE("GPL");
-module_init(aircable_init);
-module_exit(aircable_exit);
-
module_param(debug, bool, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(debug, "Debug enabled or not");
diff --git a/drivers/usb/serial/ark3116.c b/drivers/usb/serial/ark3116.c
index 69328dcfd91..f99f47100dd 100644
--- a/drivers/usb/serial/ark3116.c
+++ b/drivers/usb/serial/ark3116.c
@@ -719,7 +719,6 @@ static struct usb_driver ark3116_driver = {
.probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
.id_table = id_table,
- .no_dynamic_id = 1,
};
static struct usb_serial_driver ark3116_device = {
@@ -728,7 +727,6 @@ static struct usb_serial_driver ark3116_device = {
.name = "ark3116",
},
.id_table = id_table,
- .usb_driver = &ark3116_driver,
.num_ports = 1,
.attach = ark3116_attach,
.release = ark3116_release,
@@ -745,32 +743,12 @@ static struct usb_serial_driver ark3116_device = {
.process_read_urb = ark3116_process_read_urb,
};
-static int __init ark3116_init(void)
-{
- int retval;
-
- retval = usb_serial_register(&ark3116_device);
- if (retval)
- return retval;
- retval = usb_register(&ark3116_driver);
- if (retval == 0) {
- printk(KERN_INFO "%s:"
- DRIVER_VERSION ":"
- DRIVER_DESC "\n",
- KBUILD_MODNAME);
- } else
- usb_serial_deregister(&ark3116_device);
- return retval;
-}
+static struct usb_serial_driver * const serial_drivers[] = {
+ &ark3116_device, NULL
+};
-static void __exit ark3116_exit(void)
-{
- usb_deregister(&ark3116_driver);
- usb_serial_deregister(&ark3116_device);
-}
+module_usb_serial_driver(ark3116_driver, serial_drivers);
-module_init(ark3116_init);
-module_exit(ark3116_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR(DRIVER_AUTHOR);
diff --git a/drivers/usb/serial/belkin_sa.c b/drivers/usb/serial/belkin_sa.c
index 29ffeb6279c..a52e0d2cec3 100644
--- a/drivers/usb/serial/belkin_sa.c
+++ b/drivers/usb/serial/belkin_sa.c
@@ -78,7 +78,6 @@ static struct usb_driver belkin_driver = {
.probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
.id_table = id_table_combined,
- .no_dynamic_id = 1,
};
/* All of the device info needed for the serial converters */
@@ -88,7 +87,6 @@ static struct usb_serial_driver belkin_device = {
.name = "belkin",
},
.description = "Belkin / Peracom / GoHubs USB Serial Adapter",
- .usb_driver = &belkin_driver,
.id_table = id_table_combined,
.num_ports = 1,
.open = belkin_sa_open,
@@ -103,6 +101,10 @@ static struct usb_serial_driver belkin_device = {
.release = belkin_sa_release,
};
+static struct usb_serial_driver * const serial_drivers[] = {
+ &belkin_device, NULL
+};
+
struct belkin_sa_private {
spinlock_t lock;
unsigned long control_state;
@@ -522,34 +524,7 @@ exit:
return retval;
}
-
-static int __init belkin_sa_init(void)
-{
- int retval;
- retval = usb_serial_register(&belkin_device);
- if (retval)
- goto failed_usb_serial_register;
- retval = usb_register(&belkin_driver);
- if (retval)
- goto failed_usb_register;
- printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
- DRIVER_DESC "\n");
- return 0;
-failed_usb_register:
- usb_serial_deregister(&belkin_device);
-failed_usb_serial_register:
- return retval;
-}
-
-static void __exit belkin_sa_exit (void)
-{
- usb_deregister(&belkin_driver);
- usb_serial_deregister(&belkin_device);
-}
-
-
-module_init(belkin_sa_init);
-module_exit(belkin_sa_exit);
+module_usb_serial_driver(belkin_driver, serial_drivers);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c
index 5e53cc59e65..aaab32db31d 100644
--- a/drivers/usb/serial/ch341.c
+++ b/drivers/usb/serial/ch341.c
@@ -625,7 +625,6 @@ static struct usb_driver ch341_driver = {
.resume = usb_serial_resume,
.reset_resume = ch341_reset_resume,
.id_table = id_table,
- .no_dynamic_id = 1,
.supports_autosuspend = 1,
};
@@ -635,7 +634,6 @@ static struct usb_serial_driver ch341_device = {
.name = "ch341-uart",
},
.id_table = id_table,
- .usb_driver = &ch341_driver,
.num_ports = 1,
.open = ch341_open,
.dtr_rts = ch341_dtr_rts,
@@ -650,30 +648,13 @@ static struct usb_serial_driver ch341_device = {
.attach = ch341_attach,
};
-static int __init ch341_init(void)
-{
- int retval;
-
- retval = usb_serial_register(&ch341_device);
- if (retval)
- return retval;
- retval = usb_register(&ch341_driver);
- if (retval)
- usb_serial_deregister(&ch341_device);
- return retval;
-}
+static struct usb_serial_driver * const serial_drivers[] = {
+ &ch341_device, NULL
+};
-static void __exit ch341_exit(void)
-{
- usb_deregister(&ch341_driver);
- usb_serial_deregister(&ch341_device);
-}
+module_usb_serial_driver(ch341_driver, serial_drivers);
-module_init(ch341_init);
-module_exit(ch341_exit);
MODULE_LICENSE("GPL");
module_param(debug, bool, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(debug, "Debug enabled or not");
-
-/* EOF ch341.c */
diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c
index fba1147ed91..651b2aa1348 100644
--- a/drivers/usb/serial/cp210x.c
+++ b/drivers/usb/serial/cp210x.c
@@ -39,6 +39,8 @@ static void cp210x_get_termios(struct tty_struct *,
struct usb_serial_port *port);
static void cp210x_get_termios_port(struct usb_serial_port *port,
unsigned int *cflagp, unsigned int *baudp);
+static void cp210x_change_speed(struct tty_struct *, struct usb_serial_port *,
+ struct ktermios *);
static void cp210x_set_termios(struct tty_struct *, struct usb_serial_port *,
struct ktermios*);
static int cp210x_tiocmget(struct tty_struct *);
@@ -134,10 +136,13 @@ static const struct usb_device_id id_table[] = {
{ USB_DEVICE(0x16DC, 0x0011) }, /* W-IE-NE-R Plein & Baus GmbH RCM Remote Control for MARATON Power Supply */
{ USB_DEVICE(0x16DC, 0x0012) }, /* W-IE-NE-R Plein & Baus GmbH MPOD Multi Channel Power Supply */
{ USB_DEVICE(0x16DC, 0x0015) }, /* W-IE-NE-R Plein & Baus GmbH CML Control, Monitoring and Data Logger */
+ { USB_DEVICE(0x17A8, 0x0001) }, /* Kamstrup Optical Eye/3-wire */
+ { USB_DEVICE(0x17A8, 0x0005) }, /* Kamstrup M-Bus Master MultiPort 250D */
{ USB_DEVICE(0x17F4, 0xAAAA) }, /* Wavesense Jazz blood glucose meter */
{ USB_DEVICE(0x1843, 0x0200) }, /* Vaisala USB Instrument Cable */
{ USB_DEVICE(0x18EF, 0xE00F) }, /* ELV USB-I2C-Interface */
{ USB_DEVICE(0x1BE3, 0x07A6) }, /* WAGO 750-923 USB Service Cable */
+ { USB_DEVICE(0x3195, 0xF190) }, /* Link Instruments MSO-19 */
{ USB_DEVICE(0x413C, 0x9500) }, /* DW700 GPS USB interface */
{ } /* Terminating Entry */
};
@@ -149,7 +154,6 @@ static struct usb_driver cp210x_driver = {
.probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
.id_table = id_table,
- .no_dynamic_id = 1,
};
static struct usb_serial_driver cp210x_device = {
@@ -157,7 +161,6 @@ static struct usb_serial_driver cp210x_device = {
.owner = THIS_MODULE,
.name = "cp210x",
},
- .usb_driver = &cp210x_driver,
.id_table = id_table,
.num_ports = 1,
.bulk_in_size = 256,
@@ -172,6 +175,10 @@ static struct usb_serial_driver cp210x_device = {
.dtr_rts = cp210x_dtr_rts
};
+static struct usb_serial_driver * const serial_drivers[] = {
+ &cp210x_device, NULL
+};
+
/* Config request types */
#define REQTYPE_HOST_TO_DEVICE 0x41
#define REQTYPE_DEVICE_TO_HOST 0xc1
@@ -201,6 +208,8 @@ static struct usb_serial_driver cp210x_device = {
#define CP210X_EMBED_EVENTS 0x15
#define CP210X_GET_EVENTSTATE 0x16
#define CP210X_SET_CHARS 0x19
+#define CP210X_GET_BAUDRATE 0x1D
+#define CP210X_SET_BAUDRATE 0x1E
/* CP210X_IFC_ENABLE */
#define UART_ENABLE 0x0001
@@ -279,7 +288,7 @@ static int cp210x_get_config(struct usb_serial_port *port, u8 request,
if (result != size) {
dbg("%s - Unable to send config request, "
- "request=0x%x size=%d result=%d\n",
+ "request=0x%x size=%d result=%d",
__func__, request, size, result);
if (result > 0)
result = -EPROTO;
@@ -333,7 +342,7 @@ static int cp210x_set_config(struct usb_serial_port *port, u8 request,
if ((size > 2 && result != size) || result < 0) {
dbg("%s - Unable to send request, "
- "request=0x%x size=%d result=%d\n",
+ "request=0x%x size=%d result=%d",
__func__, request, size, result);
if (result > 0)
result = -EPROTO;
@@ -360,8 +369,8 @@ static inline int cp210x_set_config_single(struct usb_serial_port *port,
* Quantises the baud rate as per AN205 Table 1
*/
static unsigned int cp210x_quantise_baudrate(unsigned int baud) {
- if (baud <= 56) baud = 0;
- else if (baud <= 300) baud = 300;
+ if (baud <= 300)
+ baud = 300;
else if (baud <= 600) baud = 600;
else if (baud <= 1200) baud = 1200;
else if (baud <= 1800) baud = 1800;
@@ -389,10 +398,10 @@ static unsigned int cp210x_quantise_baudrate(unsigned int baud) {
else if (baud <= 491520) baud = 460800;
else if (baud <= 567138) baud = 500000;
else if (baud <= 670254) baud = 576000;
- else if (baud <= 1053257) baud = 921600;
- else if (baud <= 1474560) baud = 1228800;
- else if (baud <= 2457600) baud = 1843200;
- else baud = 3686400;
+ else if (baud < 1000000)
+ baud = 921600;
+ else if (baud > 2000000)
+ baud = 2000000;
return baud;
}
@@ -409,13 +418,14 @@ static int cp210x_open(struct tty_struct *tty, struct usb_serial_port *port)
return result;
}
- result = usb_serial_generic_open(tty, port);
- if (result)
- return result;
-
/* Configure the termios structure */
cp210x_get_termios(tty, port);
- return 0;
+
+ /* The baud rate must be initialised on cp2104 */
+ if (tty)
+ cp210x_change_speed(tty, port, NULL);
+
+ return usb_serial_generic_open(tty, port);
}
static void cp210x_close(struct usb_serial_port *port)
@@ -467,10 +477,7 @@ static void cp210x_get_termios_port(struct usb_serial_port *port,
dbg("%s - port %d", __func__, port->number);
- cp210x_get_config(port, CP210X_GET_BAUDDIV, &baud, 2);
- /* Convert to baudrate */
- if (baud)
- baud = cp210x_quantise_baudrate((BAUD_RATE_GEN_FREQ + baud/2)/ baud);
+ cp210x_get_config(port, CP210X_GET_BAUDRATE, &baud, 4);
dbg("%s - baud rate = %d", __func__, baud);
*baudp = baud;
@@ -579,11 +586,64 @@ static void cp210x_get_termios_port(struct usb_serial_port *port,
*cflagp = cflag;
}
+/*
+ * CP2101 supports the following baud rates:
+ *
+ * 300, 600, 1200, 1800, 2400, 4800, 7200, 9600, 14400, 19200, 28800,
+ * 38400, 56000, 57600, 115200, 128000, 230400, 460800, 921600
+ *
+ * CP2102 and CP2103 support the following additional rates:
+ *
+ * 4000, 16000, 51200, 64000, 76800, 153600, 250000, 256000, 500000,
+ * 576000
+ *
+ * The device will map a requested rate to a supported one, but the result
+ * of requests for rates greater than 1053257 is undefined (see AN205).
+ *
+ * CP2104, CP2105 and CP2110 support most rates up to 2M, 921k and 1M baud,
+ * respectively, with an error less than 1%. The actual rates are determined
+ * by
+ *
+ * div = round(freq / (2 x prescale x request))
+ * actual = freq / (2 x prescale x div)
+ *
+ * For CP2104 and CP2105 freq is 48Mhz and prescale is 4 for request <= 365bps
+ * or 1 otherwise.
+ * For CP2110 freq is 24Mhz and prescale is 4 for request <= 300bps or 1
+ * otherwise.
+ */
+static void cp210x_change_speed(struct tty_struct *tty,
+ struct usb_serial_port *port, struct ktermios *old_termios)
+{
+ u32 baud;
+
+ baud = tty->termios->c_ospeed;
+
+ /* This maps the requested rate to a rate valid on cp2102 or cp2103,
+ * or to an arbitrary rate in [1M,2M].
+ *
+ * NOTE: B0 is not implemented.
+ */
+ baud = cp210x_quantise_baudrate(baud);
+
+ dbg("%s - setting baud rate to %u", __func__, baud);
+ if (cp210x_set_config(port, CP210X_SET_BAUDRATE, &baud,
+ sizeof(baud))) {
+ dev_warn(&port->dev, "failed to set baud rate to %u\n", baud);
+ if (old_termios)
+ baud = old_termios->c_ospeed;
+ else
+ baud = 9600;
+ }
+
+ tty_encode_baud_rate(tty, baud, baud);
+}
+
static void cp210x_set_termios(struct tty_struct *tty,
struct usb_serial_port *port, struct ktermios *old_termios)
{
unsigned int cflag, old_cflag;
- unsigned int baud = 0, bits;
+ unsigned int bits;
unsigned int modem_ctl[4];
dbg("%s - port %d", __func__, port->number);
@@ -593,20 +653,9 @@ static void cp210x_set_termios(struct tty_struct *tty,
cflag = tty->termios->c_cflag;
old_cflag = old_termios->c_cflag;
- baud = cp210x_quantise_baudrate(tty_get_baud_rate(tty));
-
- /* If the baud rate is to be updated*/
- if (baud != tty_termios_baud_rate(old_termios) && baud != 0) {
- dbg("%s - Setting baud rate to %d baud", __func__,
- baud);
- if (cp210x_set_config_single(port, CP210X_SET_BAUDDIV,
- ((BAUD_RATE_GEN_FREQ + baud/2) / baud))) {
- dbg("Baud rate requested not supported by device");
- baud = tty_termios_baud_rate(old_termios);
- }
- }
- /* Report back the resulting baud rate */
- tty_encode_baud_rate(tty, baud, baud);
+
+ if (tty->termios->c_ospeed != old_termios->c_ospeed)
+ cp210x_change_speed(tty, port, old_termios);
/* If the number of data bits is to be updated */
if ((cflag & CSIZE) != (old_cflag & CSIZE)) {
@@ -636,13 +685,13 @@ static void cp210x_set_termios(struct tty_struct *tty,
default:
dbg("cp210x driver does not "
"support the number of bits requested,"
- " using 8 bit mode\n");
+ " using 8 bit mode");
bits |= BITS_DATA_8;
break;
}
if (cp210x_set_config(port, CP210X_SET_LINE_CTL, &bits, 2))
dbg("Number of data bits requested "
- "not supported by device\n");
+ "not supported by device");
}
if ((cflag & (PARENB|PARODD|CMSPAR)) !=
@@ -669,8 +718,7 @@ static void cp210x_set_termios(struct tty_struct *tty,
}
}
if (cp210x_set_config(port, CP210X_SET_LINE_CTL, &bits, 2))
- dbg("Parity mode not supported "
- "by device\n");
+ dbg("Parity mode not supported by device");
}
if ((cflag & CSTOPB) != (old_cflag & CSTOPB)) {
@@ -685,7 +733,7 @@ static void cp210x_set_termios(struct tty_struct *tty,
}
if (cp210x_set_config(port, CP210X_SET_LINE_CTL, &bits, 2))
dbg("Number of stop bits requested "
- "not supported by device\n");
+ "not supported by device");
}
if ((cflag & CRTSCTS) != (old_cflag & CRTSCTS)) {
@@ -802,35 +850,7 @@ static int cp210x_startup(struct usb_serial *serial)
return 0;
}
-static int __init cp210x_init(void)
-{
- int retval;
-
- retval = usb_serial_register(&cp210x_device);
- if (retval)
- return retval; /* Failed to register */
-
- retval = usb_register(&cp210x_driver);
- if (retval) {
- /* Failed to register */
- usb_serial_deregister(&cp210x_device);
- return retval;
- }
-
- /* Success */
- printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
- DRIVER_DESC "\n");
- return 0;
-}
-
-static void __exit cp210x_exit(void)
-{
- usb_deregister(&cp210x_driver);
- usb_serial_deregister(&cp210x_device);
-}
-
-module_init(cp210x_init);
-module_exit(cp210x_exit);
+module_usb_serial_driver(cp210x_driver, serial_drivers);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_VERSION(DRIVER_VERSION);
diff --git a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c
index 6bc3802a581..d39b9418f2f 100644
--- a/drivers/usb/serial/cyberjack.c
+++ b/drivers/usb/serial/cyberjack.c
@@ -82,7 +82,6 @@ static struct usb_driver cyberjack_driver = {
.probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
.id_table = id_table,
- .no_dynamic_id = 1,
};
static struct usb_serial_driver cyberjack_device = {
@@ -91,7 +90,6 @@ static struct usb_serial_driver cyberjack_device = {
.name = "cyberjack",
},
.description = "Reiner SCT Cyberjack USB card reader",
- .usb_driver = &cyberjack_driver,
.id_table = id_table,
.num_ports = 1,
.attach = cyberjack_startup,
@@ -106,6 +104,10 @@ static struct usb_serial_driver cyberjack_device = {
.write_bulk_callback = cyberjack_write_bulk_callback,
};
+static struct usb_serial_driver * const serial_drivers[] = {
+ &cyberjack_device, NULL
+};
+
struct cyberjack_private {
spinlock_t lock; /* Lock for SMP */
short rdtodo; /* Bytes still to read */
@@ -473,35 +475,7 @@ exit:
usb_serial_port_softint(port);
}
-static int __init cyberjack_init(void)
-{
- int retval;
- retval = usb_serial_register(&cyberjack_device);
- if (retval)
- goto failed_usb_serial_register;
- retval = usb_register(&cyberjack_driver);
- if (retval)
- goto failed_usb_register;
-
- printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION " "
- DRIVER_AUTHOR "\n");
- printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "\n");
-
- return 0;
-failed_usb_register:
- usb_serial_deregister(&cyberjack_device);
-failed_usb_serial_register:
- return retval;
-}
-
-static void __exit cyberjack_exit(void)
-{
- usb_deregister(&cyberjack_driver);
- usb_serial_deregister(&cyberjack_device);
-}
-
-module_init(cyberjack_init);
-module_exit(cyberjack_exit);
+module_usb_serial_driver(cyberjack_driver, serial_drivers);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c
index 3bdeafa29c2..afc886c75d2 100644
--- a/drivers/usb/serial/cypress_m8.c
+++ b/drivers/usb/serial/cypress_m8.c
@@ -94,7 +94,6 @@ static struct usb_driver cypress_driver = {
.probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
.id_table = id_table_combined,
- .no_dynamic_id = 1,
};
enum packet_format {
@@ -163,7 +162,6 @@ static struct usb_serial_driver cypress_earthmate_device = {
.name = "earthmate",
},
.description = "DeLorme Earthmate USB",
- .usb_driver = &cypress_driver,
.id_table = id_table_earthmate,
.num_ports = 1,
.attach = cypress_earthmate_startup,
@@ -190,7 +188,6 @@ static struct usb_serial_driver cypress_hidcom_device = {
.name = "cyphidcom",
},
.description = "HID->COM RS232 Adapter",
- .usb_driver = &cypress_driver,
.id_table = id_table_cyphidcomrs232,
.num_ports = 1,
.attach = cypress_hidcom_startup,
@@ -217,7 +214,6 @@ static struct usb_serial_driver cypress_ca42v2_device = {
.name = "nokiaca42v2",
},
.description = "Nokia CA-42 V2 Adapter",
- .usb_driver = &cypress_driver,
.id_table = id_table_nokiaca42v2,
.num_ports = 1,
.attach = cypress_ca42v2_startup,
@@ -238,6 +234,11 @@ static struct usb_serial_driver cypress_ca42v2_device = {
.write_int_callback = cypress_write_int_callback,
};
+static struct usb_serial_driver * const serial_drivers[] = {
+ &cypress_earthmate_device, &cypress_hidcom_device,
+ &cypress_ca42v2_device, NULL
+};
+
/*****************************************************************************
* Cypress serial helper functions
*****************************************************************************/
@@ -800,7 +801,7 @@ send:
cypress_write_int_callback, port, priv->write_urb_interval);
result = usb_submit_urb(port->interrupt_out_urb, GFP_ATOMIC);
if (result) {
- dev_err(&port->dev,
+ dev_err_console(port,
"%s - failed submitting write urb, error %d\n",
__func__, result);
priv->write_urb_in_use = 0;
@@ -1345,58 +1346,7 @@ static void cypress_write_int_callback(struct urb *urb)
cypress_send(port);
}
-
-/*****************************************************************************
- * Module functions
- *****************************************************************************/
-
-static int __init cypress_init(void)
-{
- int retval;
-
- dbg("%s", __func__);
-
- retval = usb_serial_register(&cypress_earthmate_device);
- if (retval)
- goto failed_em_register;
- retval = usb_serial_register(&cypress_hidcom_device);
- if (retval)
- goto failed_hidcom_register;
- retval = usb_serial_register(&cypress_ca42v2_device);
- if (retval)
- goto failed_ca42v2_register;
- retval = usb_register(&cypress_driver);
- if (retval)
- goto failed_usb_register;
-
- printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
- DRIVER_DESC "\n");
- return 0;
-
-failed_usb_register:
- usb_serial_deregister(&cypress_ca42v2_device);
-failed_ca42v2_register:
- usb_serial_deregister(&cypress_hidcom_device);
-failed_hidcom_register:
- usb_serial_deregister(&cypress_earthmate_device);
-failed_em_register:
- return retval;
-}
-
-
-static void __exit cypress_exit(void)
-{
- dbg("%s", __func__);
-
- usb_deregister(&cypress_driver);
- usb_serial_deregister(&cypress_earthmate_device);
- usb_serial_deregister(&cypress_hidcom_device);
- usb_serial_deregister(&cypress_ca42v2_device);
-}
-
-
-module_init(cypress_init);
-module_exit(cypress_exit);
+module_usb_serial_driver(cypress_driver, serial_drivers);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c
index b23bebd721a..999f91bf70d 100644
--- a/drivers/usb/serial/digi_acceleport.c
+++ b/drivers/usb/serial/digi_acceleport.c
@@ -276,7 +276,6 @@ static struct usb_driver digi_driver = {
.probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
.id_table = id_table_combined,
- .no_dynamic_id = 1,
};
@@ -288,7 +287,6 @@ static struct usb_serial_driver digi_acceleport_2_device = {
.name = "digi_2",
},
.description = "Digi 2 port USB adapter",
- .usb_driver = &digi_driver,
.id_table = id_table_2,
.num_ports = 3,
.open = digi_open,
@@ -316,7 +314,6 @@ static struct usb_serial_driver digi_acceleport_4_device = {
.name = "digi_4",
},
.description = "Digi 4 port USB adapter",
- .usb_driver = &digi_driver,
.id_table = id_table_4,
.num_ports = 4,
.open = digi_open,
@@ -337,6 +334,9 @@ static struct usb_serial_driver digi_acceleport_4_device = {
.release = digi_release,
};
+static struct usb_serial_driver * const serial_drivers[] = {
+ &digi_acceleport_2_device, &digi_acceleport_4_device, NULL
+};
/* Functions */
@@ -995,7 +995,7 @@ static int digi_write(struct tty_struct *tty, struct usb_serial_port *port,
/* return length of new data written, or error */
spin_unlock_irqrestore(&priv->dp_port_lock, flags);
if (ret < 0)
- dev_err(&port->dev,
+ dev_err_console(port,
"%s: usb_submit_urb failed, ret=%d, port=%d\n",
__func__, ret, priv->dp_port_num);
dbg("digi_write: returning %d", ret);
@@ -1065,7 +1065,7 @@ static void digi_write_bulk_callback(struct urb *urb)
spin_unlock(&priv->dp_port_lock);
if (ret && ret != -EPERM)
- dev_err(&port->dev,
+ dev_err_console(port,
"%s: usb_submit_urb failed, ret=%d, port=%d\n",
__func__, ret, priv->dp_port_num);
}
@@ -1580,40 +1580,7 @@ static int digi_read_oob_callback(struct urb *urb)
}
-static int __init digi_init(void)
-{
- int retval;
- retval = usb_serial_register(&digi_acceleport_2_device);
- if (retval)
- goto failed_acceleport_2_device;
- retval = usb_serial_register(&digi_acceleport_4_device);
- if (retval)
- goto failed_acceleport_4_device;
- retval = usb_register(&digi_driver);
- if (retval)
- goto failed_usb_register;
- printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
- DRIVER_DESC "\n");
- return 0;
-failed_usb_register:
- usb_serial_deregister(&digi_acceleport_4_device);
-failed_acceleport_4_device:
- usb_serial_deregister(&digi_acceleport_2_device);
-failed_acceleport_2_device:
- return retval;
-}
-
-static void __exit digi_exit (void)
-{
- usb_deregister(&digi_driver);
- usb_serial_deregister(&digi_acceleport_2_device);
- usb_serial_deregister(&digi_acceleport_4_device);
-}
-
-
-module_init(digi_init);
-module_exit(digi_exit);
-
+module_usb_serial_driver(digi_driver, serial_drivers);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/drivers/usb/serial/empeg.c b/drivers/usb/serial/empeg.c
index aced6817bf9..5b99fc09e32 100644
--- a/drivers/usb/serial/empeg.c
+++ b/drivers/usb/serial/empeg.c
@@ -56,7 +56,6 @@ static struct usb_driver empeg_driver = {
.probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
.id_table = id_table,
- .no_dynamic_id = 1,
};
static struct usb_serial_driver empeg_device = {
@@ -65,7 +64,6 @@ static struct usb_serial_driver empeg_device = {
.name = "empeg",
},
.id_table = id_table,
- .usb_driver = &empeg_driver,
.num_ports = 1,
.bulk_out_size = 256,
.throttle = usb_serial_generic_throttle,
@@ -74,6 +72,10 @@ static struct usb_serial_driver empeg_device = {
.init_termios = empeg_init_termios,
};
+static struct usb_serial_driver * const serial_drivers[] = {
+ &empeg_device, NULL
+};
+
static int empeg_startup(struct usb_serial *serial)
{
int r;
@@ -136,33 +138,7 @@ static void empeg_init_termios(struct tty_struct *tty)
tty_encode_baud_rate(tty, 115200, 115200);
}
-static int __init empeg_init(void)
-{
- int retval;
-
- retval = usb_serial_register(&empeg_device);
- if (retval)
- return retval;
- retval = usb_register(&empeg_driver);
- if (retval) {
- usb_serial_deregister(&empeg_device);
- return retval;
- }
- printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
- DRIVER_DESC "\n");
-
- return 0;
-}
-
-static void __exit empeg_exit(void)
-{
- usb_deregister(&empeg_driver);
- usb_serial_deregister(&empeg_device);
-}
-
-
-module_init(empeg_init);
-module_exit(empeg_exit);
+module_usb_serial_driver(empeg_driver, serial_drivers);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/drivers/usb/serial/f81232.c b/drivers/usb/serial/f81232.c
new file mode 100644
index 00000000000..88c0b196392
--- /dev/null
+++ b/drivers/usb/serial/f81232.c
@@ -0,0 +1,405 @@
+/*
+ * Fintek F81232 USB to serial adaptor driver
+ *
+ * Copyright (C) 2012 Greg Kroah-Hartman (gregkh@linuxfoundation.org)
+ * Copyright (C) 2012 Linux Foundation
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/tty.h>
+#include <linux/tty_driver.h>
+#include <linux/tty_flip.h>
+#include <linux/serial.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/spinlock.h>
+#include <linux/uaccess.h>
+#include <linux/usb.h>
+#include <linux/usb/serial.h>
+
+static bool debug;
+
+static const struct usb_device_id id_table[] = {
+ { USB_DEVICE(0x1934, 0x0706) },
+ { } /* Terminating entry */
+};
+MODULE_DEVICE_TABLE(usb, id_table);
+
+#define CONTROL_DTR 0x01
+#define CONTROL_RTS 0x02
+
+#define UART_STATE 0x08
+#define UART_STATE_TRANSIENT_MASK 0x74
+#define UART_DCD 0x01
+#define UART_DSR 0x02
+#define UART_BREAK_ERROR 0x04
+#define UART_RING 0x08
+#define UART_FRAME_ERROR 0x10
+#define UART_PARITY_ERROR 0x20
+#define UART_OVERRUN_ERROR 0x40
+#define UART_CTS 0x80
+
+struct f81232_private {
+ spinlock_t lock;
+ wait_queue_head_t delta_msr_wait;
+ u8 line_control;
+ u8 line_status;
+};
+
+static void f81232_update_line_status(struct usb_serial_port *port,
+ unsigned char *data,
+ unsigned int actual_length)
+{
+}
+
+static void f81232_read_int_callback(struct urb *urb)
+{
+ struct usb_serial_port *port = urb->context;
+ unsigned char *data = urb->transfer_buffer;
+ unsigned int actual_length = urb->actual_length;
+ int status = urb->status;
+ int retval;
+
+ dbg("%s (%d)", __func__, port->number);
+
+ switch (status) {
+ case 0:
+ /* success */
+ break;
+ case -ECONNRESET:
+ case -ENOENT:
+ case -ESHUTDOWN:
+ /* this urb is terminated, clean up */
+ dbg("%s - urb shutting down with status: %d", __func__,
+ status);
+ return;
+ default:
+ dbg("%s - nonzero urb status received: %d", __func__,
+ status);
+ goto exit;
+ }
+
+ usb_serial_debug_data(debug, &port->dev, __func__,
+ urb->actual_length, urb->transfer_buffer);
+
+ f81232_update_line_status(port, data, actual_length);
+
+exit:
+ retval = usb_submit_urb(urb, GFP_ATOMIC);
+ if (retval)
+ dev_err(&urb->dev->dev,
+ "%s - usb_submit_urb failed with result %d\n",
+ __func__, retval);
+}
+
+static void f81232_process_read_urb(struct urb *urb)
+{
+ struct usb_serial_port *port = urb->context;
+ struct f81232_private *priv = usb_get_serial_port_data(port);
+ struct tty_struct *tty;
+ unsigned char *data = urb->transfer_buffer;
+ char tty_flag = TTY_NORMAL;
+ unsigned long flags;
+ u8 line_status;
+ int i;
+
+ /* update line status */
+ spin_lock_irqsave(&priv->lock, flags);
+ line_status = priv->line_status;
+ priv->line_status &= ~UART_STATE_TRANSIENT_MASK;
+ spin_unlock_irqrestore(&priv->lock, flags);
+ wake_up_interruptible(&priv->delta_msr_wait);
+
+ if (!urb->actual_length)
+ return;
+
+ tty = tty_port_tty_get(&port->port);
+ if (!tty)
+ return;
+
+ /* break takes precedence over parity, */
+ /* which takes precedence over framing errors */
+ if (line_status & UART_BREAK_ERROR)
+ tty_flag = TTY_BREAK;
+ else if (line_status & UART_PARITY_ERROR)
+ tty_flag = TTY_PARITY;
+ else if (line_status & UART_FRAME_ERROR)
+ tty_flag = TTY_FRAME;
+ dbg("%s - tty_flag = %d", __func__, tty_flag);
+
+ /* overrun is special, not associated with a char */
+ if (line_status & UART_OVERRUN_ERROR)
+ tty_insert_flip_char(tty, 0, TTY_OVERRUN);
+
+ if (port->port.console && port->sysrq) {
+ for (i = 0; i < urb->actual_length; ++i)
+ if (!usb_serial_handle_sysrq_char(port, data[i]))
+ tty_insert_flip_char(tty, data[i], tty_flag);
+ } else {
+ tty_insert_flip_string_fixed_flag(tty, data, tty_flag,
+ urb->actual_length);
+ }
+
+ tty_flip_buffer_push(tty);
+ tty_kref_put(tty);
+}
+
+static int set_control_lines(struct usb_device *dev, u8 value)
+{
+ /* FIXME - Stubbed out for now */
+ return 0;
+}
+
+static void f81232_break_ctl(struct tty_struct *tty, int break_state)
+{
+ /* FIXME - Stubbed out for now */
+
+ /*
+ * break_state = -1 to turn on break, and 0 to turn off break
+ * see drivers/char/tty_io.c to see it used.
+ * last_set_data_urb_value NEVER has the break bit set in it.
+ */
+}
+
+static void f81232_set_termios(struct tty_struct *tty,
+ struct usb_serial_port *port, struct ktermios *old_termios)
+{
+ /* FIXME - Stubbed out for now */
+
+ /* Don't change anything if nothing has changed */
+ if (!tty_termios_hw_change(tty->termios, old_termios))
+ return;
+
+ /* Do the real work here... */
+}
+
+static int f81232_tiocmget(struct tty_struct *tty)
+{
+ /* FIXME - Stubbed out for now */
+ return 0;
+}
+
+static int f81232_tiocmset(struct tty_struct *tty,
+ unsigned int set, unsigned int clear)
+{
+ /* FIXME - Stubbed out for now */
+ return 0;
+}
+
+static int f81232_open(struct tty_struct *tty, struct usb_serial_port *port)
+{
+ struct ktermios tmp_termios;
+ int result;
+
+ /* Setup termios */
+ if (tty)
+ f81232_set_termios(tty, port, &tmp_termios);
+
+ dbg("%s - submitting interrupt urb", __func__);
+ result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
+ if (result) {
+ dev_err(&port->dev, "%s - failed submitting interrupt urb,"
+ " error %d\n", __func__, result);
+ return result;
+ }
+
+ result = usb_serial_generic_open(tty, port);
+ if (result) {
+ usb_kill_urb(port->interrupt_in_urb);
+ return result;
+ }
+
+ port->port.drain_delay = 256;
+ return 0;
+}
+
+static void f81232_close(struct usb_serial_port *port)
+{
+ usb_serial_generic_close(port);
+ usb_kill_urb(port->interrupt_in_urb);
+}
+
+static void f81232_dtr_rts(struct usb_serial_port *port, int on)
+{
+ struct f81232_private *priv = usb_get_serial_port_data(port);
+ unsigned long flags;
+ u8 control;
+
+ spin_lock_irqsave(&priv->lock, flags);
+ /* Change DTR and RTS */
+ if (on)
+ priv->line_control |= (CONTROL_DTR | CONTROL_RTS);
+ else
+ priv->line_control &= ~(CONTROL_DTR | CONTROL_RTS);
+ control = priv->line_control;
+ spin_unlock_irqrestore(&priv->lock, flags);
+ set_control_lines(port->serial->dev, control);
+}
+
+static int f81232_carrier_raised(struct usb_serial_port *port)
+{
+ struct f81232_private *priv = usb_get_serial_port_data(port);
+ if (priv->line_status & UART_DCD)
+ return 1;
+ return 0;
+}
+
+static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
+{
+ struct f81232_private *priv = usb_get_serial_port_data(port);
+ unsigned long flags;
+ unsigned int prevstatus;
+ unsigned int status;
+ unsigned int changed;
+
+ spin_lock_irqsave(&priv->lock, flags);
+ prevstatus = priv->line_status;
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ while (1) {
+ interruptible_sleep_on(&priv->delta_msr_wait);
+ /* see if a signal did it */
+ if (signal_pending(current))
+ return -ERESTARTSYS;
+
+ spin_lock_irqsave(&priv->lock, flags);
+ status = priv->line_status;
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ changed = prevstatus ^ status;
+
+ if (((arg & TIOCM_RNG) && (changed & UART_RING)) ||
+ ((arg & TIOCM_DSR) && (changed & UART_DSR)) ||
+ ((arg & TIOCM_CD) && (changed & UART_DCD)) ||
+ ((arg & TIOCM_CTS) && (changed & UART_CTS))) {
+ return 0;
+ }
+ prevstatus = status;
+ }
+ /* NOTREACHED */
+ return 0;
+}
+
+static int f81232_ioctl(struct tty_struct *tty,
+ unsigned int cmd, unsigned long arg)
+{
+ struct serial_struct ser;
+ struct usb_serial_port *port = tty->driver_data;
+ dbg("%s (%d) cmd = 0x%04x", __func__, port->number, cmd);
+
+ switch (cmd) {
+ case TIOCGSERIAL:
+ memset(&ser, 0, sizeof ser);
+ ser.type = PORT_16654;
+ ser.line = port->serial->minor;
+ ser.port = port->number;
+ ser.baud_base = 460800;
+
+ if (copy_to_user((void __user *)arg, &ser, sizeof ser))
+ return -EFAULT;
+
+ return 0;
+
+ case TIOCMIWAIT:
+ dbg("%s (%d) TIOCMIWAIT", __func__, port->number);
+ return wait_modem_info(port, arg);
+ default:
+ dbg("%s not supported = 0x%04x", __func__, cmd);
+ break;
+ }
+ return -ENOIOCTLCMD;
+}
+
+static int f81232_startup(struct usb_serial *serial)
+{
+ struct f81232_private *priv;
+ int i;
+
+ for (i = 0; i < serial->num_ports; ++i) {
+ priv = kzalloc(sizeof(struct f81232_private), GFP_KERNEL);
+ if (!priv)
+ goto cleanup;
+ spin_lock_init(&priv->lock);
+ init_waitqueue_head(&priv->delta_msr_wait);
+ usb_set_serial_port_data(serial->port[i], priv);
+ }
+ return 0;
+
+cleanup:
+ for (--i; i >= 0; --i) {
+ priv = usb_get_serial_port_data(serial->port[i]);
+ kfree(priv);
+ usb_set_serial_port_data(serial->port[i], NULL);
+ }
+ return -ENOMEM;
+}
+
+static void f81232_release(struct usb_serial *serial)
+{
+ int i;
+ struct f81232_private *priv;
+
+ for (i = 0; i < serial->num_ports; ++i) {
+ priv = usb_get_serial_port_data(serial->port[i]);
+ kfree(priv);
+ }
+}
+
+static struct usb_driver f81232_driver = {
+ .name = "f81232",
+ .probe = usb_serial_probe,
+ .disconnect = usb_serial_disconnect,
+ .id_table = id_table,
+ .suspend = usb_serial_suspend,
+ .resume = usb_serial_resume,
+ .no_dynamic_id = 1,
+ .supports_autosuspend = 1,
+};
+
+static struct usb_serial_driver f81232_device = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "f81232",
+ },
+ .id_table = id_table,
+ .usb_driver = &f81232_driver,
+ .num_ports = 1,
+ .bulk_in_size = 256,
+ .bulk_out_size = 256,
+ .open = f81232_open,
+ .close = f81232_close,
+ .dtr_rts = f81232_dtr_rts,
+ .carrier_raised = f81232_carrier_raised,
+ .ioctl = f81232_ioctl,
+ .break_ctl = f81232_break_ctl,
+ .set_termios = f81232_set_termios,
+ .tiocmget = f81232_tiocmget,
+ .tiocmset = f81232_tiocmset,
+ .process_read_urb = f81232_process_read_urb,
+ .read_int_callback = f81232_read_int_callback,
+ .attach = f81232_startup,
+ .release = f81232_release,
+};
+
+static struct usb_serial_driver * const serial_drivers[] = {
+ &f81232_device,
+ NULL,
+};
+
+module_usb_serial_driver(f81232_driver, serial_drivers);
+
+MODULE_DESCRIPTION("Fintek F81232 USB to serial adaptor driver");
+MODULE_AUTHOR("Greg Kroah-Hartman <gregkh@linuxfoundation.org");
+MODULE_LICENSE("GPL v2");
+
+module_param(debug, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Debug enabled or not");
+
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index 01b6404df39..98926260668 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -536,6 +536,10 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_6_PID) },
{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_7_PID) },
{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_8_PID) },
+ { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803R_1_PID) },
+ { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803R_2_PID) },
+ { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803R_3_PID) },
+ { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803R_4_PID) },
{ USB_DEVICE(IDTECH_VID, IDTECH_IDT1221U_PID) },
{ USB_DEVICE(OCT_VID, OCT_US101_PID) },
{ USB_DEVICE(OCT_VID, OCT_DK201_PID) },
@@ -797,6 +801,7 @@ static struct usb_device_id id_table_combined [] = {
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
{ USB_DEVICE(ADI_VID, ADI_GNICEPLUS_PID),
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
+ { USB_DEVICE(HORNBY_VID, HORNBY_ELITE_PID) },
{ USB_DEVICE(JETI_VID, JETI_SPC1201_PID) },
{ USB_DEVICE(MARVELL_VID, MARVELL_SHEEVAPLUG_PID),
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
@@ -805,6 +810,8 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(BAYER_VID, BAYER_CONTOUR_CABLE_PID) },
{ USB_DEVICE(FTDI_VID, MARVELL_OPENRD_PID),
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
+ { USB_DEVICE(FTDI_VID, TI_XDS100V2_PID),
+ .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
{ USB_DEVICE(FTDI_VID, HAMEG_HO820_PID) },
{ USB_DEVICE(FTDI_VID, HAMEG_HO720_PID) },
{ USB_DEVICE(FTDI_VID, HAMEG_HO730_PID) },
@@ -836,11 +843,13 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(FTDI_VID, FTDI_SCIENCESCOPE_LOGBOOKML_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_SCIENCESCOPE_LS_LOGBOOK_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_SCIENCESCOPE_HS_LOGBOOK_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_CINTERION_MC55I_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_DOTEC_PID) },
{ USB_DEVICE(QIHARDWARE_VID, MILKYMISTONE_JTAGSERIAL_PID),
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
{ USB_DEVICE(ST_VID, ST_STMCLT1030_PID),
.driver_info = (kernel_ulong_t)&ftdi_stmclite_quirk },
+ { USB_DEVICE(FTDI_VID, FTDI_RF_R106) },
{ }, /* Optional parameter entry */
{ } /* Terminating entry */
};
@@ -852,7 +861,6 @@ static struct usb_driver ftdi_driver = {
.probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
.id_table = id_table_combined,
- .no_dynamic_id = 1,
};
static const char *ftdi_chip_name[] = {
@@ -910,7 +918,6 @@ static struct usb_serial_driver ftdi_sio_device = {
.name = "ftdi_sio",
},
.description = "FTDI USB Serial Device",
- .usb_driver = &ftdi_driver,
.id_table = id_table_combined,
.num_ports = 1,
.bulk_in_size = 512,
@@ -933,6 +940,10 @@ static struct usb_serial_driver ftdi_sio_device = {
.break_ctl = ftdi_break_ctl,
};
+static struct usb_serial_driver * const serial_drivers[] = {
+ &ftdi_sio_device, NULL
+};
+
#define WDR_TIMEOUT 5000 /* default urb timeout */
#define WDR_SHORT_TIMEOUT 1000 /* shorter urb timeout */
@@ -1333,8 +1344,7 @@ static int set_serial_info(struct tty_struct *tty,
goto check_and_exit;
}
- if ((new_serial.baud_base != priv->baud_base) &&
- (new_serial.baud_base < 9600)) {
+ if (new_serial.baud_base != priv->baud_base) {
mutex_unlock(&priv->cfg_lock);
return -EINVAL;
}
@@ -1759,7 +1769,8 @@ static int ftdi_8u2232c_probe(struct usb_serial *serial)
dbg("%s", __func__);
- if (strcmp(udev->manufacturer, "CALAO Systems") == 0)
+ if ((udev->manufacturer) &&
+ (strcmp(udev->manufacturer, "CALAO Systems") == 0))
return ftdi_jtag_probe(serial);
return 0;
@@ -1824,6 +1835,7 @@ static int ftdi_sio_port_remove(struct usb_serial_port *port)
static int ftdi_open(struct tty_struct *tty, struct usb_serial_port *port)
{
+ struct ktermios dummy;
struct usb_device *dev = port->serial->dev;
struct ftdi_private *priv = usb_get_serial_port_data(port);
int result;
@@ -1842,8 +1854,10 @@ static int ftdi_open(struct tty_struct *tty, struct usb_serial_port *port)
This is same behaviour as serial.c/rs_open() - Kuba */
/* ftdi_set_termios will send usb control messages */
- if (tty)
- ftdi_set_termios(tty, port, tty->termios);
+ if (tty) {
+ memset(&dummy, 0, sizeof(dummy));
+ ftdi_set_termios(tty, port, &dummy);
+ }
/* Start reading from the device */
result = usb_serial_generic_open(tty, port);
@@ -2413,19 +2427,10 @@ static int __init ftdi_init(void)
id_table_combined[i].idVendor = vendor;
id_table_combined[i].idProduct = product;
}
- retval = usb_serial_register(&ftdi_sio_device);
- if (retval)
- goto failed_sio_register;
- retval = usb_register(&ftdi_driver);
- if (retval)
- goto failed_usb_register;
-
- printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
- DRIVER_DESC "\n");
- return 0;
-failed_usb_register:
- usb_serial_deregister(&ftdi_sio_device);
-failed_sio_register:
+ retval = usb_serial_register_drivers(&ftdi_driver, serial_drivers);
+ if (retval == 0)
+ printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+ DRIVER_DESC "\n");
return retval;
}
@@ -2433,8 +2438,7 @@ static void __exit ftdi_exit(void)
{
dbg("%s", __func__);
- usb_deregister(&ftdi_driver);
- usb_serial_deregister(&ftdi_sio_device);
+ usb_serial_deregister_drivers(&ftdi_driver, serial_drivers);
}
diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h
index df1d7da933e..ed74019c5b4 100644
--- a/drivers/usb/serial/ftdi_sio_ids.h
+++ b/drivers/usb/serial/ftdi_sio_ids.h
@@ -39,6 +39,13 @@
/* www.candapter.com Ewert Energy Systems CANdapter device */
#define FTDI_CANDAPTER_PID 0x9F80 /* Product Id */
+/*
+ * Texas Instruments XDS100v2 JTAG / BeagleBone A3
+ * http://processors.wiki.ti.com/index.php/XDS100
+ * http://beagleboard.org/bone
+ */
+#define TI_XDS100V2_PID 0xa6d0
+
#define FTDI_NXTCAM_PID 0xABB8 /* NXTCam for Mindstorms NXT */
/* US Interface Navigator (http://www.usinterface.com/) */
@@ -525,6 +532,12 @@
#define ADI_GNICEPLUS_PID 0xF001
/*
+ * Hornby Elite
+ */
+#define HORNBY_VID 0x04D8
+#define HORNBY_ELITE_PID 0x000A
+
+/*
* RATOC REX-USB60F
*/
#define RATOC_VENDOR_ID 0x0584
@@ -667,6 +680,10 @@
#define SEALEVEL_2803_6_PID 0X2863 /* SeaLINK+8 (2803) Port 6 */
#define SEALEVEL_2803_7_PID 0X2873 /* SeaLINK+8 (2803) Port 7 */
#define SEALEVEL_2803_8_PID 0X2883 /* SeaLINK+8 (2803) Port 8 */
+#define SEALEVEL_2803R_1_PID 0Xa02a /* SeaLINK+8 (2803-ROHS) Port 1+2 */
+#define SEALEVEL_2803R_2_PID 0Xa02b /* SeaLINK+8 (2803-ROHS) Port 3+4 */
+#define SEALEVEL_2803R_3_PID 0Xa02c /* SeaLINK+8 (2803-ROHS) Port 5+6 */
+#define SEALEVEL_2803R_4_PID 0Xa02d /* SeaLINK+8 (2803-ROHS) Port 7+8 */
/*
* JETI SPECTROMETER SPECBOS 1201
@@ -1168,3 +1185,16 @@
*/
/* TagTracer MIFARE*/
#define FTDI_ZEITCONTROL_TAGTRACE_MIFARE_PID 0xF7C0
+
+/*
+ * Rainforest Automation
+ */
+/* ZigBee controller */
+#define FTDI_RF_R106 0x8A28
+
+/*
+ * Product: HCP HIT GPRS modem
+ * Manufacturer: HCP d.o.o.
+ * ATI command output: Cinterion MC55i
+ */
+#define FTDI_CINTERION_MC55I_PID 0xA951
diff --git a/drivers/usb/serial/funsoft.c b/drivers/usb/serial/funsoft.c
index 5d4b099dcf8..4577b360792 100644
--- a/drivers/usb/serial/funsoft.c
+++ b/drivers/usb/serial/funsoft.c
@@ -29,7 +29,6 @@ static struct usb_driver funsoft_driver = {
.probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
.id_table = id_table,
- .no_dynamic_id = 1,
};
static struct usb_serial_driver funsoft_device = {
@@ -38,31 +37,15 @@ static struct usb_serial_driver funsoft_device = {
.name = "funsoft",
},
.id_table = id_table,
- .usb_driver = &funsoft_driver,
.num_ports = 1,
};
-static int __init funsoft_init(void)
-{
- int retval;
-
- retval = usb_serial_register(&funsoft_device);
- if (retval)
- return retval;
- retval = usb_register(&funsoft_driver);
- if (retval)
- usb_serial_deregister(&funsoft_device);
- return retval;
-}
+static struct usb_serial_driver * const serial_drivers[] = {
+ &funsoft_device, NULL
+};
-static void __exit funsoft_exit(void)
-{
- usb_deregister(&funsoft_driver);
- usb_serial_deregister(&funsoft_device);
-}
+module_usb_serial_driver(funsoft_driver, serial_drivers);
-module_init(funsoft_init);
-module_exit(funsoft_exit);
MODULE_LICENSE("GPL");
module_param(debug, bool, S_IRUGO | S_IWUSR);
diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c
index 21343378c32..e8eb6347bf3 100644
--- a/drivers/usb/serial/garmin_gps.c
+++ b/drivers/usb/serial/garmin_gps.c
@@ -224,7 +224,6 @@ static struct usb_driver garmin_driver = {
.probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
.id_table = id_table,
- .no_dynamic_id = 1,
};
@@ -1497,7 +1496,6 @@ static struct usb_serial_driver garmin_device = {
.name = "garmin_gps",
},
.description = "Garmin GPS usb/tty",
- .usb_driver = &garmin_driver,
.id_table = id_table,
.num_ports = 1,
.open = garmin_open,
@@ -1514,40 +1512,11 @@ static struct usb_serial_driver garmin_device = {
.read_int_callback = garmin_read_int_callback,
};
+static struct usb_serial_driver * const serial_drivers[] = {
+ &garmin_device, NULL
+};
-
-static int __init garmin_init(void)
-{
- int retval;
-
- retval = usb_serial_register(&garmin_device);
- if (retval)
- goto failed_garmin_register;
- retval = usb_register(&garmin_driver);
- if (retval)
- goto failed_usb_register;
- printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
- DRIVER_DESC "\n");
-
- return 0;
-failed_usb_register:
- usb_serial_deregister(&garmin_device);
-failed_garmin_register:
- return retval;
-}
-
-
-static void __exit garmin_exit(void)
-{
- usb_deregister(&garmin_driver);
- usb_serial_deregister(&garmin_device);
-}
-
-
-
-
-module_init(garmin_init);
-module_exit(garmin_exit);
+module_usb_serial_driver(garmin_driver, serial_drivers);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
@@ -1557,4 +1526,3 @@ module_param(debug, bool, S_IWUSR | S_IRUGO);
MODULE_PARM_DESC(debug, "Debug enabled or not");
module_param(initial_mode, int, S_IRUGO);
MODULE_PARM_DESC(initial_mode, "Initial mode");
-
diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c
index f7403576f99..664deb63807 100644
--- a/drivers/usb/serial/generic.c
+++ b/drivers/usb/serial/generic.c
@@ -54,7 +54,6 @@ static struct usb_driver generic_driver = {
.probe = generic_probe,
.disconnect = usb_serial_disconnect,
.id_table = generic_serial_ids,
- .no_dynamic_id = 1,
};
/* All of the device info needed for the Generic Serial Converter */
@@ -64,7 +63,6 @@ struct usb_serial_driver usb_serial_generic_device = {
.name = "generic",
},
.id_table = generic_device_ids,
- .usb_driver = &generic_driver,
.num_ports = 1,
.disconnect = usb_serial_generic_disconnect,
.release = usb_serial_generic_release,
@@ -73,6 +71,10 @@ struct usb_serial_driver usb_serial_generic_device = {
.resume = usb_serial_generic_resume,
};
+static struct usb_serial_driver * const serial_drivers[] = {
+ &usb_serial_generic_device, NULL
+};
+
static int generic_probe(struct usb_interface *interface,
const struct usb_device_id *id)
{
@@ -97,13 +99,7 @@ int usb_serial_generic_register(int _debug)
USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_PRODUCT;
/* register our generic driver with ourselves */
- retval = usb_serial_register(&usb_serial_generic_device);
- if (retval)
- goto exit;
- retval = usb_register(&generic_driver);
- if (retval)
- usb_serial_deregister(&usb_serial_generic_device);
-exit:
+ retval = usb_serial_register_drivers(&generic_driver, serial_drivers);
#endif
return retval;
}
@@ -112,8 +108,7 @@ void usb_serial_generic_deregister(void)
{
#ifdef CONFIG_USB_SERIAL_GENERIC
/* remove our generic driver */
- usb_deregister(&generic_driver);
- usb_serial_deregister(&usb_serial_generic_device);
+ usb_serial_deregister_drivers(&generic_driver, serial_drivers);
#endif
}
@@ -217,7 +212,7 @@ retry:
clear_bit(i, &port->write_urbs_free);
result = usb_submit_urb(urb, GFP_ATOMIC);
if (result) {
- dev_err(&port->dev, "%s - error submitting urb: %d\n",
+ dev_err_console(port, "%s - error submitting urb: %d\n",
__func__, result);
set_bit(i, &port->write_urbs_free);
spin_lock_irqsave(&port->lock, flags);
diff --git a/drivers/usb/serial/hp4x.c b/drivers/usb/serial/hp4x.c
index 809379159b0..2563e788c9b 100644
--- a/drivers/usb/serial/hp4x.c
+++ b/drivers/usb/serial/hp4x.c
@@ -41,7 +41,6 @@ static struct usb_driver hp49gp_driver = {
.probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
.id_table = id_table,
- .no_dynamic_id = 1,
};
static struct usb_serial_driver hp49gp_device = {
@@ -50,36 +49,14 @@ static struct usb_serial_driver hp49gp_device = {
.name = "hp4X",
},
.id_table = id_table,
- .usb_driver = &hp49gp_driver,
.num_ports = 1,
};
-static int __init hp49gp_init(void)
-{
- int retval;
- retval = usb_serial_register(&hp49gp_device);
- if (retval)
- goto failed_usb_serial_register;
- retval = usb_register(&hp49gp_driver);
- if (retval)
- goto failed_usb_register;
- printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
- DRIVER_DESC "\n");
- return 0;
-failed_usb_register:
- usb_serial_deregister(&hp49gp_device);
-failed_usb_serial_register:
- return retval;
-}
-
-static void __exit hp49gp_exit(void)
-{
- usb_deregister(&hp49gp_driver);
- usb_serial_deregister(&hp49gp_device);
-}
+static struct usb_serial_driver * const serial_drivers[] = {
+ &hp49gp_device, NULL
+};
-module_init(hp49gp_init);
-module_exit(hp49gp_exit);
+module_usb_serial_driver(hp49gp_driver, serial_drivers);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_VERSION(DRIVER_VERSION);
diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c
index 0497575e479..323e8723571 100644
--- a/drivers/usb/serial/io_edgeport.c
+++ b/drivers/usb/serial/io_edgeport.c
@@ -193,7 +193,8 @@ static const struct divisor_table_entry divisor_table[] = {
/* local variables */
static bool debug;
-static atomic_t CmdUrbs; /* Number of outstanding Command Write Urbs */
+/* Number of outstanding Command Write Urbs */
+static atomic_t CmdUrbs = ATOMIC_INIT(0);
/* local function prototypes */
@@ -1286,7 +1287,7 @@ static void send_more_port_data(struct edgeport_serial *edge_serial,
count = fifo->count;
buffer = kmalloc(count+2, GFP_ATOMIC);
if (buffer == NULL) {
- dev_err(&edge_port->port->dev,
+ dev_err_console(edge_port->port,
"%s - no more kernel memory...\n", __func__);
edge_port->write_in_progress = false;
goto exit_send;
@@ -1331,7 +1332,7 @@ static void send_more_port_data(struct edgeport_serial *edge_serial,
status = usb_submit_urb(urb, GFP_ATOMIC);
if (status) {
/* something went wrong */
- dev_err(&edge_port->port->dev,
+ dev_err_console(edge_port->port,
"%s - usb_submit_urb(write bulk) failed, status = %d, data lost\n",
__func__, status);
edge_port->write_in_progress = false;
@@ -3180,65 +3181,8 @@ static void edge_release(struct usb_serial *serial)
kfree(edge_serial);
}
+module_usb_serial_driver(io_driver, serial_drivers);
-/****************************************************************************
- * edgeport_init
- * This is called by the module subsystem, or on startup to initialize us
- ****************************************************************************/
-static int __init edgeport_init(void)
-{
- int retval;
-
- retval = usb_serial_register(&edgeport_2port_device);
- if (retval)
- goto failed_2port_device_register;
- retval = usb_serial_register(&edgeport_4port_device);
- if (retval)
- goto failed_4port_device_register;
- retval = usb_serial_register(&edgeport_8port_device);
- if (retval)
- goto failed_8port_device_register;
- retval = usb_serial_register(&epic_device);
- if (retval)
- goto failed_epic_device_register;
- retval = usb_register(&io_driver);
- if (retval)
- goto failed_usb_register;
- atomic_set(&CmdUrbs, 0);
- printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
- DRIVER_DESC "\n");
- return 0;
-
-failed_usb_register:
- usb_serial_deregister(&epic_device);
-failed_epic_device_register:
- usb_serial_deregister(&edgeport_8port_device);
-failed_8port_device_register:
- usb_serial_deregister(&edgeport_4port_device);
-failed_4port_device_register:
- usb_serial_deregister(&edgeport_2port_device);
-failed_2port_device_register:
- return retval;
-}
-
-
-/****************************************************************************
- * edgeport_exit
- * Called when the driver is about to be unloaded.
- ****************************************************************************/
-static void __exit edgeport_exit (void)
-{
- usb_deregister(&io_driver);
- usb_serial_deregister(&edgeport_2port_device);
- usb_serial_deregister(&edgeport_4port_device);
- usb_serial_deregister(&edgeport_8port_device);
- usb_serial_deregister(&epic_device);
-}
-
-module_init(edgeport_init);
-module_exit(edgeport_exit);
-
-/* Module information */
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
diff --git a/drivers/usb/serial/io_tables.h b/drivers/usb/serial/io_tables.h
index 178b22eb32b..d0e7c9affb6 100644
--- a/drivers/usb/serial/io_tables.h
+++ b/drivers/usb/serial/io_tables.h
@@ -100,7 +100,6 @@ static struct usb_driver io_driver = {
.probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
.id_table = id_table_combined,
- .no_dynamic_id = 1,
};
static struct usb_serial_driver edgeport_2port_device = {
@@ -109,7 +108,6 @@ static struct usb_serial_driver edgeport_2port_device = {
.name = "edgeport_2",
},
.description = "Edgeport 2 port adapter",
- .usb_driver = &io_driver,
.id_table = edgeport_2port_id_table,
.num_ports = 2,
.open = edge_open,
@@ -139,7 +137,6 @@ static struct usb_serial_driver edgeport_4port_device = {
.name = "edgeport_4",
},
.description = "Edgeport 4 port adapter",
- .usb_driver = &io_driver,
.id_table = edgeport_4port_id_table,
.num_ports = 4,
.open = edge_open,
@@ -169,7 +166,6 @@ static struct usb_serial_driver edgeport_8port_device = {
.name = "edgeport_8",
},
.description = "Edgeport 8 port adapter",
- .usb_driver = &io_driver,
.id_table = edgeport_8port_id_table,
.num_ports = 8,
.open = edge_open,
@@ -199,7 +195,6 @@ static struct usb_serial_driver epic_device = {
.name = "epic",
},
.description = "EPiC device",
- .usb_driver = &io_driver,
.id_table = Epic_port_id_table,
.num_ports = 1,
.open = edge_open,
@@ -223,5 +218,10 @@ static struct usb_serial_driver epic_device = {
.write_bulk_callback = edge_bulk_out_data_callback,
};
+static struct usb_serial_driver * const serial_drivers[] = {
+ &edgeport_2port_device, &edgeport_4port_device,
+ &edgeport_8port_device, &epic_device, NULL
+};
+
#endif
diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c
index 65bf06aa591..40a95a7fe38 100644
--- a/drivers/usb/serial/io_ti.c
+++ b/drivers/usb/serial/io_ti.c
@@ -202,7 +202,6 @@ static struct usb_driver io_driver = {
.probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
.id_table = id_table_combined,
- .no_dynamic_id = 1,
};
@@ -1817,7 +1816,7 @@ static void edge_bulk_out_callback(struct urb *urb)
__func__, status);
return;
default:
- dev_err(&urb->dev->dev, "%s - nonzero write bulk status "
+ dev_err_console(port, "%s - nonzero write bulk status "
"received: %d\n", __func__, status);
}
@@ -2111,7 +2110,7 @@ static void edge_send(struct tty_struct *tty)
/* send the data out the bulk port */
result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
if (result) {
- dev_err(&port->dev,
+ dev_err_console(port,
"%s - failed submitting write urb, error %d\n",
__func__, result);
edge_port->ep_write_urb_in_use = 0;
@@ -2657,15 +2656,7 @@ cleanup:
static void edge_disconnect(struct usb_serial *serial)
{
- int i;
- struct edgeport_port *edge_port;
-
dbg("%s", __func__);
-
- for (i = 0; i < serial->num_ports; ++i) {
- edge_port = usb_get_serial_port_data(serial->port[i]);
- edge_remove_sysfs_attrs(edge_port->port);
- }
}
static void edge_release(struct usb_serial *serial)
@@ -2733,7 +2724,6 @@ static struct usb_serial_driver edgeport_1port_device = {
.name = "edgeport_ti_1",
},
.description = "Edgeport TI 1 port adapter",
- .usb_driver = &io_driver,
.id_table = edgeport_1port_id_table,
.num_ports = 1,
.open = edge_open,
@@ -2744,6 +2734,7 @@ static struct usb_serial_driver edgeport_1port_device = {
.disconnect = edge_disconnect,
.release = edge_release,
.port_probe = edge_create_sysfs_attrs,
+ .port_remove = edge_remove_sysfs_attrs,
.ioctl = edge_ioctl,
.set_termios = edge_set_termios,
.tiocmget = edge_tiocmget,
@@ -2764,7 +2755,6 @@ static struct usb_serial_driver edgeport_2port_device = {
.name = "edgeport_ti_2",
},
.description = "Edgeport TI 2 port adapter",
- .usb_driver = &io_driver,
.id_table = edgeport_2port_id_table,
.num_ports = 2,
.open = edge_open,
@@ -2775,6 +2765,7 @@ static struct usb_serial_driver edgeport_2port_device = {
.disconnect = edge_disconnect,
.release = edge_release,
.port_probe = edge_create_sysfs_attrs,
+ .port_remove = edge_remove_sysfs_attrs,
.ioctl = edge_ioctl,
.set_termios = edge_set_termios,
.tiocmget = edge_tiocmget,
@@ -2788,41 +2779,12 @@ static struct usb_serial_driver edgeport_2port_device = {
.write_bulk_callback = edge_bulk_out_callback,
};
+static struct usb_serial_driver * const serial_drivers[] = {
+ &edgeport_1port_device, &edgeport_2port_device, NULL
+};
-static int __init edgeport_init(void)
-{
- int retval;
- retval = usb_serial_register(&edgeport_1port_device);
- if (retval)
- goto failed_1port_device_register;
- retval = usb_serial_register(&edgeport_2port_device);
- if (retval)
- goto failed_2port_device_register;
- retval = usb_register(&io_driver);
- if (retval)
- goto failed_usb_register;
- printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
- DRIVER_DESC "\n");
- return 0;
-failed_usb_register:
- usb_serial_deregister(&edgeport_2port_device);
-failed_2port_device_register:
- usb_serial_deregister(&edgeport_1port_device);
-failed_1port_device_register:
- return retval;
-}
-
-static void __exit edgeport_exit(void)
-{
- usb_deregister(&io_driver);
- usb_serial_deregister(&edgeport_1port_device);
- usb_serial_deregister(&edgeport_2port_device);
-}
-
-module_init(edgeport_init);
-module_exit(edgeport_exit);
+module_usb_serial_driver(io_driver, serial_drivers);
-/* Module information */
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c
index 06053a920dd..10c02b8b566 100644
--- a/drivers/usb/serial/ipaq.c
+++ b/drivers/usb/serial/ipaq.c
@@ -510,7 +510,6 @@ static struct usb_driver ipaq_driver = {
.probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
.id_table = ipaq_id_table,
- .no_dynamic_id = 1,
};
@@ -521,7 +520,6 @@ static struct usb_serial_driver ipaq_device = {
.name = "ipaq",
},
.description = "PocketPC PDA",
- .usb_driver = &ipaq_driver,
.id_table = ipaq_id_table,
.bulk_in_size = 256,
.bulk_out_size = 256,
@@ -530,6 +528,10 @@ static struct usb_serial_driver ipaq_device = {
.calc_num_ports = ipaq_calc_num_ports,
};
+static struct usb_serial_driver * const serial_drivers[] = {
+ &ipaq_device, NULL
+};
+
static int ipaq_open(struct tty_struct *tty,
struct usb_serial_port *port)
{
@@ -624,30 +626,22 @@ static int ipaq_startup(struct usb_serial *serial)
static int __init ipaq_init(void)
{
int retval;
- retval = usb_serial_register(&ipaq_device);
- if (retval)
- goto failed_usb_serial_register;
+
if (vendor) {
ipaq_id_table[0].idVendor = vendor;
ipaq_id_table[0].idProduct = product;
}
- retval = usb_register(&ipaq_driver);
- if (retval)
- goto failed_usb_register;
-
- printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
- DRIVER_DESC "\n");
- return 0;
-failed_usb_register:
- usb_serial_deregister(&ipaq_device);
-failed_usb_serial_register:
+
+ retval = usb_serial_register_drivers(&ipaq_driver, serial_drivers);
+ if (retval == 0)
+ printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+ DRIVER_DESC "\n");
return retval;
}
static void __exit ipaq_exit(void)
{
- usb_deregister(&ipaq_driver);
- usb_serial_deregister(&ipaq_device);
+ usb_serial_deregister_drivers(&ipaq_driver, serial_drivers);
}
diff --git a/drivers/usb/serial/ipw.c b/drivers/usb/serial/ipw.c
index 6f9356f3f99..76a06406e26 100644
--- a/drivers/usb/serial/ipw.c
+++ b/drivers/usb/serial/ipw.c
@@ -144,7 +144,6 @@ static struct usb_driver usb_ipw_driver = {
.probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
.id_table = usb_ipw_ids,
- .no_dynamic_id = 1,
};
static bool debug;
@@ -318,7 +317,6 @@ static struct usb_serial_driver ipw_device = {
.name = "ipw",
},
.description = "IPWireless converter",
- .usb_driver = &usb_ipw_driver,
.id_table = usb_ipw_ids,
.num_ports = 1,
.disconnect = usb_wwan_disconnect,
@@ -331,33 +329,11 @@ static struct usb_serial_driver ipw_device = {
.write = usb_wwan_write,
};
+static struct usb_serial_driver * const serial_drivers[] = {
+ &ipw_device, NULL
+};
-
-static int __init usb_ipw_init(void)
-{
- int retval;
-
- retval = usb_serial_register(&ipw_device);
- if (retval)
- return retval;
- retval = usb_register(&usb_ipw_driver);
- if (retval) {
- usb_serial_deregister(&ipw_device);
- return retval;
- }
- printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
- DRIVER_DESC "\n");
- return 0;
-}
-
-static void __exit usb_ipw_exit(void)
-{
- usb_deregister(&usb_ipw_driver);
- usb_serial_deregister(&ipw_device);
-}
-
-module_init(usb_ipw_init);
-module_exit(usb_ipw_exit);
+module_usb_serial_driver(usb_ipw_driver, serial_drivers);
/* Module information */
MODULE_AUTHOR(DRIVER_AUTHOR);
diff --git a/drivers/usb/serial/ir-usb.c b/drivers/usb/serial/ir-usb.c
index 84a396e8367..84965cd65c7 100644
--- a/drivers/usb/serial/ir-usb.c
+++ b/drivers/usb/serial/ir-usb.c
@@ -82,7 +82,6 @@ static struct usb_driver ir_driver = {
.probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
.id_table = ir_id_table,
- .no_dynamic_id = 1,
};
static struct usb_serial_driver ir_device = {
@@ -91,7 +90,6 @@ static struct usb_serial_driver ir_device = {
.name = "ir-usb",
},
.description = "IR Dongle",
- .usb_driver = &ir_driver,
.id_table = ir_id_table,
.num_ports = 1,
.set_termios = ir_set_termios,
@@ -101,6 +99,10 @@ static struct usb_serial_driver ir_device = {
.process_read_urb = ir_process_read_urb,
};
+static struct usb_serial_driver * const serial_drivers[] = {
+ &ir_device, NULL
+};
+
static inline void irda_usb_dump_class_desc(struct usb_irda_cs_descriptor *desc)
{
dbg("bLength=%x", desc->bLength);
@@ -445,30 +447,16 @@ static int __init ir_init(void)
ir_device.bulk_out_size = buffer_size;
}
- retval = usb_serial_register(&ir_device);
- if (retval)
- goto failed_usb_serial_register;
-
- retval = usb_register(&ir_driver);
- if (retval)
- goto failed_usb_register;
-
- printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
- DRIVER_DESC "\n");
-
- return 0;
-
-failed_usb_register:
- usb_serial_deregister(&ir_device);
-
-failed_usb_serial_register:
+ retval = usb_serial_register_drivers(&ir_driver, serial_drivers);
+ if (retval == 0)
+ printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+ DRIVER_DESC "\n");
return retval;
}
static void __exit ir_exit(void)
{
- usb_deregister(&ir_driver);
- usb_serial_deregister(&ir_device);
+ usb_serial_deregister_drivers(&ir_driver, serial_drivers);
}
diff --git a/drivers/usb/serial/iuu_phoenix.c b/drivers/usb/serial/iuu_phoenix.c
index 3077a443697..f2192d527db 100644
--- a/drivers/usb/serial/iuu_phoenix.c
+++ b/drivers/usb/serial/iuu_phoenix.c
@@ -56,7 +56,6 @@ static struct usb_driver iuu_driver = {
.probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
.id_table = id_table,
- .no_dynamic_id = 1,
};
/* turbo parameter */
@@ -1274,7 +1273,6 @@ static struct usb_serial_driver iuu_device = {
.name = "iuu_phoenix",
},
.id_table = id_table,
- .usb_driver = &iuu_driver,
.num_ports = 1,
.bulk_in_size = 512,
.bulk_out_size = 512,
@@ -1292,32 +1290,11 @@ static struct usb_serial_driver iuu_device = {
.release = iuu_release,
};
-static int __init iuu_init(void)
-{
- int retval;
- retval = usb_serial_register(&iuu_device);
- if (retval)
- goto failed_usb_serial_register;
- retval = usb_register(&iuu_driver);
- if (retval)
- goto failed_usb_register;
- printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
- DRIVER_DESC "\n");
- return 0;
-failed_usb_register:
- usb_serial_deregister(&iuu_device);
-failed_usb_serial_register:
- return retval;
-}
-
-static void __exit iuu_exit(void)
-{
- usb_deregister(&iuu_driver);
- usb_serial_deregister(&iuu_device);
-}
+static struct usb_serial_driver * const serial_drivers[] = {
+ &iuu_device, NULL
+};
-module_init(iuu_init);
-module_exit(iuu_exit);
+module_usb_serial_driver(iuu_driver, serial_drivers);
MODULE_AUTHOR("Alain Degreffe eczema@ecze.com");
diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c
index 4cc36c76180..a39ddd1b0dc 100644
--- a/drivers/usb/serial/keyspan.c
+++ b/drivers/usb/serial/keyspan.c
@@ -130,53 +130,7 @@ struct keyspan_port_private {
#include "keyspan_usa67msg.h"
-/* Functions used by new usb-serial code. */
-static int __init keyspan_init(void)
-{
- int retval;
- retval = usb_serial_register(&keyspan_pre_device);
- if (retval)
- goto failed_pre_device_register;
- retval = usb_serial_register(&keyspan_1port_device);
- if (retval)
- goto failed_1port_device_register;
- retval = usb_serial_register(&keyspan_2port_device);
- if (retval)
- goto failed_2port_device_register;
- retval = usb_serial_register(&keyspan_4port_device);
- if (retval)
- goto failed_4port_device_register;
- retval = usb_register(&keyspan_driver);
- if (retval)
- goto failed_usb_register;
-
- printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
- DRIVER_DESC "\n");
-
- return 0;
-failed_usb_register:
- usb_serial_deregister(&keyspan_4port_device);
-failed_4port_device_register:
- usb_serial_deregister(&keyspan_2port_device);
-failed_2port_device_register:
- usb_serial_deregister(&keyspan_1port_device);
-failed_1port_device_register:
- usb_serial_deregister(&keyspan_pre_device);
-failed_pre_device_register:
- return retval;
-}
-
-static void __exit keyspan_exit(void)
-{
- usb_deregister(&keyspan_driver);
- usb_serial_deregister(&keyspan_pre_device);
- usb_serial_deregister(&keyspan_1port_device);
- usb_serial_deregister(&keyspan_2port_device);
- usb_serial_deregister(&keyspan_4port_device);
-}
-
-module_init(keyspan_init);
-module_exit(keyspan_exit);
+module_usb_serial_driver(keyspan_driver, serial_drivers);
static void keyspan_break_ctl(struct tty_struct *tty, int break_state)
{
diff --git a/drivers/usb/serial/keyspan.h b/drivers/usb/serial/keyspan.h
index 13fa1d1cc90..622853c9e38 100644
--- a/drivers/usb/serial/keyspan.h
+++ b/drivers/usb/serial/keyspan.h
@@ -492,7 +492,6 @@ static struct usb_driver keyspan_driver = {
.probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
.id_table = keyspan_ids_combined,
- .no_dynamic_id = 1,
};
/* usb_device_id table for the pre-firmware download keyspan devices */
@@ -545,7 +544,6 @@ static struct usb_serial_driver keyspan_pre_device = {
.name = "keyspan_no_firm",
},
.description = "Keyspan - (without firmware)",
- .usb_driver = &keyspan_driver,
.id_table = keyspan_pre_ids,
.num_ports = 1,
.attach = keyspan_fake_startup,
@@ -557,7 +555,6 @@ static struct usb_serial_driver keyspan_1port_device = {
.name = "keyspan_1",
},
.description = "Keyspan 1 port adapter",
- .usb_driver = &keyspan_driver,
.id_table = keyspan_1port_ids,
.num_ports = 1,
.open = keyspan_open,
@@ -580,7 +577,6 @@ static struct usb_serial_driver keyspan_2port_device = {
.name = "keyspan_2",
},
.description = "Keyspan 2 port adapter",
- .usb_driver = &keyspan_driver,
.id_table = keyspan_2port_ids,
.num_ports = 2,
.open = keyspan_open,
@@ -603,7 +599,6 @@ static struct usb_serial_driver keyspan_4port_device = {
.name = "keyspan_4",
},
.description = "Keyspan 4 port adapter",
- .usb_driver = &keyspan_driver,
.id_table = keyspan_4port_ids,
.num_ports = 4,
.open = keyspan_open,
@@ -620,4 +615,9 @@ static struct usb_serial_driver keyspan_4port_device = {
.release = keyspan_release,
};
+static struct usb_serial_driver * const serial_drivers[] = {
+ &keyspan_pre_device, &keyspan_1port_device,
+ &keyspan_2port_device, &keyspan_4port_device, NULL
+};
+
#endif
diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c
index 7c62a704830..693bcdfcb3d 100644
--- a/drivers/usb/serial/keyspan_pda.c
+++ b/drivers/usb/serial/keyspan_pda.c
@@ -91,7 +91,6 @@ static struct usb_driver keyspan_pda_driver = {
.probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
.id_table = id_table_combined,
- .no_dynamic_id = 1,
};
static const struct usb_device_id id_table_std[] = {
@@ -779,7 +778,6 @@ static struct usb_serial_driver keyspan_pda_fake_device = {
.name = "keyspan_pda_pre",
},
.description = "Keyspan PDA - (prerenumeration)",
- .usb_driver = &keyspan_pda_driver,
.id_table = id_table_fake,
.num_ports = 1,
.attach = keyspan_pda_fake_startup,
@@ -793,7 +791,6 @@ static struct usb_serial_driver xircom_pgs_fake_device = {
.name = "xircom_no_firm",
},
.description = "Xircom / Entregra PGS - (prerenumeration)",
- .usb_driver = &keyspan_pda_driver,
.id_table = id_table_fake_xircom,
.num_ports = 1,
.attach = keyspan_pda_fake_startup,
@@ -806,7 +803,6 @@ static struct usb_serial_driver keyspan_pda_device = {
.name = "keyspan_pda",
},
.description = "Keyspan PDA",
- .usb_driver = &keyspan_pda_driver,
.id_table = id_table_std,
.num_ports = 1,
.dtr_rts = keyspan_pda_dtr_rts,
@@ -827,61 +823,18 @@ static struct usb_serial_driver keyspan_pda_device = {
.release = keyspan_pda_release,
};
-
-static int __init keyspan_pda_init(void)
-{
- int retval;
- retval = usb_serial_register(&keyspan_pda_device);
- if (retval)
- goto failed_pda_register;
+static struct usb_serial_driver * const serial_drivers[] = {
+ &keyspan_pda_device,
#ifdef KEYSPAN
- retval = usb_serial_register(&keyspan_pda_fake_device);
- if (retval)
- goto failed_pda_fake_register;
+ &keyspan_pda_fake_device,
#endif
#ifdef XIRCOM
- retval = usb_serial_register(&xircom_pgs_fake_device);
- if (retval)
- goto failed_xircom_register;
-#endif
- retval = usb_register(&keyspan_pda_driver);
- if (retval)
- goto failed_usb_register;
- printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
- DRIVER_DESC "\n");
- return 0;
-failed_usb_register:
-#ifdef XIRCOM
- usb_serial_deregister(&xircom_pgs_fake_device);
-failed_xircom_register:
-#endif /* XIRCOM */
-#ifdef KEYSPAN
- usb_serial_deregister(&keyspan_pda_fake_device);
-#endif
-#ifdef KEYSPAN
-failed_pda_fake_register:
+ &xircom_pgs_fake_device,
#endif
- usb_serial_deregister(&keyspan_pda_device);
-failed_pda_register:
- return retval;
-}
-
-
-static void __exit keyspan_pda_exit(void)
-{
- usb_deregister(&keyspan_pda_driver);
- usb_serial_deregister(&keyspan_pda_device);
-#ifdef KEYSPAN
- usb_serial_deregister(&keyspan_pda_fake_device);
-#endif
-#ifdef XIRCOM
- usb_serial_deregister(&xircom_pgs_fake_device);
-#endif
-}
-
+ NULL
+};
-module_init(keyspan_pda_init);
-module_exit(keyspan_pda_exit);
+module_usb_serial_driver(keyspan_pda_driver, serial_drivers);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
@@ -889,4 +842,3 @@ MODULE_LICENSE("GPL");
module_param(debug, bool, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(debug, "Debug enabled or not");
-
diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c
index fc064e1442c..10f05407e53 100644
--- a/drivers/usb/serial/kl5kusb105.c
+++ b/drivers/usb/serial/kl5kusb105.c
@@ -91,7 +91,6 @@ static struct usb_driver kl5kusb105d_driver = {
.probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
.id_table = id_table,
- .no_dynamic_id = 1,
};
static struct usb_serial_driver kl5kusb105d_device = {
@@ -100,7 +99,6 @@ static struct usb_serial_driver kl5kusb105d_device = {
.name = "kl5kusb105d",
},
.description = "KL5KUSB105D / PalmConnect",
- .usb_driver = &kl5kusb105d_driver,
.id_table = id_table,
.num_ports = 1,
.bulk_out_size = 64,
@@ -118,6 +116,10 @@ static struct usb_serial_driver kl5kusb105d_device = {
.prepare_write_buffer = klsi_105_prepare_write_buffer,
};
+static struct usb_serial_driver * const serial_drivers[] = {
+ &kl5kusb105d_device, NULL
+};
+
struct klsi_105_port_settings {
__u8 pktlen; /* always 5, it seems */
__u8 baudrate;
@@ -690,40 +692,11 @@ static int klsi_105_tiocmset(struct tty_struct *tty,
return retval;
}
-
-static int __init klsi_105_init(void)
-{
- int retval;
- retval = usb_serial_register(&kl5kusb105d_device);
- if (retval)
- goto failed_usb_serial_register;
- retval = usb_register(&kl5kusb105d_driver);
- if (retval)
- goto failed_usb_register;
-
- printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
- DRIVER_DESC "\n");
- return 0;
-failed_usb_register:
- usb_serial_deregister(&kl5kusb105d_device);
-failed_usb_serial_register:
- return retval;
-}
-
-static void __exit klsi_105_exit(void)
-{
- usb_deregister(&kl5kusb105d_driver);
- usb_serial_deregister(&kl5kusb105d_device);
-}
-
-
-module_init(klsi_105_init);
-module_exit(klsi_105_exit);
+module_usb_serial_driver(kl5kusb105d_driver, serial_drivers);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
-
module_param(debug, bool, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(debug, "enable extensive debugging messages");
diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c
index 5d3beeeb5fd..4a9a75eb9b9 100644
--- a/drivers/usb/serial/kobil_sct.c
+++ b/drivers/usb/serial/kobil_sct.c
@@ -38,7 +38,7 @@
#include <linux/ioctl.h>
#include "kobil_sct.h"
-static int debug;
+static bool debug;
/* Version Information */
#define DRIVER_VERSION "21/05/2004"
@@ -90,7 +90,6 @@ static struct usb_driver kobil_driver = {
.probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
.id_table = id_table,
- .no_dynamic_id = 1,
};
@@ -100,7 +99,6 @@ static struct usb_serial_driver kobil_device = {
.name = "kobil",
},
.description = "KOBIL USB smart card terminal",
- .usb_driver = &kobil_driver,
.id_table = id_table,
.num_ports = 1,
.attach = kobil_startup,
@@ -117,6 +115,9 @@ static struct usb_serial_driver kobil_device = {
.read_int_callback = kobil_read_int_callback,
};
+static struct usb_serial_driver * const serial_drivers[] = {
+ &kobil_device, NULL
+};
struct kobil_private {
int write_int_endpoint_address;
@@ -682,35 +683,7 @@ static int kobil_ioctl(struct tty_struct *tty,
}
}
-static int __init kobil_init(void)
-{
- int retval;
- retval = usb_serial_register(&kobil_device);
- if (retval)
- goto failed_usb_serial_register;
- retval = usb_register(&kobil_driver);
- if (retval)
- goto failed_usb_register;
-
- printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
- DRIVER_DESC "\n");
-
- return 0;
-failed_usb_register:
- usb_serial_deregister(&kobil_device);
-failed_usb_serial_register:
- return retval;
-}
-
-
-static void __exit kobil_exit(void)
-{
- usb_deregister(&kobil_driver);
- usb_serial_deregister(&kobil_device);
-}
-
-module_init(kobil_init);
-module_exit(kobil_exit);
+module_usb_serial_driver(kobil_driver, serial_drivers);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c
index 27fa9c8a77b..6edd26130e2 100644
--- a/drivers/usb/serial/mct_u232.c
+++ b/drivers/usb/serial/mct_u232.c
@@ -88,7 +88,6 @@ static struct usb_driver mct_u232_driver = {
.probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
.id_table = id_table_combined,
- .no_dynamic_id = 1,
};
static struct usb_serial_driver mct_u232_device = {
@@ -97,7 +96,6 @@ static struct usb_serial_driver mct_u232_device = {
.name = "mct_u232",
},
.description = "MCT U232",
- .usb_driver = &mct_u232_driver,
.id_table = id_table_combined,
.num_ports = 1,
.open = mct_u232_open,
@@ -116,6 +114,10 @@ static struct usb_serial_driver mct_u232_device = {
.get_icount = mct_u232_get_icount,
};
+static struct usb_serial_driver * const serial_drivers[] = {
+ &mct_u232_device, NULL
+};
+
struct mct_u232_private {
spinlock_t lock;
unsigned int control_state; /* Modem Line Setting (TIOCM) */
@@ -904,33 +906,7 @@ static int mct_u232_get_icount(struct tty_struct *tty,
return 0;
}
-static int __init mct_u232_init(void)
-{
- int retval;
- retval = usb_serial_register(&mct_u232_device);
- if (retval)
- goto failed_usb_serial_register;
- retval = usb_register(&mct_u232_driver);
- if (retval)
- goto failed_usb_register;
- printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
- DRIVER_DESC "\n");
- return 0;
-failed_usb_register:
- usb_serial_deregister(&mct_u232_device);
-failed_usb_serial_register:
- return retval;
-}
-
-
-static void __exit mct_u232_exit(void)
-{
- usb_deregister(&mct_u232_driver);
- usb_serial_deregister(&mct_u232_device);
-}
-
-module_init(mct_u232_init);
-module_exit(mct_u232_exit);
+module_usb_serial_driver(mct_u232_driver, serial_drivers);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c
index 4554ee49e63..bdce8203412 100644
--- a/drivers/usb/serial/mos7720.c
+++ b/drivers/usb/serial/mos7720.c
@@ -1294,7 +1294,7 @@ static int mos7720_write(struct tty_struct *tty, struct usb_serial_port *port,
urb->transfer_buffer = kmalloc(URB_TRANSFER_BUFFER_SIZE,
GFP_KERNEL);
if (urb->transfer_buffer == NULL) {
- dev_err(&port->dev, "%s no more kernel memory...\n",
+ dev_err_console(port, "%s no more kernel memory...\n",
__func__);
goto exit;
}
@@ -1315,7 +1315,7 @@ static int mos7720_write(struct tty_struct *tty, struct usb_serial_port *port,
/* send it down the pipe */
status = usb_submit_urb(urb, GFP_ATOMIC);
if (status) {
- dev_err(&port->dev, "%s - usb_submit_urb(write bulk) failed "
+ dev_err_console(port, "%s - usb_submit_urb(write bulk) failed "
"with status = %d\n", __func__, status);
bytes_sent = status;
goto exit;
@@ -2169,7 +2169,6 @@ static struct usb_driver usb_driver = {
.probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
.id_table = moschip_port_id_table,
- .no_dynamic_id = 1,
};
static struct usb_serial_driver moschip7720_2port_driver = {
@@ -2178,7 +2177,6 @@ static struct usb_serial_driver moschip7720_2port_driver = {
.name = "moschip7720",
},
.description = "Moschip 2 port adapter",
- .usb_driver = &usb_driver,
.id_table = moschip_port_id_table,
.calc_num_ports = mos77xx_calc_num_ports,
.open = mos7720_open,
@@ -2201,44 +2199,12 @@ static struct usb_serial_driver moschip7720_2port_driver = {
.read_int_callback = NULL /* dynamically assigned in probe() */
};
-static int __init moschip7720_init(void)
-{
- int retval;
-
- dbg("%s: Entering ..........", __func__);
-
- /* Register with the usb serial */
- retval = usb_serial_register(&moschip7720_2port_driver);
- if (retval)
- goto failed_port_device_register;
-
- printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
- DRIVER_DESC "\n");
-
- /* Register with the usb */
- retval = usb_register(&usb_driver);
- if (retval)
- goto failed_usb_register;
-
- return 0;
-
-failed_usb_register:
- usb_serial_deregister(&moschip7720_2port_driver);
-
-failed_port_device_register:
- return retval;
-}
-
-static void __exit moschip7720_exit(void)
-{
- usb_deregister(&usb_driver);
- usb_serial_deregister(&moschip7720_2port_driver);
-}
+static struct usb_serial_driver * const serial_drivers[] = {
+ &moschip7720_2port_driver, NULL
+};
-module_init(moschip7720_init);
-module_exit(moschip7720_exit);
+module_usb_serial_driver(usb_driver, serial_drivers);
-/* Module information */
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c
index 03b5e249e95..f7e6e30f53e 100644
--- a/drivers/usb/serial/mos7840.c
+++ b/drivers/usb/serial/mos7840.c
@@ -1509,7 +1509,7 @@ static int mos7840_write(struct tty_struct *tty, struct usb_serial_port *port,
kmalloc(URB_TRANSFER_BUFFER_SIZE, GFP_KERNEL);
if (urb->transfer_buffer == NULL) {
- dev_err(&port->dev, "%s no more kernel memory...\n",
+ dev_err_console(port, "%s no more kernel memory...\n",
__func__);
goto exit;
}
@@ -1535,7 +1535,7 @@ static int mos7840_write(struct tty_struct *tty, struct usb_serial_port *port,
if (status) {
mos7840_port->busy[i] = 0;
- dev_err(&port->dev, "%s - usb_submit_urb(write bulk) failed "
+ dev_err_console(port, "%s - usb_submit_urb(write bulk) failed "
"with status = %d\n", __func__, status);
bytes_sent = status;
goto exit;
@@ -2638,7 +2638,6 @@ static struct usb_driver io_driver = {
.probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
.id_table = moschip_id_table_combined,
- .no_dynamic_id = 1,
};
static struct usb_serial_driver moschip7840_4port_device = {
@@ -2647,7 +2646,6 @@ static struct usb_serial_driver moschip7840_4port_device = {
.name = "mos7840",
},
.description = DRIVER_DESC,
- .usb_driver = &io_driver,
.id_table = moschip_port_id_table,
.num_ports = 4,
.open = mos7840_open,
@@ -2674,57 +2672,12 @@ static struct usb_serial_driver moschip7840_4port_device = {
.read_int_callback = mos7840_interrupt_callback,
};
-/****************************************************************************
- * moschip7840_init
- * This is called by the module subsystem, or on startup to initialize us
- ****************************************************************************/
-static int __init moschip7840_init(void)
-{
- int retval;
-
- dbg("%s", " mos7840_init :entering..........");
-
- /* Register with the usb serial */
- retval = usb_serial_register(&moschip7840_4port_device);
-
- if (retval)
- goto failed_port_device_register;
-
- dbg("%s", "Entering...");
- printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
- DRIVER_DESC "\n");
-
- /* Register with the usb */
- retval = usb_register(&io_driver);
- if (retval == 0) {
- dbg("%s", "Leaving...");
- return 0;
- }
- usb_serial_deregister(&moschip7840_4port_device);
-failed_port_device_register:
- return retval;
-}
-
-/****************************************************************************
- * moschip7840_exit
- * Called when the driver is about to be unloaded.
- ****************************************************************************/
-static void __exit moschip7840_exit(void)
-{
-
- dbg("%s", " mos7840_exit :entering..........");
-
- usb_deregister(&io_driver);
-
- usb_serial_deregister(&moschip7840_4port_device);
-
- dbg("%s", "Entering...");
-}
+static struct usb_serial_driver * const serial_drivers[] = {
+ &moschip7840_4port_device, NULL
+};
-module_init(moschip7840_init);
-module_exit(moschip7840_exit);
+module_usb_serial_driver(io_driver, serial_drivers);
-/* Module information */
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
diff --git a/drivers/usb/serial/moto_modem.c b/drivers/usb/serial/moto_modem.c
index e2bfecc4640..3ab6214b4bb 100644
--- a/drivers/usb/serial/moto_modem.c
+++ b/drivers/usb/serial/moto_modem.c
@@ -36,7 +36,6 @@ static struct usb_driver moto_driver = {
.probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
.id_table = id_table,
- .no_dynamic_id = 1,
};
static struct usb_serial_driver moto_device = {
@@ -45,29 +44,12 @@ static struct usb_serial_driver moto_device = {
.name = "moto-modem",
},
.id_table = id_table,
- .usb_driver = &moto_driver,
.num_ports = 1,
};
-static int __init moto_init(void)
-{
- int retval;
-
- retval = usb_serial_register(&moto_device);
- if (retval)
- return retval;
- retval = usb_register(&moto_driver);
- if (retval)
- usb_serial_deregister(&moto_device);
- return retval;
-}
-
-static void __exit moto_exit(void)
-{
- usb_deregister(&moto_driver);
- usb_serial_deregister(&moto_device);
-}
+static struct usb_serial_driver * const serial_drivers[] = {
+ &moto_device, NULL
+};
-module_init(moto_init);
-module_exit(moto_exit);
+module_usb_serial_driver(moto_driver, serial_drivers);
MODULE_LICENSE("GPL");
diff --git a/drivers/usb/serial/navman.c b/drivers/usb/serial/navman.c
index b28f1db0195..29ab6eb5b53 100644
--- a/drivers/usb/serial/navman.c
+++ b/drivers/usb/serial/navman.c
@@ -35,7 +35,6 @@ static struct usb_driver navman_driver = {
.probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
.id_table = id_table,
- .no_dynamic_id = 1,
};
static void navman_read_int_callback(struct urb *urb)
@@ -122,7 +121,6 @@ static struct usb_serial_driver navman_device = {
.name = "navman",
},
.id_table = id_table,
- .usb_driver = &navman_driver,
.num_ports = 1,
.open = navman_open,
.close = navman_close,
@@ -130,27 +128,12 @@ static struct usb_serial_driver navman_device = {
.read_int_callback = navman_read_int_callback,
};
-static int __init navman_init(void)
-{
- int retval;
-
- retval = usb_serial_register(&navman_device);
- if (retval)
- return retval;
- retval = usb_register(&navman_driver);
- if (retval)
- usb_serial_deregister(&navman_device);
- return retval;
-}
+static struct usb_serial_driver * const serial_drivers[] = {
+ &navman_device, NULL
+};
-static void __exit navman_exit(void)
-{
- usb_deregister(&navman_driver);
- usb_serial_deregister(&navman_device);
-}
+module_usb_serial_driver(navman_driver, serial_drivers);
-module_init(navman_init);
-module_exit(navman_exit);
MODULE_LICENSE("GPL");
module_param(debug, bool, S_IRUGO | S_IWUSR);
diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c
index 8b8d58a2ac1..88dc785bb29 100644
--- a/drivers/usb/serial/omninet.c
+++ b/drivers/usb/serial/omninet.c
@@ -62,7 +62,6 @@ static struct usb_driver omninet_driver = {
.probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
.id_table = id_table,
- .no_dynamic_id = 1,
};
@@ -72,7 +71,6 @@ static struct usb_serial_driver zyxel_omninet_device = {
.name = "omninet",
},
.description = "ZyXEL - omni.net lcd plus usb",
- .usb_driver = &omninet_driver,
.id_table = id_table,
.num_ports = 1,
.attach = omninet_attach,
@@ -86,6 +84,10 @@ static struct usb_serial_driver zyxel_omninet_device = {
.release = omninet_release,
};
+static struct usb_serial_driver * const serial_drivers[] = {
+ &zyxel_omninet_device, NULL
+};
+
/* The protocol.
*
@@ -254,7 +256,7 @@ static int omninet_write(struct tty_struct *tty, struct usb_serial_port *port,
result = usb_submit_urb(wport->write_urb, GFP_ATOMIC);
if (result) {
set_bit(0, &wport->write_urbs_free);
- dev_err(&port->dev,
+ dev_err_console(port,
"%s - failed submitting write urb, error %d\n",
__func__, result);
} else
@@ -319,35 +321,7 @@ static void omninet_release(struct usb_serial *serial)
kfree(usb_get_serial_port_data(port));
}
-
-static int __init omninet_init(void)
-{
- int retval;
- retval = usb_serial_register(&zyxel_omninet_device);
- if (retval)
- goto failed_usb_serial_register;
- retval = usb_register(&omninet_driver);
- if (retval)
- goto failed_usb_register;
- printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
- DRIVER_DESC "\n");
- return 0;
-failed_usb_register:
- usb_serial_deregister(&zyxel_omninet_device);
-failed_usb_serial_register:
- return retval;
-}
-
-
-static void __exit omninet_exit(void)
-{
- usb_deregister(&omninet_driver);
- usb_serial_deregister(&zyxel_omninet_device);
-}
-
-
-module_init(omninet_init);
-module_exit(omninet_exit);
+module_usb_serial_driver(omninet_driver, serial_drivers);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/drivers/usb/serial/opticon.c b/drivers/usb/serial/opticon.c
index 262ded9e076..82cc9d202b8 100644
--- a/drivers/usb/serial/opticon.c
+++ b/drivers/usb/serial/opticon.c
@@ -604,7 +604,6 @@ static struct usb_driver opticon_driver = {
.suspend = opticon_suspend,
.resume = opticon_resume,
.id_table = id_table,
- .no_dynamic_id = 1,
};
static struct usb_serial_driver opticon_device = {
@@ -613,7 +612,6 @@ static struct usb_serial_driver opticon_device = {
.name = "opticon",
},
.id_table = id_table,
- .usb_driver = &opticon_driver,
.num_ports = 1,
.attach = opticon_startup,
.open = opticon_open,
@@ -629,27 +627,12 @@ static struct usb_serial_driver opticon_device = {
.tiocmset = opticon_tiocmset,
};
-static int __init opticon_init(void)
-{
- int retval;
-
- retval = usb_serial_register(&opticon_device);
- if (retval)
- return retval;
- retval = usb_register(&opticon_driver);
- if (retval)
- usb_serial_deregister(&opticon_device);
- return retval;
-}
+static struct usb_serial_driver * const serial_drivers[] = {
+ &opticon_device, NULL
+};
-static void __exit opticon_exit(void)
-{
- usb_deregister(&opticon_driver);
- usb_serial_deregister(&opticon_device);
-}
+module_usb_serial_driver(opticon_driver, serial_drivers);
-module_init(opticon_init);
-module_exit(opticon_exit);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index 420d9857394..005511b2ee0 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -480,6 +480,13 @@ static void option_instat_callback(struct urb *urb);
#define ZD_VENDOR_ID 0x0685
#define ZD_PRODUCT_7000 0x7000
+/* LG products */
+#define LG_VENDOR_ID 0x1004
+#define LG_PRODUCT_L02C 0x618f
+
+/* MediaTek products */
+#define MEDIATEK_VENDOR_ID 0x0e8d
+
/* some devices interfaces need special handling due to a number of reasons */
enum option_blacklist_reason {
OPTION_BLACKLIST_NONE = 0,
@@ -784,7 +791,6 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0012, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&net_intf1_blacklist },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0013, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0014, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MF628, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0016, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0017, 0xff, 0xff, 0xff),
@@ -799,7 +805,6 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0024, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0025, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&net_intf1_blacklist },
- /* { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0026, 0xff, 0xff, 0xff) }, */
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0028, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0029, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0030, 0xff, 0xff, 0xff) },
@@ -824,7 +829,6 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0051, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0052, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&net_intf4_blacklist },
- /* { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0053, 0xff, 0xff, 0xff) }, */
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0054, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0055, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&net_intf1_blacklist },
@@ -832,7 +836,6 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0057, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0058, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&net_intf4_blacklist },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0059, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0061, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0062, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0063, 0xff, 0xff, 0xff),
@@ -842,7 +845,6 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0066, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0067, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0069, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0070, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0076, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0077, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0078, 0xff, 0xff, 0xff) },
@@ -851,6 +853,16 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0083, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0086, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0087, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0088, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0089, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0090, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0091, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0092, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0093, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0094, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0095, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0096, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0097, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0104, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&net_intf4_blacklist },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0105, 0xff, 0xff, 0xff) },
@@ -871,23 +883,18 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0143, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0144, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0145, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0146, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0147, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0148, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0149, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0150, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0151, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0152, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0153, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0154, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0155, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0156, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0157, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0158, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0159, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0160, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0161, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0162, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0164, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0165, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1008, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1010, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1012, 0xff, 0xff, 0xff) },
@@ -1062,17 +1069,27 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1298, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1299, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1300, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2002, 0xff,
+ 0xff, 0xff), .driver_info = (kernel_ulong_t)&zte_k3765_z_blacklist },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2003, 0xff, 0xff, 0xff) },
+
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0014, 0xff, 0xff, 0xff) }, /* ZTE CDMA products */
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0027, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0059, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0060, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0070, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0073, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0094, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0130, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0133, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0141, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2002, 0xff,
- 0xff, 0xff), .driver_info = (kernel_ulong_t)&zte_k3765_z_blacklist },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2003, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0147, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0152, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0168, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0170, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0176, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0178, 0xff, 0xff, 0xff) },
+
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_CDMA_TECH, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC8710, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC2726, 0xff, 0xff, 0xff) },
@@ -1183,6 +1200,11 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLU526) },
{ USB_DEVICE_AND_INTERFACE_INFO(VIETTEL_VENDOR_ID, VIETTEL_PRODUCT_VT1000, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZD_VENDOR_ID, ZD_PRODUCT_7000, 0xff, 0xff, 0xff) },
+ { USB_DEVICE(LG_VENDOR_ID, LG_PRODUCT_L02C) }, /* docomo L-02C modem */
+ { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, 0x00a1, 0xff, 0x00, 0x00) },
+ { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, 0x00a1, 0xff, 0x02, 0x01) },
+ { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, 0x00a2, 0xff, 0x00, 0x00) },
+ { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, 0x00a2, 0xff, 0x02, 0x01) }, /* MediaTek MT6276M modem & app port */
{ } /* Terminating entry */
};
MODULE_DEVICE_TABLE(usb, option_ids);
@@ -1197,7 +1219,6 @@ static struct usb_driver option_driver = {
.supports_autosuspend = 1,
#endif
.id_table = option_ids,
- .no_dynamic_id = 1,
};
/* The card has three separate interfaces, which the serial driver
@@ -1210,7 +1231,6 @@ static struct usb_serial_driver option_1port_device = {
.name = "option1",
},
.description = "GSM modem (1-port)",
- .usb_driver = &option_driver,
.id_table = option_ids,
.num_ports = 1,
.probe = option_probe,
@@ -1234,6 +1254,10 @@ static struct usb_serial_driver option_1port_device = {
#endif
};
+static struct usb_serial_driver * const serial_drivers[] = {
+ &option_1port_device, NULL
+};
+
static bool debug;
/* per port private data */
@@ -1265,36 +1289,7 @@ struct option_port_private {
unsigned long tx_start_time[N_OUT_URB];
};
-/* Functions used by new usb-serial code. */
-static int __init option_init(void)
-{
- int retval;
- retval = usb_serial_register(&option_1port_device);
- if (retval)
- goto failed_1port_device_register;
- retval = usb_register(&option_driver);
- if (retval)
- goto failed_driver_register;
-
- printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
- DRIVER_DESC "\n");
-
- return 0;
-
-failed_driver_register:
- usb_serial_deregister(&option_1port_device);
-failed_1port_device_register:
- return retval;
-}
-
-static void __exit option_exit(void)
-{
- usb_deregister(&option_driver);
- usb_serial_deregister(&option_1port_device);
-}
-
-module_init(option_init);
-module_exit(option_exit);
+module_usb_serial_driver(option_driver, serial_drivers);
static bool is_blacklisted(const u8 ifnum, enum option_blacklist_reason reason,
const struct option_blacklist_info *blacklist)
diff --git a/drivers/usb/serial/oti6858.c b/drivers/usb/serial/oti6858.c
index e287fd32682..5fdc33c6a3c 100644
--- a/drivers/usb/serial/oti6858.c
+++ b/drivers/usb/serial/oti6858.c
@@ -71,7 +71,6 @@ static struct usb_driver oti6858_driver = {
.probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
.id_table = id_table,
- .no_dynamic_id = 1,
};
static bool debug;
@@ -157,7 +156,6 @@ static struct usb_serial_driver oti6858_device = {
.name = "oti6858",
},
.id_table = id_table,
- .usb_driver = &oti6858_driver,
.num_ports = 1,
.open = oti6858_open,
.close = oti6858_close,
@@ -176,6 +174,10 @@ static struct usb_serial_driver oti6858_device = {
.release = oti6858_release,
};
+static struct usb_serial_driver * const serial_drivers[] = {
+ &oti6858_device, NULL
+};
+
struct oti6858_private {
spinlock_t lock;
@@ -302,7 +304,7 @@ static void send_data(struct work_struct *work)
if (count != 0) {
allow = kmalloc(1, GFP_KERNEL);
if (!allow) {
- dev_err(&port->dev, "%s(): kmalloc failed\n",
+ dev_err_console(port, "%s(): kmalloc failed\n",
__func__);
return;
}
@@ -334,7 +336,7 @@ static void send_data(struct work_struct *work)
port->write_urb->transfer_buffer_length = count;
result = usb_submit_urb(port->write_urb, GFP_NOIO);
if (result != 0) {
- dev_err(&port->dev, "%s(): usb_submit_urb() failed"
+ dev_err_console(port, "%s(): usb_submit_urb() failed"
" with error %d\n", __func__, result);
priv->flags.write_urb_in_use = 0;
}
@@ -938,7 +940,7 @@ static void oti6858_write_bulk_callback(struct urb *urb)
port->write_urb->transfer_buffer_length = 1;
result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
if (result) {
- dev_err(&port->dev, "%s(): usb_submit_urb() failed,"
+ dev_err_console(port, "%s(): usb_submit_urb() failed,"
" error %d\n", __func__, result);
} else {
return;
@@ -956,29 +958,7 @@ static void oti6858_write_bulk_callback(struct urb *urb)
}
}
-/* module description and (de)initialization */
-
-static int __init oti6858_init(void)
-{
- int retval;
-
- retval = usb_serial_register(&oti6858_device);
- if (retval == 0) {
- retval = usb_register(&oti6858_driver);
- if (retval)
- usb_serial_deregister(&oti6858_device);
- }
- return retval;
-}
-
-static void __exit oti6858_exit(void)
-{
- usb_deregister(&oti6858_driver);
- usb_serial_deregister(&oti6858_device);
-}
-
-module_init(oti6858_init);
-module_exit(oti6858_exit);
+module_usb_serial_driver(oti6858_driver, serial_drivers);
MODULE_DESCRIPTION(OTI6858_DESCRIPTION);
MODULE_AUTHOR(OTI6858_AUTHOR);
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index 3d8cda57ce7..ff4a174fa5d 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -104,7 +104,6 @@ static struct usb_driver pl2303_driver = {
.id_table = id_table,
.suspend = usb_serial_suspend,
.resume = usb_serial_resume,
- .no_dynamic_id = 1,
.supports_autosuspend = 1,
};
@@ -834,7 +833,6 @@ static struct usb_serial_driver pl2303_device = {
.name = "pl2303",
},
.id_table = id_table,
- .usb_driver = &pl2303_driver,
.num_ports = 1,
.bulk_in_size = 256,
.bulk_out_size = 256,
@@ -853,32 +851,11 @@ static struct usb_serial_driver pl2303_device = {
.release = pl2303_release,
};
-static int __init pl2303_init(void)
-{
- int retval;
-
- retval = usb_serial_register(&pl2303_device);
- if (retval)
- goto failed_usb_serial_register;
- retval = usb_register(&pl2303_driver);
- if (retval)
- goto failed_usb_register;
- printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "\n");
- return 0;
-failed_usb_register:
- usb_serial_deregister(&pl2303_device);
-failed_usb_serial_register:
- return retval;
-}
-
-static void __exit pl2303_exit(void)
-{
- usb_deregister(&pl2303_driver);
- usb_serial_deregister(&pl2303_device);
-}
+static struct usb_serial_driver * const serial_drivers[] = {
+ &pl2303_device, NULL
+};
-module_init(pl2303_init);
-module_exit(pl2303_exit);
+module_usb_serial_driver(pl2303_driver, serial_drivers);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
diff --git a/drivers/usb/serial/qcaux.c b/drivers/usb/serial/qcaux.c
index 30b73e68a90..966245680f5 100644
--- a/drivers/usb/serial/qcaux.c
+++ b/drivers/usb/serial/qcaux.c
@@ -36,6 +36,7 @@
#define UTSTARCOM_PRODUCT_UM175_V1 0x3712
#define UTSTARCOM_PRODUCT_UM175_V2 0x3714
#define UTSTARCOM_PRODUCT_UM175_ALLTEL 0x3715
+#define PANTECH_PRODUCT_UML190_VZW 0x3716
#define PANTECH_PRODUCT_UML290_VZW 0x3718
/* CMOTECH devices */
@@ -67,7 +68,11 @@ static struct usb_device_id id_table[] = {
{ USB_DEVICE_AND_INTERFACE_INFO(LG_VENDOR_ID, LG_PRODUCT_VX4400_6000, 0xff, 0xff, 0x00) },
{ USB_DEVICE_AND_INTERFACE_INFO(SANYO_VENDOR_ID, SANYO_PRODUCT_KATANA_LX, 0xff, 0xff, 0x00) },
{ USB_DEVICE_AND_INTERFACE_INFO(SAMSUNG_VENDOR_ID, SAMSUNG_PRODUCT_U520, 0xff, 0x00, 0x00) },
- { USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, PANTECH_PRODUCT_UML290_VZW, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, PANTECH_PRODUCT_UML190_VZW, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, PANTECH_PRODUCT_UML190_VZW, 0xff, 0xfe, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, PANTECH_PRODUCT_UML290_VZW, 0xff, 0xfd, 0xff) }, /* NMEA */
+ { USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, PANTECH_PRODUCT_UML290_VZW, 0xff, 0xfe, 0xff) }, /* WMC */
+ { USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, PANTECH_PRODUCT_UML290_VZW, 0xff, 0xff, 0xff) }, /* DIAG */
{ },
};
MODULE_DEVICE_TABLE(usb, id_table);
@@ -77,7 +82,6 @@ static struct usb_driver qcaux_driver = {
.probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
.id_table = id_table,
- .no_dynamic_id = 1,
};
static struct usb_serial_driver qcaux_device = {
@@ -86,29 +90,12 @@ static struct usb_serial_driver qcaux_device = {
.name = "qcaux",
},
.id_table = id_table,
- .usb_driver = &qcaux_driver,
.num_ports = 1,
};
-static int __init qcaux_init(void)
-{
- int retval;
-
- retval = usb_serial_register(&qcaux_device);
- if (retval)
- return retval;
- retval = usb_register(&qcaux_driver);
- if (retval)
- usb_serial_deregister(&qcaux_device);
- return retval;
-}
-
-static void __exit qcaux_exit(void)
-{
- usb_deregister(&qcaux_driver);
- usb_serial_deregister(&qcaux_device);
-}
+static struct usb_serial_driver * const serial_drivers[] = {
+ &qcaux_device, NULL
+};
-module_init(qcaux_init);
-module_exit(qcaux_exit);
+module_usb_serial_driver(qcaux_driver, serial_drivers);
MODULE_LICENSE("GPL");
diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c
index 1d5deee3be5..0206b10c9e6 100644
--- a/drivers/usb/serial/qcserial.c
+++ b/drivers/usb/serial/qcserial.c
@@ -24,34 +24,44 @@
static bool debug;
+#define DEVICE_G1K(v, p) \
+ USB_DEVICE(v, p), .driver_info = 1
+
static const struct usb_device_id id_table[] = {
- {USB_DEVICE(0x05c6, 0x9211)}, /* Acer Gobi QDL device */
- {USB_DEVICE(0x05c6, 0x9212)}, /* Acer Gobi Modem Device */
- {USB_DEVICE(0x03f0, 0x1f1d)}, /* HP un2400 Gobi Modem Device */
- {USB_DEVICE(0x03f0, 0x201d)}, /* HP un2400 Gobi QDL Device */
- {USB_DEVICE(0x03f0, 0x371d)}, /* HP un2430 Mobile Broadband Module */
- {USB_DEVICE(0x04da, 0x250d)}, /* Panasonic Gobi Modem device */
- {USB_DEVICE(0x04da, 0x250c)}, /* Panasonic Gobi QDL device */
- {USB_DEVICE(0x413c, 0x8172)}, /* Dell Gobi Modem device */
- {USB_DEVICE(0x413c, 0x8171)}, /* Dell Gobi QDL device */
- {USB_DEVICE(0x1410, 0xa001)}, /* Novatel Gobi Modem device */
- {USB_DEVICE(0x1410, 0xa008)}, /* Novatel Gobi QDL device */
- {USB_DEVICE(0x0b05, 0x1776)}, /* Asus Gobi Modem device */
- {USB_DEVICE(0x0b05, 0x1774)}, /* Asus Gobi QDL device */
- {USB_DEVICE(0x19d2, 0xfff3)}, /* ONDA Gobi Modem device */
- {USB_DEVICE(0x19d2, 0xfff2)}, /* ONDA Gobi QDL device */
- {USB_DEVICE(0x1557, 0x0a80)}, /* OQO Gobi QDL device */
- {USB_DEVICE(0x05c6, 0x9001)}, /* Generic Gobi Modem device */
- {USB_DEVICE(0x05c6, 0x9002)}, /* Generic Gobi Modem device */
- {USB_DEVICE(0x05c6, 0x9202)}, /* Generic Gobi Modem device */
- {USB_DEVICE(0x05c6, 0x9203)}, /* Generic Gobi Modem device */
- {USB_DEVICE(0x05c6, 0x9222)}, /* Generic Gobi Modem device */
- {USB_DEVICE(0x05c6, 0x9008)}, /* Generic Gobi QDL device */
- {USB_DEVICE(0x05c6, 0x9009)}, /* Generic Gobi Modem device */
- {USB_DEVICE(0x05c6, 0x9201)}, /* Generic Gobi QDL device */
- {USB_DEVICE(0x05c6, 0x9221)}, /* Generic Gobi QDL device */
- {USB_DEVICE(0x05c6, 0x9231)}, /* Generic Gobi QDL device */
- {USB_DEVICE(0x1f45, 0x0001)}, /* Unknown Gobi QDL device */
+ /* Gobi 1000 devices */
+ {DEVICE_G1K(0x05c6, 0x9211)}, /* Acer Gobi QDL device */
+ {DEVICE_G1K(0x05c6, 0x9212)}, /* Acer Gobi Modem Device */
+ {DEVICE_G1K(0x03f0, 0x1f1d)}, /* HP un2400 Gobi Modem Device */
+ {DEVICE_G1K(0x03f0, 0x201d)}, /* HP un2400 Gobi QDL Device */
+ {DEVICE_G1K(0x04da, 0x250d)}, /* Panasonic Gobi Modem device */
+ {DEVICE_G1K(0x04da, 0x250c)}, /* Panasonic Gobi QDL device */
+ {DEVICE_G1K(0x413c, 0x8172)}, /* Dell Gobi Modem device */
+ {DEVICE_G1K(0x413c, 0x8171)}, /* Dell Gobi QDL device */
+ {DEVICE_G1K(0x1410, 0xa001)}, /* Novatel Gobi Modem device */
+ {DEVICE_G1K(0x1410, 0xa008)}, /* Novatel Gobi QDL device */
+ {DEVICE_G1K(0x0b05, 0x1776)}, /* Asus Gobi Modem device */
+ {DEVICE_G1K(0x0b05, 0x1774)}, /* Asus Gobi QDL device */
+ {DEVICE_G1K(0x19d2, 0xfff3)}, /* ONDA Gobi Modem device */
+ {DEVICE_G1K(0x19d2, 0xfff2)}, /* ONDA Gobi QDL device */
+ {DEVICE_G1K(0x1557, 0x0a80)}, /* OQO Gobi QDL device */
+ {DEVICE_G1K(0x05c6, 0x9001)}, /* Generic Gobi Modem device */
+ {DEVICE_G1K(0x05c6, 0x9002)}, /* Generic Gobi Modem device */
+ {DEVICE_G1K(0x05c6, 0x9202)}, /* Generic Gobi Modem device */
+ {DEVICE_G1K(0x05c6, 0x9203)}, /* Generic Gobi Modem device */
+ {DEVICE_G1K(0x05c6, 0x9222)}, /* Generic Gobi Modem device */
+ {DEVICE_G1K(0x05c6, 0x9008)}, /* Generic Gobi QDL device */
+ {DEVICE_G1K(0x05c6, 0x9009)}, /* Generic Gobi Modem device */
+ {DEVICE_G1K(0x05c6, 0x9201)}, /* Generic Gobi QDL device */
+ {DEVICE_G1K(0x05c6, 0x9221)}, /* Generic Gobi QDL device */
+ {DEVICE_G1K(0x05c6, 0x9231)}, /* Generic Gobi QDL device */
+ {DEVICE_G1K(0x1f45, 0x0001)}, /* Unknown Gobi QDL device */
+
+ /* Gobi 2000 devices */
+ {USB_DEVICE(0x1410, 0xa010)}, /* Novatel Gobi 2000 QDL device */
+ {USB_DEVICE(0x1410, 0xa011)}, /* Novatel Gobi 2000 QDL device */
+ {USB_DEVICE(0x1410, 0xa012)}, /* Novatel Gobi 2000 QDL device */
+ {USB_DEVICE(0x1410, 0xa013)}, /* Novatel Gobi 2000 QDL device */
+ {USB_DEVICE(0x1410, 0xa014)}, /* Novatel Gobi 2000 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, 0x9208)}, /* Generic Gobi 2000 QDL device */
@@ -86,7 +96,18 @@ static const struct usb_device_id id_table[] = {
{USB_DEVICE(0x16d8, 0x8002)}, /* CMDTech Gobi 2000 Modem device (VU922) */
{USB_DEVICE(0x05c6, 0x9204)}, /* Gobi 2000 QDL device */
{USB_DEVICE(0x05c6, 0x9205)}, /* Gobi 2000 Modem device */
+
+ /* Gobi 3000 devices */
+ {USB_DEVICE(0x03f0, 0x371d)}, /* HP un2430 Gobi 3000 QDL */
+ {USB_DEVICE(0x05c6, 0x920c)}, /* Gobi 3000 QDL */
+ {USB_DEVICE(0x05c6, 0x920d)}, /* Gobi 3000 Composite */
+ {USB_DEVICE(0x1410, 0xa020)}, /* Novatel Gobi 3000 QDL */
+ {USB_DEVICE(0x1410, 0xa021)}, /* Novatel Gobi 3000 Composite */
+ {USB_DEVICE(0x413c, 0x8193)}, /* Dell Gobi 3000 QDL */
+ {USB_DEVICE(0x413c, 0x8194)}, /* Dell Gobi 3000 Composite */
{USB_DEVICE(0x1199, 0x9013)}, /* Sierra Wireless Gobi 3000 Modem device (MC8355) */
+ {USB_DEVICE(0x12D1, 0x14F0)}, /* Sony Gobi 3000 QDL */
+ {USB_DEVICE(0x12D1, 0x14F1)}, /* Sony Gobi 3000 Composite */
{ } /* Terminating entry */
};
MODULE_DEVICE_TABLE(usb, id_table);
@@ -108,8 +129,10 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
int retval = -ENODEV;
__u8 nintf;
__u8 ifnum;
+ bool is_gobi1k = id->driver_info ? true : false;
dbg("%s", __func__);
+ dbg("Is Gobi 1000 = %d", is_gobi1k);
nintf = serial->dev->actconfig->desc.bNumInterfaces;
dbg("Num Interfaces = %d", nintf);
@@ -123,8 +146,6 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
spin_lock_init(&data->susp_lock);
- usb_enable_autosuspend(serial->dev);
-
switch (nintf) {
case 1:
/* QDL mode */
@@ -157,15 +178,25 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
case 3:
case 4:
- /* Composite mode */
- /* ifnum == 0 is a broadband network adapter */
- if (ifnum == 1) {
- /*
- * Diagnostics Monitor (serial line 9600 8N1)
- * Qualcomm DM protocol
- * use "libqcdm" (ModemManager) for communication
- */
- dbg("Diagnostics Monitor found");
+ /* Composite mode; don't bind to the QMI/net interface as that
+ * gets handled by other drivers.
+ */
+
+ /* Gobi 1K USB layout:
+ * 0: serial port (doesn't respond)
+ * 1: serial port (doesn't respond)
+ * 2: AT-capable modem port
+ * 3: QMI/net
+ *
+ * Gobi 2K+ USB layout:
+ * 0: QMI/net
+ * 1: DM/DIAG (use libqcdm from ModemManager for communication)
+ * 2: AT-capable modem port
+ * 3: NMEA
+ */
+
+ if (ifnum == 1 && !is_gobi1k) {
+ dbg("Gobi 2K+ DM/DIAG interface found");
retval = usb_set_interface(serial->dev, ifnum, 0);
if (retval < 0) {
dev_err(&serial->dev->dev,
@@ -184,13 +215,13 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
retval = -ENODEV;
kfree(data);
}
- } else if (ifnum==3) {
+ } else if (ifnum==3 && !is_gobi1k) {
/*
* NMEA (serial line 9600 8N1)
* # echo "\$GPS_START" > /dev/ttyUSBx
* # echo "\$GPS_STOP" > /dev/ttyUSBx
*/
- dbg("NMEA GPS interface found");
+ dbg("Gobi 2K+ NMEA GPS interface found");
retval = usb_set_interface(serial->dev, ifnum, 0);
if (retval < 0) {
dev_err(&serial->dev->dev,
@@ -234,7 +265,6 @@ static struct usb_serial_driver qcdevice = {
},
.description = "Qualcomm USB modem",
.id_table = id_table,
- .usb_driver = &qcdriver,
.num_ports = 1,
.probe = qcprobe,
.open = usb_wwan_open,
@@ -251,31 +281,11 @@ static struct usb_serial_driver qcdevice = {
#endif
};
-static int __init qcinit(void)
-{
- int retval;
-
- retval = usb_serial_register(&qcdevice);
- if (retval)
- return retval;
-
- retval = usb_register(&qcdriver);
- if (retval) {
- usb_serial_deregister(&qcdevice);
- return retval;
- }
-
- return 0;
-}
-
-static void __exit qcexit(void)
-{
- usb_deregister(&qcdriver);
- usb_serial_deregister(&qcdevice);
-}
+static struct usb_serial_driver * const serial_drivers[] = {
+ &qcdevice, NULL
+};
-module_init(qcinit);
-module_exit(qcexit);
+module_usb_serial_driver(qcdriver, serial_drivers);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/drivers/usb/serial/safe_serial.c b/drivers/usb/serial/safe_serial.c
index d074b3740dc..ae4ee30c741 100644
--- a/drivers/usb/serial/safe_serial.c
+++ b/drivers/usb/serial/safe_serial.c
@@ -156,7 +156,6 @@ static struct usb_driver safe_driver = {
.probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
.id_table = id_table,
- .no_dynamic_id = 1,
};
static const __u16 crc10_table[256] = {
@@ -309,16 +308,19 @@ static struct usb_serial_driver safe_device = {
.name = "safe_serial",
},
.id_table = id_table,
- .usb_driver = &safe_driver,
.num_ports = 1,
.process_read_urb = safe_process_read_urb,
.prepare_write_buffer = safe_prepare_write_buffer,
.attach = safe_startup,
};
+static struct usb_serial_driver * const serial_drivers[] = {
+ &safe_device, NULL
+};
+
static int __init safe_init(void)
{
- int i, retval;
+ int i;
printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
DRIVER_DESC "\n");
@@ -337,24 +339,12 @@ static int __init safe_init(void)
}
}
- retval = usb_serial_register(&safe_device);
- if (retval)
- goto failed_usb_serial_register;
- retval = usb_register(&safe_driver);
- if (retval)
- goto failed_usb_register;
-
- return 0;
-failed_usb_register:
- usb_serial_deregister(&safe_device);
-failed_usb_serial_register:
- return retval;
+ return usb_serial_register_drivers(&safe_driver, serial_drivers);
}
static void __exit safe_exit(void)
{
- usb_deregister(&safe_driver);
- usb_serial_deregister(&safe_device);
+ usb_serial_deregister_drivers(&safe_driver, serial_drivers);
}
module_init(safe_init);
diff --git a/drivers/usb/serial/siemens_mpi.c b/drivers/usb/serial/siemens_mpi.c
index 74cd4ccdb3f..46c0430fd38 100644
--- a/drivers/usb/serial/siemens_mpi.c
+++ b/drivers/usb/serial/siemens_mpi.c
@@ -42,37 +42,15 @@ static struct usb_serial_driver siemens_usb_mpi_device = {
.name = "siemens_mpi",
},
.id_table = id_table,
- .usb_driver = &siemens_usb_mpi_driver,
.num_ports = 1,
};
-static int __init siemens_usb_mpi_init(void)
-{
- int retval;
-
- retval = usb_serial_register(&siemens_usb_mpi_device);
- if (retval)
- goto failed_usb_serial_register;
- retval = usb_register(&siemens_usb_mpi_driver);
- if (retval)
- goto failed_usb_register;
- printk(KERN_INFO DRIVER_DESC "\n");
- printk(KERN_INFO DRIVER_VERSION " " DRIVER_AUTHOR "\n");
- return retval;
-failed_usb_register:
- usb_serial_deregister(&siemens_usb_mpi_device);
-failed_usb_serial_register:
- return retval;
-}
+static struct usb_serial_driver * const serial_drivers[] = {
+ &siemens_usb_mpi_device, NULL
+};
-static void __exit siemens_usb_mpi_exit(void)
-{
- usb_deregister(&siemens_usb_mpi_driver);
- usb_serial_deregister(&siemens_usb_mpi_device);
-}
+module_usb_serial_driver(siemens_usb_mpi_driver, serial_drivers);
-module_init(siemens_usb_mpi_init);
-module_exit(siemens_usb_mpi_exit);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c
index fdae0a4407c..f14465a83dd 100644
--- a/drivers/usb/serial/sierra.c
+++ b/drivers/usb/serial/sierra.c
@@ -1084,7 +1084,6 @@ static struct usb_driver sierra_driver = {
.resume = usb_serial_resume,
.reset_resume = sierra_reset_resume,
.id_table = id_table,
- .no_dynamic_id = 1,
.supports_autosuspend = 1,
};
@@ -1095,7 +1094,6 @@ static struct usb_serial_driver sierra_device = {
},
.description = "Sierra USB modem",
.id_table = id_table,
- .usb_driver = &sierra_driver,
.calc_num_ports = sierra_calc_num_ports,
.probe = sierra_probe,
.open = sierra_open,
@@ -1113,38 +1111,11 @@ static struct usb_serial_driver sierra_device = {
.read_int_callback = sierra_instat_callback,
};
-/* Functions used by new usb-serial code. */
-static int __init sierra_init(void)
-{
- int retval;
- retval = usb_serial_register(&sierra_device);
- if (retval)
- goto failed_device_register;
-
-
- retval = usb_register(&sierra_driver);
- if (retval)
- goto failed_driver_register;
-
- printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
- DRIVER_DESC "\n");
-
- return 0;
-
-failed_driver_register:
- usb_serial_deregister(&sierra_device);
-failed_device_register:
- return retval;
-}
-
-static void __exit sierra_exit(void)
-{
- usb_deregister(&sierra_driver);
- usb_serial_deregister(&sierra_device);
-}
+static struct usb_serial_driver * const serial_drivers[] = {
+ &sierra_device, NULL
+};
-module_init(sierra_init);
-module_exit(sierra_exit);
+module_usb_serial_driver(sierra_driver, serial_drivers);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/drivers/usb/serial/spcp8x5.c b/drivers/usb/serial/spcp8x5.c
index d7f5eee18f0..f06c9a8f3d3 100644
--- a/drivers/usb/serial/spcp8x5.c
+++ b/drivers/usb/serial/spcp8x5.c
@@ -156,7 +156,6 @@ static struct usb_driver spcp8x5_driver = {
.probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
.id_table = id_table,
- .no_dynamic_id = 1,
};
@@ -649,7 +648,6 @@ static struct usb_serial_driver spcp8x5_device = {
.name = "SPCP8x5",
},
.id_table = id_table,
- .usb_driver = &spcp8x5_driver,
.num_ports = 1,
.open = spcp8x5_open,
.dtr_rts = spcp8x5_dtr_rts,
@@ -664,32 +662,11 @@ static struct usb_serial_driver spcp8x5_device = {
.process_read_urb = spcp8x5_process_read_urb,
};
-static int __init spcp8x5_init(void)
-{
- int retval;
- retval = usb_serial_register(&spcp8x5_device);
- if (retval)
- goto failed_usb_serial_register;
- retval = usb_register(&spcp8x5_driver);
- if (retval)
- goto failed_usb_register;
- printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
- DRIVER_DESC "\n");
- return 0;
-failed_usb_register:
- usb_serial_deregister(&spcp8x5_device);
-failed_usb_serial_register:
- return retval;
-}
-
-static void __exit spcp8x5_exit(void)
-{
- usb_deregister(&spcp8x5_driver);
- usb_serial_deregister(&spcp8x5_device);
-}
+static struct usb_serial_driver * const serial_drivers[] = {
+ &spcp8x5_device, NULL
+};
-module_init(spcp8x5_init);
-module_exit(spcp8x5_exit);
+module_usb_serial_driver(spcp8x5_driver, serial_drivers);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_VERSION(DRIVER_VERSION);
diff --git a/drivers/usb/serial/ssu100.c b/drivers/usb/serial/ssu100.c
index 7697858d885..3cdc8a52de4 100644
--- a/drivers/usb/serial/ssu100.c
+++ b/drivers/usb/serial/ssu100.c
@@ -70,7 +70,6 @@ static struct usb_driver ssu100_driver = {
.id_table = id_table,
.suspend = usb_serial_suspend,
.resume = usb_serial_resume,
- .no_dynamic_id = 1,
.supports_autosuspend = 1,
};
@@ -677,7 +676,6 @@ static struct usb_serial_driver ssu100_device = {
},
.description = DRIVER_DESC,
.id_table = id_table,
- .usb_driver = &ssu100_driver,
.num_ports = 1,
.open = ssu100_open,
.close = ssu100_close,
@@ -693,41 +691,11 @@ static struct usb_serial_driver ssu100_device = {
.disconnect = usb_serial_generic_disconnect,
};
-static int __init ssu100_init(void)
-{
- int retval;
-
- dbg("%s", __func__);
-
- /* register with usb-serial */
- retval = usb_serial_register(&ssu100_device);
-
- if (retval)
- goto failed_usb_sio_register;
-
- retval = usb_register(&ssu100_driver);
- if (retval)
- goto failed_usb_register;
-
- printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
- DRIVER_DESC "\n");
-
- return 0;
-
-failed_usb_register:
- usb_serial_deregister(&ssu100_device);
-failed_usb_sio_register:
- return retval;
-}
-
-static void __exit ssu100_exit(void)
-{
- usb_deregister(&ssu100_driver);
- usb_serial_deregister(&ssu100_device);
-}
+static struct usb_serial_driver * const serial_drivers[] = {
+ &ssu100_device, NULL
+};
-module_init(ssu100_init);
-module_exit(ssu100_exit);
+module_usb_serial_driver(ssu100_driver, serial_drivers);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
diff --git a/drivers/usb/serial/symbolserial.c b/drivers/usb/serial/symbolserial.c
index 50651cf4fc6..1a5be136e6c 100644
--- a/drivers/usb/serial/symbolserial.c
+++ b/drivers/usb/serial/symbolserial.c
@@ -287,7 +287,6 @@ static struct usb_driver symbol_driver = {
.probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
.id_table = id_table,
- .no_dynamic_id = 1,
};
static struct usb_serial_driver symbol_device = {
@@ -296,7 +295,6 @@ static struct usb_serial_driver symbol_device = {
.name = "symbol",
},
.id_table = id_table,
- .usb_driver = &symbol_driver,
.num_ports = 1,
.attach = symbol_startup,
.open = symbol_open,
@@ -307,27 +305,12 @@ static struct usb_serial_driver symbol_device = {
.unthrottle = symbol_unthrottle,
};
-static int __init symbol_init(void)
-{
- int retval;
-
- retval = usb_serial_register(&symbol_device);
- if (retval)
- return retval;
- retval = usb_register(&symbol_driver);
- if (retval)
- usb_serial_deregister(&symbol_device);
- return retval;
-}
+static struct usb_serial_driver * const serial_drivers[] = {
+ &symbol_device, NULL
+};
-static void __exit symbol_exit(void)
-{
- usb_deregister(&symbol_driver);
- usb_serial_deregister(&symbol_device);
-}
+module_usb_serial_driver(symbol_driver, serial_drivers);
-module_init(symbol_init);
-module_exit(symbol_exit);
MODULE_LICENSE("GPL");
module_param(debug, bool, S_IRUGO | S_IWUSR);
diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c
index 8468eb769a2..ab74123d658 100644
--- a/drivers/usb/serial/ti_usb_3410_5052.c
+++ b/drivers/usb/serial/ti_usb_3410_5052.c
@@ -165,7 +165,7 @@ static unsigned int product_5052_count;
/* the array dimension is the number of default entries plus */
/* TI_EXTRA_VID_PID_COUNT user defined entries plus 1 terminating */
/* null entry */
-static struct usb_device_id ti_id_table_3410[13+TI_EXTRA_VID_PID_COUNT+1] = {
+static struct usb_device_id ti_id_table_3410[14+TI_EXTRA_VID_PID_COUNT+1] = {
{ USB_DEVICE(TI_VENDOR_ID, TI_3410_PRODUCT_ID) },
{ USB_DEVICE(TI_VENDOR_ID, TI_3410_EZ430_ID) },
{ USB_DEVICE(MTS_VENDOR_ID, MTS_GSM_NO_FW_PRODUCT_ID) },
@@ -179,6 +179,7 @@ static struct usb_device_id ti_id_table_3410[13+TI_EXTRA_VID_PID_COUNT+1] = {
{ USB_DEVICE(IBM_VENDOR_ID, IBM_4543_PRODUCT_ID) },
{ USB_DEVICE(IBM_VENDOR_ID, IBM_454B_PRODUCT_ID) },
{ USB_DEVICE(IBM_VENDOR_ID, IBM_454C_PRODUCT_ID) },
+ { USB_DEVICE(ABBOTT_VENDOR_ID, ABBOTT_PRODUCT_ID) },
};
static struct usb_device_id ti_id_table_5052[5+TI_EXTRA_VID_PID_COUNT+1] = {
@@ -188,7 +189,7 @@ static struct usb_device_id ti_id_table_5052[5+TI_EXTRA_VID_PID_COUNT+1] = {
{ USB_DEVICE(TI_VENDOR_ID, TI_5052_FIRMWARE_PRODUCT_ID) },
};
-static struct usb_device_id ti_id_table_combined[17+2*TI_EXTRA_VID_PID_COUNT+1] = {
+static struct usb_device_id ti_id_table_combined[18+2*TI_EXTRA_VID_PID_COUNT+1] = {
{ USB_DEVICE(TI_VENDOR_ID, TI_3410_PRODUCT_ID) },
{ USB_DEVICE(TI_VENDOR_ID, TI_3410_EZ430_ID) },
{ USB_DEVICE(MTS_VENDOR_ID, MTS_GSM_NO_FW_PRODUCT_ID) },
@@ -206,6 +207,7 @@ static struct usb_device_id ti_id_table_combined[17+2*TI_EXTRA_VID_PID_COUNT+1]
{ USB_DEVICE(IBM_VENDOR_ID, IBM_4543_PRODUCT_ID) },
{ USB_DEVICE(IBM_VENDOR_ID, IBM_454B_PRODUCT_ID) },
{ USB_DEVICE(IBM_VENDOR_ID, IBM_454C_PRODUCT_ID) },
+ { USB_DEVICE(ABBOTT_VENDOR_ID, ABBOTT_PRODUCT_ID) },
{ }
};
@@ -214,7 +216,6 @@ static struct usb_driver ti_usb_driver = {
.probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
.id_table = ti_id_table_combined,
- .no_dynamic_id = 1,
};
static struct usb_serial_driver ti_1port_device = {
@@ -223,7 +224,6 @@ static struct usb_serial_driver ti_1port_device = {
.name = "ti_usb_3410_5052_1",
},
.description = "TI USB 3410 1 port adapter",
- .usb_driver = &ti_usb_driver,
.id_table = ti_id_table_3410,
.num_ports = 1,
.attach = ti_startup,
@@ -252,7 +252,6 @@ static struct usb_serial_driver ti_2port_device = {
.name = "ti_usb_3410_5052_2",
},
.description = "TI USB 5052 2 port adapter",
- .usb_driver = &ti_usb_driver,
.id_table = ti_id_table_5052,
.num_ports = 2,
.attach = ti_startup,
@@ -275,6 +274,9 @@ static struct usb_serial_driver ti_2port_device = {
.write_bulk_callback = ti_bulk_out_callback,
};
+static struct usb_serial_driver * const serial_drivers[] = {
+ &ti_1port_device, &ti_2port_device, NULL
+};
/* Module */
@@ -342,36 +344,17 @@ static int __init ti_init(void)
ti_id_table_combined[c].match_flags = USB_DEVICE_ID_MATCH_DEVICE;
}
- ret = usb_serial_register(&ti_1port_device);
- if (ret)
- goto failed_1port;
- ret = usb_serial_register(&ti_2port_device);
- if (ret)
- goto failed_2port;
-
- ret = usb_register(&ti_usb_driver);
- if (ret)
- goto failed_usb;
-
- printk(KERN_INFO KBUILD_MODNAME ": " TI_DRIVER_VERSION ":"
- TI_DRIVER_DESC "\n");
-
- return 0;
-
-failed_usb:
- usb_serial_deregister(&ti_2port_device);
-failed_2port:
- usb_serial_deregister(&ti_1port_device);
-failed_1port:
+ ret = usb_serial_register_drivers(&ti_usb_driver, serial_drivers);
+ if (ret == 0)
+ printk(KERN_INFO KBUILD_MODNAME ": " TI_DRIVER_VERSION ":"
+ TI_DRIVER_DESC "\n");
return ret;
}
static void __exit ti_exit(void)
{
- usb_deregister(&ti_usb_driver);
- usb_serial_deregister(&ti_1port_device);
- usb_serial_deregister(&ti_2port_device);
+ usb_serial_deregister_drivers(&ti_usb_driver, serial_drivers);
}
@@ -1248,7 +1231,6 @@ static void ti_bulk_out_callback(struct urb *urb)
{
struct ti_port *tport = urb->context;
struct usb_serial_port *port = tport->tp_port;
- struct device *dev = &urb->dev->dev;
int status = urb->status;
dbg("%s - port %d", __func__, port->number);
@@ -1266,7 +1248,7 @@ static void ti_bulk_out_callback(struct urb *urb)
wake_up_interruptible(&tport->tp_write_wait);
return;
default:
- dev_err(dev, "%s - nonzero urb status, %d\n",
+ dev_err_console(port, "%s - nonzero urb status, %d\n",
__func__, status);
tport->tp_tdev->td_urb_error = 1;
wake_up_interruptible(&tport->tp_write_wait);
@@ -1335,7 +1317,7 @@ static void ti_send(struct ti_port *tport)
result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
if (result) {
- dev_err(&port->dev, "%s - submit write urb failed, %d\n",
+ dev_err_console(port, "%s - submit write urb failed, %d\n",
__func__, result);
tport->tp_write_urb_in_use = 0;
/* TODO: reschedule ti_send */
diff --git a/drivers/usb/serial/ti_usb_3410_5052.h b/drivers/usb/serial/ti_usb_3410_5052.h
index 2aac1953993..f140f1b9d5c 100644
--- a/drivers/usb/serial/ti_usb_3410_5052.h
+++ b/drivers/usb/serial/ti_usb_3410_5052.h
@@ -49,6 +49,10 @@
#define MTS_MT9234ZBA_PRODUCT_ID 0xF115
#define MTS_MT9234ZBAOLD_PRODUCT_ID 0x0319
+/* Abbott Diabetics vendor and product ids */
+#define ABBOTT_VENDOR_ID 0x1a61
+#define ABBOTT_PRODUCT_ID 0x3410
+
/* Commands */
#define TI_GET_VERSION 0x01
#define TI_GET_PORT_STATUS 0x02
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index 611b206591c..63ba47dbcc7 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -1338,7 +1338,7 @@ static void fixup_generic(struct usb_serial_driver *device)
set_to_generic_if_null(device, prepare_write_buffer);
}
-int usb_serial_register(struct usb_serial_driver *driver)
+static int usb_serial_register(struct usb_serial_driver *driver)
{
int retval;
@@ -1372,10 +1372,8 @@ int usb_serial_register(struct usb_serial_driver *driver)
mutex_unlock(&table_lock);
return retval;
}
-EXPORT_SYMBOL_GPL(usb_serial_register);
-
-void usb_serial_deregister(struct usb_serial_driver *device)
+static void usb_serial_deregister(struct usb_serial_driver *device)
{
printk(KERN_INFO "USB Serial deregistering driver %s\n",
device->description);
@@ -1384,7 +1382,76 @@ void usb_serial_deregister(struct usb_serial_driver *device)
usb_serial_bus_deregister(device);
mutex_unlock(&table_lock);
}
-EXPORT_SYMBOL_GPL(usb_serial_deregister);
+
+/**
+ * usb_serial_register_drivers - register drivers for a usb-serial module
+ * @udriver: usb_driver used for matching devices/interfaces
+ * @serial_drivers: NULL-terminated array of pointers to drivers to be registered
+ *
+ * Registers @udriver and all the drivers in the @serial_drivers array.
+ * Automatically fills in the .no_dynamic_id field in @udriver and
+ * the .usb_driver field in each serial driver.
+ */
+int usb_serial_register_drivers(struct usb_driver *udriver,
+ struct usb_serial_driver * const serial_drivers[])
+{
+ int rc;
+ const struct usb_device_id *saved_id_table;
+ struct usb_serial_driver * const *sd;
+
+ /*
+ * udriver must be registered before any of the serial drivers,
+ * because the store_new_id() routine for the serial drivers (in
+ * bus.c) probes udriver.
+ *
+ * Performance hack: We don't want udriver to be probed until
+ * the serial drivers are registered, because the probe would
+ * simply fail for lack of a matching serial driver.
+ * Therefore save off udriver's id_table until we are all set.
+ */
+ saved_id_table = udriver->id_table;
+ udriver->id_table = NULL;
+
+ udriver->no_dynamic_id = 1;
+ rc = usb_register(udriver);
+ if (rc)
+ return rc;
+
+ for (sd = serial_drivers; *sd; ++sd) {
+ (*sd)->usb_driver = udriver;
+ rc = usb_serial_register(*sd);
+ if (rc)
+ goto failed;
+ }
+
+ /* Now restore udriver's id_table and look for matches */
+ udriver->id_table = saved_id_table;
+ rc = driver_attach(&udriver->drvwrap.driver);
+ return 0;
+
+ failed:
+ while (sd-- > serial_drivers)
+ usb_serial_deregister(*sd);
+ usb_deregister(udriver);
+ return rc;
+}
+EXPORT_SYMBOL_GPL(usb_serial_register_drivers);
+
+/**
+ * usb_serial_deregister_drivers - deregister drivers for a usb-serial module
+ * @udriver: usb_driver to unregister
+ * @serial_drivers: NULL-terminated array of pointers to drivers to be deregistered
+ *
+ * Deregisters @udriver and all the drivers in the @serial_drivers array.
+ */
+void usb_serial_deregister_drivers(struct usb_driver *udriver,
+ struct usb_serial_driver * const serial_drivers[])
+{
+ for (; *serial_drivers; ++serial_drivers)
+ usb_serial_deregister(*serial_drivers);
+ usb_deregister(udriver);
+}
+EXPORT_SYMBOL_GPL(usb_serial_deregister_drivers);
/* Module information */
MODULE_AUTHOR(DRIVER_AUTHOR);
diff --git a/drivers/usb/serial/usb_debug.c b/drivers/usb/serial/usb_debug.c
index 9b632e75321..e3e8995a473 100644
--- a/drivers/usb/serial/usb_debug.c
+++ b/drivers/usb/serial/usb_debug.c
@@ -40,7 +40,6 @@ static struct usb_driver debug_driver = {
.probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
.id_table = id_table,
- .no_dynamic_id = 1,
};
/* This HW really does not support a serial break, so one will be
@@ -74,32 +73,15 @@ static struct usb_serial_driver debug_device = {
.name = "debug",
},
.id_table = id_table,
- .usb_driver = &debug_driver,
.num_ports = 1,
.bulk_out_size = USB_DEBUG_MAX_PACKET_SIZE,
.break_ctl = usb_debug_break_ctl,
.process_read_urb = usb_debug_process_read_urb,
};
-static int __init debug_init(void)
-{
- int retval;
-
- retval = usb_serial_register(&debug_device);
- if (retval)
- return retval;
- retval = usb_register(&debug_driver);
- if (retval)
- usb_serial_deregister(&debug_device);
- return retval;
-}
-
-static void __exit debug_exit(void)
-{
- usb_deregister(&debug_driver);
- usb_serial_deregister(&debug_device);
-}
+static struct usb_serial_driver * const serial_drivers[] = {
+ &debug_device, NULL
+};
-module_init(debug_init);
-module_exit(debug_exit);
+module_usb_serial_driver(debug_driver, serial_drivers);
MODULE_LICENSE("GPL");
diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c
index 210e4b10dc1..71d696474f2 100644
--- a/drivers/usb/serial/visor.c
+++ b/drivers/usb/serial/visor.c
@@ -173,7 +173,6 @@ static struct usb_driver visor_driver = {
.probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
.id_table = id_table_combined,
- .no_dynamic_id = 1,
};
/* All of the device info needed for the Handspring Visor,
@@ -184,7 +183,6 @@ static struct usb_serial_driver handspring_device = {
.name = "visor",
},
.description = "Handspring Visor / Palm OS",
- .usb_driver = &visor_driver,
.id_table = id_table,
.num_ports = 2,
.bulk_out_size = 256,
@@ -205,7 +203,6 @@ static struct usb_serial_driver clie_5_device = {
.name = "clie_5",
},
.description = "Sony Clie 5.0",
- .usb_driver = &visor_driver,
.id_table = clie_id_5_table,
.num_ports = 2,
.bulk_out_size = 256,
@@ -226,7 +223,6 @@ static struct usb_serial_driver clie_3_5_device = {
.name = "clie_3.5",
},
.description = "Sony Clie 3.5",
- .usb_driver = &visor_driver,
.id_table = clie_id_3_5_table,
.num_ports = 1,
.bulk_out_size = 256,
@@ -237,6 +233,10 @@ static struct usb_serial_driver clie_3_5_device = {
.attach = clie_3_5_startup,
};
+static struct usb_serial_driver * const serial_drivers[] = {
+ &handspring_device, &clie_5_device, &clie_3_5_device, NULL
+};
+
/******************************************************************************
* Handspring Visor specific driver functions
******************************************************************************/
@@ -685,38 +685,17 @@ static int __init visor_init(void)
": Adding Palm OS protocol 4.x support for unknown device: 0x%x/0x%x\n",
vendor, product);
}
- retval = usb_serial_register(&handspring_device);
- if (retval)
- goto failed_handspring_register;
- retval = usb_serial_register(&clie_3_5_device);
- if (retval)
- goto failed_clie_3_5_register;
- retval = usb_serial_register(&clie_5_device);
- if (retval)
- goto failed_clie_5_register;
- retval = usb_register(&visor_driver);
- if (retval)
- goto failed_usb_register;
- printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "\n");
- return 0;
-failed_usb_register:
- usb_serial_deregister(&clie_5_device);
-failed_clie_5_register:
- usb_serial_deregister(&clie_3_5_device);
-failed_clie_3_5_register:
- usb_serial_deregister(&handspring_device);
-failed_handspring_register:
+ retval = usb_serial_register_drivers(&visor_driver, serial_drivers);
+ if (retval == 0)
+ printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "\n");
return retval;
}
static void __exit visor_exit (void)
{
- usb_deregister(&visor_driver);
- usb_serial_deregister(&handspring_device);
- usb_serial_deregister(&clie_3_5_device);
- usb_serial_deregister(&clie_5_device);
+ usb_serial_deregister_drivers(&visor_driver, serial_drivers);
}
diff --git a/drivers/usb/serial/vivopay-serial.c b/drivers/usb/serial/vivopay-serial.c
index f719d00972f..078f338b5fe 100644
--- a/drivers/usb/serial/vivopay-serial.c
+++ b/drivers/usb/serial/vivopay-serial.c
@@ -30,7 +30,6 @@ static struct usb_driver vivopay_serial_driver = {
.probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
.id_table = id_table,
- .no_dynamic_id = 1,
};
static struct usb_serial_driver vivopay_serial_device = {
@@ -39,36 +38,14 @@ static struct usb_serial_driver vivopay_serial_device = {
.name = "vivopay-serial",
},
.id_table = id_table,
- .usb_driver = &vivopay_serial_driver,
.num_ports = 1,
};
-static int __init vivopay_serial_init(void)
-{
- int retval;
- retval = usb_serial_register(&vivopay_serial_device);
- if (retval)
- goto failed_usb_serial_register;
- retval = usb_register(&vivopay_serial_driver);
- if (retval)
- goto failed_usb_register;
- printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
- DRIVER_DESC "\n");
- return 0;
-failed_usb_register:
- usb_serial_deregister(&vivopay_serial_device);
-failed_usb_serial_register:
- return retval;
-}
-
-static void __exit vivopay_serial_exit(void)
-{
- usb_deregister(&vivopay_serial_driver);
- usb_serial_deregister(&vivopay_serial_device);
-}
+static struct usb_serial_driver * const serial_drivers[] = {
+ &vivopay_serial_device, NULL
+};
-module_init(vivopay_serial_init);
-module_exit(vivopay_serial_exit);
+module_usb_serial_driver(vivopay_serial_driver, serial_drivers);
MODULE_AUTHOR("Forest Bond <forest.bond@outpostembedded.com>");
MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c
index 7e0acf5c8e3..407e23c8794 100644
--- a/drivers/usb/serial/whiteheat.c
+++ b/drivers/usb/serial/whiteheat.c
@@ -83,7 +83,6 @@ static struct usb_driver whiteheat_driver = {
.probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
.id_table = id_table_combined,
- .no_dynamic_id = 1,
};
/* function prototypes for the Connect Tech WhiteHEAT prerenumeration device */
@@ -121,7 +120,6 @@ static struct usb_serial_driver whiteheat_fake_device = {
.name = "whiteheatnofirm",
},
.description = "Connect Tech - WhiteHEAT - (prerenumeration)",
- .usb_driver = &whiteheat_driver,
.id_table = id_table_prerenumeration,
.num_ports = 1,
.probe = whiteheat_firmware_download,
@@ -134,7 +132,6 @@ static struct usb_serial_driver whiteheat_device = {
.name = "whiteheat",
},
.description = "Connect Tech - WhiteHEAT",
- .usb_driver = &whiteheat_driver,
.id_table = id_table_std,
.num_ports = 4,
.attach = whiteheat_attach,
@@ -155,6 +152,9 @@ static struct usb_serial_driver whiteheat_device = {
.write_bulk_callback = whiteheat_write_callback,
};
+static struct usb_serial_driver * const serial_drivers[] = {
+ &whiteheat_fake_device, &whiteheat_device, NULL
+};
struct whiteheat_command_private {
struct mutex mutex;
@@ -740,7 +740,7 @@ static int whiteheat_write(struct tty_struct *tty,
urb->transfer_buffer_length = bytes;
result = usb_submit_urb(urb, GFP_ATOMIC);
if (result) {
- dev_err(&port->dev,
+ dev_err_console(port,
"%s - failed submitting write urb, error %d\n",
__func__, result);
sent = result;
@@ -1454,44 +1454,7 @@ out:
tty_kref_put(tty);
}
-
-/*****************************************************************************
- * Connect Tech's White Heat module functions
- *****************************************************************************/
-static int __init whiteheat_init(void)
-{
- int retval;
- retval = usb_serial_register(&whiteheat_fake_device);
- if (retval)
- goto failed_fake_register;
- retval = usb_serial_register(&whiteheat_device);
- if (retval)
- goto failed_device_register;
- retval = usb_register(&whiteheat_driver);
- if (retval)
- goto failed_usb_register;
- printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
- DRIVER_DESC "\n");
- return 0;
-failed_usb_register:
- usb_serial_deregister(&whiteheat_device);
-failed_device_register:
- usb_serial_deregister(&whiteheat_fake_device);
-failed_fake_register:
- return retval;
-}
-
-
-static void __exit whiteheat_exit(void)
-{
- usb_deregister(&whiteheat_driver);
- usb_serial_deregister(&whiteheat_fake_device);
- usb_serial_deregister(&whiteheat_device);
-}
-
-
-module_init(whiteheat_init);
-module_exit(whiteheat_exit);
+module_usb_serial_driver(whiteheat_driver, serial_drivers);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/drivers/usb/serial/zio.c b/drivers/usb/serial/zio.c
index f5796727883..9d0bb3752cd 100644
--- a/drivers/usb/serial/zio.c
+++ b/drivers/usb/serial/zio.c
@@ -27,7 +27,6 @@ static struct usb_driver zio_driver = {
.probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
.id_table = id_table,
- .no_dynamic_id = 1,
};
static struct usb_serial_driver zio_device = {
@@ -36,29 +35,12 @@ static struct usb_serial_driver zio_device = {
.name = "zio",
},
.id_table = id_table,
- .usb_driver = &zio_driver,
.num_ports = 1,
};
-static int __init zio_init(void)
-{
- int retval;
-
- retval = usb_serial_register(&zio_device);
- if (retval)
- return retval;
- retval = usb_register(&zio_driver);
- if (retval)
- usb_serial_deregister(&zio_device);
- return retval;
-}
-
-static void __exit zio_exit(void)
-{
- usb_deregister(&zio_driver);
- usb_serial_deregister(&zio_device);
-}
+static struct usb_serial_driver * const serial_drivers[] = {
+ &zio_device, NULL
+};
-module_init(zio_init);
-module_exit(zio_exit);
+module_usb_serial_driver(zio_driver, serial_drivers);
MODULE_LICENSE("GPL");
diff --git a/drivers/usb/storage/alauda.c b/drivers/usb/storage/alauda.c
index 51af2fee2ef..bab8c8fe829 100644
--- a/drivers/usb/storage/alauda.c
+++ b/drivers/usb/storage/alauda.c
@@ -1276,6 +1276,7 @@ static struct usb_driver alauda_driver = {
.post_reset = usb_stor_post_reset,
.id_table = alauda_usb_ids,
.soft_unbind = 1,
+ .no_dynamic_id = 1,
};
module_usb_driver(alauda_driver);
diff --git a/drivers/usb/storage/cypress_atacb.c b/drivers/usb/storage/cypress_atacb.c
index 387cbd47acc..5fe451d16e6 100644
--- a/drivers/usb/storage/cypress_atacb.c
+++ b/drivers/usb/storage/cypress_atacb.c
@@ -272,6 +272,7 @@ static struct usb_driver cypress_driver = {
.post_reset = usb_stor_post_reset,
.id_table = cypress_usb_ids,
.soft_unbind = 1,
+ .no_dynamic_id = 1,
};
module_usb_driver(cypress_driver);
diff --git a/drivers/usb/storage/datafab.c b/drivers/usb/storage/datafab.c
index 15d41f2b3d6..35e9c51e669 100644
--- a/drivers/usb/storage/datafab.c
+++ b/drivers/usb/storage/datafab.c
@@ -751,6 +751,7 @@ static struct usb_driver datafab_driver = {
.post_reset = usb_stor_post_reset,
.id_table = datafab_usb_ids,
.soft_unbind = 1,
+ .no_dynamic_id = 1,
};
module_usb_driver(datafab_driver);
diff --git a/drivers/usb/storage/ene_ub6250.c b/drivers/usb/storage/ene_ub6250.c
index a6ade4071a9..e7e67810950 100644
--- a/drivers/usb/storage/ene_ub6250.c
+++ b/drivers/usb/storage/ene_ub6250.c
@@ -674,7 +674,7 @@ static int sd_scsi_read(struct us_data *us, struct scsi_cmnd *srb)
memset(bcb, 0, sizeof(struct bulk_cb_wrap));
bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
bcb->DataTransferLength = blenByte;
- bcb->Flags = 0x80;
+ bcb->Flags = US_BULK_FLAG_IN;
bcb->CDB[0] = 0xF1;
bcb->CDB[5] = (unsigned char)(bnByte);
bcb->CDB[4] = (unsigned char)(bnByte>>8);
@@ -858,7 +858,7 @@ static int ms_read_readpage(struct us_data *us, u32 PhyBlockAddr,
memset(bcb, 0, sizeof(struct bulk_cb_wrap));
bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
bcb->DataTransferLength = 0x200;
- bcb->Flags = 0x80;
+ bcb->Flags = US_BULK_FLAG_IN;
bcb->CDB[0] = 0xF1;
bcb->CDB[1] = 0x02; /* in init.c ENE_MSInit() is 0x01 */
@@ -877,7 +877,7 @@ static int ms_read_readpage(struct us_data *us, u32 PhyBlockAddr,
memset(bcb, 0, sizeof(struct bulk_cb_wrap));
bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
bcb->DataTransferLength = 0x4;
- bcb->Flags = 0x80;
+ bcb->Flags = US_BULK_FLAG_IN;
bcb->CDB[0] = 0xF1;
bcb->CDB[1] = 0x03;
@@ -1170,7 +1170,7 @@ static int ms_read_eraseblock(struct us_data *us, u32 PhyBlockAddr)
memset(bcb, 0, sizeof(struct bulk_cb_wrap));
bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
bcb->DataTransferLength = 0x200;
- bcb->Flags = 0x80;
+ bcb->Flags = US_BULK_FLAG_IN;
bcb->CDB[0] = 0xF2;
bcb->CDB[1] = 0x06;
bcb->CDB[4] = (unsigned char)(bn);
@@ -1249,7 +1249,7 @@ static int ms_lib_overwrite_extra(struct us_data *us, u32 PhyBlockAddr,
memset(bcb, 0, sizeof(struct bulk_cb_wrap));
bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
bcb->DataTransferLength = 0x4;
- bcb->Flags = 0x80;
+ bcb->Flags = US_BULK_FLAG_IN;
bcb->CDB[0] = 0xF2;
bcb->CDB[1] = 0x05;
bcb->CDB[5] = (unsigned char)(PageNum);
@@ -1331,7 +1331,7 @@ static int ms_lib_read_extra(struct us_data *us, u32 PhyBlock,
memset(bcb, 0, sizeof(struct bulk_cb_wrap));
bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
bcb->DataTransferLength = 0x4;
- bcb->Flags = 0x80;
+ bcb->Flags = US_BULK_FLAG_IN;
bcb->CDB[0] = 0xF1;
bcb->CDB[1] = 0x03;
bcb->CDB[5] = (unsigned char)(PageNum);
@@ -1533,7 +1533,7 @@ static int ms_lib_read_extrablock(struct us_data *us, u32 PhyBlock,
memset(bcb, 0, sizeof(struct bulk_cb_wrap));
bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
bcb->DataTransferLength = 0x4 * blen;
- bcb->Flags = 0x80;
+ bcb->Flags = US_BULK_FLAG_IN;
bcb->CDB[0] = 0xF1;
bcb->CDB[1] = 0x03;
bcb->CDB[5] = (unsigned char)(PageNum);
@@ -1650,7 +1650,7 @@ static int ms_scsi_read(struct us_data *us, struct scsi_cmnd *srb)
memset(bcb, 0, sizeof(struct bulk_cb_wrap));
bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
bcb->DataTransferLength = blenByte;
- bcb->Flags = 0x80;
+ bcb->Flags = US_BULK_FLAG_IN;
bcb->CDB[0] = 0xF1;
bcb->CDB[1] = 0x02;
bcb->CDB[5] = (unsigned char)(bn);
@@ -1694,7 +1694,7 @@ static int ms_scsi_read(struct us_data *us, struct scsi_cmnd *srb)
memset(bcb, 0, sizeof(struct bulk_cb_wrap));
bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
bcb->DataTransferLength = 0x200 * len;
- bcb->Flags = 0x80;
+ bcb->Flags = US_BULK_FLAG_IN;
bcb->CDB[0] = 0xF1;
bcb->CDB[1] = 0x02;
bcb->CDB[5] = (unsigned char)(blkno);
@@ -1827,7 +1827,7 @@ static int ene_get_card_type(struct us_data *us, u16 index, void *buf)
memset(bcb, 0, sizeof(struct bulk_cb_wrap));
bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
bcb->DataTransferLength = 0x01;
- bcb->Flags = 0x80;
+ bcb->Flags = US_BULK_FLAG_IN;
bcb->CDB[0] = 0xED;
bcb->CDB[2] = (unsigned char)(index>>8);
bcb->CDB[3] = (unsigned char)index;
@@ -2083,7 +2083,7 @@ static int ene_ms_init(struct us_data *us)
memset(bcb, 0, sizeof(struct bulk_cb_wrap));
bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
bcb->DataTransferLength = 0x200;
- bcb->Flags = 0x80;
+ bcb->Flags = US_BULK_FLAG_IN;
bcb->CDB[0] = 0xF1;
bcb->CDB[1] = 0x01;
@@ -2134,7 +2134,7 @@ static int ene_sd_init(struct us_data *us)
memset(bcb, 0, sizeof(struct bulk_cb_wrap));
bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
- bcb->Flags = 0x80;
+ bcb->Flags = US_BULK_FLAG_IN;
bcb->CDB[0] = 0xF2;
result = ene_send_scsi_cmd(us, FDIR_READ, NULL, 0);
@@ -2153,7 +2153,7 @@ static int ene_sd_init(struct us_data *us)
memset(bcb, 0, sizeof(struct bulk_cb_wrap));
bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
bcb->DataTransferLength = 0x200;
- bcb->Flags = 0x80;
+ bcb->Flags = US_BULK_FLAG_IN;
bcb->CDB[0] = 0xF1;
result = ene_send_scsi_cmd(us, FDIR_READ, &buf, 0);
@@ -2407,6 +2407,7 @@ static struct usb_driver ene_ub6250_driver = {
.post_reset = usb_stor_post_reset,
.id_table = ene_ub6250_usb_ids,
.soft_unbind = 1,
+ .no_dynamic_id = 1,
};
module_usb_driver(ene_ub6250_driver);
diff --git a/drivers/usb/storage/freecom.c b/drivers/usb/storage/freecom.c
index fa161574847..042cf9ef315 100644
--- a/drivers/usb/storage/freecom.c
+++ b/drivers/usb/storage/freecom.c
@@ -553,6 +553,7 @@ static struct usb_driver freecom_driver = {
.post_reset = usb_stor_post_reset,
.id_table = freecom_usb_ids,
.soft_unbind = 1,
+ .no_dynamic_id = 1,
};
module_usb_driver(freecom_driver);
diff --git a/drivers/usb/storage/isd200.c b/drivers/usb/storage/isd200.c
index bd550270083..31fa24e7e68 100644
--- a/drivers/usb/storage/isd200.c
+++ b/drivers/usb/storage/isd200.c
@@ -1566,6 +1566,7 @@ static struct usb_driver isd200_driver = {
.post_reset = usb_stor_post_reset,
.id_table = isd200_usb_ids,
.soft_unbind = 1,
+ .no_dynamic_id = 1,
};
module_usb_driver(isd200_driver);
diff --git a/drivers/usb/storage/jumpshot.c b/drivers/usb/storage/jumpshot.c
index a19211b5c26..e3b97383186 100644
--- a/drivers/usb/storage/jumpshot.c
+++ b/drivers/usb/storage/jumpshot.c
@@ -677,6 +677,7 @@ static struct usb_driver jumpshot_driver = {
.post_reset = usb_stor_post_reset,
.id_table = jumpshot_usb_ids,
.soft_unbind = 1,
+ .no_dynamic_id = 1,
};
module_usb_driver(jumpshot_driver);
diff --git a/drivers/usb/storage/karma.c b/drivers/usb/storage/karma.c
index e720f8ebdf9..a8708eae978 100644
--- a/drivers/usb/storage/karma.c
+++ b/drivers/usb/storage/karma.c
@@ -230,6 +230,7 @@ static struct usb_driver karma_driver = {
.post_reset = usb_stor_post_reset,
.id_table = karma_usb_ids,
.soft_unbind = 1,
+ .no_dynamic_id = 1,
};
module_usb_driver(karma_driver);
diff --git a/drivers/usb/storage/onetouch.c b/drivers/usb/storage/onetouch.c
index d75155c3820..886567a3806 100644
--- a/drivers/usb/storage/onetouch.c
+++ b/drivers/usb/storage/onetouch.c
@@ -312,6 +312,7 @@ static struct usb_driver onetouch_driver = {
.post_reset = usb_stor_post_reset,
.id_table = onetouch_usb_ids,
.soft_unbind = 1,
+ .no_dynamic_id = 1,
};
module_usb_driver(onetouch_driver);
diff --git a/drivers/usb/storage/realtek_cr.c b/drivers/usb/storage/realtek_cr.c
index 1f62723ef1a..63cf2822e29 100644
--- a/drivers/usb/storage/realtek_cr.c
+++ b/drivers/usb/storage/realtek_cr.c
@@ -219,7 +219,7 @@ static int rts51x_bulk_transport(struct us_data *us, u8 lun,
/* set up the command wrapper */
bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
bcb->DataTransferLength = cpu_to_le32(buf_len);
- bcb->Flags = (dir == DMA_FROM_DEVICE) ? 1 << 7 : 0;
+ bcb->Flags = (dir == DMA_FROM_DEVICE) ? US_BULK_FLAG_IN : 0;
bcb->Tag = ++us->tag;
bcb->Lun = lun;
bcb->Length = cmd_len;
@@ -305,7 +305,7 @@ static int rts51x_bulk_transport_special(struct us_data *us, u8 lun,
/* set up the command wrapper */
bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
bcb->DataTransferLength = cpu_to_le32(buf_len);
- bcb->Flags = (dir == DMA_FROM_DEVICE) ? 1 << 7 : 0;
+ bcb->Flags = (dir == DMA_FROM_DEVICE) ? US_BULK_FLAG_IN : 0;
bcb->Tag = ++us->tag;
bcb->Lun = lun;
bcb->Length = cmd_len;
@@ -507,9 +507,14 @@ static int __do_config_autodelink(struct us_data *us, u8 *data, u16 len)
{
int retval;
u8 cmnd[12] = {0};
+ u8 *buf;
US_DEBUGP("%s, addr = 0xfe47, len = %d\n", __FUNCTION__, len);
+ buf = kmemdup(data, len, GFP_NOIO);
+ if (!buf)
+ return USB_STOR_TRANSPORT_ERROR;
+
cmnd[0] = 0xF0;
cmnd[1] = 0x0E;
cmnd[2] = 0xfe;
@@ -517,7 +522,8 @@ static int __do_config_autodelink(struct us_data *us, u8 *data, u16 len)
cmnd[4] = (u8)(len >> 8);
cmnd[5] = (u8)len;
- retval = rts51x_bulk_transport_special(us, 0, cmnd, 12, data, len, DMA_TO_DEVICE, NULL);
+ retval = rts51x_bulk_transport_special(us, 0, cmnd, 12, buf, len, DMA_TO_DEVICE, NULL);
+ kfree(buf);
if (retval != USB_STOR_TRANSPORT_GOOD) {
return -EIO;
}
@@ -789,7 +795,7 @@ static void rts51x_suspend_timer_fn(unsigned long data)
rts51x_set_stat(chip, RTS51X_STAT_SS);
/* ignore mass storage interface's children */
pm_suspend_ignore_children(&us->pusb_intf->dev, true);
- usb_autopm_put_interface(us->pusb_intf);
+ usb_autopm_put_interface_async(us->pusb_intf);
US_DEBUGP("%s: RTS51X_STAT_SS 01,"
"intf->pm_usage_cnt:%d, power.usage:%d\n",
__func__,
@@ -1100,6 +1106,7 @@ static struct usb_driver realtek_cr_driver = {
.id_table = realtek_cr_ids,
.soft_unbind = 1,
.supports_autosuspend = 1,
+ .no_dynamic_id = 1,
};
module_usb_driver(realtek_cr_driver);
diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
index 13b8bcdf3db..a324a5d21e9 100644
--- a/drivers/usb/storage/scsiglue.c
+++ b/drivers/usb/storage/scsiglue.c
@@ -78,8 +78,6 @@ static const char* host_info(struct Scsi_Host *host)
static int slave_alloc (struct scsi_device *sdev)
{
- struct us_data *us = host_to_us(sdev->host);
-
/*
* Set the INQUIRY transfer length to 36. We don't use any of
* the extra data and many devices choke if asked for more or
@@ -104,18 +102,6 @@ static int slave_alloc (struct scsi_device *sdev)
*/
blk_queue_update_dma_alignment(sdev->request_queue, (512 - 1));
- /*
- * The UFI spec treates the Peripheral Qualifier bits in an
- * INQUIRY result as reserved and requires devices to set them
- * to 0. However the SCSI spec requires these bits to be set
- * to 3 to indicate when a LUN is not present.
- *
- * Let the scanning code know if this target merely sets
- * Peripheral Device Type to 0x1f to indicate no LUN.
- */
- if (us->subclass == USB_SC_UFI)
- sdev->sdev_target->pdt_1f_for_no_lun = 1;
-
return 0;
}
@@ -197,6 +183,9 @@ static int slave_configure(struct scsi_device *sdev)
* page x08, so we will skip it. */
sdev->skip_ms_page_8 = 1;
+ /* Some devices don't handle VPD pages correctly */
+ sdev->skip_vpd_pages = 1;
+
/* Some disks return the total number of blocks in response
* to READ CAPACITY rather than the highest block number.
* If this device makes that mistake, tell the sd driver. */
@@ -217,16 +206,6 @@ static int slave_configure(struct scsi_device *sdev)
if (sdev->scsi_level > SCSI_SPC_2)
us->fflags |= US_FL_SANE_SENSE;
- /* Some devices report a SCSI revision level above 2 but are
- * unable to handle the REPORT LUNS command (for which
- * support is mandatory at level 3). Since we already have
- * a Get-Max-LUN request, we won't lose much by setting the
- * revision level down to 2. The only devices that would be
- * affected are those with sparse LUNs. */
- if (sdev->scsi_level > SCSI_2)
- sdev->sdev_target->scsi_level =
- sdev->scsi_level = SCSI_2;
-
/* USB-IDE bridges tend to report SK = 0x04 (Non-recoverable
* Hardware Error) when any low-level error occurs,
* recoverable or not. Setting this flag tells the SCSI
@@ -283,6 +262,33 @@ static int slave_configure(struct scsi_device *sdev)
return 0;
}
+static int target_alloc(struct scsi_target *starget)
+{
+ struct us_data *us = host_to_us(dev_to_shost(starget->dev.parent));
+
+ /*
+ * Some USB drives don't support REPORT LUNS, even though they
+ * report a SCSI revision level above 2. Tell the SCSI layer
+ * not to issue that command; it will perform a normal sequential
+ * scan instead.
+ */
+ starget->no_report_luns = 1;
+
+ /*
+ * The UFI spec treats the Peripheral Qualifier bits in an
+ * INQUIRY result as reserved and requires devices to set them
+ * to 0. However the SCSI spec requires these bits to be set
+ * to 3 to indicate when a LUN is not present.
+ *
+ * Let the scanning code know if this target merely sets
+ * Peripheral Device Type to 0x1f to indicate no LUN.
+ */
+ if (us->subclass == USB_SC_UFI)
+ starget->pdt_1f_for_no_lun = 1;
+
+ return 0;
+}
+
/* queue a command */
/* This is always called with scsi_lock(host) held */
static int queuecommand_lck(struct scsi_cmnd *srb,
@@ -546,6 +552,7 @@ struct scsi_host_template usb_stor_host_template = {
.slave_alloc = slave_alloc,
.slave_configure = slave_configure,
+ .target_alloc = target_alloc,
/* lots of sg segments can be handled */
.sg_tablesize = SCSI_MAX_SG_CHAIN_SEGMENTS,
diff --git a/drivers/usb/storage/sddr09.c b/drivers/usb/storage/sddr09.c
index 425df7df2e5..3252a62b31b 100644
--- a/drivers/usb/storage/sddr09.c
+++ b/drivers/usb/storage/sddr09.c
@@ -1787,6 +1787,7 @@ static struct usb_driver sddr09_driver = {
.post_reset = usb_stor_post_reset,
.id_table = sddr09_usb_ids,
.soft_unbind = 1,
+ .no_dynamic_id = 1,
};
module_usb_driver(sddr09_driver);
diff --git a/drivers/usb/storage/sddr55.c b/drivers/usb/storage/sddr55.c
index e4ca5fcb7cc..c144078065a 100644
--- a/drivers/usb/storage/sddr55.c
+++ b/drivers/usb/storage/sddr55.c
@@ -1006,6 +1006,7 @@ static struct usb_driver sddr55_driver = {
.post_reset = usb_stor_post_reset,
.id_table = sddr55_usb_ids,
.soft_unbind = 1,
+ .no_dynamic_id = 1,
};
module_usb_driver(sddr55_driver);
diff --git a/drivers/usb/storage/shuttle_usbat.c b/drivers/usb/storage/shuttle_usbat.c
index 1369d259061..fa1ceebc465 100644
--- a/drivers/usb/storage/shuttle_usbat.c
+++ b/drivers/usb/storage/shuttle_usbat.c
@@ -1863,6 +1863,7 @@ static struct usb_driver usbat_driver = {
.post_reset = usb_stor_post_reset,
.id_table = usbat_usb_ids,
.soft_unbind = 1,
+ .no_dynamic_id = 1,
};
module_usb_driver(usbat_driver);
diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
index 0e5c91c6187..c70109e5d60 100644
--- a/drivers/usb/storage/transport.c
+++ b/drivers/usb/storage/transport.c
@@ -1071,7 +1071,8 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us)
/* set up the command wrapper */
bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
bcb->DataTransferLength = cpu_to_le32(transfer_length);
- bcb->Flags = srb->sc_data_direction == DMA_FROM_DEVICE ? 1 << 7 : 0;
+ bcb->Flags = srb->sc_data_direction == DMA_FROM_DEVICE ?
+ US_BULK_FLAG_IN : 0;
bcb->Tag = ++us->tag;
bcb->Lun = srb->device->lun;
if (us->fflags & US_FL_SCM_MULT_TARG)
diff --git a/drivers/usb/storage/transport.h b/drivers/usb/storage/transport.h
index 242ff5e791a..9369d752d41 100644
--- a/drivers/usb/storage/transport.h
+++ b/drivers/usb/storage/transport.h
@@ -42,45 +42,6 @@
#include <linux/blkdev.h>
/*
- * Bulk only data structures
- */
-
-/* command block wrapper */
-struct bulk_cb_wrap {
- __le32 Signature; /* contains 'USBC' */
- __u32 Tag; /* unique per command id */
- __le32 DataTransferLength; /* size of data */
- __u8 Flags; /* direction in bit 0 */
- __u8 Lun; /* LUN normally 0 */
- __u8 Length; /* of of the CDB */
- __u8 CDB[16]; /* max command */
-};
-
-#define US_BULK_CB_WRAP_LEN 31
-#define US_BULK_CB_SIGN 0x43425355 /*spells out USBC */
-#define US_BULK_FLAG_IN 1
-#define US_BULK_FLAG_OUT 0
-
-/* command status wrapper */
-struct bulk_cs_wrap {
- __le32 Signature; /* should = 'USBS' */
- __u32 Tag; /* same as original command */
- __le32 Residue; /* amount not transferred */
- __u8 Status; /* see below */
- __u8 Filler[18];
-};
-
-#define US_BULK_CS_WRAP_LEN 13
-#define US_BULK_CS_SIGN 0x53425355 /* spells out 'USBS' */
-#define US_BULK_STAT_OK 0
-#define US_BULK_STAT_FAIL 1
-#define US_BULK_STAT_PHASE 2
-
-/* bulk-only class specific requests */
-#define US_BULK_RESET_REQUEST 0xff
-#define US_BULK_GET_MAX_LUN 0xfe
-
-/*
* usb_stor_bulk_transfer_xxx() return codes, in order of severity
*/
diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c
index a33ead5dce2..8ec8a6e66f5 100644
--- a/drivers/usb/storage/uas.c
+++ b/drivers/usb/storage/uas.c
@@ -13,7 +13,9 @@
#include <linux/types.h>
#include <linux/module.h>
#include <linux/usb.h>
+#include <linux/usb/hcd.h>
#include <linux/usb/storage.h>
+#include <linux/usb/uas.h>
#include <scsi/scsi.h>
#include <scsi/scsi_dbg.h>
@@ -22,49 +24,6 @@
#include <scsi/scsi_host.h>
#include <scsi/scsi_tcq.h>
-/* Common header for all IUs */
-struct iu {
- __u8 iu_id;
- __u8 rsvd1;
- __be16 tag;
-};
-
-enum {
- IU_ID_COMMAND = 0x01,
- IU_ID_STATUS = 0x03,
- IU_ID_RESPONSE = 0x04,
- IU_ID_TASK_MGMT = 0x05,
- IU_ID_READ_READY = 0x06,
- IU_ID_WRITE_READY = 0x07,
-};
-
-struct command_iu {
- __u8 iu_id;
- __u8 rsvd1;
- __be16 tag;
- __u8 prio_attr;
- __u8 rsvd5;
- __u8 len;
- __u8 rsvd7;
- struct scsi_lun lun;
- __u8 cdb[16]; /* XXX: Overflow-checking tools may misunderstand */
-};
-
-/*
- * Also used for the Read Ready and Write Ready IUs since they have the
- * same first four bytes
- */
-struct sense_iu {
- __u8 iu_id;
- __u8 rsvd1;
- __be16 tag;
- __be16 status_qual;
- __u8 status;
- __u8 rsvd7[7];
- __be16 len;
- __u8 sense[SCSI_SENSE_BUFFERSIZE];
-};
-
/*
* The r00-r01c specs define this version of the SENSE IU data structure.
* It's still in use by several different firmware releases.
@@ -79,18 +38,6 @@ struct sense_iu_old {
__u8 sense[SCSI_SENSE_BUFFERSIZE];
};
-enum {
- CMD_PIPE_ID = 1,
- STATUS_PIPE_ID = 2,
- DATA_IN_PIPE_ID = 3,
- DATA_OUT_PIPE_ID = 4,
-
- UAS_SIMPLE_TAG = 0,
- UAS_HEAD_TAG = 1,
- UAS_ORDERED_TAG = 2,
- UAS_ACA = 4,
-};
-
struct uas_dev_info {
struct usb_interface *intf;
struct usb_device *udev;
@@ -98,6 +45,8 @@ struct uas_dev_info {
unsigned cmd_pipe, status_pipe, data_in_pipe, data_out_pipe;
unsigned use_streams:1;
unsigned uas_sense_old:1;
+ struct scsi_cmnd *cmnd;
+ struct urb *status_urb; /* used only if stream support is available */
};
enum {
@@ -109,6 +58,9 @@ enum {
SUBMIT_DATA_OUT_URB = (1 << 5),
ALLOC_CMD_URB = (1 << 6),
SUBMIT_CMD_URB = (1 << 7),
+ COMPLETED_DATA_IN = (1 << 8),
+ COMPLETED_DATA_OUT = (1 << 9),
+ DATA_COMPLETES_CMD = (1 << 10),
};
/* Overrides scsi_pointer */
@@ -116,6 +68,7 @@ struct uas_cmd_info {
unsigned int state;
unsigned int stream;
struct urb *cmd_urb;
+ /* status_urb is used only if stream support isn't available */
struct urb *status_urb;
struct urb *data_in_urb;
struct urb *data_out_urb;
@@ -125,33 +78,43 @@ struct uas_cmd_info {
/* I hate forward declarations, but I actually have a loop */
static int uas_submit_urbs(struct scsi_cmnd *cmnd,
struct uas_dev_info *devinfo, gfp_t gfp);
+static void uas_do_work(struct work_struct *work);
+static DECLARE_WORK(uas_work, uas_do_work);
static DEFINE_SPINLOCK(uas_work_lock);
static LIST_HEAD(uas_work_list);
static void uas_do_work(struct work_struct *work)
{
struct uas_cmd_info *cmdinfo;
+ struct uas_cmd_info *temp;
struct list_head list;
+ int err;
spin_lock_irq(&uas_work_lock);
list_replace_init(&uas_work_list, &list);
spin_unlock_irq(&uas_work_lock);
- list_for_each_entry(cmdinfo, &list, list) {
+ list_for_each_entry_safe(cmdinfo, temp, &list, list) {
struct scsi_pointer *scp = (void *)cmdinfo;
struct scsi_cmnd *cmnd = container_of(scp,
struct scsi_cmnd, SCp);
- uas_submit_urbs(cmnd, cmnd->device->hostdata, GFP_NOIO);
+ err = uas_submit_urbs(cmnd, cmnd->device->hostdata, GFP_NOIO);
+ if (err) {
+ list_del(&cmdinfo->list);
+ spin_lock_irq(&uas_work_lock);
+ list_add_tail(&cmdinfo->list, &uas_work_list);
+ spin_unlock_irq(&uas_work_lock);
+ schedule_work(&uas_work);
+ }
}
}
-static DECLARE_WORK(uas_work, uas_do_work);
-
static void uas_sense(struct urb *urb, struct scsi_cmnd *cmnd)
{
struct sense_iu *sense_iu = urb->transfer_buffer;
struct scsi_device *sdev = cmnd->device;
+ struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
if (urb->actual_length > 16) {
unsigned len = be16_to_cpup(&sense_iu->len);
@@ -169,16 +132,15 @@ static void uas_sense(struct urb *urb, struct scsi_cmnd *cmnd)
}
cmnd->result = sense_iu->status;
- if (sdev->current_cmnd)
- sdev->current_cmnd = NULL;
- cmnd->scsi_done(cmnd);
- usb_free_urb(urb);
+ if (!(cmdinfo->state & DATA_COMPLETES_CMD))
+ cmnd->scsi_done(cmnd);
}
static void uas_sense_old(struct urb *urb, struct scsi_cmnd *cmnd)
{
struct sense_iu_old *sense_iu = urb->transfer_buffer;
struct scsi_device *sdev = cmnd->device;
+ struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
if (urb->actual_length > 8) {
unsigned len = be16_to_cpup(&sense_iu->len) - 2;
@@ -196,10 +158,8 @@ static void uas_sense_old(struct urb *urb, struct scsi_cmnd *cmnd)
}
cmnd->result = sense_iu->status;
- if (sdev->current_cmnd)
- sdev->current_cmnd = NULL;
- cmnd->scsi_done(cmnd);
- usb_free_urb(urb);
+ if (!(cmdinfo->state & DATA_COMPLETES_CMD))
+ cmnd->scsi_done(cmnd);
}
static void uas_xfer_data(struct urb *urb, struct scsi_cmnd *cmnd,
@@ -208,7 +168,7 @@ static void uas_xfer_data(struct urb *urb, struct scsi_cmnd *cmnd,
struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
int err;
- cmdinfo->state = direction | SUBMIT_STATUS_URB;
+ cmdinfo->state = direction;
err = uas_submit_urbs(cmnd, cmnd->device->hostdata, GFP_ATOMIC);
if (err) {
spin_lock(&uas_work_lock);
@@ -221,27 +181,61 @@ static void uas_xfer_data(struct urb *urb, struct scsi_cmnd *cmnd,
static void uas_stat_cmplt(struct urb *urb)
{
struct iu *iu = urb->transfer_buffer;
- struct scsi_device *sdev = urb->context;
- struct uas_dev_info *devinfo = sdev->hostdata;
+ struct Scsi_Host *shost = urb->context;
+ struct uas_dev_info *devinfo = (void *)shost->hostdata[0];
struct scsi_cmnd *cmnd;
+ struct uas_cmd_info *cmdinfo;
u16 tag;
+ int ret;
if (urb->status) {
dev_err(&urb->dev->dev, "URB BAD STATUS %d\n", urb->status);
- usb_free_urb(urb);
+ if (devinfo->use_streams)
+ usb_free_urb(urb);
return;
}
tag = be16_to_cpup(&iu->tag) - 1;
- if (sdev->current_cmnd)
- cmnd = sdev->current_cmnd;
+ if (tag == 0)
+ cmnd = devinfo->cmnd;
else
- cmnd = scsi_find_tag(sdev, tag);
- if (!cmnd)
+ cmnd = scsi_host_find_tag(shost, tag - 1);
+ if (!cmnd) {
+ if (devinfo->use_streams) {
+ usb_free_urb(urb);
+ return;
+ }
+ ret = usb_submit_urb(urb, GFP_ATOMIC);
+ if (ret)
+ dev_err(&urb->dev->dev, "failed submit status urb\n");
return;
+ }
+ cmdinfo = (void *)&cmnd->SCp;
switch (iu->iu_id) {
case IU_ID_STATUS:
+ if (devinfo->cmnd == cmnd)
+ devinfo->cmnd = NULL;
+
+ if (!(cmdinfo->state & COMPLETED_DATA_IN) &&
+ cmdinfo->data_in_urb) {
+ if (devinfo->use_streams) {
+ cmdinfo->state |= DATA_COMPLETES_CMD;
+ usb_unlink_urb(cmdinfo->data_in_urb);
+ } else {
+ usb_free_urb(cmdinfo->data_in_urb);
+ }
+ }
+ if (!(cmdinfo->state & COMPLETED_DATA_OUT) &&
+ cmdinfo->data_out_urb) {
+ if (devinfo->use_streams) {
+ cmdinfo->state |= DATA_COMPLETES_CMD;
+ usb_unlink_urb(cmdinfo->data_in_urb);
+ } else {
+ usb_free_urb(cmdinfo->data_out_urb);
+ }
+ }
+
if (urb->actual_length < 16)
devinfo->uas_sense_old = 1;
if (devinfo->uas_sense_old)
@@ -259,29 +253,70 @@ static void uas_stat_cmplt(struct urb *urb)
scmd_printk(KERN_ERR, cmnd,
"Bogus IU (%d) received on status pipe\n", iu->iu_id);
}
+
+ if (devinfo->use_streams) {
+ usb_free_urb(urb);
+ return;
+ }
+
+ ret = usb_submit_urb(urb, GFP_ATOMIC);
+ if (ret)
+ dev_err(&urb->dev->dev, "failed submit status urb\n");
}
-static void uas_data_cmplt(struct urb *urb)
+static void uas_data_out_cmplt(struct urb *urb)
{
- struct scsi_data_buffer *sdb = urb->context;
+ struct scsi_cmnd *cmnd = urb->context;
+ struct scsi_data_buffer *sdb = scsi_out(cmnd);
+ struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
+
+ cmdinfo->state |= COMPLETED_DATA_OUT;
+
sdb->resid = sdb->length - urb->actual_length;
usb_free_urb(urb);
+
+ if (cmdinfo->state & DATA_COMPLETES_CMD)
+ cmnd->scsi_done(cmnd);
+}
+
+static void uas_data_in_cmplt(struct urb *urb)
+{
+ struct scsi_cmnd *cmnd = urb->context;
+ struct scsi_data_buffer *sdb = scsi_in(cmnd);
+ struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
+
+ cmdinfo->state |= COMPLETED_DATA_IN;
+
+ sdb->resid = sdb->length - urb->actual_length;
+ usb_free_urb(urb);
+
+ if (cmdinfo->state & DATA_COMPLETES_CMD)
+ cmnd->scsi_done(cmnd);
}
static struct urb *uas_alloc_data_urb(struct uas_dev_info *devinfo, gfp_t gfp,
- unsigned int pipe, u16 stream_id,
- struct scsi_data_buffer *sdb,
- enum dma_data_direction dir)
+ unsigned int pipe, struct scsi_cmnd *cmnd,
+ enum dma_data_direction dir)
{
+ struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
struct usb_device *udev = devinfo->udev;
struct urb *urb = usb_alloc_urb(0, gfp);
+ struct scsi_data_buffer *sdb;
+ usb_complete_t complete_fn;
+ u16 stream_id = cmdinfo->stream;
if (!urb)
goto out;
- usb_fill_bulk_urb(urb, udev, pipe, NULL, sdb->length, uas_data_cmplt,
- sdb);
- if (devinfo->use_streams)
- urb->stream_id = stream_id;
+ if (dir == DMA_FROM_DEVICE) {
+ sdb = scsi_in(cmnd);
+ complete_fn = uas_data_in_cmplt;
+ } else {
+ sdb = scsi_out(cmnd);
+ complete_fn = uas_data_out_cmplt;
+ }
+ usb_fill_bulk_urb(urb, udev, pipe, NULL, sdb->length,
+ complete_fn, cmnd);
+ urb->stream_id = stream_id;
urb->num_sgs = udev->bus->sg_tablesize ? sdb->table.nents : 0;
urb->sg = sdb->table.sgl;
out:
@@ -289,7 +324,7 @@ static struct urb *uas_alloc_data_urb(struct uas_dev_info *devinfo, gfp_t gfp,
}
static struct urb *uas_alloc_sense_urb(struct uas_dev_info *devinfo, gfp_t gfp,
- struct scsi_cmnd *cmnd, u16 stream_id)
+ struct Scsi_Host *shost, u16 stream_id)
{
struct usb_device *udev = devinfo->udev;
struct urb *urb = usb_alloc_urb(0, gfp);
@@ -303,7 +338,7 @@ static struct urb *uas_alloc_sense_urb(struct uas_dev_info *devinfo, gfp_t gfp,
goto free;
usb_fill_bulk_urb(urb, udev, devinfo->status_pipe, iu, sizeof(*iu),
- uas_stat_cmplt, cmnd->device);
+ uas_stat_cmplt, shost);
urb->stream_id = stream_id;
urb->transfer_flags |= URB_FREE_BUFFER;
out:
@@ -334,7 +369,10 @@ static struct urb *uas_alloc_cmd_urb(struct uas_dev_info *devinfo, gfp_t gfp,
goto free;
iu->iu_id = IU_ID_COMMAND;
- iu->tag = cpu_to_be16(stream_id);
+ if (blk_rq_tagged(cmnd->request))
+ iu->tag = cpu_to_be16(cmnd->request->tag + 2);
+ else
+ iu->tag = cpu_to_be16(1);
iu->prio_attr = UAS_SIMPLE_TAG;
iu->len = len;
int_to_scsilun(sdev->lun, &iu->lun);
@@ -362,8 +400,8 @@ static int uas_submit_urbs(struct scsi_cmnd *cmnd,
struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
if (cmdinfo->state & ALLOC_STATUS_URB) {
- cmdinfo->status_urb = uas_alloc_sense_urb(devinfo, gfp, cmnd,
- cmdinfo->stream);
+ cmdinfo->status_urb = uas_alloc_sense_urb(devinfo, gfp,
+ cmnd->device->host, cmdinfo->stream);
if (!cmdinfo->status_urb)
return SCSI_MLQUEUE_DEVICE_BUSY;
cmdinfo->state &= ~ALLOC_STATUS_URB;
@@ -380,8 +418,8 @@ static int uas_submit_urbs(struct scsi_cmnd *cmnd,
if (cmdinfo->state & ALLOC_DATA_IN_URB) {
cmdinfo->data_in_urb = uas_alloc_data_urb(devinfo, gfp,
- devinfo->data_in_pipe, cmdinfo->stream,
- scsi_in(cmnd), DMA_FROM_DEVICE);
+ devinfo->data_in_pipe, cmnd,
+ DMA_FROM_DEVICE);
if (!cmdinfo->data_in_urb)
return SCSI_MLQUEUE_DEVICE_BUSY;
cmdinfo->state &= ~ALLOC_DATA_IN_URB;
@@ -398,8 +436,8 @@ static int uas_submit_urbs(struct scsi_cmnd *cmnd,
if (cmdinfo->state & ALLOC_DATA_OUT_URB) {
cmdinfo->data_out_urb = uas_alloc_data_urb(devinfo, gfp,
- devinfo->data_out_pipe, cmdinfo->stream,
- scsi_out(cmnd), DMA_TO_DEVICE);
+ devinfo->data_out_pipe, cmnd,
+ DMA_TO_DEVICE);
if (!cmdinfo->data_out_urb)
return SCSI_MLQUEUE_DEVICE_BUSY;
cmdinfo->state &= ~ALLOC_DATA_OUT_URB;
@@ -444,13 +482,13 @@ static int uas_queuecommand_lck(struct scsi_cmnd *cmnd,
BUILD_BUG_ON(sizeof(struct uas_cmd_info) > sizeof(struct scsi_pointer));
- if (!cmdinfo->status_urb && sdev->current_cmnd)
+ if (devinfo->cmnd)
return SCSI_MLQUEUE_DEVICE_BUSY;
if (blk_rq_tagged(cmnd->request)) {
- cmdinfo->stream = cmnd->request->tag + 1;
+ cmdinfo->stream = cmnd->request->tag + 2;
} else {
- sdev->current_cmnd = cmnd;
+ devinfo->cmnd = cmnd;
cmdinfo->stream = 1;
}
@@ -472,7 +510,8 @@ static int uas_queuecommand_lck(struct scsi_cmnd *cmnd,
}
if (!devinfo->use_streams) {
- cmdinfo->state &= ~(SUBMIT_DATA_IN_URB | SUBMIT_DATA_OUT_URB);
+ cmdinfo->state &= ~(SUBMIT_DATA_IN_URB | SUBMIT_DATA_OUT_URB |
+ ALLOC_STATUS_URB | SUBMIT_STATUS_URB);
cmdinfo->stream = 0;
}
@@ -551,7 +590,7 @@ static int uas_slave_configure(struct scsi_device *sdev)
{
struct uas_dev_info *devinfo = sdev->hostdata;
scsi_set_tag_type(sdev, MSG_ORDERED_TAG);
- scsi_activate_tcq(sdev, devinfo->qdepth - 1);
+ scsi_activate_tcq(sdev, devinfo->qdepth - 2);
return 0;
}
@@ -589,22 +628,34 @@ static int uas_is_interface(struct usb_host_interface *intf)
intf->desc.bInterfaceProtocol == USB_PR_UAS);
}
+static int uas_isnt_supported(struct usb_device *udev)
+{
+ struct usb_hcd *hcd = bus_to_hcd(udev->bus);
+
+ dev_warn(&udev->dev, "The driver for the USB controller %s does not "
+ "support scatter-gather which is\n",
+ hcd->driver->description);
+ dev_warn(&udev->dev, "required by the UAS driver. Please try an"
+ "alternative USB controller if you wish to use UAS.\n");
+ return -ENODEV;
+}
+
static int uas_switch_interface(struct usb_device *udev,
struct usb_interface *intf)
{
int i;
-
- if (uas_is_interface(intf->cur_altsetting))
- return 0;
+ int sg_supported = udev->bus->sg_tablesize != 0;
for (i = 0; i < intf->num_altsetting; i++) {
struct usb_host_interface *alt = &intf->altsetting[i];
- if (alt == intf->cur_altsetting)
- continue;
- if (uas_is_interface(alt))
+
+ if (uas_is_interface(alt)) {
+ if (!sg_supported)
+ return uas_isnt_supported(udev);
return usb_set_interface(udev,
alt->desc.bInterfaceNumber,
alt->desc.bAlternateSetting);
+ }
}
return -ENODEV;
@@ -619,6 +670,7 @@ static void uas_configure_endpoints(struct uas_dev_info *devinfo)
unsigned i, n_endpoints = intf->cur_altsetting->desc.bNumEndpoints;
devinfo->uas_sense_old = 0;
+ devinfo->cmnd = NULL;
for (i = 0; i < n_endpoints; i++) {
unsigned char *extra = endpoint[i].extra;
@@ -670,6 +722,40 @@ static void uas_configure_endpoints(struct uas_dev_info *devinfo)
}
}
+static int uas_alloc_status_urb(struct uas_dev_info *devinfo,
+ struct Scsi_Host *shost)
+{
+ if (devinfo->use_streams) {
+ devinfo->status_urb = NULL;
+ return 0;
+ }
+
+ devinfo->status_urb = uas_alloc_sense_urb(devinfo, GFP_KERNEL,
+ shost, 0);
+ if (!devinfo->status_urb)
+ goto err_s_urb;
+
+ if (usb_submit_urb(devinfo->status_urb, GFP_KERNEL))
+ goto err_submit_urb;
+
+ return 0;
+err_submit_urb:
+ usb_free_urb(devinfo->status_urb);
+err_s_urb:
+ return -ENOMEM;
+}
+
+static void uas_free_streams(struct uas_dev_info *devinfo)
+{
+ struct usb_device *udev = devinfo->udev;
+ struct usb_host_endpoint *eps[3];
+
+ eps[0] = usb_pipe_endpoint(udev, devinfo->status_pipe);
+ eps[1] = usb_pipe_endpoint(udev, devinfo->data_in_pipe);
+ eps[2] = usb_pipe_endpoint(udev, devinfo->data_out_pipe);
+ usb_free_streams(devinfo->intf, eps, 3, GFP_KERNEL);
+}
+
/*
* XXX: What I'd like to do here is register a SCSI host for each USB host in
* the system. Follow usb-storage's design of registering a SCSI host for
@@ -699,18 +785,33 @@ static int uas_probe(struct usb_interface *intf, const struct usb_device_id *id)
shost->max_id = 1;
shost->sg_tablesize = udev->bus->sg_tablesize;
- result = scsi_add_host(shost, &intf->dev);
+ devinfo->intf = intf;
+ devinfo->udev = udev;
+ uas_configure_endpoints(devinfo);
+
+ result = scsi_init_shared_tag_map(shost, devinfo->qdepth - 2);
if (result)
goto free;
+
+ result = scsi_add_host(shost, &intf->dev);
+ if (result)
+ goto deconfig_eps;
+
shost->hostdata[0] = (unsigned long)devinfo;
- devinfo->intf = intf;
- devinfo->udev = udev;
- uas_configure_endpoints(devinfo);
+ result = uas_alloc_status_urb(devinfo, shost);
+ if (result)
+ goto err_alloc_status;
scsi_scan_host(shost);
usb_set_intfdata(intf, shost);
return result;
+
+err_alloc_status:
+ scsi_remove_host(shost);
+ shost = NULL;
+deconfig_eps:
+ uas_free_streams(devinfo);
free:
kfree(devinfo);
if (shost)
@@ -732,18 +833,13 @@ static int uas_post_reset(struct usb_interface *intf)
static void uas_disconnect(struct usb_interface *intf)
{
- struct usb_device *udev = interface_to_usbdev(intf);
- struct usb_host_endpoint *eps[3];
struct Scsi_Host *shost = usb_get_intfdata(intf);
struct uas_dev_info *devinfo = (void *)shost->hostdata[0];
scsi_remove_host(shost);
-
- eps[0] = usb_pipe_endpoint(udev, devinfo->status_pipe);
- eps[1] = usb_pipe_endpoint(udev, devinfo->data_in_pipe);
- eps[2] = usb_pipe_endpoint(udev, devinfo->data_out_pipe);
- usb_free_streams(intf, eps, 3, GFP_KERNEL);
-
+ usb_kill_urb(devinfo->status_urb);
+ usb_free_urb(devinfo->status_urb);
+ uas_free_streams(devinfo);
kfree(devinfo);
}
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
index 3dd7da9fd50..c18538e4a6d 100644
--- a/drivers/usb/storage/usb.c
+++ b/drivers/usb/storage/usb.c
@@ -125,6 +125,9 @@ static struct us_unusual_dev us_unusual_dev_list[] = {
{ } /* Terminating entry */
};
+static struct us_unusual_dev for_dynamic_ids =
+ USUAL_DEV(USB_SC_SCSI, USB_PR_BULK, 0);
+
#undef UNUSUAL_DEV
#undef COMPLIANT_DEV
#undef USUAL_DEV
@@ -788,15 +791,19 @@ static void quiesce_and_remove_host(struct us_data *us)
struct Scsi_Host *host = us_to_host(us);
/* If the device is really gone, cut short reset delays */
- if (us->pusb_dev->state == USB_STATE_NOTATTACHED)
+ if (us->pusb_dev->state == USB_STATE_NOTATTACHED) {
set_bit(US_FLIDX_DISCONNECTING, &us->dflags);
+ wake_up(&us->delay_wait);
+ }
- /* Prevent SCSI-scanning (if it hasn't started yet)
- * and wait for the SCSI-scanning thread to stop.
+ /* Prevent SCSI scanning (if it hasn't started yet)
+ * or wait for the SCSI-scanning routine to stop.
*/
- set_bit(US_FLIDX_DONT_SCAN, &us->dflags);
- wake_up(&us->delay_wait);
- wait_for_completion(&us->scanning_done);
+ cancel_delayed_work_sync(&us->scan_dwork);
+
+ /* Balance autopm calls if scanning was cancelled */
+ if (test_bit(US_FLIDX_SCAN_PENDING, &us->dflags))
+ usb_autopm_put_interface_no_suspend(us->pusb_intf);
/* Removing the host will perform an orderly shutdown: caches
* synchronized, disks spun down, etc.
@@ -823,53 +830,28 @@ static void release_everything(struct us_data *us)
scsi_host_put(us_to_host(us));
}
-/* Thread to carry out delayed SCSI-device scanning */
-static int usb_stor_scan_thread(void * __us)
+/* Delayed-work routine to carry out SCSI-device scanning */
+static void usb_stor_scan_dwork(struct work_struct *work)
{
- struct us_data *us = (struct us_data *)__us;
+ struct us_data *us = container_of(work, struct us_data,
+ scan_dwork.work);
struct device *dev = &us->pusb_intf->dev;
- dev_dbg(dev, "device found\n");
-
- set_freezable();
+ dev_dbg(dev, "starting scan\n");
- /*
- * Wait for the timeout to expire or for a disconnect
- *
- * We can't freeze in this thread or we risk causing khubd to
- * fail to freeze, but we can't be non-freezable either. Nor can
- * khubd freeze while waiting for scanning to complete as it may
- * hold the device lock, causing a hang when suspending devices.
- * So instead of using wait_event_freezable(), explicitly test
- * for (DONT_SCAN || freezing) in interruptible wait and proceed
- * if any of DONT_SCAN, freezing or timeout has happened.
- */
- if (delay_use > 0) {
- dev_dbg(dev, "waiting for device to settle "
- "before scanning\n");
- wait_event_interruptible_timeout(us->delay_wait,
- test_bit(US_FLIDX_DONT_SCAN, &us->dflags) ||
- freezing(current), delay_use * HZ);
+ /* For bulk-only devices, determine the max LUN value */
+ if (us->protocol == USB_PR_BULK && !(us->fflags & US_FL_SINGLE_LUN)) {
+ mutex_lock(&us->dev_mutex);
+ us->max_lun = usb_stor_Bulk_max_lun(us);
+ mutex_unlock(&us->dev_mutex);
}
+ scsi_scan_host(us_to_host(us));
+ dev_dbg(dev, "scan complete\n");
- /* If the device is still connected, perform the scanning */
- if (!test_bit(US_FLIDX_DONT_SCAN, &us->dflags)) {
-
- /* For bulk-only devices, determine the max LUN value */
- if (us->protocol == USB_PR_BULK &&
- !(us->fflags & US_FL_SINGLE_LUN)) {
- mutex_lock(&us->dev_mutex);
- us->max_lun = usb_stor_Bulk_max_lun(us);
- mutex_unlock(&us->dev_mutex);
- }
- scsi_scan_host(us_to_host(us));
- dev_dbg(dev, "scan complete\n");
-
- /* Should we unbind if no devices were detected? */
- }
+ /* Should we unbind if no devices were detected? */
usb_autopm_put_interface(us->pusb_intf);
- complete_and_exit(&us->scanning_done, 0);
+ clear_bit(US_FLIDX_SCAN_PENDING, &us->dflags);
}
static unsigned int usb_stor_sg_tablesize(struct usb_interface *intf)
@@ -916,7 +898,7 @@ int usb_stor_probe1(struct us_data **pus,
init_completion(&us->cmnd_ready);
init_completion(&(us->notify));
init_waitqueue_head(&us->delay_wait);
- init_completion(&us->scanning_done);
+ INIT_DELAYED_WORK(&us->scan_dwork, usb_stor_scan_dwork);
/* Associate the us_data structure with the USB device */
result = associate_dev(us, intf);
@@ -947,7 +929,6 @@ EXPORT_SYMBOL_GPL(usb_stor_probe1);
/* Second part of general USB mass-storage probing */
int usb_stor_probe2(struct us_data *us)
{
- struct task_struct *th;
int result;
struct device *dev = &us->pusb_intf->dev;
@@ -988,20 +969,14 @@ int usb_stor_probe2(struct us_data *us)
goto BadDevice;
}
- /* Start up the thread for delayed SCSI-device scanning */
- th = kthread_create(usb_stor_scan_thread, us, "usb-stor-scan");
- if (IS_ERR(th)) {
- dev_warn(dev,
- "Unable to start the device-scanning thread\n");
- complete(&us->scanning_done);
- quiesce_and_remove_host(us);
- result = PTR_ERR(th);
- goto BadDevice;
- }
-
+ /* Submit the delayed_work for SCSI-device scanning */
usb_autopm_get_interface_no_resume(us->pusb_intf);
- wake_up_process(th);
+ set_bit(US_FLIDX_SCAN_PENDING, &us->dflags);
+ if (delay_use > 0)
+ dev_dbg(dev, "waiting for device to settle before scanning\n");
+ queue_delayed_work(system_freezable_wq, &us->scan_dwork,
+ delay_use * HZ);
return 0;
/* We come here if there are any problems */
@@ -1027,8 +1002,10 @@ EXPORT_SYMBOL_GPL(usb_stor_disconnect);
static int storage_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
+ struct us_unusual_dev *unusual_dev;
struct us_data *us;
int result;
+ int size;
/*
* If libusual is configured, let it decide whether a standard
@@ -1047,8 +1024,19 @@ static int storage_probe(struct usb_interface *intf,
* table, so we use the index of the id entry to find the
* corresponding unusual_devs entry.
*/
- result = usb_stor_probe1(&us, intf, id,
- (id - usb_storage_usb_ids) + us_unusual_dev_list);
+
+ size = ARRAY_SIZE(us_unusual_dev_list);
+ if (id >= usb_storage_usb_ids && id < usb_storage_usb_ids + size) {
+ unusual_dev = (id - usb_storage_usb_ids) + us_unusual_dev_list;
+ } else {
+ unusual_dev = &for_dynamic_ids;
+
+ US_DEBUGP("%s %s 0x%04x 0x%04x\n", "Use Bulk-Only transport",
+ "with the Transparent SCSI protocol for dynamic id:",
+ id->idVendor, id->idProduct);
+ }
+
+ result = usb_stor_probe1(&us, intf, id, unusual_dev);
if (result)
return result;
@@ -1074,7 +1062,6 @@ static struct usb_driver usb_storage_driver = {
.id_table = usb_storage_usb_ids,
.supports_autosuspend = 1,
.soft_unbind = 1,
- .no_dynamic_id = 1,
};
static int __init usb_stor_init(void)
diff --git a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h
index 7b0f2113632..75f70f04f37 100644
--- a/drivers/usb/storage/usb.h
+++ b/drivers/usb/storage/usb.h
@@ -47,6 +47,7 @@
#include <linux/blkdev.h>
#include <linux/completion.h>
#include <linux/mutex.h>
+#include <linux/workqueue.h>
#include <scsi/scsi_host.h>
struct us_data;
@@ -72,7 +73,7 @@ struct us_unusual_dev {
#define US_FLIDX_DISCONNECTING 3 /* disconnect in progress */
#define US_FLIDX_RESETTING 4 /* device reset in progress */
#define US_FLIDX_TIMED_OUT 5 /* SCSI midlayer timed out */
-#define US_FLIDX_DONT_SCAN 6 /* don't scan (disconnect) */
+#define US_FLIDX_SCAN_PENDING 6 /* scanning not yet done */
#define US_FLIDX_REDO_READ10 7 /* redo READ(10) command */
#define US_FLIDX_READ10_WORKED 8 /* previous READ(10) succeeded */
@@ -147,8 +148,8 @@ struct us_data {
/* mutual exclusion and synchronization structures */
struct completion cmnd_ready; /* to sleep thread on */
struct completion notify; /* thread begin/end */
- wait_queue_head_t delay_wait; /* wait during scan, reset */
- struct completion scanning_done; /* wait for scan thread */
+ wait_queue_head_t delay_wait; /* wait during reset */
+ struct delayed_work scan_dwork; /* for async scanning */
/* subdriver information */
void *extra; /* Any extra data */
diff --git a/drivers/usb/usb-skeleton.c b/drivers/usb/usb-skeleton.c
index 8efeae24764..b4a71679c93 100644
--- a/drivers/usb/usb-skeleton.c
+++ b/drivers/usb/usb-skeleton.c
@@ -27,8 +27,6 @@
#define USB_SKEL_VENDOR_ID 0xfff0
#define USB_SKEL_PRODUCT_ID 0xfff0
-static DEFINE_MUTEX(skel_mutex);
-
/* table of devices that work with this driver */
static const struct usb_device_id skel_table[] = {
{ USB_DEVICE(USB_SKEL_VENDOR_ID, USB_SKEL_PRODUCT_ID) },
@@ -101,25 +99,18 @@ static int skel_open(struct inode *inode, struct file *file)
goto exit;
}
- mutex_lock(&skel_mutex);
dev = usb_get_intfdata(interface);
if (!dev) {
- mutex_unlock(&skel_mutex);
retval = -ENODEV;
goto exit;
}
/* increment our usage count for the device */
kref_get(&dev->kref);
- mutex_unlock(&skel_mutex);
/* lock the device to allow correctly handling errors
* in resumption */
mutex_lock(&dev->io_mutex);
- if (!dev->interface) {
- retval = -ENODEV;
- goto out_err;
- }
retval = usb_autopm_get_interface(interface);
if (retval)
@@ -127,11 +118,7 @@ static int skel_open(struct inode *inode, struct file *file)
/* save our object in the file's private structure */
file->private_data = dev;
-
-out_err:
mutex_unlock(&dev->io_mutex);
- if (retval)
- kref_put(&dev->kref, skel_delete);
exit:
return retval;
@@ -611,6 +598,7 @@ static void skel_disconnect(struct usb_interface *interface)
int minor = interface->minor;
dev = usb_get_intfdata(interface);
+ usb_set_intfdata(interface, NULL);
/* give back our minor */
usb_deregister_dev(interface, &skel_class);
@@ -622,12 +610,8 @@ static void skel_disconnect(struct usb_interface *interface)
usb_kill_anchored_urbs(&dev->submitted);
- mutex_lock(&skel_mutex);
- usb_set_intfdata(interface, NULL);
-
/* decrement our usage count */
kref_put(&dev->kref, skel_delete);
- mutex_unlock(&skel_mutex);
dev_info(&interface->dev, "USB Skeleton #%d now disconnected", minor);
}
diff --git a/drivers/usb/wusbcore/Kconfig b/drivers/usb/wusbcore/Kconfig
index 0ead8826ec7..f29fdd7f6d7 100644
--- a/drivers/usb/wusbcore/Kconfig
+++ b/drivers/usb/wusbcore/Kconfig
@@ -6,7 +6,7 @@ config USB_WUSB
depends on EXPERIMENTAL
depends on USB
depends on PCI
- select UWB
+ depends on UWB
select CRYPTO
select CRYPTO_BLKCIPHER
select CRYPTO_CBC