Commit 4bca55d3 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'usb-3.6-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb

Pull USB patches from Greg Kroah-Hartman:
 "Here are a number of USB patches, a bit more than I normally like this
  late in the -rc series, but given people's vacations (myself
  included), and the kernel summit, it seems to have happened this way.

  All are tiny, but they add up.  A number of gadget and xhci fixes, and
  a few new device ids.  All have been tested in linux-next.

  Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>"

* tag 'usb-3.6-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (33 commits)
  usb: chipidea: udc: don't stall endpoint if request list is empty in isr_tr_complete_low
  usb: chipidea: cleanup dma_pool if udc_start() fails
  usb: chipidea: udc: fix error path in udc_start()
  usb: chipidea: udc: add pullup fuction, needed by the uvc gadget
  usb: chipidea: udc: fix setup of endpoint maxpacket size
  USB: option: replace ZTE K5006-Z entry with vendor class rule
  EHCI: Update qTD next pointer in QH overlay region during unlink
  USB: cdc-wdm: fix wdm_find_device* return value
  USB: ftdi_sio: do not claim CDC ACM function
  usb: dwc3: gadget: fix pending isoc handling
  usb: renesas_usbhs: fixup DMA transport data alignment
  usb: gadget: at91udc: Don't check for ep->ep.desc
  usb: gadget: at91udc: don't overwrite driver data
  usb: dwc3: core: fix incorrect usage of resource pointer
  usb: musb: musbhsdma: fix IRQ check
  usb: musb: tusb6010: fix error path in tusb_probe()
  usb: musb: host: fix for musb_start_urb Oops
  usb: gadget: dummy_hcd: add support for USB_DT_BOS on rh
  usb: gadget: dummy_hcd: fixup error probe path
  usb: gadget: s3c-hsotg.c: fix error return code
  ...
parents fe59d297 38bb2ca6
...@@ -78,8 +78,7 @@ static inline int ep_to_bit(struct ci13xxx *ci, int n) ...@@ -78,8 +78,7 @@ static inline int ep_to_bit(struct ci13xxx *ci, int n)
} }
/** /**
* hw_device_state: enables/disables interrupts & starts/stops device (execute * hw_device_state: enables/disables interrupts (execute without interruption)
* without interruption)
* @dma: 0 => disable, !0 => enable and set dma engine * @dma: 0 => disable, !0 => enable and set dma engine
* *
* This function returns an error code * This function returns an error code
...@@ -91,9 +90,7 @@ static int hw_device_state(struct ci13xxx *ci, u32 dma) ...@@ -91,9 +90,7 @@ static int hw_device_state(struct ci13xxx *ci, u32 dma)
/* interrupt, error, port change, reset, sleep/suspend */ /* interrupt, error, port change, reset, sleep/suspend */
hw_write(ci, OP_USBINTR, ~0, hw_write(ci, OP_USBINTR, ~0,
USBi_UI|USBi_UEI|USBi_PCI|USBi_URI|USBi_SLI); USBi_UI|USBi_UEI|USBi_PCI|USBi_URI|USBi_SLI);
hw_write(ci, OP_USBCMD, USBCMD_RS, USBCMD_RS);
} else { } else {
hw_write(ci, OP_USBCMD, USBCMD_RS, 0);
hw_write(ci, OP_USBINTR, ~0, 0); hw_write(ci, OP_USBINTR, ~0, 0);
} }
return 0; return 0;
...@@ -774,10 +771,7 @@ __acquires(mEp->lock) ...@@ -774,10 +771,7 @@ __acquires(mEp->lock)
{ {
struct ci13xxx_req *mReq, *mReqTemp; struct ci13xxx_req *mReq, *mReqTemp;
struct ci13xxx_ep *mEpTemp = mEp; struct ci13xxx_ep *mEpTemp = mEp;
int uninitialized_var(retval); int retval = 0;
if (list_empty(&mEp->qh.queue))
return -EINVAL;
list_for_each_entry_safe(mReq, mReqTemp, &mEp->qh.queue, list_for_each_entry_safe(mReq, mReqTemp, &mEp->qh.queue,
queue) { queue) {
...@@ -1420,6 +1414,21 @@ static int ci13xxx_vbus_draw(struct usb_gadget *_gadget, unsigned mA) ...@@ -1420,6 +1414,21 @@ static int ci13xxx_vbus_draw(struct usb_gadget *_gadget, unsigned mA)
return -ENOTSUPP; return -ENOTSUPP;
} }
/* Change Data+ pullup status
* this func is used by usb_gadget_connect/disconnet
*/
static int ci13xxx_pullup(struct usb_gadget *_gadget, int is_on)
{
struct ci13xxx *ci = container_of(_gadget, struct ci13xxx, gadget);
if (is_on)
hw_write(ci, OP_USBCMD, USBCMD_RS, USBCMD_RS);
else
hw_write(ci, OP_USBCMD, USBCMD_RS, 0);
return 0;
}
static int ci13xxx_start(struct usb_gadget *gadget, static int ci13xxx_start(struct usb_gadget *gadget,
struct usb_gadget_driver *driver); struct usb_gadget_driver *driver);
static int ci13xxx_stop(struct usb_gadget *gadget, static int ci13xxx_stop(struct usb_gadget *gadget,
...@@ -1432,6 +1441,7 @@ static int ci13xxx_stop(struct usb_gadget *gadget, ...@@ -1432,6 +1441,7 @@ static int ci13xxx_stop(struct usb_gadget *gadget,
static const struct usb_gadget_ops usb_gadget_ops = { static const struct usb_gadget_ops usb_gadget_ops = {
.vbus_session = ci13xxx_vbus_session, .vbus_session = ci13xxx_vbus_session,
.wakeup = ci13xxx_wakeup, .wakeup = ci13xxx_wakeup,
.pullup = ci13xxx_pullup,
.vbus_draw = ci13xxx_vbus_draw, .vbus_draw = ci13xxx_vbus_draw,
.udc_start = ci13xxx_start, .udc_start = ci13xxx_start,
.udc_stop = ci13xxx_stop, .udc_stop = ci13xxx_stop,
...@@ -1455,7 +1465,12 @@ static int init_eps(struct ci13xxx *ci) ...@@ -1455,7 +1465,12 @@ static int init_eps(struct ci13xxx *ci)
mEp->ep.name = mEp->name; mEp->ep.name = mEp->name;
mEp->ep.ops = &usb_ep_ops; mEp->ep.ops = &usb_ep_ops;
mEp->ep.maxpacket = CTRL_PAYLOAD_MAX; /*
* for ep0: maxP defined in desc, for other
* eps, maxP is set by epautoconfig() called
* by gadget layer
*/
mEp->ep.maxpacket = (unsigned short)~0;
INIT_LIST_HEAD(&mEp->qh.queue); INIT_LIST_HEAD(&mEp->qh.queue);
mEp->qh.ptr = dma_pool_alloc(ci->qh_pool, GFP_KERNEL, mEp->qh.ptr = dma_pool_alloc(ci->qh_pool, GFP_KERNEL,
...@@ -1475,6 +1490,7 @@ static int init_eps(struct ci13xxx *ci) ...@@ -1475,6 +1490,7 @@ static int init_eps(struct ci13xxx *ci)
else else
ci->ep0in = mEp; ci->ep0in = mEp;
mEp->ep.maxpacket = CTRL_PAYLOAD_MAX;
continue; continue;
} }
...@@ -1484,6 +1500,17 @@ static int init_eps(struct ci13xxx *ci) ...@@ -1484,6 +1500,17 @@ static int init_eps(struct ci13xxx *ci)
return retval; return retval;
} }
static void destroy_eps(struct ci13xxx *ci)
{
int i;
for (i = 0; i < ci->hw_ep_max; i++) {
struct ci13xxx_ep *mEp = &ci->ci13xxx_ep[i];
dma_pool_free(ci->qh_pool, mEp->qh.ptr, mEp->qh.dma);
}
}
/** /**
* ci13xxx_start: register a gadget driver * ci13xxx_start: register a gadget driver
* @gadget: our gadget * @gadget: our gadget
...@@ -1691,7 +1718,7 @@ static int udc_start(struct ci13xxx *ci) ...@@ -1691,7 +1718,7 @@ static int udc_start(struct ci13xxx *ci)
if (ci->platdata->flags & CI13XXX_REQUIRE_TRANSCEIVER) { if (ci->platdata->flags & CI13XXX_REQUIRE_TRANSCEIVER) {
if (ci->transceiver == NULL) { if (ci->transceiver == NULL) {
retval = -ENODEV; retval = -ENODEV;
goto free_pools; goto destroy_eps;
} }
} }
...@@ -1729,7 +1756,7 @@ static int udc_start(struct ci13xxx *ci) ...@@ -1729,7 +1756,7 @@ static int udc_start(struct ci13xxx *ci)
remove_trans: remove_trans:
if (!IS_ERR_OR_NULL(ci->transceiver)) { if (!IS_ERR_OR_NULL(ci->transceiver)) {
otg_set_peripheral(ci->transceiver->otg, &ci->gadget); otg_set_peripheral(ci->transceiver->otg, NULL);
if (ci->global_phy) if (ci->global_phy)
usb_put_phy(ci->transceiver); usb_put_phy(ci->transceiver);
} }
...@@ -1742,6 +1769,8 @@ static int udc_start(struct ci13xxx *ci) ...@@ -1742,6 +1769,8 @@ static int udc_start(struct ci13xxx *ci)
put_transceiver: put_transceiver:
if (!IS_ERR_OR_NULL(ci->transceiver) && ci->global_phy) if (!IS_ERR_OR_NULL(ci->transceiver) && ci->global_phy)
usb_put_phy(ci->transceiver); usb_put_phy(ci->transceiver);
destroy_eps:
destroy_eps(ci);
free_pools: free_pools:
dma_pool_destroy(ci->td_pool); dma_pool_destroy(ci->td_pool);
free_qh_pool: free_qh_pool:
...@@ -1756,18 +1785,12 @@ static int udc_start(struct ci13xxx *ci) ...@@ -1756,18 +1785,12 @@ static int udc_start(struct ci13xxx *ci)
*/ */
static void udc_stop(struct ci13xxx *ci) static void udc_stop(struct ci13xxx *ci)
{ {
int i;
if (ci == NULL) if (ci == NULL)
return; return;
usb_del_gadget_udc(&ci->gadget); usb_del_gadget_udc(&ci->gadget);
for (i = 0; i < ci->hw_ep_max; i++) { destroy_eps(ci);
struct ci13xxx_ep *mEp = &ci->ci13xxx_ep[i];
dma_pool_free(ci->qh_pool, mEp->qh.ptr, mEp->qh.dma);
}
dma_pool_destroy(ci->td_pool); dma_pool_destroy(ci->td_pool);
dma_pool_destroy(ci->qh_pool); dma_pool_destroy(ci->qh_pool);
......
...@@ -109,12 +109,14 @@ static struct usb_driver wdm_driver; ...@@ -109,12 +109,14 @@ static struct usb_driver wdm_driver;
/* return intfdata if we own the interface, else look up intf in the list */ /* return intfdata if we own the interface, else look up intf in the list */
static struct wdm_device *wdm_find_device(struct usb_interface *intf) static struct wdm_device *wdm_find_device(struct usb_interface *intf)
{ {
struct wdm_device *desc = NULL; struct wdm_device *desc;
spin_lock(&wdm_device_list_lock); spin_lock(&wdm_device_list_lock);
list_for_each_entry(desc, &wdm_device_list, device_list) list_for_each_entry(desc, &wdm_device_list, device_list)
if (desc->intf == intf) if (desc->intf == intf)
break; goto found;
desc = NULL;
found:
spin_unlock(&wdm_device_list_lock); spin_unlock(&wdm_device_list_lock);
return desc; return desc;
...@@ -122,12 +124,14 @@ static struct wdm_device *wdm_find_device(struct usb_interface *intf) ...@@ -122,12 +124,14 @@ static struct wdm_device *wdm_find_device(struct usb_interface *intf)
static struct wdm_device *wdm_find_device_by_minor(int minor) static struct wdm_device *wdm_find_device_by_minor(int minor)
{ {
struct wdm_device *desc = NULL; struct wdm_device *desc;
spin_lock(&wdm_device_list_lock); spin_lock(&wdm_device_list_lock);
list_for_each_entry(desc, &wdm_device_list, device_list) list_for_each_entry(desc, &wdm_device_list, device_list)
if (desc->intf->minor == minor) if (desc->intf->minor == minor)
break; goto found;
desc = NULL;
found:
spin_unlock(&wdm_device_list_lock); spin_unlock(&wdm_device_list_lock);
return desc; return desc;
......
...@@ -71,6 +71,10 @@ static const struct usb_device_id usb_quirk_list[] = { ...@@ -71,6 +71,10 @@ static const struct usb_device_id usb_quirk_list[] = {
{ USB_DEVICE(0x04b4, 0x0526), .driver_info = { USB_DEVICE(0x04b4, 0x0526), .driver_info =
USB_QUIRK_CONFIG_INTF_STRINGS }, USB_QUIRK_CONFIG_INTF_STRINGS },
/* Microchip Joss Optical infrared touchboard device */
{ USB_DEVICE(0x04d8, 0x000c), .driver_info =
USB_QUIRK_CONFIG_INTF_STRINGS },
/* Samsung Android phone modem - ID conflict with SPH-I500 */ /* Samsung Android phone modem - ID conflict with SPH-I500 */
{ USB_DEVICE(0x04e8, 0x6601), .driver_info = { USB_DEVICE(0x04e8, 0x6601), .driver_info =
USB_QUIRK_CONFIG_INTF_STRINGS }, USB_QUIRK_CONFIG_INTF_STRINGS },
......
...@@ -436,16 +436,21 @@ static int __devinit dwc3_probe(struct platform_device *pdev) ...@@ -436,16 +436,21 @@ static int __devinit dwc3_probe(struct platform_device *pdev)
dev_err(dev, "missing IRQ\n"); dev_err(dev, "missing IRQ\n");
return -ENODEV; return -ENODEV;
} }
dwc->xhci_resources[1] = *res; dwc->xhci_resources[1].start = res->start;
dwc->xhci_resources[1].end = res->end;
dwc->xhci_resources[1].flags = res->flags;
dwc->xhci_resources[1].name = res->name;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) { if (!res) {
dev_err(dev, "missing memory resource\n"); dev_err(dev, "missing memory resource\n");
return -ENODEV; return -ENODEV;
} }
dwc->xhci_resources[0] = *res; dwc->xhci_resources[0].start = res->start;
dwc->xhci_resources[0].end = dwc->xhci_resources[0].start + dwc->xhci_resources[0].end = dwc->xhci_resources[0].start +
DWC3_XHCI_REGS_END; DWC3_XHCI_REGS_END;
dwc->xhci_resources[0].flags = res->flags;
dwc->xhci_resources[0].name = res->name;
/* /*
* Request memory region but exclude xHCI regs, * Request memory region but exclude xHCI regs,
......
...@@ -720,7 +720,6 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc, ...@@ -720,7 +720,6 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc,
transferred = min_t(u32, ur->length, transferred = min_t(u32, ur->length,
transfer_size - length); transfer_size - length);
memcpy(ur->buf, dwc->ep0_bounce, transferred); memcpy(ur->buf, dwc->ep0_bounce, transferred);
dwc->ep0_bounced = false;
} else { } else {
transferred = ur->length - length; transferred = ur->length - length;
} }
......
...@@ -263,8 +263,11 @@ void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req, ...@@ -263,8 +263,11 @@ void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req,
if (req->request.status == -EINPROGRESS) if (req->request.status == -EINPROGRESS)
req->request.status = status; req->request.status = status;
usb_gadget_unmap_request(&dwc->gadget, &req->request, if (dwc->ep0_bounced && dep->number == 0)
req->direction); dwc->ep0_bounced = false;
else
usb_gadget_unmap_request(&dwc->gadget, &req->request,
req->direction);
dev_dbg(dwc->dev, "request %p from %s completed %d/%d ===> %d\n", dev_dbg(dwc->dev, "request %p from %s completed %d/%d ===> %d\n",
req, dep->name, req->request.actual, req, dep->name, req->request.actual,
...@@ -1026,6 +1029,7 @@ static void __dwc3_gadget_start_isoc(struct dwc3 *dwc, ...@@ -1026,6 +1029,7 @@ static void __dwc3_gadget_start_isoc(struct dwc3 *dwc,
if (list_empty(&dep->request_list)) { if (list_empty(&dep->request_list)) {
dev_vdbg(dwc->dev, "ISOC ep %s run out for requests.\n", dev_vdbg(dwc->dev, "ISOC ep %s run out for requests.\n",
dep->name); dep->name);
dep->flags |= DWC3_EP_PENDING_REQUEST;
return; return;
} }
...@@ -1089,6 +1093,17 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req) ...@@ -1089,6 +1093,17 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
if (dep->flags & DWC3_EP_PENDING_REQUEST) { if (dep->flags & DWC3_EP_PENDING_REQUEST) {
int ret; int ret;
/*
* If xfernotready is already elapsed and it is a case
* of isoc transfer, then issue END TRANSFER, so that
* you can receive xfernotready again and can have
* notion of current microframe.
*/
if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) {
dwc3_stop_active_transfer(dwc, dep->number);
return 0;
}
ret = __dwc3_gadget_kick_transfer(dep, 0, true); ret = __dwc3_gadget_kick_transfer(dep, 0, true);
if (ret && ret != -EBUSY) { if (ret && ret != -EBUSY) {
struct dwc3 *dwc = dep->dwc; struct dwc3 *dwc = dep->dwc;
......
...@@ -475,8 +475,7 @@ static int at91_ep_enable(struct usb_ep *_ep, ...@@ -475,8 +475,7 @@ static int at91_ep_enable(struct usb_ep *_ep,
unsigned long flags; unsigned long flags;
if (!_ep || !ep if (!_ep || !ep
|| !desc || ep->ep.desc || !desc || _ep->name == ep0name
|| _ep->name == ep0name
|| desc->bDescriptorType != USB_DT_ENDPOINT || desc->bDescriptorType != USB_DT_ENDPOINT
|| (maxpacket = usb_endpoint_maxp(desc)) == 0 || (maxpacket = usb_endpoint_maxp(desc)) == 0
|| maxpacket > ep->maxpacket) { || maxpacket > ep->maxpacket) {
...@@ -530,7 +529,6 @@ static int at91_ep_enable(struct usb_ep *_ep, ...@@ -530,7 +529,6 @@ static int at91_ep_enable(struct usb_ep *_ep,
tmp |= AT91_UDP_EPEDS; tmp |= AT91_UDP_EPEDS;
__raw_writel(tmp, ep->creg); __raw_writel(tmp, ep->creg);
ep->ep.desc = desc;
ep->ep.maxpacket = maxpacket; ep->ep.maxpacket = maxpacket;
/* /*
...@@ -1635,7 +1633,6 @@ static int at91_start(struct usb_gadget *gadget, ...@@ -1635,7 +1633,6 @@ static int at91_start(struct usb_gadget *gadget,
udc->driver = driver; udc->driver = driver;
udc->gadget.dev.driver = &driver->driver; udc->gadget.dev.driver = &driver->driver;
udc->gadget.dev.of_node = udc->pdev->dev.of_node; udc->gadget.dev.of_node = udc->pdev->dev.of_node;
dev_set_drvdata(&udc->gadget.dev, &driver->driver);
udc->enabled = 1; udc->enabled = 1;
udc->selfpowered = 1; udc->selfpowered = 1;
...@@ -1656,7 +1653,6 @@ static int at91_stop(struct usb_gadget *gadget, ...@@ -1656,7 +1653,6 @@ static int at91_stop(struct usb_gadget *gadget,
spin_unlock_irqrestore(&udc->lock, flags); spin_unlock_irqrestore(&udc->lock, flags);
udc->gadget.dev.driver = NULL; udc->gadget.dev.driver = NULL;
dev_set_drvdata(&udc->gadget.dev, NULL);
udc->driver = NULL; udc->driver = NULL;
DBG("unbound from %s\n", driver->driver.name); DBG("unbound from %s\n", driver->driver.name);
......
...@@ -1916,6 +1916,27 @@ static int dummy_hub_status(struct usb_hcd *hcd, char *buf) ...@@ -1916,6 +1916,27 @@ static int dummy_hub_status(struct usb_hcd *hcd, char *buf)
return retval; return retval;
} }
/* usb 3.0 root hub device descriptor */
struct {
struct usb_bos_descriptor bos;
struct usb_ss_cap_descriptor ss_cap;
} __packed usb3_bos_desc = {
.bos = {
.bLength = USB_DT_BOS_SIZE,
.bDescriptorType = USB_DT_BOS,
.wTotalLength = cpu_to_le16(sizeof(usb3_bos_desc)),
.bNumDeviceCaps = 1,
},
.ss_cap = {
.bLength = USB_DT_USB_SS_CAP_SIZE,
.bDescriptorType = USB_DT_DEVICE_CAPABILITY,
.bDevCapabilityType = USB_SS_CAP_TYPE,
.wSpeedSupported = cpu_to_le16(USB_5GBPS_OPERATION),
.bFunctionalitySupport = ilog2(USB_5GBPS_OPERATION),
},
};
static inline void static inline void
ss_hub_descriptor(struct usb_hub_descriptor *desc) ss_hub_descriptor(struct usb_hub_descriptor *desc)
{ {
...@@ -2006,6 +2027,18 @@ static int dummy_hub_control( ...@@ -2006,6 +2027,18 @@ static int dummy_hub_control(
else else
hub_descriptor((struct usb_hub_descriptor *) buf); hub_descriptor((struct usb_hub_descriptor *) buf);
break; break;
case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
if (hcd->speed != HCD_USB3)
goto error;
if ((wValue >> 8) != USB_DT_BOS)
goto error;
memcpy(buf, &usb3_bos_desc, sizeof(usb3_bos_desc));
retval = sizeof(usb3_bos_desc);
break;
case GetHubStatus: case GetHubStatus:
*(__le32 *) buf = cpu_to_le32(0); *(__le32 *) buf = cpu_to_le32(0);
break; break;
...@@ -2503,10 +2536,8 @@ static int dummy_hcd_probe(struct platform_device *pdev) ...@@ -2503,10 +2536,8 @@ static int dummy_hcd_probe(struct platform_device *pdev)
hs_hcd->has_tt = 1; hs_hcd->has_tt = 1;
retval = usb_add_hcd(hs_hcd, 0, 0); retval = usb_add_hcd(hs_hcd, 0, 0);
if (retval != 0) { if (retval)
usb_put_hcd(hs_hcd); goto put_usb2_hcd;
return retval;
}
if (mod_data.is_super_speed) { if (mod_data.is_super_speed) {
ss_hcd = usb_create_shared_hcd(&dummy_hcd, &pdev->dev, ss_hcd = usb_create_shared_hcd(&dummy_hcd, &pdev->dev,
...@@ -2525,6 +2556,8 @@ static int dummy_hcd_probe(struct platform_device *pdev) ...@@ -2525,6 +2556,8 @@ static int dummy_hcd_probe(struct platform_device *pdev)
put_usb3_hcd: put_usb3_hcd:
usb_put_hcd(ss_hcd); usb_put_hcd(ss_hcd);
dealloc_usb2_hcd: dealloc_usb2_hcd:
usb_remove_hcd(hs_hcd);
put_usb2_hcd:
usb_put_hcd(hs_hcd); usb_put_hcd(hs_hcd);
the_controller.hs_hcd = the_controller.ss_hcd = NULL; the_controller.hs_hcd = the_controller.ss_hcd = NULL;
return retval; return retval;
......
...@@ -34,11 +34,15 @@ ...@@ -34,11 +34,15 @@
/* Debugging ****************************************************************/ /* Debugging ****************************************************************/
#ifdef VERBOSE_DEBUG #ifdef VERBOSE_DEBUG
#ifndef pr_vdebug
# define pr_vdebug pr_debug # define pr_vdebug pr_debug
#endif /* pr_vdebug */
# define ffs_dump_mem(prefix, ptr, len) \ # define ffs_dump_mem(prefix, ptr, len) \
print_hex_dump_bytes(pr_fmt(prefix ": "), DUMP_PREFIX_NONE, ptr, len) print_hex_dump_bytes(pr_fmt(prefix ": "), DUMP_PREFIX_NONE, ptr, len)
#else #else
#ifndef pr_vdebug
# define pr_vdebug(...) do { } while (0) # define pr_vdebug(...) do { } while (0)
#endif /* pr_vdebug */
# define ffs_dump_mem(prefix, ptr, len) do { } while (0) # define ffs_dump_mem(prefix, ptr, len) do { } while (0)
#endif /* VERBOSE_DEBUG */ #endif /* VERBOSE_DEBUG */
......
...@@ -3599,6 +3599,7 @@ static int __devinit s3c_hsotg_probe(struct platform_device *pdev) ...@@ -3599,6 +3599,7 @@ static int __devinit s3c_hsotg_probe(struct platform_device *pdev)
if (hsotg->num_of_eps == 0) { if (hsotg->num_of_eps == 0) {
dev_err(dev, "wrong number of EPs (zero)\n"); dev_err(dev, "wrong number of EPs (zero)\n");
ret = -EINVAL;
goto err_supplies; goto err_supplies;
} }
...@@ -3606,6 +3607,7 @@ static int __devinit s3c_hsotg_probe(struct platform_device *pdev) ...@@ -3606,6 +3607,7 @@ static int __devinit s3c_hsotg_probe(struct platform_device *pdev)
GFP_KERNEL); GFP_KERNEL);
if (!eps) { if (!eps) {
dev_err(dev, "cannot get memory\n"); dev_err(dev, "cannot get memory\n");
ret = -ENOMEM;
goto err_supplies; goto err_supplies;
} }
...@@ -3622,6 +3624,7 @@ static int __devinit s3c_hsotg_probe(struct platform_device *pdev) ...@@ -3622,6 +3624,7 @@ static int __devinit s3c_hsotg_probe(struct platform_device *pdev)
GFP_KERNEL); GFP_KERNEL);
if (!hsotg->ctrl_req) { if (!hsotg->ctrl_req) {
dev_err(dev, "failed to allocate ctrl req\n"); dev_err(dev, "failed to allocate ctrl req\n");
ret = -ENOMEM;
goto err_ep_mem; goto err_ep_mem;
} }
......
...@@ -132,11 +132,15 @@ static unsigned n_ports; ...@@ -132,11 +132,15 @@ static unsigned n_ports;
#ifdef VERBOSE_DEBUG #ifdef VERBOSE_DEBUG
#ifndef pr_vdebug
#define pr_vdebug(fmt, arg...) \ #define pr_vdebug(fmt, arg...) \
pr_debug(fmt, ##arg) pr_debug(fmt, ##arg)
#endif /* pr_vdebug */
#else #else
#ifndef pr_vdebig
#define pr_vdebug(fmt, arg...) \ #define pr_vdebug(fmt, arg...) \
({ if (0) pr_debug(fmt, ##arg); }) ({ if (0) pr_debug(fmt, ##arg); })
#endif /* pr_vdebug */
#endif #endif
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
......
...@@ -128,9 +128,17 @@ qh_refresh (struct ehci_hcd *ehci, struct ehci_qh *qh) ...@@ -128,9 +128,17 @@ qh_refresh (struct ehci_hcd *ehci, struct ehci_qh *qh)
else { else {
qtd = list_entry (qh->qtd_list.next, qtd = list_entry (qh->qtd_list.next,
struct ehci_qtd, qtd_list); struct ehci_qtd, qtd_list);
/* first qtd may already be partially processed */ /*
if (cpu_to_hc32(ehci, qtd->qtd_dma) == qh->hw->hw_current) * first qtd may already be partially processed.
* If we come here during unlink, the QH overlay region
* might have reference to the just unlinked qtd. The
* qtd is updated in qh_completions(). Update the QH
* overlay here.
*/
if (cpu_to_hc32(ehci, qtd->qtd_dma) == qh->hw->hw_current) {
qh->hw->hw_qtd_next = qtd->hw_next;
qtd = NULL; qtd = NULL;
}
} }
if (qtd) if (qtd)
......
...@@ -570,6 +570,16 @@ static int __devinit ohci_hcd_at91_drv_probe(struct platform_device *pdev) ...@@ -570,6 +570,16 @@ static int __devinit ohci_hcd_at91_drv_probe(struct platform_device *pdev)
if (pdata) { if (pdata) {
at91_for_each_port(i) { at91_for_each_port(i) {
/*
* do not configure PIO if not in relation with
* real USB port on board
*/
if (i >= pdata->ports) {
pdata->vbus_pin[i] = -EINVAL;
pdata->overcurrent_pin[i] = -EINVAL;
break;
}
if (!gpio_is_valid(pdata->vbus_pin[i])) if (!gpio_is_valid(pdata->vbus_pin[i]))
continue; continue;
gpio = pdata->vbus_pin[i]; gpio = pdata->vbus_pin[i];
......
...@@ -75,7 +75,9 @@ ...@@ -75,7 +75,9 @@
#define NB_PIF0_PWRDOWN_1 0x01100013 #define NB_PIF0_PWRDOWN_1 0x01100013
#define USB_INTEL_XUSB2PR 0xD0 #define USB_INTEL_XUSB2PR 0xD0
#define USB_INTEL_USB2PRM 0xD4
#define USB_INTEL_USB3_PSSEN 0xD8 #define USB_INTEL_USB3_PSSEN 0xD8
#define USB_INTEL_USB3PRM 0xDC
static struct amd_chipset_info { static struct amd_chipset_info {
struct pci_dev *nb_dev; struct pci_dev *nb_dev;
...@@ -772,10 +774,18 @@ void usb_enable_xhci_ports(struct pci_dev *xhci_pdev) ...@@ -772,10 +774,18 @@ void usb_enable_xhci_ports(struct pci_dev *xhci_pdev)
return; return;
} }
ports_available = 0xffffffff; /* Read USB3PRM, the USB 3.0 Port Routing Mask Register
* Indicate the ports that can be changed from OS.
*/
pci_read_config_dword(xhci_pdev, USB_INTEL_USB3PRM,
&ports_available);
dev_dbg(&xhci_pdev->dev, "Configurable ports to enable SuperSpeed: 0x%x\n",
ports_available);
/* Write USB3_PSSEN, the USB 3.0 Port SuperSpeed Enable /* Write USB3_PSSEN, the USB 3.0 Port SuperSpeed Enable
* Register, to turn on SuperSpeed terminations for all * Register, to turn on SuperSpeed terminations for the
* available ports. * switchable ports.
*/ */
pci_write_config_dword(xhci_pdev, USB_INTEL_USB3_PSSEN, pci_write_config_dword(xhci_pdev, USB_INTEL_USB3_PSSEN,
cpu_to_le32(ports_available)); cpu_to_le32(ports_available));
...@@ -785,7 +795,16 @@ void usb_enable_xhci_ports(struct pci_dev *xhci_pdev) ...@@ -785,7 +795,16 @@ void usb_enable_xhci_ports(struct pci_dev *xhci_pdev)
dev_dbg(&xhci_pdev->dev, "USB 3.0 ports that are now enabled " dev_dbg(&xhci_pdev->dev, "USB 3.0 ports that are now enabled "
"under xHCI: 0x%x\n", ports_available); "under xHCI: 0x%x\n", ports_available);
ports_available = 0xffffffff; /* Read XUSB2PRM, xHCI USB 2.0 Port Routing Mask Register
* Indicate the USB 2.0 ports to be controlled by the xHCI host.
*/
pci_read_config_dword(xhci_pdev, USB_INTEL_USB2PRM,
&ports_available);
dev_dbg(&xhci_pdev->dev, "Configurable USB 2.0 ports to hand over to xCHI: 0x%x\n",
ports_available);
/* Write XUSB2PR, the xHC USB 2.0 Port Routing Register, to /* Write XUSB2PR, the xHC USB 2.0 Port Routing Register, to
* switch the USB 2.0 power and data lines over to the xHCI * switch the USB 2.0 power and data lines over to the xHCI
* host. * host.
...@@ -822,12 +841,12 @@ static void __devinit quirk_usb_handoff_xhci(struct pci_dev *pdev) ...@@ -822,12 +841,12 @@ static void __devinit quirk_usb_handoff_xhci(struct pci_dev *pdev)
void __iomem *op_reg_base; void __iomem *op_reg_base;
u32 val; u32 val;
int timeout; int timeout;
int len = pci_resource_len(pdev, 0);
if (!mmio_resource_enabled(pdev, 0)) if (!mmio_resource_enabled(pdev, 0))
return; return;
base = ioremap_nocache(pci_resource_start(pdev, 0), base = ioremap_nocache(pci_resource_start(pdev, 0), len);
pci_resource_len(pdev, 0));
if (base == NULL) if (base == NULL)
return; return;
...@@ -837,9 +856,17 @@ static void __devinit quirk_usb_handoff_xhci(struct pci_dev *pdev) ...@@ -837,9 +856,17 @@ static void __devinit quirk_usb_handoff_xhci(struct pci_dev *pdev)
*/ */
ext_cap_offset = xhci_find_next_cap_offset(base, XHCI_HCC_PARAMS_OFFSET); ext_cap_offset = xhci_find_next_cap_offset(base, XHCI_HCC_PARAMS_OFFSET);
do { do {
if ((ext_cap_offset + sizeof(val)) > len) {
/* We're reading garbage from the controller */
dev_warn(&pdev->dev,
"xHCI controller failing to respond");
return;
}
if (!ext_cap_offset) if (!ext_cap_offset)
/* We've reached the end of the extended capabilities */ /* We've reached the end of the extended capabilities */
goto hc_init; goto hc_init;
val = readl(base + ext_cap_offset); val = readl(base + ext_cap_offset);
if (XHCI_EXT_CAPS_ID(val) == XHCI_EXT_CAPS_LEGACY) if (XHCI_EXT_CAPS_ID(val) == XHCI_EXT_CAPS_LEGACY)
break; break;
...@@ -870,9 +897,10 @@ static void __devinit quirk_usb_handoff_xhci(struct pci_dev *pdev) ...@@ -870,9 +897,10 @@ static void __devinit quirk_usb_handoff_xhci(struct pci_dev *pdev)
/* Disable any BIOS SMIs and clear all SMI events*/ /* Disable any BIOS SMIs and clear all SMI events*/
writel(val, base + ext_cap_offset + XHCI_LEGACY_CONTROL_OFFSET); writel(val, base + ext_cap_offset + XHCI_LEGACY_CONTROL_OFFSET);
hc_init:
if (usb_is_intel_switchable_xhci(pdev)) if (usb_is_intel_switchable_xhci(pdev))
usb_enable_xhci_ports(pdev); usb_enable_xhci_ports(pdev);
hc_init:
op_reg_base = base + XHCI_HC_LENGTH(readl(base)); op_reg_base = base + XHCI_HC_LENGTH(readl(base));
/* Wait for the host controller to be ready before writing any /* Wait for the host controller to be ready before writing any
......
...@@ -15,6 +15,7 @@ void usb_disable_xhci_ports(struct pci_dev *xhci_pdev); ...@@ -15,6 +15,7 @@ void usb_disable_xhci_ports(struct pci_dev *xhci_pdev);
static inline void usb_amd_quirk_pll_disable(void) {} static inline void usb_amd_quirk_pll_disable(void) {}
static inline void usb_amd_quirk_pll_enable(void) {} static inline void usb_amd_quirk_pll_enable(void) {}
static inline void usb_amd_dev_put(void) {} static inline void usb_amd_dev_put(void) {}
static inline void usb_disable_xhci_ports(struct pci_dev *xhci_pdev) {}
#endif /* CONFIG_PCI */ #endif /* CONFIG_PCI */
#endif /* __LINUX_USB_PCI_QUIRKS_H */ #endif /* __LINUX_USB_PCI_QUIRKS_H */
...@@ -493,11 +493,48 @@ static void xhci_hub_report_link_state(u32 *status, u32 status_reg) ...@@ -493,11 +493,48 @@ static void xhci_hub_report_link_state(u32 *status, u32 status_reg)
* when this bit is set. * when this bit is set.
*/ */
pls |= USB_PORT_STAT_CONNECTION; pls |= USB_PORT_STAT_CONNECTION;
} else {
/*
* If CAS bit isn't set but the Port is already at
* Compliance Mode, fake a connection so the USB core
* notices the Compliance state and resets the port.
* This resolves an issue generated by the SN65LVPE502CP
* in which sometimes the port enters compliance mode
* caused by a delay on the host-device negotiation.
*/
if (pls == USB_SS_PORT_LS_COMP_MOD)
pls |= USB_PORT_STAT_CONNECTION;
} }
/* update status field */ /* update status field */
*status |= pls; *status |= pls;
} }
/*
* Function for Compliance Mode Quirk.
*
* This Function verifies if all xhc USB3 ports have entered U0, if so,
* the compliance mode timer is deleted. A port won't enter
* compliance mode if it has previously entered U0.
*/
void xhci_del_comp_mod_timer(struct xhci_hcd *xhci, u32 status, u16 wIndex)
{
u32 all_ports_seen_u0 = ((1 << xhci->num_usb3_ports)-1);
bool port_in_u0 = ((status & PORT_PLS_MASK) == XDEV_U0);
if (!(xhci->quirks & XHCI_COMP_MODE_QUIRK))
return;
if ((xhci->port_status_u0 != all_ports_seen_u0) && port_in_u0) {
xhci->port_status_u0 |= 1 << wIndex;
if (xhci->port_status_u0 == all_ports_seen_u0) {
del_timer_sync(&xhci->comp_mode_recovery_timer);
xhci_dbg(xhci, "All USB3 ports have entered U0 already!\n");
xhci_dbg(xhci, "Compliance Mode Recovery Timer Deleted.\n");
}
}
}
int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
u16 wIndex, char *buf, u16 wLength) u16 wIndex, char *buf, u16 wLength)
{ {
...@@ -651,6 +688,11 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, ...@@ -651,6 +688,11 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
/* Update Port Link State for super speed ports*/ /* Update Port Link State for super speed ports*/
if (hcd->speed == HCD_USB3) { if (hcd->speed == HCD_USB3) {
xhci_hub_report_link_state(&status, temp); xhci_hub_report_link_state(&status, temp);
/*
* Verify if all USB3 Ports Have entered U0 already.
* Delete Compliance Mode Timer if so.
*/
xhci_del_comp_mod_timer(xhci, temp, wIndex);
} }
if (bus_state->port_c_suspend & (1 << wIndex)) if (bus_state->port_c_suspend & (1 << wIndex))
status |= 1 << USB_PORT_FEAT_C_SUSPEND; status |= 1 << USB_PORT_FEAT_C_SUSPEND;
......
...@@ -118,7 +118,7 @@ static int xhci_plat_probe(struct platform_device *pdev) ...@@ -118,7 +118,7 @@ static int xhci_plat_probe(struct platform_device *pdev)
goto put_hcd; goto put_hcd;
} }
hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len);
if (!hcd->regs) { if (!hcd->regs) {
dev_dbg(&pdev->dev, "error mapping memory\n"); dev_dbg(&pdev->dev, "error mapping memory\n");
ret = -EFAULT; ret = -EFAULT;
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/moduleparam.h> #include <linux/moduleparam.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/dmi.h>
#include "xhci.h" #include "xhci.h"
...@@ -398,6 +399,95 @@ static void xhci_msix_sync_irqs(struct xhci_hcd *xhci) ...@@ -398,6 +399,95 @@ static void xhci_msix_sync_irqs(struct xhci_hcd *xhci)
#endif #endif
static void compliance_mode_recovery(unsigned long arg)
{
struct xhci_hcd *xhci;
struct usb_hcd *hcd;
u32 temp;
int i;
xhci = (struct xhci_hcd *)arg;
for (i = 0; i < xhci->num_usb3_ports; i++) {
temp = xhci_readl(xhci, xhci->usb3_ports[i]);
if ((temp & PORT_PLS_MASK) == USB_SS_PORT_LS_COMP_MOD) {
/*
* Compliance Mode Detected. Letting USB Core
* handle the Warm Reset
*/
xhci_dbg(xhci, "Compliance Mode Detected->Port %d!\n",
i + 1);
xhci_dbg(xhci, "Attempting Recovery routine!\n");
hcd = xhci->shared_hcd;
if (hcd->state == HC_STATE_SUSPENDED)
usb_hcd_resume_root_hub(hcd);
usb_hcd_poll_rh_status(hcd);
}
}
if (xhci->port_status_u0 != ((1 << xhci->num_usb3_ports)-1))
mod_timer(&xhci->comp_mode_recovery_timer,
jiffies + msecs_to_jiffies(COMP_MODE_RCVRY_MSECS));
}
/*
* Quirk to work around issue generated by the SN65LVPE502CP USB3.0 re-driver
* that causes ports behind that hardware to enter compliance mode sometimes.
* The quirk creates a timer that polls every 2 seconds the link state of
* each host controller's port and recovers it by issuing a Warm reset
* if Compliance mode is detected, otherwise the port will become "dead" (no
* device connections or disconnections will be detected anymore). Becasue no
* status event is generated when entering compliance mode (per xhci spec),
* this quirk is needed on systems that have the failing hardware installed.
*/
static void compliance_mode_recovery_timer_init(struct xhci_hcd *xhci)
{
xhci->port_status_u0 = 0;
init_timer(&xhci->comp_mode_recovery_timer);
xhci->comp_mode_recovery_timer.data = (unsigned long) xhci;
xhci->comp_mode_recovery_timer.function = compliance_mode_recovery;
xhci->comp_mode_recovery_timer.expires = jiffies +
msecs_to_jiffies(COMP_MODE_RCVRY_MSECS);
set_timer_slack(&xhci->comp_mode_recovery_timer,
msecs_to_jiffies(COMP_MODE_RCVRY_MSECS));
add_timer(&xhci->comp_mode_recovery_timer);
xhci_dbg(xhci, "Compliance Mode Recovery Timer Initialized.\n");
}
/*
* This function identifies the systems that have installed the SN65LVPE502CP
* USB3.0 re-driver and that need the Compliance Mode Quirk.
* Systems:
* Vendor: Hewlett-Packard -> System Models: Z420, Z620 and Z820
*/
static bool compliance_mode_recovery_timer_quirk_check(void)
{
const char *dmi_product_name, *dmi_sys_vendor;
dmi_product_name = dmi_get_system_info(DMI_PRODUCT_NAME);
dmi_sys_vendor = dmi_get_system_info(DMI_SYS_VENDOR);
if (!(strstr(dmi_sys_vendor, "Hewlett-Packard")))
return false;
if (strstr(dmi_product_name, "Z420") ||
strstr(dmi_product_name, "Z620") ||
strstr(dmi_product_name, "Z820"))
return true;
return false;
}
static int xhci_all_ports_seen_u0(struct xhci_hcd *xhci)
{
return (xhci->port_status_u0 == ((1 << xhci->num_usb3_ports)-1));
}
/* /*
* Initialize memory for HCD and xHC (one-time init). * Initialize memory for HCD and xHC (one-time init).
* *
...@@ -421,6 +511,12 @@ int xhci_init(struct usb_hcd *hcd) ...@@ -421,6 +511,12 @@ int xhci_init(struct usb_hcd *hcd)
retval = xhci_mem_init(xhci, GFP_KERNEL); retval = xhci_mem_init(xhci, GFP_KERNEL);
xhci_dbg(xhci, "Finished xhci_init\n"); xhci_dbg(xhci, "Finished xhci_init\n");
/* Initializing Compliance Mode Recovery Data If Needed */
if (compliance_mode_recovery_timer_quirk_check()) {
xhci->quirks |= XHCI_COMP_MODE_QUIRK;
compliance_mode_recovery_timer_init(xhci);
}
return retval; return retval;
} }
...@@ -629,6 +725,11 @@ void xhci_stop(struct usb_hcd *hcd) ...@@ -629,6 +725,11 @@ void xhci_stop(struct usb_hcd *hcd)
del_timer_sync(&xhci->event_ring_timer); del_timer_sync(&xhci->event_ring_timer);
#endif #endif
/* Deleting Compliance Mode Recovery Timer */
if ((xhci->quirks & XHCI_COMP_MODE_QUIRK) &&
(!(xhci_all_ports_seen_u0(xhci))))
del_timer_sync(&xhci->comp_mode_recovery_timer);
if (xhci->quirks & XHCI_AMD_PLL_FIX) if (xhci->quirks & XHCI_AMD_PLL_FIX)
usb_amd_dev_put(); usb_amd_dev_put();
...@@ -659,7 +760,7 @@ void xhci_shutdown(struct usb_hcd *hcd) ...@@ -659,7 +760,7 @@ void xhci_shutdown(struct usb_hcd *hcd)
{ {
struct xhci_hcd *xhci = hcd_to_xhci(hcd); struct xhci_hcd *xhci = hcd_to_xhci(hcd);
if (xhci->quirks && XHCI_SPURIOUS_REBOOT) if (xhci->quirks & XHCI_SPURIOUS_REBOOT)
usb_disable_xhci_ports(to_pci_dev(hcd->self.controller)); usb_disable_xhci_ports(to_pci_dev(hcd->self.controller));
spin_lock_irq(&xhci->lock); spin_lock_irq(&xhci->lock);
...@@ -806,6 +907,16 @@ int xhci_suspend(struct xhci_hcd *xhci) ...@@ -806,6 +907,16 @@ int xhci_suspend(struct xhci_hcd *xhci)
} }
spin_unlock_irq(&xhci->lock); spin_unlock_irq(&xhci->lock);
/*
* Deleting Compliance Mode Recovery Timer because the xHCI Host
* is about to be suspended.
*/
if ((xhci->quirks & XHCI_COMP_MODE_QUIRK) &&
(!(xhci_all_ports_seen_u0(xhci)))) {
del_timer_sync(&xhci->comp_mode_recovery_timer);
xhci_dbg(xhci, "Compliance Mode Recovery Timer Deleted!\n");
}
/* step 5: remove core well power */ /* step 5: remove core well power */
/* synchronize irq when using MSI-X */ /* synchronize irq when using MSI-X */
xhci_msix_sync_irqs(xhci); xhci_msix_sync_irqs(xhci);
...@@ -938,6 +1049,16 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated) ...@@ -938,6 +1049,16 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
usb_hcd_resume_root_hub(hcd); usb_hcd_resume_root_hub(hcd);
usb_hcd_resume_root_hub(xhci->shared_hcd); usb_hcd_resume_root_hub(xhci->shared_hcd);
} }
/*
* If system is subject to the Quirk, Compliance Mode Timer needs to
* be re-initialized Always after a system resume. Ports are subject
* to suffer the Compliance Mode issue again. It doesn't matter if
* ports have entered previously to U0 before system's suspension.
*/
if (xhci->quirks & XHCI_COMP_MODE_QUIRK)
compliance_mode_recovery_timer_init(xhci);
return retval; return retval;
} }
#endif /* CONFIG_PM */ #endif /* CONFIG_PM */
......
...@@ -1495,6 +1495,7 @@ struct xhci_hcd { ...@@ -1495,6 +1495,7 @@ struct xhci_hcd {
#define XHCI_LPM_SUPPORT (1 << 11) #define XHCI_LPM_SUPPORT (1 << 11)
#define XHCI_INTEL_HOST (1 << 12) #define XHCI_INTEL_HOST (1 << 12)
#define XHCI_SPURIOUS_REBOOT (1 << 13) #define XHCI_SPURIOUS_REBOOT (1 << 13)
#define XHCI_COMP_MODE_QUIRK (1 << 14)
unsigned int num_active_eps; unsigned int num_active_eps;
unsigned int limit_active_eps; unsigned int limit_active_eps;
/* There are two roothubs to keep track of bus suspend info for */ /* There are two roothubs to keep track of bus suspend info for */
...@@ -1511,6 +1512,11 @@ struct xhci_hcd { ...@@ -1511,6 +1512,11 @@ struct xhci_hcd {
unsigned sw_lpm_support:1; unsigned sw_lpm_support:1;
/* support xHCI 1.0 spec USB2 hardware LPM */ /* support xHCI 1.0 spec USB2 hardware LPM */
unsigned hw_lpm_support:1; unsigned hw_lpm_support:1;
/* Compliance Mode Recovery Data */
struct timer_list comp_mode_recovery_timer;
u32 port_status_u0;
/* Compliance Mode Timer Triggered every 2 seconds */
#define COMP_MODE_RCVRY_MSECS 2000
}; };
/* convert between an HCD pointer and the corresponding EHCI_HCD */ /* convert between an HCD pointer and the corresponding EHCI_HCD */
......
...@@ -2049,7 +2049,7 @@ static int musb_urb_enqueue( ...@@ -2049,7 +2049,7 @@ static int musb_urb_enqueue(
* we only have work to do in the former case. * we only have work to do in the former case.
*/ */
spin_lock_irqsave(&musb->lock, flags); spin_lock_irqsave(&musb->lock, flags);
if (hep->hcpriv) { if (hep->hcpriv || !next_urb(qh)) {
/* some concurrent activity submitted another urb to hep... /* some concurrent activity submitted another urb to hep...
* odd, rare, error prone, but legal. * odd, rare, error prone, but legal.
*/ */
......
...@@ -388,7 +388,7 @@ dma_controller_create(struct musb *musb, void __iomem *base) ...@@ -388,7 +388,7 @@ dma_controller_create(struct musb *musb, void __iomem *base)
struct platform_device *pdev = to_platform_device(dev); struct platform_device *pdev = to_platform_device(dev);
int irq = platform_get_irq_byname(pdev, "dma"); int irq = platform_get_irq_byname(pdev, "dma");
if (irq == 0) { if (irq <= 0) {
dev_err(dev, "No DMA interrupt line!\n"); dev_err(dev, "No DMA interrupt line!\n");
return NULL; return NULL;
} }
......
...@@ -1215,7 +1215,7 @@ static int __devinit tusb_probe(struct platform_device *pdev) ...@@ -1215,7 +1215,7 @@ static int __devinit tusb_probe(struct platform_device *pdev)
ret = platform_device_add(musb); ret = platform_device_add(musb);
if (ret) { if (ret) {
dev_err(&pdev->dev, "failed to register musb device\n"); dev_err(&pdev->dev, "failed to register musb device\n");
goto err1; goto err2;
} }
return 0; return 0;
......
...@@ -818,7 +818,7 @@ static int usbhsf_dma_prepare_push(struct usbhs_pkt *pkt, int *is_done) ...@@ -818,7 +818,7 @@ static int usbhsf_dma_prepare_push(struct usbhs_pkt *pkt, int *is_done)
usbhs_pipe_is_dcp(pipe)) usbhs_pipe_is_dcp(pipe))
goto usbhsf_pio_prepare_push; goto usbhsf_pio_prepare_push;
if (len % 4) /* 32bit alignment */ if (len & 0x7) /* 8byte alignment */
goto usbhsf_pio_prepare_push; goto usbhsf_pio_prepare_push;
if ((uintptr_t)(pkt->buf + pkt->actual) & 0x7) /* 8byte alignment */ if ((uintptr_t)(pkt->buf + pkt->actual) & 0x7) /* 8byte alignment */
...@@ -905,7 +905,7 @@ static int usbhsf_dma_try_pop(struct usbhs_pkt *pkt, int *is_done) ...@@ -905,7 +905,7 @@ static int usbhsf_dma_try_pop(struct usbhs_pkt *pkt, int *is_done)
/* use PIO if packet is less than pio_dma_border */ /* use PIO if packet is less than pio_dma_border */
len = usbhsf_fifo_rcv_len(priv, fifo); len = usbhsf_fifo_rcv_len(priv, fifo);
len = min(pkt->length - pkt->actual, len); len = min(pkt->length - pkt->actual, len);
if (len % 4) /* 32bit alignment */ if (len & 0x7) /* 8byte alignment */
goto usbhsf_pio_prepare_pop_unselect; goto usbhsf_pio_prepare_pop_unselect;
if (len < usbhs_get_dparam(priv, pio_dma_border)) if (len < usbhs_get_dparam(priv, pio_dma_border))
......
...@@ -704,6 +704,7 @@ static struct usb_device_id id_table_combined [] = { ...@@ -704,6 +704,7 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(FTDI_VID, FTDI_PCDJ_DAC2_PID) }, { USB_DEVICE(FTDI_VID, FTDI_PCDJ_DAC2_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_RRCIRKITS_LOCOBUFFER_PID) }, { USB_DEVICE(FTDI_VID, FTDI_RRCIRKITS_LOCOBUFFER_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_ASK_RDR400_PID) }, { USB_DEVICE(FTDI_VID, FTDI_ASK_RDR400_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_NZR_SEM_USB_PID) },
{ USB_DEVICE(ICOM_VID, ICOM_ID_1_PID) }, { USB_DEVICE(ICOM_VID, ICOM_ID_1_PID) },
{ USB_DEVICE(ICOM_VID, ICOM_OPC_U_UC_PID) }, { USB_DEVICE(ICOM_VID, ICOM_OPC_U_UC_PID) },
{ USB_DEVICE(ICOM_VID, ICOM_ID_RP2C1_PID) }, { USB_DEVICE(ICOM_VID, ICOM_ID_RP2C1_PID) },
...@@ -804,13 +805,32 @@ static struct usb_device_id id_table_combined [] = { ...@@ -804,13 +805,32 @@ static struct usb_device_id id_table_combined [] = {
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
{ USB_DEVICE(ADI_VID, ADI_GNICEPLUS_PID), { USB_DEVICE(ADI_VID, ADI_GNICEPLUS_PID),
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
{ USB_DEVICE(MICROCHIP_VID, MICROCHIP_USB_BOARD_PID) }, { USB_DEVICE_AND_INTERFACE_INFO(MICROCHIP_VID, MICROCHIP_USB_BOARD_PID,
USB_CLASS_VENDOR_SPEC,
USB_SUBCLASS_VENDOR_SPEC, 0x00) },
{ USB_DEVICE(JETI_VID, JETI_SPC1201_PID) }, { USB_DEVICE(JETI_VID, JETI_SPC1201_PID) },
{ USB_DEVICE(MARVELL_VID, MARVELL_SHEEVAPLUG_PID), { USB_DEVICE(MARVELL_VID, MARVELL_SHEEVAPLUG_PID),
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
{ USB_DEVICE(LARSENBRUSGAARD_VID, LB_ALTITRACK_PID) }, { USB_DEVICE(LARSENBRUSGAARD_VID, LB_ALTITRACK_PID) },
{ USB_DEVICE(GN_OTOMETRICS_VID, AURICAL_USB_PID) }, { USB_DEVICE(GN_OTOMETRICS_VID, AURICAL_USB_PID) },
{ USB_DEVICE(FTDI_VID, PI_C865_PID) },
{ USB_DEVICE(FTDI_VID, PI_C857_PID) },
{ USB_DEVICE(PI_VID, PI_C866_PID) },
{ USB_DEVICE(PI_VID, PI_C663_PID) },
{ USB_DEVICE(PI_VID, PI_C725_PID) },
{ USB_DEVICE(PI_VID, PI_E517_PID) },
{ USB_DEVICE(PI_VID, PI_C863_PID) },
{ USB_DEVICE(PI_VID, PI_E861_PID) }, { USB_DEVICE(PI_VID, PI_E861_PID) },
{ USB_DEVICE(PI_VID, PI_C867_PID) },
{ USB_DEVICE(PI_VID, PI_E609_PID) },
{ USB_DEVICE(PI_VID, PI_E709_PID) },
{ USB_DEVICE(PI_VID, PI_100F_PID) },
{ USB_DEVICE(PI_VID, PI_1011_PID) },
{ USB_DEVICE(PI_VID, PI_1012_PID) },
{ USB_DEVICE(PI_VID, PI_1013_PID) },
{ USB_DEVICE(PI_VID, PI_1014_PID) },
{ USB_DEVICE(PI_VID, PI_1015_PID) },
{ USB_DEVICE(PI_VID, PI_1016_PID) },
{ USB_DEVICE(KONDO_VID, KONDO_USB_SERIAL_PID) }, { USB_DEVICE(KONDO_VID, KONDO_USB_SERIAL_PID) },
{ USB_DEVICE(BAYER_VID, BAYER_CONTOUR_CABLE_PID) }, { USB_DEVICE(BAYER_VID, BAYER_CONTOUR_CABLE_PID) },
{ USB_DEVICE(FTDI_VID, MARVELL_OPENRD_PID), { USB_DEVICE(FTDI_VID, MARVELL_OPENRD_PID),
......
...@@ -75,6 +75,9 @@ ...@@ -75,6 +75,9 @@
#define FTDI_OPENDCC_GATEWAY_PID 0xBFDB #define FTDI_OPENDCC_GATEWAY_PID 0xBFDB
#define FTDI_OPENDCC_GBM_PID 0xBFDC #define FTDI_OPENDCC_GBM_PID 0xBFDC
/* NZR SEM 16+ USB (http://www.nzr.de) */
#define FTDI_NZR_SEM_USB_PID 0xC1E0 /* NZR SEM-LOG16+ */
/* /*
* RR-CirKits LocoBuffer USB (http://www.rr-cirkits.com) * RR-CirKits LocoBuffer USB (http://www.rr-cirkits.com)
*/ */
...@@ -539,7 +542,10 @@ ...@@ -539,7 +542,10 @@
/* /*
* Microchip Technology, Inc. * Microchip Technology, Inc.
* *
* MICROCHIP_VID (0x04D8) and MICROCHIP_USB_BOARD_PID (0x000A) are also used by: * MICROCHIP_VID (0x04D8) and MICROCHIP_USB_BOARD_PID (0x000A) are
* used by single function CDC ACM class based firmware demo
* applications. The VID/PID has also been used in firmware
* emulating FTDI serial chips by:
* Hornby Elite - Digital Command Control Console * Hornby Elite - Digital Command Control Console
* http://www.hornby.com/hornby-dcc/controllers/ * http://www.hornby.com/hornby-dcc/controllers/
*/ */
...@@ -791,8 +797,27 @@ ...@@ -791,8 +797,27 @@
* Physik Instrumente * Physik Instrumente
* http://www.physikinstrumente.com/en/products/ * http://www.physikinstrumente.com/en/products/
*/ */
/* These two devices use the VID of FTDI */
#define PI_C865_PID 0xe0a0 /* PI C-865 Piezomotor Controller */
#define PI_C857_PID 0xe0a1 /* PI Encoder Trigger Box */
#define PI_VID 0x1a72 /* Vendor ID */ #define PI_VID 0x1a72 /* Vendor ID */
#define PI_E861_PID 0x1008 /* E-861 piezo controller USB connection */ #define PI_C866_PID 0x1000 /* PI C-866 Piezomotor Controller */
#define PI_C663_PID 0x1001 /* PI C-663 Mercury-Step */
#define PI_C725_PID 0x1002 /* PI C-725 Piezomotor Controller */
#define PI_E517_PID 0x1005 /* PI E-517 Digital Piezo Controller Operation Module */
#define PI_C863_PID 0x1007 /* PI C-863 */
#define PI_E861_PID 0x1008 /* PI E-861 Piezomotor Controller */
#define PI_C867_PID 0x1009 /* PI C-867 Piezomotor Controller */
#define PI_E609_PID 0x100D /* PI E-609 Digital Piezo Controller */
#define PI_E709_PID 0x100E /* PI E-709 Digital Piezo Controller */
#define PI_100F_PID 0x100F /* PI Digital Piezo Controller */
#define PI_1011_PID 0x1011 /* PI Digital Piezo Controller */
#define PI_1012_PID 0x1012 /* PI Motion Controller */
#define PI_1013_PID 0x1013 /* PI Motion Controller */
#define PI_1014_PID 0x1014 /* PI Device */
#define PI_1015_PID 0x1015 /* PI Device */
#define PI_1016_PID 0x1016 /* PI Digital Servo Module */
/* /*
* Kondo Kagaku Co.Ltd. * Kondo Kagaku Co.Ltd.
......
...@@ -886,8 +886,6 @@ static const struct usb_device_id option_ids[] = { ...@@ -886,8 +886,6 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1010, 0xff, 0xff, 0xff), { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1010, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&net_intf4_blacklist }, .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1012, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1012, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1018, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&net_intf3_blacklist },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1057, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1057, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1058, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1058, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1059, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1059, 0xff, 0xff, 0xff) },
...@@ -1092,6 +1090,10 @@ static const struct usb_device_id option_ids[] = { ...@@ -1092,6 +1090,10 @@ static const struct usb_device_id option_ids[] = {
.driver_info = (kernel_ulong_t)&zte_ad3812_z_blacklist }, .driver_info = (kernel_ulong_t)&zte_ad3812_z_blacklist },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MC2716, 0xff, 0xff, 0xff), { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MC2716, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&zte_mc2716_z_blacklist }, .driver_info = (kernel_ulong_t)&zte_mc2716_z_blacklist },
{ USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff, 0x02, 0x01) },
{ USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff, 0x02, 0x05) },
{ USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff, 0x86, 0x10) },
{ USB_DEVICE(BENQ_VENDOR_ID, BENQ_PRODUCT_H10) }, { USB_DEVICE(BENQ_VENDOR_ID, BENQ_PRODUCT_H10) },
{ USB_DEVICE(DLINK_VENDOR_ID, DLINK_PRODUCT_DWM_652) }, { USB_DEVICE(DLINK_VENDOR_ID, DLINK_PRODUCT_DWM_652) },
{ USB_DEVICE(ALINK_VENDOR_ID, DLINK_PRODUCT_DWM_652_U5) }, /* Yes, ALINK_VENDOR_ID */ { USB_DEVICE(ALINK_VENDOR_ID, DLINK_PRODUCT_DWM_652_U5) }, /* Yes, ALINK_VENDOR_ID */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment