summaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/class/cdc-wdm.c2
-rw-r--r--drivers/usb/core/Kconfig6
-rw-r--r--drivers/usb/core/endpoint.c2
-rw-r--r--drivers/usb/gadget/Kconfig7
-rw-r--r--drivers/usb/gadget/ci13xxx_udc.c268
-rw-r--r--drivers/usb/gadget/ci13xxx_udc.h9
-rw-r--r--drivers/usb/gadget/composite.c5
-rw-r--r--drivers/usb/gadget/imx_udc.c2
-rw-r--r--drivers/usb/gadget/langwell_udc.c4
-rw-r--r--drivers/usb/gadget/pch_udc.c127
-rw-r--r--drivers/usb/gadget/printer.c19
-rw-r--r--drivers/usb/gadget/storage_common.c7
-rw-r--r--drivers/usb/host/ehci-fsl.c13
-rw-r--r--drivers/usb/host/ehci-fsl.h3
-rw-r--r--drivers/usb/host/ehci-hcd.c19
-rw-r--r--drivers/usb/host/ehci-mxc.c25
-rw-r--r--drivers/usb/host/ehci-pci.c33
-rw-r--r--drivers/usb/host/fhci-hcd.c4
-rw-r--r--drivers/usb/host/fhci-tds.c4
-rw-r--r--drivers/usb/host/fsl-mph-dr-of.c11
-rw-r--r--drivers/usb/host/imx21-hcd.c2
-rw-r--r--drivers/usb/host/oxu210hp-hcd.c2
-rw-r--r--drivers/usb/misc/adutux.c2
-rw-r--r--drivers/usb/misc/iowarrior.c2
-rw-r--r--drivers/usb/misc/ldusb.c2
-rw-r--r--drivers/usb/misc/usbled.c2
-rw-r--r--drivers/usb/misc/uss720.c1
-rw-r--r--drivers/usb/musb/musb_gadget.c4
-rw-r--r--drivers/usb/otg/nop-usb-xceiv.c2
-rw-r--r--drivers/usb/otg/ulpi.c2
-rw-r--r--drivers/usb/serial/ch341.c10
-rw-r--r--drivers/usb/serial/cp210x.c16
-rw-r--r--drivers/usb/serial/digi_acceleport.c10
-rw-r--r--drivers/usb/serial/ftdi_sio.c12
-rw-r--r--drivers/usb/serial/ftdi_sio_ids.h22
-rw-r--r--drivers/usb/serial/generic.c20
-rw-r--r--drivers/usb/serial/io_tables.h1
-rw-r--r--drivers/usb/serial/iuu_phoenix.c1
-rw-r--r--drivers/usb/serial/keyspan.h4
-rw-r--r--drivers/usb/serial/keyspan_pda.c17
-rw-r--r--drivers/usb/serial/moto_modem.c1
-rw-r--r--drivers/usb/serial/option.c24
-rw-r--r--drivers/usb/serial/oti6858.c1
-rw-r--r--drivers/usb/serial/pl2303.c12
-rw-r--r--drivers/usb/serial/pl2303.h1
-rw-r--r--drivers/usb/serial/qcaux.c3
-rw-r--r--drivers/usb/serial/siemens_mpi.c1
-rw-r--r--drivers/usb/serial/spcp8x5.c7
-rw-r--r--drivers/usb/serial/usb-serial.c8
-rw-r--r--drivers/usb/serial/usb_debug.c1
-rw-r--r--drivers/usb/storage/unusual_cypress.h5
-rw-r--r--drivers/usb/storage/unusual_devs.h18
-rw-r--r--drivers/usb/wusbcore/wa-rpipe.c2
53 files changed, 469 insertions, 319 deletions
diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c
index 6ee4451..47085e5 100644
--- a/drivers/usb/class/cdc-wdm.c
+++ b/drivers/usb/class/cdc-wdm.c
@@ -342,7 +342,7 @@ static ssize_t wdm_write
goto outnp;
}
- if (!file->f_flags && O_NONBLOCK)
+ if (!(file->f_flags & O_NONBLOCK))
r = wait_event_interruptible(desc->wait, !test_bit(WDM_IN_USE,
&desc->flags));
else
diff --git a/drivers/usb/core/Kconfig b/drivers/usb/core/Kconfig
index bcc2477..18d02e3 100644
--- a/drivers/usb/core/Kconfig
+++ b/drivers/usb/core/Kconfig
@@ -123,9 +123,9 @@ config USB_OTG
config USB_OTG_WHITELIST
bool "Rely on OTG Targeted Peripherals List"
- depends on USB_OTG || EMBEDDED
+ depends on USB_OTG || EXPERT
default y if USB_OTG
- default n if EMBEDDED
+ default n if EXPERT
help
If you say Y here, the "otg_whitelist.h" file will be used as a
product whitelist, so USB peripherals not listed there will be
@@ -141,7 +141,7 @@ config USB_OTG_WHITELIST
config USB_OTG_BLACKLIST_HUB
bool "Disable external hubs"
- depends on USB_OTG || EMBEDDED
+ depends on USB_OTG || EXPERT
help
If you say Y here, then Linux will refuse to enumerate
external hubs. OTG hosts are allowed to reduce hardware
diff --git a/drivers/usb/core/endpoint.c b/drivers/usb/core/endpoint.c
index 9da2505..df502a9 100644
--- a/drivers/usb/core/endpoint.c
+++ b/drivers/usb/core/endpoint.c
@@ -192,12 +192,12 @@ int usb_create_ep_devs(struct device *parent,
ep_dev->dev.parent = parent;
ep_dev->dev.release = ep_device_release;
dev_set_name(&ep_dev->dev, "ep_%02x", endpoint->desc.bEndpointAddress);
- device_enable_async_suspend(&ep_dev->dev);
retval = device_register(&ep_dev->dev);
if (retval)
goto error_register;
+ device_enable_async_suspend(&ep_dev->dev);
endpoint->ep_dev = ep_dev;
return retval;
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index 1dc9739..06bb9d4 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -509,7 +509,7 @@ config USB_LANGWELL
select USB_GADGET_SELECTED
config USB_GADGET_EG20T
- boolean "Intel EG20T(Topcliff) USB Device controller"
+ boolean "Intel EG20T PCH/OKI SEMICONDUCTOR ML7213 IOH UDC"
depends on PCI
select USB_GADGET_DUALSPEED
help
@@ -525,6 +525,11 @@ config USB_GADGET_EG20T
This driver dose not support interrupt transfer or isochronous
transfer modes.
+ This driver also can be used for OKI SEMICONDUCTOR's ML7213 which is
+ for IVI(In-Vehicle Infotainment) use.
+ ML7213 is companion chip for Intel Atom E6xx series.
+ ML7213 is completely compatible for Intel EG20T PCH.
+
config USB_EG20T
tristate
depends on USB_GADGET_EG20T
diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c
index 31656a2..a1c67ae 100644
--- a/drivers/usb/gadget/ci13xxx_udc.c
+++ b/drivers/usb/gadget/ci13xxx_udc.c
@@ -76,10 +76,21 @@ static DEFINE_SPINLOCK(udc_lock);
/* control endpoint description */
static const struct usb_endpoint_descriptor
-ctrl_endpt_desc = {
+ctrl_endpt_out_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = USB_DIR_OUT,
+ .bmAttributes = USB_ENDPOINT_XFER_CONTROL,
+ .wMaxPacketSize = cpu_to_le16(CTRL_PAYLOAD_MAX),
+};
+
+static const struct usb_endpoint_descriptor
+ctrl_endpt_in_desc = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+
+ .bEndpointAddress = USB_DIR_IN,
.bmAttributes = USB_ENDPOINT_XFER_CONTROL,
.wMaxPacketSize = cpu_to_le16(CTRL_PAYLOAD_MAX),
};
@@ -265,10 +276,10 @@ static int hw_device_init(void __iomem *base)
hw_bank.size /= sizeof(u32);
reg = hw_aread(ABS_DCCPARAMS, DCCPARAMS_DEN) >> ffs_nr(DCCPARAMS_DEN);
- if (reg == 0 || reg > ENDPT_MAX)
- return -ENODEV;
+ hw_ep_max = reg * 2; /* cache hw ENDPT_MAX */
- hw_ep_max = reg; /* cache hw ENDPT_MAX */
+ if (hw_ep_max == 0 || hw_ep_max > ENDPT_MAX)
+ return -ENODEV;
/* setup lock mode ? */
@@ -1197,16 +1208,17 @@ static ssize_t show_qheads(struct device *dev, struct device_attribute *attr,
}
spin_lock_irqsave(udc->lock, flags);
- for (i = 0; i < hw_ep_max; i++) {
- struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[i];
+ for (i = 0; i < hw_ep_max/2; i++) {
+ struct ci13xxx_ep *mEpRx = &udc->ci13xxx_ep[i];
+ struct ci13xxx_ep *mEpTx = &udc->ci13xxx_ep[i + hw_ep_max/2];
n += scnprintf(buf + n, PAGE_SIZE - n,
"EP=%02i: RX=%08X TX=%08X\n",
- i, (u32)mEp->qh[RX].dma, (u32)mEp->qh[TX].dma);
+ i, (u32)mEpRx->qh.dma, (u32)mEpTx->qh.dma);
for (j = 0; j < (sizeof(struct ci13xxx_qh)/sizeof(u32)); j++) {
n += scnprintf(buf + n, PAGE_SIZE - n,
" %04X: %08X %08X\n", j,
- *((u32 *)mEp->qh[RX].ptr + j),
- *((u32 *)mEp->qh[TX].ptr + j));
+ *((u32 *)mEpRx->qh.ptr + j),
+ *((u32 *)mEpTx->qh.ptr + j));
}
}
spin_unlock_irqrestore(udc->lock, flags);
@@ -1293,7 +1305,7 @@ static ssize_t show_requests(struct device *dev, struct device_attribute *attr,
unsigned long flags;
struct list_head *ptr = NULL;
struct ci13xxx_req *req = NULL;
- unsigned i, j, k, n = 0, qSize = sizeof(struct ci13xxx_td)/sizeof(u32);
+ unsigned i, j, n = 0, qSize = sizeof(struct ci13xxx_td)/sizeof(u32);
dbg_trace("[%s] %p\n", __func__, buf);
if (attr == NULL || buf == NULL) {
@@ -1303,22 +1315,20 @@ static ssize_t show_requests(struct device *dev, struct device_attribute *attr,
spin_lock_irqsave(udc->lock, flags);
for (i = 0; i < hw_ep_max; i++)
- for (k = RX; k <= TX; k++)
- list_for_each(ptr, &udc->ci13xxx_ep[i].qh[k].queue)
- {
- req = list_entry(ptr,
- struct ci13xxx_req, queue);
+ list_for_each(ptr, &udc->ci13xxx_ep[i].qh.queue)
+ {
+ req = list_entry(ptr, struct ci13xxx_req, queue);
+
+ n += scnprintf(buf + n, PAGE_SIZE - n,
+ "EP=%02i: TD=%08X %s\n",
+ i % hw_ep_max/2, (u32)req->dma,
+ ((i < hw_ep_max/2) ? "RX" : "TX"));
+ for (j = 0; j < qSize; j++)
n += scnprintf(buf + n, PAGE_SIZE - n,
- "EP=%02i: TD=%08X %s\n",
- i, (u32)req->dma,
- ((k == RX) ? "RX" : "TX"));
-
- for (j = 0; j < qSize; j++)
- n += scnprintf(buf + n, PAGE_SIZE - n,
- " %04X: %08X\n", j,
- *((u32 *)req->ptr + j));
- }
+ " %04X: %08X\n", j,
+ *((u32 *)req->ptr + j));
+ }
spin_unlock_irqrestore(udc->lock, flags);
return n;
@@ -1467,12 +1477,12 @@ static int _hardware_enqueue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq)
* At this point it's guaranteed exclusive access to qhead
* (endpt is not primed) so it's no need to use tripwire
*/
- mEp->qh[mEp->dir].ptr->td.next = mReq->dma; /* TERMINATE = 0 */
- mEp->qh[mEp->dir].ptr->td.token &= ~TD_STATUS; /* clear status */
+ mEp->qh.ptr->td.next = mReq->dma; /* TERMINATE = 0 */
+ mEp->qh.ptr->td.token &= ~TD_STATUS; /* clear status */
if (mReq->req.zero == 0)
- mEp->qh[mEp->dir].ptr->cap |= QH_ZLT;
+ mEp->qh.ptr->cap |= QH_ZLT;
else
- mEp->qh[mEp->dir].ptr->cap &= ~QH_ZLT;
+ mEp->qh.ptr->cap &= ~QH_ZLT;
wmb(); /* synchronize before ep prime */
@@ -1542,11 +1552,11 @@ __acquires(mEp->lock)
hw_ep_flush(mEp->num, mEp->dir);
- while (!list_empty(&mEp->qh[mEp->dir].queue)) {
+ while (!list_empty(&mEp->qh.queue)) {
/* pop oldest request */
struct ci13xxx_req *mReq = \
- list_entry(mEp->qh[mEp->dir].queue.next,
+ list_entry(mEp->qh.queue.next,
struct ci13xxx_req, queue);
list_del_init(&mReq->queue);
mReq->req.status = -ESHUTDOWN;
@@ -1571,8 +1581,6 @@ static int _gadget_stop_activity(struct usb_gadget *gadget)
{
struct usb_ep *ep;
struct ci13xxx *udc = container_of(gadget, struct ci13xxx, gadget);
- struct ci13xxx_ep *mEp = container_of(gadget->ep0,
- struct ci13xxx_ep, ep);
trace("%p", gadget);
@@ -1583,7 +1591,8 @@ static int _gadget_stop_activity(struct usb_gadget *gadget)
gadget_for_each_ep(ep, gadget) {
usb_ep_fifo_flush(ep);
}
- usb_ep_fifo_flush(gadget->ep0);
+ usb_ep_fifo_flush(&udc->ep0out.ep);
+ usb_ep_fifo_flush(&udc->ep0in.ep);
udc->driver->disconnect(gadget);
@@ -1591,11 +1600,12 @@ static int _gadget_stop_activity(struct usb_gadget *gadget)
gadget_for_each_ep(ep, gadget) {
usb_ep_disable(ep);
}
- usb_ep_disable(gadget->ep0);
+ usb_ep_disable(&udc->ep0out.ep);
+ usb_ep_disable(&udc->ep0in.ep);
- if (mEp->status != NULL) {
- usb_ep_free_request(gadget->ep0, mEp->status);
- mEp->status = NULL;
+ if (udc->status != NULL) {
+ usb_ep_free_request(&udc->ep0in.ep, udc->status);
+ udc->status = NULL;
}
return 0;
@@ -1614,7 +1624,6 @@ static void isr_reset_handler(struct ci13xxx *udc)
__releases(udc->lock)
__acquires(udc->lock)
{
- struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[0];
int retval;
trace("%p", udc);
@@ -1635,11 +1644,15 @@ __acquires(udc->lock)
if (retval)
goto done;
- retval = usb_ep_enable(&mEp->ep, &ctrl_endpt_desc);
+ retval = usb_ep_enable(&udc->ep0out.ep, &ctrl_endpt_out_desc);
+ if (retval)
+ goto done;
+
+ retval = usb_ep_enable(&udc->ep0in.ep, &ctrl_endpt_in_desc);
if (!retval) {
- mEp->status = usb_ep_alloc_request(&mEp->ep, GFP_ATOMIC);
- if (mEp->status == NULL) {
- usb_ep_disable(&mEp->ep);
+ udc->status = usb_ep_alloc_request(&udc->ep0in.ep, GFP_ATOMIC);
+ if (udc->status == NULL) {
+ usb_ep_disable(&udc->ep0out.ep);
retval = -ENOMEM;
}
}
@@ -1672,16 +1685,17 @@ static void isr_get_status_complete(struct usb_ep *ep, struct usb_request *req)
/**
* isr_get_status_response: get_status request response
- * @ep: endpoint
+ * @udc: udc struct
* @setup: setup request packet
*
* This function returns an error code
*/
-static int isr_get_status_response(struct ci13xxx_ep *mEp,
+static int isr_get_status_response(struct ci13xxx *udc,
struct usb_ctrlrequest *setup)
__releases(mEp->lock)
__acquires(mEp->lock)
{
+ struct ci13xxx_ep *mEp = &udc->ep0in;
struct usb_request *req = NULL;
gfp_t gfp_flags = GFP_ATOMIC;
int dir, num, retval;
@@ -1736,27 +1750,23 @@ __acquires(mEp->lock)
/**
* isr_setup_status_phase: queues the status phase of a setup transation
- * @mEp: endpoint
+ * @udc: udc struct
*
* This function returns an error code
*/
-static int isr_setup_status_phase(struct ci13xxx_ep *mEp)
+static int isr_setup_status_phase(struct ci13xxx *udc)
__releases(mEp->lock)
__acquires(mEp->lock)
{
int retval;
+ struct ci13xxx_ep *mEp;
- trace("%p", mEp);
-
- /* mEp is always valid & configured */
-
- if (mEp->type == USB_ENDPOINT_XFER_CONTROL)
- mEp->dir = (mEp->dir == TX) ? RX : TX;
+ trace("%p", udc);
- mEp->status->no_interrupt = 1;
+ mEp = (udc->ep0_dir == TX) ? &udc->ep0out : &udc->ep0in;
spin_unlock(mEp->lock);
- retval = usb_ep_queue(&mEp->ep, mEp->status, GFP_ATOMIC);
+ retval = usb_ep_queue(&mEp->ep, udc->status, GFP_ATOMIC);
spin_lock(mEp->lock);
return retval;
@@ -1778,11 +1788,11 @@ __acquires(mEp->lock)
trace("%p", mEp);
- if (list_empty(&mEp->qh[mEp->dir].queue))
+ if (list_empty(&mEp->qh.queue))
return -EINVAL;
/* pop oldest request */
- mReq = list_entry(mEp->qh[mEp->dir].queue.next,
+ mReq = list_entry(mEp->qh.queue.next,
struct ci13xxx_req, queue);
list_del_init(&mReq->queue);
@@ -1794,10 +1804,10 @@ __acquires(mEp->lock)
dbg_done(_usb_addr(mEp), mReq->ptr->token, retval);
- if (!list_empty(&mEp->qh[mEp->dir].queue)) {
+ if (!list_empty(&mEp->qh.queue)) {
struct ci13xxx_req* mReqEnq;
- mReqEnq = list_entry(mEp->qh[mEp->dir].queue.next,
+ mReqEnq = list_entry(mEp->qh.queue.next,
struct ci13xxx_req, queue);
_hardware_enqueue(mEp, mReqEnq);
}
@@ -1836,16 +1846,14 @@ __acquires(udc->lock)
int type, num, err = -EINVAL;
struct usb_ctrlrequest req;
-
if (mEp->desc == NULL)
continue; /* not configured */
- if ((mEp->dir == RX && hw_test_and_clear_complete(i)) ||
- (mEp->dir == TX && hw_test_and_clear_complete(i + 16))) {
+ if (hw_test_and_clear_complete(i)) {
err = isr_tr_complete_low(mEp);
if (mEp->type == USB_ENDPOINT_XFER_CONTROL) {
if (err > 0) /* needs status phase */
- err = isr_setup_status_phase(mEp);
+ err = isr_setup_status_phase(udc);
if (err < 0) {
dbg_event(_usb_addr(mEp),
"ERROR", err);
@@ -1866,15 +1874,22 @@ __acquires(udc->lock)
continue;
}
+ /*
+ * Flush data and handshake transactions of previous
+ * setup packet.
+ */
+ _ep_nuke(&udc->ep0out);
+ _ep_nuke(&udc->ep0in);
+
/* read_setup_packet */
do {
hw_test_and_set_setup_guard();
- memcpy(&req, &mEp->qh[RX].ptr->setup, sizeof(req));
+ memcpy(&req, &mEp->qh.ptr->setup, sizeof(req));
} while (!hw_test_and_clear_setup_guard());
type = req.bRequestType;
- mEp->dir = (type & USB_DIR_IN) ? TX : RX;
+ udc->ep0_dir = (type & USB_DIR_IN) ? TX : RX;
dbg_setup(_usb_addr(mEp), &req);
@@ -1895,7 +1910,7 @@ __acquires(udc->lock)
if (err)
break;
}
- err = isr_setup_status_phase(mEp);
+ err = isr_setup_status_phase(udc);
break;
case USB_REQ_GET_STATUS:
if (type != (USB_DIR_IN|USB_RECIP_DEVICE) &&
@@ -1905,7 +1920,7 @@ __acquires(udc->lock)
if (le16_to_cpu(req.wLength) != 2 ||
le16_to_cpu(req.wValue) != 0)
break;
- err = isr_get_status_response(mEp, &req);
+ err = isr_get_status_response(udc, &req);
break;
case USB_REQ_SET_ADDRESS:
if (type != (USB_DIR_OUT|USB_RECIP_DEVICE))
@@ -1916,7 +1931,7 @@ __acquires(udc->lock)
err = hw_usb_set_address((u8)le16_to_cpu(req.wValue));
if (err)
break;
- err = isr_setup_status_phase(mEp);
+ err = isr_setup_status_phase(udc);
break;
case USB_REQ_SET_FEATURE:
if (type != (USB_DIR_OUT|USB_RECIP_ENDPOINT) &&
@@ -1932,12 +1947,12 @@ __acquires(udc->lock)
spin_lock(udc->lock);
if (err)
break;
- err = isr_setup_status_phase(mEp);
+ err = isr_setup_status_phase(udc);
break;
default:
delegate:
if (req.wLength == 0) /* no data phase */
- mEp->dir = TX;
+ udc->ep0_dir = TX;
spin_unlock(udc->lock);
err = udc->driver->setup(&udc->gadget, &req);
@@ -1968,7 +1983,7 @@ static int ep_enable(struct usb_ep *ep,
const struct usb_endpoint_descriptor *desc)
{
struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
- int direction, retval = 0;
+ int retval = 0;
unsigned long flags;
trace("%p, %p", ep, desc);
@@ -1982,7 +1997,7 @@ static int ep_enable(struct usb_ep *ep,
mEp->desc = desc;
- if (!list_empty(&mEp->qh[mEp->dir].queue))
+ if (!list_empty(&mEp->qh.queue))
warn("enabling a non-empty endpoint!");
mEp->dir = usb_endpoint_dir_in(desc) ? TX : RX;
@@ -1991,29 +2006,22 @@ static int ep_enable(struct usb_ep *ep,
mEp->ep.maxpacket = __constant_le16_to_cpu(desc->wMaxPacketSize);
- direction = mEp->dir;
- do {
- dbg_event(_usb_addr(mEp), "ENABLE", 0);
+ dbg_event(_usb_addr(mEp), "ENABLE", 0);
- mEp->qh[mEp->dir].ptr->cap = 0;
+ mEp->qh.ptr->cap = 0;
- if (mEp->type == USB_ENDPOINT_XFER_CONTROL)
- mEp->qh[mEp->dir].ptr->cap |= QH_IOS;
- else if (mEp->type == USB_ENDPOINT_XFER_ISOC)
- mEp->qh[mEp->dir].ptr->cap &= ~QH_MULT;
- else
- mEp->qh[mEp->dir].ptr->cap &= ~QH_ZLT;
-
- mEp->qh[mEp->dir].ptr->cap |=
- (mEp->ep.maxpacket << ffs_nr(QH_MAX_PKT)) & QH_MAX_PKT;
- mEp->qh[mEp->dir].ptr->td.next |= TD_TERMINATE; /* needed? */
-
- retval |= hw_ep_enable(mEp->num, mEp->dir, mEp->type);
+ if (mEp->type == USB_ENDPOINT_XFER_CONTROL)
+ mEp->qh.ptr->cap |= QH_IOS;
+ else if (mEp->type == USB_ENDPOINT_XFER_ISOC)
+ mEp->qh.ptr->cap &= ~QH_MULT;
+ else
+ mEp->qh.ptr->cap &= ~QH_ZLT;
- if (mEp->type == USB_ENDPOINT_XFER_CONTROL)
- mEp->dir = (mEp->dir == TX) ? RX : TX;
+ mEp->qh.ptr->cap |=
+ (mEp->ep.maxpacket << ffs_nr(QH_MAX_PKT)) & QH_MAX_PKT;
+ mEp->qh.ptr->td.next |= TD_TERMINATE; /* needed? */
- } while (mEp->dir != direction);
+ retval |= hw_ep_enable(mEp->num, mEp->dir, mEp->type);
spin_unlock_irqrestore(mEp->lock, flags);
return retval;
@@ -2146,7 +2154,7 @@ static int ep_queue(struct usb_ep *ep, struct usb_request *req,
spin_lock_irqsave(mEp->lock, flags);
if (mEp->type == USB_ENDPOINT_XFER_CONTROL &&
- !list_empty(&mEp->qh[mEp->dir].queue)) {
+ !list_empty(&mEp->qh.queue)) {
_ep_nuke(mEp);
retval = -EOVERFLOW;
warn("endpoint ctrl %X nuked", _usb_addr(mEp));
@@ -2170,9 +2178,9 @@ static int ep_queue(struct usb_ep *ep, struct usb_request *req,
/* push request */
mReq->req.status = -EINPROGRESS;
mReq->req.actual = 0;
- list_add_tail(&mReq->queue, &mEp->qh[mEp->dir].queue);
+ list_add_tail(&mReq->queue, &mEp->qh.queue);
- if (list_is_singular(&mEp->qh[mEp->dir].queue))
+ if (list_is_singular(&mEp->qh.queue))
retval = _hardware_enqueue(mEp, mReq);
if (retval == -EALREADY) {
@@ -2199,7 +2207,7 @@ static int ep_dequeue(struct usb_ep *ep, struct usb_request *req)
trace("%p, %p", ep, req);
if (ep == NULL || req == NULL || mEp->desc == NULL ||
- list_empty(&mReq->queue) || list_empty(&mEp->qh[mEp->dir].queue))
+ list_empty(&mReq->queue) || list_empty(&mEp->qh.queue))
return -EINVAL;
spin_lock_irqsave(mEp->lock, flags);
@@ -2244,7 +2252,7 @@ static int ep_set_halt(struct usb_ep *ep, int value)
#ifndef STALL_IN
/* g_file_storage MS compliant but g_zero fails chapter 9 compliance */
if (value && mEp->type == USB_ENDPOINT_XFER_BULK && mEp->dir == TX &&
- !list_empty(&mEp->qh[mEp->dir].queue)) {
+ !list_empty(&mEp->qh.queue)) {
spin_unlock_irqrestore(mEp->lock, flags);
return -EAGAIN;
}
@@ -2355,7 +2363,7 @@ static int ci13xxx_vbus_session(struct usb_gadget *_gadget, int is_active)
if (is_active) {
pm_runtime_get_sync(&_gadget->dev);
hw_device_reset(udc);
- hw_device_state(udc->ci13xxx_ep[0].qh[RX].dma);
+ hw_device_state(udc->ep0out.qh.dma);
} else {
hw_device_state(0);
if (udc->udc_driver->notify_event)
@@ -2390,7 +2398,8 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
int (*bind)(struct usb_gadget *))
{
struct ci13xxx *udc = _udc;
- unsigned long i, k, flags;
+ unsigned long flags;
+ int i, j;
int retval = -ENOMEM;
trace("%p", driver);
@@ -2427,45 +2436,46 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
info("hw_ep_max = %d", hw_ep_max);
- udc->driver = driver;
udc->gadget.dev.driver = NULL;
retval = 0;
- for (i = 0; i < hw_ep_max; i++) {
- struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[i];
+ for (i = 0; i < hw_ep_max/2; i++) {
+ for (j = RX; j <= TX; j++) {
+ int k = i + j * hw_ep_max/2;
+ struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[k];
- scnprintf(mEp->name, sizeof(mEp->name), "ep%i", (int)i);
+ scnprintf(mEp->name, sizeof(mEp->name), "ep%i%s", i,
+ (j == TX) ? "in" : "out");
- mEp->lock = udc->lock;
- mEp->device = &udc->gadget.dev;
- mEp->td_pool = udc->td_pool;
+ mEp->lock = udc->lock;
+ mEp->device = &udc->gadget.dev;
+ mEp->td_pool = udc->td_pool;
- mEp->ep.name = mEp->name;
- mEp->ep.ops = &usb_ep_ops;
- mEp->ep.maxpacket = CTRL_PAYLOAD_MAX;
+ mEp->ep.name = mEp->name;
+ mEp->ep.ops = &usb_ep_ops;
+ mEp->ep.maxpacket = CTRL_PAYLOAD_MAX;
- /* this allocation cannot be random */
- for (k = RX; k <= TX; k++) {
- INIT_LIST_HEAD(&mEp->qh[k].queue);
+ INIT_LIST_HEAD(&mEp->qh.queue);
spin_unlock_irqrestore(udc->lock, flags);
- mEp->qh[k].ptr = dma_pool_alloc(udc->qh_pool,
- GFP_KERNEL,
- &mEp->qh[k].dma);
+ mEp->qh.ptr = dma_pool_alloc(udc->qh_pool, GFP_KERNEL,
+ &mEp->qh.dma);
spin_lock_irqsave(udc->lock, flags);
- if (mEp->qh[k].ptr == NULL)
+ if (mEp->qh.ptr == NULL)
retval = -ENOMEM;
else
- memset(mEp->qh[k].ptr, 0,
- sizeof(*mEp->qh[k].ptr));
- }
- if (i == 0)
- udc->gadget.ep0 = &mEp->ep;
- else
+ memset(mEp->qh.ptr, 0, sizeof(*mEp->qh.ptr));
+
+ /* skip ep0 out and in endpoints */
+ if (i == 0)
+ continue;
+
list_add_tail(&mEp->ep.ep_list, &udc->gadget.ep_list);
+ }
}
if (retval)
goto done;
+ udc->gadget.ep0 = &udc->ep0in.ep;
/* bind gadget */
driver->driver.bus = NULL;
udc->gadget.dev.driver = &driver->driver;
@@ -2479,6 +2489,7 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
goto done;
}
+ udc->driver = driver;
pm_runtime_get_sync(&udc->gadget.dev);
if (udc->udc_driver->flags & CI13XXX_PULLUP_ON_VBUS) {
if (udc->vbus_active) {
@@ -2490,14 +2501,12 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
}
}
- retval = hw_device_state(udc->ci13xxx_ep[0].qh[RX].dma);
+ retval = hw_device_state(udc->ep0out.qh.dma);
if (retval)
pm_runtime_put_sync(&udc->gadget.dev);
done:
spin_unlock_irqrestore(udc->lock, flags);
- if (retval)
- usb_gadget_unregister_driver(driver);
return retval;
}
EXPORT_SYMBOL(usb_gadget_probe_driver);
@@ -2510,7 +2519,7 @@ EXPORT_SYMBOL(usb_gadget_probe_driver);
int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
{
struct ci13xxx *udc = _udc;
- unsigned long i, k, flags;
+ unsigned long i, flags;
trace("%p", driver);
@@ -2546,17 +2555,14 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
for (i = 0; i < hw_ep_max; i++) {
struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[i];
- if (i == 0)
- udc->gadget.ep0 = NULL;
- else if (!list_empty(&mEp->ep.ep_list))
+ if (!list_empty(&mEp->ep.ep_list))
list_del_init(&mEp->ep.ep_list);
- for (k = RX; k <= TX; k++)
- if (mEp->qh[k].ptr != NULL)
- dma_pool_free(udc->qh_pool,
- mEp->qh[k].ptr, mEp->qh[k].dma);
+ if (mEp->qh.ptr != NULL)
+ dma_pool_free(udc->qh_pool, mEp->qh.ptr, mEp->qh.dma);
}
+ udc->gadget.ep0 = NULL;
udc->driver = NULL;
spin_unlock_irqrestore(udc->lock, flags);
diff --git a/drivers/usb/gadget/ci13xxx_udc.h b/drivers/usb/gadget/ci13xxx_udc.h
index f61fed0..a2492b6 100644
--- a/drivers/usb/gadget/ci13xxx_udc.h
+++ b/drivers/usb/gadget/ci13xxx_udc.h
@@ -20,7 +20,7 @@
* DEFINE
*****************************************************************************/
#define CI13XXX_PAGE_SIZE 4096ul /* page size for TD's */
-#define ENDPT_MAX (16)
+#define ENDPT_MAX (32)
#define CTRL_PAYLOAD_MAX (64)
#define RX (0) /* similar to USB_DIR_OUT but can be used as an index */
#define TX (1) /* similar to USB_DIR_IN but can be used as an index */
@@ -88,8 +88,7 @@ struct ci13xxx_ep {
struct list_head queue;
struct ci13xxx_qh *ptr;
dma_addr_t dma;
- } qh[2];
- struct usb_request *status;
+ } qh;
int wedge;
/* global resources */
@@ -119,9 +118,13 @@ struct ci13xxx {
struct dma_pool *qh_pool; /* DMA pool for queue heads */
struct dma_pool *td_pool; /* DMA pool for transfer descs */
+ struct usb_request *status; /* ep0 status request */
struct usb_gadget gadget; /* USB slave device */
struct ci13xxx_ep ci13xxx_ep[ENDPT_MAX]; /* extended endpts */
+ u32 ep0_dir; /* ep0 direction */
+#define ep0out ci13xxx_ep[0]
+#define ep0in ci13xxx_ep[16]
struct usb_gadget_driver *driver; /* 3rd party gadget driver */
struct ci13xxx_udc_driver *udc_driver; /* device controller driver */
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index f6ff845..1ba4bef 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -928,8 +928,9 @@ unknown:
*/
switch (ctrl->bRequestType & USB_RECIP_MASK) {
case USB_RECIP_INTERFACE:
- if (cdev->config)
- f = cdev->config->interface[intf];
+ if (!cdev->config || w_index >= MAX_CONFIG_INTERFACES)
+ break;
+ f = cdev->config->interface[intf];
break;
case USB_RECIP_ENDPOINT:
diff --git a/drivers/usb/gadget/imx_udc.c b/drivers/usb/gadget/imx_udc.c
index 1210534..5408186 100644
--- a/drivers/usb/gadget/imx_udc.c
+++ b/drivers/usb/gadget/imx_udc.c
@@ -1320,7 +1320,7 @@ static struct imx_udc_struct controller = {
};
/*******************************************************************************
- * USB gadged driver functions
+ * USB gadget driver functions
*******************************************************************************
*/
int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
diff --git a/drivers/usb/gadget/langwell_udc.c b/drivers/usb/gadget/langwell_udc.c
index 7779724..1eca8b4 100644
--- a/drivers/usb/gadget/langwell_udc.c
+++ b/drivers/usb/gadget/langwell_udc.c
@@ -3086,7 +3086,7 @@ static void langwell_udc_remove(struct pci_dev *pdev)
kfree(dev->ep);
- /* diable IRQ handler */
+ /* disable IRQ handler */
if (dev->got_irq)
free_irq(pdev->irq, dev);
@@ -3406,7 +3406,7 @@ static int langwell_udc_suspend(struct pci_dev *pdev, pm_message_t state)
/* disable interrupt and set controller to stop state */
langwell_udc_stop(dev);
- /* diable IRQ handler */
+ /* disable IRQ handler */
if (dev->got_irq)
free_irq(pdev->irq, dev);
dev->got_irq = 0;
diff --git a/drivers/usb/gadget/pch_udc.c b/drivers/usb/gadget/pch_udc.c
index 0c8dd81..b120dbb 100644
--- a/drivers/usb/gadget/pch_udc.c
+++ b/drivers/usb/gadget/pch_udc.c
@@ -198,10 +198,10 @@
#define PCH_UDC_BRLEN 0x0F /* Burst length */
#define PCH_UDC_THLEN 0x1F /* Threshold length */
/* Value of EP Buffer Size */
-#define UDC_EP0IN_BUFF_SIZE 64
-#define UDC_EPIN_BUFF_SIZE 512
-#define UDC_EP0OUT_BUFF_SIZE 64
-#define UDC_EPOUT_BUFF_SIZE 512
+#define UDC_EP0IN_BUFF_SIZE 16
+#define UDC_EPIN_BUFF_SIZE 256
+#define UDC_EP0OUT_BUFF_SIZE 16
+#define UDC_EPOUT_BUFF_SIZE 256
/* Value of EP maximum packet size */
#define UDC_EP0IN_MAX_PKT_SIZE 64
#define UDC_EP0OUT_MAX_PKT_SIZE 64
@@ -351,7 +351,7 @@ struct pch_udc_dev {
struct pci_pool *data_requests;
struct pci_pool *stp_requests;
dma_addr_t dma_addr;
- unsigned long ep0out_buf[64];
+ void *ep0out_buf;
struct usb_ctrlrequest setup_data;
unsigned long phys_addr;
void __iomem *base_addr;
@@ -361,6 +361,8 @@ struct pch_udc_dev {
#define PCH_UDC_PCI_BAR 1
#define PCI_DEVICE_ID_INTEL_EG20T_UDC 0x8808
+#define PCI_VENDOR_ID_ROHM 0x10DB
+#define PCI_DEVICE_ID_ML7213_IOH_UDC 0x801D
static const char ep0_string[] = "ep0in";
static DEFINE_SPINLOCK(udc_stall_spinlock); /* stall spin lock */
@@ -1219,11 +1221,11 @@ static void complete_req(struct pch_udc_ep *ep, struct pch_udc_request *req,
dev = ep->dev;
if (req->dma_mapped) {
if (ep->in)
- pci_unmap_single(dev->pdev, req->req.dma,
- req->req.length, PCI_DMA_TODEVICE);
+ dma_unmap_single(&dev->pdev->dev, req->req.dma,
+ req->req.length, DMA_TO_DEVICE);
else
- pci_unmap_single(dev->pdev, req->req.dma,
- req->req.length, PCI_DMA_FROMDEVICE);
+ dma_unmap_single(&dev->pdev->dev, req->req.dma,
+ req->req.length, DMA_FROM_DEVICE);
req->dma_mapped = 0;
req->req.dma = DMA_ADDR_INVALID;
}
@@ -1414,7 +1416,6 @@ static void pch_udc_start_rxrequest(struct pch_udc_ep *ep,
pch_udc_clear_dma(ep->dev, DMA_DIR_RX);
td_data = req->td_data;
- ep->td_data = req->td_data;
/* Set the status bits for all descriptors */
while (1) {
td_data->status = (td_data->status & ~PCH_UDC_BUFF_STS) |
@@ -1613,15 +1614,19 @@ static int pch_udc_pcd_queue(struct usb_ep *usbep, struct usb_request *usbreq,
if (usbreq->length &&
((usbreq->dma == DMA_ADDR_INVALID) || !usbreq->dma)) {
if (ep->in)
- usbreq->dma = pci_map_single(dev->pdev, usbreq->buf,
- usbreq->length, PCI_DMA_TODEVICE);
+ usbreq->dma = dma_map_single(&dev->pdev->dev,
+ usbreq->buf,
+ usbreq->length,
+ DMA_TO_DEVICE);
else
- usbreq->dma = pci_map_single(dev->pdev, usbreq->buf,
- usbreq->length, PCI_DMA_FROMDEVICE);
+ usbreq->dma = dma_map_single(&dev->pdev->dev,
+ usbreq->buf,
+ usbreq->length,
+ DMA_FROM_DEVICE);
req->dma_mapped = 1;
}
if (usbreq->length > 0) {
- retval = prepare_dma(ep, req, gfp);
+ retval = prepare_dma(ep, req, GFP_ATOMIC);
if (retval)
goto probe_end;
}
@@ -1646,7 +1651,6 @@ static int pch_udc_pcd_queue(struct usb_ep *usbep, struct usb_request *usbreq,
pch_udc_wait_ep_stall(ep);
pch_udc_ep_clear_nak(ep);
pch_udc_enable_ep_interrupts(ep->dev, (1 << ep->num));
- pch_udc_set_dma(dev, DMA_DIR_TX);
}
}
/* Now add this request to the ep's pending requests */
@@ -1926,6 +1930,7 @@ static void pch_udc_complete_receiver(struct pch_udc_ep *ep)
PCH_UDC_BS_DMA_DONE)
return;
pch_udc_clear_dma(ep->dev, DMA_DIR_RX);
+ pch_udc_ep_set_ddptr(ep, 0);
if ((req->td_data_last->status & PCH_UDC_RXTX_STS) !=
PCH_UDC_RTS_SUCC) {
dev_err(&dev->pdev->dev, "Invalid RXTX status (0x%08x) "
@@ -1963,7 +1968,7 @@ static void pch_udc_svc_data_in(struct pch_udc_dev *dev, int ep_num)
u32 epsts;
struct pch_udc_ep *ep;
- ep = &dev->ep[2*ep_num];
+ ep = &dev->ep[UDC_EPIN_IDX(ep_num)];
epsts = ep->epsts;
ep->epsts = 0;
@@ -2008,7 +2013,7 @@ static void pch_udc_svc_data_out(struct pch_udc_dev *dev, int ep_num)
struct pch_udc_ep *ep;
struct pch_udc_request *req = NULL;
- ep = &dev->ep[2*ep_num + 1];
+ ep = &dev->ep[UDC_EPOUT_IDX(ep_num)];
epsts = ep->epsts;
ep->epsts = 0;
@@ -2025,10 +2030,11 @@ static void pch_udc_svc_data_out(struct pch_udc_dev *dev, int ep_num)
}
if (epsts & UDC_EPSTS_HE)
return;
- if (epsts & UDC_EPSTS_RSS)
+ if (epsts & UDC_EPSTS_RSS) {
pch_udc_ep_set_stall(ep);
pch_udc_enable_ep_interrupts(ep->dev,
PCH_UDC_EPINT(ep->in, ep->num));
+ }
if (epsts & UDC_EPSTS_RCS) {
if (!dev->prot_stall) {
pch_udc_ep_clear_stall(ep);
@@ -2060,8 +2066,10 @@ static void pch_udc_svc_control_in(struct pch_udc_dev *dev)
{
u32 epsts;
struct pch_udc_ep *ep;
+ struct pch_udc_ep *ep_out;
ep = &dev->ep[UDC_EP0IN_IDX];
+ ep_out = &dev->ep[UDC_EP0OUT_IDX];
epsts = ep->epsts;
ep->epsts = 0;
@@ -2073,8 +2081,16 @@ static void pch_udc_svc_control_in(struct pch_udc_dev *dev)
return;
if (epsts & UDC_EPSTS_HE)
return;
- if ((epsts & UDC_EPSTS_TDC) && (!dev->stall))
+ if ((epsts & UDC_EPSTS_TDC) && (!dev->stall)) {
pch_udc_complete_transfer(ep);
+ pch_udc_clear_dma(dev, DMA_DIR_RX);
+ ep_out->td_data->status = (ep_out->td_data->status &
+ ~PCH_UDC_BUFF_STS) |
+ PCH_UDC_BS_HST_RDY;
+ pch_udc_ep_clear_nak(ep_out);
+ pch_udc_set_dma(dev, DMA_DIR_RX);
+ pch_udc_ep_set_rrdy(ep_out);
+ }
/* On IN interrupt, provide data if we have any */
if ((epsts & UDC_EPSTS_IN) && !(epsts & UDC_EPSTS_TDC) &&
!(epsts & UDC_EPSTS_TXEMPTY))
@@ -2102,11 +2118,9 @@ static void pch_udc_svc_control_out(struct pch_udc_dev *dev)
dev->stall = 0;
dev->ep[UDC_EP0IN_IDX].halted = 0;
dev->ep[UDC_EP0OUT_IDX].halted = 0;
- /* In data not ready */
- pch_udc_ep_set_nak(&(dev->ep[UDC_EP0IN_IDX]));
dev->setup_data = ep->td_stp->request;
pch_udc_init_setup_buff(ep->td_stp);
- pch_udc_clear_dma(dev, DMA_DIR_TX);
+ pch_udc_clear_dma(dev, DMA_DIR_RX);
pch_udc_ep_fifo_flush(&(dev->ep[UDC_EP0IN_IDX]),
dev->ep[UDC_EP0IN_IDX].in);
if ((dev->setup_data.bRequestType & USB_DIR_IN))
@@ -2122,14 +2136,23 @@ static void pch_udc_svc_control_out(struct pch_udc_dev *dev)
setup_supported = dev->driver->setup(&dev->gadget,
&dev->setup_data);
spin_lock(&dev->lock);
+
+ if (dev->setup_data.bRequestType & USB_DIR_IN) {
+ ep->td_data->status = (ep->td_data->status &
+ ~PCH_UDC_BUFF_STS) |
+ PCH_UDC_BS_HST_RDY;
+ pch_udc_ep_set_ddptr(ep, ep->td_data_phys);
+ }
/* ep0 in returns data on IN phase */
if (setup_supported >= 0 && setup_supported <
UDC_EP0IN_MAX_PKT_SIZE) {
pch_udc_ep_clear_nak(&(dev->ep[UDC_EP0IN_IDX]));
/* Gadget would have queued a request when
* we called the setup */
- pch_udc_set_dma(dev, DMA_DIR_RX);
- pch_udc_ep_clear_nak(ep);
+ if (!(dev->setup_data.bRequestType & USB_DIR_IN)) {
+ pch_udc_set_dma(dev, DMA_DIR_RX);
+ pch_udc_ep_clear_nak(ep);
+ }
} else if (setup_supported < 0) {
/* if unsupported request, then stall */
pch_udc_ep_set_stall(&(dev->ep[UDC_EP0IN_IDX]));
@@ -2142,22 +2165,13 @@ static void pch_udc_svc_control_out(struct pch_udc_dev *dev)
}
} else if ((((stat & UDC_EPSTS_OUT_MASK) >> UDC_EPSTS_OUT_SHIFT) ==
UDC_EPSTS_OUT_DATA) && !dev->stall) {
- if (list_empty(&ep->queue)) {
- dev_err(&dev->pdev->dev, "%s: No request\n", __func__);
- ep->td_data->status = (ep->td_data->status &
- ~PCH_UDC_BUFF_STS) |
- PCH_UDC_BS_HST_RDY;
- pch_udc_set_dma(dev, DMA_DIR_RX);
- } else {
- /* control write */
- /* next function will pickuo an clear the status */
+ pch_udc_clear_dma(dev, DMA_DIR_RX);
+ pch_udc_ep_set_ddptr(ep, 0);
+ if (!list_empty(&ep->queue)) {
ep->epsts = stat;
-
- pch_udc_svc_data_out(dev, 0);
- /* re-program desc. pointer for possible ZLPs */
- pch_udc_ep_set_ddptr(ep, ep->td_data_phys);
- pch_udc_set_dma(dev, DMA_DIR_RX);
+ pch_udc_svc_data_out(dev, PCH_UDC_EP0);
}
+ pch_udc_set_dma(dev, DMA_DIR_RX);
}
pch_udc_ep_set_rrdy(ep);
}
@@ -2174,7 +2188,7 @@ static void pch_udc_postsvc_epinters(struct pch_udc_dev *dev, int ep_num)
struct pch_udc_ep *ep;
struct pch_udc_request *req;
- ep = &dev->ep[2*ep_num];
+ ep = &dev->ep[UDC_EPIN_IDX(ep_num)];
if (!list_empty(&ep->queue)) {
req = list_entry(ep->queue.next, struct pch_udc_request, queue);
pch_udc_enable_ep_interrupts(ep->dev,
@@ -2196,13 +2210,13 @@ static void pch_udc_read_all_epstatus(struct pch_udc_dev *dev, u32 ep_intr)
for (i = 0; i < PCH_UDC_USED_EP_NUM; i++) {
/* IN */
if (ep_intr & (0x1 << i)) {
- ep = &dev->ep[2*i];
+ ep = &dev->ep[UDC_EPIN_IDX(i)];
ep->epsts = pch_udc_read_ep_status(ep);
pch_udc_clear_ep_status(ep, ep->epsts);
}
/* OUT */
if (ep_intr & (0x10000 << i)) {
- ep = &dev->ep[2*i+1];
+ ep = &dev->ep[UDC_EPOUT_IDX(i)];
ep->epsts = pch_udc_read_ep_status(ep);
pch_udc_clear_ep_status(ep, ep->epsts);
}
@@ -2563,9 +2577,6 @@ static void pch_udc_pcd_reinit(struct pch_udc_dev *dev)
dev->ep[UDC_EP0IN_IDX].ep.maxpacket = UDC_EP0IN_MAX_PKT_SIZE;
dev->ep[UDC_EP0OUT_IDX].ep.maxpacket = UDC_EP0OUT_MAX_PKT_SIZE;
- dev->dma_addr = pci_map_single(dev->pdev, dev->ep0out_buf, 256,
- PCI_DMA_FROMDEVICE);
-
/* remove ep0 in and out from the list. They have own pointer */
list_del_init(&dev->ep[UDC_EP0IN_IDX].ep.ep_list);
list_del_init(&dev->ep[UDC_EP0OUT_IDX].ep.ep_list);
@@ -2637,6 +2648,13 @@ static int init_dma_pools(struct pch_udc_dev *dev)
dev->ep[UDC_EP0IN_IDX].td_stp_phys = 0;
dev->ep[UDC_EP0IN_IDX].td_data = NULL;
dev->ep[UDC_EP0IN_IDX].td_data_phys = 0;
+
+ dev->ep0out_buf = kzalloc(UDC_EP0OUT_BUFF_SIZE * 4, GFP_KERNEL);
+ if (!dev->ep0out_buf)
+ return -ENOMEM;
+ dev->dma_addr = dma_map_single(&dev->pdev->dev, dev->ep0out_buf,
+ UDC_EP0OUT_BUFF_SIZE * 4,
+ DMA_FROM_DEVICE);
return 0;
}
@@ -2700,7 +2718,8 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
pch_udc_disable_interrupts(dev, UDC_DEVINT_MSK);
- /* Assues that there are no pending requets with this driver */
+ /* Assures that there are no pending requests with this driver */
+ driver->disconnect(&dev->gadget);
driver->unbind(&dev->gadget);
dev->gadget.dev.driver = NULL;
dev->driver = NULL;
@@ -2750,6 +2769,11 @@ static void pch_udc_remove(struct pci_dev *pdev)
pci_pool_destroy(dev->stp_requests);
}
+ if (dev->dma_addr)
+ dma_unmap_single(&dev->pdev->dev, dev->dma_addr,
+ UDC_EP0OUT_BUFF_SIZE * 4, DMA_FROM_DEVICE);
+ kfree(dev->ep0out_buf);
+
pch_udc_exit(dev);
if (dev->irq_registered)
@@ -2792,11 +2816,7 @@ static int pch_udc_resume(struct pci_dev *pdev)
int ret;
pci_set_power_state(pdev, PCI_D0);
- ret = pci_restore_state(pdev);
- if (ret) {
- dev_err(&pdev->dev, "%s: pci_restore_state failed\n", __func__);
- return ret;
- }
+ pci_restore_state(pdev);
ret = pci_enable_device(pdev);
if (ret) {
dev_err(&pdev->dev, "%s: pci_enable_device failed\n", __func__);
@@ -2914,6 +2934,11 @@ static DEFINE_PCI_DEVICE_TABLE(pch_udc_pcidev_id) = {
.class = (PCI_CLASS_SERIAL_USB << 8) | 0xfe,
.class_mask = 0xffffffff,
},
+ {
+ PCI_DEVICE(PCI_VENDOR_ID_ROHM, PCI_DEVICE_ID_ML7213_IOH_UDC),
+ .class = (PCI_CLASS_SERIAL_USB << 8) | 0xfe,
+ .class_mask = 0xffffffff,
+ },
{ 0 },
};
diff --git a/drivers/usb/gadget/printer.c b/drivers/usb/gadget/printer.c
index 2fc8636..12ff6cf 100644
--- a/drivers/usb/gadget/printer.c
+++ b/drivers/usb/gadget/printer.c
@@ -131,31 +131,31 @@ static struct printer_dev usb_printer_gadget;
* parameters are in UTF-8 (superset of ASCII's 7 bit characters).
*/
-static ushort __initdata idVendor;
+static ushort idVendor;
module_param(idVendor, ushort, S_IRUGO);
MODULE_PARM_DESC(idVendor, "USB Vendor ID");
-static ushort __initdata idProduct;
+static ushort idProduct;
module_param(idProduct, ushort, S_IRUGO);
MODULE_PARM_DESC(idProduct, "USB Product ID");
-static ushort __initdata bcdDevice;
+static ushort bcdDevice;
module_param(bcdDevice, ushort, S_IRUGO);
MODULE_PARM_DESC(bcdDevice, "USB Device version (BCD)");
-static char *__initdata iManufacturer;
+static char *iManufacturer;
module_param(iManufacturer, charp, S_IRUGO);
MODULE_PARM_DESC(iManufacturer, "USB Manufacturer string");
-static char *__initdata iProduct;
+static char *iProduct;
module_param(iProduct, charp, S_IRUGO);
MODULE_PARM_DESC(iProduct, "USB Product string");
-static char *__initdata iSerialNum;
+static char *iSerialNum;
module_param(iSerialNum, charp, S_IRUGO);
MODULE_PARM_DESC(iSerialNum, "1");
-static char *__initdata iPNPstring;
+static char *iPNPstring;
module_param(iPNPstring, charp, S_IRUGO);
MODULE_PARM_DESC(iPNPstring, "MFG:linux;MDL:g_printer;CLS:PRINTER;SN:1;");
@@ -1596,13 +1596,12 @@ cleanup(void)
int status;
mutex_lock(&usb_printer_gadget.lock_printer_io);
- class_destroy(usb_gadget_class);
- unregister_chrdev_region(g_printer_devno, 2);
-
status = usb_gadget_unregister_driver(&printer_driver);
if (status)
ERROR(dev, "usb_gadget_unregister_driver %x\n", status);
+ unregister_chrdev_region(g_printer_devno, 2);
+ class_destroy(usb_gadget_class);
mutex_unlock(&usb_printer_gadget.lock_printer_io);
}
module_exit(cleanup);
diff --git a/drivers/usb/gadget/storage_common.c b/drivers/usb/gadget/storage_common.c
index 3b513ba..b015561 100644
--- a/drivers/usb/gadget/storage_common.c
+++ b/drivers/usb/gadget/storage_common.c
@@ -543,7 +543,7 @@ static int fsg_lun_open(struct fsg_lun *curlun, const char *filename)
ro = curlun->initially_ro;
if (!ro) {
filp = filp_open(filename, O_RDWR | O_LARGEFILE, 0);
- if (-EROFS == PTR_ERR(filp))
+ if (PTR_ERR(filp) == -EROFS || PTR_ERR(filp) == -EACCES)
ro = 1;
}
if (ro)
@@ -558,10 +558,7 @@ static int fsg_lun_open(struct fsg_lun *curlun, const char *filename)
if (filp->f_path.dentry)
inode = filp->f_path.dentry->d_inode;
- if (inode && S_ISBLK(inode->i_mode)) {
- if (bdev_read_only(inode->i_bdev))
- ro = 1;
- } else if (!inode || !S_ISREG(inode->i_mode)) {
+ if (!inode || (!S_ISREG(inode->i_mode) && !S_ISBLK(inode->i_mode))) {
LINFO(curlun, "invalid file type: %s\n", filename);
goto out;
}
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
index 86e4289..5c761df 100644
--- a/drivers/usb/host/ehci-fsl.c
+++ b/drivers/usb/host/ehci-fsl.c
@@ -52,7 +52,6 @@ static int usb_hcd_fsl_probe(const struct hc_driver *driver,
struct resource *res;
int irq;
int retval;
- unsigned int temp;
pr_debug("initializing FSL-SOC USB Controller\n");
@@ -126,18 +125,6 @@ static int usb_hcd_fsl_probe(const struct hc_driver *driver,
goto err3;
}
- /*
- * Check if it is MPC5121 SoC, otherwise set pdata->have_sysif_regs
- * flag for 83xx or 8536 system interface registers.
- */
- if (pdata->big_endian_mmio)
- temp = in_be32(hcd->regs + FSL_SOC_USB_ID);
- else
- temp = in_le32(hcd->regs + FSL_SOC_USB_ID);
-
- if ((temp & ID_MSK) != (~((temp & NID_MSK) >> 8) & ID_MSK))
- pdata->have_sysif_regs = 1;
-
/* Enable USB controller, 83xx or 8536 */
if (pdata->have_sysif_regs)
setbits32(hcd->regs + FSL_SOC_USB_CTRL, 0x4);
diff --git a/drivers/usb/host/ehci-fsl.h b/drivers/usb/host/ehci-fsl.h
index 2c83537..3fabed3 100644
--- a/drivers/usb/host/ehci-fsl.h
+++ b/drivers/usb/host/ehci-fsl.h
@@ -19,9 +19,6 @@
#define _EHCI_FSL_H
/* offsets for the non-ehci registers in the FSL SOC USB controller */
-#define FSL_SOC_USB_ID 0x0
-#define ID_MSK 0x3f
-#define NID_MSK 0x3f00
#define FSL_SOC_USB_ULPIVP 0x170
#define FSL_SOC_USB_PORTSC1 0x184
#define PORT_PTS_MSK (3<<30)
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 6fee3cd..74dcf49 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -572,6 +572,8 @@ static int ehci_init(struct usb_hcd *hcd)
ehci->iaa_watchdog.function = ehci_iaa_watchdog;
ehci->iaa_watchdog.data = (unsigned long) ehci;
+ hcc_params = ehci_readl(ehci, &ehci->caps->hcc_params);
+
/*
* hw default: 1K periodic list heads, one per frame.
* periodic_size can shrink by USBCMD update if hcc_params allows.
@@ -579,11 +581,20 @@ static int ehci_init(struct usb_hcd *hcd)
ehci->periodic_size = DEFAULT_I_TDPS;
INIT_LIST_HEAD(&ehci->cached_itd_list);
INIT_LIST_HEAD(&ehci->cached_sitd_list);
+
+ if (HCC_PGM_FRAMELISTLEN(hcc_params)) {
+ /* periodic schedule size can be smaller than default */
+ switch (EHCI_TUNE_FLS) {
+ case 0: ehci->periodic_size = 1024; break;
+ case 1: ehci->periodic_size = 512; break;
+ case 2: ehci->periodic_size = 256; break;
+ default: BUG();
+ }
+ }
if ((retval = ehci_mem_init(ehci, GFP_KERNEL)) < 0)
return retval;
/* controllers may cache some of the periodic schedule ... */
- hcc_params = ehci_readl(ehci, &ehci->caps->hcc_params);
if (HCC_ISOC_CACHE(hcc_params)) // full frame cache
ehci->i_thresh = 2 + 8;
else // N microframes cached
@@ -637,12 +648,6 @@ static int ehci_init(struct usb_hcd *hcd)
/* periodic schedule size can be smaller than default */
temp &= ~(3 << 2);
temp |= (EHCI_TUNE_FLS << 2);
- switch (EHCI_TUNE_FLS) {
- case 0: ehci->periodic_size = 1024; break;
- case 1: ehci->periodic_size = 512; break;
- case 2: ehci->periodic_size = 256; break;
- default: BUG();
- }
}
if (HCC_LPM(hcc_params)) {
/* support link power management EHCI 1.1 addendum */
diff --git a/drivers/usb/host/ehci-mxc.c b/drivers/usb/host/ehci-mxc.c
index fa59b26..c8e360d 100644
--- a/drivers/usb/host/ehci-mxc.c
+++ b/drivers/usb/host/ehci-mxc.c
@@ -21,10 +21,13 @@
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/usb/otg.h>
+#include <linux/usb/ulpi.h>
#include <linux/slab.h>
#include <mach/mxc_ehci.h>
+#include <asm/mach-types.h>
+
#define ULPI_VIEWPORT_OFFSET 0x170
struct ehci_mxc_priv {
@@ -114,6 +117,7 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev)
struct usb_hcd *hcd;
struct resource *res;
int irq, ret;
+ unsigned int flags;
struct ehci_mxc_priv *priv;
struct device *dev = &pdev->dev;
struct ehci_hcd *ehci;
@@ -177,8 +181,8 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev)
clk_enable(priv->ahbclk);
}
- /* "dr" device has its own clock */
- if (pdev->id == 0) {
+ /* "dr" device has its own clock on i.MX51 */
+ if (cpu_is_mx51() && (pdev->id == 0)) {
priv->phy1clk = clk_get(dev, "usb_phy1");
if (IS_ERR(priv->phy1clk)) {
ret = PTR_ERR(priv->phy1clk);
@@ -240,6 +244,23 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev)
if (ret)
goto err_add;
+ if (pdata->otg) {
+ /*
+ * efikamx and efikasb have some hardware bug which is
+ * preventing usb to work unless CHRGVBUS is set.
+ * It's in violation of USB specs
+ */
+ if (machine_is_mx51_efikamx() || machine_is_mx51_efikasb()) {
+ flags = otg_io_read(pdata->otg, ULPI_OTG_CTRL);
+ flags |= ULPI_OTG_CTRL_CHRGVBUS;
+ ret = otg_io_write(pdata->otg, flags, ULPI_OTG_CTRL);
+ if (ret) {
+ dev_err(dev, "unable to set CHRVBUS\n");
+ goto err_add;
+ }
+ }
+ }
+
return 0;
err_add:
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
index 76179c3..bed07d4 100644
--- a/drivers/usb/host/ehci-pci.c
+++ b/drivers/usb/host/ehci-pci.c
@@ -44,28 +44,35 @@ static int ehci_pci_reinit(struct ehci_hcd *ehci, struct pci_dev *pdev)
return 0;
}
-static int ehci_quirk_amd_SB800(struct ehci_hcd *ehci)
+static int ehci_quirk_amd_hudson(struct ehci_hcd *ehci)
{
struct pci_dev *amd_smbus_dev;
u8 rev = 0;
amd_smbus_dev = pci_get_device(PCI_VENDOR_ID_ATI, 0x4385, NULL);
- if (!amd_smbus_dev)
- return 0;
-
- pci_read_config_byte(amd_smbus_dev, PCI_REVISION_ID, &rev);
- if (rev < 0x40) {
- pci_dev_put(amd_smbus_dev);
- amd_smbus_dev = NULL;
- return 0;
+ if (amd_smbus_dev) {
+ pci_read_config_byte(amd_smbus_dev, PCI_REVISION_ID, &rev);
+ if (rev < 0x40) {
+ pci_dev_put(amd_smbus_dev);
+ amd_smbus_dev = NULL;
+ return 0;
+ }
+ } else {
+ amd_smbus_dev = pci_get_device(PCI_VENDOR_ID_AMD, 0x780b, NULL);
+ if (!amd_smbus_dev)
+ return 0;
+ pci_read_config_byte(amd_smbus_dev, PCI_REVISION_ID, &rev);
+ if (rev < 0x11 || rev > 0x18) {
+ pci_dev_put(amd_smbus_dev);
+ amd_smbus_dev = NULL;
+ return 0;
+ }
}
if (!amd_nb_dev)
amd_nb_dev = pci_get_device(PCI_VENDOR_ID_AMD, 0x1510, NULL);
- if (!amd_nb_dev)
- ehci_err(ehci, "QUIRK: unable to get AMD NB device\n");
- ehci_info(ehci, "QUIRK: Enable AMD SB800 L1 fix\n");
+ ehci_info(ehci, "QUIRK: Enable exception for AMD Hudson ASPM\n");
pci_dev_put(amd_smbus_dev);
amd_smbus_dev = NULL;
@@ -131,7 +138,7 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
/* cache this readonly data; minimize chip reads */
ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
- if (ehci_quirk_amd_SB800(ehci))
+ if (ehci_quirk_amd_hudson(ehci))
ehci->amd_l1_fix = 1;
retval = ehci_halt(ehci);
diff --git a/drivers/usb/host/fhci-hcd.c b/drivers/usb/host/fhci-hcd.c
index 20092a2..12fd184 100644
--- a/drivers/usb/host/fhci-hcd.c
+++ b/drivers/usb/host/fhci-hcd.c
@@ -98,13 +98,13 @@ void fhci_usb_enable_interrupt(struct fhci_usb *usb)
usb->intr_nesting_cnt--;
}
-/* diable the usb interrupt */
+/* disable the usb interrupt */
void fhci_usb_disable_interrupt(struct fhci_usb *usb)
{
struct fhci_hcd *fhci = usb->fhci;
if (usb->intr_nesting_cnt == 0) {
- /* diable the timer interrupt */
+ /* disable the timer interrupt */
disable_irq_nosync(fhci->timer->irq);
/* disable the usb interrupt */
diff --git a/drivers/usb/host/fhci-tds.c b/drivers/usb/host/fhci-tds.c
index 7be548c..38fe058 100644
--- a/drivers/usb/host/fhci-tds.c
+++ b/drivers/usb/host/fhci-tds.c
@@ -271,8 +271,8 @@ void fhci_init_ep_registers(struct fhci_usb *usb, struct endpoint *ep,
/*
* Collect the submitted frames and inform the application about them
- * It is also prepearing the TDs for new frames. If the Tx interrupts
- * are diabled, the application should call that routine to get
+ * It is also preparing the TDs for new frames. If the Tx interrupts
+ * are disabled, the application should call that routine to get
* confirmation about the submitted frames. Otherwise, the routine is
* called frome the interrupt service routine during the Tx interrupt.
* In that case the application is informed by calling the application
diff --git a/drivers/usb/host/fsl-mph-dr-of.c b/drivers/usb/host/fsl-mph-dr-of.c
index 574b99e..79a66d6 100644
--- a/drivers/usb/host/fsl-mph-dr-of.c
+++ b/drivers/usb/host/fsl-mph-dr-of.c
@@ -262,19 +262,24 @@ static void fsl_usb2_mpc5121_exit(struct platform_device *pdev)
}
}
-struct fsl_usb2_platform_data fsl_usb2_mpc5121_pd = {
+static struct fsl_usb2_platform_data fsl_usb2_mpc5121_pd = {
.big_endian_desc = 1,
.big_endian_mmio = 1,
.es = 1,
+ .have_sysif_regs = 0,
.le_setup_buf = 1,
.init = fsl_usb2_mpc5121_init,
.exit = fsl_usb2_mpc5121_exit,
};
#endif /* CONFIG_PPC_MPC512x */
+static struct fsl_usb2_platform_data fsl_usb2_mpc8xxx_pd = {
+ .have_sysif_regs = 1,
+};
+
static const struct of_device_id fsl_usb2_mph_dr_of_match[] = {
- { .compatible = "fsl-usb2-mph", },
- { .compatible = "fsl-usb2-dr", },
+ { .compatible = "fsl-usb2-mph", .data = &fsl_usb2_mpc8xxx_pd, },
+ { .compatible = "fsl-usb2-dr", .data = &fsl_usb2_mpc8xxx_pd, },
#ifdef CONFIG_PPC_MPC512x
{ .compatible = "fsl,mpc5121-usb2-dr", .data = &fsl_usb2_mpc5121_pd, },
#endif
diff --git a/drivers/usb/host/imx21-hcd.c b/drivers/usb/host/imx21-hcd.c
index e49b75a..f90d003 100644
--- a/drivers/usb/host/imx21-hcd.c
+++ b/drivers/usb/host/imx21-hcd.c
@@ -1658,7 +1658,7 @@ static int imx21_hc_reset(struct usb_hcd *hcd)
spin_lock_irqsave(&imx21->lock, flags);
- /* Reset the Host controler modules */
+ /* Reset the Host controller modules */
writel(USBOTG_RST_RSTCTRL | USBOTG_RST_RSTRH |
USBOTG_RST_RSTHSIE | USBOTG_RST_RSTHC,
imx21->regs + USBOTG_RST_CTRL);
diff --git a/drivers/usb/host/oxu210hp-hcd.c b/drivers/usb/host/oxu210hp-hcd.c
index 32149be..e0cb12b 100644
--- a/drivers/usb/host/oxu210hp-hcd.c
+++ b/drivers/usb/host/oxu210hp-hcd.c
@@ -3094,7 +3094,7 @@ static int oxu_hub_status_data(struct usb_hcd *hcd, char *buf)
/* Some boards (mostly VIA?) report bogus overcurrent indications,
* causing massive log spam unless we completely ignore them. It
- * may be relevant that VIA VT8235 controlers, where PORT_POWER is
+ * may be relevant that VIA VT8235 controllers, where PORT_POWER is
* always set, seem to clear PORT_OCC and PORT_CSC when writing to
* PORT_POWER; that's surprising, but maybe within-spec.
*/
diff --git a/drivers/usb/misc/adutux.c b/drivers/usb/misc/adutux.c
index 44f8b922..a6afd15 100644
--- a/drivers/usb/misc/adutux.c
+++ b/drivers/usb/misc/adutux.c
@@ -717,7 +717,7 @@ static int adu_probe(struct usb_interface *interface,
goto exit;
}
- /* allocate memory for our device state and intialize it */
+ /* allocate memory for our device state and initialize it */
dev = kzalloc(sizeof(struct adu_device), GFP_KERNEL);
if (dev == NULL) {
dev_err(&interface->dev, "Out of memory\n");
diff --git a/drivers/usb/misc/iowarrior.c b/drivers/usb/misc/iowarrior.c
index c9078e4..e573e4704 100644
--- a/drivers/usb/misc/iowarrior.c
+++ b/drivers/usb/misc/iowarrior.c
@@ -769,7 +769,7 @@ static int iowarrior_probe(struct usb_interface *interface,
int i;
int retval = -ENOMEM;
- /* allocate memory for our device state and intialize it */
+ /* allocate memory for our device state and initialize it */
dev = kzalloc(sizeof(struct iowarrior), GFP_KERNEL);
if (dev == NULL) {
dev_err(&interface->dev, "Out of memory\n");
diff --git a/drivers/usb/misc/ldusb.c b/drivers/usb/misc/ldusb.c
index edffef6..eefb827 100644
--- a/drivers/usb/misc/ldusb.c
+++ b/drivers/usb/misc/ldusb.c
@@ -642,7 +642,7 @@ static int ld_usb_probe(struct usb_interface *intf, const struct usb_device_id *
int i;
int retval = -ENOMEM;
- /* allocate memory for our device state and intialize it */
+ /* allocate memory for our device state and initialize it */
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (dev == NULL) {
diff --git a/drivers/usb/misc/usbled.c b/drivers/usb/misc/usbled.c
index 1732d9b..1616ad1 100644
--- a/drivers/usb/misc/usbled.c
+++ b/drivers/usb/misc/usbled.c
@@ -45,7 +45,7 @@ struct usb_led {
static void change_color(struct usb_led *led)
{
- int retval;
+ int retval = 0;
unsigned char *buffer;
buffer = kmalloc(8, GFP_KERNEL);
diff --git a/drivers/usb/misc/uss720.c b/drivers/usb/misc/uss720.c
index 4ff2158..f7a2057 100644
--- a/drivers/usb/misc/uss720.c
+++ b/drivers/usb/misc/uss720.c
@@ -776,7 +776,6 @@ static const struct usb_device_id uss720_table[] = {
{ USB_DEVICE(0x0557, 0x2001) },
{ USB_DEVICE(0x0729, 0x1284) },
{ USB_DEVICE(0x1293, 0x0002) },
- { USB_DEVICE(0x1293, 0x0002) },
{ USB_DEVICE(0x050d, 0x0002) },
{ } /* Terminating entry */
};
diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c
index 9b162df..ed58c6c 100644
--- a/drivers/usb/musb/musb_gadget.c
+++ b/drivers/usb/musb/musb_gadget.c
@@ -1684,7 +1684,7 @@ static inline void __init musb_g_init_endpoints(struct musb *musb)
struct musb_hw_ep *hw_ep;
unsigned count = 0;
- /* intialize endpoint list just once */
+ /* initialize endpoint list just once */
INIT_LIST_HEAD(&(musb->g.ep_list));
for (epnum = 0, hw_ep = musb->endpoints;
@@ -1765,7 +1765,7 @@ void musb_gadget_cleanup(struct musb *musb)
*
* -EINVAL something went wrong (not driver)
* -EBUSY another gadget is already using the controller
- * -ENOMEM no memeory to perform the operation
+ * -ENOMEM no memory to perform the operation
*
* @param driver the gadget driver
* @param bind the driver's bind function
diff --git a/drivers/usb/otg/nop-usb-xceiv.c b/drivers/usb/otg/nop-usb-xceiv.c
index e70014a..8acf165 100644
--- a/drivers/usb/otg/nop-usb-xceiv.c
+++ b/drivers/usb/otg/nop-usb-xceiv.c
@@ -132,6 +132,8 @@ static int __devinit nop_usb_xceiv_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, nop);
+ BLOCKING_INIT_NOTIFIER_HEAD(&nop->otg.notifier);
+
return 0;
exit:
kfree(nop);
diff --git a/drivers/usb/otg/ulpi.c b/drivers/usb/otg/ulpi.c
index 059d9ac..770d799 100644
--- a/drivers/usb/otg/ulpi.c
+++ b/drivers/usb/otg/ulpi.c
@@ -45,7 +45,7 @@ struct ulpi_info {
/* ULPI hardcoded IDs, used for probing */
static struct ulpi_info ulpi_ids[] = {
ULPI_INFO(ULPI_ID(0x04cc, 0x1504), "NXP ISP1504"),
- ULPI_INFO(ULPI_ID(0x0424, 0x0006), "SMSC USB3319"),
+ ULPI_INFO(ULPI_ID(0x0424, 0x0006), "SMSC USB331x"),
};
static int ulpi_set_otg_flags(struct otg_transceiver *otg)
diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c
index 63f7cc4..7b8815d 100644
--- a/drivers/usb/serial/ch341.c
+++ b/drivers/usb/serial/ch341.c
@@ -486,12 +486,22 @@ static void ch341_read_int_callback(struct urb *urb)
if (actual_length >= 4) {
struct ch341_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
+ u8 prev_line_status = priv->line_status;
spin_lock_irqsave(&priv->lock, flags);
priv->line_status = (~(data[2])) & CH341_BITS_MODEM_STAT;
if ((data[1] & CH341_MULT_STAT))
priv->multi_status_change = 1;
spin_unlock_irqrestore(&priv->lock, flags);
+
+ if ((priv->line_status ^ prev_line_status) & CH341_BIT_DCD) {
+ struct tty_struct *tty = tty_port_tty_get(&port->port);
+ if (tty)
+ usb_serial_handle_dcd_change(port, tty,
+ priv->line_status & CH341_BIT_DCD);
+ tty_kref_put(tty);
+ }
+
wake_up_interruptible(&priv->delta_msr_wait);
}
diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c
index 8d7731d..735ea03 100644
--- a/drivers/usb/serial/cp210x.c
+++ b/drivers/usb/serial/cp210x.c
@@ -49,7 +49,6 @@ static int cp210x_tiocmset_port(struct usb_serial_port *port, struct file *,
static void cp210x_break_ctl(struct tty_struct *, int);
static int cp210x_startup(struct usb_serial *);
static void cp210x_dtr_rts(struct usb_serial_port *p, int on);
-static int cp210x_carrier_raised(struct usb_serial_port *p);
static int debug;
@@ -87,7 +86,6 @@ static const struct usb_device_id id_table[] = {
{ USB_DEVICE(0x10C4, 0x8115) }, /* Arygon NFC/Mifare Reader */
{ USB_DEVICE(0x10C4, 0x813D) }, /* Burnside Telecom Deskmobile */
{ USB_DEVICE(0x10C4, 0x813F) }, /* Tams Master Easy Control */
- { USB_DEVICE(0x10C4, 0x8149) }, /* West Mountain Radio Computerized Battery Analyzer */
{ USB_DEVICE(0x10C4, 0x814A) }, /* West Mountain Radio RIGblaster P&P */
{ USB_DEVICE(0x10C4, 0x814B) }, /* West Mountain Radio RIGtalk */
{ USB_DEVICE(0x10C4, 0x8156) }, /* B&G H3000 link cable */
@@ -110,7 +108,9 @@ static const struct usb_device_id id_table[] = {
{ USB_DEVICE(0x10C4, 0x8341) }, /* Siemens MC35PU GPRS Modem */
{ USB_DEVICE(0x10C4, 0x8382) }, /* Cygnal Integrated Products, Inc. */
{ USB_DEVICE(0x10C4, 0x83A8) }, /* Amber Wireless AMB2560 */
+ { USB_DEVICE(0x10C4, 0x83D8) }, /* DekTec DTA Plus VHF/UHF Booster/Attenuator */
{ USB_DEVICE(0x10C4, 0x8411) }, /* Kyocera GPS Module */
+ { USB_DEVICE(0x10C4, 0x8418) }, /* IRZ Automation Teleport SG-10 GSM/GPRS Modem */
{ USB_DEVICE(0x10C4, 0x846E) }, /* BEI USB Sensor Interface (VCP) */
{ USB_DEVICE(0x10C4, 0x8477) }, /* Balluff RFID */
{ USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */
@@ -165,8 +165,7 @@ static struct usb_serial_driver cp210x_device = {
.tiocmget = cp210x_tiocmget,
.tiocmset = cp210x_tiocmset,
.attach = cp210x_startup,
- .dtr_rts = cp210x_dtr_rts,
- .carrier_raised = cp210x_carrier_raised
+ .dtr_rts = cp210x_dtr_rts
};
/* Config request types */
@@ -765,15 +764,6 @@ static int cp210x_tiocmget (struct tty_struct *tty, struct file *file)
return result;
}
-static int cp210x_carrier_raised(struct usb_serial_port *p)
-{
- unsigned int control;
- cp210x_get_config(p, CP210X_GET_MDMSTS, &control, 1);
- if (control & CONTROL_DCD)
- return 1;
- return 0;
-}
-
static void cp210x_break_ctl (struct tty_struct *tty, int break_state)
{
struct usb_serial_port *port = tty->driver_data;
diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c
index b92070c..666e5a6 100644
--- a/drivers/usb/serial/digi_acceleport.c
+++ b/drivers/usb/serial/digi_acceleport.c
@@ -455,7 +455,6 @@ static int digi_write_room(struct tty_struct *tty);
static int digi_chars_in_buffer(struct tty_struct *tty);
static int digi_open(struct tty_struct *tty, struct usb_serial_port *port);
static void digi_close(struct usb_serial_port *port);
-static int digi_carrier_raised(struct usb_serial_port *port);
static void digi_dtr_rts(struct usb_serial_port *port, int on);
static int digi_startup_device(struct usb_serial *serial);
static int digi_startup(struct usb_serial *serial);
@@ -511,7 +510,6 @@ static struct usb_serial_driver digi_acceleport_2_device = {
.open = digi_open,
.close = digi_close,
.dtr_rts = digi_dtr_rts,
- .carrier_raised = digi_carrier_raised,
.write = digi_write,
.write_room = digi_write_room,
.write_bulk_callback = digi_write_bulk_callback,
@@ -1339,14 +1337,6 @@ static void digi_dtr_rts(struct usb_serial_port *port, int on)
digi_set_modem_signals(port, on * (TIOCM_DTR|TIOCM_RTS), 1);
}
-static int digi_carrier_raised(struct usb_serial_port *port)
-{
- struct digi_port *priv = usb_get_serial_port_data(port);
- if (priv->dp_modem_signals & TIOCM_CD)
- return 1;
- return 0;
-}
-
static int digi_open(struct tty_struct *tty, struct usb_serial_port *port)
{
int ret;
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index a2668d0..4787c0c 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -676,7 +676,17 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(FTDI_VID, FTDI_PCDJ_DAC2_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_RRCIRKITS_LOCOBUFFER_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_ASK_RDR400_PID) },
- { USB_DEVICE(ICOM_ID1_VID, ICOM_ID1_PID) },
+ { USB_DEVICE(ICOM_VID, ICOM_ID_1_PID) },
+ { USB_DEVICE(ICOM_VID, ICOM_OPC_U_UC_PID) },
+ { USB_DEVICE(ICOM_VID, ICOM_ID_RP2C1_PID) },
+ { USB_DEVICE(ICOM_VID, ICOM_ID_RP2C2_PID) },
+ { USB_DEVICE(ICOM_VID, ICOM_ID_RP2D_PID) },
+ { USB_DEVICE(ICOM_VID, ICOM_ID_RP2VT_PID) },
+ { USB_DEVICE(ICOM_VID, ICOM_ID_RP2VR_PID) },
+ { USB_DEVICE(ICOM_VID, ICOM_ID_RP4KVT_PID) },
+ { USB_DEVICE(ICOM_VID, ICOM_ID_RP4KVR_PID) },
+ { USB_DEVICE(ICOM_VID, ICOM_ID_RP2KVT_PID) },
+ { USB_DEVICE(ICOM_VID, ICOM_ID_RP2KVR_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_ACG_HFDUAL_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_YEI_SERVOCENTER31_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_THORLABS_PID) },
diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h
index bf08672..ed160de 100644
--- a/drivers/usb/serial/ftdi_sio_ids.h
+++ b/drivers/usb/serial/ftdi_sio_ids.h
@@ -569,11 +569,23 @@
#define OCT_US101_PID 0x0421 /* OCT US101 USB to RS-232 */
/*
- * Icom ID-1 digital transceiver
- */
-
-#define ICOM_ID1_VID 0x0C26
-#define ICOM_ID1_PID 0x0004
+ * Definitions for Icom Inc. devices
+ */
+#define ICOM_VID 0x0C26 /* Icom vendor ID */
+/* Note: ID-1 is a communications tranceiver for HAM-radio operators */
+#define ICOM_ID_1_PID 0x0004 /* ID-1 USB to RS-232 */
+/* Note: OPC is an Optional cable to connect an Icom Tranceiver */
+#define ICOM_OPC_U_UC_PID 0x0018 /* OPC-478UC, OPC-1122U cloning cable */
+/* Note: ID-RP* devices are Icom Repeater Devices for HAM-radio */
+#define ICOM_ID_RP2C1_PID 0x0009 /* ID-RP2C Asset 1 to RS-232 */
+#define ICOM_ID_RP2C2_PID 0x000A /* ID-RP2C Asset 2 to RS-232 */
+#define ICOM_ID_RP2D_PID 0x000B /* ID-RP2D configuration port*/
+#define ICOM_ID_RP2VT_PID 0x000C /* ID-RP2V Transmit config port */
+#define ICOM_ID_RP2VR_PID 0x000D /* ID-RP2V Receive config port */
+#define ICOM_ID_RP4KVT_PID 0x0010 /* ID-RP4000V Transmit config port */
+#define ICOM_ID_RP4KVR_PID 0x0011 /* ID-RP4000V Receive config port */
+#define ICOM_ID_RP2KVT_PID 0x0012 /* ID-RP2000V Transmit config port */
+#define ICOM_ID_RP2KVR_PID 0x0013 /* ID-RP2000V Receive config port */
/*
* GN Otometrics (http://www.otometrics.com)
diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c
index e6833e2..e4db5ad 100644
--- a/drivers/usb/serial/generic.c
+++ b/drivers/usb/serial/generic.c
@@ -479,6 +479,26 @@ int usb_serial_handle_break(struct usb_serial_port *port)
}
EXPORT_SYMBOL_GPL(usb_serial_handle_break);
+/**
+ * usb_serial_handle_dcd_change - handle a change of carrier detect state
+ * @port: usb_serial_port structure for the open port
+ * @tty: tty_struct structure for the port
+ * @status: new carrier detect status, nonzero if active
+ */
+void usb_serial_handle_dcd_change(struct usb_serial_port *usb_port,
+ struct tty_struct *tty, unsigned int status)
+{
+ struct tty_port *port = &usb_port->port;
+
+ dbg("%s - port %d, status %d", __func__, usb_port->number, status);
+
+ if (status)
+ wake_up_interruptible(&port->open_wait);
+ else if (tty && !C_CLOCAL(tty))
+ tty_hangup(tty);
+}
+EXPORT_SYMBOL_GPL(usb_serial_handle_dcd_change);
+
int usb_serial_generic_resume(struct usb_serial *serial)
{
struct usb_serial_port *port;
diff --git a/drivers/usb/serial/io_tables.h b/drivers/usb/serial/io_tables.h
index 6ab2a3f..178b22e 100644
--- a/drivers/usb/serial/io_tables.h
+++ b/drivers/usb/serial/io_tables.h
@@ -199,6 +199,7 @@ 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,
diff --git a/drivers/usb/serial/iuu_phoenix.c b/drivers/usb/serial/iuu_phoenix.c
index 12ed594..99b97c0 100644
--- a/drivers/usb/serial/iuu_phoenix.c
+++ b/drivers/usb/serial/iuu_phoenix.c
@@ -1275,6 +1275,7 @@ 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,
diff --git a/drivers/usb/serial/keyspan.h b/drivers/usb/serial/keyspan.h
index 2d8baf6..ce134dc 100644
--- a/drivers/usb/serial/keyspan.h
+++ b/drivers/usb/serial/keyspan.h
@@ -546,6 +546,7 @@ 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,6 +558,7 @@ 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,
@@ -579,6 +581,7 @@ 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,
@@ -601,6 +604,7 @@ 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,
diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c
index a10dd56..554a869 100644
--- a/drivers/usb/serial/keyspan_pda.c
+++ b/drivers/usb/serial/keyspan_pda.c
@@ -679,22 +679,6 @@ static void keyspan_pda_dtr_rts(struct usb_serial_port *port, int on)
}
}
-static int keyspan_pda_carrier_raised(struct usb_serial_port *port)
-{
- struct usb_serial *serial = port->serial;
- unsigned char modembits;
-
- /* If we can read the modem status and the DCD is low then
- carrier is not raised yet */
- if (keyspan_pda_get_modem_info(serial, &modembits) >= 0) {
- if (!(modembits & (1>>6)))
- return 0;
- }
- /* Carrier raised, or we failed (eg disconnected) so
- progress accordingly */
- return 1;
-}
-
static int keyspan_pda_open(struct tty_struct *tty,
struct usb_serial_port *port)
@@ -881,7 +865,6 @@ static struct usb_serial_driver keyspan_pda_device = {
.id_table = id_table_std,
.num_ports = 1,
.dtr_rts = keyspan_pda_dtr_rts,
- .carrier_raised = keyspan_pda_carrier_raised,
.open = keyspan_pda_open,
.close = keyspan_pda_close,
.write = keyspan_pda_write,
diff --git a/drivers/usb/serial/moto_modem.c b/drivers/usb/serial/moto_modem.c
index cf17183..653465f 100644
--- a/drivers/usb/serial/moto_modem.c
+++ b/drivers/usb/serial/moto_modem.c
@@ -44,6 +44,7 @@ static struct usb_serial_driver moto_device = {
.name = "moto-modem",
},
.id_table = id_table,
+ .usb_driver = &moto_driver,
.num_ports = 1,
};
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index cdfb186..5f46838 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -382,7 +382,16 @@ static void option_instat_callback(struct urb *urb);
#define HAIER_VENDOR_ID 0x201e
#define HAIER_PRODUCT_CE100 0x2009
-#define CINTERION_VENDOR_ID 0x0681
+/* Cinterion (formerly Siemens) products */
+#define SIEMENS_VENDOR_ID 0x0681
+#define CINTERION_VENDOR_ID 0x1e2d
+#define CINTERION_PRODUCT_HC25_MDM 0x0047
+#define CINTERION_PRODUCT_HC25_MDMNET 0x0040
+#define CINTERION_PRODUCT_HC28_MDM 0x004C
+#define CINTERION_PRODUCT_HC28_MDMNET 0x004A /* same for HC28J */
+#define CINTERION_PRODUCT_EU3_E 0x0051
+#define CINTERION_PRODUCT_EU3_P 0x0052
+#define CINTERION_PRODUCT_PH8 0x0053
/* Olivetti products */
#define OLIVETTI_VENDOR_ID 0x0b3c
@@ -615,7 +624,6 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0004, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0005, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0006, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0007, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0008, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0009, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x000a, 0xff, 0xff, 0xff) },
@@ -945,7 +953,17 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100F) },
{ USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1011)},
{ USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1012)},
- { USB_DEVICE(CINTERION_VENDOR_ID, 0x0047) },
+ /* Cinterion */
+ { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_EU3_E) },
+ { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_EU3_P) },
+ { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_PH8) },
+ { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_HC28_MDM) },
+ { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_HC28_MDMNET) },
+ { USB_DEVICE(SIEMENS_VENDOR_ID, CINTERION_PRODUCT_HC25_MDM) },
+ { USB_DEVICE(SIEMENS_VENDOR_ID, CINTERION_PRODUCT_HC25_MDMNET) },
+ { USB_DEVICE(SIEMENS_VENDOR_ID, CINTERION_PRODUCT_HC28_MDM) }, /* HC28 enumerates with Siemens or Cinterion VID depending on FW revision */
+ { USB_DEVICE(SIEMENS_VENDOR_ID, CINTERION_PRODUCT_HC28_MDMNET) },
+
{ USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD100) },
{ USB_DEVICE(CELOT_VENDOR_ID, CELOT_PRODUCT_CT680M) }, /* CT-650 CDMA 450 1xEVDO modem */
{ USB_DEVICE(ONDA_VENDOR_ID, ONDA_MT825UP) }, /* ONDA MT825UP modem */
diff --git a/drivers/usb/serial/oti6858.c b/drivers/usb/serial/oti6858.c
index 5be866b..7361320 100644
--- a/drivers/usb/serial/oti6858.c
+++ b/drivers/usb/serial/oti6858.c
@@ -157,6 +157,7 @@ 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,
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index 8ae4c6c..08c9181 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -50,6 +50,7 @@ static const struct usb_device_id id_table[] = {
{ USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_MMX) },
{ USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_GPRS) },
{ USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_HCR331) },
+ { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_MOTOROLA) },
{ USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID) },
{ USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID_RSAQ5) },
{ USB_DEVICE(ATEN_VENDOR_ID, ATEN_PRODUCT_ID) },
@@ -677,9 +678,11 @@ static void pl2303_update_line_status(struct usb_serial_port *port,
{
struct pl2303_private *priv = usb_get_serial_port_data(port);
+ struct tty_struct *tty;
unsigned long flags;
u8 status_idx = UART_STATE;
u8 length = UART_STATE + 1;
+ u8 prev_line_status;
u16 idv, idp;
idv = le16_to_cpu(port->serial->dev->descriptor.idVendor);
@@ -701,11 +704,20 @@ static void pl2303_update_line_status(struct usb_serial_port *port,
/* Save off the uart status for others to look at */
spin_lock_irqsave(&priv->lock, flags);
+ prev_line_status = priv->line_status;
priv->line_status = data[status_idx];
spin_unlock_irqrestore(&priv->lock, flags);
if (priv->line_status & UART_BREAK_ERROR)
usb_serial_handle_break(port);
wake_up_interruptible(&priv->delta_msr_wait);
+
+ tty = tty_port_tty_get(&port->port);
+ if (!tty)
+ return;
+ if ((priv->line_status ^ prev_line_status) & UART_DCD)
+ usb_serial_handle_dcd_change(port, tty,
+ priv->line_status & UART_DCD);
+ tty_kref_put(tty);
}
static void pl2303_read_int_callback(struct urb *urb)
diff --git a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h
index 43eb9bd..1b025f7 100644
--- a/drivers/usb/serial/pl2303.h
+++ b/drivers/usb/serial/pl2303.h
@@ -21,6 +21,7 @@
#define PL2303_PRODUCT_ID_MMX 0x0612
#define PL2303_PRODUCT_ID_GPRS 0x0609
#define PL2303_PRODUCT_ID_HCR331 0x331a
+#define PL2303_PRODUCT_ID_MOTOROLA 0x0307
#define ATEN_VENDOR_ID 0x0557
#define ATEN_VENDOR_ID2 0x0547
diff --git a/drivers/usb/serial/qcaux.c b/drivers/usb/serial/qcaux.c
index 214a3e5..30b73e6 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_UML290_VZW 0x3718
/* CMOTECH devices */
#define CMOTECH_VENDOR_ID 0x16d8
@@ -66,6 +67,7 @@ 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) },
{ },
};
MODULE_DEVICE_TABLE(usb, id_table);
@@ -84,6 +86,7 @@ static struct usb_serial_driver qcaux_device = {
.name = "qcaux",
},
.id_table = id_table,
+ .usb_driver = &qcaux_driver,
.num_ports = 1,
};
diff --git a/drivers/usb/serial/siemens_mpi.c b/drivers/usb/serial/siemens_mpi.c
index cb8195c..74cd4cc 100644
--- a/drivers/usb/serial/siemens_mpi.c
+++ b/drivers/usb/serial/siemens_mpi.c
@@ -42,6 +42,7 @@ 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,
};
diff --git a/drivers/usb/serial/spcp8x5.c b/drivers/usb/serial/spcp8x5.c
index 765aa98..cbfb70b 100644
--- a/drivers/usb/serial/spcp8x5.c
+++ b/drivers/usb/serial/spcp8x5.c
@@ -133,7 +133,7 @@ struct spcp8x5_usb_ctrl_arg {
/* how come ??? */
#define UART_STATE 0x08
-#define UART_STATE_TRANSIENT_MASK 0x74
+#define UART_STATE_TRANSIENT_MASK 0x75
#define UART_DCD 0x01
#define UART_DSR 0x02
#define UART_BREAK_ERROR 0x04
@@ -525,6 +525,10 @@ static void spcp8x5_process_read_urb(struct urb *urb)
/* overrun is special, not associated with a char */
if (status & UART_OVERRUN_ERROR)
tty_insert_flip_char(tty, 0, TTY_OVERRUN);
+
+ if (status & UART_DCD)
+ usb_serial_handle_dcd_change(port, tty,
+ priv->line_status & MSR_STATUS_LINE_DCD);
}
tty_insert_flip_string_fixed_flag(tty, data, tty_flag,
@@ -645,6 +649,7 @@ 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,
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index 6954de5..546a521 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -1344,11 +1344,15 @@ int usb_serial_register(struct usb_serial_driver *driver)
return -ENODEV;
fixup_generic(driver);
- if (driver->usb_driver)
- driver->usb_driver->supports_autosuspend = 1;
if (!driver->description)
driver->description = driver->driver.name;
+ if (!driver->usb_driver) {
+ WARN(1, "Serial driver %s has no usb_driver\n",
+ driver->description);
+ return -EINVAL;
+ }
+ driver->usb_driver->supports_autosuspend = 1;
/* Add this device to our list of devices */
mutex_lock(&table_lock);
diff --git a/drivers/usb/serial/usb_debug.c b/drivers/usb/serial/usb_debug.c
index f2ed6a3..95a8214 100644
--- a/drivers/usb/serial/usb_debug.c
+++ b/drivers/usb/serial/usb_debug.c
@@ -75,6 +75,7 @@ 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,
diff --git a/drivers/usb/storage/unusual_cypress.h b/drivers/usb/storage/unusual_cypress.h
index c854fde..2c85530 100644
--- a/drivers/usb/storage/unusual_cypress.h
+++ b/drivers/usb/storage/unusual_cypress.h
@@ -31,4 +31,9 @@ UNUSUAL_DEV( 0x04b4, 0x6831, 0x0000, 0x9999,
"Cypress ISD-300LP",
USB_SC_CYP_ATACB, USB_PR_DEVICE, NULL, 0),
+UNUSUAL_DEV( 0x14cd, 0x6116, 0x0000, 0x9999,
+ "Super Top",
+ "USB 2.0 SATA BRIDGE",
+ USB_SC_CYP_ATACB, USB_PR_DEVICE, NULL, 0),
+
#endif /* defined(CONFIG_USB_STORAGE_CYPRESS_ATACB) || ... */
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
index fcc1e32..24bd5d7 100644
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -1044,6 +1044,15 @@ UNUSUAL_DEV( 0x084d, 0x0011, 0x0110, 0x0110,
USB_SC_DEVICE, USB_PR_DEVICE, NULL,
US_FL_BULK32),
+/* Reported by <ttkspam@free.fr>
+ * The device reports a vendor-specific device class, requiring an
+ * explicit vendor/product match.
+ */
+UNUSUAL_DEV( 0x0851, 0x1542, 0x0002, 0x0002,
+ "MagicPixel",
+ "FW_Omega2",
+ USB_SC_DEVICE, USB_PR_DEVICE, NULL, 0),
+
/* Andrew Lunn <andrew@lunn.ch>
* PanDigital Digital Picture Frame. Does not like ALLOW_MEDIUM_REMOVAL
* on LUN 4.
@@ -1872,6 +1881,15 @@ UNUSUAL_DEV( 0x1908, 0x3335, 0x0200, 0x0200,
USB_SC_DEVICE, USB_PR_DEVICE, NULL,
US_FL_NO_READ_DISC_INFO ),
+/* Patch by Richard Schütz <r.schtz@t-online.de>
+ * This external hard drive enclosure uses a JMicron chip which
+ * needs the US_FL_IGNORE_RESIDUE flag to work properly. */
+UNUSUAL_DEV( 0x1e68, 0x001b, 0x0000, 0x0000,
+ "TrekStor GmbH & Co. KG",
+ "DataStation maxi g.u",
+ USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+ US_FL_IGNORE_RESIDUE | US_FL_SANE_SENSE ),
+
UNUSUAL_DEV( 0x2116, 0x0320, 0x0001, 0x0001,
"ST",
"2A",
diff --git a/drivers/usb/wusbcore/wa-rpipe.c b/drivers/usb/wusbcore/wa-rpipe.c
index c7b1d81..8cb9d80 100644
--- a/drivers/usb/wusbcore/wa-rpipe.c
+++ b/drivers/usb/wusbcore/wa-rpipe.c
@@ -49,7 +49,7 @@
*
* USB Stack port number 4 (1 based)
* WUSB code port index 3 (0 based)
- * USB Addresss 5 (2 based -- 0 is for default, 1 for root hub)
+ * USB Address 5 (2 based -- 0 is for default, 1 for root hub)
*
* Now, because we don't use the concept as default address exactly
* like the (wired) USB code does, we need to kind of skip it. So we
OpenPOWER on IntegriCloud