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:
Linus Torvalds 2011-02-01 08:07:40 +10:00
commit cbae48738f
48 changed files with 567 additions and 380 deletions

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -405,7 +405,12 @@ static int suspend_common(struct device *dev, bool do_wakeup)
return retval;
}
synchronize_irq(pci_dev->irq);
/* 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
* there will be no DMA activity. Now we can shut down the upstream

View File

@ -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);
}

View File

@ -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

View File

@ -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);
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,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;
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;
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? */
mEp->qh.ptr->cap |=
(mEp->ep.maxpacket << ffs_nr(QH_MAX_PKT)) & QH_MAX_PKT;
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);
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);

View File

@ -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 */

View File

@ -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:

View File

@ -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 },
};

View File

@ -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);

View File

@ -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);

View File

@ -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)

View File

@ -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 */

View File

@ -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:

View File

@ -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);

View File

@ -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

View File

@ -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();
start_trb->field[3] |= start_cycle;
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",

View File

@ -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);

View File

@ -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

View File

@ -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);

View File

@ -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 */
};

View File

@ -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);

View File

@ -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)

View File

@ -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);
}

View File

@ -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;

View File

@ -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;

View File

@ -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) },

View File

@ -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)

View File

@ -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;

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -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,
};

View File

@ -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 */

View File

@ -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,

View File

@ -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)

View File

@ -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

View File

@ -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,
};

View File

@ -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,
};

View File

@ -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,

View File

@ -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);

View File

@ -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,

View File

@ -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) || ... */

View File

@ -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",

View File

@ -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. */

View File

@ -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);