Commit 2c01c3d5 authored by Linus Torvalds's avatar Linus Torvalds

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
parents 3ffea9a7 fc1d1a71
...@@ -1131,6 +1131,7 @@ static int cxacru_bind(struct usbatm_data *usbatm_instance, ...@@ -1131,6 +1131,7 @@ static int cxacru_bind(struct usbatm_data *usbatm_instance,
struct cxacru_data *instance; struct cxacru_data *instance;
struct usb_device *usb_dev = interface_to_usbdev(intf); struct usb_device *usb_dev = interface_to_usbdev(intf);
struct usb_host_endpoint *cmd_ep = usb_dev->ep_in[CXACRU_EP_CMD]; struct usb_host_endpoint *cmd_ep = usb_dev->ep_in[CXACRU_EP_CMD];
struct usb_endpoint_descriptor *in, *out;
int ret; int ret;
/* instance init */ /* instance init */
...@@ -1177,6 +1178,19 @@ static int cxacru_bind(struct usbatm_data *usbatm_instance, ...@@ -1177,6 +1178,19 @@ static int cxacru_bind(struct usbatm_data *usbatm_instance,
goto fail; 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) if ((cmd_ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
== USB_ENDPOINT_XFER_INT) { == USB_ENDPOINT_XFER_INT) {
usb_fill_int_urb(instance->rcv_urb, usb_fill_int_urb(instance->rcv_urb,
......
...@@ -957,12 +957,16 @@ static bool dwc3_core_is_valid(struct dwc3 *dwc) ...@@ -957,12 +957,16 @@ static bool dwc3_core_is_valid(struct dwc3 *dwc)
static void dwc3_core_setup_global_control(struct dwc3 *dwc) static void dwc3_core_setup_global_control(struct dwc3 *dwc)
{ {
unsigned int power_opt;
unsigned int hw_mode;
u32 reg; u32 reg;
reg = dwc3_readl(dwc->regs, DWC3_GCTL); reg = dwc3_readl(dwc->regs, DWC3_GCTL);
reg &= ~DWC3_GCTL_SCALEDOWN_MASK; 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: case DWC3_GHWPARAMS1_EN_PWROPT_CLK:
/** /**
* WORKAROUND: DWC3 revisions between 2.10a and 2.50a have an * 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) ...@@ -995,6 +999,20 @@ static void dwc3_core_setup_global_control(struct dwc3 *dwc)
break; 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 */ /* check if current dwc3 is on simulation board */
if (dwc->hwparams.hwparams6 & DWC3_GHWPARAMS6_EN_FPGA) { if (dwc->hwparams.hwparams6 & DWC3_GHWPARAMS6_EN_FPGA) {
dev_info(dwc->dev, "Running with FPGA optimizations\n"); dev_info(dwc->dev, "Running with FPGA optimizations\n");
...@@ -2250,7 +2268,6 @@ static int dwc3_core_init_for_resume(struct dwc3 *dwc) ...@@ -2250,7 +2268,6 @@ static int dwc3_core_init_for_resume(struct dwc3 *dwc)
static int dwc3_suspend_common(struct dwc3 *dwc, pm_message_t msg) static int dwc3_suspend_common(struct dwc3 *dwc, pm_message_t msg)
{ {
unsigned long flags;
u32 reg; u32 reg;
int i; int i;
...@@ -2293,9 +2310,7 @@ static int dwc3_suspend_common(struct dwc3 *dwc, pm_message_t msg) ...@@ -2293,9 +2310,7 @@ static int dwc3_suspend_common(struct dwc3 *dwc, pm_message_t msg)
break; break;
if (dwc->current_otg_role == DWC3_OTG_ROLE_DEVICE) { if (dwc->current_otg_role == DWC3_OTG_ROLE_DEVICE) {
spin_lock_irqsave(&dwc->lock, flags);
dwc3_gadget_suspend(dwc); dwc3_gadget_suspend(dwc);
spin_unlock_irqrestore(&dwc->lock, flags);
synchronize_irq(dwc->irq_gadget); synchronize_irq(dwc->irq_gadget);
} }
...@@ -2312,7 +2327,6 @@ static int dwc3_suspend_common(struct dwc3 *dwc, pm_message_t msg) ...@@ -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) static int dwc3_resume_common(struct dwc3 *dwc, pm_message_t msg)
{ {
unsigned long flags;
int ret; int ret;
u32 reg; u32 reg;
int i; int i;
...@@ -2366,9 +2380,7 @@ static int dwc3_resume_common(struct dwc3 *dwc, pm_message_t msg) ...@@ -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) { if (dwc->current_otg_role == DWC3_OTG_ROLE_HOST) {
dwc3_otg_host_init(dwc); dwc3_otg_host_init(dwc);
} else if (dwc->current_otg_role == DWC3_OTG_ROLE_DEVICE) { } else if (dwc->current_otg_role == DWC3_OTG_ROLE_DEVICE) {
spin_lock_irqsave(&dwc->lock, flags);
dwc3_gadget_resume(dwc); dwc3_gadget_resume(dwc);
spin_unlock_irqrestore(&dwc->lock, flags);
} }
break; break;
......
...@@ -213,6 +213,7 @@ static inline struct usb_endpoint_descriptor *ep_desc(struct usb_gadget *gadget, ...@@ -213,6 +213,7 @@ static inline struct usb_endpoint_descriptor *ep_desc(struct usb_gadget *gadget,
struct usb_endpoint_descriptor *ss) struct usb_endpoint_descriptor *ss)
{ {
switch (gadget->speed) { switch (gadget->speed) {
case USB_SPEED_SUPER_PLUS:
case USB_SPEED_SUPER: case USB_SPEED_SUPER:
return ss; return ss;
case USB_SPEED_HIGH: case USB_SPEED_HIGH:
...@@ -449,11 +450,8 @@ printer_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr) ...@@ -449,11 +450,8 @@ printer_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr)
mutex_lock(&dev->lock_printer_io); mutex_lock(&dev->lock_printer_io);
spin_lock_irqsave(&dev->lock, flags); spin_lock_irqsave(&dev->lock, flags);
if (dev->interface < 0) { if (dev->interface < 0)
spin_unlock_irqrestore(&dev->lock, flags); goto out_disabled;
mutex_unlock(&dev->lock_printer_io);
return -ENODEV;
}
/* We will use this flag later to check if a printer reset happened /* We will use this flag later to check if a printer reset happened
* after we turn interrupts back on. * after we turn interrupts back on.
...@@ -461,6 +459,9 @@ printer_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr) ...@@ -461,6 +459,9 @@ printer_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr)
dev->reset_printer = 0; dev->reset_printer = 0;
setup_rx_reqs(dev); setup_rx_reqs(dev);
/* this dropped the lock - need to retest */
if (dev->interface < 0)
goto out_disabled;
bytes_copied = 0; bytes_copied = 0;
current_rx_req = dev->current_rx_req; 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) ...@@ -494,6 +495,8 @@ printer_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr)
wait_event_interruptible(dev->rx_wait, wait_event_interruptible(dev->rx_wait,
(likely(!list_empty(&dev->rx_buffers)))); (likely(!list_empty(&dev->rx_buffers))));
spin_lock_irqsave(&dev->lock, flags); 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.*/ /* 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) ...@@ -537,6 +540,9 @@ printer_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr)
return -EAGAIN; return -EAGAIN;
} }
if (dev->interface < 0)
goto out_disabled;
/* If we not returning all the data left in this RX request /* If we not returning all the data left in this RX request
* buffer then adjust the amount of data left in the buffer. * buffer then adjust the amount of data left in the buffer.
* Othewise if we are done with this RX request buffer then * 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) ...@@ -566,6 +572,11 @@ printer_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr)
return bytes_copied; return bytes_copied;
else else
return -EAGAIN; return -EAGAIN;
out_disabled:
spin_unlock_irqrestore(&dev->lock, flags);
mutex_unlock(&dev->lock_printer_io);
return -ENODEV;
} }
static ssize_t static ssize_t
...@@ -586,11 +597,8 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr) ...@@ -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); mutex_lock(&dev->lock_printer_io);
spin_lock_irqsave(&dev->lock, flags); spin_lock_irqsave(&dev->lock, flags);
if (dev->interface < 0) { if (dev->interface < 0)
spin_unlock_irqrestore(&dev->lock, flags); goto out_disabled;
mutex_unlock(&dev->lock_printer_io);
return -ENODEV;
}
/* Check if a printer reset happens while we have interrupts on */ /* Check if a printer reset happens while we have interrupts on */
dev->reset_printer = 0; dev->reset_printer = 0;
...@@ -613,6 +621,8 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr) ...@@ -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, wait_event_interruptible(dev->tx_wait,
(likely(!list_empty(&dev->tx_reqs)))); (likely(!list_empty(&dev->tx_reqs))));
spin_lock_irqsave(&dev->lock, flags); spin_lock_irqsave(&dev->lock, flags);
if (dev->interface < 0)
goto out_disabled;
} }
while (likely(!list_empty(&dev->tx_reqs)) && len) { 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) ...@@ -662,6 +672,9 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
return -EAGAIN; return -EAGAIN;
} }
if (dev->interface < 0)
goto out_disabled;
list_add(&req->list, &dev->tx_reqs_active); list_add(&req->list, &dev->tx_reqs_active);
/* here, we unlock, and only unlock, to avoid deadlock. */ /* 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) ...@@ -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); mutex_unlock(&dev->lock_printer_io);
return -EAGAIN; return -EAGAIN;
} }
if (dev->interface < 0)
goto out_disabled;
} }
spin_unlock_irqrestore(&dev->lock, flags); 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) ...@@ -685,6 +700,11 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
return bytes_copied; return bytes_copied;
else else
return -EAGAIN; return -EAGAIN;
out_disabled:
spin_unlock_irqrestore(&dev->lock, flags);
mutex_unlock(&dev->lock_printer_io);
return -ENODEV;
} }
static int static int
......
...@@ -1163,8 +1163,6 @@ struct net_device *gether_connect(struct gether *link) ...@@ -1163,8 +1163,6 @@ struct net_device *gether_connect(struct gether *link)
if (netif_running(dev->net)) if (netif_running(dev->net))
eth_start(dev, GFP_ATOMIC); eth_start(dev, GFP_ATOMIC);
netif_device_attach(dev->net);
/* on error, disable any endpoints */ /* on error, disable any endpoints */
} else { } else {
(void) usb_ep_disable(link->out_ep); (void) usb_ep_disable(link->out_ep);
...@@ -1202,7 +1200,7 @@ void gether_disconnect(struct gether *link) ...@@ -1202,7 +1200,7 @@ void gether_disconnect(struct gether *link)
DBG(dev, "%s\n", __func__); DBG(dev, "%s\n", __func__);
netif_device_detach(dev->net); netif_stop_queue(dev->net);
netif_carrier_off(dev->net); netif_carrier_off(dev->net);
/* disable endpoints, forcing (synchronous) completion /* disable endpoints, forcing (synchronous) completion
......
...@@ -66,8 +66,8 @@ ...@@ -66,8 +66,8 @@
#define USB_UPSTREAM_EN BIT(0) #define USB_UPSTREAM_EN BIT(0)
/* Main config reg */ /* Main config reg */
#define UDC_CFG_SET_ADDR(x) ((x) & 0x3f) #define UDC_CFG_SET_ADDR(x) ((x) & UDC_CFG_ADDR_MASK)
#define UDC_CFG_ADDR_MASK (0x3f) #define UDC_CFG_ADDR_MASK GENMASK(6, 0)
/* Interrupt ctrl & status reg */ /* Interrupt ctrl & status reg */
#define UDC_IRQ_EP_POOL_NAK BIT(17) #define UDC_IRQ_EP_POOL_NAK BIT(17)
......
...@@ -556,7 +556,7 @@ static int da8xx_probe(struct platform_device *pdev) ...@@ -556,7 +556,7 @@ static int da8xx_probe(struct platform_device *pdev)
ret = of_platform_populate(pdev->dev.of_node, NULL, ret = of_platform_populate(pdev->dev.of_node, NULL,
da8xx_auxdata_lookup, &pdev->dev); da8xx_auxdata_lookup, &pdev->dev);
if (ret) if (ret)
return ret; goto err_unregister_phy;
pinfo = da8xx_dev_info; pinfo = da8xx_dev_info;
pinfo.parent = &pdev->dev; pinfo.parent = &pdev->dev;
...@@ -571,9 +571,13 @@ static int da8xx_probe(struct platform_device *pdev) ...@@ -571,9 +571,13 @@ static int da8xx_probe(struct platform_device *pdev)
ret = PTR_ERR_OR_ZERO(glue->musb); ret = PTR_ERR_OR_ZERO(glue->musb);
if (ret) { if (ret) {
dev_err(&pdev->dev, "failed to register musb device: %d\n", 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; return ret;
} }
......
...@@ -25,6 +25,7 @@ struct ucsi_acpi { ...@@ -25,6 +25,7 @@ struct ucsi_acpi {
unsigned long flags; unsigned long flags;
#define UCSI_ACPI_COMMAND_PENDING 1 #define UCSI_ACPI_COMMAND_PENDING 1
#define UCSI_ACPI_ACK_PENDING 2 #define UCSI_ACPI_ACK_PENDING 2
#define UCSI_ACPI_CHECK_BOGUS_EVENT 3
guid_t guid; guid_t guid;
u64 cmd; u64 cmd;
}; };
...@@ -128,6 +129,58 @@ static const struct ucsi_operations ucsi_zenbook_ops = { ...@@ -128,6 +129,58 @@ static const struct ucsi_operations ucsi_zenbook_ops = {
.async_write = ucsi_acpi_async_write .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[] = { static const struct dmi_system_id ucsi_acpi_quirks[] = {
{ {
.matches = { .matches = {
...@@ -136,6 +189,14 @@ static const struct dmi_system_id ucsi_acpi_quirks[] = { ...@@ -136,6 +189,14 @@ static const struct dmi_system_id ucsi_acpi_quirks[] = {
}, },
.driver_data = (void *)&ucsi_zenbook_ops, .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,
},
{ } { }
}; };
......
...@@ -372,6 +372,7 @@ static int pmic_glink_ucsi_probe(struct auxiliary_device *adev, ...@@ -372,6 +372,7 @@ static int pmic_glink_ucsi_probe(struct auxiliary_device *adev,
ret = fwnode_property_read_u32(fwnode, "reg", &port); ret = fwnode_property_read_u32(fwnode, "reg", &port);
if (ret < 0) { if (ret < 0) {
dev_err(dev, "missing reg property of %pOFn\n", fwnode); dev_err(dev, "missing reg property of %pOFn\n", fwnode);
fwnode_handle_put(fwnode);
return ret; return ret;
} }
...@@ -386,9 +387,11 @@ static int pmic_glink_ucsi_probe(struct auxiliary_device *adev, ...@@ -386,9 +387,11 @@ static int pmic_glink_ucsi_probe(struct auxiliary_device *adev,
if (!desc) if (!desc)
continue; continue;
if (IS_ERR(desc)) if (IS_ERR(desc)) {
fwnode_handle_put(fwnode);
return dev_err_probe(dev, PTR_ERR(desc), return dev_err_probe(dev, PTR_ERR(desc),
"unable to acquire orientation gpio\n"); "unable to acquire orientation gpio\n");
}
ucsi->port_orientation[port] = desc; ucsi->port_orientation[port] = desc;
} }
......
...@@ -65,6 +65,7 @@ struct ucsi_stm32g0 { ...@@ -65,6 +65,7 @@ struct ucsi_stm32g0 {
struct device *dev; struct device *dev;
unsigned long flags; unsigned long flags;
#define COMMAND_PENDING 1 #define COMMAND_PENDING 1
#define ACK_PENDING 2
const char *fw_name; const char *fw_name;
struct ucsi *ucsi; struct ucsi *ucsi;
bool suspended; bool suspended;
...@@ -396,9 +397,13 @@ static int ucsi_stm32g0_sync_write(struct ucsi *ucsi, unsigned int offset, const ...@@ -396,9 +397,13 @@ static int ucsi_stm32g0_sync_write(struct ucsi *ucsi, unsigned int offset, const
size_t len) size_t len)
{ {
struct ucsi_stm32g0 *g0 = ucsi_get_drvdata(ucsi); struct ucsi_stm32g0 *g0 = ucsi_get_drvdata(ucsi);
bool ack = UCSI_COMMAND(*(u64 *)val) == UCSI_ACK_CC_CI;
int ret; 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); ret = ucsi_stm32g0_async_write(ucsi, offset, val, len);
if (ret) if (ret)
...@@ -406,9 +411,14 @@ static int ucsi_stm32g0_sync_write(struct ucsi *ucsi, unsigned int offset, const ...@@ -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))) if (!wait_for_completion_timeout(&g0->complete, msecs_to_jiffies(5000)))
ret = -ETIMEDOUT; ret = -ETIMEDOUT;
else
return 0;
out_clear_bit: 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; return ret;
} }
...@@ -429,8 +439,9 @@ static irqreturn_t ucsi_stm32g0_irq_handler(int irq, void *data) ...@@ -429,8 +439,9 @@ static irqreturn_t ucsi_stm32g0_irq_handler(int irq, void *data)
if (UCSI_CCI_CONNECTOR(cci)) if (UCSI_CCI_CONNECTOR(cci))
ucsi_connector_change(g0->ucsi, UCSI_CCI_CONNECTOR(cci)); ucsi_connector_change(g0->ucsi, UCSI_CCI_CONNECTOR(cci));
if (test_bit(COMMAND_PENDING, &g0->flags) && if (cci & UCSI_CCI_ACK_COMPLETE && test_and_clear_bit(ACK_PENDING, &g0->flags))
cci & (UCSI_CCI_ACK_COMPLETE | UCSI_CCI_COMMAND_COMPLETE)) complete(&g0->complete);
if (cci & UCSI_CCI_COMMAND_COMPLETE && test_and_clear_bit(COMMAND_PENDING, &g0->flags))
complete(&g0->complete); complete(&g0->complete);
return IRQ_HANDLED; return IRQ_HANDLED;
......
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