Merge branch 'usb-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6
* 'usb-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6: (42 commits) usb: gadget: composite: avoid access beyond array max length USB: serial: handle Data Carrier Detect changes USB: gadget: Fix endpoint representation in ci13xxx_udc USB: gadget: Fix error path in ci13xxx_udc gadget probe function usb: pch_udc: Fix the worning log issue at gadget driver remove USB: serial: Updated support for ICOM devices USB: ehci-mxc: add work-around for efika mx/sb bug USB: unbreak ehci-mxc on otg port of i.MX27 drivers: update to pl2303 usb-serial to support Motorola cables USB: adding USB support for Cinterion's HC2x, EU3 and PH8 products USB serial: add missing .usb_driver field in serial drivers USB: ehci-fsl: Fix 'have_sysif_regs' detection USB: g_printer: fix bug in module parameter definitions USB: g_printer: fix bug in unregistration USB: uss720: remove duplicate USB device MAINTAINERS: add ueagle-atm entry USB: EHCI: fix DMA deallocation bug USB: pch_udc: support new device ML7213 IOH usb: pch_udc: Fixed issue which does not work with g_serial usb: set ep_dev async suspend should be later than device_initialize ...
This commit is contained in:
commit
cbae48738f
|
@ -3139,6 +3139,12 @@ S: Maintained
|
|||
F: net/ieee802154/
|
||||
F: drivers/ieee802154/
|
||||
|
||||
IKANOS/ADI EAGLE ADSL USB DRIVER
|
||||
M: Matthieu Castet <castet.matthieu@free.fr>
|
||||
M: Stanislaw Gruszka <stf_xl@wp.pl>
|
||||
S: Maintained
|
||||
F: drivers/usb/atm/ueagle-atm.c
|
||||
|
||||
INTEGRITY MEASUREMENT ARCHITECTURE (IMA)
|
||||
M: Mimi Zohar <zohar@us.ibm.com>
|
||||
S: Supported
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -405,6 +405,11 @@ static int suspend_common(struct device *dev, bool do_wakeup)
|
|||
return retval;
|
||||
}
|
||||
|
||||
/* If MSI-X is enabled, the driver will have synchronized all vectors
|
||||
* in pci_suspend(). If MSI or legacy PCI is enabled, that will be
|
||||
* synchronized here.
|
||||
*/
|
||||
if (!hcd->msix_enabled)
|
||||
synchronize_irq(pci_dev->irq);
|
||||
|
||||
/* Downstream ports from this root hub should already be quiesced, so
|
||||
|
|
|
@ -676,6 +676,8 @@ static void hub_init_func3(struct work_struct *ws);
|
|||
static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
|
||||
{
|
||||
struct usb_device *hdev = hub->hdev;
|
||||
struct usb_hcd *hcd;
|
||||
int ret;
|
||||
int port1;
|
||||
int status;
|
||||
bool need_debounce_delay = false;
|
||||
|
@ -714,6 +716,25 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
|
|||
usb_autopm_get_interface_no_resume(
|
||||
to_usb_interface(hub->intfdev));
|
||||
return; /* Continues at init2: below */
|
||||
} else if (type == HUB_RESET_RESUME) {
|
||||
/* The internal host controller state for the hub device
|
||||
* may be gone after a host power loss on system resume.
|
||||
* Update the device's info so the HW knows it's a hub.
|
||||
*/
|
||||
hcd = bus_to_hcd(hdev->bus);
|
||||
if (hcd->driver->update_hub_device) {
|
||||
ret = hcd->driver->update_hub_device(hcd, hdev,
|
||||
&hub->tt, GFP_NOIO);
|
||||
if (ret < 0) {
|
||||
dev_err(hub->intfdev, "Host not "
|
||||
"accepting hub info "
|
||||
"update.\n");
|
||||
dev_err(hub->intfdev, "LS/FS devices "
|
||||
"and hubs may not work "
|
||||
"under this hub\n.");
|
||||
}
|
||||
}
|
||||
hub_power_on(hub, true);
|
||||
} else {
|
||||
hub_power_on(hub, true);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,16 +1315,14 @@ 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)
|
||||
list_for_each(ptr, &udc->ci13xxx_ep[i].qh.queue)
|
||||
{
|
||||
req = list_entry(ptr,
|
||||
struct ci13xxx_req, queue);
|
||||
req = list_entry(ptr, struct ci13xxx_req, queue);
|
||||
|
||||
n += scnprintf(buf + n, PAGE_SIZE - n,
|
||||
"EP=%02i: TD=%08X %s\n",
|
||||
i, (u32)req->dma,
|
||||
((k == RX) ? "RX" : "TX"));
|
||||
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,
|
||||
|
@ -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);
|
||||
trace("%p", udc);
|
||||
|
||||
/* mEp is always valid & configured */
|
||||
|
||||
if (mEp->type == USB_ENDPOINT_XFER_CONTROL)
|
||||
mEp->dir = (mEp->dir == TX) ? RX : TX;
|
||||
|
||||
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,30 +2006,23 @@ 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);
|
||||
|
||||
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;
|
||||
mEp->qh.ptr->cap |= QH_IOS;
|
||||
else if (mEp->type == USB_ENDPOINT_XFER_ISOC)
|
||||
mEp->qh[mEp->dir].ptr->cap &= ~QH_MULT;
|
||||
mEp->qh.ptr->cap &= ~QH_MULT;
|
||||
else
|
||||
mEp->qh[mEp->dir].ptr->cap &= ~QH_ZLT;
|
||||
mEp->qh.ptr->cap &= ~QH_ZLT;
|
||||
|
||||
mEp->qh[mEp->dir].ptr->cap |=
|
||||
mEp->qh.ptr->cap |=
|
||||
(mEp->ep.maxpacket << ffs_nr(QH_MAX_PKT)) & QH_MAX_PKT;
|
||||
mEp->qh[mEp->dir].ptr->td.next |= TD_TERMINATE; /* needed? */
|
||||
mEp->qh.ptr->td.next |= TD_TERMINATE; /* needed? */
|
||||
|
||||
retval |= hw_ep_enable(mEp->num, mEp->dir, mEp->type);
|
||||
|
||||
if (mEp->type == USB_ENDPOINT_XFER_CONTROL)
|
||||
mEp->dir = (mEp->dir == TX) ? RX : TX;
|
||||
|
||||
} while (mEp->dir != direction);
|
||||
|
||||
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,14 +2436,16 @@ 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;
|
||||
|
@ -2444,28 +2455,27 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
|
|||
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));
|
||||
}
|
||||
memset(mEp->qh.ptr, 0, sizeof(*mEp->qh.ptr));
|
||||
|
||||
/* skip ep0 out and in endpoints */
|
||||
if (i == 0)
|
||||
udc->gadget.ep0 = &mEp->ep;
|
||||
else
|
||||
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);
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -928,7 +928,8 @@ unknown:
|
|||
*/
|
||||
switch (ctrl->bRequestType & USB_RECIP_MASK) {
|
||||
case USB_RECIP_INTERFACE:
|
||||
if (cdev->config)
|
||||
if (!cdev->config || w_index >= MAX_CONFIG_INTERFACES)
|
||||
break;
|
||||
f = cdev->config->interface[intf];
|
||||
break;
|
||||
|
||||
|
|
|
@ -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 */
|
||||
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 },
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
|
||||
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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -308,11 +308,8 @@ static int room_on_ring(struct xhci_hcd *xhci, struct xhci_ring *ring,
|
|||
/* Ring the host controller doorbell after placing a command on the ring */
|
||||
void xhci_ring_cmd_db(struct xhci_hcd *xhci)
|
||||
{
|
||||
u32 temp;
|
||||
|
||||
xhci_dbg(xhci, "// Ding dong!\n");
|
||||
temp = xhci_readl(xhci, &xhci->dba->doorbell[0]) & DB_MASK;
|
||||
xhci_writel(xhci, temp | DB_TARGET_HOST, &xhci->dba->doorbell[0]);
|
||||
xhci_writel(xhci, DB_VALUE_HOST, &xhci->dba->doorbell[0]);
|
||||
/* Flush PCI posted writes */
|
||||
xhci_readl(xhci, &xhci->dba->doorbell[0]);
|
||||
}
|
||||
|
@ -322,26 +319,24 @@ void xhci_ring_ep_doorbell(struct xhci_hcd *xhci,
|
|||
unsigned int ep_index,
|
||||
unsigned int stream_id)
|
||||
{
|
||||
struct xhci_virt_ep *ep;
|
||||
unsigned int ep_state;
|
||||
u32 field;
|
||||
__u32 __iomem *db_addr = &xhci->dba->doorbell[slot_id];
|
||||
struct xhci_virt_ep *ep = &xhci->devs[slot_id]->eps[ep_index];
|
||||
unsigned int ep_state = ep->ep_state;
|
||||
|
||||
ep = &xhci->devs[slot_id]->eps[ep_index];
|
||||
ep_state = ep->ep_state;
|
||||
/* Don't ring the doorbell for this endpoint if there are pending
|
||||
* cancellations because the we don't want to interrupt processing.
|
||||
* cancellations because we don't want to interrupt processing.
|
||||
* We don't want to restart any stream rings if there's a set dequeue
|
||||
* pointer command pending because the device can choose to start any
|
||||
* stream once the endpoint is on the HW schedule.
|
||||
* FIXME - check all the stream rings for pending cancellations.
|
||||
*/
|
||||
if (!(ep_state & EP_HALT_PENDING) && !(ep_state & SET_DEQ_PENDING)
|
||||
&& !(ep_state & EP_HALTED)) {
|
||||
field = xhci_readl(xhci, db_addr) & DB_MASK;
|
||||
field |= EPI_TO_DB(ep_index) | STREAM_ID_TO_DB(stream_id);
|
||||
xhci_writel(xhci, field, db_addr);
|
||||
}
|
||||
if ((ep_state & EP_HALT_PENDING) || (ep_state & SET_DEQ_PENDING) ||
|
||||
(ep_state & EP_HALTED))
|
||||
return;
|
||||
xhci_writel(xhci, DB_VALUE(ep_index, stream_id), db_addr);
|
||||
/* The CPU has better things to do at this point than wait for a
|
||||
* write-posting flush. It'll get there soon enough.
|
||||
*/
|
||||
}
|
||||
|
||||
/* Ring the doorbell for any rings with pending URBs */
|
||||
|
@ -1188,7 +1183,7 @@ static void handle_port_status(struct xhci_hcd *xhci,
|
|||
|
||||
addr = &xhci->op_regs->port_status_base + NUM_PORT_REGS * (port_id - 1);
|
||||
temp = xhci_readl(xhci, addr);
|
||||
if ((temp & PORT_CONNECT) && (hcd->state == HC_STATE_SUSPENDED)) {
|
||||
if (hcd->state == HC_STATE_SUSPENDED) {
|
||||
xhci_dbg(xhci, "resume root hub\n");
|
||||
usb_hcd_resume_root_hub(hcd);
|
||||
}
|
||||
|
@ -1710,8 +1705,7 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td,
|
|||
/* Others already handled above */
|
||||
break;
|
||||
}
|
||||
dev_dbg(&td->urb->dev->dev,
|
||||
"ep %#x - asked for %d bytes, "
|
||||
xhci_dbg(xhci, "ep %#x - asked for %d bytes, "
|
||||
"%d bytes untransferred\n",
|
||||
td->urb->ep->desc.bEndpointAddress,
|
||||
td->urb->transfer_buffer_length,
|
||||
|
@ -2389,7 +2383,8 @@ static unsigned int count_sg_trbs_needed(struct xhci_hcd *xhci, struct urb *urb)
|
|||
}
|
||||
xhci_dbg(xhci, "\n");
|
||||
if (!in_interrupt())
|
||||
dev_dbg(&urb->dev->dev, "ep %#x - urb len = %d, sglist used, num_trbs = %d\n",
|
||||
xhci_dbg(xhci, "ep %#x - urb len = %d, sglist used, "
|
||||
"num_trbs = %d\n",
|
||||
urb->ep->desc.bEndpointAddress,
|
||||
urb->transfer_buffer_length,
|
||||
num_trbs);
|
||||
|
@ -2414,14 +2409,17 @@ static void check_trb_math(struct urb *urb, int num_trbs, int running_total)
|
|||
|
||||
static void giveback_first_trb(struct xhci_hcd *xhci, int slot_id,
|
||||
unsigned int ep_index, unsigned int stream_id, int start_cycle,
|
||||
struct xhci_generic_trb *start_trb, struct xhci_td *td)
|
||||
struct xhci_generic_trb *start_trb)
|
||||
{
|
||||
/*
|
||||
* Pass all the TRBs to the hardware at once and make sure this write
|
||||
* isn't reordered.
|
||||
*/
|
||||
wmb();
|
||||
if (start_cycle)
|
||||
start_trb->field[3] |= start_cycle;
|
||||
else
|
||||
start_trb->field[3] &= ~0x1;
|
||||
xhci_ring_ep_doorbell(xhci, slot_id, ep_index, stream_id);
|
||||
}
|
||||
|
||||
|
@ -2449,7 +2447,7 @@ int xhci_queue_intr_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
|
|||
* to set the polling interval (once the API is added).
|
||||
*/
|
||||
if (xhci_interval != ep_interval) {
|
||||
if (!printk_ratelimit())
|
||||
if (printk_ratelimit())
|
||||
dev_dbg(&urb->dev->dev, "Driver uses different interval"
|
||||
" (%d microframe%s) than xHCI "
|
||||
"(%d microframe%s)\n",
|
||||
|
@ -2551,9 +2549,11 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
|
|||
u32 remainder = 0;
|
||||
|
||||
/* Don't change the cycle bit of the first TRB until later */
|
||||
if (first_trb)
|
||||
if (first_trb) {
|
||||
first_trb = false;
|
||||
else
|
||||
if (start_cycle == 0)
|
||||
field |= 0x1;
|
||||
} else
|
||||
field |= ep_ring->cycle_state;
|
||||
|
||||
/* Chain all the TRBs together; clear the chain bit in the last
|
||||
|
@ -2625,7 +2625,7 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
|
|||
|
||||
check_trb_math(urb, num_trbs, running_total);
|
||||
giveback_first_trb(xhci, slot_id, ep_index, urb->stream_id,
|
||||
start_cycle, start_trb, td);
|
||||
start_cycle, start_trb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -2671,7 +2671,8 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
|
|||
/* FIXME: this doesn't deal with URB_ZERO_PACKET - need one more */
|
||||
|
||||
if (!in_interrupt())
|
||||
dev_dbg(&urb->dev->dev, "ep %#x - urb len = %#x (%d), addr = %#llx, num_trbs = %d\n",
|
||||
xhci_dbg(xhci, "ep %#x - urb len = %#x (%d), "
|
||||
"addr = %#llx, num_trbs = %d\n",
|
||||
urb->ep->desc.bEndpointAddress,
|
||||
urb->transfer_buffer_length,
|
||||
urb->transfer_buffer_length,
|
||||
|
@ -2711,9 +2712,11 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
|
|||
field = 0;
|
||||
|
||||
/* Don't change the cycle bit of the first TRB until later */
|
||||
if (first_trb)
|
||||
if (first_trb) {
|
||||
first_trb = false;
|
||||
else
|
||||
if (start_cycle == 0)
|
||||
field |= 0x1;
|
||||
} else
|
||||
field |= ep_ring->cycle_state;
|
||||
|
||||
/* Chain all the TRBs together; clear the chain bit in the last
|
||||
|
@ -2757,7 +2760,7 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
|
|||
|
||||
check_trb_math(urb, num_trbs, running_total);
|
||||
giveback_first_trb(xhci, slot_id, ep_index, urb->stream_id,
|
||||
start_cycle, start_trb, td);
|
||||
start_cycle, start_trb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -2818,13 +2821,17 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
|
|||
/* Queue setup TRB - see section 6.4.1.2.1 */
|
||||
/* FIXME better way to translate setup_packet into two u32 fields? */
|
||||
setup = (struct usb_ctrlrequest *) urb->setup_packet;
|
||||
field = 0;
|
||||
field |= TRB_IDT | TRB_TYPE(TRB_SETUP);
|
||||
if (start_cycle == 0)
|
||||
field |= 0x1;
|
||||
queue_trb(xhci, ep_ring, false, true,
|
||||
/* FIXME endianness is probably going to bite my ass here. */
|
||||
setup->bRequestType | setup->bRequest << 8 | setup->wValue << 16,
|
||||
setup->wIndex | setup->wLength << 16,
|
||||
TRB_LEN(8) | TRB_INTR_TARGET(0),
|
||||
/* Immediate data in pointer */
|
||||
TRB_IDT | TRB_TYPE(TRB_SETUP));
|
||||
field);
|
||||
|
||||
/* If there's data, queue data TRBs */
|
||||
field = 0;
|
||||
|
@ -2859,7 +2866,7 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
|
|||
field | TRB_IOC | TRB_TYPE(TRB_STATUS) | ep_ring->cycle_state);
|
||||
|
||||
giveback_first_trb(xhci, slot_id, ep_index, 0,
|
||||
start_cycle, start_trb, td);
|
||||
start_cycle, start_trb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -2900,6 +2907,7 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
|
|||
int running_total, trb_buff_len, td_len, td_remain_len, ret;
|
||||
u64 start_addr, addr;
|
||||
int i, j;
|
||||
bool more_trbs_coming;
|
||||
|
||||
ep_ring = xhci->devs[slot_id]->eps[ep_index].ring;
|
||||
|
||||
|
@ -2910,7 +2918,7 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
|
|||
}
|
||||
|
||||
if (!in_interrupt())
|
||||
dev_dbg(&urb->dev->dev, "ep %#x - urb len = %#x (%d),"
|
||||
xhci_dbg(xhci, "ep %#x - urb len = %#x (%d),"
|
||||
" addr = %#llx, num_tds = %d\n",
|
||||
urb->ep->desc.bEndpointAddress,
|
||||
urb->transfer_buffer_length,
|
||||
|
@ -2950,7 +2958,10 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
|
|||
field |= TRB_TYPE(TRB_ISOC);
|
||||
/* Assume URB_ISO_ASAP is set */
|
||||
field |= TRB_SIA;
|
||||
if (i > 0)
|
||||
if (i == 0) {
|
||||
if (start_cycle == 0)
|
||||
field |= 0x1;
|
||||
} else
|
||||
field |= ep_ring->cycle_state;
|
||||
first_trb = false;
|
||||
} else {
|
||||
|
@ -2965,9 +2976,11 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
|
|||
*/
|
||||
if (j < trbs_per_td - 1) {
|
||||
field |= TRB_CHAIN;
|
||||
more_trbs_coming = true;
|
||||
} else {
|
||||
td->last_trb = ep_ring->enqueue;
|
||||
field |= TRB_IOC;
|
||||
more_trbs_coming = false;
|
||||
}
|
||||
|
||||
/* Calculate TRB length */
|
||||
|
@ -2980,7 +2993,7 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
|
|||
length_field = TRB_LEN(trb_buff_len) |
|
||||
remainder |
|
||||
TRB_INTR_TARGET(0);
|
||||
queue_trb(xhci, ep_ring, false, false,
|
||||
queue_trb(xhci, ep_ring, false, more_trbs_coming,
|
||||
lower_32_bits(addr),
|
||||
upper_32_bits(addr),
|
||||
length_field,
|
||||
|
@ -3003,10 +3016,8 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
|
|||
}
|
||||
}
|
||||
|
||||
wmb();
|
||||
start_trb->field[3] |= start_cycle;
|
||||
|
||||
xhci_ring_ep_doorbell(xhci, slot_id, ep_index, urb->stream_id);
|
||||
giveback_first_trb(xhci, slot_id, ep_index, urb->stream_id,
|
||||
start_cycle, start_trb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -3064,7 +3075,7 @@ int xhci_queue_isoc_tx_prepare(struct xhci_hcd *xhci, gfp_t mem_flags,
|
|||
* to set the polling interval (once the API is added).
|
||||
*/
|
||||
if (xhci_interval != ep_interval) {
|
||||
if (!printk_ratelimit())
|
||||
if (printk_ratelimit())
|
||||
dev_dbg(&urb->dev->dev, "Driver uses different interval"
|
||||
" (%d microframe%s) than xHCI "
|
||||
"(%d microframe%s)\n",
|
||||
|
|
|
@ -226,7 +226,8 @@ static int xhci_setup_msi(struct xhci_hcd *xhci)
|
|||
static int xhci_setup_msix(struct xhci_hcd *xhci)
|
||||
{
|
||||
int i, ret = 0;
|
||||
struct pci_dev *pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller);
|
||||
struct usb_hcd *hcd = xhci_to_hcd(xhci);
|
||||
struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
|
||||
|
||||
/*
|
||||
* calculate number of msi-x vectors supported.
|
||||
|
@ -265,6 +266,7 @@ static int xhci_setup_msix(struct xhci_hcd *xhci)
|
|||
goto disable_msix;
|
||||
}
|
||||
|
||||
hcd->msix_enabled = 1;
|
||||
return ret;
|
||||
|
||||
disable_msix:
|
||||
|
@ -280,7 +282,8 @@ free_entries:
|
|||
/* Free any IRQs and disable MSI-X */
|
||||
static void xhci_cleanup_msix(struct xhci_hcd *xhci)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller);
|
||||
struct usb_hcd *hcd = xhci_to_hcd(xhci);
|
||||
struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
|
||||
|
||||
xhci_free_irq(xhci);
|
||||
|
||||
|
@ -292,6 +295,7 @@ static void xhci_cleanup_msix(struct xhci_hcd *xhci)
|
|||
pci_disable_msi(pdev);
|
||||
}
|
||||
|
||||
hcd->msix_enabled = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -508,9 +512,10 @@ void xhci_stop(struct usb_hcd *hcd)
|
|||
spin_lock_irq(&xhci->lock);
|
||||
xhci_halt(xhci);
|
||||
xhci_reset(xhci);
|
||||
xhci_cleanup_msix(xhci);
|
||||
spin_unlock_irq(&xhci->lock);
|
||||
|
||||
xhci_cleanup_msix(xhci);
|
||||
|
||||
#ifdef CONFIG_USB_XHCI_HCD_DEBUGGING
|
||||
/* Tell the event ring poll function not to reschedule */
|
||||
xhci->zombie = 1;
|
||||
|
@ -544,9 +549,10 @@ void xhci_shutdown(struct usb_hcd *hcd)
|
|||
|
||||
spin_lock_irq(&xhci->lock);
|
||||
xhci_halt(xhci);
|
||||
xhci_cleanup_msix(xhci);
|
||||
spin_unlock_irq(&xhci->lock);
|
||||
|
||||
xhci_cleanup_msix(xhci);
|
||||
|
||||
xhci_dbg(xhci, "xhci_shutdown completed - status = %x\n",
|
||||
xhci_readl(xhci, &xhci->op_regs->status));
|
||||
}
|
||||
|
@ -647,6 +653,7 @@ int xhci_suspend(struct xhci_hcd *xhci)
|
|||
int rc = 0;
|
||||
struct usb_hcd *hcd = xhci_to_hcd(xhci);
|
||||
u32 command;
|
||||
int i;
|
||||
|
||||
spin_lock_irq(&xhci->lock);
|
||||
clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
|
||||
|
@ -677,10 +684,15 @@ int xhci_suspend(struct xhci_hcd *xhci)
|
|||
spin_unlock_irq(&xhci->lock);
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
/* step 5: remove core well power */
|
||||
xhci_cleanup_msix(xhci);
|
||||
spin_unlock_irq(&xhci->lock);
|
||||
|
||||
/* step 5: remove core well power */
|
||||
/* synchronize irq when using MSI-X */
|
||||
if (xhci->msix_entries) {
|
||||
for (i = 0; i < xhci->msix_count; i++)
|
||||
synchronize_irq(xhci->msix_entries[i].vector);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -694,7 +706,6 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
|
|||
{
|
||||
u32 command, temp = 0;
|
||||
struct usb_hcd *hcd = xhci_to_hcd(xhci);
|
||||
struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
|
||||
int old_state, retval;
|
||||
|
||||
old_state = hcd->state;
|
||||
|
@ -729,9 +740,8 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
|
|||
xhci_dbg(xhci, "Stop HCD\n");
|
||||
xhci_halt(xhci);
|
||||
xhci_reset(xhci);
|
||||
if (hibernated)
|
||||
xhci_cleanup_msix(xhci);
|
||||
spin_unlock_irq(&xhci->lock);
|
||||
xhci_cleanup_msix(xhci);
|
||||
|
||||
#ifdef CONFIG_USB_XHCI_HCD_DEBUGGING
|
||||
/* Tell the event ring poll function not to reschedule */
|
||||
|
@ -765,30 +775,6 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
|
|||
return retval;
|
||||
}
|
||||
|
||||
spin_unlock_irq(&xhci->lock);
|
||||
/* Re-setup MSI-X */
|
||||
if (hcd->irq)
|
||||
free_irq(hcd->irq, hcd);
|
||||
hcd->irq = -1;
|
||||
|
||||
retval = xhci_setup_msix(xhci);
|
||||
if (retval)
|
||||
/* fall back to msi*/
|
||||
retval = xhci_setup_msi(xhci);
|
||||
|
||||
if (retval) {
|
||||
/* fall back to legacy interrupt*/
|
||||
retval = request_irq(pdev->irq, &usb_hcd_irq, IRQF_SHARED,
|
||||
hcd->irq_descr, hcd);
|
||||
if (retval) {
|
||||
xhci_err(xhci, "request interrupt %d failed\n",
|
||||
pdev->irq);
|
||||
return retval;
|
||||
}
|
||||
hcd->irq = pdev->irq;
|
||||
}
|
||||
|
||||
spin_lock_irq(&xhci->lock);
|
||||
/* step 4: set Run/Stop bit */
|
||||
command = xhci_readl(xhci, &xhci->op_regs->command);
|
||||
command |= CMD_RUN;
|
||||
|
@ -2445,8 +2431,12 @@ int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev)
|
|||
xhci_err(xhci, "Error while assigning device slot ID\n");
|
||||
return 0;
|
||||
}
|
||||
/* xhci_alloc_virt_device() does not touch rings; no need to lock */
|
||||
if (!xhci_alloc_virt_device(xhci, xhci->slot_id, udev, GFP_KERNEL)) {
|
||||
/* xhci_alloc_virt_device() does not touch rings; no need to lock.
|
||||
* Use GFP_NOIO, since this function can be called from
|
||||
* xhci_discover_or_reset_device(), which may be called as part of
|
||||
* mass storage driver error handling.
|
||||
*/
|
||||
if (!xhci_alloc_virt_device(xhci, xhci->slot_id, udev, GFP_NOIO)) {
|
||||
/* Disable slot, if we can do it without mem alloc */
|
||||
xhci_warn(xhci, "Could not allocate xHCI USB device data structures\n");
|
||||
spin_lock_irqsave(&xhci->lock, flags);
|
||||
|
|
|
@ -436,22 +436,18 @@ struct xhci_run_regs {
|
|||
/**
|
||||
* struct doorbell_array
|
||||
*
|
||||
* Bits 0 - 7: Endpoint target
|
||||
* Bits 8 - 15: RsvdZ
|
||||
* Bits 16 - 31: Stream ID
|
||||
*
|
||||
* Section 5.6
|
||||
*/
|
||||
struct xhci_doorbell_array {
|
||||
u32 doorbell[256];
|
||||
};
|
||||
|
||||
#define DB_TARGET_MASK 0xFFFFFF00
|
||||
#define DB_STREAM_ID_MASK 0x0000FFFF
|
||||
#define DB_TARGET_HOST 0x0
|
||||
#define DB_STREAM_ID_HOST 0x0
|
||||
#define DB_MASK (0xff << 8)
|
||||
|
||||
/* Endpoint Target - bits 0:7 */
|
||||
#define EPI_TO_DB(p) (((p) + 1) & 0xff)
|
||||
#define STREAM_ID_TO_DB(p) (((p) & 0xffff) << 16)
|
||||
|
||||
#define DB_VALUE(ep, stream) ((((ep) + 1) & 0xff) | ((stream) << 16))
|
||||
#define DB_VALUE_HOST 0x00000000
|
||||
|
||||
/**
|
||||
* struct xhci_protocol_caps
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) },
|
||||
|
|
|
@ -569,11 +569,23 @@
|
|||
#define OCT_US101_PID 0x0421 /* OCT US101 USB to RS-232 */
|
||||
|
||||
/*
|
||||
* Icom ID-1 digital transceiver
|
||||
* Definitions for Icom Inc. devices
|
||||
*/
|
||||
|
||||
#define ICOM_ID1_VID 0x0C26
|
||||
#define ICOM_ID1_PID 0x0004
|
||||
#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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
@ -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
|
||||
|
@ -944,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 */
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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) || ... */
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -112,6 +112,7 @@ struct usb_hcd {
|
|||
/* Flags that get set only during HCD registration or removal. */
|
||||
unsigned rh_registered:1;/* is root hub registered? */
|
||||
unsigned rh_pollable:1; /* may we poll the root hub? */
|
||||
unsigned msix_enabled:1; /* driver has MSI-X enabled? */
|
||||
|
||||
/* The next flag is a stopgap, to be removed when all the HCDs
|
||||
* support the new root-hub polling mechanism. */
|
||||
|
|
|
@ -347,6 +347,9 @@ extern int usb_serial_generic_prepare_write_buffer(struct usb_serial_port *port,
|
|||
extern int usb_serial_handle_sysrq_char(struct usb_serial_port *port,
|
||||
unsigned int ch);
|
||||
extern int usb_serial_handle_break(struct usb_serial_port *port);
|
||||
extern void usb_serial_handle_dcd_change(struct usb_serial_port *usb_port,
|
||||
struct tty_struct *tty,
|
||||
unsigned int status);
|
||||
|
||||
|
||||
extern int usb_serial_bus_register(struct usb_serial_driver *device);
|
||||
|
|
Loading…
Reference in New Issue