提交 bcba282a 编写于 作者: L Linus Torvalds

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

Pull USB fixes from Greg KH:
 "Here are some USB driver fixes for 4.3-rc3.

  There's the usual assortment of new device ids, combined with xhci and
  gadget driver fixes.  Full details in the shortlog.  All of these have
  been in linux-next with no reported problems"

* tag 'usb-4.3-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (34 commits)
  MAINTAINERS: remove amd5536udc USB gadget driver maintainer
  USB: whiteheat: fix potential null-deref at probe
  xhci: init command timeout timer earlier to avoid deleting it uninitialized
  xhci: change xhci 1.0 only restrictions to support xhci 1.1
  usb: xhci: exit early in xhci_setup_device() if we're halted or dying
  usb: xhci: stop everything on the first call to xhci_stop
  usb: xhci: Clear XHCI_STATE_DYING on start
  usb: xhci: lock mutex on xhci_stop
  xhci: Move xhci_pme_quirk() behind #ifdef CONFIG_PM
  xhci: give command abortion one more chance before killing xhci
  usb: Use the USB_SS_MULT() macro to get the burst multiplier.
  usb: dwc3: gadget: Fix BUG in RT config
  usb: musb: fix cppi channel teardown for isoch transfer
  usb: phy: isp1301: Export I2C module alias information
  usb: gadget: drop null test before destroy functions
  usb: gadget: dummy_hcd: in transfer(), return data sent, not limit
  usb: gadget: dummy_hcd: fix rescan logic for transfer
  usb: gadget: dummy_hcd: fix unneeded else-if condition
  usb: gadget: dummy_hcd: emulate sending zlp in packet logic
  usb: musb: dsps: fix polling in device-only mode
  ...
......@@ -6,6 +6,7 @@ Required properties:
"lsi,zevio-usb"
"qcom,ci-hdrc"
"chipidea,usb2"
"xlnx,zynq-usb-2.20a"
- reg: base address and length of the registers
- interrupts: interrupt for the USB controller
......
......@@ -615,9 +615,8 @@ F: Documentation/hwmon/fam15h_power
F: drivers/hwmon/fam15h_power.c
AMD GEODE CS5536 USB DEVICE CONTROLLER DRIVER
M: Thomas Dahlmann <dahlmann.thomas@arcor.de>
L: linux-geode@lists.infradead.org (moderated for non-subscribers)
S: Supported
S: Orphan
F: drivers/usb/gadget/udc/amd5536udc.*
AMD GEODE PROCESSOR/CHIPSET SUPPORT
......
......@@ -61,7 +61,7 @@ static const struct of_device_id ci_hdrc_imx_dt_ids[] = {
{ .compatible = "fsl,imx27-usb", .data = &imx27_usb_data},
{ .compatible = "fsl,imx6q-usb", .data = &imx6q_usb_data},
{ .compatible = "fsl,imx6sl-usb", .data = &imx6sl_usb_data},
{ .compatible = "fsl,imx6sx-usb", .data = &imx6sl_usb_data},
{ .compatible = "fsl,imx6sx-usb", .data = &imx6sx_usb_data},
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, ci_hdrc_imx_dt_ids);
......
......@@ -12,6 +12,7 @@
#include <linux/dma-mapping.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/phy/phy.h>
#include <linux/platform_device.h>
#include <linux/usb/chipidea.h>
......@@ -30,18 +31,36 @@ static const struct ci_hdrc_platform_data ci_default_pdata = {
.flags = CI_HDRC_DISABLE_STREAMING,
};
static struct ci_hdrc_platform_data ci_zynq_pdata = {
.capoffset = DEF_CAPOFFSET,
};
static const struct of_device_id ci_hdrc_usb2_of_match[] = {
{ .compatible = "chipidea,usb2"},
{ .compatible = "xlnx,zynq-usb-2.20a", .data = &ci_zynq_pdata},
{ }
};
MODULE_DEVICE_TABLE(of, ci_hdrc_usb2_of_match);
static int ci_hdrc_usb2_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct ci_hdrc_usb2_priv *priv;
struct ci_hdrc_platform_data *ci_pdata = dev_get_platdata(dev);
int ret;
const struct of_device_id *match;
if (!ci_pdata) {
ci_pdata = devm_kmalloc(dev, sizeof(*ci_pdata), GFP_KERNEL);
*ci_pdata = ci_default_pdata; /* struct copy */
}
match = of_match_device(ci_hdrc_usb2_of_match, &pdev->dev);
if (match && match->data) {
/* struct copy */
*ci_pdata = *(struct ci_hdrc_platform_data *)match->data;
}
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
......@@ -96,12 +115,6 @@ static int ci_hdrc_usb2_remove(struct platform_device *pdev)
return 0;
}
static const struct of_device_id ci_hdrc_usb2_of_match[] = {
{ .compatible = "chipidea,usb2" },
{ }
};
MODULE_DEVICE_TABLE(of, ci_hdrc_usb2_of_match);
static struct platform_driver ci_hdrc_usb2_driver = {
.probe = ci_hdrc_usb2_probe,
.remove = ci_hdrc_usb2_remove,
......
......@@ -656,6 +656,44 @@ __acquires(hwep->lock)
return 0;
}
static int _ep_set_halt(struct usb_ep *ep, int value, bool check_transfer)
{
struct ci_hw_ep *hwep = container_of(ep, struct ci_hw_ep, ep);
int direction, retval = 0;
unsigned long flags;
if (ep == NULL || hwep->ep.desc == NULL)
return -EINVAL;
if (usb_endpoint_xfer_isoc(hwep->ep.desc))
return -EOPNOTSUPP;
spin_lock_irqsave(hwep->lock, flags);
if (value && hwep->dir == TX && check_transfer &&
!list_empty(&hwep->qh.queue) &&
!usb_endpoint_xfer_control(hwep->ep.desc)) {
spin_unlock_irqrestore(hwep->lock, flags);
return -EAGAIN;
}
direction = hwep->dir;
do {
retval |= hw_ep_set_halt(hwep->ci, hwep->num, hwep->dir, value);
if (!value)
hwep->wedge = 0;
if (hwep->type == USB_ENDPOINT_XFER_CONTROL)
hwep->dir = (hwep->dir == TX) ? RX : TX;
} while (hwep->dir != direction);
spin_unlock_irqrestore(hwep->lock, flags);
return retval;
}
/**
* _gadget_stop_activity: stops all USB activity, flushes & disables all endpts
* @gadget: gadget
......@@ -1051,7 +1089,7 @@ __acquires(ci->lock)
num += ci->hw_ep_max / 2;
spin_unlock(&ci->lock);
err = usb_ep_set_halt(&ci->ci_hw_ep[num].ep);
err = _ep_set_halt(&ci->ci_hw_ep[num].ep, 1, false);
spin_lock(&ci->lock);
if (!err)
isr_setup_status_phase(ci);
......@@ -1117,8 +1155,8 @@ __acquires(ci->lock)
if (err < 0) {
spin_unlock(&ci->lock);
if (usb_ep_set_halt(&hwep->ep))
dev_err(ci->dev, "error: ep_set_halt\n");
if (_ep_set_halt(&hwep->ep, 1, false))
dev_err(ci->dev, "error: _ep_set_halt\n");
spin_lock(&ci->lock);
}
}
......@@ -1149,9 +1187,9 @@ __acquires(ci->lock)
err = isr_setup_status_phase(ci);
if (err < 0) {
spin_unlock(&ci->lock);
if (usb_ep_set_halt(&hwep->ep))
if (_ep_set_halt(&hwep->ep, 1, false))
dev_err(ci->dev,
"error: ep_set_halt\n");
"error: _ep_set_halt\n");
spin_lock(&ci->lock);
}
}
......@@ -1397,41 +1435,7 @@ static int ep_dequeue(struct usb_ep *ep, struct usb_request *req)
*/
static int ep_set_halt(struct usb_ep *ep, int value)
{
struct ci_hw_ep *hwep = container_of(ep, struct ci_hw_ep, ep);
int direction, retval = 0;
unsigned long flags;
if (ep == NULL || hwep->ep.desc == NULL)
return -EINVAL;
if (usb_endpoint_xfer_isoc(hwep->ep.desc))
return -EOPNOTSUPP;
spin_lock_irqsave(hwep->lock, flags);
#ifndef STALL_IN
/* g_file_storage MS compliant but g_zero fails chapter 9 compliance */
if (value && hwep->type == USB_ENDPOINT_XFER_BULK && hwep->dir == TX &&
!list_empty(&hwep->qh.queue)) {
spin_unlock_irqrestore(hwep->lock, flags);
return -EAGAIN;
}
#endif
direction = hwep->dir;
do {
retval |= hw_ep_set_halt(hwep->ci, hwep->num, hwep->dir, value);
if (!value)
hwep->wedge = 0;
if (hwep->type == USB_ENDPOINT_XFER_CONTROL)
hwep->dir = (hwep->dir == TX) ? RX : TX;
} while (hwep->dir != direction);
spin_unlock_irqrestore(hwep->lock, flags);
return retval;
return _ep_set_halt(ep, value, true);
}
/**
......
......@@ -112,7 +112,7 @@ static void usb_parse_ss_endpoint_companion(struct device *ddev, int cfgno,
cfgno, inum, asnum, ep->desc.bEndpointAddress);
ep->ss_ep_comp.bmAttributes = 16;
} else if (usb_endpoint_xfer_isoc(&ep->desc) &&
desc->bmAttributes > 2) {
USB_SS_MULT(desc->bmAttributes) > 3) {
dev_warn(ddev, "Isoc endpoint has Mult of %d in "
"config %d interface %d altsetting %d ep %d: "
"setting to 3\n", desc->bmAttributes + 1,
......@@ -121,7 +121,8 @@ static void usb_parse_ss_endpoint_companion(struct device *ddev, int cfgno,
}
if (usb_endpoint_xfer_isoc(&ep->desc))
max_tx = (desc->bMaxBurst + 1) * (desc->bmAttributes + 1) *
max_tx = (desc->bMaxBurst + 1) *
(USB_SS_MULT(desc->bmAttributes)) *
usb_endpoint_maxp(&ep->desc);
else if (usb_endpoint_xfer_int(&ep->desc))
max_tx = usb_endpoint_maxp(&ep->desc) *
......
......@@ -514,8 +514,6 @@ static int dwc3_omap_probe(struct platform_device *pdev)
goto err1;
}
dwc3_omap_enable_irqs(omap);
ret = dwc3_omap_extcon_register(omap);
if (ret < 0)
goto err2;
......@@ -526,6 +524,8 @@ static int dwc3_omap_probe(struct platform_device *pdev)
goto err3;
}
dwc3_omap_enable_irqs(omap);
return 0;
err3:
......
......@@ -2665,8 +2665,6 @@ static irqreturn_t dwc3_interrupt(int irq, void *_dwc)
int i;
irqreturn_t ret = IRQ_NONE;
spin_lock(&dwc->lock);
for (i = 0; i < dwc->num_event_buffers; i++) {
irqreturn_t status;
......@@ -2675,8 +2673,6 @@ static irqreturn_t dwc3_interrupt(int irq, void *_dwc)
ret = status;
}
spin_unlock(&dwc->lock);
return ret;
}
......
......@@ -186,6 +186,7 @@ void usb_ep_autoconfig_reset (struct usb_gadget *gadget)
list_for_each_entry (ep, &gadget->ep_list, ep_list) {
ep->claimed = false;
ep->driver_data = NULL;
}
gadget->in_epnum = 0;
gadget->out_epnum = 0;
......
......@@ -3138,8 +3138,8 @@ static void udc_pci_remove(struct pci_dev *pdev)
writel(AMD_BIT(UDC_DEVCFG_SOFTRESET), &dev->regs->cfg);
if (dev->irq_registered)
free_irq(pdev->irq, dev);
if (dev->regs)
iounmap(dev->regs);
if (dev->virt_addr)
iounmap(dev->virt_addr);
if (dev->mem_region)
release_mem_region(pci_resource_start(pdev, 0),
pci_resource_len(pdev, 0));
......@@ -3226,17 +3226,13 @@ static int udc_pci_probe(
/* init */
dev = kzalloc(sizeof(struct udc), GFP_KERNEL);
if (!dev) {
retval = -ENOMEM;
goto finished;
}
if (!dev)
return -ENOMEM;
/* pci setup */
if (pci_enable_device(pdev) < 0) {
kfree(dev);
dev = NULL;
retval = -ENODEV;
goto finished;
goto err_pcidev;
}
dev->active = 1;
......@@ -3246,28 +3242,22 @@ static int udc_pci_probe(
if (!request_mem_region(resource, len, name)) {
dev_dbg(&pdev->dev, "pci device used already\n");
kfree(dev);
dev = NULL;
retval = -EBUSY;
goto finished;
goto err_memreg;
}
dev->mem_region = 1;
dev->virt_addr = ioremap_nocache(resource, len);
if (dev->virt_addr == NULL) {
dev_dbg(&pdev->dev, "start address cannot be mapped\n");
kfree(dev);
dev = NULL;
retval = -EFAULT;
goto finished;
goto err_ioremap;
}
if (!pdev->irq) {
dev_err(&pdev->dev, "irq not set\n");
kfree(dev);
dev = NULL;
retval = -ENODEV;
goto finished;
goto err_irq;
}
spin_lock_init(&dev->lock);
......@@ -3283,10 +3273,8 @@ static int udc_pci_probe(
if (request_irq(pdev->irq, udc_irq, IRQF_SHARED, name, dev) != 0) {
dev_dbg(&pdev->dev, "request_irq(%d) fail\n", pdev->irq);
kfree(dev);
dev = NULL;
retval = -EBUSY;
goto finished;
goto err_irq;
}
dev->irq_registered = 1;
......@@ -3314,8 +3302,17 @@ static int udc_pci_probe(
return 0;
finished:
if (dev)
udc_pci_remove(pdev);
udc_pci_remove(pdev);
return retval;
err_irq:
iounmap(dev->virt_addr);
err_ioremap:
release_mem_region(resource, len);
err_memreg:
pci_disable_device(pdev);
err_pcidev:
kfree(dev);
return retval;
}
......
......@@ -2002,6 +2002,17 @@ static struct usba_ep * atmel_udc_of_init(struct platform_device *pdev,
ep->udc = udc;
INIT_LIST_HEAD(&ep->queue);
if (ep->index == 0) {
ep->ep.caps.type_control = true;
} else {
ep->ep.caps.type_iso = ep->can_isoc;
ep->ep.caps.type_bulk = true;
ep->ep.caps.type_int = true;
}
ep->ep.caps.dir_in = true;
ep->ep.caps.dir_out = true;
if (i)
list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list);
......
......@@ -324,8 +324,7 @@ static void bdc_mem_free(struct bdc *bdc)
bdc->scratchpad.buff, bdc->scratchpad.sp_dma);
/* Destroy the dma pools */
if (bdc->bd_table_pool)
dma_pool_destroy(bdc->bd_table_pool);
dma_pool_destroy(bdc->bd_table_pool);
/* Free the bdc_ep array */
kfree(bdc->bdc_ep_array);
......
......@@ -1348,6 +1348,7 @@ static int transfer(struct dummy_hcd *dum_hcd, struct urb *urb,
{
struct dummy *dum = dum_hcd->dum;
struct dummy_request *req;
int sent = 0;
top:
/* if there's no request queued, the device is NAKing; return */
......@@ -1385,12 +1386,15 @@ static int transfer(struct dummy_hcd *dum_hcd, struct urb *urb,
if (len == 0)
break;
/* use an extra pass for the final short packet */
if (len > ep->ep.maxpacket) {
rescan = 1;
len -= (len % ep->ep.maxpacket);
/* send multiple of maxpacket first, then remainder */
if (len >= ep->ep.maxpacket) {
is_short = 0;
if (len % ep->ep.maxpacket)
rescan = 1;
len -= len % ep->ep.maxpacket;
} else {
is_short = 1;
}
is_short = (len % ep->ep.maxpacket) != 0;
len = dummy_perform_transfer(urb, req, len);
......@@ -1399,6 +1403,7 @@ static int transfer(struct dummy_hcd *dum_hcd, struct urb *urb,
req->req.status = len;
} else {
limit -= len;
sent += len;
urb->actual_length += len;
req->req.actual += len;
}
......@@ -1421,7 +1426,7 @@ static int transfer(struct dummy_hcd *dum_hcd, struct urb *urb,
*status = -EOVERFLOW;
else
*status = 0;
} else if (!to_host) {
} else {
*status = 0;
if (host_len > dev_len)
req->req.status = -EOVERFLOW;
......@@ -1429,15 +1434,24 @@ static int transfer(struct dummy_hcd *dum_hcd, struct urb *urb,
req->req.status = 0;
}
/* many requests terminate without a short packet */
/*
* many requests terminate without a short packet.
* send a zlp if demanded by flags.
*/
} else {
if (req->req.length == req->req.actual
&& !req->req.zero)
req->req.status = 0;
if (urb->transfer_buffer_length == urb->actual_length
&& !(urb->transfer_flags
& URB_ZERO_PACKET))
*status = 0;
if (req->req.length == req->req.actual) {
if (req->req.zero && to_host)
rescan = 1;
else
req->req.status = 0;
}
if (urb->transfer_buffer_length == urb->actual_length) {
if (urb->transfer_flags & URB_ZERO_PACKET &&
!to_host)
rescan = 1;
else
*status = 0;
}
}
/* device side completion --> continuable */
......@@ -1460,7 +1474,7 @@ static int transfer(struct dummy_hcd *dum_hcd, struct urb *urb,
if (rescan)
goto top;
}
return limit;
return sent;
}
static int periodic_bytes(struct dummy *dum, struct dummy_ep *ep)
......@@ -1890,7 +1904,7 @@ static void dummy_timer(unsigned long _dum_hcd)
default:
treat_control_like_bulk:
ep->last_io = jiffies;
total = transfer(dum_hcd, urb, ep, limit, &status);
total -= transfer(dum_hcd, urb, ep, limit, &status);
break;
}
......
......@@ -2117,8 +2117,7 @@ static int gr_remove(struct platform_device *pdev)
return -EBUSY;
gr_dfs_delete(dev);
if (dev->desc_pool)
dma_pool_destroy(dev->desc_pool);
dma_pool_destroy(dev->desc_pool);
platform_set_drvdata(pdev, NULL);
gr_free_request(&dev->epi[0].ep, &dev->ep0reqi->req);
......
......@@ -1767,8 +1767,7 @@ static int mv_u3d_remove(struct platform_device *dev)
usb_del_gadget_udc(&u3d->gadget);
/* free memory allocated in probe */
if (u3d->trb_pool)
dma_pool_destroy(u3d->trb_pool);
dma_pool_destroy(u3d->trb_pool);
if (u3d->ep_context)
dma_free_coherent(&dev->dev, u3d->ep_context_size,
......
......@@ -2100,8 +2100,7 @@ static int mv_udc_remove(struct platform_device *pdev)
}
/* free memory allocated in probe */
if (udc->dtd_pool)
dma_pool_destroy(udc->dtd_pool);
dma_pool_destroy(udc->dtd_pool);
if (udc->ep_dqh)
dma_free_coherent(&pdev->dev, udc->ep_dqh_size,
......
......@@ -1498,10 +1498,10 @@ int xhci_endpoint_init(struct xhci_hcd *xhci,
* use Event Data TRBs, and we don't chain in a link TRB on short
* transfers, we're basically dividing by 1.
*
* xHCI 1.0 specification indicates that the Average TRB Length should
* be set to 8 for control endpoints.
* xHCI 1.0 and 1.1 specification indicates that the Average TRB Length
* should be set to 8 for control endpoints.
*/
if (usb_endpoint_xfer_control(&ep->desc) && xhci->hci_version == 0x100)
if (usb_endpoint_xfer_control(&ep->desc) && xhci->hci_version >= 0x100)
ep_ctx->tx_info |= cpu_to_le32(AVG_TRB_LENGTH_FOR_EP(8));
else
ep_ctx->tx_info |=
......@@ -1792,8 +1792,7 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)
int size;
int i, j, num_ports;
if (timer_pending(&xhci->cmd_timer))
del_timer_sync(&xhci->cmd_timer);
del_timer_sync(&xhci->cmd_timer);
/* Free the Event Ring Segment Table and the actual Event Ring */
size = sizeof(struct xhci_erst_entry)*(xhci->erst.num_entries);
......@@ -2321,6 +2320,10 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
INIT_LIST_HEAD(&xhci->cmd_list);
/* init command timeout timer */
setup_timer(&xhci->cmd_timer, xhci_handle_command_timeout,
(unsigned long)xhci);
page_size = readl(&xhci->op_regs->page_size);
xhci_dbg_trace(xhci, trace_xhci_dbg_init,
"Supported page size register = 0x%x", page_size);
......@@ -2505,10 +2508,6 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
"Wrote ERST address to ir_set 0.");
xhci_print_ir_set(xhci, 0);
/* init command timeout timer */
setup_timer(&xhci->cmd_timer, xhci_handle_command_timeout,
(unsigned long)xhci);
/*
* XXX: Might need to set the Interrupter Moderation Register to
* something other than the default (~1ms minimum between interrupts).
......
......@@ -180,51 +180,6 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
"QUIRK: Resetting on resume");
}
/*
* In some Intel xHCI controllers, in order to get D3 working,
* through a vendor specific SSIC CONFIG register at offset 0x883c,
* SSIC PORT need to be marked as "unused" before putting xHCI
* into D3. After D3 exit, the SSIC port need to be marked as "used".
* Without this change, xHCI might not enter D3 state.
* Make sure PME works on some Intel xHCI controllers by writing 1 to clear
* the Internal PME flag bit in vendor specific PMCTRL register at offset 0x80a4
*/
static void xhci_pme_quirk(struct usb_hcd *hcd, bool suspend)
{
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
u32 val;
void __iomem *reg;
if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
pdev->device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI) {
reg = (void __iomem *) xhci->cap_regs + PORT2_SSIC_CONFIG_REG2;
/* Notify SSIC that SSIC profile programming is not done */
val = readl(reg) & ~PROG_DONE;
writel(val, reg);
/* Mark SSIC port as unused(suspend) or used(resume) */
val = readl(reg);
if (suspend)
val |= SSIC_PORT_UNUSED;
else
val &= ~SSIC_PORT_UNUSED;
writel(val, reg);
/* Notify SSIC that SSIC profile programming is done */
val = readl(reg) | PROG_DONE;
writel(val, reg);
readl(reg);
}
reg = (void __iomem *) xhci->cap_regs + 0x80a4;
val = readl(reg);
writel(val | BIT(28), reg);
readl(reg);
}
#ifdef CONFIG_ACPI
static void xhci_pme_acpi_rtd3_enable(struct pci_dev *dev)
{
......@@ -345,6 +300,51 @@ static void xhci_pci_remove(struct pci_dev *dev)
}
#ifdef CONFIG_PM
/*
* In some Intel xHCI controllers, in order to get D3 working,
* through a vendor specific SSIC CONFIG register at offset 0x883c,
* SSIC PORT need to be marked as "unused" before putting xHCI
* into D3. After D3 exit, the SSIC port need to be marked as "used".
* Without this change, xHCI might not enter D3 state.
* Make sure PME works on some Intel xHCI controllers by writing 1 to clear
* the Internal PME flag bit in vendor specific PMCTRL register at offset 0x80a4
*/
static void xhci_pme_quirk(struct usb_hcd *hcd, bool suspend)
{
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
u32 val;
void __iomem *reg;
if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
pdev->device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI) {
reg = (void __iomem *) xhci->cap_regs + PORT2_SSIC_CONFIG_REG2;
/* Notify SSIC that SSIC profile programming is not done */
val = readl(reg) & ~PROG_DONE;
writel(val, reg);
/* Mark SSIC port as unused(suspend) or used(resume) */
val = readl(reg);
if (suspend)
val |= SSIC_PORT_UNUSED;
else
val &= ~SSIC_PORT_UNUSED;
writel(val, reg);
/* Notify SSIC that SSIC profile programming is done */
val = readl(reg) | PROG_DONE;
writel(val, reg);
readl(reg);
}
reg = (void __iomem *) xhci->cap_regs + 0x80a4;
val = readl(reg);
writel(val | BIT(28), reg);
readl(reg);
}
static int xhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup)
{
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
......
......@@ -302,6 +302,15 @@ static int xhci_abort_cmd_ring(struct xhci_hcd *xhci)
ret = xhci_handshake(&xhci->op_regs->cmd_ring,
CMD_RING_RUNNING, 0, 5 * 1000 * 1000);
if (ret < 0) {
/* we are about to kill xhci, give it one more chance */
xhci_write_64(xhci, temp_64 | CMD_RING_ABORT,
&xhci->op_regs->cmd_ring);
udelay(1000);
ret = xhci_handshake(&xhci->op_regs->cmd_ring,
CMD_RING_RUNNING, 0, 3 * 1000 * 1000);
if (ret == 0)
return 0;
xhci_err(xhci, "Stopped the command ring failed, "
"maybe the host is dead\n");
xhci->xhc_state |= XHCI_STATE_DYING;
......@@ -3461,8 +3470,8 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
if (start_cycle == 0)
field |= 0x1;
/* xHCI 1.0 6.4.1.2.1: Transfer Type field */
if (xhci->hci_version == 0x100) {
/* xHCI 1.0/1.1 6.4.1.2.1: Transfer Type field */
if (xhci->hci_version >= 0x100) {
if (urb->transfer_buffer_length > 0) {
if (setup->bRequestType & USB_DIR_IN)
field |= TRB_TX_TYPE(TRB_DATA_IN);
......
......@@ -146,7 +146,8 @@ static int xhci_start(struct xhci_hcd *xhci)
"waited %u microseconds.\n",
XHCI_MAX_HALT_USEC);
if (!ret)
xhci->xhc_state &= ~XHCI_STATE_HALTED;
xhci->xhc_state &= ~(XHCI_STATE_HALTED | XHCI_STATE_DYING);
return ret;
}
......@@ -654,15 +655,6 @@ int xhci_run(struct usb_hcd *hcd)
}
EXPORT_SYMBOL_GPL(xhci_run);
static void xhci_only_stop_hcd(struct usb_hcd *hcd)
{
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
spin_lock_irq(&xhci->lock);
xhci_halt(xhci);
spin_unlock_irq(&xhci->lock);
}
/*
* Stop xHCI driver.
*
......@@ -677,12 +669,14 @@ void xhci_stop(struct usb_hcd *hcd)
u32 temp;
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
if (!usb_hcd_is_primary_hcd(hcd)) {
xhci_only_stop_hcd(xhci->shared_hcd);
if (xhci->xhc_state & XHCI_STATE_HALTED)
return;
}
mutex_lock(&xhci->mutex);
spin_lock_irq(&xhci->lock);
xhci->xhc_state |= XHCI_STATE_HALTED;
xhci->cmd_ring_state = CMD_RING_STATE_STOPPED;
/* Make sure the xHC is halted for a USB3 roothub
* (xhci_stop() could be called as part of failed init).
*/
......@@ -717,6 +711,7 @@ void xhci_stop(struct usb_hcd *hcd)
xhci_dbg_trace(xhci, trace_xhci_dbg_init,
"xhci_stop completed - status = %x",
readl(&xhci->op_regs->status));
mutex_unlock(&xhci->mutex);
}
/*
......@@ -3793,6 +3788,9 @@ static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev,
mutex_lock(&xhci->mutex);
if (xhci->xhc_state) /* dying or halted */
goto out;
if (!udev->slot_id) {
xhci_dbg_trace(xhci, trace_xhci_dbg_address,
"Bad Slot ID %d", udev->slot_id);
......
......@@ -1051,6 +1051,7 @@ void musb_start(struct musb *musb)
* (c) peripheral initiates, using SRP
*/
if (musb->port_mode != MUSB_PORT_MODE_HOST &&
musb->xceiv->otg->state != OTG_STATE_A_WAIT_BCON &&
(devctl & MUSB_DEVCTL_VBUS) == MUSB_DEVCTL_VBUS) {
musb->is_active = 1;
} else {
......@@ -2448,6 +2449,9 @@ static int musb_suspend(struct device *dev)
struct musb *musb = dev_to_musb(dev);
unsigned long flags;
musb_platform_disable(musb);
musb_generic_disable(musb);
spin_lock_irqsave(&musb->lock, flags);
if (is_peripheral_active(musb)) {
......@@ -2501,6 +2505,9 @@ static int musb_resume(struct device *dev)
pm_runtime_disable(dev);
pm_runtime_set_active(dev);
pm_runtime_enable(dev);
musb_start(musb);
return 0;
}
......
......@@ -551,6 +551,9 @@ static int cppi41_dma_channel_abort(struct dma_channel *channel)
} else {
cppi41_set_autoreq_mode(cppi41_channel, EP_MODE_AUTOREQ_NONE);
/* delay to drain to cppi dma pipeline for isoch */
udelay(250);
csr = musb_readw(epio, MUSB_RXCSR);
csr &= ~(MUSB_RXCSR_H_REQPKT | MUSB_RXCSR_DMAENAB);
musb_writew(epio, MUSB_RXCSR, csr);
......
......@@ -225,8 +225,11 @@ static void dsps_musb_enable(struct musb *musb)
dsps_writel(reg_base, wrp->epintr_set, epmask);
dsps_writel(reg_base, wrp->coreintr_set, coremask);
/* start polling for ID change. */
mod_timer(&glue->timer, jiffies + msecs_to_jiffies(wrp->poll_timeout));
/* start polling for ID change in dual-role idle mode */
if (musb->xceiv->otg->state == OTG_STATE_B_IDLE &&
musb->port_mode == MUSB_PORT_MODE_DUAL_ROLE)
mod_timer(&glue->timer, jiffies +
msecs_to_jiffies(wrp->poll_timeout));
dsps_musb_try_idle(musb, 0);
}
......
......@@ -379,6 +379,8 @@ static const struct of_device_id ux500_match[] = {
{}
};
MODULE_DEVICE_TABLE(of, ux500_match);
static struct platform_driver ux500_driver = {
.probe = ux500_probe,
.remove = ux500_remove,
......
......@@ -155,7 +155,7 @@ config USB_MSM_OTG
config USB_QCOM_8X16_PHY
tristate "Qualcomm APQ8016/MSM8916 on-chip USB PHY controller support"
depends on ARCH_QCOM || COMPILE_TEST
depends on RESET_CONTROLLER
depends on RESET_CONTROLLER && EXTCON
select USB_PHY
select USB_ULPI_VIEWPORT
help
......
......@@ -232,7 +232,8 @@ int usb_phy_gen_create_phy(struct device *dev, struct usb_phy_generic *nop,
clk_rate = pdata->clk_rate;
needs_vcc = pdata->needs_vcc;
if (gpio_is_valid(pdata->gpio_reset)) {
err = devm_gpio_request_one(dev, pdata->gpio_reset, 0,
err = devm_gpio_request_one(dev, pdata->gpio_reset,
GPIOF_ACTIVE_LOW,
dev_name(dev));
if (!err)
nop->gpiod_reset =
......
......@@ -31,6 +31,7 @@ static const struct i2c_device_id isp1301_id[] = {
{ "isp1301", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, isp1301_id);
static struct i2c_client *isp1301_i2c_client;
......
......@@ -278,6 +278,10 @@ static void option_instat_callback(struct urb *urb);
#define ZTE_PRODUCT_MF622 0x0001
#define ZTE_PRODUCT_MF628 0x0015
#define ZTE_PRODUCT_MF626 0x0031
#define ZTE_PRODUCT_ZM8620_X 0x0396
#define ZTE_PRODUCT_ME3620_MBIM 0x0426
#define ZTE_PRODUCT_ME3620_X 0x1432
#define ZTE_PRODUCT_ME3620_L 0x1433
#define ZTE_PRODUCT_AC2726 0xfff1
#define ZTE_PRODUCT_MG880 0xfffd
#define ZTE_PRODUCT_CDMA_TECH 0xfffe
......@@ -544,6 +548,18 @@ static const struct option_blacklist_info zte_mc2716_z_blacklist = {
.sendsetup = BIT(1) | BIT(2) | BIT(3),
};
static const struct option_blacklist_info zte_me3620_mbim_blacklist = {
.reserved = BIT(2) | BIT(3) | BIT(4),
};
static const struct option_blacklist_info zte_me3620_xl_blacklist = {
.reserved = BIT(3) | BIT(4) | BIT(5),
};
static const struct option_blacklist_info zte_zm8620_x_blacklist = {
.reserved = BIT(3) | BIT(4) | BIT(5),
};
static const struct option_blacklist_info huawei_cdc12_blacklist = {
.reserved = BIT(1) | BIT(2),
};
......@@ -1591,6 +1607,14 @@ static const struct usb_device_id option_ids[] = {
.driver_info = (kernel_ulong_t)&zte_ad3812_z_blacklist },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MC2716, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&zte_mc2716_z_blacklist },
{ USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_ME3620_L),
.driver_info = (kernel_ulong_t)&zte_me3620_xl_blacklist },
{ USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_ME3620_MBIM),
.driver_info = (kernel_ulong_t)&zte_me3620_mbim_blacklist },
{ USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_ME3620_X),
.driver_info = (kernel_ulong_t)&zte_me3620_xl_blacklist },
{ USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_ZM8620_X),
.driver_info = (kernel_ulong_t)&zte_zm8620_x_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) },
......
......@@ -80,6 +80,8 @@ static int whiteheat_firmware_download(struct usb_serial *serial,
static int whiteheat_firmware_attach(struct usb_serial *serial);
/* function prototypes for the Connect Tech WhiteHEAT serial converter */
static int whiteheat_probe(struct usb_serial *serial,
const struct usb_device_id *id);
static int whiteheat_attach(struct usb_serial *serial);
static void whiteheat_release(struct usb_serial *serial);
static int whiteheat_port_probe(struct usb_serial_port *port);
......@@ -116,6 +118,7 @@ static struct usb_serial_driver whiteheat_device = {
.description = "Connect Tech - WhiteHEAT",
.id_table = id_table_std,
.num_ports = 4,
.probe = whiteheat_probe,
.attach = whiteheat_attach,
.release = whiteheat_release,
.port_probe = whiteheat_port_probe,
......@@ -217,6 +220,34 @@ static int whiteheat_firmware_attach(struct usb_serial *serial)
/*****************************************************************************
* Connect Tech's White Heat serial driver functions
*****************************************************************************/
static int whiteheat_probe(struct usb_serial *serial,
const struct usb_device_id *id)
{
struct usb_host_interface *iface_desc;
struct usb_endpoint_descriptor *endpoint;
size_t num_bulk_in = 0;
size_t num_bulk_out = 0;
size_t min_num_bulk;
unsigned int i;
iface_desc = serial->interface->cur_altsetting;
for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) {
endpoint = &iface_desc->endpoint[i].desc;
if (usb_endpoint_is_bulk_in(endpoint))
++num_bulk_in;
if (usb_endpoint_is_bulk_out(endpoint))
++num_bulk_out;
}
min_num_bulk = COMMAND_PORT + 1;
if (num_bulk_in < min_num_bulk || num_bulk_out < min_num_bulk)
return -ENODEV;
return 0;
}
static int whiteheat_attach(struct usb_serial *serial)
{
struct usb_serial_port *command_port;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册