Skip to content

Commit

Permalink
Merge tag 'usb-5.18-rc5' of git://git.kernel.org/pub/scm/linux/kernel…
Browse files Browse the repository at this point in the history
…/git/gregkh/usb

Pull USB fixes from Greg KH:
 "Here are a number of small USB driver fixes for 5.18-rc5 for some
  reported issues and new quirks. They include:

   - dwc3 driver fixes

   - xhci driver fixes

   - typec driver fixes

   - new usb-serial driver ids

   - added new USB devices to existing quirk tables

   - other tiny fixes

  All of these have been in linux-next for a while with no reported
  issues"

* tag 'usb-5.18-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (31 commits)
  usb: phy: generic: Get the vbus supply
  usb: dwc3: gadget: Return proper request status
  usb: dwc3: pci: add support for the Intel Meteor Lake-P
  usb: dwc3: core: Only handle soft-reset in DCTL
  usb: gadget: configfs: clear deactivation flag in configfs_composite_unbind()
  usb: misc: eud: Fix an error handling path in eud_probe()
  usb: core: Don't hold the device lock while sleeping in do_proc_control()
  usb: dwc3: Try usb-role-switch first in dwc3_drd_init
  usb: dwc3: core: Fix tx/rx threshold settings
  usb: mtu3: fix USB 3.0 dual-role-switch from device to host
  xhci: Enable runtime PM on second Alderlake controller
  usb: dwc3: fix backwards compat with rockchip devices
  dt-bindings: usb: samsung,exynos-usb2: add missing required reg
  usb: misc: fix improper handling of refcount in uss720_probe()
  USB: Fix ehci infinite suspend-resume loop issue in zhaoxin
  usb: typec: tcpm: Fix undefined behavior due to shift overflowing the constant
  usb: typec: rt1719: Fix build error without CONFIG_POWER_SUPPLY
  usb: typec: ucsi: Fix role swapping
  usb: typec: ucsi: Fix reuse of completion structure
  usb: xhci: tegra:Fix PM usage reference leak of tegra_xusb_unpowergate_partitions
  ...
  • Loading branch information
Linus Torvalds committed Apr 30, 2022
2 parents e9512f3 + 03e607c commit da1b404
Show file tree
Hide file tree
Showing 28 changed files with 193 additions and 45 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ required:
- interrupts
- phys
- phy-names
- reg

allOf:
- if:
Expand Down
7 changes: 5 additions & 2 deletions drivers/usb/cdns3/cdns3-gadget.c
Original file line number Diff line number Diff line change
Expand Up @@ -2684,6 +2684,7 @@ int __cdns3_gadget_ep_clear_halt(struct cdns3_endpoint *priv_ep)
struct usb_request *request;
struct cdns3_request *priv_req;
struct cdns3_trb *trb = NULL;
struct cdns3_trb trb_tmp;
int ret;
int val;

Expand All @@ -2693,8 +2694,10 @@ int __cdns3_gadget_ep_clear_halt(struct cdns3_endpoint *priv_ep)
if (request) {
priv_req = to_cdns3_request(request);
trb = priv_req->trb;
if (trb)
if (trb) {
trb_tmp = *trb;
trb->control = trb->control ^ cpu_to_le32(TRB_CYCLE);
}
}

writel(EP_CMD_CSTALL | EP_CMD_EPRST, &priv_dev->regs->ep_cmd);
Expand All @@ -2709,7 +2712,7 @@ int __cdns3_gadget_ep_clear_halt(struct cdns3_endpoint *priv_ep)

if (request) {
if (trb)
trb->control = trb->control ^ cpu_to_le32(TRB_CYCLE);
*trb = trb_tmp;

cdns3_rearm_transfer(priv_ep, 1);
}
Expand Down
14 changes: 9 additions & 5 deletions drivers/usb/core/devio.c
Original file line number Diff line number Diff line change
Expand Up @@ -1209,12 +1209,16 @@ static int do_proc_control(struct usb_dev_state *ps,

usb_unlock_device(dev);
i = usbfs_start_wait_urb(urb, tmo, &actlen);

/* Linger a bit, prior to the next control message. */
if (dev->quirks & USB_QUIRK_DELAY_CTRL_MSG)
msleep(200);
usb_lock_device(dev);
snoop_urb(dev, NULL, pipe, actlen, i, COMPLETE, tbuf, actlen);
if (!i && actlen) {
if (copy_to_user(ctrl->data, tbuf, actlen)) {
ret = -EFAULT;
goto recv_fault;
goto done;
}
}
} else {
Expand All @@ -1231,6 +1235,10 @@ static int do_proc_control(struct usb_dev_state *ps,

usb_unlock_device(dev);
i = usbfs_start_wait_urb(urb, tmo, &actlen);

/* Linger a bit, prior to the next control message. */
if (dev->quirks & USB_QUIRK_DELAY_CTRL_MSG)
msleep(200);
usb_lock_device(dev);
snoop_urb(dev, NULL, pipe, actlen, i, COMPLETE, NULL, 0);
}
Expand All @@ -1242,10 +1250,6 @@ static int do_proc_control(struct usb_dev_state *ps,
}
ret = (i < 0 ? i : actlen);

recv_fault:
/* Linger a bit, prior to the next control message. */
if (dev->quirks & USB_QUIRK_DELAY_CTRL_MSG)
msleep(200);
done:
kfree(dr);
usb_free_urb(urb);
Expand Down
6 changes: 6 additions & 0 deletions drivers/usb/core/quirks.c
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,9 @@ static const struct usb_device_id usb_quirk_list[] = {
{ USB_DEVICE(0x0b05, 0x17e0), .driver_info =
USB_QUIRK_IGNORE_REMOTE_WAKEUP },

/* Realtek Semiconductor Corp. Mass Storage Device (Multicard Reader)*/
{ USB_DEVICE(0x0bda, 0x0151), .driver_info = USB_QUIRK_CONFIG_INTF_STRINGS },

/* Realtek hub in Dell WD19 (Type-C) */
{ USB_DEVICE(0x0bda, 0x0487), .driver_info = USB_QUIRK_NO_LPM },

Expand Down Expand Up @@ -507,6 +510,9 @@ static const struct usb_device_id usb_quirk_list[] = {
/* DJI CineSSD */
{ USB_DEVICE(0x2ca3, 0x0031), .driver_info = USB_QUIRK_NO_LPM },

/* VCOM device */
{ USB_DEVICE(0x4296, 0x7570), .driver_info = USB_QUIRK_CONFIG_INTF_STRINGS },

/* INTEL VALUE SSD */
{ USB_DEVICE(0x8086, 0xf1a5), .driver_info = USB_QUIRK_RESET_RESUME },

Expand Down
34 changes: 29 additions & 5 deletions drivers/usb/dwc3/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,8 @@ int dwc3_core_soft_reset(struct dwc3 *dwc)

reg = dwc3_readl(dwc->regs, DWC3_DCTL);
reg |= DWC3_DCTL_CSFTRST;
dwc3_writel(dwc->regs, DWC3_DCTL, reg);
reg &= ~DWC3_DCTL_RUN_STOP;
dwc3_gadget_dctl_write_safe(dwc, reg);

/*
* For DWC_usb31 controller 1.90a and later, the DCTL.CSFRST bit
Expand Down Expand Up @@ -1377,10 +1378,10 @@ static void dwc3_get_properties(struct dwc3 *dwc)
u8 lpm_nyet_threshold;
u8 tx_de_emphasis;
u8 hird_threshold;
u8 rx_thr_num_pkt_prd;
u8 rx_max_burst_prd;
u8 tx_thr_num_pkt_prd;
u8 tx_max_burst_prd;
u8 rx_thr_num_pkt_prd = 0;
u8 rx_max_burst_prd = 0;
u8 tx_thr_num_pkt_prd = 0;
u8 tx_max_burst_prd = 0;
u8 tx_fifo_resize_max_num;
const char *usb_psy_name;
int ret;
Expand Down Expand Up @@ -1690,21 +1691,44 @@ static int dwc3_probe(struct platform_device *pdev)
/*
* Clocks are optional, but new DT platforms should support all
* clocks as required by the DT-binding.
* Some devices have different clock names in legacy device trees,
* check for them to retain backwards compatibility.
*/
dwc->bus_clk = devm_clk_get_optional(dev, "bus_early");
if (IS_ERR(dwc->bus_clk))
return dev_err_probe(dev, PTR_ERR(dwc->bus_clk),
"could not get bus clock\n");

if (dwc->bus_clk == NULL) {
dwc->bus_clk = devm_clk_get_optional(dev, "bus_clk");
if (IS_ERR(dwc->bus_clk))
return dev_err_probe(dev, PTR_ERR(dwc->bus_clk),
"could not get bus clock\n");
}

dwc->ref_clk = devm_clk_get_optional(dev, "ref");
if (IS_ERR(dwc->ref_clk))
return dev_err_probe(dev, PTR_ERR(dwc->ref_clk),
"could not get ref clock\n");

if (dwc->ref_clk == NULL) {
dwc->ref_clk = devm_clk_get_optional(dev, "ref_clk");
if (IS_ERR(dwc->ref_clk))
return dev_err_probe(dev, PTR_ERR(dwc->ref_clk),
"could not get ref clock\n");
}

dwc->susp_clk = devm_clk_get_optional(dev, "suspend");
if (IS_ERR(dwc->susp_clk))
return dev_err_probe(dev, PTR_ERR(dwc->susp_clk),
"could not get suspend clock\n");

if (dwc->susp_clk == NULL) {
dwc->susp_clk = devm_clk_get_optional(dev, "suspend_clk");
if (IS_ERR(dwc->susp_clk))
return dev_err_probe(dev, PTR_ERR(dwc->susp_clk),
"could not get suspend clock\n");
}
}

ret = reset_control_deassert(dwc->reset);
Expand Down
11 changes: 5 additions & 6 deletions drivers/usb/dwc3/drd.c
Original file line number Diff line number Diff line change
Expand Up @@ -584,16 +584,15 @@ int dwc3_drd_init(struct dwc3 *dwc)
{
int ret, irq;

if (ROLE_SWITCH &&
device_property_read_bool(dwc->dev, "usb-role-switch"))
return dwc3_setup_role_switch(dwc);

dwc->edev = dwc3_get_extcon(dwc);
if (IS_ERR(dwc->edev))
return PTR_ERR(dwc->edev);

if (ROLE_SWITCH &&
device_property_read_bool(dwc->dev, "usb-role-switch")) {
ret = dwc3_setup_role_switch(dwc);
if (ret < 0)
return ret;
} else if (dwc->edev) {
if (dwc->edev) {
dwc->edev_nb.notifier_call = dwc3_drd_notifier;
ret = extcon_register_notifier(dwc->edev, EXTCON_USB_HOST,
&dwc->edev_nb);
Expand Down
8 changes: 8 additions & 0 deletions drivers/usb/dwc3/dwc3-pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@
#define PCI_DEVICE_ID_INTEL_ADLM 0x54ee
#define PCI_DEVICE_ID_INTEL_ADLS 0x7ae1
#define PCI_DEVICE_ID_INTEL_RPLS 0x7a61
#define PCI_DEVICE_ID_INTEL_MTLP 0x7ec1
#define PCI_DEVICE_ID_INTEL_MTL 0x7e7e
#define PCI_DEVICE_ID_INTEL_TGL 0x9a15
#define PCI_DEVICE_ID_AMD_MR 0x163a

Expand Down Expand Up @@ -456,6 +458,12 @@ static const struct pci_device_id dwc3_pci_id_table[] = {
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_RPLS),
(kernel_ulong_t) &dwc3_pci_intel_swnode, },

{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_MTLP),
(kernel_ulong_t) &dwc3_pci_intel_swnode, },

{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_MTL),
(kernel_ulong_t) &dwc3_pci_intel_swnode, },

{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_TGL),
(kernel_ulong_t) &dwc3_pci_intel_swnode, },

Expand Down
31 changes: 30 additions & 1 deletion drivers/usb/dwc3/gadget.c
Original file line number Diff line number Diff line change
Expand Up @@ -3274,6 +3274,7 @@ static int dwc3_gadget_ep_cleanup_completed_request(struct dwc3_ep *dep,
const struct dwc3_event_depevt *event,
struct dwc3_request *req, int status)
{
int request_status;
int ret;

if (req->request.num_mapped_sgs)
Expand All @@ -3294,7 +3295,35 @@ static int dwc3_gadget_ep_cleanup_completed_request(struct dwc3_ep *dep,
req->needs_extra_trb = false;
}

dwc3_gadget_giveback(dep, req, status);
/*
* The event status only reflects the status of the TRB with IOC set.
* For the requests that don't set interrupt on completion, the driver
* needs to check and return the status of the completed TRBs associated
* with the request. Use the status of the last TRB of the request.
*/
if (req->request.no_interrupt) {
struct dwc3_trb *trb;

trb = dwc3_ep_prev_trb(dep, dep->trb_dequeue);
switch (DWC3_TRB_SIZE_TRBSTS(trb->size)) {
case DWC3_TRBSTS_MISSED_ISOC:
/* Isoc endpoint only */
request_status = -EXDEV;
break;
case DWC3_TRB_STS_XFER_IN_PROG:
/* Applicable when End Transfer with ForceRM=0 */
case DWC3_TRBSTS_SETUP_PENDING:
/* Control endpoint only */
case DWC3_TRBSTS_OK:
default:
request_status = 0;
break;
}
} else {
request_status = status;
}

dwc3_gadget_giveback(dep, req, request_status);

out:
return ret;
Expand Down
2 changes: 2 additions & 0 deletions drivers/usb/gadget/configfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -1438,6 +1438,8 @@ static void configfs_composite_unbind(struct usb_gadget *gadget)
usb_ep_autoconfig_reset(cdev->gadget);
spin_lock_irqsave(&gi->spinlock, flags);
cdev->gadget = NULL;
cdev->deactivations = 0;
gadget->deactivated = false;
set_gadget_data(gadget, NULL);
spin_unlock_irqrestore(&gi->spinlock, flags);
}
Expand Down
2 changes: 2 additions & 0 deletions drivers/usb/gadget/function/uvc_queue.c
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,8 @@ void uvcg_queue_cancel(struct uvc_video_queue *queue, int disconnect)
buf->state = UVC_BUF_STATE_ERROR;
vb2_buffer_done(&buf->buf.vb2_buf, VB2_BUF_STATE_ERROR);
}
queue->buf_used = 0;

/* This must be protected by the irqlock spinlock to avoid race
* conditions between uvc_queue_buffer and the disconnection event that
* could result in an interruptible wait in uvc_dequeue_buffer. Do not
Expand Down
23 changes: 23 additions & 0 deletions drivers/usb/host/ehci-hcd.c
Original file line number Diff line number Diff line change
Expand Up @@ -1103,6 +1103,26 @@ static void ehci_remove_device(struct usb_hcd *hcd, struct usb_device *udev)

#ifdef CONFIG_PM

/* Clear wakeup signal locked in zhaoxin platform when device plug in. */
static void ehci_zx_wakeup_clear(struct ehci_hcd *ehci)
{
u32 __iomem *reg = &ehci->regs->port_status[4];
u32 t1 = ehci_readl(ehci, reg);

t1 &= (u32)~0xf0000;
t1 |= PORT_TEST_FORCE;
ehci_writel(ehci, t1, reg);
t1 = ehci_readl(ehci, reg);
msleep(1);
t1 &= (u32)~0xf0000;
ehci_writel(ehci, t1, reg);
ehci_readl(ehci, reg);
msleep(1);
t1 = ehci_readl(ehci, reg);
ehci_writel(ehci, t1 | PORT_CSC, reg);
ehci_readl(ehci, reg);
}

/* suspend/resume, section 4.3 */

/* These routines handle the generic parts of controller suspend/resume */
Expand Down Expand Up @@ -1154,6 +1174,9 @@ int ehci_resume(struct usb_hcd *hcd, bool force_reset)
if (ehci->shutdown)
return 0; /* Controller is dead */

if (ehci->zx_wakeup_clear_needed)
ehci_zx_wakeup_clear(ehci);

/*
* If CF is still set and reset isn't forced
* then we maintained suspend power.
Expand Down
4 changes: 4 additions & 0 deletions drivers/usb/host/ehci-pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,10 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
ehci->is_aspeed = 1;
}
break;
case PCI_VENDOR_ID_ZHAOXIN:
if (pdev->device == 0x3104 && (pdev->revision & 0xf0) == 0x90)
ehci->zx_wakeup_clear_needed = 1;
break;
}

/* optional debug port, normally in the first BAR */
Expand Down
1 change: 1 addition & 0 deletions drivers/usb/host/ehci.h
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,7 @@ struct ehci_hcd { /* one per controller */
unsigned imx28_write_fix:1; /* For Freescale i.MX28 */
unsigned spurious_oc:1;
unsigned is_aspeed:1;
unsigned zx_wakeup_clear_needed:1;

/* required for usb32 quirk */
#define OHCI_CTRL_HCFS (3 << 6)
Expand Down
2 changes: 1 addition & 1 deletion drivers/usb/host/xhci-hub.c
Original file line number Diff line number Diff line change
Expand Up @@ -1434,7 +1434,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
}
spin_unlock_irqrestore(&xhci->lock, flags);
if (!wait_for_completion_timeout(&bus_state->u3exit_done[wIndex],
msecs_to_jiffies(100)))
msecs_to_jiffies(500)))
xhci_dbg(xhci, "missing U0 port change event for port %d-%d\n",
hcd->self.busnum, wIndex + 1);
spin_lock_irqsave(&xhci->lock, flags);
Expand Down
4 changes: 3 additions & 1 deletion drivers/usb/host/xhci-pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
#define PCI_DEVICE_ID_INTEL_TIGER_LAKE_XHCI 0x9a13
#define PCI_DEVICE_ID_INTEL_MAPLE_RIDGE_XHCI 0x1138
#define PCI_DEVICE_ID_INTEL_ALDER_LAKE_XHCI 0x461e
#define PCI_DEVICE_ID_INTEL_ALDER_LAKE_PCH_XHCI 0x51ed

#define PCI_DEVICE_ID_AMD_RENOIR_XHCI 0x1639
#define PCI_DEVICE_ID_AMD_PROMONTORYA_4 0x43b9
Expand Down Expand Up @@ -266,7 +267,8 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
pdev->device == PCI_DEVICE_ID_INTEL_ICE_LAKE_XHCI ||
pdev->device == PCI_DEVICE_ID_INTEL_TIGER_LAKE_XHCI ||
pdev->device == PCI_DEVICE_ID_INTEL_MAPLE_RIDGE_XHCI ||
pdev->device == PCI_DEVICE_ID_INTEL_ALDER_LAKE_XHCI))
pdev->device == PCI_DEVICE_ID_INTEL_ALDER_LAKE_XHCI ||
pdev->device == PCI_DEVICE_ID_INTEL_ALDER_LAKE_PCH_XHCI))
xhci->quirks |= XHCI_DEFAULT_PM_RUNTIME_ALLOW;

if (pdev->vendor == PCI_VENDOR_ID_ETRON &&
Expand Down
1 change: 1 addition & 0 deletions drivers/usb/host/xhci-ring.c
Original file line number Diff line number Diff line change
Expand Up @@ -3141,6 +3141,7 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd)
if (event_loop++ < TRBS_PER_SEGMENT / 2)
continue;
xhci_update_erst_dequeue(xhci, event_ring_deq);
event_ring_deq = xhci->event_ring->dequeue;

/* ring is half-full, force isoc trbs to interrupt more often */
if (xhci->isoc_bei_interval > AVOID_BEI_INTERVAL_MIN)
Expand Down
4 changes: 2 additions & 2 deletions drivers/usb/host/xhci-tegra.c
Original file line number Diff line number Diff line change
Expand Up @@ -1034,13 +1034,13 @@ static int tegra_xusb_unpowergate_partitions(struct tegra_xusb *tegra)
int rc;

if (tegra->use_genpd) {
rc = pm_runtime_get_sync(tegra->genpd_dev_ss);
rc = pm_runtime_resume_and_get(tegra->genpd_dev_ss);
if (rc < 0) {
dev_err(dev, "failed to enable XUSB SS partition\n");
return rc;
}

rc = pm_runtime_get_sync(tegra->genpd_dev_host);
rc = pm_runtime_resume_and_get(tegra->genpd_dev_host);
if (rc < 0) {
dev_err(dev, "failed to enable XUSB Host partition\n");
pm_runtime_put_sync(tegra->genpd_dev_ss);
Expand Down
11 changes: 11 additions & 0 deletions drivers/usb/host/xhci.c
Original file line number Diff line number Diff line change
Expand Up @@ -781,6 +781,17 @@ void xhci_shutdown(struct usb_hcd *hcd)
if (xhci->quirks & XHCI_SPURIOUS_REBOOT)
usb_disable_xhci_ports(to_pci_dev(hcd->self.sysdev));

/* Don't poll the roothubs after shutdown. */
xhci_dbg(xhci, "%s: stopping usb%d port polling.\n",
__func__, hcd->self.busnum);
clear_bit(HCD_FLAG_POLL_RH, &hcd->flags);
del_timer_sync(&hcd->rh_timer);

if (xhci->shared_hcd) {
clear_bit(HCD_FLAG_POLL_RH, &xhci->shared_hcd->flags);
del_timer_sync(&xhci->shared_hcd->rh_timer);
}

spin_lock_irq(&xhci->lock);
xhci_halt(xhci);
/* Workaround for spurious wakeups at shutdown with HSW */
Expand Down
Loading

0 comments on commit da1b404

Please sign in to comment.