USB fixes for 6.10-rc6

Here are a handful of small USB driver fixes for 6.10-rc6 to resolve
 some reported issues.  Included in here are:
   - typec driver bugfixes
   - usb gadget driver reverts for commits that were reported to have
     problems
   - resource leak bugfix
   - gadget driver bugfixes
   - dwc3 driver bugfixes
   - usb atm driver bugfix for when syzbot got loose on it
 
 All of these have been in linux-next this week with no reported issues.
 
 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 -----BEGIN PGP SIGNATURE-----
 
 iG0EABECAC0WIQT0tgzFv3jCIUoxPcsxR9QN2y37KQUCZoFnUA8cZ3JlZ0Brcm9h
 aC5jb20ACgkQMUfUDdst+ym3ggCgyM2B+cIOH4FtyWi7FfXj8XjDsjIAoKzX45+o
 TO/pSGQhRwx9PeFfDISM
 =pFEO
 -----END PGP SIGNATURE-----

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

Pull USB fixes from Greg KH:
 "Here are a handful of small USB driver fixes for 6.10-rc6 to resolve
  some reported issues. Included in here are:

   - typec driver bugfixes

   - usb gadget driver reverts for commits that were reported to have
     problems

   - resource leak bugfix

   - gadget driver bugfixes

   - dwc3 driver bugfixes

   - usb atm driver bugfix for when syzbot got loose on it

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

* tag 'usb-6.10-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb:
  usb: dwc3: core: Workaround for CSR read timeout
  Revert "usb: gadget: u_ether: Replace netif_stop_queue with netif_device_detach"
  Revert "usb: gadget: u_ether: Re-attach netif device to mirror detachment"
  usb: gadget: aspeed_udc: fix device address configuration
  usb: dwc3: core: remove lock of otg mode during gadget suspend/resume to avoid deadlock
  usb: typec: ucsi: glink: fix child node release in probe function
  usb: musb: da8xx: fix a resource leak in probe()
  usb: typec: ucsi_acpi: Add LG Gram quirk
  usb: ucsi: stm32: fix command completion handling
  usb: atm: cxacru: fix endpoint checking in cxacru_bind()
  usb: gadget: printer: fix races against disable
  usb: gadget: printer: SS+ support
This commit is contained in:
Linus Torvalds 2024-06-30 08:54:24 -07:00
commit 2c01c3d552
9 changed files with 152 additions and 29 deletions

View File

@ -1131,6 +1131,7 @@ static int cxacru_bind(struct usbatm_data *usbatm_instance,
struct cxacru_data *instance;
struct usb_device *usb_dev = interface_to_usbdev(intf);
struct usb_host_endpoint *cmd_ep = usb_dev->ep_in[CXACRU_EP_CMD];
struct usb_endpoint_descriptor *in, *out;
int ret;
/* instance init */
@ -1177,6 +1178,19 @@ static int cxacru_bind(struct usbatm_data *usbatm_instance,
goto fail;
}
if (usb_endpoint_xfer_int(&cmd_ep->desc))
ret = usb_find_common_endpoints(intf->cur_altsetting,
NULL, NULL, &in, &out);
else
ret = usb_find_common_endpoints(intf->cur_altsetting,
&in, &out, NULL, NULL);
if (ret) {
usb_err(usbatm_instance, "cxacru_bind: interface has incorrect endpoints\n");
ret = -ENODEV;
goto fail;
}
if ((cmd_ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
== USB_ENDPOINT_XFER_INT) {
usb_fill_int_urb(instance->rcv_urb,

View File

@ -957,12 +957,16 @@ static bool dwc3_core_is_valid(struct dwc3 *dwc)
static void dwc3_core_setup_global_control(struct dwc3 *dwc)
{
unsigned int power_opt;
unsigned int hw_mode;
u32 reg;
reg = dwc3_readl(dwc->regs, DWC3_GCTL);
reg &= ~DWC3_GCTL_SCALEDOWN_MASK;
hw_mode = DWC3_GHWPARAMS0_MODE(dwc->hwparams.hwparams0);
power_opt = DWC3_GHWPARAMS1_EN_PWROPT(dwc->hwparams.hwparams1);
switch (DWC3_GHWPARAMS1_EN_PWROPT(dwc->hwparams.hwparams1)) {
switch (power_opt) {
case DWC3_GHWPARAMS1_EN_PWROPT_CLK:
/**
* WORKAROUND: DWC3 revisions between 2.10a and 2.50a have an
@ -995,6 +999,20 @@ static void dwc3_core_setup_global_control(struct dwc3 *dwc)
break;
}
/*
* This is a workaround for STAR#4846132, which only affects
* DWC_usb31 version2.00a operating in host mode.
*
* There is a problem in DWC_usb31 version 2.00a operating
* in host mode that would cause a CSR read timeout When CSR
* read coincides with RAM Clock Gating Entry. By disable
* Clock Gating, sacrificing power consumption for normal
* operation.
*/
if (power_opt != DWC3_GHWPARAMS1_EN_PWROPT_NO &&
hw_mode != DWC3_GHWPARAMS0_MODE_GADGET && DWC3_VER_IS(DWC31, 200A))
reg |= DWC3_GCTL_DSBLCLKGTNG;
/* check if current dwc3 is on simulation board */
if (dwc->hwparams.hwparams6 & DWC3_GHWPARAMS6_EN_FPGA) {
dev_info(dwc->dev, "Running with FPGA optimizations\n");
@ -2250,7 +2268,6 @@ assert_reset:
static int dwc3_suspend_common(struct dwc3 *dwc, pm_message_t msg)
{
unsigned long flags;
u32 reg;
int i;
@ -2293,9 +2310,7 @@ static int dwc3_suspend_common(struct dwc3 *dwc, pm_message_t msg)
break;
if (dwc->current_otg_role == DWC3_OTG_ROLE_DEVICE) {
spin_lock_irqsave(&dwc->lock, flags);
dwc3_gadget_suspend(dwc);
spin_unlock_irqrestore(&dwc->lock, flags);
synchronize_irq(dwc->irq_gadget);
}
@ -2312,7 +2327,6 @@ static int dwc3_suspend_common(struct dwc3 *dwc, pm_message_t msg)
static int dwc3_resume_common(struct dwc3 *dwc, pm_message_t msg)
{
unsigned long flags;
int ret;
u32 reg;
int i;
@ -2366,9 +2380,7 @@ static int dwc3_resume_common(struct dwc3 *dwc, pm_message_t msg)
if (dwc->current_otg_role == DWC3_OTG_ROLE_HOST) {
dwc3_otg_host_init(dwc);
} else if (dwc->current_otg_role == DWC3_OTG_ROLE_DEVICE) {
spin_lock_irqsave(&dwc->lock, flags);
dwc3_gadget_resume(dwc);
spin_unlock_irqrestore(&dwc->lock, flags);
}
break;

View File

@ -213,6 +213,7 @@ static inline struct usb_endpoint_descriptor *ep_desc(struct usb_gadget *gadget,
struct usb_endpoint_descriptor *ss)
{
switch (gadget->speed) {
case USB_SPEED_SUPER_PLUS:
case USB_SPEED_SUPER:
return ss;
case USB_SPEED_HIGH:
@ -449,11 +450,8 @@ printer_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr)
mutex_lock(&dev->lock_printer_io);
spin_lock_irqsave(&dev->lock, flags);
if (dev->interface < 0) {
spin_unlock_irqrestore(&dev->lock, flags);
mutex_unlock(&dev->lock_printer_io);
return -ENODEV;
}
if (dev->interface < 0)
goto out_disabled;
/* We will use this flag later to check if a printer reset happened
* after we turn interrupts back on.
@ -461,6 +459,9 @@ printer_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr)
dev->reset_printer = 0;
setup_rx_reqs(dev);
/* this dropped the lock - need to retest */
if (dev->interface < 0)
goto out_disabled;
bytes_copied = 0;
current_rx_req = dev->current_rx_req;
@ -494,6 +495,8 @@ printer_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr)
wait_event_interruptible(dev->rx_wait,
(likely(!list_empty(&dev->rx_buffers))));
spin_lock_irqsave(&dev->lock, flags);
if (dev->interface < 0)
goto out_disabled;
}
/* We have data to return then copy it to the caller's buffer.*/
@ -537,6 +540,9 @@ printer_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr)
return -EAGAIN;
}
if (dev->interface < 0)
goto out_disabled;
/* If we not returning all the data left in this RX request
* buffer then adjust the amount of data left in the buffer.
* Othewise if we are done with this RX request buffer then
@ -566,6 +572,11 @@ printer_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr)
return bytes_copied;
else
return -EAGAIN;
out_disabled:
spin_unlock_irqrestore(&dev->lock, flags);
mutex_unlock(&dev->lock_printer_io);
return -ENODEV;
}
static ssize_t
@ -586,11 +597,8 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
mutex_lock(&dev->lock_printer_io);
spin_lock_irqsave(&dev->lock, flags);
if (dev->interface < 0) {
spin_unlock_irqrestore(&dev->lock, flags);
mutex_unlock(&dev->lock_printer_io);
return -ENODEV;
}
if (dev->interface < 0)
goto out_disabled;
/* Check if a printer reset happens while we have interrupts on */
dev->reset_printer = 0;
@ -613,6 +621,8 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
wait_event_interruptible(dev->tx_wait,
(likely(!list_empty(&dev->tx_reqs))));
spin_lock_irqsave(&dev->lock, flags);
if (dev->interface < 0)
goto out_disabled;
}
while (likely(!list_empty(&dev->tx_reqs)) && len) {
@ -662,6 +672,9 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
return -EAGAIN;
}
if (dev->interface < 0)
goto out_disabled;
list_add(&req->list, &dev->tx_reqs_active);
/* here, we unlock, and only unlock, to avoid deadlock. */
@ -674,6 +687,8 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
mutex_unlock(&dev->lock_printer_io);
return -EAGAIN;
}
if (dev->interface < 0)
goto out_disabled;
}
spin_unlock_irqrestore(&dev->lock, flags);
@ -685,6 +700,11 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
return bytes_copied;
else
return -EAGAIN;
out_disabled:
spin_unlock_irqrestore(&dev->lock, flags);
mutex_unlock(&dev->lock_printer_io);
return -ENODEV;
}
static int

View File

@ -1163,8 +1163,6 @@ struct net_device *gether_connect(struct gether *link)
if (netif_running(dev->net))
eth_start(dev, GFP_ATOMIC);
netif_device_attach(dev->net);
/* on error, disable any endpoints */
} else {
(void) usb_ep_disable(link->out_ep);
@ -1202,7 +1200,7 @@ void gether_disconnect(struct gether *link)
DBG(dev, "%s\n", __func__);
netif_device_detach(dev->net);
netif_stop_queue(dev->net);
netif_carrier_off(dev->net);
/* disable endpoints, forcing (synchronous) completion

View File

@ -66,8 +66,8 @@
#define USB_UPSTREAM_EN BIT(0)
/* Main config reg */
#define UDC_CFG_SET_ADDR(x) ((x) & 0x3f)
#define UDC_CFG_ADDR_MASK (0x3f)
#define UDC_CFG_SET_ADDR(x) ((x) & UDC_CFG_ADDR_MASK)
#define UDC_CFG_ADDR_MASK GENMASK(6, 0)
/* Interrupt ctrl & status reg */
#define UDC_IRQ_EP_POOL_NAK BIT(17)

View File

@ -556,7 +556,7 @@ static int da8xx_probe(struct platform_device *pdev)
ret = of_platform_populate(pdev->dev.of_node, NULL,
da8xx_auxdata_lookup, &pdev->dev);
if (ret)
return ret;
goto err_unregister_phy;
pinfo = da8xx_dev_info;
pinfo.parent = &pdev->dev;
@ -571,9 +571,13 @@ static int da8xx_probe(struct platform_device *pdev)
ret = PTR_ERR_OR_ZERO(glue->musb);
if (ret) {
dev_err(&pdev->dev, "failed to register musb device: %d\n", ret);
usb_phy_generic_unregister(glue->usb_phy);
goto err_unregister_phy;
}
return 0;
err_unregister_phy:
usb_phy_generic_unregister(glue->usb_phy);
return ret;
}

View File

@ -25,6 +25,7 @@ struct ucsi_acpi {
unsigned long flags;
#define UCSI_ACPI_COMMAND_PENDING 1
#define UCSI_ACPI_ACK_PENDING 2
#define UCSI_ACPI_CHECK_BOGUS_EVENT 3
guid_t guid;
u64 cmd;
};
@ -128,6 +129,58 @@ static const struct ucsi_operations ucsi_zenbook_ops = {
.async_write = ucsi_acpi_async_write
};
static int ucsi_gram_read(struct ucsi *ucsi, unsigned int offset,
void *val, size_t val_len)
{
u16 bogus_change = UCSI_CONSTAT_POWER_LEVEL_CHANGE |
UCSI_CONSTAT_PDOS_CHANGE;
struct ucsi_acpi *ua = ucsi_get_drvdata(ucsi);
struct ucsi_connector_status *status;
int ret;
ret = ucsi_acpi_read(ucsi, offset, val, val_len);
if (ret < 0)
return ret;
if (UCSI_COMMAND(ua->cmd) == UCSI_GET_CONNECTOR_STATUS &&
test_bit(UCSI_ACPI_CHECK_BOGUS_EVENT, &ua->flags) &&
offset == UCSI_MESSAGE_IN) {
status = (struct ucsi_connector_status *)val;
/* Clear the bogus change */
if (status->change == bogus_change)
status->change = 0;
clear_bit(UCSI_ACPI_CHECK_BOGUS_EVENT, &ua->flags);
}
return ret;
}
static int ucsi_gram_sync_write(struct ucsi *ucsi, unsigned int offset,
const void *val, size_t val_len)
{
struct ucsi_acpi *ua = ucsi_get_drvdata(ucsi);
int ret;
ret = ucsi_acpi_sync_write(ucsi, offset, val, val_len);
if (ret < 0)
return ret;
if (UCSI_COMMAND(ua->cmd) == UCSI_GET_PDOS &&
ua->cmd & UCSI_GET_PDOS_PARTNER_PDO(1) &&
ua->cmd & UCSI_GET_PDOS_SRC_PDOS)
set_bit(UCSI_ACPI_CHECK_BOGUS_EVENT, &ua->flags);
return ret;
}
static const struct ucsi_operations ucsi_gram_ops = {
.read = ucsi_gram_read,
.sync_write = ucsi_gram_sync_write,
.async_write = ucsi_acpi_async_write
};
static const struct dmi_system_id ucsi_acpi_quirks[] = {
{
.matches = {
@ -136,6 +189,14 @@ static const struct dmi_system_id ucsi_acpi_quirks[] = {
},
.driver_data = (void *)&ucsi_zenbook_ops,
},
{
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "LG Electronics"),
DMI_MATCH(DMI_PRODUCT_FAMILY, "LG gram PC"),
DMI_MATCH(DMI_PRODUCT_NAME, "90Q"),
},
.driver_data = (void *)&ucsi_gram_ops,
},
{ }
};

View File

@ -372,6 +372,7 @@ static int pmic_glink_ucsi_probe(struct auxiliary_device *adev,
ret = fwnode_property_read_u32(fwnode, "reg", &port);
if (ret < 0) {
dev_err(dev, "missing reg property of %pOFn\n", fwnode);
fwnode_handle_put(fwnode);
return ret;
}
@ -386,9 +387,11 @@ static int pmic_glink_ucsi_probe(struct auxiliary_device *adev,
if (!desc)
continue;
if (IS_ERR(desc))
if (IS_ERR(desc)) {
fwnode_handle_put(fwnode);
return dev_err_probe(dev, PTR_ERR(desc),
"unable to acquire orientation gpio\n");
}
ucsi->port_orientation[port] = desc;
}

View File

@ -65,6 +65,7 @@ struct ucsi_stm32g0 {
struct device *dev;
unsigned long flags;
#define COMMAND_PENDING 1
#define ACK_PENDING 2
const char *fw_name;
struct ucsi *ucsi;
bool suspended;
@ -396,9 +397,13 @@ static int ucsi_stm32g0_sync_write(struct ucsi *ucsi, unsigned int offset, const
size_t len)
{
struct ucsi_stm32g0 *g0 = ucsi_get_drvdata(ucsi);
bool ack = UCSI_COMMAND(*(u64 *)val) == UCSI_ACK_CC_CI;
int ret;
set_bit(COMMAND_PENDING, &g0->flags);
if (ack)
set_bit(ACK_PENDING, &g0->flags);
else
set_bit(COMMAND_PENDING, &g0->flags);
ret = ucsi_stm32g0_async_write(ucsi, offset, val, len);
if (ret)
@ -406,9 +411,14 @@ static int ucsi_stm32g0_sync_write(struct ucsi *ucsi, unsigned int offset, const
if (!wait_for_completion_timeout(&g0->complete, msecs_to_jiffies(5000)))
ret = -ETIMEDOUT;
else
return 0;
out_clear_bit:
clear_bit(COMMAND_PENDING, &g0->flags);
if (ack)
clear_bit(ACK_PENDING, &g0->flags);
else
clear_bit(COMMAND_PENDING, &g0->flags);
return ret;
}
@ -429,8 +439,9 @@ static irqreturn_t ucsi_stm32g0_irq_handler(int irq, void *data)
if (UCSI_CCI_CONNECTOR(cci))
ucsi_connector_change(g0->ucsi, UCSI_CCI_CONNECTOR(cci));
if (test_bit(COMMAND_PENDING, &g0->flags) &&
cci & (UCSI_CCI_ACK_COMPLETE | UCSI_CCI_COMMAND_COMPLETE))
if (cci & UCSI_CCI_ACK_COMPLETE && test_and_clear_bit(ACK_PENDING, &g0->flags))
complete(&g0->complete);
if (cci & UCSI_CCI_COMMAND_COMPLETE && test_and_clear_bit(COMMAND_PENDING, &g0->flags))
complete(&g0->complete);
return IRQ_HANDLED;