From: sashiko-bot@kernel.org
To: "Chen-Yu Tsai" <wenst@chromium.org>
Cc: devicetree@vger.kernel.org, robh@kernel.org, conor+dt@kernel.org
Subject: Re: [PATCH v2 07/16] usb: hub: Power on connected M.2 E-key connectors
Date: Wed, 10 Jun 2026 09:03:44 +0000 [thread overview]
Message-ID: <20260610090345.335541F00893@smtp.kernel.org> (raw)
In-Reply-To: <20260610084053.2059858-8-wenst@chromium.org>
Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:
- [Critical] Unconditional calls to power sequencing APIs will fail all USB port initializations when `CONFIG_POWER_SEQUENCING` is disabled.
- [High] Concurrent modification of the `pwrseq_on` bitfield on a shared `usb_port` device causes data races and corruption of other bitfields.
- [High] Premature physical power-off of the shared M.2 E-key power sequencer when one peer logical port suspends, unexpectedly disconnecting the active peer.
- [Medium] Leaked fwnode reference during USB port creation via `fwnode_graph_get_port_by_id()`.
--
commit 984160fb49fab6dc951a766897ded9fb49d0992b
Author: Chen-Yu Tsai <wenst@chromium.org>
usb: hub: Power on connected M.2 E-key connectors
This patch adds support for powering on directly connected M.2 E-key
connectors via the power sequencing API. It ties the power sequencing
descriptor to the usb port device to allow providers to distinguish
ports on a hub. The power state is toggled using the power sequencing
API during port power changes.
> diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
> index 0c75965fefb7c..585b6beec71bb 100644
> --- a/drivers/usb/core/hub.c
> +++ b/drivers/usb/core/hub.c
> @@ -886,20 +887,41 @@ static void hub_tt_work(struct work_struct *work)
> int usb_hub_set_port_power(struct usb_device *hdev, struct usb_hub *hub,
> int port1, bool set)
> {
> - int ret;
> + struct usb_port *pwrseq_port = hub->ports[port1 - 1];
> + int ret = 0;
> +
> + /* non-SuperSpeed USB port holds pwrseq descriptor reference. */
> + if (hub->ports[port1 - 1]->is_superspeed && hub->ports[port1 - 1]->peer)
> + pwrseq_port = hub->ports[port1 - 1]->peer;
> +
> + if (set && !pwrseq_port->pwrseq_on)
> + ret = pwrseq_power_on(pwrseq_port->pwrseq);
> + else if (!set && pwrseq_port->pwrseq_on)
> + ret = pwrseq_power_off(pwrseq_port->pwrseq);
[Severity: High]
Will this prematurely cut physical power to the M.2 slot if the HiSpeed
logical port suspends?
A physical M.2 connector has both a SuperSpeed and HiSpeed logical port.
This patch binds the power sequencing descriptor only to the HiSpeed port
and shares a single pwrseq_on boolean for both logical ports.
If a SuperSpeed device is connected, the SuperSpeed port remains active,
but the HiSpeed port suspends via usb_port_runtime_suspend() since it detects
no active HiSpeed device. Suspending the HiSpeed port invokes
usb_hub_set_port_power(..., false) which immediately calls
pwrseq_power_off() here since pwrseq_on is true.
This would abruptly cut physical power to the M.2 slot and drop the active
SuperSpeed device, because the boolean flag bypasses the power sequencing
framework's internal reference counting and ignores the active state of the
SuperSpeed port.
> + if (ret)
> + return ret;
>
> if (set)
> ret = set_port_feature(hdev, port1, USB_PORT_FEAT_POWER);
> else
> ret = usb_clear_port_feature(hdev, port1, USB_PORT_FEAT_POWER);
>
> - if (ret)
> + if (ret) {
> + if (set && !pwrseq_port->pwrseq_on)
> + pwrseq_power_off(pwrseq_port->pwrseq);
> + else if (!set && pwrseq_port->pwrseq_on)
> + pwrseq_power_on(pwrseq_port->pwrseq);
> return ret;
> + }
>
> - if (set)
> + if (set) {
> set_bit(port1, hub->power_bits);
> - else
> + pwrseq_port->pwrseq_on = 1;
> + } else {
> clear_bit(port1, hub->power_bits);
> + pwrseq_port->pwrseq_on = 0;
> + }
[Severity: High]
Could modifying this bitfield without holding usb_lock_port() cause a data race?
Since pwrseq_on is packed alongside other 1-bit fields in struct usb_port
(like ignore_event, early_stop, and usb3_lpm_u1_permit), modifying it here
in usb_hub_set_port_power() without synchronization can cause a
read-modify-write data race.
If sysfs (like usb3_lpm_u1_permit_store) or hub event workqueues modify
adjacent bits under their respective locks concurrently, one thread's update
could silently overwrite the other's, corrupting the port state.
[ ... ]
> diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c
> index d9d3e2bb8f251..a5e7fbf4aa6e2 100644
> --- a/drivers/usb/core/port.c
> +++ b/drivers/usb/core/port.c
> @@ -803,10 +846,25 @@ int usb_hub_create_port_device(struct usb_hub *hub, int port1)
> goto err_put_kn;
> }
>
[Severity: Medium]
Does port creation leak an fwnode reference here?
Earlier in usb_hub_create_port_device(), the call to
fwnode_graph_get_port_by_id() returns a firmware node with an incremented
reference count. This node is passed to device_set_node(), which assigns it
but does not take ownership of the reference.
Neither the error paths in usb_hub_create_port_device(), nor
usb_hub_remove_port_device() call fwnode_handle_put() to release it, causing
a reference leak every time a usb port is enumerated.
> + port_dev->pwrseq = usb_hub_port_pwrseq_get(port_dev);
> + if (IS_ERR(port_dev->pwrseq)) {
> + retval = PTR_ERR(port_dev->pwrseq);
> + dev_err_probe(&port_dev->dev, retval,
> + "failed to get power sequencing descriptor\n");
> + goto err_put_kn;
> + }
> +
> + retval = pwrseq_power_on(port_dev->pwrseq);
> + if (retval) {
> + dev_err_probe(&port_dev->dev, retval, "failed to enable power\n");
> + goto err_put_pwrseq;
> + }
[Severity: Critical]
Will this fail port creation for all usb ports when power sequencing
is disabled?
If the kernel is built without power sequencing enabled,
usb_hub_port_pwrseq_get() deliberately returns NULL.
However, pwrseq_power_on(NULL) unconditionally returns -ENOSYS when the
feature is disabled. Treating -ENOSYS as a hard failure here will abort port
creation, causing the entire usb subsystem to fail enumerating any ports on
systems where power sequencing is disabled.
> + port_dev->pwrseq_on = 1;
> +
> retval = component_add(&port_dev->dev, &connector_ops);
> if (retval) {
> dev_warn(&port_dev->dev, "failed to add component\n");
> - goto err_put_kn;
> + goto err_pwrseq_off;
> }
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260610084053.2059858-1-wenst@chromium.org?part=7
next prev parent reply other threads:[~2026-06-10 9:03 UTC|newest]
Thread overview: 32+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-10 8:40 [PATCH v2 00/16] arm64: mediatek: Add M.2 E-key slot on Chromebooks Chen-Yu Tsai
2026-06-10 8:40 ` [PATCH v2 01/16] device property: Add fwnode_graph_get_port_by_id() Chen-Yu Tsai
2026-06-10 8:55 ` sashiko-bot
2026-06-10 13:57 ` Andy Shevchenko
2026-06-10 8:40 ` [PATCH v2 02/16] device property: Add fwnode_graph_get_next_port_endpoint() Chen-Yu Tsai
2026-06-10 8:57 ` sashiko-bot
2026-06-10 14:08 ` Andy Shevchenko
2026-06-10 8:40 ` [PATCH v2 03/16] power: sequencing: Change CONFIG_POWER_SEQUENCING to bool Chen-Yu Tsai
2026-06-10 8:55 ` sashiko-bot
2026-06-10 9:00 ` Chen-Yu Tsai
2026-06-10 8:40 ` [PATCH v2 04/16] usb: hub: Return actual error from hub_configure() in hub_probe() Chen-Yu Tsai
2026-06-10 14:20 ` Andy Shevchenko
2026-06-10 8:40 ` [PATCH v2 05/16] usb: hub: Associate port@ fwnode with USB port device Chen-Yu Tsai
2026-06-10 8:56 ` sashiko-bot
2026-06-10 14:16 ` Andy Shevchenko
2026-06-10 8:40 ` [PATCH v2 06/16] usb: hub: Pass |struct usb_port*| to usb_port_is_power_on() Chen-Yu Tsai
2026-06-10 8:40 ` [PATCH v2 07/16] usb: hub: Power on connected M.2 E-key connectors Chen-Yu Tsai
2026-06-10 9:03 ` sashiko-bot [this message]
2026-06-10 14:31 ` Andy Shevchenko
2026-06-10 8:40 ` [PATCH v2 08/16] Revert "dt-bindings: usb: mediatek,mtk-xhci: Add port for SuperSpeed EP" Chen-Yu Tsai
2026-06-10 8:40 ` [PATCH v2 09/16] dt-bindings: usb: mediatek,mtk-xhci: Allow ports for USB connections Chen-Yu Tsai
2026-06-10 8:40 ` [PATCH v2 10/16] power: sequencing: pcie-m2: support matching on remote "port" node Chen-Yu Tsai
2026-06-10 14:33 ` Andy Shevchenko
2026-06-10 8:40 ` [PATCH v2 11/16] power: sequencing: pcie-m2: Add usb and sdio targets for E-key connector Chen-Yu Tsai
2026-06-10 14:36 ` Andy Shevchenko
2026-06-10 8:40 ` [PATCH v2 12/16] arm64: dts: mediatek: mt8192-asurada: Add USB type-A connector Chen-Yu Tsai
2026-06-10 8:40 ` [PATCH v2 13/16] arm64: dts: mediatek: mt8192-asurada: Add M.2 E-key slot Chen-Yu Tsai
2026-06-10 8:40 ` [PATCH v2 14/16] arm64: dts: mediatek: mt8195-cherry: " Chen-Yu Tsai
2026-06-10 9:03 ` sashiko-bot
2026-06-10 8:40 ` [PATCH v2 15/16] arm64: dts: mediatek: mt8195-cherry: Add USB type-A connector Chen-Yu Tsai
2026-06-10 8:40 ` [PATCH v2 16/16] arm64: dts: mediatek: mt8188-geralt: Add WiFi/BT as M.2 E-key slot Chen-Yu Tsai
2026-06-10 9:02 ` sashiko-bot
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260610090345.335541F00893@smtp.kernel.org \
--to=sashiko-bot@kernel.org \
--cc=conor+dt@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=robh@kernel.org \
--cc=sashiko-reviews@lists.linux.dev \
--cc=wenst@chromium.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.