Commit 44aa31a2 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull USB driver fixes from Greg KH:
 "Here are some small USB driver fixes for 5.17-rc2 that resolve a
  number of reported problems. These include:

   - typec driver fixes

   - xhci platform driver fixes for suspending

   - ulpi core fix

   - role.h build fix

   - new device ids

   - syzbot-reported bugfixes

   - gadget driver fixes

   - dwc3 driver fixes

   - other small fixes

  All of these have been in linux-next this week with no reported
  issues"

* tag 'usb-5.17-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb:
  usb: cdnsp: Fix segmentation fault in cdns_lost_power function
  usb: dwc2: gadget: don't try to disable ep0 in dwc2_hsotg_suspend
  usb: gadget: at91_udc: fix incorrect print type
  usb: dwc3: xilinx: Fix error handling when getting USB3 PHY
  usb: dwc3: xilinx: Skip resets and USB3 register settings for USB2.0 mode
  usb: xhci-plat: fix crash when suspend if remote wake enable
  usb: common: ulpi: Fix crash in ulpi_match()
  usb: gadget: f_sourcesink: Fix isoc transfer for USB_SPEED_SUPER_PLUS
  ucsi_ccg: Check DEV_INT bit only when starting CCG4
  USB: core: Fix hang in usb_kill_urb by adding memory barriers
  usb-storage: Add unusual-devs entry for VL817 USB-SATA bridge
  usb: typec: tcpm: Do not disconnect when receiving VSAFE0V
  usb: typec: tcpm: Do not disconnect while receiving VBUS off
  usb: typec: Don't try to register component master without components
  usb: typec: Only attempt to link USB ports if there is fwnode
  usb: typec: tcpci: don't touch CC line if it's Vconn source
  usb: roles: fix include/linux/usb/role.h compile issue
parents cb323ee7 79aa3e19
...@@ -483,11 +483,11 @@ int cdns_drd_exit(struct cdns *cdns) ...@@ -483,11 +483,11 @@ int cdns_drd_exit(struct cdns *cdns)
/* Indicate the cdns3 core was power lost before */ /* Indicate the cdns3 core was power lost before */
bool cdns_power_is_lost(struct cdns *cdns) bool cdns_power_is_lost(struct cdns *cdns)
{ {
if (cdns->version == CDNS3_CONTROLLER_V1) { if (cdns->version == CDNS3_CONTROLLER_V0) {
if (!(readl(&cdns->otg_v1_regs->simulate) & BIT(0))) if (!(readl(&cdns->otg_v0_regs->simulate) & BIT(0)))
return true; return true;
} else { } else {
if (!(readl(&cdns->otg_v0_regs->simulate) & BIT(0))) if (!(readl(&cdns->otg_v1_regs->simulate) & BIT(0)))
return true; return true;
} }
return false; return false;
......
...@@ -39,8 +39,11 @@ static int ulpi_match(struct device *dev, struct device_driver *driver) ...@@ -39,8 +39,11 @@ static int ulpi_match(struct device *dev, struct device_driver *driver)
struct ulpi *ulpi = to_ulpi_dev(dev); struct ulpi *ulpi = to_ulpi_dev(dev);
const struct ulpi_device_id *id; const struct ulpi_device_id *id;
/* Some ULPI devices don't have a vendor id so rely on OF match */ /*
if (ulpi->id.vendor == 0) * Some ULPI devices don't have a vendor id
* or provide an id_table so rely on OF match.
*/
if (ulpi->id.vendor == 0 || !drv->id_table)
return of_driver_match_device(dev, driver); return of_driver_match_device(dev, driver);
for (id = drv->id_table; id->vendor; id++) for (id = drv->id_table; id->vendor; id++)
......
...@@ -1563,6 +1563,13 @@ int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags) ...@@ -1563,6 +1563,13 @@ int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags)
urb->hcpriv = NULL; urb->hcpriv = NULL;
INIT_LIST_HEAD(&urb->urb_list); INIT_LIST_HEAD(&urb->urb_list);
atomic_dec(&urb->use_count); atomic_dec(&urb->use_count);
/*
* Order the write of urb->use_count above before the read
* of urb->reject below. Pairs with the memory barriers in
* usb_kill_urb() and usb_poison_urb().
*/
smp_mb__after_atomic();
atomic_dec(&urb->dev->urbnum); atomic_dec(&urb->dev->urbnum);
if (atomic_read(&urb->reject)) if (atomic_read(&urb->reject))
wake_up(&usb_kill_urb_queue); wake_up(&usb_kill_urb_queue);
...@@ -1665,6 +1672,13 @@ static void __usb_hcd_giveback_urb(struct urb *urb) ...@@ -1665,6 +1672,13 @@ static void __usb_hcd_giveback_urb(struct urb *urb)
usb_anchor_resume_wakeups(anchor); usb_anchor_resume_wakeups(anchor);
atomic_dec(&urb->use_count); atomic_dec(&urb->use_count);
/*
* Order the write of urb->use_count above before the read
* of urb->reject below. Pairs with the memory barriers in
* usb_kill_urb() and usb_poison_urb().
*/
smp_mb__after_atomic();
if (unlikely(atomic_read(&urb->reject))) if (unlikely(atomic_read(&urb->reject)))
wake_up(&usb_kill_urb_queue); wake_up(&usb_kill_urb_queue);
usb_put_urb(urb); usb_put_urb(urb);
......
...@@ -715,6 +715,12 @@ void usb_kill_urb(struct urb *urb) ...@@ -715,6 +715,12 @@ void usb_kill_urb(struct urb *urb)
if (!(urb && urb->dev && urb->ep)) if (!(urb && urb->dev && urb->ep))
return; return;
atomic_inc(&urb->reject); atomic_inc(&urb->reject);
/*
* Order the write of urb->reject above before the read
* of urb->use_count below. Pairs with the barriers in
* __usb_hcd_giveback_urb() and usb_hcd_submit_urb().
*/
smp_mb__after_atomic();
usb_hcd_unlink_urb(urb, -ENOENT); usb_hcd_unlink_urb(urb, -ENOENT);
wait_event(usb_kill_urb_queue, atomic_read(&urb->use_count) == 0); wait_event(usb_kill_urb_queue, atomic_read(&urb->use_count) == 0);
...@@ -756,6 +762,12 @@ void usb_poison_urb(struct urb *urb) ...@@ -756,6 +762,12 @@ void usb_poison_urb(struct urb *urb)
if (!urb) if (!urb)
return; return;
atomic_inc(&urb->reject); atomic_inc(&urb->reject);
/*
* Order the write of urb->reject above before the read
* of urb->use_count below. Pairs with the barriers in
* __usb_hcd_giveback_urb() and usb_hcd_submit_urb().
*/
smp_mb__after_atomic();
if (!urb->dev || !urb->ep) if (!urb->dev || !urb->ep)
return; return;
......
...@@ -5097,7 +5097,7 @@ int dwc2_hsotg_suspend(struct dwc2_hsotg *hsotg) ...@@ -5097,7 +5097,7 @@ int dwc2_hsotg_suspend(struct dwc2_hsotg *hsotg)
hsotg->gadget.speed = USB_SPEED_UNKNOWN; hsotg->gadget.speed = USB_SPEED_UNKNOWN;
spin_unlock_irqrestore(&hsotg->lock, flags); spin_unlock_irqrestore(&hsotg->lock, flags);
for (ep = 0; ep < hsotg->num_of_eps; ep++) { for (ep = 1; ep < hsotg->num_of_eps; ep++) {
if (hsotg->eps_in[ep]) if (hsotg->eps_in[ep])
dwc2_hsotg_ep_disable_lock(&hsotg->eps_in[ep]->ep); dwc2_hsotg_ep_disable_lock(&hsotg->eps_in[ep]->ep);
if (hsotg->eps_out[ep]) if (hsotg->eps_out[ep])
......
...@@ -102,14 +102,26 @@ static int dwc3_xlnx_init_zynqmp(struct dwc3_xlnx *priv_data) ...@@ -102,14 +102,26 @@ static int dwc3_xlnx_init_zynqmp(struct dwc3_xlnx *priv_data)
int ret; int ret;
u32 reg; u32 reg;
usb3_phy = devm_phy_get(dev, "usb3-phy"); usb3_phy = devm_phy_optional_get(dev, "usb3-phy");
if (PTR_ERR(usb3_phy) == -EPROBE_DEFER) { if (IS_ERR(usb3_phy)) {
ret = -EPROBE_DEFER; ret = PTR_ERR(usb3_phy);
dev_err_probe(dev, ret,
"failed to get USB3 PHY\n");
goto err; goto err;
} else if (IS_ERR(usb3_phy)) {
usb3_phy = NULL;
} }
/*
* The following core resets are not required unless a USB3 PHY
* is used, and the subsequent register settings are not required
* unless a core reset is performed (they should be set properly
* by the first-stage boot loader, but may be reverted by a core
* reset). They may also break the configuration if USB3 is actually
* in use but the usb3-phy entry is missing from the device tree.
* Therefore, skip these operations in this case.
*/
if (!usb3_phy)
goto skip_usb3_phy;
crst = devm_reset_control_get_exclusive(dev, "usb_crst"); crst = devm_reset_control_get_exclusive(dev, "usb_crst");
if (IS_ERR(crst)) { if (IS_ERR(crst)) {
ret = PTR_ERR(crst); ret = PTR_ERR(crst);
...@@ -188,6 +200,7 @@ static int dwc3_xlnx_init_zynqmp(struct dwc3_xlnx *priv_data) ...@@ -188,6 +200,7 @@ static int dwc3_xlnx_init_zynqmp(struct dwc3_xlnx *priv_data)
goto err; goto err;
} }
skip_usb3_phy:
/* /*
* This routes the USB DMA traffic to go through FPD path instead * This routes the USB DMA traffic to go through FPD path instead
* of reaching DDR directly. This traffic routing is needed to * of reaching DDR directly. This traffic routing is needed to
......
...@@ -584,6 +584,7 @@ static int source_sink_start_ep(struct f_sourcesink *ss, bool is_in, ...@@ -584,6 +584,7 @@ static int source_sink_start_ep(struct f_sourcesink *ss, bool is_in,
if (is_iso) { if (is_iso) {
switch (speed) { switch (speed) {
case USB_SPEED_SUPER_PLUS:
case USB_SPEED_SUPER: case USB_SPEED_SUPER:
size = ss->isoc_maxpacket * size = ss->isoc_maxpacket *
(ss->isoc_mult + 1) * (ss->isoc_mult + 1) *
......
...@@ -1895,7 +1895,7 @@ static int at91udc_probe(struct platform_device *pdev) ...@@ -1895,7 +1895,7 @@ static int at91udc_probe(struct platform_device *pdev)
at91_vbus_irq, 0, driver_name, udc); at91_vbus_irq, 0, driver_name, udc);
if (retval) { if (retval) {
DBG("request vbus irq %d failed\n", DBG("request vbus irq %d failed\n",
udc->board.vbus_pin); desc_to_gpio(udc->board.vbus_pin));
goto err_unprepare_iclk; goto err_unprepare_iclk;
} }
} }
......
...@@ -437,6 +437,9 @@ static int __maybe_unused xhci_plat_suspend(struct device *dev) ...@@ -437,6 +437,9 @@ static int __maybe_unused xhci_plat_suspend(struct device *dev)
struct xhci_hcd *xhci = hcd_to_xhci(hcd); struct xhci_hcd *xhci = hcd_to_xhci(hcd);
int ret; int ret;
if (pm_runtime_suspended(dev))
pm_runtime_resume(dev);
ret = xhci_priv_suspend_quirk(hcd); ret = xhci_priv_suspend_quirk(hcd);
if (ret) if (ret)
return ret; return ret;
......
...@@ -2301,6 +2301,16 @@ UNUSUAL_DEV( 0x2027, 0xa001, 0x0000, 0x9999, ...@@ -2301,6 +2301,16 @@ UNUSUAL_DEV( 0x2027, 0xa001, 0x0000, 0x9999,
USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_euscsi_init, USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_euscsi_init,
US_FL_SCM_MULT_TARG ), US_FL_SCM_MULT_TARG ),
/*
* Reported by DocMAX <mail@vacharakis.de>
* and Thomas Weißschuh <linux@weissschuh.net>
*/
UNUSUAL_DEV( 0x2109, 0x0715, 0x9999, 0x9999,
"VIA Labs, Inc.",
"VL817 SATA Bridge",
USB_SC_DEVICE, USB_PR_DEVICE, NULL,
US_FL_IGNORE_UAS),
UNUSUAL_DEV( 0x2116, 0x0320, 0x0001, 0x0001, UNUSUAL_DEV( 0x2116, 0x0320, 0x0001, 0x0001,
"ST", "ST",
"2A", "2A",
......
...@@ -56,7 +56,12 @@ int typec_link_ports(struct typec_port *con) ...@@ -56,7 +56,12 @@ int typec_link_ports(struct typec_port *con)
{ {
struct each_port_arg arg = { .port = con, .match = NULL }; struct each_port_arg arg = { .port = con, .match = NULL };
if (!has_acpi_companion(&con->dev))
return 0;
bus_for_each_dev(&acpi_bus_type, NULL, &arg, typec_port_match); bus_for_each_dev(&acpi_bus_type, NULL, &arg, typec_port_match);
if (!arg.match)
return 0;
/* /*
* REVISIT: Now each connector can have only a single component master. * REVISIT: Now each connector can have only a single component master.
...@@ -74,5 +79,6 @@ int typec_link_ports(struct typec_port *con) ...@@ -74,5 +79,6 @@ int typec_link_ports(struct typec_port *con)
void typec_unlink_ports(struct typec_port *con) void typec_unlink_ports(struct typec_port *con)
{ {
if (has_acpi_companion(&con->dev))
component_master_del(&con->dev, &typec_aggregate_ops); component_master_del(&con->dev, &typec_aggregate_ops);
} }
...@@ -75,9 +75,25 @@ static int tcpci_write16(struct tcpci *tcpci, unsigned int reg, u16 val) ...@@ -75,9 +75,25 @@ static int tcpci_write16(struct tcpci *tcpci, unsigned int reg, u16 val)
static int tcpci_set_cc(struct tcpc_dev *tcpc, enum typec_cc_status cc) static int tcpci_set_cc(struct tcpc_dev *tcpc, enum typec_cc_status cc)
{ {
struct tcpci *tcpci = tcpc_to_tcpci(tcpc); struct tcpci *tcpci = tcpc_to_tcpci(tcpc);
bool vconn_pres;
enum typec_cc_polarity polarity = TYPEC_POLARITY_CC1;
unsigned int reg; unsigned int reg;
int ret; int ret;
ret = regmap_read(tcpci->regmap, TCPC_POWER_STATUS, &reg);
if (ret < 0)
return ret;
vconn_pres = !!(reg & TCPC_POWER_STATUS_VCONN_PRES);
if (vconn_pres) {
ret = regmap_read(tcpci->regmap, TCPC_TCPC_CTRL, &reg);
if (ret < 0)
return ret;
if (reg & TCPC_TCPC_CTRL_ORIENTATION)
polarity = TYPEC_POLARITY_CC2;
}
switch (cc) { switch (cc) {
case TYPEC_CC_RA: case TYPEC_CC_RA:
reg = (TCPC_ROLE_CTRL_CC_RA << TCPC_ROLE_CTRL_CC1_SHIFT) | reg = (TCPC_ROLE_CTRL_CC_RA << TCPC_ROLE_CTRL_CC1_SHIFT) |
...@@ -112,6 +128,16 @@ static int tcpci_set_cc(struct tcpc_dev *tcpc, enum typec_cc_status cc) ...@@ -112,6 +128,16 @@ static int tcpci_set_cc(struct tcpc_dev *tcpc, enum typec_cc_status cc)
break; break;
} }
if (vconn_pres) {
if (polarity == TYPEC_POLARITY_CC2) {
reg &= ~(TCPC_ROLE_CTRL_CC1_MASK << TCPC_ROLE_CTRL_CC1_SHIFT);
reg |= (TCPC_ROLE_CTRL_CC_OPEN << TCPC_ROLE_CTRL_CC1_SHIFT);
} else {
reg &= ~(TCPC_ROLE_CTRL_CC2_MASK << TCPC_ROLE_CTRL_CC2_SHIFT);
reg |= (TCPC_ROLE_CTRL_CC_OPEN << TCPC_ROLE_CTRL_CC2_SHIFT);
}
}
ret = regmap_write(tcpci->regmap, TCPC_ROLE_CTRL, reg); ret = regmap_write(tcpci->regmap, TCPC_ROLE_CTRL, reg);
if (ret < 0) if (ret < 0)
return ret; return ret;
......
...@@ -98,6 +98,7 @@ ...@@ -98,6 +98,7 @@
#define TCPC_POWER_STATUS_SOURCING_VBUS BIT(4) #define TCPC_POWER_STATUS_SOURCING_VBUS BIT(4)
#define TCPC_POWER_STATUS_VBUS_DET BIT(3) #define TCPC_POWER_STATUS_VBUS_DET BIT(3)
#define TCPC_POWER_STATUS_VBUS_PRES BIT(2) #define TCPC_POWER_STATUS_VBUS_PRES BIT(2)
#define TCPC_POWER_STATUS_VCONN_PRES BIT(1)
#define TCPC_POWER_STATUS_SINKING_VBUS BIT(0) #define TCPC_POWER_STATUS_SINKING_VBUS BIT(0)
#define TCPC_FAULT_STATUS 0x1f #define TCPC_FAULT_STATUS 0x1f
......
...@@ -5156,7 +5156,8 @@ static void _tcpm_pd_vbus_off(struct tcpm_port *port) ...@@ -5156,7 +5156,8 @@ static void _tcpm_pd_vbus_off(struct tcpm_port *port)
case SNK_TRYWAIT_DEBOUNCE: case SNK_TRYWAIT_DEBOUNCE:
break; break;
case SNK_ATTACH_WAIT: case SNK_ATTACH_WAIT:
tcpm_set_state(port, SNK_UNATTACHED, 0); case SNK_DEBOUNCED:
/* Do nothing, as TCPM is still waiting for vbus to reaach VSAFE5V to connect */
break; break;
case SNK_NEGOTIATE_CAPABILITIES: case SNK_NEGOTIATE_CAPABILITIES:
...@@ -5263,6 +5264,10 @@ static void _tcpm_pd_vbus_vsafe0v(struct tcpm_port *port) ...@@ -5263,6 +5264,10 @@ static void _tcpm_pd_vbus_vsafe0v(struct tcpm_port *port)
case PR_SWAP_SNK_SRC_SOURCE_ON: case PR_SWAP_SNK_SRC_SOURCE_ON:
/* Do nothing, vsafe0v is expected during transition */ /* Do nothing, vsafe0v is expected during transition */
break; break;
case SNK_ATTACH_WAIT:
case SNK_DEBOUNCED:
/*Do nothing, still waiting for VSAFE5V for connect */
break;
default: default:
if (port->pwr_role == TYPEC_SINK && port->auto_vbus_discharge_enabled) if (port->pwr_role == TYPEC_SINK && port->auto_vbus_discharge_enabled)
tcpm_set_state(port, SNK_UNATTACHED, 0); tcpm_set_state(port, SNK_UNATTACHED, 0);
......
...@@ -325,7 +325,7 @@ static int ucsi_ccg_init(struct ucsi_ccg *uc) ...@@ -325,7 +325,7 @@ static int ucsi_ccg_init(struct ucsi_ccg *uc)
if (status < 0) if (status < 0)
return status; return status;
if (!data) if (!(data & DEV_INT))
return 0; return 0;
status = ccg_write(uc, CCGX_RAB_INTR_REG, &data, sizeof(data)); status = ccg_write(uc, CCGX_RAB_INTR_REG, &data, sizeof(data));
......
...@@ -91,6 +91,12 @@ fwnode_usb_role_switch_get(struct fwnode_handle *node) ...@@ -91,6 +91,12 @@ fwnode_usb_role_switch_get(struct fwnode_handle *node)
static inline void usb_role_switch_put(struct usb_role_switch *sw) { } static inline void usb_role_switch_put(struct usb_role_switch *sw) { }
static inline struct usb_role_switch *
usb_role_switch_find_by_fwnode(const struct fwnode_handle *fwnode)
{
return NULL;
}
static inline struct usb_role_switch * static inline struct usb_role_switch *
usb_role_switch_register(struct device *parent, usb_role_switch_register(struct device *parent,
const struct usb_role_switch_desc *desc) const struct usb_role_switch_desc *desc)
......
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