1

USB / Thunderbolt fixes for 6.12-rc6

Here are some small USB and Thunderbolt driver fixes for 6.12-rc6 that
 have been sitting in my tree this week.  Included in here are the
 following:
   - thunderbolt driver fixes for reported issues
   - USB typec driver fixes
   - xhci driver fixes for reported problems
   - dwc2 driver revert for a broken change
   - usb phy driver fix
   - usbip tool fix
 
 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-----
 
 iG0EABECAC0WIQT0tgzFv3jCIUoxPcsxR9QN2y37KQUCZydklw8cZ3JlZ0Brcm9h
 aC5jb20ACgkQMUfUDdst+ynrOQCgvUxfi1tUPR78CDuIR1fiaNxdsDsAoI+WwyFt
 5U2D3ezAl3ovyRVWlN4y
 =DSxw
 -----END PGP SIGNATURE-----

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

Pull USB / Thunderbolt fixes from Greg KH:
 "Here are some small USB and Thunderbolt driver fixes for 6.12-rc6 that
  have been sitting in my tree this week. Included in here are the
  following:

   - thunderbolt driver fixes for reported issues

   - USB typec driver fixes

   - xhci driver fixes for reported problems

   - dwc2 driver revert for a broken change

   - usb phy driver fix

   - usbip tool fix

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

* tag 'usb-6.12-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb:
  usb: typec: tcpm: restrict SNK_WAIT_CAPABILITIES_TIMEOUT transitions to non self-powered devices
  usb: phy: Fix API devm_usb_put_phy() can not release the phy
  usb: typec: use cleanup facility for 'altmodes_node'
  usb: typec: fix unreleased fwnode_handle in typec_port_register_altmodes()
  usb: typec: qcom-pmic-typec: fix missing fwnode removal in error path
  usb: typec: qcom-pmic-typec: use fwnode_handle_put() to release fwnodes
  usb: acpi: fix boot hang due to early incorrect 'tunneled' USB3 device links
  Revert "usb: dwc2: Skip clock gating on Broadcom SoCs"
  xhci: Fix Link TRB DMA in command ring stopped completion event
  xhci: Use pm_runtime_get to prevent RPM on unsupported systems
  usbip: tools: Fix detach_port() invalid port error path
  thunderbolt: Honor TMU requirements in the domain when setting TMU mode
  thunderbolt: Fix KASAN reported stack out-of-bounds read in tb_retimer_scan()
This commit is contained in:
Linus Torvalds 2024-11-03 08:48:11 -10:00
commit be5bfa1378
11 changed files with 78 additions and 31 deletions

View File

@ -516,7 +516,7 @@ int tb_retimer_scan(struct tb_port *port, bool add)
*/
tb_retimer_set_inbound_sbtx(port);
for (i = 1; i <= TB_MAX_RETIMER_INDEX; i++) {
for (max = 1, i = 1; i <= TB_MAX_RETIMER_INDEX; i++) {
/*
* Last retimer is true only for the last on-board
* retimer (the one connected directly to the Type-C
@ -527,9 +527,10 @@ int tb_retimer_scan(struct tb_port *port, bool add)
last_idx = i;
else if (ret < 0)
break;
max = i;
}
max = i;
ret = 0;
/* Add retimers if they do not exist already */

View File

@ -288,6 +288,24 @@ static void tb_increase_tmu_accuracy(struct tb_tunnel *tunnel)
device_for_each_child(&sw->dev, NULL, tb_increase_switch_tmu_accuracy);
}
static int tb_switch_tmu_hifi_uni_required(struct device *dev, void *not_used)
{
struct tb_switch *sw = tb_to_switch(dev);
if (sw && tb_switch_tmu_is_enabled(sw) &&
tb_switch_tmu_is_configured(sw, TB_SWITCH_TMU_MODE_HIFI_UNI))
return 1;
return device_for_each_child(dev, NULL,
tb_switch_tmu_hifi_uni_required);
}
static bool tb_tmu_hifi_uni_required(struct tb *tb)
{
return device_for_each_child(&tb->dev, NULL,
tb_switch_tmu_hifi_uni_required) == 1;
}
static int tb_enable_tmu(struct tb_switch *sw)
{
int ret;
@ -302,12 +320,30 @@ static int tb_enable_tmu(struct tb_switch *sw)
ret = tb_switch_tmu_configure(sw,
TB_SWITCH_TMU_MODE_MEDRES_ENHANCED_UNI);
if (ret == -EOPNOTSUPP) {
if (tb_switch_clx_is_enabled(sw, TB_CL1))
ret = tb_switch_tmu_configure(sw,
TB_SWITCH_TMU_MODE_LOWRES);
else
ret = tb_switch_tmu_configure(sw,
TB_SWITCH_TMU_MODE_HIFI_BI);
if (tb_switch_clx_is_enabled(sw, TB_CL1)) {
/*
* Figure out uni-directional HiFi TMU requirements
* currently in the domain. If there are no
* uni-directional HiFi requirements we can put the TMU
* into LowRes mode.
*
* Deliberately skip bi-directional HiFi links
* as these work independently of other links
* (and they do not allow any CL states anyway).
*/
if (tb_tmu_hifi_uni_required(sw->tb))
ret = tb_switch_tmu_configure(sw,
TB_SWITCH_TMU_MODE_HIFI_UNI);
else
ret = tb_switch_tmu_configure(sw,
TB_SWITCH_TMU_MODE_LOWRES);
} else {
ret = tb_switch_tmu_configure(sw, TB_SWITCH_TMU_MODE_HIFI_BI);
}
/* If not supported, fallback to bi-directional HiFi */
if (ret == -EOPNOTSUPP)
ret = tb_switch_tmu_configure(sw, TB_SWITCH_TMU_MODE_HIFI_BI);
}
if (ret)
return ret;

View File

@ -170,11 +170,11 @@ static int usb_acpi_add_usb4_devlink(struct usb_device *udev)
struct fwnode_handle *nhi_fwnode __free(fwnode_handle) =
fwnode_find_reference(dev_fwnode(&port_dev->dev), "usb4-host-interface", 0);
if (IS_ERR(nhi_fwnode))
if (IS_ERR(nhi_fwnode) || !nhi_fwnode->dev)
return 0;
link = device_link_add(&port_dev->child->dev, nhi_fwnode->dev,
DL_FLAG_AUTOREMOVE_CONSUMER |
DL_FLAG_STATELESS |
DL_FLAG_RPM_ACTIVE |
DL_FLAG_PM_RUNTIME);
if (!link) {

View File

@ -23,7 +23,6 @@ static void dwc2_set_bcm_params(struct dwc2_hsotg *hsotg)
p->max_transfer_size = 65535;
p->max_packet_count = 511;
p->ahbcfg = 0x10;
p->no_clock_gating = true;
}
static void dwc2_set_his_params(struct dwc2_hsotg *hsotg)

View File

@ -640,7 +640,7 @@ int xhci_pci_common_probe(struct pci_dev *dev, const struct pci_device_id *id)
pm_runtime_put_noidle(&dev->dev);
if (pci_choose_state(dev, PMSG_SUSPEND) == PCI_D0)
pm_runtime_forbid(&dev->dev);
pm_runtime_get(&dev->dev);
else if (xhci->quirks & XHCI_DEFAULT_PM_RUNTIME_ALLOW)
pm_runtime_allow(&dev->dev);
@ -683,7 +683,9 @@ void xhci_pci_remove(struct pci_dev *dev)
xhci->xhc_state |= XHCI_STATE_REMOVING;
if (xhci->quirks & XHCI_DEFAULT_PM_RUNTIME_ALLOW)
if (pci_choose_state(dev, PMSG_SUSPEND) == PCI_D0)
pm_runtime_put(&dev->dev);
else if (xhci->quirks & XHCI_DEFAULT_PM_RUNTIME_ALLOW)
pm_runtime_forbid(&dev->dev);
if (xhci->shared_hcd) {

View File

@ -1718,6 +1718,14 @@ static void handle_cmd_completion(struct xhci_hcd *xhci,
trace_xhci_handle_command(xhci->cmd_ring, &cmd_trb->generic);
cmd_comp_code = GET_COMP_CODE(le32_to_cpu(event->status));
/* If CMD ring stopped we own the trbs between enqueue and dequeue */
if (cmd_comp_code == COMP_COMMAND_RING_STOPPED) {
complete_all(&xhci->cmd_ring_stop_completion);
return;
}
cmd_dequeue_dma = xhci_trb_virt_to_dma(xhci->cmd_ring->deq_seg,
cmd_trb);
/*
@ -1734,14 +1742,6 @@ static void handle_cmd_completion(struct xhci_hcd *xhci,
cancel_delayed_work(&xhci->cmd_timer);
cmd_comp_code = GET_COMP_CODE(le32_to_cpu(event->status));
/* If CMD ring stopped we own the trbs between enqueue and dequeue */
if (cmd_comp_code == COMP_COMMAND_RING_STOPPED) {
complete_all(&xhci->cmd_ring_stop_completion);
return;
}
if (cmd->command_trb != xhci->cmd_ring->dequeue) {
xhci_err(xhci,
"Command completion event does not match command\n");

View File

@ -628,7 +628,7 @@ void devm_usb_put_phy(struct device *dev, struct usb_phy *phy)
{
int r;
r = devres_destroy(dev, devm_usb_phy_release, devm_usb_phy_match, phy);
r = devres_release(dev, devm_usb_phy_release, devm_usb_phy_match, phy);
dev_WARN_ONCE(dev, r, "couldn't find PHY resource\n");
}
EXPORT_SYMBOL_GPL(devm_usb_put_phy);

View File

@ -2293,7 +2293,7 @@ void typec_port_register_altmodes(struct typec_port *port,
const struct typec_altmode_ops *ops, void *drvdata,
struct typec_altmode **altmodes, size_t n)
{
struct fwnode_handle *altmodes_node, *child;
struct fwnode_handle *child;
struct typec_altmode_desc desc;
struct typec_altmode *alt;
size_t index = 0;
@ -2301,7 +2301,9 @@ void typec_port_register_altmodes(struct typec_port *port,
u32 vdo;
int ret;
altmodes_node = device_get_named_child_node(&port->dev, "altmodes");
struct fwnode_handle *altmodes_node __free(fwnode_handle) =
device_get_named_child_node(&port->dev, "altmodes");
if (!altmodes_node)
return; /* No altmodes specified */

View File

@ -93,8 +93,10 @@ static int qcom_pmic_typec_probe(struct platform_device *pdev)
return -EINVAL;
bridge_dev = devm_drm_dp_hpd_bridge_alloc(tcpm->dev, to_of_node(tcpm->tcpc.fwnode));
if (IS_ERR(bridge_dev))
return PTR_ERR(bridge_dev);
if (IS_ERR(bridge_dev)) {
ret = PTR_ERR(bridge_dev);
goto fwnode_remove;
}
tcpm->tcpm_port = tcpm_register_port(tcpm->dev, &tcpm->tcpc);
if (IS_ERR(tcpm->tcpm_port)) {
@ -123,7 +125,7 @@ port_stop:
port_unregister:
tcpm_unregister_port(tcpm->tcpm_port);
fwnode_remove:
fwnode_remove_software_node(tcpm->tcpc.fwnode);
fwnode_handle_put(tcpm->tcpc.fwnode);
return ret;
}
@ -135,7 +137,7 @@ static void qcom_pmic_typec_remove(struct platform_device *pdev)
tcpm->pdphy_stop(tcpm);
tcpm->port_stop(tcpm);
tcpm_unregister_port(tcpm->tcpm_port);
fwnode_remove_software_node(tcpm->tcpc.fwnode);
fwnode_handle_put(tcpm->tcpc.fwnode);
}
static const struct pmic_typec_resources pm8150b_typec_res = {

View File

@ -4515,7 +4515,8 @@ static inline enum tcpm_state hard_reset_state(struct tcpm_port *port)
return ERROR_RECOVERY;
if (port->pwr_role == TYPEC_SOURCE)
return SRC_UNATTACHED;
if (port->state == SNK_WAIT_CAPABILITIES_TIMEOUT)
if (port->state == SNK_WAIT_CAPABILITIES ||
port->state == SNK_WAIT_CAPABILITIES_TIMEOUT)
return SNK_READY;
return SNK_UNATTACHED;
}
@ -5043,8 +5044,11 @@ static void run_state_machine(struct tcpm_port *port)
tcpm_set_state(port, SNK_SOFT_RESET,
PD_T_SINK_WAIT_CAP);
} else {
tcpm_set_state(port, SNK_WAIT_CAPABILITIES_TIMEOUT,
PD_T_SINK_WAIT_CAP);
if (!port->self_powered)
upcoming_state = SNK_WAIT_CAPABILITIES_TIMEOUT;
else
upcoming_state = hard_reset_state(port);
tcpm_set_state(port, upcoming_state, PD_T_SINK_WAIT_CAP);
}
break;
case SNK_WAIT_CAPABILITIES_TIMEOUT:

View File

@ -68,6 +68,7 @@ static int detach_port(char *port)
}
if (!found) {
ret = -1;
err("Invalid port %s > maxports %d",
port, vhci_driver->nports);
goto call_driver_close;