* [PATCH RFC 07/12] dt-bindings: usb: mediatek,mtk-xhci: Allow ports for USB connections
From: Chen-Yu Tsai @ 2026-05-15 9:01 UTC (permalink / raw)
To: Bartosz Golaszewski, Greg Kroah-Hartman, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
AngeloGioacchino Del Regno
Cc: Chen-Yu Tsai, linux-pm, linux-usb, devicetree, linux-mediatek,
linux-arm-kernel, linux-kernel, Manivannan Sadhasivam
In-Reply-To: <20260515090149.3169406-1-wenst@chromium.org>
MediaTek's XHCI implementation supports both USB 2.0 High Speed (HS)
and USB 3.x Super Speed (SS). The block can also be synthesized with
either HS-only capability or HS+SS capability.
For example, on the MT8195, the first two instances support both HS and
SS, while the latter two instances support only HS.
Allow a ports sub-node for describing USB connections. Port 1 is Super
Speed if the controller is SS-capable, otherwise it is High Speed. Port
2 is High Speed if SS-capable. This port mapping scheme directly matches
what the hardware returns in its capability registers.
Signed-off-by: Chen-Yu Tsai <wenst@chromium.org>
---
.../devicetree/bindings/usb/mediatek,mtk-xhci.yaml | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.yaml b/Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.yaml
index 75ecce3bdc7a..d6c75bd20b78 100644
--- a/Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.yaml
+++ b/Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.yaml
@@ -184,6 +184,19 @@ properties:
"#size-cells":
const: 0
+ ports:
+ $ref: /schemas/graph.yaml#/properties/ports
+
+ properties:
+ port@1:
+ $ref: /schemas/graph.yaml#/properties/port
+ description: Super Speed (SS) data bus if SS-capable;
+ otherwise High Speed (HS) data bus.
+
+ port@2:
+ $ref: /schemas/graph.yaml#/properties/port
+ description: High Speed (HS) data bus if controller is SS-capable.
+
patternProperties:
"@[0-9a-f]{1}$":
type: object
--
2.54.0.563.g4f69b47b94-goog
^ permalink raw reply related
* [PATCH RFC 06/12] Revert "dt-bindings: usb: mediatek,mtk-xhci: Add port for SuperSpeed EP"
From: Chen-Yu Tsai @ 2026-05-15 9:01 UTC (permalink / raw)
To: Bartosz Golaszewski, Greg Kroah-Hartman, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
AngeloGioacchino Del Regno
Cc: Chen-Yu Tsai, linux-pm, linux-usb, devicetree, linux-mediatek,
linux-arm-kernel, linux-kernel, Manivannan Sadhasivam
In-Reply-To: <20260515090149.3169406-1-wenst@chromium.org>
This reverts commit 454a1e3cd36c113341d7b71e8e691c6e47ab4a8a.
mtk-xhci handles both USB 2.0 High Speed (HS) and USB 3.x SuperSpeed
(SS) host connections. And there are USB 2.0 only mtk-xhci blocks.
The SSUSB controller handles the device or gadget mode. Saying that
SSUSB handles the HS portion is wrong.
Fixes: 454a1e3cd36c ("dt-bindings: usb: mediatek,mtk-xhci: Add port for SuperSpeed EP")
Cc: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Signed-off-by: Chen-Yu Tsai <wenst@chromium.org>
---
Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.yaml | 4 ----
1 file changed, 4 deletions(-)
diff --git a/Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.yaml b/Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.yaml
index 231e6f35a986..75ecce3bdc7a 100644
--- a/Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.yaml
+++ b/Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.yaml
@@ -107,10 +107,6 @@ properties:
- description: USB3/SS(P) PHY
- description: USB2/HS PHY
- port:
- $ref: /schemas/graph.yaml#/properties/port
- description: Super Speed (SS) Output endpoint to a Type-C connector
-
vusb33-supply:
description: Regulator of USB AVDD3.3v
--
2.54.0.563.g4f69b47b94-goog
^ permalink raw reply related
* [PATCH RFC 05/12] usb: hub: Power on connected M.2 E-key connectors
From: Chen-Yu Tsai @ 2026-05-15 9:01 UTC (permalink / raw)
To: Bartosz Golaszewski, Greg Kroah-Hartman, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
AngeloGioacchino Del Regno
Cc: Chen-Yu Tsai, linux-pm, linux-usb, devicetree, linux-mediatek,
linux-arm-kernel, linux-kernel, Manivannan Sadhasivam
In-Reply-To: <20260515090149.3169406-1-wenst@chromium.org>
The new M.2 E-key connector can have a USB connection. For the USB device
on this connector to work, its power must be enabled and the W_DISABLE2#
signal deasserted. The connector driver handles this and provides a
toggle over the power sequencing API.
This feature currently only supports a directly connected (no mux in
between) M.2 E-key connector. Existing USB connector types are not
covered. The USB A connector was recently added to the onboard devices
driver. USB B connectors have historically been managed by the USB
gadget or dual-role device controller drivers. USB C connectors are
handled by TCPM drivers.
The power sequencing API does not know whether a power sequence provider
is not needed or not available yet, so we only request it for connectors
that we know need it, which at this time is just the E-key connector.
The feature is limited to OF platforms, since the connection is over an
OF graph. And it doesn't make sense to return an error when the power
sequencing framework is not enabled, as that would block all USB
devices. Therefor the function short circuits out if any of these
conditions happen.
Also, this is not implemented in the onboard USB devices driver. The
power sequencing API expects the consumer device to make the request,
but there is no device node to instantiate a platform device to tie
the driver to. The connector is not a child node of the USB host or
hub, and the graph connection is from a USB port to the connector.
Signed-off-by: Chen-Yu Tsai <wenst@chromium.org>
---
drivers/usb/core/hub.c | 17 ++++++++++++-
drivers/usb/core/hub.h | 2 ++
drivers/usb/core/port.c | 54 ++++++++++++++++++++++++++++++++++++++++-
3 files changed, 71 insertions(+), 2 deletions(-)
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 90ea597d42ae..4165f71e212b 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -31,7 +31,9 @@
#include <linux/minmax.h>
#include <linux/mutex.h>
#include <linux/random.h>
+#include <linux/of_graph.h>
#include <linux/pm_qos.h>
+#include <linux/pwrseq/consumer.h>
#include <linux/kobject.h>
#include <linux/bitfield.h>
@@ -888,13 +890,25 @@ int usb_hub_set_port_power(struct usb_device *hdev, struct usb_hub *hub,
{
int ret;
+ if (set)
+ ret = pwrseq_power_on(hub->ports[port1 - 1]->pwrseq);
+ else
+ ret = pwrseq_power_off(hub->ports[port1 - 1]->pwrseq);
+ 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_power_off(hub->ports[port1 - 1]->pwrseq);
+ else
+ pwrseq_power_on(hub->ports[port1 - 1]->pwrseq);
return ret;
+ }
if (set)
set_bit(port1, hub->power_bits);
@@ -1867,6 +1881,7 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id)
struct usb_host_interface *desc;
struct usb_device *hdev;
struct usb_hub *hub;
+ int ret;
desc = intf->cur_altsetting;
hdev = interface_to_usbdev(intf);
diff --git a/drivers/usb/core/hub.h b/drivers/usb/core/hub.h
index 9ebc5ef54a32..6039e5f5dcd7 100644
--- a/drivers/usb/core/hub.h
+++ b/drivers/usb/core/hub.h
@@ -85,6 +85,7 @@ struct usb_hub {
* @port_owner: port's owner
* @peer: related usb2 and usb3 ports (share the same connector)
* @connector: USB Type-C connector
+ * @pwrseq: power sequencing descriptor for the port
* @req: default pm qos request for hubs without port power control
* @connect_type: port's connect type
* @state: device state of the usb device attached to the port
@@ -104,6 +105,7 @@ struct usb_port {
struct usb_dev_state *port_owner;
struct usb_port *peer;
struct typec_connector *connector;
+ struct pwrseq_desc *pwrseq;
struct dev_pm_qos_request *req;
enum usb_port_connect_type connect_type;
enum usb_device_state state;
diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c
index b1364f0c384c..2d09037fee93 100644
--- a/drivers/usb/core/port.c
+++ b/drivers/usb/core/port.c
@@ -7,11 +7,14 @@
* Author: Lan Tianyu <tianyu.lan@intel.com>
*/
+#include <linux/cleanup.h>
#include <linux/kstrtox.h>
#include <linux/slab.h>
#include <linux/string_choices.h>
#include <linux/sysfs.h>
+#include <linux/of_graph.h>
#include <linux/pm_qos.h>
+#include <linux/pwrseq/consumer.h>
#include <linux/component.h>
#include <linux/usb/of.h>
@@ -28,6 +31,9 @@ static bool usb_port_allow_power_off(struct usb_device *hdev,
if (hub_is_port_power_switchable(hub))
return true;
+ if (port_dev->pwrseq)
+ return true;
+
if (!IS_ENABLED(CONFIG_ACPI))
return false;
@@ -748,6 +754,32 @@ static const struct component_ops connector_ops = {
.unbind = connector_unbind,
};
+static struct pwrseq_desc *usb_hub_port_pwrseq_get(struct usb_device *hub, int port1)
+{
+ struct device_node *node = dev_of_node(&hub->dev);
+ struct device_node *np __free(device_node) = NULL;
+
+ if (!IS_ENABLED(CONFIG_OF))
+ return NULL;
+
+ if (!IS_ENABLED(CONFIG_POWER_SEQUENCING))
+ return NULL;
+
+ if (!of_graph_is_present(node))
+ return NULL;
+
+ np = of_graph_get_remote_node(node, port1, -1);
+ if (!np)
+ return NULL;
+
+ if (!of_device_is_compatible(np, "pcie-m2-e-connector")) {
+ dev_dbg(&hub->dev, "remote endpoint %pOF not m2 connector", np);
+ return NULL;
+ }
+
+ return pwrseq_get_index(&hub->dev, "usb", port1);
+}
+
int usb_hub_create_port_device(struct usb_hub *hub, int port1)
{
struct usb_port *port_dev;
@@ -801,10 +833,24 @@ int usb_hub_create_port_device(struct usb_hub *hub, int port1)
goto err_put_kn;
}
+ port_dev->pwrseq = usb_hub_port_pwrseq_get(hdev, port1);
+ 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;
+ }
+
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;
}
find_and_link_peer(hub, port1);
@@ -842,6 +888,10 @@ int usb_hub_create_port_device(struct usb_hub *hub, int port1)
}
return 0;
+err_pwrseq_off:
+ pwrseq_power_off(port_dev->pwrseq);
+err_put_pwrseq:
+ pwrseq_put(port_dev->pwrseq);
err_put_kn:
sysfs_put(port_dev->state_kn);
err_unregister:
@@ -858,6 +908,8 @@ void usb_hub_remove_port_device(struct usb_hub *hub, int port1)
peer = port_dev->peer;
if (peer)
unlink_peers(port_dev, peer);
+ pwrseq_power_off(port_dev->pwrseq);
+ pwrseq_put(port_dev->pwrseq);
component_del(&port_dev->dev, &connector_ops);
sysfs_put(port_dev->state_kn);
device_unregister(&port_dev->dev);
--
2.54.0.563.g4f69b47b94-goog
^ permalink raw reply related
* [PATCH RFC 04/12] usb: hub: Return actual error from hub_configure() in hub_probe()
From: Chen-Yu Tsai @ 2026-05-15 9:01 UTC (permalink / raw)
To: Bartosz Golaszewski, Greg Kroah-Hartman, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
AngeloGioacchino Del Regno
Cc: Chen-Yu Tsai, linux-pm, linux-usb, devicetree, linux-mediatek,
linux-arm-kernel, linux-kernel, Manivannan Sadhasivam
In-Reply-To: <20260515090149.3169406-1-wenst@chromium.org>
The addition of power sequencing descriptor handling in the USB hub code
requires dealing with deferred probing from pwrseq_get(). The power
sequencing provider may not yet be available when the USB hub probes.
Return the actual error code from hub_configure() when it fails, so that
the driver core can notice the deferred probe request.
Signed-off-by: Chen-Yu Tsai <wenst@chromium.org>
---
drivers/usb/core/hub.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 24960ba9caa9..90ea597d42ae 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -1998,14 +1998,15 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id)
usb_set_interface(hdev, 0, 0);
}
- if (hub_configure(hub, &desc->endpoint[0].desc) >= 0) {
+ ret = hub_configure(hub, &desc->endpoint[0].desc);
+ if (ret >= 0) {
onboard_dev_create_pdevs(hdev, &hub->onboard_devs);
return 0;
}
hub_disconnect(intf);
- return -ENODEV;
+ return ret;
}
static int
--
2.54.0.563.g4f69b47b94-goog
^ permalink raw reply related
* [PATCH RFC 03/12] power: sequencing: pcie-m2: Add usb and sdio targets for E-key connector
From: Chen-Yu Tsai @ 2026-05-15 9:01 UTC (permalink / raw)
To: Bartosz Golaszewski, Greg Kroah-Hartman, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
AngeloGioacchino Del Regno
Cc: Chen-Yu Tsai, linux-pm, linux-usb, devicetree, linux-mediatek,
linux-arm-kernel, linux-kernel, Manivannan Sadhasivam
In-Reply-To: <20260515090149.3169406-1-wenst@chromium.org>
The M.2 E-key connector allows either PCIe or SDIO for WiFi and USB or
UART for BT. Currently the driver only supports PCIe and UART.
Add power sequencing targets for SDIO and USB. To avoid adding a
complicated dependency tree, rename the existing power sequencing units
"pcie" and "uart" to "wifi" and "bt". The existing target names are left
untouched. The new "sdio" and "usb" targets just point to the renamed
"wifi" and "bt" units.
Signed-off-by: Chen-Yu Tsai <wenst@chromium.org>
---
drivers/power/sequencing/pwrseq-pcie-m2.c | 41 +++++++++++++++--------
1 file changed, 27 insertions(+), 14 deletions(-)
diff --git a/drivers/power/sequencing/pwrseq-pcie-m2.c b/drivers/power/sequencing/pwrseq-pcie-m2.c
index c9aed2c02e81..a5585f000ef1 100644
--- a/drivers/power/sequencing/pwrseq-pcie-m2.c
+++ b/drivers/power/sequencing/pwrseq-pcie-m2.c
@@ -62,46 +62,46 @@ static const struct pwrseq_unit_data *pwrseq_pcie_m2_unit_deps[] = {
NULL
};
-static int pwrseq_pci_m2_e_uart_enable(struct pwrseq_device *pwrseq)
+static int pwrseq_pci_m2_e_bt_enable(struct pwrseq_device *pwrseq)
{
struct pwrseq_pcie_m2_ctx *ctx = pwrseq_device_get_drvdata(pwrseq);
return gpiod_set_value_cansleep(ctx->w_disable2_gpio, 0);
}
-static int pwrseq_pci_m2_e_uart_disable(struct pwrseq_device *pwrseq)
+static int pwrseq_pci_m2_e_bt_disable(struct pwrseq_device *pwrseq)
{
struct pwrseq_pcie_m2_ctx *ctx = pwrseq_device_get_drvdata(pwrseq);
return gpiod_set_value_cansleep(ctx->w_disable2_gpio, 1);
}
-static const struct pwrseq_unit_data pwrseq_pcie_m2_e_uart_unit_data = {
- .name = "uart-enable",
+static const struct pwrseq_unit_data pwrseq_pcie_m2_e_bt_unit_data = {
+ .name = "bt-enable",
.deps = pwrseq_pcie_m2_unit_deps,
- .enable = pwrseq_pci_m2_e_uart_enable,
- .disable = pwrseq_pci_m2_e_uart_disable,
+ .enable = pwrseq_pci_m2_e_bt_enable,
+ .disable = pwrseq_pci_m2_e_bt_disable,
};
-static int pwrseq_pci_m2_e_pcie_enable(struct pwrseq_device *pwrseq)
+static int pwrseq_pci_m2_e_wifi_enable(struct pwrseq_device *pwrseq)
{
struct pwrseq_pcie_m2_ctx *ctx = pwrseq_device_get_drvdata(pwrseq);
return gpiod_set_value_cansleep(ctx->w_disable1_gpio, 0);
}
-static int pwrseq_pci_m2_e_pcie_disable(struct pwrseq_device *pwrseq)
+static int pwrseq_pci_m2_e_wifi_disable(struct pwrseq_device *pwrseq)
{
struct pwrseq_pcie_m2_ctx *ctx = pwrseq_device_get_drvdata(pwrseq);
return gpiod_set_value_cansleep(ctx->w_disable1_gpio, 1);
}
-static const struct pwrseq_unit_data pwrseq_pcie_m2_e_pcie_unit_data = {
- .name = "pcie-enable",
+static const struct pwrseq_unit_data pwrseq_pcie_m2_e_wifi_unit_data = {
+ .name = "wifi-enable",
.deps = pwrseq_pcie_m2_unit_deps,
- .enable = pwrseq_pci_m2_e_pcie_enable,
- .disable = pwrseq_pci_m2_e_pcie_disable,
+ .enable = pwrseq_pci_m2_e_wifi_enable,
+ .disable = pwrseq_pci_m2_e_wifi_disable,
};
static const struct pwrseq_unit_data pwrseq_pcie_m2_m_pcie_unit_data = {
@@ -123,13 +123,24 @@ static int pwrseq_pcie_m2_e_pwup_delay(struct pwrseq_device *pwrseq)
static const struct pwrseq_target_data pwrseq_pcie_m2_e_uart_target_data = {
.name = "uart",
- .unit = &pwrseq_pcie_m2_e_uart_unit_data,
+ .unit = &pwrseq_pcie_m2_e_bt_unit_data,
.post_enable = pwrseq_pcie_m2_e_pwup_delay,
};
+static const struct pwrseq_target_data pwrseq_pcie_m2_e_usb_target_data = {
+ .name = "usb",
+ .unit = &pwrseq_pcie_m2_e_bt_unit_data,
+};
+
static const struct pwrseq_target_data pwrseq_pcie_m2_e_pcie_target_data = {
.name = "pcie",
- .unit = &pwrseq_pcie_m2_e_pcie_unit_data,
+ .unit = &pwrseq_pcie_m2_e_wifi_unit_data,
+ .post_enable = pwrseq_pcie_m2_e_pwup_delay,
+};
+
+static const struct pwrseq_target_data pwrseq_pcie_m2_e_sdio_target_data = {
+ .name = "sdio",
+ .unit = &pwrseq_pcie_m2_e_wifi_unit_data,
.post_enable = pwrseq_pcie_m2_e_pwup_delay,
};
@@ -140,7 +151,9 @@ static const struct pwrseq_target_data pwrseq_pcie_m2_m_pcie_target_data = {
static const struct pwrseq_target_data *pwrseq_pcie_m2_e_targets[] = {
&pwrseq_pcie_m2_e_pcie_target_data,
+ &pwrseq_pcie_m2_e_sdio_target_data,
&pwrseq_pcie_m2_e_uart_target_data,
+ &pwrseq_pcie_m2_e_usb_target_data,
NULL
};
--
2.54.0.563.g4f69b47b94-goog
^ permalink raw reply related
* [PATCH RFC 02/12] power: sequencing: pcie-m2: implement port index matching
From: Chen-Yu Tsai @ 2026-05-15 9:01 UTC (permalink / raw)
To: Bartosz Golaszewski, Greg Kroah-Hartman, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
AngeloGioacchino Del Regno
Cc: Chen-Yu Tsai, linux-pm, linux-usb, devicetree, linux-mediatek,
linux-arm-kernel, linux-kernel, Manivannan Sadhasivam
In-Reply-To: <20260515090149.3169406-1-wenst@chromium.org>
For USB connections, the upstream USB (hub) device could be connected to
multiple M.2 E-key slots (or other power sequencer providers) via
different downstream USB ports. The provider needs a way to tell the
different connections apart so that the correct provider is matched.
In the previous change an index parameter was added for the consumer API
and the provider matching function. Implement port matching using the
index parameter. We simply check if the remote endpoint's port number
matches the index.
Signed-off-by: Chen-Yu Tsai <wenst@chromium.org>
---
drivers/power/sequencing/pwrseq-pcie-m2.c | 22 +++++++++++++++++++---
1 file changed, 19 insertions(+), 3 deletions(-)
diff --git a/drivers/power/sequencing/pwrseq-pcie-m2.c b/drivers/power/sequencing/pwrseq-pcie-m2.c
index 16a332f9da7d..c9aed2c02e81 100644
--- a/drivers/power/sequencing/pwrseq-pcie-m2.c
+++ b/drivers/power/sequencing/pwrseq-pcie-m2.c
@@ -165,12 +165,28 @@ static int pwrseq_pcie_m2_match(struct pwrseq_device *pwrseq,
/*
* Traverse the 'remote-endpoint' nodes and check if the remote node's
- * parent matches the OF node of 'dev'.
+ * parent matches the OF node of 'dev' and the port number matches
+ * 'index'.
*/
for_each_endpoint_of_node(ctx->of_node, endpoint) {
+ struct device_node *remote_ep __free(device_node) =
+ of_graph_get_remote_endpoint(endpoint);
struct device_node *remote __free(device_node) =
- of_graph_get_remote_port_parent(endpoint);
- if (remote && (remote == dev_of_node(dev)))
+ of_graph_get_port_parent(remote_ep);
+ struct of_endpoint ep;
+
+ if (!remote)
+ continue;
+ if (remote != dev_of_node(dev))
+ continue;
+ /* For existing users of pwrseq_get(): index = -1 */
+ if (index < 0)
+ return PWRSEQ_MATCH_OK;
+
+ /* Check if the remote endpoint's port matches 'index'. */
+ if (of_graph_parse_endpoint(remote_ep, &ep) < 0)
+ continue;
+ if (ep.port == index)
return PWRSEQ_MATCH_OK;
}
--
2.54.0.563.g4f69b47b94-goog
^ permalink raw reply related
* [PATCH RFC 01/12] power: sequencing: Add index parameter for getting power sequencer
From: Chen-Yu Tsai @ 2026-05-15 9:01 UTC (permalink / raw)
To: Bartosz Golaszewski, Greg Kroah-Hartman, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
AngeloGioacchino Del Regno
Cc: Chen-Yu Tsai, linux-pm, linux-usb, devicetree, linux-mediatek,
linux-arm-kernel, linux-kernel, Manivannan Sadhasivam
In-Reply-To: <20260515090149.3169406-1-wenst@chromium.org>
In some cases more than one sequencer could be associated with a
particular device. For example, a USB hub has multiple downstream ports,
and each port could be connected to a different M.2 E-key slot. In this
case the index would be the port number. The index tells power
sequencers for different slots (connected to different hub ports) apart.
For the consumer API, add a new pwrseq_get_index() for new users. The
original pwrseq_get() now calls pwrseq_get_index() with index = -1.
For the provider API, add the index parameter to the .match function
signature, and tweak all existing providers to match. Actual use of
the new index parameter will be introduced in the next change.
Other than the API change, no functional changes are intended.
Signed-off-by: Chen-Yu Tsai <wenst@chromium.org>
---
drivers/power/sequencing/core.c | 12 ++++++++----
drivers/power/sequencing/pwrseq-pcie-m2.c | 2 +-
drivers/power/sequencing/pwrseq-qcom-wcn.c | 6 +++---
drivers/power/sequencing/pwrseq-thead-gpu.c | 2 +-
include/linux/pwrseq/consumer.h | 6 ++++--
include/linux/pwrseq/provider.h | 2 +-
6 files changed, 18 insertions(+), 12 deletions(-)
diff --git a/drivers/power/sequencing/core.c b/drivers/power/sequencing/core.c
index 14335c4f813e..1a91ee6d416f 100644
--- a/drivers/power/sequencing/core.c
+++ b/drivers/power/sequencing/core.c
@@ -612,6 +612,7 @@ struct pwrseq_match_data {
struct pwrseq_desc *desc;
struct device *dev;
const char *target;
+ int index;
};
static int pwrseq_match_device(struct device *pwrseq_dev, void *data)
@@ -627,7 +628,7 @@ static int pwrseq_match_device(struct device *pwrseq_dev, void *data)
if (!device_is_registered(&pwrseq->dev))
return 0;
- ret = pwrseq->match(pwrseq, match_data->dev);
+ ret = pwrseq->match(pwrseq, match_data->dev, match_data->index);
if (ret == PWRSEQ_NO_MATCH || ret < 0)
return ret;
@@ -655,16 +656,18 @@ static int pwrseq_match_device(struct device *pwrseq_dev, void *data)
}
/**
- * pwrseq_get() - Get the power sequencer associated with this device.
+ * pwrseq_get_index() - Get the power sequencer associated with this device.
* @dev: Device for which to get the sequencer.
* @target: Name of the target exposed by the sequencer this device wants to
* reach.
+ * @index: Index of the sequencer associated with the device.
*
* Returns:
* New power sequencer descriptor for use by the consumer driver or ERR_PTR()
* on failure.
*/
-struct pwrseq_desc *pwrseq_get(struct device *dev, const char *target)
+struct pwrseq_desc *pwrseq_get_index(struct device *dev, const char *target,
+ int index)
{
struct pwrseq_match_data match_data;
int ret;
@@ -676,6 +679,7 @@ struct pwrseq_desc *pwrseq_get(struct device *dev, const char *target)
match_data.desc = desc;
match_data.dev = dev;
match_data.target = target;
+ match_data.index = index;
guard(rwsem_read)(&pwrseq_sem);
@@ -689,7 +693,7 @@ struct pwrseq_desc *pwrseq_get(struct device *dev, const char *target)
return_ptr(desc);
}
-EXPORT_SYMBOL_GPL(pwrseq_get);
+EXPORT_SYMBOL_GPL(pwrseq_get_index);
/**
* pwrseq_put() - Release the power sequencer descriptor.
diff --git a/drivers/power/sequencing/pwrseq-pcie-m2.c b/drivers/power/sequencing/pwrseq-pcie-m2.c
index ef69ae268059..16a332f9da7d 100644
--- a/drivers/power/sequencing/pwrseq-pcie-m2.c
+++ b/drivers/power/sequencing/pwrseq-pcie-m2.c
@@ -158,7 +158,7 @@ static const struct pwrseq_pcie_m2_pdata pwrseq_pcie_m2_m_of_data = {
};
static int pwrseq_pcie_m2_match(struct pwrseq_device *pwrseq,
- struct device *dev)
+ struct device *dev, int index)
{
struct pwrseq_pcie_m2_ctx *ctx = pwrseq_device_get_drvdata(pwrseq);
struct device_node *endpoint __free(device_node) = NULL;
diff --git a/drivers/power/sequencing/pwrseq-qcom-wcn.c b/drivers/power/sequencing/pwrseq-qcom-wcn.c
index b55b4317e21b..ac6b34e01c51 100644
--- a/drivers/power/sequencing/pwrseq-qcom-wcn.c
+++ b/drivers/power/sequencing/pwrseq-qcom-wcn.c
@@ -335,7 +335,7 @@ static const char *const pwrseq_wcn3990_vregs[] = {
};
static int pwrseq_qcom_wcn3990_match(struct pwrseq_device *pwrseq,
- struct device *dev);
+ struct device *dev, int index);
static const struct pwrseq_qcom_wcn_pdata pwrseq_wcn3990_of_data = {
.vregs = pwrseq_wcn3990_vregs,
@@ -436,13 +436,13 @@ static int pwrseq_qcom_wcn_match_regulator(struct pwrseq_device *pwrseq,
}
static int pwrseq_qcom_wcn_match(struct pwrseq_device *pwrseq,
- struct device *dev)
+ struct device *dev, int index)
{
return pwrseq_qcom_wcn_match_regulator(pwrseq, dev, "vddaon-supply");
}
static int pwrseq_qcom_wcn3990_match(struct pwrseq_device *pwrseq,
- struct device *dev)
+ struct device *dev, int index)
{
int ret;
diff --git a/drivers/power/sequencing/pwrseq-thead-gpu.c b/drivers/power/sequencing/pwrseq-thead-gpu.c
index a45318b4b2c1..cb7a6ea66c4b 100644
--- a/drivers/power/sequencing/pwrseq-thead-gpu.c
+++ b/drivers/power/sequencing/pwrseq-thead-gpu.c
@@ -115,7 +115,7 @@ static const struct pwrseq_target_data *pwrseq_thead_gpu_targets[] = {
};
static int pwrseq_thead_gpu_match(struct pwrseq_device *pwrseq,
- struct device *dev)
+ struct device *dev, int index)
{
struct pwrseq_thead_gpu_ctx *ctx = pwrseq_device_get_drvdata(pwrseq);
static const char *const clk_names[] = { "core", "sys" };
diff --git a/include/linux/pwrseq/consumer.h b/include/linux/pwrseq/consumer.h
index 7d583b4f266e..d5d57cdb0c8e 100644
--- a/include/linux/pwrseq/consumer.h
+++ b/include/linux/pwrseq/consumer.h
@@ -11,10 +11,12 @@
struct device;
struct pwrseq_desc;
+#define pwrseq_get(dev, target) pwrseq_get_index(dev, target, -1)
+
#if IS_ENABLED(CONFIG_POWER_SEQUENCING)
struct pwrseq_desc * __must_check
-pwrseq_get(struct device *dev, const char *target);
+pwrseq_get_index(struct device *dev, const char *target, int index);
void pwrseq_put(struct pwrseq_desc *desc);
struct pwrseq_desc * __must_check
@@ -26,7 +28,7 @@ int pwrseq_power_off(struct pwrseq_desc *desc);
#else /* CONFIG_POWER_SEQUENCING */
static inline struct pwrseq_desc * __must_check
-pwrseq_get(struct device *dev, const char *target)
+pwrseq_get_index(struct device *dev, const char *target, int index)
{
return ERR_PTR(-ENOSYS);
}
diff --git a/include/linux/pwrseq/provider.h b/include/linux/pwrseq/provider.h
index 33b3d2c2e39d..a2ec6c612c8b 100644
--- a/include/linux/pwrseq/provider.h
+++ b/include/linux/pwrseq/provider.h
@@ -11,7 +11,7 @@ struct module;
struct pwrseq_device;
typedef int (*pwrseq_power_state_func)(struct pwrseq_device *);
-typedef int (*pwrseq_match_func)(struct pwrseq_device *, struct device *);
+typedef int (*pwrseq_match_func)(struct pwrseq_device *, struct device *, int);
#define PWRSEQ_NO_MATCH 0
#define PWRSEQ_MATCH_OK 1
--
2.54.0.563.g4f69b47b94-goog
^ permalink raw reply related
* [PATCH RFC 00/12] arm64: mediatek: Add M.2 E-key slot on Chromebooks
From: Chen-Yu Tsai @ 2026-05-15 9:01 UTC (permalink / raw)
To: Bartosz Golaszewski, Greg Kroah-Hartman, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
AngeloGioacchino Del Regno
Cc: Chen-Yu Tsai, linux-pm, linux-usb, devicetree, linux-mediatek,
linux-arm-kernel, linux-kernel, Manivannan Sadhasivam
Hi everyone,
This series is my attempt at enabling power sequencing for USB to support
the USB connection on M.2 E-key slots. M.2 E-key was enabled in v7.1-rc1
with just PCIe and UART supported [1].
Most of the series is based on next-20260508, while the DT changes also
depend on some other DT cleanup patches I sent [2][3].
Patch 1 reworks the power sequencing framework to allow matching against
different USB ports. The consumer API gains an "index" parameter (which
is the USB port number on the hub), while the provider API is reworked
to pass the index to the matching function of the providing driver.
Patch 2 implements the index matching in the pcie-m2 driver. Matching
only happens when a valid (>= 0) index is given.
Patch 3 reworks the power sequencing targets for the E-key connector in
the pcie-m2 driver to add targets for USB and SDIO. The former is used
later on in this series.
Patch 4 reworks the USB hub driver to return the actual error code from
hub_configure() in hub_probe(). This is needed in the next patch to
correctly return -EPROBE_DEFER.
Patch 5 lets the USB hub driver look for power sequencers for each port.
Currently this only works for M.2 E-key connections, but it could be
extended to cover other cases. It should also make port reset via turning
off the port VBUS work, even when VBUS is not directly controlled by the
hub.
I expect some discussion on this patch, because a) it adds some
OF-specific code into an otherwise generic (core) driver, and
b) it doesn't yet handle USB 2.0 / 3.x shared ports; it ends up powering
on the port twice, which negates the port reset part.
Patch 6 reverts an incorrectly modeled OF graph connection for the
MediaTek XHCI controller.
Patch 7 then adds a proper representation.
Patches 8 through 12 enable the M.2 E-key slots (used for WiFi/BT) and
USB type-A connectors found on MediaTek-based Chromebooks. These are
provided in this series for reference. The USB type-A connector changes,
while not directly related, have overlapping context, and was easier to
include. They were also used to test some extra local changes I tried
to convert the USB A connector from an onboard USB device to a power
sequencing provider.
As this series changes existing power sequencing API, and also uses the
changed API in subsequent patches, I think the best way to merge this
is for Bartosz to take the power sequencing patches and provide an
immutable tag for Greg to merge and then merge the USB patches.
The DT patches can go through the soc tree once all the driver and DT
binding changes are merged.
Thanks
ChenYu
P.S. I'll be at Embedded Recipes if anyone wants to discuss details.
[1] https://lore.kernel.org/all/20260326-pci-m2-e-v7-0-43324a7866e6@oss.qualcomm.com/
[2] https://lore.kernel.org/all/20260505101408.1796563-1-wenst@chromium.org/
[3] https://lore.kernel.org/all/20260514101254.2749300-1-wenst@chromium.org/
Chen-Yu Tsai (12):
power: sequencing: Add index parameter for getting power sequencer
power: sequencing: pcie-m2: implement port index matching
power: sequencing: pcie-m2: Add usb and sdio targets for E-key
connector
usb: hub: Return actual error from hub_configure() in hub_probe()
usb: hub: Power on connected M.2 E-key connectors
Revert "dt-bindings: usb: mediatek,mtk-xhci: Add port for SuperSpeed
EP"
dt-bindings: usb: mediatek,mtk-xhci: Allow ports for USB connections
arm64: dts: mediatek: mt8192-asurada: Add USB type-A connector
arm64: dts: mediatek: mt8192-asurada: Add M.2 E-key slot
arm64: dts: mediatek: mt8195-cherry: Add M.2 E-key slot
arm64: dts: mediatek: mt8195-cherry: Add USB type-A connector
arm64: dts: mediatek: mt8188-geralt: Add WiFi/BT as M.2 E-key slot
.../bindings/usb/mediatek,mtk-xhci.yaml | 17 +-
.../boot/dts/mediatek/mt8188-geralt.dtsi | 93 ++++++++++-
.../boot/dts/mediatek/mt8192-asurada.dtsi | 139 +++++++++++++++--
.../boot/dts/mediatek/mt8195-cherry.dtsi | 146 +++++++++++++++++-
drivers/power/sequencing/core.c | 12 +-
drivers/power/sequencing/pwrseq-pcie-m2.c | 65 +++++---
drivers/power/sequencing/pwrseq-qcom-wcn.c | 6 +-
drivers/power/sequencing/pwrseq-thead-gpu.c | 2 +-
drivers/usb/core/hub.c | 22 ++-
drivers/usb/core/hub.h | 2 +
drivers/usb/core/port.c | 54 ++++++-
include/linux/pwrseq/consumer.h | 6 +-
include/linux/pwrseq/provider.h | 2 +-
13 files changed, 508 insertions(+), 58 deletions(-)
--
2.54.0.563.g4f69b47b94-goog
^ permalink raw reply
* Re: [PATCH v2 16/16] MAINTAINERS: add MediaTek mt6323 PMIC thermal driver maintainer
From: Roman Vivchar @ 2026-05-15 8:38 UTC (permalink / raw)
To: Krzysztof Kozlowski, AngeloGioacchino Del Regno, Matthias Brugger
Cc: Jonathan Cameron, David Lechner, Nuno Sá, Andy Shevchenko,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Sen Chu,
Sean Wang, Macpaul Lin, Lee Jones, Srinivas Kandagatla,
Rafael J. Wysocki, Daniel Lezcano, Zhang Rui, Lukasz Luba,
linux-iio, devicetree, linux-kernel, linux-arm-kernel,
linux-mediatek, linux-pm, Ben Grisdale
In-Reply-To: <20260514-sweet-electric-buffalo-841c18@quoll>
Hi Krzysztof,
On Thursday, May 14th, 2026 at 4:03 PM, Krzysztof Kozlowski <krzk@kernel.org> wrote:
> On Tue, May 12, 2026 at 08:18:30AM +0300, Roman Vivchar wrote:
...
> >
> > +MEDIATEK PMIC THERMAL DRIVER
> > +M: Roman Vivchar <rva333@protonmail.com>
> > +S: Odd Fixes
>
> Odd Fixes means driver is half-abandonded, so please explain in the
> commit msg why you add yourself as maintainer but not really committed.
> Such entry makes more sense for subsystems, but if individual driver has
> odd-fixes stage, shouldn't we just remove this maintainer entry? If so,
> why adding it in the first place?
That is a fair point. As an individual contributor, I'm hesitant to use
"Maintained" indefinitely, but I understand that "Odd Fixes" for a new
driver is not the best idea either.
If no one else can take it, I'll change the status to "Maintained" for
v3, but I want to see if there's a more sustainable long-term home for
the drivers first.
Angelo, Matthias:
Since the patch series is about MediaTek PMIC drivers, would you be
open for taking drivers under "ARM/Mediatek SoC support" entry?
Or is there someone at MediaTek who might be interested in this?
Best regards,
Roman
^ permalink raw reply
* Re: [PATCH v1] ufs: core: decouple CQE processing from spinlock critical section
From: Peter Wang (王信友) @ 2026-05-15 8:13 UTC (permalink / raw)
To: linux-scsi@vger.kernel.org, jejb@linux.ibm.com,
avri.altman@sandisk.com, bvanassche@acm.org,
alim.akhtar@samsung.com, martin.petersen@oracle.com
Cc: quic_asutoshd@guicinc.com, Alice Chao (趙珮均),
Eddie Huang (黃智傑),
CC Chou (周志杰),
Ed Tsai (蔡宗軒), wsd_upstream,
Chaotian Jing (井朝天),
Chun-Hung Wu (巫駿宏),
Naomi Chu (朱詠田),
linux-mediatek@lists.infradead.org,
Tun-yu Yu (游敦聿), quic_cang@guicinc.com,
Light Hsieh (謝明燈)
In-Reply-To: <382f6d79-c877-4dc8-813b-ee91ac5489f9@acm.org>
On Thu, 2026-05-14 at 09:22 -0700, Bart Van Assche wrote:
> On 5/14/26 1:26 AM, peter.wang@mediatek.com wrote:
> > 4. In both ufshcd_mcq_compl_all_cqes_lock() and
> > ufshcd_mcq_poll_cqe_lock(), snapshot the starting CQE pointer
> > before
> > advancing the head slot under the spinlock, then process the
> > collected
> > CQEs after releasing the lock using the new helper.
>
> This can't work reliably. ufshcd_mcq_poll_cqe_lock() may be called
> concurrently from different CPU cores, e.g. from a UFS completion
> interrupt and from ufshcd_poll(). Processing CQEs without holding
> hwq->cq_lock may lead to overwriting of CQEs before these have been
> processed.
>
> Thanks,
>
> Bart.
Hi Bart,
This is not an issue because the CQ head is protected by cq_lock.
Only the CQEs from head to tail will be processed by ufshcd_poll
or the ISR. The main difference is that these CQEs will be
processed later, without holding the cq_lock.
Thanks
Peter
^ permalink raw reply
* [PATCH] PCI: mediatek: Fix operator precedence in PCIE_FTS_NUM_L0 macro
From: lirongqing @ 2026-05-15 0:55 UTC (permalink / raw)
To: Ryder Lee, Jianjun Wang, Lorenzo Pieralisi,
Krzysztof Wilczyński, Manivannan Sadhasivam, Rob Herring,
Bjorn Helgaas, Matthias Brugger, AngeloGioacchino Del Regno,
linux-pci, linux-mediatek, linux-arm-kernel
Cc: Li RongQing
From: Li RongQing <lirongqing@baidu.com>
The original PCIE_FTS_NUM_L0(x) macro was buggy due to improper operator
precedence, where ((x) & 0xff << 8) was evaluated as ((x) & 0xff00).
Instead of just fixing the parentheses, use the standard FIELD_PREP()
macro. This makes the code more robust by automatically handling masks
and shifts, while also adding compile-time type and range checking to
ensure the value fits within PCIE_FTS_NUM_MASK.
Fixes: 637cfacae96f ("PCI: mediatek: Add MediaTek PCIe host controller support")
Signed-off-by: Li RongQing <lirongqing@baidu.com>
---
drivers/pci/controller/pcie-mediatek.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/pci/controller/pcie-mediatek.c b/drivers/pci/controller/pcie-mediatek.c
index 7572252..00f0e29 100644
--- a/drivers/pci/controller/pcie-mediatek.c
+++ b/drivers/pci/controller/pcie-mediatek.c
@@ -61,7 +61,7 @@
/* MediaTek specific configuration registers */
#define PCIE_FTS_NUM 0x70c
#define PCIE_FTS_NUM_MASK GENMASK(15, 8)
-#define PCIE_FTS_NUM_L0(x) ((x) & 0xff << 8)
+#define PCIE_FTS_NUM_L0(x) FIELD_PREP(PCIE_FTS_NUM_MASK, x)
#define PCIE_FC_CREDIT 0x73c
#define PCIE_FC_CREDIT_MASK (GENMASK(31, 31) | GENMASK(28, 16))
--
2.9.4
^ permalink raw reply related
* Re: [PATCH] PCI: mediatek: Fix operator precedence in PCIE_FTS_NUM_L0 macro
From: Krzysztof Wilczyński @ 2026-05-15 1:27 UTC (permalink / raw)
To: lirongqing
Cc: Ryder Lee, Jianjun Wang, Lorenzo Pieralisi, Manivannan Sadhasivam,
Rob Herring, Bjorn Helgaas, Matthias Brugger,
AngeloGioacchino Del Regno, linux-pci, linux-mediatek,
linux-arm-kernel
In-Reply-To: <20260515005552.2343-1-lirongqing@baidu.com>
Hello,
> The original PCIE_FTS_NUM_L0(x) macro was buggy due to improper operator
> precedence, where ((x) & 0xff << 8) was evaluated as ((x) & 0xff00).
>
> Instead of just fixing the parentheses, use the standard FIELD_PREP()
> macro. This makes the code more robust by automatically handling masks
> and shifts, while also adding compile-time type and range checking to
> ensure the value fits within PCIE_FTS_NUM_MASK.
>
> Fixes: 637cfacae96f ("PCI: mediatek: Add MediaTek PCIe host controller support")
> Signed-off-by: Li RongQing <lirongqing@baidu.com>
> ---
> drivers/pci/controller/pcie-mediatek.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/pci/controller/pcie-mediatek.c b/drivers/pci/controller/pcie-mediatek.c
> index 7572252..00f0e29 100644
> --- a/drivers/pci/controller/pcie-mediatek.c
> +++ b/drivers/pci/controller/pcie-mediatek.c
> @@ -61,7 +61,7 @@
> /* MediaTek specific configuration registers */
> #define PCIE_FTS_NUM 0x70c
> #define PCIE_FTS_NUM_MASK GENMASK(15, 8)
> -#define PCIE_FTS_NUM_L0(x) ((x) & 0xff << 8)
> +#define PCIE_FTS_NUM_L0(x) FIELD_PREP(PCIE_FTS_NUM_MASK, x)
Aww. Nice catch! Thank you for fixing this!
Happy to offer:
Reviewed-by: Krzysztof Wilczyński <kwilczynski@kernel.org>
All the best,
Krzysztof
^ permalink raw reply
* [PATCH] wifi: mt76: Use IS_ERR() check for mt76_register_debugfs_fops()
From: Ingyu Jang @ 2026-05-14 19:32 UTC (permalink / raw)
To: Felix Fietkau, Lorenzo Bianconi, Ryder Lee
Cc: Shayne Chen, Sean Wang, Matthias Brugger,
AngeloGioacchino Del Regno, linux-wireless, linux-arm-kernel,
linux-mediatek, linux-kernel
mt76_register_debugfs_fops() returns the dentry from
debugfs_create_dir(), which yields an error pointer on failure and
never NULL. The NULL checks in the per-chip *_init_debugfs() helpers
are therefore unreachable, and on a real failure the ERR_PTR would
be returned to callers as a valid pointer.
Use IS_ERR() and propagate the actual error via PTR_ERR() in
mt7615/mt7915/mt7921/mt7925/mt7996.
Signed-off-by: Ingyu Jang <ingyujang25@korea.ac.kr>
---
drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c | 4 ++--
drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c | 4 ++--
drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c | 4 ++--
drivers/net/wireless/mediatek/mt76/mt7925/debugfs.c | 4 ++--
drivers/net/wireless/mediatek/mt76/mt7996/debugfs.c | 4 ++--
5 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c
index 0f7b20152279c..5c3646a67e4b7 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c
@@ -550,8 +550,8 @@ int mt7615_init_debugfs(struct mt7615_dev *dev)
struct dentry *dir;
dir = mt76_register_debugfs_fops(&dev->mphy, &fops_regval);
- if (!dir)
- return -ENOMEM;
+ if (IS_ERR(dir))
+ return PTR_ERR(dir);
if (is_mt7615(&dev->mt76))
debugfs_create_devm_seqfile(dev->mt76.dev, "xmit-queues", dir,
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c
index 26ed3745af43e..f62a17c8958ac 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c
@@ -1296,8 +1296,8 @@ int mt7915_init_debugfs(struct mt7915_phy *phy)
struct dentry *dir;
dir = mt76_register_debugfs_fops(phy->mt76, NULL);
- if (!dir)
- return -ENOMEM;
+ if (IS_ERR(dir))
+ return PTR_ERR(dir);
debugfs_create_file("muru_debug", 0600, dir, dev, &fops_muru_debug);
debugfs_create_file("muru_stats", 0400, dir, phy,
&mt7915_muru_stats_fops);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c
index 4333005b3ad95..4da339867b6a7 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c
@@ -266,8 +266,8 @@ int mt7921_init_debugfs(struct mt792x_dev *dev)
struct dentry *dir;
dir = mt76_register_debugfs_fops(&dev->mphy, &fops_regval);
- if (!dir)
- return -ENOMEM;
+ if (IS_ERR(dir))
+ return PTR_ERR(dir);
if (mt76_is_mmio(&dev->mt76))
debugfs_create_devm_seqfile(dev->mt76.dev, "xmit-queues",
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7925/debugfs.c
index e2498659c884e..01aa4a1071fdd 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/debugfs.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/debugfs.c
@@ -291,8 +291,8 @@ int mt7925_init_debugfs(struct mt792x_dev *dev)
struct dentry *dir;
dir = mt76_register_debugfs_fops(&dev->mphy, &fops_regval);
- if (!dir)
- return -ENOMEM;
+ if (IS_ERR(dir))
+ return PTR_ERR(dir);
if (mt76_is_mmio(&dev->mt76))
debugfs_create_devm_seqfile(dev->mt76.dev, "xmit-queues",
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7996/debugfs.c
index 34af800964d11..63cd490977106 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/debugfs.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/debugfs.c
@@ -875,8 +875,8 @@ int mt7996_init_debugfs(struct mt7996_dev *dev)
struct dentry *dir;
dir = mt76_register_debugfs_fops(&dev->mphy, NULL);
- if (!dir)
- return -ENOMEM;
+ if (IS_ERR(dir))
+ return PTR_ERR(dir);
debugfs_create_file("hw-queues", 0400, dir, dev,
&mt7996_hw_queues_fops);
--
2.34.1
^ permalink raw reply related
* Re: [PATCH v2 1/2] dt-bindings: arm64: dts: airoha: Add an7583 entry
From: Conor Dooley @ 2026-05-14 18:09 UTC (permalink / raw)
To: Lorenzo Bianconi
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Felix Fietkau,
John Crispin, Matthias Brugger, AngeloGioacchino Del Regno,
Christian Marangi, devicetree, linux-arm-kernel, linux-mediatek
In-Reply-To: <20260513-airoha-7583-v2-1-ee0d82b37ce7@kernel.org>
[-- Attachment #1: Type: text/plain, Size: 75 bytes --]
Acked-by: Conor Dooley <conor.dooley@microchip.com>
pw-bot: not-applicable
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply
* [PATCH] Bluetooth: btmtk: Fix FUNC_CTRL parsing for devices with zero-length payloads
From: Shivam Kalra via B4 Relay @ 2026-05-14 17:48 UTC (permalink / raw)
To: Marcel Holtmann, Luiz Augusto von Dentz, Matthias Brugger,
AngeloGioacchino Del Regno, Tristan Madani
Cc: Luiz Augusto von Dentz, linux-bluetooth, linux-kernel,
linux-arm-kernel, linux-mediatek, stable, Shivam Kalra
From: Shivam Kalra <shivamkalra98@zohomail.in>
Commit 634a4408c061 ("Bluetooth: btmtk: validate WMT event SKB length
before struct access") added strict SKB length checks to prevent OOB
memory reads when parsing WMT events.
However, when enabling the protocol (flag = 0), the MT7922 returns a WMT
event with a zero-length payload (skb->len == 7), omitting the 2-byte
status field entirely.
The strict sizeof() check unconditionally enforced the presence of the
status field for all BTMTK_WMT_FUNC_CTRL events. This caused the driver
to reject these payload-less responses with -EINVAL, failing Bluetooth
initialization ("Failed to send wmt func ctrl (-22)").
Fix this by making skb_pull_data() conditional: if the status payload is
present, parse it as before; if omitted, default to BTMTK_WMT_ON_UNDONE.
This restores the pre-regression initialization behavior while
maintaining the memory safety bounds of the previous patch.
Fixes: 634a4408c061 ("Bluetooth: btmtk: validate WMT event SKB length before struct access")
Closes: https://bugzilla.kernel.org/show_bug.cgi?id=221511
Cc: stable@vger.kernel.org
Signed-off-by: Shivam Kalra <shivamkalra98@zohomail.in>
---
Tested on a laptop with a single MediaTek MT7922 (USB ID 0489:e0e0)
Bluetooth controller. Before this patch, Bluetooth initialization failed
with "Failed to send wmt func ctrl (-22)" on every boot. After applying
this patch, initialization succeeds reliably.
This regression is also reported by other users on the kernel bug
tracker [1].
Note: btmtksdio.c and btmtkuart.c have similar FUNC_CTRL parsing code
but were not modified by the original commit 634a4408c061, so they are
not affected by this regression and do not require changes.
[1] https://bugzilla.kernel.org/show_bug.cgi?id=221511
---
drivers/bluetooth/btmtk.c | 24 ++++++++++++------------
1 file changed, 12 insertions(+), 12 deletions(-)
diff --git a/drivers/bluetooth/btmtk.c b/drivers/bluetooth/btmtk.c
index f70c1b0f8990..026e5a76b086 100644
--- a/drivers/bluetooth/btmtk.c
+++ b/drivers/bluetooth/btmtk.c
@@ -717,19 +717,19 @@ static int btmtk_usb_hci_wmt_sync(struct hci_dev *hdev,
status = BTMTK_WMT_PATCH_DONE;
break;
case BTMTK_WMT_FUNC_CTRL:
- if (!skb_pull_data(data->evt_skb,
- sizeof(wmt_evt_funcc->status))) {
- err = -EINVAL;
- goto err_free_skb;
- }
-
- wmt_evt_funcc = (struct btmtk_hci_wmt_evt_funcc *)wmt_evt;
- if (be16_to_cpu(wmt_evt_funcc->status) == 0x404)
- status = BTMTK_WMT_ON_DONE;
- else if (be16_to_cpu(wmt_evt_funcc->status) == 0x420)
- status = BTMTK_WMT_ON_PROGRESS;
- else
+ if (skb_pull_data(data->evt_skb,
+ sizeof(wmt_evt_funcc->status))) {
+ wmt_evt_funcc =
+ (struct btmtk_hci_wmt_evt_funcc *)wmt_evt;
+ if (be16_to_cpu(wmt_evt_funcc->status) == 0x404)
+ status = BTMTK_WMT_ON_DONE;
+ else if (be16_to_cpu(wmt_evt_funcc->status) == 0x420)
+ status = BTMTK_WMT_ON_PROGRESS;
+ else
+ status = BTMTK_WMT_ON_UNDONE;
+ } else {
status = BTMTK_WMT_ON_UNDONE;
+ }
break;
case BTMTK_WMT_PATCH_DWNLD:
if (wmt_evt->whdr.flag == 2)
---
base-commit: 5d6919055dec134de3c40167a490f33c74c12581
change-id: 20260514-bluetooh-fix-mt7922-92bbbeff229b
Best regards,
--
Shivam Kalra <shivamkalra98@zohomail.in>
^ permalink raw reply related
* Re: [PATCH v1] ufs: core: decouple CQE processing from spinlock critical section
From: Bart Van Assche @ 2026-05-14 16:22 UTC (permalink / raw)
To: peter.wang, linux-scsi, martin.petersen, avri.altman, alim.akhtar,
jejb
Cc: wsd_upstream, linux-mediatek, chun-hung.wu, alice.chao, cc.chou,
chaotian.jing, tun-yu.yu, eddie.huang, naomi.chu, ed.tsai,
quic_cang, quic_asutoshd, light.hsieh
In-Reply-To: <20260514082906.58593-1-peter.wang@mediatek.com>
On 5/14/26 1:26 AM, peter.wang@mediatek.com wrote:
> 4. In both ufshcd_mcq_compl_all_cqes_lock() and
> ufshcd_mcq_poll_cqe_lock(), snapshot the starting CQE pointer before
> advancing the head slot under the spinlock, then process the collected
> CQEs after releasing the lock using the new helper.
This can't work reliably. ufshcd_mcq_poll_cqe_lock() may be called
concurrently from different CPU cores, e.g. from a UFS completion
interrupt and from ufshcd_poll(). Processing CQEs without holding
hwq->cq_lock may lead to overwriting of CQEs before these have been
processed.
Thanks,
Bart.
^ permalink raw reply
* Re: [PATCH] phy: mediatek: xsphy: reduce main allocation
From: Vinod Koul @ 2026-05-14 16:18 UTC (permalink / raw)
To: linux-phy, Rosen Penev
Cc: Chunfeng Yun, Neil Armstrong, Matthias Brugger,
AngeloGioacchino Del Regno, Kees Cook, Gustavo A. R. Silva,
linux-arm-kernel, linux-mediatek, linux-kernel, linux-hardening
In-Reply-To: <20260304043420.14151-1-rosenp@gmail.com>
On Tue, 03 Mar 2026 20:34:20 -0800, Rosen Penev wrote:
> Instead of kzalloc and kcalloc, we can use a flex array to reduce to a
> single allocation.
>
> Also added __counted_by() for extra possible analysis.
>
>
Applied, thanks!
[1/1] phy: mediatek: xsphy: reduce main allocation
commit: fd6cd05ceabdf67635a4cef5145f79d1217bf11b
Best regards,
--
~Vinod
^ permalink raw reply
* Re: [PATCH] dt-bindings: Consolidate "sram" property definition
From: Shah, Tanmay @ 2026-05-14 15:18 UTC (permalink / raw)
To: Rob Herring (Arm), Liu Ying, Philipp Zabel, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter,
Krzysztof Kozlowski, Conor Dooley, Frank Li, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam, Rob Clark, Sean Paul,
Konrad Dybcio, Akhil P Oommen, Dmitry Baryshkov, Abhinav Kumar,
Jessica Zhang, Marijn Suijten, Vinod Koul, Nas Chung, Jackson Lee,
Mauro Carvalho Chehab, Mirela Rabulea, Detlev Casanova,
Ezequiel Garcia, Heiko Stuebner, Hugues Fruchet, Alain Volmat,
Maxime Coquelin, Alexandre Torgue, Andrew Lunn, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, MD Danish Anwar,
Roger Quadros, Parvathi Pudi, Mohan Reddy Putluru,
Bjorn Andersson, Mathieu Poirier, Neil Armstrong, Kevin Hilman,
Jerome Brunet, Martin Blumenstingl, Michal Simek, Mark Brown,
Matthias Brugger, AngeloGioacchino Del Regno, Linus Walleij,
Lorenzo Bianconi, Felix Fietkau, Andrew F. Davis, Hussain Khaja,
Suman Anna, Ben Levinsky, Tanmay Shah, Erwan Leray,
Fabrice Gasnier
Cc: Roger Quadros, dri-devel, devicetree, imx, linux-arm-kernel,
linux-kernel, linux-arm-msm, freedreno, dmaengine, linux-media,
linux-rockchip, linux-stm32, netdev, linux-remoteproc,
linux-amlogic, linux-spi, linux-mediatek
In-Reply-To: <20260511165942.2774868-1-robh@kernel.org>
Reviewed-by: Tanmay Shah <tanmay.shah@amd.com>
On 5/11/2026 11:59 AM, Rob Herring (Arm) wrote:
> The "sram" property has become a de facto standard property, so create a
> common schema for it and drop all the duplicated definitions.
>
> Signed-off-by: Rob Herring (Arm) <robh@kernel.org>
> ---
> .../imx/fsl,imx8qxp-dc-command-sequencer.yaml | 2 +-
> .../devicetree/bindings/display/msm/gpu.yaml | 6 +----
> .../bindings/dma/stericsson,dma40.yaml | 8 ++----
> .../bindings/media/cnm,wave521c.yaml | 2 +-
> .../bindings/media/nxp,imx8-jpeg.yaml | 6 ++---
> .../bindings/media/rockchip,vdec.yaml | 5 ++--
> .../bindings/media/st,stm32-dcmi.yaml | 6 ++---
> .../devicetree/bindings/net/mediatek,net.yaml | 3 +--
> .../bindings/net/ti,icssg-prueth.yaml | 2 +-
> .../bindings/net/ti,icssm-prueth.yaml | 2 +-
> .../remoteproc/amlogic,meson-mx-ao-arc.yaml | 7 +----
> .../bindings/remoteproc/ti,k3-dsp-rproc.yaml | 8 ------
> .../bindings/remoteproc/ti,k3-r5f-rproc.yaml | 8 ------
> .../remoteproc/xlnx,zynqmp-r5fss.yaml | 9 +------
> .../devicetree/bindings/spi/st,stm32-spi.yaml | 10 +++----
> .../bindings/sram/sram-consumer.yaml | 26 +++++++++++++++++++
> 16 files changed, 48 insertions(+), 62 deletions(-)
> create mode 100644 Documentation/devicetree/bindings/sram/sram-consumer.yaml
>
> diff --git a/Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-command-sequencer.yaml b/Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-command-sequencer.yaml
> index 27118f4c0d28..fd095e5742c5 100644
> --- a/Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-command-sequencer.yaml
> +++ b/Documentation/devicetree/bindings/display/imx/fsl,imx8qxp-dc-command-sequencer.yaml
> @@ -41,7 +41,7 @@ properties:
> - const: sw3
>
> sram:
> - $ref: /schemas/types.yaml#/definitions/phandle
> + maxItems: 1
> description: phandle pointing to the mmio-sram device node
>
> required:
> diff --git a/Documentation/devicetree/bindings/display/msm/gpu.yaml b/Documentation/devicetree/bindings/display/msm/gpu.yaml
> index 04b2328903ca..358759fad8dc 100644
> --- a/Documentation/devicetree/bindings/display/msm/gpu.yaml
> +++ b/Documentation/devicetree/bindings/display/msm/gpu.yaml
> @@ -84,13 +84,9 @@ properties:
> maxItems: 64
>
> sram:
> - $ref: /schemas/types.yaml#/definitions/phandle-array
> minItems: 1
> maxItems: 4
> - items:
> - maxItems: 1
> - description: |
> - phandles to one or more reserved on-chip SRAM regions.
> + description:
> phandle to the On Chip Memory (OCMEM) that's present on some a3xx and
> a4xx Snapdragon SoCs. See
> Documentation/devicetree/bindings/sram/qcom,ocmem.yaml
> diff --git a/Documentation/devicetree/bindings/dma/stericsson,dma40.yaml b/Documentation/devicetree/bindings/dma/stericsson,dma40.yaml
> index 607da11e7baa..d8f92838f4c9 100644
> --- a/Documentation/devicetree/bindings/dma/stericsson,dma40.yaml
> +++ b/Documentation/devicetree/bindings/dma/stericsson,dma40.yaml
> @@ -136,13 +136,9 @@ properties:
> maxItems: 1
>
> sram:
> - $ref: /schemas/types.yaml#/definitions/phandle-array
> - description: A phandle array with inner size 1 (no arg cells).
> - First phandle is the LCPA (Logical Channel Parameter Address) memory.
> - Second phandle is the LCLA (Logical Channel Link base Address) memory.
> - maxItems: 2
> items:
> - maxItems: 1
> + - description: LCPA (Logical Channel Parameter Address) memory.
> + - description: LCLA (Logical Channel Link base Address) memory.
>
> memcpy-channels:
> $ref: /schemas/types.yaml#/definitions/uint32-array
> diff --git a/Documentation/devicetree/bindings/media/cnm,wave521c.yaml b/Documentation/devicetree/bindings/media/cnm,wave521c.yaml
> index 6a11c1d11fb5..6cd33dfd095d 100644
> --- a/Documentation/devicetree/bindings/media/cnm,wave521c.yaml
> +++ b/Documentation/devicetree/bindings/media/cnm,wave521c.yaml
> @@ -37,7 +37,7 @@ properties:
> maxItems: 1
>
> sram:
> - $ref: /schemas/types.yaml#/definitions/phandle
> + maxItems: 1
> description:
> The VPU uses the SRAM to store some of the reference data instead of
> storing it on DMA memory. It is mainly used for the purpose of reducing
> diff --git a/Documentation/devicetree/bindings/media/nxp,imx8-jpeg.yaml b/Documentation/devicetree/bindings/media/nxp,imx8-jpeg.yaml
> index 18cc6315a821..6ba668aa633d 100644
> --- a/Documentation/devicetree/bindings/media/nxp,imx8-jpeg.yaml
> +++ b/Documentation/devicetree/bindings/media/nxp,imx8-jpeg.yaml
> @@ -56,10 +56,10 @@ properties:
> maxItems: 5 # Wrapper and 4 slots
>
> sram:
> - $ref: /schemas/types.yaml#/definitions/phandle
> + maxItems: 1
> description:
> - Optional phandle to a reserved on-chip SRAM regions. The SRAM can
> - be used for descriptor storage, which may improve bus utilization.
> + The SRAM can be used for descriptor storage, which may improve bus
> + utilization.
>
> required:
> - compatible
> diff --git a/Documentation/devicetree/bindings/media/rockchip,vdec.yaml b/Documentation/devicetree/bindings/media/rockchip,vdec.yaml
> index 42022401d0ff..4f38a0ef29d8 100644
> --- a/Documentation/devicetree/bindings/media/rockchip,vdec.yaml
> +++ b/Documentation/devicetree/bindings/media/rockchip,vdec.yaml
> @@ -91,9 +91,8 @@ properties:
> maxItems: 1
>
> sram:
> - $ref: /schemas/types.yaml#/definitions/phandle
> - description: |
> - phandle to a reserved on-chip SRAM regions.
> + maxItems: 1
> + description:
> Some SoCs, like rk3588 provide on-chip SRAM to store temporary
> buffers during decoding.
>
> diff --git a/Documentation/devicetree/bindings/media/st,stm32-dcmi.yaml b/Documentation/devicetree/bindings/media/st,stm32-dcmi.yaml
> index d9fbb90b0977..7c2ddd27780f 100644
> --- a/Documentation/devicetree/bindings/media/st,stm32-dcmi.yaml
> +++ b/Documentation/devicetree/bindings/media/st,stm32-dcmi.yaml
> @@ -47,10 +47,10 @@ properties:
> maxItems: 1
>
> sram:
> - $ref: /schemas/types.yaml#/definitions/phandle
> + maxItems: 1
> description:
> - phandle to a reserved SRAM region which is used as temporary
> - storage memory between DMA and MDMA engines.
> + SRAM region which is used as temporary storage memory between DMA and
> + MDMA engines.
>
> port:
> $ref: /schemas/graph.yaml#/$defs/port-base
> diff --git a/Documentation/devicetree/bindings/net/mediatek,net.yaml b/Documentation/devicetree/bindings/net/mediatek,net.yaml
> index cc346946291a..6bbd83c6aaf7 100644
> --- a/Documentation/devicetree/bindings/net/mediatek,net.yaml
> +++ b/Documentation/devicetree/bindings/net/mediatek,net.yaml
> @@ -67,8 +67,7 @@ properties:
> - const: ppe
>
> sram:
> - $ref: /schemas/types.yaml#/definitions/phandle
> - description: phandle to mmio SRAM
> + maxItems: 1
>
> mediatek,ethsys:
> $ref: /schemas/types.yaml#/definitions/phandle
> diff --git a/Documentation/devicetree/bindings/net/ti,icssg-prueth.yaml b/Documentation/devicetree/bindings/net/ti,icssg-prueth.yaml
> index c296e5711848..883033b19b8f 100644
> --- a/Documentation/devicetree/bindings/net/ti,icssg-prueth.yaml
> +++ b/Documentation/devicetree/bindings/net/ti,icssg-prueth.yaml
> @@ -21,7 +21,7 @@ properties:
> - ti,am654-sr1-icssg-prueth # for AM65x SoC family, SR1.0
>
> sram:
> - $ref: /schemas/types.yaml#/definitions/phandle
> + maxItems: 1
> description:
> phandle to MSMC SRAM node
>
> diff --git a/Documentation/devicetree/bindings/net/ti,icssm-prueth.yaml b/Documentation/devicetree/bindings/net/ti,icssm-prueth.yaml
> index a98ad45ca66f..9370c43bc66a 100644
> --- a/Documentation/devicetree/bindings/net/ti,icssm-prueth.yaml
> +++ b/Documentation/devicetree/bindings/net/ti,icssm-prueth.yaml
> @@ -24,7 +24,7 @@ properties:
> - ti,am3359-prueth # for AM33x SoC family
>
> sram:
> - $ref: /schemas/types.yaml#/definitions/phandle
> + maxItems: 1
> description:
> phandle to OCMC SRAM node
>
> diff --git a/Documentation/devicetree/bindings/remoteproc/amlogic,meson-mx-ao-arc.yaml b/Documentation/devicetree/bindings/remoteproc/amlogic,meson-mx-ao-arc.yaml
> index 76e8ca44906a..3f710433e937 100644
> --- a/Documentation/devicetree/bindings/remoteproc/amlogic,meson-mx-ao-arc.yaml
> +++ b/Documentation/devicetree/bindings/remoteproc/amlogic,meson-mx-ao-arc.yaml
> @@ -48,12 +48,7 @@ properties:
> minItems: 1
>
> sram:
> - $ref: /schemas/types.yaml#/definitions/phandle
> - description:
> - phandles to a reserved SRAM region which is used as the memory of
> - the ARC core. The region should be defined as child nodes of the
> - AHB SRAM node as per the generic bindings in
> - Documentation/devicetree/bindings/sram/sram.yaml
> + maxItems: 1
>
> amlogic,secbus2:
> $ref: /schemas/types.yaml#/definitions/phandle
> diff --git a/Documentation/devicetree/bindings/remoteproc/ti,k3-dsp-rproc.yaml b/Documentation/devicetree/bindings/remoteproc/ti,k3-dsp-rproc.yaml
> index b51bb863d759..8b1ed384ef22 100644
> --- a/Documentation/devicetree/bindings/remoteproc/ti,k3-dsp-rproc.yaml
> +++ b/Documentation/devicetree/bindings/remoteproc/ti,k3-dsp-rproc.yaml
> @@ -75,16 +75,8 @@ properties:
> # --------------------
>
> sram:
> - $ref: /schemas/types.yaml#/definitions/phandle-array
> minItems: 1
> maxItems: 4
> - items:
> - maxItems: 1
> - description: |
> - phandles to one or more reserved on-chip SRAM regions. The regions
> - should be defined as child nodes of the respective SRAM node, and
> - should be defined as per the generic bindings in,
> - Documentation/devicetree/bindings/sram/sram.yaml
>
> allOf:
> - if:
> diff --git a/Documentation/devicetree/bindings/remoteproc/ti,k3-r5f-rproc.yaml b/Documentation/devicetree/bindings/remoteproc/ti,k3-r5f-rproc.yaml
> index 775e9b3a1938..14e6b2f817b3 100644
> --- a/Documentation/devicetree/bindings/remoteproc/ti,k3-r5f-rproc.yaml
> +++ b/Documentation/devicetree/bindings/remoteproc/ti,k3-r5f-rproc.yaml
> @@ -224,16 +224,8 @@ patternProperties:
> at 0x0) or 0 (BTCM at 0x0), default value is 1 if omitted.
>
> sram:
> - $ref: /schemas/types.yaml#/definitions/phandle-array
> minItems: 1
> maxItems: 4
> - items:
> - maxItems: 1
> - description: |
> - phandles to one or more reserved on-chip SRAM regions. The regions
> - should be defined as child nodes of the respective SRAM node, and
> - should be defined as per the generic bindings in,
> - Documentation/devicetree/bindings/sram/sram.yaml
>
> required:
> - compatible
> diff --git a/Documentation/devicetree/bindings/remoteproc/xlnx,zynqmp-r5fss.yaml b/Documentation/devicetree/bindings/remoteproc/xlnx,zynqmp-r5fss.yaml
> index ee63c03949c9..c7d5e58330d6 100644
> --- a/Documentation/devicetree/bindings/remoteproc/xlnx,zynqmp-r5fss.yaml
> +++ b/Documentation/devicetree/bindings/remoteproc/xlnx,zynqmp-r5fss.yaml
> @@ -106,20 +106,13 @@ patternProperties:
> - const: rx
>
> sram:
> - $ref: /schemas/types.yaml#/definitions/phandle-array
> minItems: 1
> maxItems: 8
> - items:
> - maxItems: 1
> - description: |
> + description:
> phandles to one or more reserved on-chip SRAM regions. Other than TCM,
> the RPU can execute instructions and access data from the OCM memory,
> the main DDR memory, and other system memories.
>
> - The regions should be defined as child nodes of the respective SRAM
> - node, and should be defined as per the generic bindings in
> - Documentation/devicetree/bindings/sram/sram.yaml
> -
> memory-region:
> description: |
> List of phandles to the reserved memory regions associated with the
> diff --git a/Documentation/devicetree/bindings/spi/st,stm32-spi.yaml b/Documentation/devicetree/bindings/spi/st,stm32-spi.yaml
> index 472e92974714..6d7d595e4ab3 100644
> --- a/Documentation/devicetree/bindings/spi/st,stm32-spi.yaml
> +++ b/Documentation/devicetree/bindings/spi/st,stm32-spi.yaml
> @@ -89,12 +89,10 @@ properties:
> - const: rxm2m
>
> sram:
> - $ref: /schemas/types.yaml#/definitions/phandle
> - description: |
> - Phandles to a reserved SRAM region which is used as temporary
> - storage memory between DMA and MDMA engines.
> - The region should be defined as child node of the AHB SRAM node
> - as per the generic bindings in Documentation/devicetree/bindings/sram/sram.yaml
> + maxItems: 1
> + description:
> + SRAM region which is used as temporary storage memory between DMA and
> + MDMA engines.
>
> power-domains:
> maxItems: 1
> diff --git a/Documentation/devicetree/bindings/sram/sram-consumer.yaml b/Documentation/devicetree/bindings/sram/sram-consumer.yaml
> new file mode 100644
> index 000000000000..f00087bd2879
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/sram/sram-consumer.yaml
> @@ -0,0 +1,26 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/sram/sram-consumer.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: SRAM Consumers
> +
> +maintainers:
> + - Rob Herring <robh@kernel.org>
> +
> +select: true
> +
> +properties:
> + sram:
> + description:
> + Phandles to one or more reserved on-chip SRAM regions. The regions
> + should be defined as child nodes of the respective SRAM node, and
> + should be defined as per the generic bindings in,
> + Documentation/devicetree/bindings/sram/sram.yaml
> + $ref: /schemas/types.yaml#/definitions/phandle-array
> + items:
> + maxItems: 1
> +
> +additionalProperties: true
> +...
^ permalink raw reply
* [PATCH v7 2/2] PCI: mediatek: Add support for EcoNet EN7528 SoC
From: Caleb James DeLisle @ 2026-05-14 15:13 UTC (permalink / raw)
To: linux-pci
Cc: linux-mips, naseefkm, ryder.lee, helgaas, lpieralisi, kwilczynski,
mani, robh, krzk+dt, conor+dt, matthias.bgg,
angelogioacchino.delregno, ansuelsmth, linux-mediatek, devicetree,
linux-kernel, Caleb James DeLisle
In-Reply-To: <20260514151318.3444959-1-cjd@cjdns.fr>
Add support for the PCIe present on the EcoNet EN7528 (and EN751221) SoCs.
These SoCs have a mix of Gen1 and Gen2 capable ports, but the Gen2 ports
require re-training after startup.
Co-developed-by: Ahmed Naseef <naseefkm@gmail.com>
Signed-off-by: Ahmed Naseef <naseefkm@gmail.com>
Signed-off-by: Caleb James DeLisle <cjd@cjdns.fr>
---
drivers/pci/controller/Kconfig | 2 +-
drivers/pci/controller/pcie-mediatek.c | 155 +++++++++++++++++++++++++
2 files changed, 156 insertions(+), 1 deletion(-)
diff --git a/drivers/pci/controller/Kconfig b/drivers/pci/controller/Kconfig
index 2247709ef6d6..8a3a31b2bc12 100644
--- a/drivers/pci/controller/Kconfig
+++ b/drivers/pci/controller/Kconfig
@@ -209,7 +209,7 @@ config PCI_MVEBU
config PCIE_MEDIATEK
tristate "MediaTek PCIe controller"
- depends on ARCH_AIROHA || ARCH_MEDIATEK || COMPILE_TEST
+ depends on ARCH_AIROHA || ARCH_MEDIATEK || ECONET || COMPILE_TEST
depends on OF
depends on PCI_MSI
select IRQ_MSI_LIB
diff --git a/drivers/pci/controller/pcie-mediatek.c b/drivers/pci/controller/pcie-mediatek.c
index 75722524fe74..3d5e2279286a 100644
--- a/drivers/pci/controller/pcie-mediatek.c
+++ b/drivers/pci/controller/pcie-mediatek.c
@@ -9,11 +9,13 @@
#include <linux/clk.h>
#include <linux/delay.h>
+#include <linux/errno.h>
#include <linux/iopoll.h>
#include <linux/irq.h>
#include <linux/irqchip/chained_irq.h>
#include <linux/irqchip/irq-msi-lib.h>
#include <linux/irqdomain.h>
+#include <linux/kconfig.h>
#include <linux/kernel.h>
#include <linux/mfd/syscon.h>
#include <linux/msi.h>
@@ -77,6 +79,7 @@
#define PCIE_CONF_VEND_ID 0x100
#define PCIE_CONF_DEVICE_ID 0x102
+#define PCIE_CONF_REV_CLASS 0x104
#define PCIE_CONF_CLASS_ID 0x106
#define PCIE_INT_MASK 0x420
@@ -89,6 +92,11 @@
#define MSI_MASK BIT(23)
#define MTK_MSI_IRQS_NUM 32
+#define EN7528_HOST_MODE 0x00804201
+#define EN7528_LINKUP_REG 0x50
+#define EN7528_RC0_LINKUP BIT(1)
+#define EN7528_RC1_LINKUP BIT(2)
+
#define PCIE_AHB_TRANS_BASE0_L 0x438
#define PCIE_AHB_TRANS_BASE0_H 0x43c
#define AHB2PCIE_SIZE(x) ((x) & GENMASK(4, 0))
@@ -148,12 +156,15 @@ struct mtk_pcie_port;
* @MTK_PCIE_FIX_DEVICE_ID: host's device ID needed to be fixed
* @MTK_PCIE_NO_MSI: Bridge has no MSI support, and relies on an external block
* @MTK_PCIE_SKIP_RSTB: Skip calling RSTB bits on PCIe probe
+ * @MTK_PCIE_RETRAIN: Retrain link to bridge after startup because some
+ * Gen2-capable devices start as Gen1.
*/
enum mtk_pcie_quirks {
MTK_PCIE_FIX_CLASS_ID = BIT(0),
MTK_PCIE_FIX_DEVICE_ID = BIT(1),
MTK_PCIE_NO_MSI = BIT(2),
MTK_PCIE_SKIP_RSTB = BIT(3),
+ MTK_PCIE_RETRAIN = BIT(4),
};
/**
@@ -753,6 +764,135 @@ static int mtk_pcie_startup_port_v2(struct mtk_pcie_port *port)
return 0;
}
+static int mtk_pcie_startup_port_en7528(struct mtk_pcie_port *port)
+{
+ struct mtk_pcie *pcie = port->pcie;
+ struct pci_host_bridge *host = pci_host_bridge_from_priv(pcie);
+ struct resource *mem = NULL;
+ struct resource_entry *entry;
+ u32 val, link_mask;
+ int err;
+
+ entry = resource_list_first_type(&host->windows, IORESOURCE_MEM);
+ if (entry)
+ mem = entry->res;
+ if (!mem)
+ return -EINVAL;
+
+ if (!pcie->cfg) {
+ dev_err(pcie->dev, "EN7528: pciecfg syscon not available\n");
+ return -EINVAL;
+ }
+
+ /* Assert all reset signals */
+ writel(0, port->base + PCIE_RST_CTRL);
+
+ /*
+ * Enable PCIe link down reset, if link status changed from link up to
+ * link down, this will reset MAC control registers and configuration
+ * space.
+ */
+ writel(PCIE_LINKDOWN_RST_EN, port->base + PCIE_RST_CTRL);
+
+ msleep(PCIE_T_PVPERL_MS);
+
+ /* De-assert PHY, PE, PIPE, MAC and configuration reset */
+ val = readl(port->base + PCIE_RST_CTRL);
+ val |= PCIE_PHY_RSTB | PCIE_PERSTB | PCIE_PIPE_SRSTB |
+ PCIE_MAC_SRSTB | PCIE_CRSTB;
+ writel(val, port->base + PCIE_RST_CTRL);
+
+ writel(PCIE_CLASS_CODE | PCIE_REVISION_ID,
+ port->base + PCIE_CONF_REV_CLASS);
+ writel(EN7528_HOST_MODE, port->base);
+
+ link_mask = (port->slot == 0) ? EN7528_RC0_LINKUP : EN7528_RC1_LINKUP;
+
+ /* 100ms timeout value should be enough for Gen1/2 training */
+ err = regmap_read_poll_timeout(pcie->cfg, EN7528_LINKUP_REG, val,
+ !!(val & link_mask), 20,
+ PCI_PM_D3COLD_WAIT * USEC_PER_MSEC);
+ if (err) {
+ dev_err(pcie->dev, "EN7528: port%d link timeout\n", port->slot);
+ return -ETIMEDOUT;
+ }
+
+ /* Activate INTx interrupts */
+ val = readl(port->base + PCIE_INT_MASK);
+ val &= ~INTX_MASK;
+ writel(val, port->base + PCIE_INT_MASK);
+
+ if (IS_ENABLED(CONFIG_PCI_MSI))
+ mtk_pcie_enable_msi(port);
+
+ /* Set AHB to PCIe translation windows */
+ val = lower_32_bits(mem->start) |
+ AHB2PCIE_SIZE(fls(resource_size(mem)));
+ writel(val, port->base + PCIE_AHB_TRANS_BASE0_L);
+
+ val = upper_32_bits(mem->start);
+ writel(val, port->base + PCIE_AHB_TRANS_BASE0_H);
+
+ writel(WIN_ENABLE, port->base + PCIE_AXI_WINDOW0);
+
+ if (!IS_BUILTIN(CONFIG_PCIE_MEDIATEK))
+ dev_info(pcie->dev,
+ "module not built-in, Gen2 unavailable even if supported\n");
+
+ return 0;
+}
+
+/**
+ * mtk_pcie_retrain - retrain the root bridge link if needed
+ * @dev: The device, for use in logging
+ * @host: The host bridge which contains the link
+ *
+ * Due to what is likely a hardware bug, some devices (notably EcoNet) start up
+ * as Gen1, and must be retrained once after initial configuration in order to
+ * reach Gen2.
+ *
+ * These devices always self-identify as Gen2 capable, but sometimes the PHY is
+ * only capable of Gen1 operation, and sometimes the PCIe card (e.g. wifi) is
+ * only Gen1 capable. Therefore it is most convenient to retrain every port
+ * after startup.
+ */
+static int mtk_pcie_retrain(struct device *dev, struct pci_host_bridge *host)
+{
+ struct pci_dev *rp;
+ int ret = -ENOENT;
+ u16 lnksta = 0;
+ u32 speed;
+
+ /* Should already have been warned about during startup_port */
+ if (!IS_BUILTIN(CONFIG_PCIE_MEDIATEK))
+ return 0;
+
+ for_each_pci_bridge(rp, host->bus) {
+ if (pci_pcie_type(rp) == PCI_EXP_TYPE_ROOT_PORT)
+ goto found_port;
+ }
+
+ /* Should not happen */
+ return dev_err_probe(dev, ret, "root port not found\n");
+
+found_port:
+
+#if IS_BUILTIN(CONFIG_PCIE_MEDIATEK)
+ ret = pcie_retrain_link(rp, true);
+#endif
+
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to retrain port\n");
+
+ pcie_capability_read_word(rp, PCI_EXP_LNKSTA, &lnksta);
+ speed = lnksta & PCI_EXP_LNKSTA_CLS;
+
+ dev_info(dev, "link retrained, speed %s\n",
+ pci_speed_string(pcie_link_speed[speed]));
+
+ return 0;
+}
+
static void __iomem *mtk_pcie_map_bus(struct pci_bus *bus,
unsigned int devfn, int where)
{
@@ -1149,6 +1289,13 @@ static int mtk_pcie_probe(struct platform_device *pdev)
if (err)
goto put_resources;
+ /*
+ * Ignore error because pci_host_probe() was already called, and in any
+ * case it is possible that the port will still work as Gen1.
+ */
+ if (pcie->soc->quirks & MTK_PCIE_RETRAIN)
+ mtk_pcie_retrain(dev, host);
+
return 0;
put_resources:
@@ -1264,8 +1411,16 @@ static const struct mtk_pcie_soc mtk_pcie_soc_mt7629 = {
.quirks = MTK_PCIE_FIX_CLASS_ID | MTK_PCIE_FIX_DEVICE_ID,
};
+static const struct mtk_pcie_soc mtk_pcie_soc_en7528 = {
+ .ops = &mtk_pcie_ops_v2,
+ .startup = mtk_pcie_startup_port_en7528,
+ .setup_irq = mtk_pcie_setup_irq,
+ .quirks = MTK_PCIE_RETRAIN,
+};
+
static const struct of_device_id mtk_pcie_ids[] = {
{ .compatible = "airoha,an7583-pcie", .data = &mtk_pcie_soc_an7583 },
+ { .compatible = "econet,en7528-pcie", .data = &mtk_pcie_soc_en7528 },
{ .compatible = "mediatek,mt2701-pcie", .data = &mtk_pcie_soc_v1 },
{ .compatible = "mediatek,mt7623-pcie", .data = &mtk_pcie_soc_v1 },
{ .compatible = "mediatek,mt2712-pcie", .data = &mtk_pcie_soc_mt2712 },
--
2.39.5
^ permalink raw reply related
* [PATCH v7 0/2] Add EcoNet EN7528 (and EN751221) PCIe support.
From: Caleb James DeLisle @ 2026-05-14 15:13 UTC (permalink / raw)
To: linux-pci
Cc: linux-mips, naseefkm, ryder.lee, helgaas, lpieralisi, kwilczynski,
mani, robh, krzk+dt, conor+dt, matthias.bgg,
angelogioacchino.delregno, ansuelsmth, linux-mediatek, devicetree,
linux-kernel, Caleb James DeLisle
Changes from v6:
* s/reset/resets/ in .yaml
* s/re-train/retrain/g
* s/Root bridge/Root port/
* If module not builtin, log at mtk_pcie_startup_port_en7528()
* Do not fail if error in mtk_pcie_retrain()
* v6: https://lore.kernel.org/linux-mips/20260513191652.3200607-1-cjd@cjdns.fr
Changes from v5:
* s/errno-base.h/errno.h/
* Breakout mtk_pcie_retrain() into a function
* Use for_each_pci_bridge() to find root bridge
* v5: https://lore.kernel.org/linux-mips/20260413140339.16238-1-cjd@cjdns.fr/
Changes from v4:
* Fixed missing Acked-by
* Rebased to commit 66672af7a095 ("Add linux-next specific files for 20260410")
* v4: https://lore.kernel.org/linux-mips/20260404182854.2183651-1-cjd@cjdns.fr/
Changes from v3:
* s/initiallized/initialized/
* Use PCIE_T_PVPERL_MS for sleep time
* Use PCI_PM_D3COLD_WAIT for startup wait time
* Clarify comment "Activate INTx interrupts"
* Add MTK_PCIE_RETRAIN quirk for devices which require link re-train
* Do not retrain *all* bridges, only root bridge
* Better comments and logging in retraining logic
* v3: https://lore.kernel.org/linux-mips/20260320094212.696671-1-cjd@cjdns.fr/
Changes from v2:
* mediatek-pcie.yaml -> s/power-domain/power-domains/ and drop example
* Patch 3 dropped as it has been applied (Thanks!)
* v2: https://lore.kernel.org/linux-mips/20260316155157.679533-1-cjd@cjdns.fr/
Changes from v1:
* mediatek-pcie.yaml slot0 needs device-type = "pci", fix dt_binding_check
Link: https://lore.kernel.org/linux-mips/177334026016.3889069.9474337544951486443.robh@kernel.org
* v1: https://lore.kernel.org/linux-mips/20260312165332.569772-1-cjd@cjdns.fr/
This was split from a larger PCIe patchset which crossed multiple
subsystems. I'm not labeling this a v3 because it's a new patchset, but
I'm keeping the historical record anyway.
Changes from econet-pcie v2:
* mediatek-pcie.yaml add missing constraints to PCI node properties
* econet-pcie v2: https://lore.kernel.org/linux-mips/20260309131818.74467-1-cjd@cjdns.fr
Changes from econet-pcie v1:
* pcie-mediatek.c Exclude pcie_retrain_link() when building as a module
* econet-pcie v1: https://lore.kernel.org/linux-mips/20260303190948.694783-1-cjd@cjdns.fr/
Caleb James DeLisle (2):
dt-bindings: PCI: mediatek: Add support for EcoNet EN7528
PCI: mediatek: Add support for EcoNet EN7528 SoC
.../bindings/pci/mediatek-pcie.yaml | 26 +++
drivers/pci/controller/Kconfig | 2 +-
drivers/pci/controller/pcie-mediatek.c | 155 ++++++++++++++++++
3 files changed, 182 insertions(+), 1 deletion(-)
base-commit: e98d21c170b01ddef366f023bbfcf6b31509fa83
--
2.39.5
^ permalink raw reply
* [PATCH v7 1/2] dt-bindings: PCI: mediatek: Add support for EcoNet EN7528
From: Caleb James DeLisle @ 2026-05-14 15:13 UTC (permalink / raw)
To: linux-pci
Cc: linux-mips, naseefkm, ryder.lee, helgaas, lpieralisi, kwilczynski,
mani, robh, krzk+dt, conor+dt, matthias.bgg,
angelogioacchino.delregno, ansuelsmth, linux-mediatek, devicetree,
linux-kernel, Caleb James DeLisle, Conor Dooley
In-Reply-To: <20260514151318.3444959-1-cjd@cjdns.fr>
Introduce EcoNet EN7528 SoC compatible in MediaTek PCIe controller
binding.
EcoNet PCIe controller has the same configuration model as
Mediatek v2 but is initialized more similarly to an MT7621
PCIe.
Signed-off-by: Caleb James DeLisle <cjd@cjdns.fr>
Acked-by: Conor Dooley <conor.dooley@microchip.com>
---
.../bindings/pci/mediatek-pcie.yaml | 26 +++++++++++++++++++
1 file changed, 26 insertions(+)
diff --git a/Documentation/devicetree/bindings/pci/mediatek-pcie.yaml b/Documentation/devicetree/bindings/pci/mediatek-pcie.yaml
index 0b8c78ec4f91..c009a7a52bc6 100644
--- a/Documentation/devicetree/bindings/pci/mediatek-pcie.yaml
+++ b/Documentation/devicetree/bindings/pci/mediatek-pcie.yaml
@@ -14,6 +14,7 @@ properties:
oneOf:
- enum:
- airoha,an7583-pcie
+ - econet,en7528-pcie
- mediatek,mt2712-pcie
- mediatek,mt7622-pcie
- mediatek,mt7629-pcie
@@ -226,6 +227,31 @@ allOf:
mediatek,pbus-csr: false
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: econet,en7528-pcie
+ then:
+ properties:
+ clocks:
+ maxItems: 1
+
+ clock-names:
+ maxItems: 1
+
+ resets: false
+
+ reset-names: false
+
+ power-domains: false
+
+ mediatek,pbus-csr: false
+
+ required:
+ - phys
+ - phy-names
+
unevaluatedProperties: false
examples:
--
2.39.5
^ permalink raw reply related
* Re: [PATCH v2 8/8] PCI: rzg3s-host: Add 100 ms delay after link training
From: kernel test robot @ 2026-05-14 14:22 UTC (permalink / raw)
To: Hans Zhang, bhelgaas, lpieralisi, kwilczynski, mani, vigneshr,
jingoohan1, thomas.petazzoni, pali, ryder.lee, jianjun.wang,
claudiu.beznea.uj, mpillai
Cc: oe-kbuild-all, robh, s-vadapalli, linux-omap, linux-arm-kernel,
linux-mediatek, linux-renesas-soc, linux-pci, linux-kernel,
Hans Zhang
In-Reply-To: <20260506152346.166056-9-18255117159@163.com>
Hi Hans,
kernel test robot noticed the following build errors:
[auto build test ERROR on a293ec25d59dd96309058c70df5a4dd0f889a1e4]
url: https://github.com/intel-lab-lkp/linux/commits/Hans-Zhang/PCI-Add-pcie_wait_after_link_train-helper/20260514-132815
base: a293ec25d59dd96309058c70df5a4dd0f889a1e4
patch link: https://lore.kernel.org/r/20260506152346.166056-9-18255117159%40163.com
patch subject: [PATCH v2 8/8] PCI: rzg3s-host: Add 100 ms delay after link training
config: arm64-allnoconfig-bpf (https://download.01.org/0day-ci/archive/20260514/202605141646.YYkbS6Hg-lkp@intel.com/config)
compiler: aarch64-linux-gnu-gcc (Debian 14.2.0-19) 14.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260514/202605141646.YYkbS6Hg-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202605141646.YYkbS6Hg-lkp@intel.com/
All errors (new ones prefixed by >>):
In file included from drivers/pci/controller/pci-thunder-pem.c:16:
drivers/pci/controller/../pci.h: In function 'pcie_wait_after_link_train':
>> drivers/pci/controller/../pci.h:73:17: error: implicit declaration of function 'msleep' [-Wimplicit-function-declaration]
73 | msleep(PCIE_RESET_CONFIG_WAIT_MS);
| ^~~~~~
--
In file included from drivers/pci/controller/dwc/pcie-al.c:14:
drivers/pci/controller/dwc/../../pci.h: In function 'pcie_wait_after_link_train':
>> drivers/pci/controller/dwc/../../pci.h:73:17: error: implicit declaration of function 'msleep' [-Wimplicit-function-declaration]
73 | msleep(PCIE_RESET_CONFIG_WAIT_MS);
| ^~~~~~
vim +/msleep +73 drivers/pci/controller/../pci.h
62
63 /**
64 * pcie_wait_after_link_train - Wait 100 ms if link speed > 5 GT/s
65 * @max_link_speed: the maximum link speed (2 = 5.0 GT/s, 3 = 8.0 GT/s, ...)
66 *
67 * Must be called after Link training completes and before the first
68 * Configuration Request is sent.
69 */
70 static inline void pcie_wait_after_link_train(int max_link_speed)
71 {
72 if (max_link_speed > 2)
> 73 msleep(PCIE_RESET_CONFIG_WAIT_MS);
74 }
75
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply
* [PATCH net v2 5/5] net: dsa: mt7530: untag VLAN-aware bridge PVID
From: Daniel Golle @ 2026-05-14 14:05 UTC (permalink / raw)
To: Chester A. Unal, Daniel Golle, Andrew Lunn, Vladimir Oltean,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Matthias Brugger, AngeloGioacchino Del Regno, DENG Qingfang,
Florian Fainelli, Arınç ÜNAL, Sean Wang, netdev,
linux-kernel, linux-arm-kernel, linux-mediatek
In-Reply-To: <cover.1778766629.git.daniel@makrotopia.org>
From: Edward Parker <edward@topnotchit.com>
With bridge VLAN filtering enabled on a port configured as untagged
member of the bridge PVID, ingress untagged frames do not reach the
corresponding bridge VLAN upper interface (br-lan.<vid>). ARP and
similar traffic is visible on the physical port but not delivered
to the VLAN sub-interface.
The MT7530/MT7531 forwards frames to the CPU port with the user
port's PVID tag applied even when the frame ingressed untagged on
the wire, because the CPU port is set to MT7530_VLAN_EG_CONSISTENT
and is a tagged member of the VLAN entry created for the bridge
VLAN. The DSA core then sees a hwaccel-tagged frame whose VID
matches the port's PVID, which the bridge does not treat as the
untagged-on-the-wire frame that the user expects.
Set ds->untag_vlan_aware_bridge_pvid in the mt7530 and mt7531
setup paths so the DSA core strips that hwaccel tag in software
when the parsed VID matches the bridge port's PVID, restoring the
on-the-wire frame as the bridge expects to see it.
Link: https://github.com/openwrt/openwrt/issues/18576
Fixes: 83163f7dca56 ("net: dsa: mediatek: add VLAN support for MT7530")
Signed-off-by: Edward Parker <edward@topnotchit.com>
[daniel@makrotopia.org: improve commit message]
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
---
v2: no changes
drivers/net/dsa/mt7530.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c
index 5b58e42bfda9..d114922e10e3 100644
--- a/drivers/net/dsa/mt7530.c
+++ b/drivers/net/dsa/mt7530.c
@@ -2452,6 +2452,7 @@ mt7530_setup(struct dsa_switch *ds)
}
ds->assisted_learning_on_cpu_port = true;
+ ds->untag_vlan_aware_bridge_pvid = true;
ds->mtu_enforcement_ingress = true;
ds->ageing_time_min = 2 * 1000;
ds->ageing_time_max = (AGE_CNT_MAX + 1) * (AGE_UNIT_MAX + 1) * 1000;
@@ -2643,6 +2644,7 @@ mt7531_setup_common(struct dsa_switch *ds)
int ret, i;
ds->assisted_learning_on_cpu_port = true;
+ ds->untag_vlan_aware_bridge_pvid = true;
ds->mtu_enforcement_ingress = true;
ds->ageing_time_min = 2 * 1000;
ds->ageing_time_max = (AGE_CNT_MAX + 1) * (AGE_UNIT_MAX + 1) * 1000;
--
2.54.0
^ permalink raw reply related
* [PATCH net v2 4/5] net: dsa: mt7530: clear flood flags on bridge leave
From: Daniel Golle @ 2026-05-14 14:05 UTC (permalink / raw)
To: Chester A. Unal, Daniel Golle, Andrew Lunn, Vladimir Oltean,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Matthias Brugger, AngeloGioacchino Del Regno, DENG Qingfang,
Florian Fainelli, Arınç ÜNAL, Sean Wang, netdev,
linux-kernel, linux-arm-kernel, linux-mediatek
In-Reply-To: <cover.1778766629.git.daniel@makrotopia.org>
Flood flags set by port_bridge_flags persist after a port leaves the
bridge, causing unknown unicast to be forwarded to standalone ports.
Clear UNU_FFP, UNM_FFP and BC_FFP in port_bridge_leave so that the
port returns to its initial state without flooding.
Fixes: 5a30833b9a16 ("net: dsa: mt7530: support MDB and bridge flag operations")
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
---
v2: no changes
drivers/net/dsa/mt7530.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c
index 752ba92b0851..5b58e42bfda9 100644
--- a/drivers/net/dsa/mt7530.c
+++ b/drivers/net/dsa/mt7530.c
@@ -1767,6 +1767,11 @@ mt7530_port_bridge_leave(struct dsa_switch *ds, int port,
mt7530_rmw(priv, MT7530_PCR_P(port), PCR_PORT_VLAN_MASK,
MT7530_PORT_MATRIX_MODE);
+ /* Clear flood flags so they don't persist across bridge leave */
+ mt7530_clear(priv, MT753X_MFC,
+ UNU_FFP(BIT(port)) | UNM_FFP(BIT(port)) |
+ BC_FFP(BIT(port)));
+
mutex_unlock(&priv->reg_mutex);
}
--
2.54.0
^ permalink raw reply related
* [PATCH net v2 3/5] net: dsa: mt7530: fix CPU port VLAN not being reset to unaware
From: Daniel Golle @ 2026-05-14 14:04 UTC (permalink / raw)
To: Chester A. Unal, Daniel Golle, Andrew Lunn, Vladimir Oltean,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Matthias Brugger, AngeloGioacchino Del Regno, DENG Qingfang,
Florian Fainelli, Arınç ÜNAL, Sean Wang, netdev,
linux-kernel, linux-arm-kernel, linux-mediatek
In-Reply-To: <cover.1778766629.git.daniel@makrotopia.org>
After a VLAN-aware bridge is destroyed, creating any VLAN-unaware
bridge loses all connectivity. The VID 0 VLAN table entry used by
VLAN-unaware ports in FALLBACK mode gets corrupted during VLAN-aware
operation: mt7530_hw_vlan_add() overwrites its EG_CON flag with
VTAG_EN and bridge teardown removes ports from its PORT_MEM.
The cleanup code that should restore it never runs because the current
port's dp->vlan_filtering flag is still true when checked (DSA updates
it only after the driver callback returns). Even when restored, the
deferred VLAN deletion events from the switchdev workqueue can corrupt
VID 0 again after the restoration.
Skip the current port in the all_user_ports_removed check, call
mt7530_setup_vlan0() to restore the VID 0 entry, and protect VID 0
from being modified by bridge VLAN operations in port_vlan_add and
port_vlan_del since it is managed exclusively by mt7530_setup_vlan0().
Remove the CPU port PCR and PVC register writes which were clobbering
PORT_VLAN mode and VLAN_ATTR with wrong values.
Fixes: 83163f7dca56 ("net: dsa: mediatek: add VLAN support for MT7530")
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
---
v2: no changes
drivers/net/dsa/mt7530.c | 111 ++++++++++++++++++++++-----------------
1 file changed, 62 insertions(+), 49 deletions(-)
diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c
index 4f657ef6aa65..752ba92b0851 100644
--- a/drivers/net/dsa/mt7530.c
+++ b/drivers/net/dsa/mt7530.c
@@ -1623,6 +1623,49 @@ mt7530_port_bridge_join(struct dsa_switch *ds, int port,
return 0;
}
+static int
+mt7530_vlan_cmd(struct mt7530_priv *priv, enum mt7530_vlan_cmd cmd, u16 vid)
+{
+ struct mt7530_dummy_poll p;
+ u32 val;
+ int ret;
+
+ val = VTCR_BUSY | VTCR_FUNC(cmd) | vid;
+ mt7530_write(priv, MT7530_VTCR, val);
+
+ INIT_MT7530_DUMMY_POLL(&p, priv, MT7530_VTCR);
+ ret = readx_poll_timeout(_mt7530_read, &p, val,
+ !(val & VTCR_BUSY), 20, 20000);
+ if (ret < 0) {
+ dev_err(priv->dev, "poll timeout\n");
+ return ret;
+ }
+
+ val = mt7530_read(priv, MT7530_VTCR);
+ if (val & VTCR_INVALID) {
+ dev_err(priv->dev, "read VTCR invalid\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int
+mt7530_setup_vlan0(struct mt7530_priv *priv)
+{
+ u32 val;
+
+ /* Validate the entry with independent learning, keep the original
+ * ingress tag attribute.
+ */
+ val = IVL_MAC | EG_CON | PORT_MEM(MT7530_ALL_MEMBERS) | FID(FID_BRIDGED) |
+ VLAN_VALID;
+ mt7530_write(priv, MT7530_VAWD1, val);
+ mt7530_write(priv, MT7530_VAWD2, 0);
+
+ return mt7530_vlan_cmd(priv, MT7530_VTCR_WR_VID, 0);
+}
+
static void
mt7530_port_set_vlan_unaware(struct dsa_switch *ds, int port)
{
@@ -1648,6 +1691,8 @@ mt7530_port_set_vlan_unaware(struct dsa_switch *ds, int port)
G0_PORT_VID_DEF);
for (i = 0; i < priv->ds->num_ports; i++) {
+ if (i == port)
+ continue;
if (dsa_is_user_port(ds, i) &&
dsa_port_is_vlan_filtering(dsa_to_port(ds, i))) {
all_user_ports_removed = false;
@@ -1659,13 +1704,9 @@ mt7530_port_set_vlan_unaware(struct dsa_switch *ds, int port)
* the CPU port get out of VLAN filtering mode.
*/
if (all_user_ports_removed) {
- struct dsa_port *dp = dsa_to_port(ds, port);
- struct dsa_port *cpu_dp = dp->cpu_dp;
-
- mt7530_write(priv, MT7530_PCR_P(cpu_dp->index),
- PCR_MATRIX(dsa_user_ports(priv->ds)));
- mt7530_write(priv, MT7530_PVC_P(cpu_dp->index), PORT_SPEC_TAG
- | PVC_EG_TAG(MT7530_VLAN_EG_CONSISTENT));
+ mutex_lock(&priv->reg_mutex);
+ mt7530_setup_vlan0(priv);
+ mutex_unlock(&priv->reg_mutex);
}
}
@@ -1853,33 +1894,6 @@ mt7530_port_mdb_del(struct dsa_switch *ds, int port,
return ret;
}
-static int
-mt7530_vlan_cmd(struct mt7530_priv *priv, enum mt7530_vlan_cmd cmd, u16 vid)
-{
- struct mt7530_dummy_poll p;
- u32 val;
- int ret;
-
- val = VTCR_BUSY | VTCR_FUNC(cmd) | vid;
- mt7530_write(priv, MT7530_VTCR, val);
-
- INIT_MT7530_DUMMY_POLL(&p, priv, MT7530_VTCR);
- ret = readx_poll_timeout(_mt7530_read, &p, val,
- !(val & VTCR_BUSY), 20, 20000);
- if (ret < 0) {
- dev_err(priv->dev, "poll timeout\n");
- return ret;
- }
-
- val = mt7530_read(priv, MT7530_VTCR);
- if (val & VTCR_INVALID) {
- dev_err(priv->dev, "read VTCR invalid\n");
- return -EINVAL;
- }
-
- return 0;
-}
-
static int
mt7530_port_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering,
struct netlink_ext_ack *extack)
@@ -1984,21 +1998,6 @@ mt7530_hw_vlan_update(struct mt7530_priv *priv, u16 vid,
mt7530_vlan_cmd(priv, MT7530_VTCR_WR_VID, vid);
}
-static int
-mt7530_setup_vlan0(struct mt7530_priv *priv)
-{
- u32 val;
-
- /* Validate the entry with independent learning, keep the original
- * ingress tag attribute.
- */
- val = IVL_MAC | EG_CON | PORT_MEM(MT7530_ALL_MEMBERS) | FID(FID_BRIDGED) |
- VLAN_VALID;
- mt7530_write(priv, MT7530_VAWD1, val);
-
- return mt7530_vlan_cmd(priv, MT7530_VTCR_WR_VID, 0);
-}
-
static int
mt7530_port_vlan_add(struct dsa_switch *ds, int port,
const struct switchdev_obj_port_vlan *vlan,
@@ -2011,9 +2010,18 @@ mt7530_port_vlan_add(struct dsa_switch *ds, int port,
mutex_lock(&priv->reg_mutex);
+ /* VID 0 is managed exclusively by mt7530_setup_vlan0() for
+ * VLAN-unaware bridge operation. Don't let the bridge overwrite
+ * its EG_CON flag with VTAG_EN and corrupt PORT_MEM.
+ */
+ if (vlan->vid == 0)
+ goto skip_vlan_table;
+
mt7530_hw_vlan_entry_init(&new_entry, port, untagged);
mt7530_hw_vlan_update(priv, vlan->vid, &new_entry, mt7530_hw_vlan_add);
+skip_vlan_table:
+
if (pvid) {
priv->ports[port].pvid = vlan->vid;
@@ -2053,10 +2061,15 @@ mt7530_port_vlan_del(struct dsa_switch *ds, int port,
mutex_lock(&priv->reg_mutex);
+ /* VID 0 is managed exclusively by mt7530_setup_vlan0(). */
+ if (vlan->vid == 0)
+ goto skip_vlan_table;
+
mt7530_hw_vlan_entry_init(&target_entry, port, 0);
mt7530_hw_vlan_update(priv, vlan->vid, &target_entry,
mt7530_hw_vlan_del);
+skip_vlan_table:
/* PVID is being restored to the default whenever the PVID port
* is being removed from the VLAN.
*/
--
2.54.0
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox