USB driver fixes for 6.13-rc3

Here are some small USB driver fixes for some reported issues.  Included
 in here are:
   - typec driver bugfixes
   - u_serial gadget driver bugfix for much reported and discussed issue
   - dwc2 bugfixes
   - midi gadget driver bugfix
   - ehci-hcd driver bugfix
   - other small bugfixes
 
 All of these have been in linux-next for over a week with no reported
 issues.
 
 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 -----BEGIN PGP SIGNATURE-----
 
 iG0EABECAC0WIQT0tgzFv3jCIUoxPcsxR9QN2y37KQUCZ12Wwg8cZ3JlZ0Brcm9h
 aC5jb20ACgkQMUfUDdst+ymbWgCeKUCeGFlUanDHY1nHq72FSMiHpcUAoIvzBTx1
 yUEhvtuYYZ/NBzfKI+8h
 =WeQD
 -----END PGP SIGNATURE-----

Merge tag 'usb-6.13-rc3' 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 some reported issues.
  Included in here are:

   - typec driver bugfixes

   - u_serial gadget driver bugfix for much reported and discussed issue

   - dwc2 bugfixes

   - midi gadget driver bugfix

   - ehci-hcd driver bugfix

   - other small bugfixes

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

* tag 'usb-6.13-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb:
  usb: typec: ucsi: Fix connector status writing past buffer size
  usb: typec: ucsi: Fix completion notifications
  usb: dwc2: Fix HCD port connection race
  usb: dwc2: hcd: Fix GetPortStatus & SetPortFeature
  usb: dwc2: Fix HCD resume
  usb: gadget: u_serial: Fix the issue that gs_start_io crashed due to accessing null pointer
  usb: misc: onboard_usb_dev: skip suspend/resume sequence for USB5744 SMBus support
  usb: dwc3: xilinx: make sure pipe clock is deselected in usb2 only mode
  usb: core: hcd: only check primary hcd skip_phy_initialization
  usb: gadget: midi2: Fix interpretation of is_midi1 bits
  usb: dwc3: imx8mp: fix software node kernel dump
  usb: typec: anx7411: fix OF node reference leaks in anx7411_typec_switch_probe()
  usb: typec: anx7411: fix fwnode_handle reference leak
  usb: host: max3421-hcd: Correctly abort a USB request.
  dt-bindings: phy: imx8mq-usb: correct reference to usb-switch.yaml
  usb: ehci-hcd: fix call balance of clocks handling routines
This commit is contained in:
Linus Torvalds 2024-12-14 09:35:22 -08:00
commit a0e3919a2d
12 changed files with 116 additions and 72 deletions

View File

@ -113,11 +113,8 @@ allOf:
maxItems: 1 maxItems: 1
- if: - if:
properties: required:
compatible: - orientation-switch
contains:
enum:
- fsl,imx95-usb-phy
then: then:
$ref: /schemas/usb/usb-switch.yaml# $ref: /schemas/usb/usb-switch.yaml#

View File

@ -2794,8 +2794,14 @@ int usb_add_hcd(struct usb_hcd *hcd,
int retval; int retval;
struct usb_device *rhdev; struct usb_device *rhdev;
struct usb_hcd *shared_hcd; struct usb_hcd *shared_hcd;
int skip_phy_initialization;
if (!hcd->skip_phy_initialization) { if (usb_hcd_is_primary_hcd(hcd))
skip_phy_initialization = hcd->skip_phy_initialization;
else
skip_phy_initialization = hcd->primary_hcd->skip_phy_initialization;
if (!skip_phy_initialization) {
if (usb_hcd_is_primary_hcd(hcd)) { if (usb_hcd_is_primary_hcd(hcd)) {
hcd->phy_roothub = usb_phy_roothub_alloc(hcd->self.sysdev); hcd->phy_roothub = usb_phy_roothub_alloc(hcd->self.sysdev);
if (IS_ERR(hcd->phy_roothub)) if (IS_ERR(hcd->phy_roothub))

View File

@ -3546,11 +3546,9 @@ static int dwc2_hcd_hub_control(struct dwc2_hsotg *hsotg, u16 typereq,
port_status |= USB_PORT_STAT_C_OVERCURRENT << 16; port_status |= USB_PORT_STAT_C_OVERCURRENT << 16;
} }
if (!hsotg->flags.b.port_connect_status) { if (dwc2_is_device_mode(hsotg)) {
/* /*
* The port is disconnected, which means the core is * Just return 0's for the remainder of the port status
* either in device mode or it soon will be. Just
* return 0's for the remainder of the port status
* since the port register can't be read if the core * since the port register can't be read if the core
* is in device mode. * is in device mode.
*/ */
@ -3620,13 +3618,11 @@ static int dwc2_hcd_hub_control(struct dwc2_hsotg *hsotg, u16 typereq,
if (wvalue != USB_PORT_FEAT_TEST && (!windex || windex > 1)) if (wvalue != USB_PORT_FEAT_TEST && (!windex || windex > 1))
goto error; goto error;
if (!hsotg->flags.b.port_connect_status) { if (dwc2_is_device_mode(hsotg)) {
/* /*
* The port is disconnected, which means the core is * Just return 0's for the remainder of the port status
* either in device mode or it soon will be. Just * since the port register can't be read if the core
* return without doing anything since the port * is in device mode.
* register can't be written if the core is in device
* mode.
*/ */
break; break;
} }
@ -4349,7 +4345,7 @@ static int _dwc2_hcd_suspend(struct usb_hcd *hcd)
if (hsotg->bus_suspended) if (hsotg->bus_suspended)
goto skip_power_saving; goto skip_power_saving;
if (hsotg->flags.b.port_connect_status == 0) if (!(dwc2_read_hprt0(hsotg) & HPRT0_CONNSTS))
goto skip_power_saving; goto skip_power_saving;
switch (hsotg->params.power_down) { switch (hsotg->params.power_down) {
@ -4431,6 +4427,7 @@ static int _dwc2_hcd_resume(struct usb_hcd *hcd)
* Power Down mode. * Power Down mode.
*/ */
if (hprt0 & HPRT0_CONNSTS) { if (hprt0 & HPRT0_CONNSTS) {
set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
hsotg->lx_state = DWC2_L0; hsotg->lx_state = DWC2_L0;
goto unlock; goto unlock;
} }

View File

@ -129,6 +129,16 @@ static void dwc3_imx8mp_wakeup_disable(struct dwc3_imx8mp *dwc3_imx)
writel(val, dwc3_imx->hsio_blk_base + USB_WAKEUP_CTRL); writel(val, dwc3_imx->hsio_blk_base + USB_WAKEUP_CTRL);
} }
static const struct property_entry dwc3_imx8mp_properties[] = {
PROPERTY_ENTRY_BOOL("xhci-missing-cas-quirk"),
PROPERTY_ENTRY_BOOL("xhci-skip-phy-init-quirk"),
{},
};
static const struct software_node dwc3_imx8mp_swnode = {
.properties = dwc3_imx8mp_properties,
};
static irqreturn_t dwc3_imx8mp_interrupt(int irq, void *_dwc3_imx) static irqreturn_t dwc3_imx8mp_interrupt(int irq, void *_dwc3_imx)
{ {
struct dwc3_imx8mp *dwc3_imx = _dwc3_imx; struct dwc3_imx8mp *dwc3_imx = _dwc3_imx;
@ -148,17 +158,6 @@ static irqreturn_t dwc3_imx8mp_interrupt(int irq, void *_dwc3_imx)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static int dwc3_imx8mp_set_software_node(struct device *dev)
{
struct property_entry props[3] = { 0 };
int prop_idx = 0;
props[prop_idx++] = PROPERTY_ENTRY_BOOL("xhci-missing-cas-quirk");
props[prop_idx++] = PROPERTY_ENTRY_BOOL("xhci-skip-phy-init-quirk");
return device_create_managed_software_node(dev, props, NULL);
}
static int dwc3_imx8mp_probe(struct platform_device *pdev) static int dwc3_imx8mp_probe(struct platform_device *pdev)
{ {
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
@ -221,17 +220,17 @@ static int dwc3_imx8mp_probe(struct platform_device *pdev)
if (err < 0) if (err < 0)
goto disable_rpm; goto disable_rpm;
err = dwc3_imx8mp_set_software_node(dev); err = device_add_software_node(dev, &dwc3_imx8mp_swnode);
if (err) { if (err) {
err = -ENODEV; err = -ENODEV;
dev_err(dev, "failed to create software node\n"); dev_err(dev, "failed to add software node\n");
goto disable_rpm; goto disable_rpm;
} }
err = of_platform_populate(node, NULL, NULL, dev); err = of_platform_populate(node, NULL, NULL, dev);
if (err) { if (err) {
dev_err(&pdev->dev, "failed to create dwc3 core\n"); dev_err(&pdev->dev, "failed to create dwc3 core\n");
goto disable_rpm; goto remove_swnode;
} }
dwc3_imx->dwc3 = of_find_device_by_node(dwc3_np); dwc3_imx->dwc3 = of_find_device_by_node(dwc3_np);
@ -255,6 +254,8 @@ static int dwc3_imx8mp_probe(struct platform_device *pdev)
depopulate: depopulate:
of_platform_depopulate(dev); of_platform_depopulate(dev);
remove_swnode:
device_remove_software_node(dev);
disable_rpm: disable_rpm:
pm_runtime_disable(dev); pm_runtime_disable(dev);
pm_runtime_put_noidle(dev); pm_runtime_put_noidle(dev);
@ -268,6 +269,7 @@ static void dwc3_imx8mp_remove(struct platform_device *pdev)
pm_runtime_get_sync(dev); pm_runtime_get_sync(dev);
of_platform_depopulate(dev); of_platform_depopulate(dev);
device_remove_software_node(dev);
pm_runtime_disable(dev); pm_runtime_disable(dev);
pm_runtime_put_noidle(dev); pm_runtime_put_noidle(dev);

View File

@ -121,8 +121,11 @@ static int dwc3_xlnx_init_zynqmp(struct dwc3_xlnx *priv_data)
* in use but the usb3-phy entry is missing from the device tree. * in use but the usb3-phy entry is missing from the device tree.
* Therefore, skip these operations in this case. * Therefore, skip these operations in this case.
*/ */
if (!priv_data->usb3_phy) if (!priv_data->usb3_phy) {
/* Deselect the PIPE Clock Select bit in FPD PIPE Clock register */
writel(PIPE_CLK_DESELECT, priv_data->regs + XLNX_USB_FPD_PIPE_CLK);
goto skip_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)) {

View File

@ -1591,7 +1591,11 @@ static int f_midi2_create_card(struct f_midi2 *midi2)
fb->info.midi_ci_version = b->midi_ci_version; fb->info.midi_ci_version = b->midi_ci_version;
fb->info.ui_hint = reverse_dir(b->ui_hint); fb->info.ui_hint = reverse_dir(b->ui_hint);
fb->info.sysex8_streams = b->sysex8_streams; fb->info.sysex8_streams = b->sysex8_streams;
if (b->is_midi1 < 2)
fb->info.flags |= b->is_midi1; fb->info.flags |= b->is_midi1;
else
fb->info.flags |= SNDRV_UMP_BLOCK_IS_MIDI1 |
SNDRV_UMP_BLOCK_IS_LOWSPEED;
strscpy(fb->info.name, ump_fb_name(b), strscpy(fb->info.name, ump_fb_name(b),
sizeof(fb->info.name)); sizeof(fb->info.name));
} }

View File

@ -579,9 +579,12 @@ static int gs_start_io(struct gs_port *port)
* we didn't in gs_start_tx() */ * we didn't in gs_start_tx() */
tty_wakeup(port->port.tty); tty_wakeup(port->port.tty);
} else { } else {
/* Free reqs only if we are still connected */
if (port->port_usb) {
gs_free_requests(ep, head, &port->read_allocated); gs_free_requests(ep, head, &port->read_allocated);
gs_free_requests(port->port_usb->in, &port->write_pool, gs_free_requests(port->port_usb->in, &port->write_pool,
&port->write_allocated); &port->write_allocated);
}
status = -EIO; status = -EIO;
} }

View File

@ -119,8 +119,12 @@ static int ehci_hcd_sh_probe(struct platform_device *pdev)
if (IS_ERR(priv->iclk)) if (IS_ERR(priv->iclk))
priv->iclk = NULL; priv->iclk = NULL;
clk_enable(priv->fclk); ret = clk_enable(priv->fclk);
clk_enable(priv->iclk); if (ret)
goto fail_request_resource;
ret = clk_enable(priv->iclk);
if (ret)
goto fail_iclk;
ret = usb_add_hcd(hcd, irq, IRQF_SHARED); ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
if (ret != 0) { if (ret != 0) {
@ -136,6 +140,7 @@ static int ehci_hcd_sh_probe(struct platform_device *pdev)
fail_add_hcd: fail_add_hcd:
clk_disable(priv->iclk); clk_disable(priv->iclk);
fail_iclk:
clk_disable(priv->fclk); clk_disable(priv->fclk);
fail_request_resource: fail_request_resource:

View File

@ -779,6 +779,11 @@ max3421_check_unlink(struct usb_hcd *hcd)
retval = 1; retval = 1;
dev_dbg(&spi->dev, "%s: URB %p unlinked=%d", dev_dbg(&spi->dev, "%s: URB %p unlinked=%d",
__func__, urb, urb->unlinked); __func__, urb, urb->unlinked);
if (urb == max3421_hcd->curr_urb) {
max3421_hcd->urb_done = 1;
max3421_hcd->hien &= ~(BIT(MAX3421_HI_HXFRDN_BIT) |
BIT(MAX3421_HI_RCVDAV_BIT));
} else {
usb_hcd_unlink_urb_from_ep(hcd, urb); usb_hcd_unlink_urb_from_ep(hcd, urb);
spin_unlock_irqrestore(&max3421_hcd->lock, spin_unlock_irqrestore(&max3421_hcd->lock,
flags); flags);
@ -787,6 +792,7 @@ max3421_check_unlink(struct usb_hcd *hcd)
} }
} }
} }
}
spin_unlock_irqrestore(&max3421_hcd->lock, flags); spin_unlock_irqrestore(&max3421_hcd->lock, flags);
return retval; return retval;
} }

View File

@ -407,8 +407,10 @@ static int onboard_dev_probe(struct platform_device *pdev)
} }
if (of_device_is_compatible(pdev->dev.of_node, "usb424,2744") || if (of_device_is_compatible(pdev->dev.of_node, "usb424,2744") ||
of_device_is_compatible(pdev->dev.of_node, "usb424,5744")) of_device_is_compatible(pdev->dev.of_node, "usb424,5744")) {
err = onboard_dev_5744_i2c_init(client); err = onboard_dev_5744_i2c_init(client);
onboard_dev->always_powered_in_suspend = true;
}
put_device(&client->dev); put_device(&client->dev);
if (err < 0) if (err < 0)

View File

@ -290,6 +290,8 @@ struct anx7411_data {
struct power_supply *psy; struct power_supply *psy;
struct power_supply_desc psy_desc; struct power_supply_desc psy_desc;
struct device *dev; struct device *dev;
struct fwnode_handle *switch_node;
struct fwnode_handle *mux_node;
}; };
static u8 snk_identity[] = { static u8 snk_identity[] = {
@ -1021,6 +1023,16 @@ static void anx7411_port_unregister_altmodes(struct typec_altmode **adev)
} }
} }
static void anx7411_port_unregister(struct typec_params *typecp)
{
fwnode_handle_put(typecp->caps.fwnode);
anx7411_port_unregister_altmodes(typecp->port_amode);
if (typecp->port)
typec_unregister_port(typecp->port);
if (typecp->role_sw)
usb_role_switch_put(typecp->role_sw);
}
static int anx7411_usb_mux_set(struct typec_mux_dev *mux, static int anx7411_usb_mux_set(struct typec_mux_dev *mux,
struct typec_mux_state *state) struct typec_mux_state *state)
{ {
@ -1089,6 +1101,7 @@ static void anx7411_unregister_mux(struct anx7411_data *ctx)
if (ctx->typec.typec_mux) { if (ctx->typec.typec_mux) {
typec_mux_unregister(ctx->typec.typec_mux); typec_mux_unregister(ctx->typec.typec_mux);
ctx->typec.typec_mux = NULL; ctx->typec.typec_mux = NULL;
fwnode_handle_put(ctx->mux_node);
} }
} }
@ -1097,6 +1110,7 @@ static void anx7411_unregister_switch(struct anx7411_data *ctx)
if (ctx->typec.typec_switch) { if (ctx->typec.typec_switch) {
typec_switch_unregister(ctx->typec.typec_switch); typec_switch_unregister(ctx->typec.typec_switch);
ctx->typec.typec_switch = NULL; ctx->typec.typec_switch = NULL;
fwnode_handle_put(ctx->switch_node);
} }
} }
@ -1104,28 +1118,29 @@ static int anx7411_typec_switch_probe(struct anx7411_data *ctx,
struct device *dev) struct device *dev)
{ {
int ret; int ret;
struct device_node *node;
node = of_get_child_by_name(dev->of_node, "orientation_switch"); ctx->switch_node = device_get_named_child_node(dev, "orientation_switch");
if (!node) if (!ctx->switch_node)
return 0; return 0;
ret = anx7411_register_switch(ctx, dev, &node->fwnode); ret = anx7411_register_switch(ctx, dev, ctx->switch_node);
if (ret) { if (ret) {
dev_err(dev, "failed register switch"); dev_err(dev, "failed register switch");
fwnode_handle_put(ctx->switch_node);
return ret; return ret;
} }
node = of_get_child_by_name(dev->of_node, "mode_switch"); ctx->mux_node = device_get_named_child_node(dev, "mode_switch");
if (!node) { if (!ctx->mux_node) {
dev_err(dev, "no typec mux exist"); dev_err(dev, "no typec mux exist");
ret = -ENODEV; ret = -ENODEV;
goto unregister_switch; goto unregister_switch;
} }
ret = anx7411_register_mux(ctx, dev, &node->fwnode); ret = anx7411_register_mux(ctx, dev, ctx->mux_node);
if (ret) { if (ret) {
dev_err(dev, "failed register mode switch"); dev_err(dev, "failed register mode switch");
fwnode_handle_put(ctx->mux_node);
ret = -ENODEV; ret = -ENODEV;
goto unregister_switch; goto unregister_switch;
} }
@ -1154,34 +1169,34 @@ static int anx7411_typec_port_probe(struct anx7411_data *ctx,
ret = fwnode_property_read_string(fwnode, "power-role", &buf); ret = fwnode_property_read_string(fwnode, "power-role", &buf);
if (ret) { if (ret) {
dev_err(dev, "power-role not found: %d\n", ret); dev_err(dev, "power-role not found: %d\n", ret);
return ret; goto put_fwnode;
} }
ret = typec_find_port_power_role(buf); ret = typec_find_port_power_role(buf);
if (ret < 0) if (ret < 0)
return ret; goto put_fwnode;
cap->type = ret; cap->type = ret;
ret = fwnode_property_read_string(fwnode, "data-role", &buf); ret = fwnode_property_read_string(fwnode, "data-role", &buf);
if (ret) { if (ret) {
dev_err(dev, "data-role not found: %d\n", ret); dev_err(dev, "data-role not found: %d\n", ret);
return ret; goto put_fwnode;
} }
ret = typec_find_port_data_role(buf); ret = typec_find_port_data_role(buf);
if (ret < 0) if (ret < 0)
return ret; goto put_fwnode;
cap->data = ret; cap->data = ret;
ret = fwnode_property_read_string(fwnode, "try-power-role", &buf); ret = fwnode_property_read_string(fwnode, "try-power-role", &buf);
if (ret) { if (ret) {
dev_err(dev, "try-power-role not found: %d\n", ret); dev_err(dev, "try-power-role not found: %d\n", ret);
return ret; goto put_fwnode;
} }
ret = typec_find_power_role(buf); ret = typec_find_power_role(buf);
if (ret < 0) if (ret < 0)
return ret; goto put_fwnode;
cap->prefer_role = ret; cap->prefer_role = ret;
/* Get source pdos */ /* Get source pdos */
@ -1193,7 +1208,7 @@ static int anx7411_typec_port_probe(struct anx7411_data *ctx,
typecp->src_pdo_nr); typecp->src_pdo_nr);
if (ret < 0) { if (ret < 0) {
dev_err(dev, "source cap validate failed: %d\n", ret); dev_err(dev, "source cap validate failed: %d\n", ret);
return -EINVAL; goto put_fwnode;
} }
typecp->caps_flags |= HAS_SOURCE_CAP; typecp->caps_flags |= HAS_SOURCE_CAP;
@ -1207,7 +1222,7 @@ static int anx7411_typec_port_probe(struct anx7411_data *ctx,
typecp->sink_pdo_nr); typecp->sink_pdo_nr);
if (ret < 0) { if (ret < 0) {
dev_err(dev, "sink cap validate failed: %d\n", ret); dev_err(dev, "sink cap validate failed: %d\n", ret);
return -EINVAL; goto put_fwnode;
} }
for (i = 0; i < typecp->sink_pdo_nr; i++) { for (i = 0; i < typecp->sink_pdo_nr; i++) {
@ -1251,13 +1266,21 @@ static int anx7411_typec_port_probe(struct anx7411_data *ctx,
ret = PTR_ERR(ctx->typec.port); ret = PTR_ERR(ctx->typec.port);
ctx->typec.port = NULL; ctx->typec.port = NULL;
dev_err(dev, "Failed to register type c port %d\n", ret); dev_err(dev, "Failed to register type c port %d\n", ret);
return ret; goto put_usb_role_switch;
} }
typec_port_register_altmodes(ctx->typec.port, NULL, ctx, typec_port_register_altmodes(ctx->typec.port, NULL, ctx,
ctx->typec.port_amode, ctx->typec.port_amode,
MAX_ALTMODE); MAX_ALTMODE);
return 0; return 0;
put_usb_role_switch:
if (ctx->typec.role_sw)
usb_role_switch_put(ctx->typec.role_sw);
put_fwnode:
fwnode_handle_put(fwnode);
return ret;
} }
static int anx7411_typec_check_connection(struct anx7411_data *ctx) static int anx7411_typec_check_connection(struct anx7411_data *ctx)
@ -1523,8 +1546,7 @@ free_wq:
destroy_workqueue(plat->workqueue); destroy_workqueue(plat->workqueue);
free_typec_port: free_typec_port:
typec_unregister_port(plat->typec.port); anx7411_port_unregister(&plat->typec);
anx7411_port_unregister_altmodes(plat->typec.port_amode);
free_typec_switch: free_typec_switch:
anx7411_unregister_switch(plat); anx7411_unregister_switch(plat);
@ -1548,17 +1570,11 @@ static void anx7411_i2c_remove(struct i2c_client *client)
i2c_unregister_device(plat->spi_client); i2c_unregister_device(plat->spi_client);
if (plat->typec.role_sw)
usb_role_switch_put(plat->typec.role_sw);
anx7411_unregister_mux(plat); anx7411_unregister_mux(plat);
anx7411_unregister_switch(plat); anx7411_unregister_switch(plat);
if (plat->typec.port) anx7411_port_unregister(&plat->typec);
typec_unregister_port(plat->typec.port);
anx7411_port_unregister_altmodes(plat->typec.port_amode);
} }
static const struct i2c_device_id anx7411_id[] = { static const struct i2c_device_id anx7411_id[] = {

View File

@ -46,11 +46,11 @@ void ucsi_notify_common(struct ucsi *ucsi, u32 cci)
ucsi_connector_change(ucsi, UCSI_CCI_CONNECTOR(cci)); ucsi_connector_change(ucsi, UCSI_CCI_CONNECTOR(cci));
if (cci & UCSI_CCI_ACK_COMPLETE && if (cci & UCSI_CCI_ACK_COMPLETE &&
test_bit(ACK_PENDING, &ucsi->flags)) test_and_clear_bit(ACK_PENDING, &ucsi->flags))
complete(&ucsi->complete); complete(&ucsi->complete);
if (cci & UCSI_CCI_COMMAND_COMPLETE && if (cci & UCSI_CCI_COMMAND_COMPLETE &&
test_bit(COMMAND_PENDING, &ucsi->flags)) test_and_clear_bit(COMMAND_PENDING, &ucsi->flags))
complete(&ucsi->complete); complete(&ucsi->complete);
} }
EXPORT_SYMBOL_GPL(ucsi_notify_common); EXPORT_SYMBOL_GPL(ucsi_notify_common);
@ -65,6 +65,8 @@ int ucsi_sync_control_common(struct ucsi *ucsi, u64 command)
else else
set_bit(COMMAND_PENDING, &ucsi->flags); set_bit(COMMAND_PENDING, &ucsi->flags);
reinit_completion(&ucsi->complete);
ret = ucsi->ops->async_control(ucsi, command); ret = ucsi->ops->async_control(ucsi, command);
if (ret) if (ret)
goto out_clear_bit; goto out_clear_bit;
@ -651,7 +653,8 @@ static void ucsi_unregister_altmodes(struct ucsi_connector *con, u8 recipient)
static int ucsi_get_connector_status(struct ucsi_connector *con, bool conn_ack) static int ucsi_get_connector_status(struct ucsi_connector *con, bool conn_ack)
{ {
u64 command = UCSI_GET_CONNECTOR_STATUS | UCSI_CONNECTOR_NUMBER(con->num); u64 command = UCSI_GET_CONNECTOR_STATUS | UCSI_CONNECTOR_NUMBER(con->num);
size_t size = min(UCSI_GET_CONNECTOR_STATUS_SIZE, UCSI_MAX_DATA_LENGTH(con->ucsi)); size_t size = min(sizeof(con->status),
UCSI_MAX_DATA_LENGTH(con->ucsi));
int ret; int ret;
ret = ucsi_send_command_common(con->ucsi, command, &con->status, size, conn_ack); ret = ucsi_send_command_common(con->ucsi, command, &con->status, size, conn_ack);