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:
commit
be5bfa1378
@ -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 */
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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)
|
||||
|
@ -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) {
|
||||
|
@ -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");
|
||||
|
@ -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);
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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 = {
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user