* Re: [PATCH v4 net-next 11/14] net: dsa: netc: add phylink MAC operations
From: Jakub Kicinski @ 2026-04-03 1:17 UTC (permalink / raw)
To: wei.fang
Cc: Jakub Kicinski, claudiu.manoil, vladimir.oltean, xiaoning.wang,
andrew+netdev, davem, edumazet, pabeni, robh, krzk+dt, conor+dt,
f.fainelli, frank.li, chleroy, horms, linux, andrew, netdev,
linux-kernel, devicetree, linuxppc-dev, linux-arm-kernel, imx
In-Reply-To: <20260331113025.1566878-12-wei.fang@nxp.com>
This is an AI-generated review of your patch. The human sending this
email has considered the AI review valid, or at least plausible.
---
net: dsa: netc: add phylink MAC operations
Different versions of NETC switches have different numbers of ports and
MAC capabilities, so add .phylink_get_caps() to struct netc_switch_info.
In addition, related interfaces of struct phylink_mac_ops are added.
> diff --git a/drivers/net/dsa/netc/netc_main.c b/drivers/net/dsa/netc/netc_main.c
> index 5828fd3e342e..f11f5d0f6a6d 100644
> --- a/drivers/net/dsa/netc/netc_main.c
> +++ b/drivers/net/dsa/netc/netc_main.c
[ ... ]
> +static void netc_port_set_mac_mode(struct netc_port *np,
> + unsigned int mode,
> + phy_interface_t phy_mode)
> +{
> + u32 mask = PM_IF_MODE_IFMODE | PM_IF_MODE_REVMII;
> + u32 val = 0;
> +
> + switch (phy_mode) {
> + case PHY_INTERFACE_MODE_RGMII:
[ ... ]
> + case PHY_INTERFACE_MODE_SGMII:
> + case PHY_INTERFACE_MODE_2500BASEX:
> + val |= IFMODE_SGMII;
> + break;
> + default:
> + break;
> + }
> +
> + netc_mac_port_rmw(np, NETC_PM_IF_MODE(0), mask, val);
> +}
In imx94_switch_phylink_get_caps(), PHY_INTERFACE_MODE_1000BASEX is
advertised as supported for ports 0 and 1. Does it need to be handled
in this switch statement? As written, it appears it will fall through
to the default case and clear the IFMODE bits, leaving the MAC in an
undefined mode.
[ ... ]
> +static void netc_port_mac_rx_enable(struct netc_port *np)
> +{
> + netc_port_rmw(np, NETC_POR, PCR_RXDIS, 0);
> + netc_mac_port_rmw(np, NETC_PM_CMD_CFG(0), PM_CMD_CFG_RX_EN,
> + PM_CMD_CFG_RX_EN);
> +}
Pseudo ports (like the CPU port) bypass PMAC register accesses during
graceful stop via is_netc_pseudo_port(). Should there be a similar check
here, and in netc_port_set_mac_mode(), to prevent accessing physical MAC
registers on pseudo ports?
Additionally, when np->caps.pmac is true, netc_port_mac_rx_graceful_stop()
disables the preemption MAC via NETC_PM_CMD_CFG(1). Should this function
re-enable it when bringing the link back up?
> +static void netc_port_wait_rx_empty(struct netc_port *np, int mac)
> +{
> + u32 val;
> +
> + if (read_poll_timeout(netc_port_rd, val, val & PM_IEVENT_RX_EMPTY,
> + 100, 10000, false, np, NETC_PM_IEVENT(mac)))
> + dev_warn(np->switch_priv->dev,
> + "MAC %d of swp%d RX is not empty\n", mac,
> + np->dp->index);
> +}
Is NETC_PM_IEVENT a sticky write-1-to-clear register? If the RX FIFO had
previously emptied during normal operation, could this bit already be set,
causing read_poll_timeout() to return immediately without waiting?
> +static void netc_port_mac_rx_graceful_stop(struct netc_port *np)
> +{
> + u32 val;
> +
> + if (is_netc_pseudo_port(np))
> + goto check_rx_busy;
> +
> + if (np->caps.pmac) {
> + netc_port_rmw(np, NETC_PM_CMD_CFG(1), PM_CMD_CFG_RX_EN, 0);
> + netc_port_wait_rx_empty(np, 1);
> + }
> +
> + netc_port_rmw(np, NETC_PM_CMD_CFG(0), PM_CMD_CFG_RX_EN, 0);
> + netc_port_wait_rx_empty(np, 0);
> +
> +check_rx_busy:
> + if (read_poll_timeout(netc_port_rd, val, !(val & PSR_RX_BUSY),
> + 100, 10000, false, np, NETC_PSR))
> + dev_warn(np->switch_priv->dev, "swp%d RX is busy\n",
> + np->dp->index);
> +
> + netc_port_rmw(np, NETC_POR, PCR_RXDIS, PCR_RXDIS);
> +}
For pseudo ports, the code jumps directly to check_rx_busy and polls for
PSR_RX_BUSY to clear. Since PCR_RXDIS is only set after the polling
completes, will the RX pipeline continue accepting traffic and cause this
poll to always timeout on an active link?
> +static void netc_mac_link_up(struct phylink_config *config,
> + struct phy_device *phy, unsigned int mode,
> + phy_interface_t interface, int speed,
> + int duplex, bool tx_pause, bool rx_pause)
> +{
> + struct dsa_port *dp = dsa_phylink_to_port(config);
> + struct netc_port *np;
> +
> + np = NETC_PORT(dp->ds, dp->index);
> + netc_port_set_speed(np, speed);
> +
> + if (phy_interface_mode_is_rgmii(interface))
> + netc_port_set_rgmii_mac(np, speed, duplex);
> +
> + if (interface == PHY_INTERFACE_MODE_RMII ||
> + interface == PHY_INTERFACE_MODE_REVMII ||
> + interface == PHY_INTERFACE_MODE_MII)
> + netc_port_set_rmii_mii_mac(np, speed, duplex);
> +
> + netc_port_mac_rx_enable(np);
> +}
The callback imx94_switch_phylink_get_caps() advertises MAC_ASYM_PAUSE and
MAC_SYM_PAUSE capabilities. Is it expected that tx_pause and rx_pause are
ignored here? If flow control is implemented in a subsequent patch, should
the advertisement be deferred until then?
> +static void netc_mac_link_down(struct phylink_config *config,
> + unsigned int mode,
> + phy_interface_t interface)
> +{
> + struct dsa_port *dp = dsa_phylink_to_port(config);
> +
> + netc_port_mac_rx_graceful_stop(NETC_PORT(dp->ds, dp->index));
> +}
This correctly stops the RX pipeline, but should the TX path
(PM_CMD_CFG_TX_EN or PCR_TXDIS) also be disabled when the link goes down?
^ permalink raw reply
* Re: [PATCH v4 net-next 10/14] net: dsa: netc: introduce NXP NETC switch driver for i.MX94
From: Jakub Kicinski @ 2026-04-03 1:17 UTC (permalink / raw)
To: wei.fang
Cc: Jakub Kicinski, claudiu.manoil, vladimir.oltean, xiaoning.wang,
andrew+netdev, davem, edumazet, pabeni, robh, krzk+dt, conor+dt,
f.fainelli, frank.li, chleroy, horms, linux, andrew, netdev,
linux-kernel, devicetree, linuxppc-dev, linux-arm-kernel, imx
In-Reply-To: <20260331113025.1566878-11-wei.fang@nxp.com>
This is an AI-generated review of your patch. The human sending this
email has considered the AI review valid, or at least plausible.
---
net: dsa: netc: introduce NXP NETC switch driver for i.MX94
This commit introduces the initial NXP NETC switch driver for the i.MX94
series. It supports basic probe and remove functionality for the integrated
802.1Q Ethernet switch. The switch includes 3 user ports and 1 CPU port
connected to an internal ENETC.
> diff --git a/drivers/net/dsa/netc/netc_main.c b/drivers/net/dsa/netc/netc_main.c
> new file mode 100644
> index 000000000000..5828fd3e342e
> --- /dev/null
> +++ b/drivers/net/dsa/netc/netc_main.c
[ ... ]
> +static int netc_port_create_emdio_bus(struct netc_port *np,
> + struct device_node *node)
> +{
[ ... ]
> + err = devm_of_mdiobus_register(dev, bus, node);
> + if (err)
> + return dev_err_probe(dev, err,
> + "Cannot register EMDIO bus\n");
> +
> + np->emdio = bus;
> +
> + return 0;
> +}
[ ... ]
> +static int netc_init_switch_id(struct netc_switch *priv)
> +{
> + struct netc_switch_regs *regs = &priv->regs;
> + struct dsa_switch *ds = priv->ds;
> +
> + /* The value of 0 is reserved for the VEPA switch and cannot
> + * be used.
> + */
> + if (ds->index > SWCR_SWID || !ds->index) {
> + dev_err(priv->dev, "Switch index %d out of range\n",
> + ds->index);
> + return -ERANGE;
> + }
Does this check cause the probe to fail unconditionally for standard
single-switch topologies?
The DSA core typically assigns ds->index = 0 by default for the first switch.
Because !ds->index evaluates to true for index 0, this setup function will
always fail unless the dsa,member property is explicitly overridden in the
device tree.
Could the driver translate the hardware ID internally, for example by writing
ds->index + 1 to NETC_SWCR, rather than forcing this hardware-specific
restriction onto the software DSA index?
> +
> + netc_base_wr(regs, NETC_SWCR, ds->index);
> +
> + return 0;
> +}
[ ... ]
> +static bool netc_port_is_emdio_consumer(struct device_node *node)
> +{
> + struct device_node *mdio_node;
> +
> + /* If the port node has phy-handle property and it does
> + * not contain a mdio child node, then the port is the
> + * EMDIO consumer.
> + */
> + mdio_node = of_get_child_by_name(node, "mdio");
> + if (!mdio_node)
> + return true;
> +
> + of_node_put(mdio_node);
> +
> + return false;
> +}
> +
> +/* Currently, phylink_of_phy_connect() is called by dsa_user_create(),
> + * so if the switch uses the external MDIO controller (like the EMDIO
> + * function) to manage the external PHYs. The MDIO bus may not be
> + * created when phylink_of_phy_connect() is called, so it will return
> + * an error and cause the switch driver to fail to probe.
> + * This workaround can be removed when DSA phylink_of_phy_connect()
> + * calls are moved from probe() to ndo_open().
> + */
> +static int netc_switch_check_emdio_is_ready(struct device *dev)
> +{
[ ... ]
> + for_each_available_child_of_node_scoped(ports, child) {
> + /* If the node does not have phy-handle property, then
> + * the port does not connect to a PHY, so the port is
> + * not the EMDIO consumer.
> + */
> + phy_node = of_parse_phandle(child, "phy-handle", 0);
> + if (!phy_node)
> + continue;
> +
> + if (!netc_port_is_emdio_consumer(child)) {
> + of_node_put(phy_node);
> + continue;
> + }
> +
> + phydev = of_phy_find_device(phy_node);
> + of_node_put(phy_node);
> + if (!phydev) {
> + err = -EPROBE_DEFER;
> + goto out;
> + }
Could this logic cause an infinite probe deferral loop for ports sharing an
internal MDIO bus?
The netc_port_is_emdio_consumer() function assumes any port node without an
mdio child is an EMDIO consumer waiting for an external controller. However,
if multiple sibling ports on the same switch share a single internal MDIO bus
defined under one port, the other ports will lack an mdio child node.
This would cause those ports to be mistakenly treated as external EMDIO
consumers, calling of_phy_find_device(). Because the internal MDIO bus is not
registered until later in netc_setup(), the PHY device cannot be found, and
the driver returns -EPROBE_DEFER.
Since netc_setup() is never reached, the MDIO bus is never registered,
causing an infinite deferral loop. Could the driver more accurately identify
whether the PHY belongs to its own switch before deferring?
> +
> + put_device(&phydev->mdio.dev);
> + }
> +
> +out:
> + of_node_put(ports);
> +
> + return err;
> +}
> +
> +static int netc_switch_pci_init(struct pci_dev *pdev)
> +{
[ ... ]
> + regs->base = pci_ioremap_bar(pdev, NETC_REGS_BAR);
> + if (!regs->base) {
> + err = -ENXIO;
> + dev_err(dev, "pci_ioremap_bar() failed\n");
> + goto release_mem_regions;
> + }
[ ... ]
> +static void netc_switch_pci_destroy(struct pci_dev *pdev)
> +{
> + struct netc_switch *priv = pci_get_drvdata(pdev);
> +
> + iounmap(priv->regs.base);
> + pci_release_mem_regions(pdev);
> + pci_disable_device(pdev);
> +}
Does unmapping the memory here introduce a use-after-unmap issue when the
MDIO bus is unregistered?
The driver registers the MDIO bus using devm_of_mdiobus_register(), meaning
devres cleans it up asynchronously after the remove function returns or when
probe fails.
However, in netc_switch_pci_destroy(), the driver explicitly unmaps the PCI
I/O memory via iounmap(). Since netc_switch_pci_destroy() is called
synchronously inside the remove function and probe error paths, the memory is
unmapped before the MDIO bus is unregistered by devres.
When devres eventually unregisters the MDIO bus, it detaches PHY devices,
which often perform MDIO transactions during removal. Because the underlying
memory priv->regs.base is already unmapped, these MDIO read/write callbacks
could trigger a synchronous external abort or kernel panic.
Would it be better to use pcim_iomap() to tie the memory mapping lifecycle to
devres, ensuring it outlives the MDIO bus?
^ permalink raw reply
* Re: [PATCH v4 net-next 09/14] net: dsa: add NETC switch tag support
From: Jakub Kicinski @ 2026-04-03 1:17 UTC (permalink / raw)
To: wei.fang
Cc: Jakub Kicinski, claudiu.manoil, vladimir.oltean, xiaoning.wang,
andrew+netdev, davem, edumazet, pabeni, robh, krzk+dt, conor+dt,
f.fainelli, frank.li, chleroy, horms, linux, andrew, netdev,
linux-kernel, devicetree, linuxppc-dev, linux-arm-kernel, imx
In-Reply-To: <20260331113025.1566878-10-wei.fang@nxp.com>
This is an AI-generated review of your patch. The human sending this
email has considered the AI review valid, or at least plausible.
---
net: dsa: add NETC switch tag support
Adds support for the proprietary NXP NETC switch tag used in NXP NETC
switches version 4.3 or later. The tag has 3 types (Forward, To_Port,
To_Host) and supports a varying length between 6 and 14 bytes.
> diff --git a/net/dsa/tag_netc.c b/net/dsa/tag_netc.c
> new file mode 100644
> index 000000000000..addd41f7f1b6
> --- /dev/null
> +++ b/net/dsa/tag_netc.c
[ ... ]
> +static void *netc_fill_common_tp_tag(struct sk_buff *skb,
> + struct net_device *ndev,
> + u8 subtype, int tag_len)
> +{
> + struct dsa_port *dp = dsa_user_to_port(ndev);
> + u16 queue = skb_get_queue_mapping(skb);
> + u8 ipv = netdev_txq_to_tc(ndev, queue);
What happens here if the interface doesn't have traffic classes configured?
By default, netdev_txq_to_tc() returns -1. Because ipv is an unsigned 8-bit
integer, this casts to 255.
When this is later passed to FIELD_PREP(NETC_TAG_IPV, ipv) in
netc_fill_common_tag(), the macro blindly masks the variable, silently
forcing the IPV field to 7 (the maximum priority) for all default,
unconfigured traffic. Valid TC values greater than 7 would also be silently
truncated.
Does this code bypass the intended QoS mechanisms?
> + void *tag;
> +
> + skb_push(skb, tag_len);
> + dsa_alloc_etype_header(skb, tag_len);
> +
> + tag = dsa_etype_header_pos_tx(skb);
> + memset(tag + NETC_TAG_CMN_LEN, 0, tag_len - NETC_TAG_CMN_LEN);
> + netc_fill_common_tag(tag, NETC_TAG_TO_PORT, subtype,
> + dp->ds->index, dp->index, ipv);
Will this break communication for standard single-switch setups?
The driver passes dp->ds->index as the hardware switch ID here, which
defaults to 0 for the first switch in a DSA tree. However, on the receive
path, frames stamped with switch ID 0 are rejected.
If the physical switch hardware uses an ID greater than 0, frames will fail
the lookup in dsa_conduit_find_user() on receive because the software index
is 0.
> +
> + return tag;
> +}
[ ... ]
> +static struct sk_buff *netc_rcv(struct sk_buff *skb,
> + struct net_device *ndev)
> +{
> + struct netc_tag_cmn *tag_cmn;
> + int tag_len, sw_id, port;
[ ... ]
> + if (tag_cmn->qos & NETC_TAG_QV)
> + skb->priority = FIELD_GET(NETC_TAG_IPV, tag_cmn->qos);
> +
> + sw_id = NETC_TAG_SWITCH & tag_cmn->switch_port;
This isn't a bug, but is there a reason to use a raw bitwise AND for sw_id
instead of using FIELD_GET(NETC_TAG_SWITCH, ...) to match how the port
field is extracted just below this?
> + /* ENETC VEPA switch ID (0) is not supported yet */
> + if (!sw_id) {
> + dev_warn_ratelimited(&ndev->dev,
> + "VEPA switch ID is not supported yet\n");
> +
> + return NULL;
> + }
> +
> + port = FIELD_GET(NETC_TAG_PORT, tag_cmn->switch_port);
> + skb->dev = dsa_conduit_find_user(ndev, sw_id, port);
[ ... ]
^ permalink raw reply
* Re: [PATCH v4 net-next 07/14] net: enetc: add support for "Add" and "Delete" operations to IPFT
From: Jakub Kicinski @ 2026-04-03 1:17 UTC (permalink / raw)
To: wei.fang
Cc: Jakub Kicinski, claudiu.manoil, vladimir.oltean, xiaoning.wang,
andrew+netdev, davem, edumazet, pabeni, robh, krzk+dt, conor+dt,
f.fainelli, frank.li, chleroy, horms, linux, andrew, netdev,
linux-kernel, devicetree, linuxppc-dev, linux-arm-kernel, imx
In-Reply-To: <20260331113025.1566878-8-wei.fang@nxp.com>
This is an AI-generated review of your patch. The human sending this
email has considered the AI review valid, or at least plausible.
---
net: enetc: add support for "Add" and "Delete" operations to IPFT
This commit adds support for the "Add" and "Delete" operations to the
ingress port filter table (IPFT). These interfaces will be used by both
the ENETC driver and the NETC switch driver.
> diff --git a/drivers/net/ethernet/freescale/enetc/ntmp.c b/drivers/net/ethernet/freescale/enetc/ntmp.c
> index 3c59b355c142..960d5be8ec42 100644
> --- a/drivers/net/ethernet/freescale/enetc/ntmp.c
> +++ b/drivers/net/ethernet/freescale/enetc/ntmp.c
[ ... ]
> @@ -468,6 +471,79 @@ int ntmp_rsst_query_entry(struct ntmp_user *user, u32 *table, int count)
> }
> EXPORT_SYMBOL_GPL(ntmp_rsst_query_entry);
>
> +/**
> + * ntmp_ipft_add_entry - add an entry into the ingress port filter table
> + * @user: target ntmp_user struct
> + * @entry: the entry data, entry->cfge (configuration element data) and
> + * entry->keye (key element data) are used as input. Since the entry ID
> + * is assigned by the hardware, so entry->entry_id is a returned value
> + * for the driver to use, the driver can update/delete/query the entry
> + * based on the entry_id.
> + *
> + * Return: 0 on success, otherwise a negative error code
> + */
> +int ntmp_ipft_add_entry(struct ntmp_user *user,
> + struct ipft_entry_data *entry)
> +{
[ ... ]
> + err = ntmp_alloc_data_mem(&data, (void **)&req);
> + if (err)
> + return err;
> +
> + ntmp_fill_crd(&req->crd, user->tbl.ipft_ver, NTMP_QA_ENTRY_ID,
> + NTMP_GEN_UA_CFGEU | NTMP_GEN_UA_STSEU);
> + req->ak.keye = entry->keye;
> + req->cfge = entry->cfge;
The request sets NTMP_GEN_UA_STSEU to indicate statistics data is present,
but struct ipft_req_ua does not appear to contain a match_count or STSE data
field before cfge.
Since the hardware expects STSE data before CFGE data (as seen in
struct ipft_resp_query), will this cause the hardware to misinterpret the
first 8 bytes of cfge as the match_count, and then read the actual filter
configuration from out-of-bounds or uninitialized memory?
> diff --git a/drivers/net/ethernet/freescale/enetc/ntmp_private.h b/drivers/net/ethernet/freescale/enetc/ntmp_private.h
> index 7d50af7745c7..6d519d59a433 100644
> --- a/drivers/net/ethernet/freescale/enetc/ntmp_private.h
> +++ b/drivers/net/ethernet/freescale/enetc/ntmp_private.h
[ ... ]
> +/* Ingress Port Filter Table Request Data Buffer Format of Update and
> + * Add actions
> + */
> +struct ipft_req_ua {
> + struct ntmp_cmn_req_data crd;
> + union ipft_access_key ak;
> + struct ipft_cfge_data cfge;
> +};
Does this struct need an STSE data field before cfge to match the request
header flags?
> diff --git a/include/linux/fsl/ntmp.h b/include/linux/fsl/ntmp.h
> index a54945dcdc61..efda35e5e22c 100644
> --- a/include/linux/fsl/ntmp.h
> +++ b/include/linux/fsl/ntmp.h
[ ... ]
> @@ -66,6 +68,94 @@ struct maft_entry_data {
> struct maft_cfge_data cfge;
> };
>
> +struct ipft_pld_byte {
> + u8 data;
> + u8 mask;
> +};
> +
> +struct ipft_keye_data {
> + __le16 precedence;
> + __le16 resv0[3];
> + __le16 frm_attr_flags;
> +#define IPFT_FAF_OVLAN BIT(2)
> +#define IPFT_FAF_IVLAN BIT(3)
> +#define IPFT_FAF_IP_HDR BIT(7)
> +#define IPFT_FAF_IP_VER6 BIT(8)
> +#define IPFT_FAF_L4_CODE GENMASK(11, 10)
> +#define IPFT_FAF_TCP_HDR 1
> +#define IPFT_FAF_UDP_HDR 2
> +#define IPFT_FAF_SCTP_HDR 3
> +#define IPFT_FAF_WOL_MAGIC BIT(12)
> + __le16 frm_attr_flags_mask;
> + __le16 dscp;
> +#define IPFT_DSCP GENMASK(5, 0)
> +#define IPFT_DSCP_MASK GENMASK(11, 0)
Does IPFT_DSCP_MASK completely overlap with IPFT_DSCP?
If it is defined as GENMASK(11, 0) instead of GENMASK(11, 6), using
FIELD_PREP with this mask will not shift the value into the upper bits,
which might overwrite the actual DSCP value in bits 0-5.
^ permalink raw reply
* Re: [PATCH v4 net-next 06/14] net: enetc: add support for the "Update" operation to buffer pool table
From: Jakub Kicinski @ 2026-04-03 1:17 UTC (permalink / raw)
To: wei.fang
Cc: Jakub Kicinski, claudiu.manoil, vladimir.oltean, xiaoning.wang,
andrew+netdev, davem, edumazet, pabeni, robh, krzk+dt, conor+dt,
f.fainelli, frank.li, chleroy, horms, linux, andrew, netdev,
linux-kernel, devicetree, linuxppc-dev, linux-arm-kernel, imx
In-Reply-To: <20260331113025.1566878-7-wei.fang@nxp.com>
This is an AI-generated review of your patch. The human sending this
email has considered the AI review valid, or at least plausible.
---
Subject: net: enetc: add support for the "Update" operation to buffer pool table
This patch adds the ntmp_bpt_update_entry() helper function to support
updating a specified entry in the buffer pool table. It provides the
ability to update buffer pool configuration data.
> diff --git a/drivers/net/ethernet/freescale/enetc/ntmp_private.h b/drivers/net/ethernet/freescale/enetc/ntmp_private.h
> --- a/drivers/net/ethernet/freescale/enetc/ntmp_private.h
> +++ b/drivers/net/ethernet/freescale/enetc/ntmp_private.h
[ ... ]
> +/* Buffer Pool Table Request Data Buffer Format of Update action */
> +struct bpt_req_update {
> + struct ntmp_req_by_eid rbe;
> + struct bpt_cfge_data cfge;
> +};
> +
[ ... ]
> diff --git a/drivers/net/ethernet/freescale/enetc/ntmp.c b/drivers/net/ethernet/freescale/enetc/ntmp.c
> --- a/drivers/net/ethernet/freescale/enetc/ntmp.c
> +++ b/drivers/net/ethernet/freescale/enetc/ntmp.c
[ ... ]
> @@ -702,5 +708,38 @@ int ntmp_vft_add_entry(struct ntmp_user *user, u16 vid,
> }
> EXPORT_SYMBOL_GPL(ntmp_vft_add_entry);
>
> +int ntmp_bpt_update_entry(struct ntmp_user *user, u32 entry_id,
> + const struct bpt_cfge_data *cfge)
> +{
> + struct ntmp_dma_buf data = {
> + .dev = user->dev,
> + .size = sizeof(struct bpt_req_update),
> + };
> + struct bpt_req_update *req;
> + union netc_cbd cbd;
> + int err;
> +
> + err = ntmp_alloc_data_mem(&data, (void **)&req);
> + if (err)
> + return err;
> +
> + ntmp_fill_crd_eid(&req->rbe, user->tbl.bpt_ver, 0,
> + NTMP_GEN_UA_CFGEU | BPT_UA_BPSEU, entry_id);
Does this update action mask match the size of the request buffer?
The mask includes both NTMP_GEN_UA_CFGEU and BPT_UA_BPSEU, which instructs
the hardware to update both the configuration entry and the status entry.
However, struct bpt_req_update only contains the configuration data,
omitting the status data.
If the hardware attempts to read the missing BPSE data, could it reject
the command due to an undersized request length, or read beyond the
intended payload into zero-initialized DMA padding? This might overwrite
critical buffer pool tracking variables like amount_used_hwm.
If only the configuration is being updated, should the BPT_UA_BPSEU flag
be removed?
> + req->cfge = *cfge;
> + ntmp_fill_request_hdr(&cbd, data.dma, NTMP_LEN(data.size, 0),
> + NTMP_BPT_ID, NTMP_CMD_UPDATE, NTMP_AM_ENTRY_ID);
> +
> + err = netc_xmit_ntmp_cmd(user, &cbd);
> + if (err)
> + dev_err(user->dev,
> + "Failed to update %s entry 0x%x, err: %pe\n",
> + ntmp_table_name(NTMP_BPT_ID), entry_id, ERR_PTR(err));
> +
> + ntmp_free_data_mem(&data);
Can this result in a DMA use-after-free if the hardware command times out?
If netc_xmit_ntmp_cmd() times out waiting for the hardware to process the
command, it returns -ETIMEDOUT without resetting the hardware ring or
explicitly cancelling the command.
The descriptor remains active in the ring, and ntmp_free_data_mem()
unconditionally frees the DMA-mapped buffer. If the hardware eventually
processes the descriptor, it will read from the now-freed DMA memory.
Could this lead to an IOMMU fault or cause the hardware to read garbage
data if the page has been reallocated?
> +
> + return err;
> +}
^ permalink raw reply
* Re: [PATCH v4 net-next 05/14] net: enetc: add support for the "Add" operation to VLAN filter table
From: Jakub Kicinski @ 2026-04-03 1:17 UTC (permalink / raw)
To: wei.fang
Cc: Jakub Kicinski, claudiu.manoil, vladimir.oltean, xiaoning.wang,
andrew+netdev, davem, edumazet, pabeni, robh, krzk+dt, conor+dt,
f.fainelli, frank.li, chleroy, horms, linux, andrew, netdev,
linux-kernel, devicetree, linuxppc-dev, linux-arm-kernel, imx
In-Reply-To: <20260331113025.1566878-6-wei.fang@nxp.com>
This is an AI-generated review of your patch. The human sending this
email has considered the AI review valid, or at least plausible.
---
net: enetc: add support for the "Add" operation to VLAN filter table
This patch adds the ntmp_vft_add_entry() helper function to support adding
entries to the VLAN filter table. It allocates a DMA buffer, formats the
request, and transmits it via the command BD ring using netc_xmit_ntmp_cmd().
> diff --git a/drivers/net/ethernet/freescale/enetc/ntmp.c b/drivers/net/ethernet/freescale/enetc/ntmp.c
> --- a/drivers/net/ethernet/freescale/enetc/ntmp.c
> +++ b/drivers/net/ethernet/freescale/enetc/ntmp.c
[ ... ]
> @@ -652,5 +655,52 @@ int ntmp_fdbt_search_port_entry(struct ntmp_user *user, int port,
> +int ntmp_vft_add_entry(struct ntmp_user *user, u16 vid,
> + const struct vft_cfge_data *cfge)
> +{
> + struct ntmp_dma_buf data = {
> + .dev = user->dev,
> + .size = sizeof(struct vft_req_ua),
> + };
> + struct vft_req_ua *req;
> + union netc_cbd cbd;
> + u32 len;
> + int err;
> +
> + err = ntmp_alloc_data_mem(&data, (void **)&req);
> + if (err)
> + return err;
> +
> + /* Request data */
> + ntmp_fill_crd(&req->crd, user->tbl.vft_ver, 0,
> + NTMP_GEN_UA_CFGEU);
> + req->ak.exact.vid = cpu_to_le16(vid);
> + req->cfge = *cfge;
> +
> + /* Request header */
> + len = NTMP_LEN(data.size, NTMP_STATUS_RESP_LEN);
> + ntmp_fill_request_hdr(&cbd, data.dma, len, NTMP_VFT_ID,
> + NTMP_CMD_ADD, NTMP_AM_EXACT_KEY);
> +
> + err = netc_xmit_ntmp_cmd(user, &cbd);
> + if (err)
> + dev_err(user->dev,
> + "Failed to add %s entry, vid: %u, err: %pe\n",
> + ntmp_table_name(NTMP_VFT_ID), vid, ERR_PTR(err));
> +
> + ntmp_free_data_mem(&data);
Does this code safely handle hardware timeouts?
If netc_xmit_ntmp_cmd() times out and returns an error, the pending
transaction is not explicitly aborted before ntmp_free_data_mem()
unconditionally frees the DMA buffer.
Could the hardware eventually process the pending command and perform a
DMA write of the response to the physical address of the freed buffer?
This might lead to silent memory corruption if that memory has already
been reallocated to another subsystem. Would it be safer to explicitly
abort the pending DMA transaction, reset the device on timeout, or
intentionally delay freeing the buffer until it is proven safe?
> +
> + return err;
> +}
^ permalink raw reply
* Re: [PATCH v4 net-next 04/14] net: enetc: add basic operations to the FDB table
From: Jakub Kicinski @ 2026-04-03 1:17 UTC (permalink / raw)
To: wei.fang
Cc: Jakub Kicinski, claudiu.manoil, vladimir.oltean, xiaoning.wang,
andrew+netdev, davem, edumazet, pabeni, robh, krzk+dt, conor+dt,
f.fainelli, frank.li, chleroy, horms, linux, andrew, netdev,
linux-kernel, devicetree, linuxppc-dev, linux-arm-kernel, imx
In-Reply-To: <20260331113025.1566878-5-wei.fang@nxp.com>
This is an AI-generated review of your patch. The human sending this
email has considered the AI review valid, or at least plausible.
---
net: enetc: add basic operations to the FDB table
This commit adds FDB table management operations (Add, Delete, Update,
Query/Search) to the enetc driver using NTMP version 2.0. FDB entries
are managed via the command BD ring.
> diff --git a/include/linux/fsl/ntmp.h b/include/linux/fsl/ntmp.h
> index 916dc4fe7de3..a9f3e6cbf422 100644
> --- a/include/linux/fsl/ntmp.h
> +++ b/include/linux/fsl/ntmp.h
[ ... ]
> @@ -116,6 +158,31 @@ static inline int ntmp_rsst_query_entry(struct ntmp_user *user,
> return 0;
> }
>
> +static inline int ntmp_fdbt_add_entry(struct ntmp_user *user, u32 *entry_id,
> + const struct fdbt_keye_data *keye,
> + const struct fdbt_cfge_data *data)
> +{
> + return 0;
> +}
If CONFIG_NXP_NETC_LIB is disabled, will returning 0 here cause callers to
falsely assume the operation succeeded and proceed to use an uninitialized
entry_id pointer? Would it be safer to return an error code such as
-EOPNOTSUPP for stubs that have output parameters?
[ ... ]
> +static inline int ntmp_fdbt_search_port_entry(struct ntmp_user *user, int port,
> + u32 *resume_entry_id,
> + struct fdbt_entry_data *entry)
> +{
> + return 0;
> +}
Similar to the above, does returning 0 here leave both resume_entry_id and
entry uninitialized while signaling success? Since resume_entry_id is
typically used as an iterator, could this lead to an infinite loop or other
unpredictable behavior in the caller if they interpret the 0 return as a
successful read of valid hardware configuration data?
^ permalink raw reply
* Re: [PATCH v4 net-next 03/14] net: enetc: add pre-boot initialization for i.MX94 switch
From: Jakub Kicinski @ 2026-04-03 1:17 UTC (permalink / raw)
To: wei.fang
Cc: Jakub Kicinski, claudiu.manoil, vladimir.oltean, xiaoning.wang,
andrew+netdev, davem, edumazet, pabeni, robh, krzk+dt, conor+dt,
f.fainelli, frank.li, chleroy, horms, linux, andrew, netdev,
linux-kernel, devicetree, linuxppc-dev, linux-arm-kernel, imx
In-Reply-To: <20260331113025.1566878-4-wei.fang@nxp.com>
This is an AI-generated review of your patch. The human sending this
email has considered the AI review valid, or at least plausible.
---
net: enetc: add pre-boot initialization for i.MX94 switch
This commit adds pre-boot initialization logic for the i.MX94 switch
in the NETC block control driver. It configures external ports, MII
protocols, and MDIO PHY addresses, and handles the MAC selection
constraint between switch port 2 and ENETC 0.
> diff --git a/drivers/net/ethernet/freescale/enetc/netc_blk_ctrl.c b/drivers/net/ethernet/freescale/enetc/netc_blk_ctrl.c
> index 92a0f824dae7..c21230f7a7fb 100644
> --- a/drivers/net/ethernet/freescale/enetc/netc_blk_ctrl.c
> +++ b/drivers/net/ethernet/freescale/enetc/netc_blk_ctrl.c
[ ... ]
> +static int imx94_switch_link_config(struct netc_blk_ctrl *priv,
> + struct device_node *np,
> + bool *swp2_en)
> +{
> + struct device_node *ports;
> + int port_id, err = 0;
Since of_property_read_u32() expects a u32 pointer, does passing a
signed int pointer here trigger an incompatible pointer types warning
during compilation?
> +
> + ports = netc_get_switch_ports(np);
> + if (!ports)
> + return -ENODEV;
> +
> + for_each_available_child_of_node_scoped(ports, child) {
> + if (of_property_read_u32(child, "reg", &port_id) < 0) {
If the device tree provides a reg value with the MSB set, port_id
would be evaluated as a negative number.
[ ... ]
> static int imx94_netcmix_init(struct platform_device *pdev)
> {
> struct netc_blk_ctrl *priv = platform_get_drvdata(pdev);
> struct device_node *np = pdev->dev.of_node;
> + bool enetc0_en = false, swp2_en = false;
> u32 val;
> int err;
>
> for_each_child_of_node_scoped(np, child) {
> for_each_child_of_node_scoped(child, gchild) {
> - if (!of_device_is_compatible(gchild, "pci1131,e101"))
> - continue;
> -
> - err = imx94_enetc_link_config(priv, gchild);
> - if (err)
> - return err;
> + if (of_device_is_compatible(gchild, "pci1131,e101")) {
> + err = imx94_enetc_link_config(priv, gchild,
> + &enetc0_en);
> + if (err)
> + return err;
> + } else if (of_device_is_compatible(gchild,
> + "pci1131,eef2")) {
Is it possible for the switch node to be disabled in the device tree?
If so, should we check of_device_is_available() for gchild before proceeding,
similar to how it is checked for enetc0_en?
Without checking availability, if the disabled switch lacks a ports subnode,
imx94_switch_link_config() might return -ENODEV and abort the entire probe.
Alternatively, if the disabled switch node has a ports subnode with an
available port 2, it could spuriously set swp2_en = true and cause a false
conflict with ENETC 0.
> + err = imx94_switch_link_config(priv, gchild,
> + &swp2_en);
> + if (err)
> + return err;
> + }
> }
> }
[ ... ]
> @@ -610,6 +682,77 @@ static int imx94_enetc_mdio_phyaddr_config(struct netc_blk_ctrl *priv,
> return 0;
> }
>
> +static int imx94_ierb_enetc_init(struct netc_blk_ctrl *priv,
[ ... ]
> +static int imx94_switch_mdio_phyaddr_config(struct netc_blk_ctrl *priv,
> + struct device_node *np,
> + int port_id, u32 phy_mask)
> +{
> + int addr;
> +
> + /* The switch has 3 external ports at most */
> + if (port_id > 2)
> + return 0;
If port_id is negative due to the signed type, it will bypass this upper
bound check.
> +
> + addr = netc_get_phy_addr(np);
> + if (addr < 0) {
> + if (addr == -ENODEV)
> + return 0;
> +
> + return addr;
> + }
> +
> + if (phy_mask & BIT(addr)) {
> + dev_err(&priv->pdev->dev,
> + "Found same PHY address in EMDIO and switch node\n");
> + return -EINVAL;
> + }
> +
> + netc_reg_write(priv->ierb, IERB_LBCR(port_id),
> + LBCR_MDIO_PHYAD_PRTAD(addr));
Could this lead to an out-of-bounds register write prior to the array base
since port_id is negative?
> +
> + return 0;
> +}
> +
> +static int imx94_ierb_switch_init(struct netc_blk_ctrl *priv,
> + struct device_node *np,
> + u32 phy_mask)
> +{
> + struct device_node *ports;
> + int port_id, err = 0;
A similar signed int declaration is used here for port_id, which would run
into the same pointer type warning and negative value issues.
> +
> + ports = netc_get_switch_ports(np);
> + if (!ports)
> + return -ENODEV;
[ ... ]
--
pw-bot: cr
^ permalink raw reply
* Re: [PATCH v2 2/4] ASoC: codecs: Add TAS675x quad-channel audio amplifier driver
From: Sen Wang @ 2026-04-03 1:16 UTC (permalink / raw)
To: Mark Brown
Cc: linux-sound, lgirdwood, robh, krzk+dt, conor+dt, devicetree,
perex, tiwai, shenghao-ding, kevin-lu, baojun.xu, niranjan.hy,
l-badrinarayanan, devarsht, v-singh1, linux-kernel
In-Reply-To: <3c300b9c-1589-492c-ace3-4d8a1d25f1ed@sirena.org.uk>
On 4/2/26 12:10, Mark Brown wrote:
> On Wed, Apr 01, 2026 at 05:28:43PM -0500, Sen Wang wrote:
>> The TAS675x (TAS6754, TAS67524) are quad-channel, digital-input
>> Class-D amplifiers with an integrated DSP, controlled over I2C.
>> They support I2S and TDM serial audio interfaces.
>
> One issue that didn't get noticed last time, sorry:
>
The more the merrier :)
>> +static int tas675x_runtime_suspend(struct device *dev)
>> +{
>> + struct tas675x_priv *tas = dev_get_drvdata(dev);
>> +
>> + cancel_delayed_work_sync(&tas->fault_check_work);
>> + tas675x_set_state_all(tas, TAS675X_STATE_SLEEP_BOTH);
>> +
>> + return 0;
>> +}
>
> This cancels the work, completing any that's already running, but...
>
>> +static void tas675x_fault_check_work(struct work_struct *work)
>> +{
>> + struct tas675x_priv *tas = container_of(work, struct tas675x_priv,
>> + fault_check_work.work);
>> +
>> + if (tas675x_check_faults(tas))
>> + regmap_write(tas->regmap, TAS675X_RESET_REG, TAS675X_FAULT_CLEAR);
>> +
>> + schedule_delayed_work(&tas->fault_check_work,
>> + msecs_to_jiffies(TAS675X_FAULT_CHECK_INTERVAL_MS));
>> +}
>
> ...the work unconditionally rearms itself so we might race and requeue
> (we cancel *then* wait) with the device powered off. There's the
> disable_delayed_work_sync() API which should be a better fit.
>
Right the APIs themselves aren't atomic, disable would be a much less
error-prone approach. Looks like TAS5720 & TAS6424 has a similar issue
too, where they have cancel work at DAPM events instead of runtime
suspend. I can test and send these changes in a separate patch.
>> +static irqreturn_t tas675x_irq_handler(int irq, void *data)
>> +{
>> + struct tas675x_priv *tas = data;
>> +
>> + tas675x_check_faults(tas);
>> +
>> + /* Clear the FAULT pin latch as something latched */
>> + regmap_write(tas->regmap, TAS675X_RESET_REG, TAS675X_FAULT_CLEAR);
>> +
>> + return IRQ_HANDLED;
>> +}
>
> Also, this should return IRQ_NONE if no faults were seen (to allow for
> interrupt sharing and the genirq core's handling of hardware faults).
Understood, thank you for the context, didn't know IRQ_NONE provides
additional heuristics to irq core. Will post a follow-up V3 addressing
the issues.
Best,
Sen Wang
^ permalink raw reply
* Re: [PATCH net-next v2 10/11] net: airoha: Do not stop GDM port if it is shared
From: Jakub Kicinski @ 2026-04-03 1:12 UTC (permalink / raw)
To: lorenzo
Cc: Jakub Kicinski, andrew+netdev, davem, edumazet, pabeni, robh,
krzk+dt, conor+dt, ansuelsmth, benjamin.larsson, linux-arm-kernel,
linux-mediatek, netdev, devicetree
In-Reply-To: <20260401-airoha-eth-multi-serdes-v2-10-ac427ae4beeb@kernel.org>
This is an AI-generated review of your patch. The human sending this
email has considered the AI review valid, or at least plausible.
---
net: airoha: Do not stop GDM port if it is shared
This patch introduces a port->users reference counter to prevent setting
the GDM port forward configuration to FE_PSE_PORT_DROP if another net_device
is still using the shared GDM port.
> diff --git a/drivers/net/ethernet/airoha/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c
> index 0780fb8aacfb..3f9bce8c5370 100644
> --- a/drivers/net/ethernet/airoha/airoha_eth.c
> +++ b/drivers/net/ethernet/airoha/airoha_eth.c
[ ... ]
> @@ -1681,9 +1682,6 @@ static int airoha_dev_stop(struct net_device *netdev)
> for (i = 0; i < ARRAY_SIZE(qdma->q_tx); i++)
> netdev_tx_reset_subqueue(netdev, i);
>
> - airoha_set_gdm_port_fwd_cfg(qdma->eth, REG_GDM_FWD_CFG(port->id),
> - FE_PSE_PORT_DROP);
> -
> if (atomic_dec_and_test(&qdma->users)) {
> airoha_qdma_clear(qdma, REG_QDMA_GLOBAL_CFG,
> GLOBAL_CFG_TX_DMA_EN_MASK |
While this patch aims to support shared GDM ports, does the remaining
unconditional call to airoha_set_vip_for_gdm_port(dev, false) at the start
of airoha_dev_stop() break other active devices sharing the port?
static int airoha_dev_stop(struct net_device *netdev)
{
...
err = airoha_set_vip_for_gdm_port(dev, false);
...
}
This appears to clear the REG_FE_VIP_PORT_EN and REG_FE_IFC_PORT_EN hardware
bits for the physical port, which might instantly kill traffic for any other
active interface using the shared port.
Similarly, in airoha_dev_open() and airoha_dev_change_mtu(), the
REG_GDM_LEN_CFG (MTU) is overwritten unconditionally. If a device with a
smaller MTU is brought up, will it overwrite the shared port's MTU limit
and cause the hardware to silently drop larger packets for the other device?
[ ... ]
> @@ -1697,6 +1695,11 @@ static int airoha_dev_stop(struct net_device *netdev)
> }
> }
>
> + if (atomic_dec_and_test(&port->users))
> + airoha_set_gdm_port_fwd_cfg(qdma->eth,
> + REG_GDM_FWD_CFG(port->id),
> + FE_PSE_PORT_DROP);
> +
> return 0;
> }
Does moving this FE_PSE_PORT_DROP configuration to the end of airoha_dev_stop()
cause a race condition when stopping the device?
In airoha_dev_open(), the driver correctly enables the QDMA engine before
configuring the GDM port to forward packets. A safe teardown typically
mirrors this by first stopping the packet source (setting FE_PSE_PORT_DROP)
and then disabling the destination DMA engine.
By moving airoha_set_gdm_port_fwd_cfg() after the airoha_qdma_clear() block,
when both qdma->users and port->users reach zero, the QDMA engine and its
queues are shut down while the GDM port is still actively forwarding packets.
Could incoming packets be forwarded to a disabled DMA engine during this
window, risking hardware lockups or buffer leaks?
^ permalink raw reply
* Re: [PATCH net-next v2 09/11] net: airoha: Support multiple net_devices for a single FE GDM port
From: Jakub Kicinski @ 2026-04-03 1:12 UTC (permalink / raw)
To: lorenzo
Cc: Jakub Kicinski, andrew+netdev, davem, edumazet, pabeni, robh,
krzk+dt, conor+dt, ansuelsmth, benjamin.larsson, linux-arm-kernel,
linux-mediatek, netdev, devicetree
In-Reply-To: <20260401-airoha-eth-multi-serdes-v2-9-ac427ae4beeb@kernel.org>
This is an AI-generated review of your patch. The human sending this
email has considered the AI review valid, or at least plausible.
---
Subject: net: airoha: Support multiple net_devices for a single FE GDM port
This commit introduces support for multiple net_devices connected to the
same Frame Engine (FE) GDM port via an external hardware arbiter. It
adds logic to parse device tree child nodes and instantiate separate
net_devices for TDM traffic from external SerDes.
> diff --git a/drivers/net/ethernet/airoha/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c
> index 5e489e8593ba..0780fb8aacfb 100644
> --- a/drivers/net/ethernet/airoha/airoha_eth.c
> +++ b/drivers/net/ethernet/airoha/airoha_eth.c
[ ... ]
> @@ -614,9 +616,8 @@ static int airoha_qdma_rx_process(struct airoha_queue *q, int budget)
> u32 hash, reason, msg1 = le32_to_cpu(desc->msg1);
> struct page *page = virt_to_head_page(e->buf);
> u32 desc_ctrl = le32_to_cpu(desc->ctrl);
> - struct airoha_gdm_port *port;
> - struct net_device *netdev;
> - int data_len, len, p;
> + struct airoha_gdm_dev *dev;
> + int data_len, len;
>
> if (!(desc_ctrl & QDMA_DESC_DONE_MASK))
> break;
> @@ -633,12 +634,10 @@ static int airoha_qdma_rx_process(struct airoha_queue *q, int budget)
> if (!len || data_len < len)
> goto free_frag;
>
> - p = airoha_qdma_get_gdm_port(eth, desc);
> - if (p < 0 || !eth->ports[p])
> + dev = airoha_qdma_get_gdm_dev(eth, desc);
> + if (IS_ERR(dev))
> goto free_frag;
If a scattered frame is being processed (q->skb is not NULL) and IS_ERR(dev)
triggers the goto free_frag, the error handler frees the skb:
free_frag:
if (q->skb) {
dev_kfree_skb(q->skb);
q->skb = NULL;
} else {
page_pool_put_full_page(q->page_pool, page, true);
}
Since the current fragment's page is not yet attached to q->skb, does this
skip the else branch and permanently leak the page pool buffer?
[ ... ]
> @@ -1747,9 +1748,7 @@ static int airoha_set_gdm2_loopback(struct airoha_gdm_dev *dev)
> airoha_fe_clear(eth, REG_FE_VIP_PORT_EN, BIT(AIROHA_GDM2_IDX));
> airoha_fe_clear(eth, REG_FE_IFC_PORT_EN, BIT(AIROHA_GDM2_IDX));
>
> - /* XXX: handle XSI_USB_PORT and XSI_PCE1_PORT */
> - nbq = port->id == AIROHA_GDM3_IDX && airoha_is_7581(eth) ? 4 : 0;
> - src_port = eth->soc->ops.get_src_port_id(port, nbq);
> + src_port = eth->soc->ops.get_src_port_id(port, dev->nbq);
> if (src_port < 0)
> return src_port;
With multiple net_devices instantiated for the same physical GDM port, does
the initialization of sibling devices overwrite shared hardware registers?
For example, when airoha_set_gdm2_loopback() uses src_port to configure
REG_FE_WAN_PORT, it explicitly clears the WAN port routing masks:
airoha_fe_rmw(eth, REG_FE_WAN_PORT,
WAN1_EN_MASK | WAN1_MASK | WAN0_MASK,
FIELD_PREP(WAN0_MASK, src_port));
Will the last initialized device clobber the WAN routing configurations and
hardware MAC filters for the others, causing their traffic to be dropped?
[ ... ]
> @@ -1970,7 +1969,8 @@ static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb,
> }
>
> fport = airoha_get_fe_port(dev);
> - msg1 = FIELD_PREP(QDMA_ETH_TXMSG_FPORT_MASK, fport) |
> + msg1 = FIELD_PREP(QDMA_ETH_TXMSG_NBOQ_MASK, dev->nbq) |
> + FIELD_PREP(QDMA_ETH_TXMSG_FPORT_MASK, fport) |
> FIELD_PREP(QDMA_ETH_TXMSG_METER_MASK, 0x7f);
>
> q = &qdma->q_tx[qid];
When multiple net_devices share a single QDMA instance and its TX rings
(qdma->q_tx), a TX queue stall might occur here.
If the shared hardware ring fills up, netif_tx_stop_queue() stops the
transmitting device's queue. Later, when descriptors are freed, the driver
only wakes the queue corresponding to the specific packet that just completed.
If multiple devices' TX queues are stopped, will the other devices' queues
remain stalled unless their specific packets happen to be processed?
[ ... ]
> @@ -2897,10 +2900,11 @@ bool airoha_is_valid_gdm_dev(struct airoha_eth *eth,
>
> static int airoha_alloc_gdm_device(struct airoha_eth *eth,
> struct airoha_gdm_port *port,
> - struct device_node *np)
> + int nbq, struct device_node *np)
> {
> - struct airoha_gdm_dev *dev;
> struct net_device *netdev;
> + struct airoha_gdm_dev *dev;
> + u8 index;
> int err;
[ ... ]
> + /* Allowed nbq for EN7581 on GDM3 port are 4 and 5 for PCIE0
> + * and PCIE1 respectively.
> + */
> + index = nbq;
> + if (airoha_is_7581(eth) && port->id == AIROHA_GDM3_IDX)
> + index -= 4;
> +
> + if (index >= ARRAY_SIZE(port->devs) || port->devs[index]) {
> + dev_err(eth->dev, "invalid nbq id: %d\n", nbq);
> + return -EINVAL;
> + }
There are two potential issues regarding the new index logic:
First, does this break probing for older device trees without child nodes?
When falling back to airoha_alloc_gdm_device(..., 0, np) with nbq = 0,
the index -= 4 operation for AIROHA_GDM3_IDX will cause the u8 index to
underflow to 252. The bounds check 252 >= 2 fails, returning -EINVAL.
Second, can an invalid device tree value bypass the bounds check?
The int nbq parameter is directly assigned to the u8 index. If a large value
like reg = <256> is provided, it truncates to 0, passing the index >= 2
check. The un-truncated int nbq is then stored in dev->nbq, potentially
causing out-of-bounds shifts when used in hardware macros.
[ ... ]
> @@ -2986,7 +3004,36 @@ static int airoha_alloc_gdm_port(struct airoha_eth *eth,
> if (err)
> return err;
>
> - return airoha_alloc_gdm_device(eth, port, np);
> + for_each_child_of_node(np, node) {
> + /* Multiple external serdes connected to the FE GDM port via an
> + * external arbiter.
> + */
> + const __be32 *nbq_ptr;
> +
> + if (!of_device_is_compatible(node, "airoha,eth-port"))
> + continue;
> +
> + d++;
> + if (!of_device_is_available(node))
> + continue;
> +
> + nbq_ptr = of_get_property(node, "reg", NULL);
> + if (!nbq_ptr) {
> + dev_err(eth->dev, "missing nbq id\n");
> + err = -EINVAL;
> + of_node_put(node);
> + break;
> + }
> +
> + err = airoha_alloc_gdm_device(eth, port, be32_to_cpup(nbq_ptr),
> + node);
> + if (err) {
> + of_node_put(node);
> + return err;
> + }
> + }
> +
> + return !d ? airoha_alloc_gdm_device(eth, port, 0, np) : 0;
> }
If nbq_ptr is missing, err = -EINVAL is set and the loop breaks. However,
since the child counter d was already incremented, the final statement
evaluates to 0 (success) because !d is false.
Does this swallow the -EINVAL error and cause a silent failure where the
driver continues probing without initializing the misconfigured GDM devices?
Additionally, the for_each_child_of_node() iterator automatically handles
taking and dropping the reference to node.
When node is passed to airoha_alloc_gdm_device(), it is directly assigned:
netdev->dev.of_node = np;
Since of_node_get() is not called, when the loop iteration finishes and drops
the reference, does this leave the net_device pointing to a freed device
tree node?
--
pw-bot: cr
^ permalink raw reply
* Re: [PATCh v3 07/14] ASoC: rsnd: ssui: Add RZ/G3E SSIU BUSIF support
From: Kuninori Morimoto @ 2026-04-03 1:09 UTC (permalink / raw)
To: John Madieu
Cc: Mark Brown, Liam Girdwood, Geert Uytterhoeven, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Jaroslav Kysela, Takashi Iwai,
Magnus Damm, Philipp Zabel, Claudiu Beznea, Biju Das, john.madieu,
linux-sound, linux-renesas-soc, devicetree, linux-kernel
In-Reply-To: <20260402162436.12059-8-john.madieu.xa@bp.renesas.com>
Hi John
Thank you for your patch
> Add support for the SSIU found on the Renesas RZ/G3E SoC, which
> provides a different BUSIF layout compared to earlier generations:
>
> - SSI0-SSI4: 4 BUSIF instances each (BUSIF0-3)
> - SSI5-SSI8: 1 BUSIF instance each (BUSIF0 only)
> - SSI9: 4 BUSIF instances (BUSIF0-3)
> - Total: 28 BUSIFs
>
> RZ/G3E also differs from Gen2/Gen3 implementations in that only two
> pairs of BUSIF error-status registers are available instead of four,
> and the SSI always operates in BUSIF mode with no PIO fallback.
>
> Rather than scattering SoC-specific checks across functional code,
> introduce an extra capability flags in the match data:
>
> - RSND_SSIU_BUSIF_STATUS_COUNT_2: only two BUSIF error-status
> register pairs are present. Used in rsnd_ssiu_busif_err_irq_ctrl()
> and rsnd_ssiu_busif_err_status_clear() to limit register iteration.
>
> Future SoCs sharing these constraints can set the flags without
> requiring code changes.
>
> Signed-off-by: John Madieu <john.madieu.xa@bp.renesas.com>
> ---
(snip)
> @@ -72,7 +73,7 @@ static void rsnd_ssiu_busif_err_irq_ctrl(struct rsnd_mod *mod, int enable)
> return;
> }
>
> - for (i = 0; i < 4; i++) {
> + for (unsigned int i = 0; i < priv->ssiu_busif_count; i++) {
> enum rsnd_reg reg = SSI_SYS_INT_ENABLE((i * 2) + offset);
> u32 val = 0xf << (shift * 4);
> u32 sys_int_enable = rsnd_mod_read(mod, reg);
(snip)
> @@ -109,7 +110,7 @@ bool rsnd_ssiu_busif_err_status_clear(struct rsnd_mod *mod)
> goto out;
> }
>
> - for (i = 0; i < 4; i++) {
> + for (unsigned int i = 0; i < priv->ssiu_busif_count; i++) {
> u32 reg = SSI_SYS_STATUS(i * 2) + offset;
> u32 status = rsnd_mod_read(mod, reg);
> u32 val = 0xf << (shift * 4);
ssiu_busif_count is for SSIU specific, no need to have it on priv.
Please move it on rsnd_ssiu.
Thank you for your help !!
Best regards
---
Kuninori Morimoto
^ permalink raw reply
* Re: [PATCh v3 06/14] ASoC: rsnd: Add RZ/G3E DMA address calculation support
From: Kuninori Morimoto @ 2026-04-03 1:08 UTC (permalink / raw)
To: John Madieu
Cc: Mark Brown, Liam Girdwood, Geert Uytterhoeven, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Jaroslav Kysela, Takashi Iwai,
Magnus Damm, Philipp Zabel, Claudiu Beznea, Biju Das, john.madieu,
linux-sound, linux-renesas-soc, devicetree, linux-kernel
In-Reply-To: <20260402162436.12059-7-john.madieu.xa@bp.renesas.com>
Hi John
Thank you for your patch
> RZ/G3E has different DMA register base addresses and offset
> calculations compared to R-Car platforms.
>
> Add dedicated rsnd_rzg3e_dma_addr() function with dispatch from
> rsnd_dma_addr(), following the existing per-generation pattern.
>
> Signed-off-by: John Madieu <john.madieu.xa@bp.renesas.com>
> ---
(snip)
> diff --git a/sound/soc/renesas/rcar/dma.c b/sound/soc/renesas/rcar/dma.c
> index 0afe4636b005..5b63206361ef 100644
> --- a/sound/soc/renesas/rcar/dma.c
> +++ b/sound/soc/renesas/rcar/dma.c
> @@ -496,7 +496,35 @@ static struct rsnd_mod_ops rsnd_dmapp_ops = {
> * SSIU: 0xec541000 / 0xec100000 / 0xec100000 / 0xec400000 / 0xec400000
> * SCU : 0xec500000 / 0xec000000 / 0xec004000 / 0xec300000 / 0xec304000
> * CMD : 0xec500000 / / 0xec008000 0xec308000
> + *
> + * ex) G3E case
> + * mod / DMAC in / DMAC out / DMAC PP in / DMAC pp out
> + * SSI : 0x13C31000 / 0x13C40000 / 0x13C40000
> + * SSIU: 0x13C31000 / 0x13C40000 / 0x13C40000 / 0xEC400000 / 0xEC400000
> + * SCU : 0x13C00000 / 0x13C10000 / 0x13C14000 / 0xEC300000 / 0xEC304000
> + * CMD : 0x13C00000 / / 0x13C18000 0xEC308000
> */
> +
> +/* RZ/G3E DMA address macros */
> +#define RDMA_SSI_I_N_G3E(addr, i) (addr ##_reg + 0x0000F000 + (0x1000 * i))
> +#define RDMA_SSI_O_N_G3E(addr, i) (addr ##_reg + 0x0000F000 + (0x1000 * i))
> +
> +#define RDMA_SSIU_I_N_G3E(addr, i, j) (addr ##_reg + 0x0000F000 + (0x1000 * (i)) + (((j) / 4) * 0xA000) + (((j) % 4) * 0x400) - (0x4000 * ((i) / 9) * ((j) / 4)))
> +#define RDMA_SSIU_O_N_G3E(addr, i, j) RDMA_SSIU_I_N_G3E(addr, i, j)
> +
> +#define RDMA_SSIU_I_P_G3E(addr, i, j) (addr ##_reg + 0xD87CF000 + (0x1000 * (i)) + (((j) / 4) * 0xA000) + (((j) % 4) * 0x400) - (0x4000 * ((i) / 9) * ((j) / 4)))
> +#define RDMA_SSIU_O_P_G3E(addr, i, j) RDMA_SSIU_I_P_G3E(addr, i, j)
> +
> +#define RDMA_SRC_I_N_G3E(addr, i) (addr ##_reg + 0x00010000 + (0x400 * i))
> +#define RDMA_SRC_O_N_G3E(addr, i) (addr ##_reg + 0x00014000 + (0x400 * i))
> +
> +#define RDMA_SRC_I_P_G3E(addr, i) (addr ##_reg + 0xD8700000 + (0x400 * i))
> +#define RDMA_SRC_O_P_G3E(addr, i) (addr ##_reg + 0xD8704000 + (0x400 * i))
> +
> +#define RDMA_CMD_O_N_G3E(addr, i) (addr ##_reg + 0x00018000 + (0x400 * i))
> +#define RDMA_CMD_O_P_G3E(addr, i) (addr ##_reg + 0xD8708000 + (0x400 * i))
Please add RZ/G3E info on top of rzg3e_dma_addr()
> +/* R-Car DMA address macros */
> #define RDMA_SSI_I_N(addr, i) (addr ##_reg - 0x00300000 + (0x40 * i) + 0x8)
> #define RDMA_SSI_O_N(addr, i) (addr ##_reg - 0x00300000 + (0x40 * i) + 0xc)
And R-Car Gen2 info to gen2_dma_addr()
> +rsnd_dma_addr_lookup(struct rsnd_dai_stream *io,
> + struct rsnd_mod *mod,
> + const struct rsnd_dma_addr tbl[3][2][3],
> + int is_play, int is_from)
> {
> - struct rsnd_priv *priv = rsnd_io_to_priv(io);
> - struct device *dev = rsnd_priv_to_dev(priv);
> - phys_addr_t ssi_reg = rsnd_gen_get_phy_addr(priv, RSND_BASE_SSI);
> - phys_addr_t src_reg = rsnd_gen_get_phy_addr(priv, RSND_BASE_SCU);
> + struct device *dev = rsnd_priv_to_dev(rsnd_io_to_priv(io));
Creating lookup() is nice idea.
Very nitpick, but do we need to remove priv, and remake dev ?
> @@ -574,20 +671,10 @@ rsnd_gen2_dma_addr(struct rsnd_dai_stream *io,
> * out of calculation rule
> */
> if ((id == 9) && (busif >= 4))
> - dev_err(dev, "This driver doesn't support SSI%d-%d, so far",
> - id, busif);
> -
> - /* it shouldn't happen */
> - if (use_cmd && !use_src)
> - dev_err(dev, "DVC is selected without SRC\n");
> -
> - /* use SSIU or SSI ? */
> - if (is_ssi && rsnd_ssi_use_busif(io))
> - is_ssi++;
> + dev_err(rsnd_priv_to_dev(priv),
> + "This driver doesn't support SSI%d-%d, so far", id, busif);
Very nitpick, but please keep dev on top.
Thank you for your help !!
Best regards
---
Kuninori Morimoto
^ permalink raw reply
* Re: [PATCh v3 05/14] ASoC: rsnd: Add audmacpp clock and reset support for RZ/G3E
From: Kuninori Morimoto @ 2026-04-03 1:06 UTC (permalink / raw)
To: John Madieu
Cc: Mark Brown, Liam Girdwood, Geert Uytterhoeven, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Jaroslav Kysela, Takashi Iwai,
Magnus Damm, Philipp Zabel, Claudiu Beznea, Biju Das, john.madieu,
linux-sound, linux-renesas-soc, devicetree, linux-kernel
In-Reply-To: <20260402162436.12059-6-john.madieu.xa@bp.renesas.com>
Hi John
Thank you for your patch
> RZ/G3E requires additional audmapp clock and reset lines for
> Audio DMA-PP operation.
>
> Add global audmacpp clock/reset management in rsnd_dma_probe()
> using optional APIs to remain transparent to other platforms.
>
> Signed-off-by: John Madieu <john.madieu.xa@bp.renesas.com>
> ---
(snip)
> --- a/sound/soc/renesas/rcar/rsnd.h
> +++ b/sound/soc/renesas/rcar/rsnd.h
> @@ -623,6 +623,13 @@ void rsnd_adg_clk_dbg_info(struct rsnd_priv *priv, struct seq_file *m);
> struct rsnd_priv {
>
> struct platform_device *pdev;
> +
> + /*
> + * below value will be filled on rsnd_dma_probe()
> + */
> + struct clk *audmapp_clk;
> + struct reset_control *audmapp_rstc;
I think it is DMA specific.
I think we can move it to struct rsnd_dma, instead of in rsnd_priv ?
Thank you for your help !!
Best regards
---
Kuninori Morimoto
^ permalink raw reply
* [PATCH v2 2/2] spmi: spmi-pmic-arb: add support for PMIC arbiter v8.5
From: Fenglin Wu @ 2026-04-03 0:55 UTC (permalink / raw)
To: Stephen Boyd, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Konrad Dybcio
Cc: Subbaraman Narayanamurthy, David Collins, linux-arm-msm,
linux-kernel, devicetree, kernel, Fenglin Wu
In-Reply-To: <20260402-hawi-spmi-v2-0-0bbe811fe3f4@oss.qualcomm.com>
PMIC arbiter v8.5 is an extension of PMIC arbiter v8 that updated
the definition of the channel status register bit fields. Add support
to handle this difference.
Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Signed-off-by: Fenglin Wu <fenglin.wu@oss.qualcomm.com>
---
drivers/spmi/spmi-pmic-arb.c | 69 ++++++++++++++++++++++++++++++++++++++------
1 file changed, 60 insertions(+), 9 deletions(-)
diff --git a/drivers/spmi/spmi-pmic-arb.c b/drivers/spmi/spmi-pmic-arb.c
index 69f8d456324a..deeaa39bb647 100644
--- a/drivers/spmi/spmi-pmic-arb.c
+++ b/drivers/spmi/spmi-pmic-arb.c
@@ -28,6 +28,7 @@
#define PMIC_ARB_VERSION_V5_MIN 0x50000000
#define PMIC_ARB_VERSION_V7_MIN 0x70000000
#define PMIC_ARB_VERSION_V8_MIN 0x80000000
+#define PMIC_ARB_VERSION_V8P5_MIN 0x80050000
#define PMIC_ARB_INT_EN 0x0004
#define PMIC_ARB_FEATURES 0x0004
@@ -63,11 +64,34 @@
#define SPMI_OWNERSHIP_PERIPH2OWNER(X) ((X) & 0x7)
/* Channel Status fields */
-enum pmic_arb_chnl_status {
- PMIC_ARB_STATUS_DONE = BIT(0),
- PMIC_ARB_STATUS_FAILURE = BIT(1),
- PMIC_ARB_STATUS_DENIED = BIT(2),
- PMIC_ARB_STATUS_DROPPED = BIT(3),
+struct pmic_arb_chnl_status_mask {
+ u8 done;
+ u8 failure;
+ u8 crc;
+ u8 parity;
+ u8 nack;
+ u8 denied;
+ u8 dropped;
+};
+
+static const struct pmic_arb_chnl_status_mask chnl_status_mask = {
+ .done = BIT(0),
+ .failure = BIT(1),
+ .crc = 0,
+ .parity = 0,
+ .nack = 0,
+ .denied = BIT(2),
+ .dropped = BIT(3),
+};
+
+static const struct pmic_arb_chnl_status_mask chnl_status_mask_v8p5 = {
+ .done = BIT(0),
+ .failure = BIT(1),
+ .crc = BIT(2),
+ .parity = BIT(3),
+ .nack = BIT(4),
+ .denied = BIT(5),
+ .dropped = BIT(6),
};
/* Command register fields */
@@ -201,6 +225,7 @@ struct spmi_pmic_arb_bus {
* @max_periphs: Number of elements in apid_data[]
* @buses: per arbiter buses instances
* @buses_available: number of buses registered
+ * @chnl_status_mask: Bit masks of channel status fields
*/
struct spmi_pmic_arb {
void __iomem *rd_base;
@@ -214,6 +239,7 @@ struct spmi_pmic_arb {
int max_periphs;
struct spmi_pmic_arb_bus *buses[PMIC_ARB_MAX_BUSES];
int buses_available;
+ const struct pmic_arb_chnl_status_mask *chnl_status_mask;
};
/**
@@ -312,6 +338,7 @@ static int pmic_arb_wait_for_done(struct spmi_controller *ctrl,
{
struct spmi_pmic_arb_bus *bus = spmi_controller_get_drvdata(ctrl);
struct spmi_pmic_arb *pmic_arb = bus->pmic_arb;
+ const struct pmic_arb_chnl_status_mask *mask;
u32 status = 0;
u32 timeout = PMIC_ARB_TIMEOUT_US;
u32 offset;
@@ -323,30 +350,49 @@ static int pmic_arb_wait_for_done(struct spmi_controller *ctrl,
offset = rc;
offset += PMIC_ARB_STATUS;
+ mask = pmic_arb->chnl_status_mask;
while (timeout--) {
status = readl_relaxed(base + offset);
- if (status & PMIC_ARB_STATUS_DONE) {
- if (status & PMIC_ARB_STATUS_DENIED) {
+ if (status & mask->done) {
+ if (status & mask->denied) {
dev_err(&ctrl->dev, "%s: %#x %#x: transaction denied (%#x)\n",
__func__, sid, addr, status);
return -EPERM;
}
- if (status & PMIC_ARB_STATUS_FAILURE) {
+ if (status & mask->failure) {
dev_err(&ctrl->dev, "%s: %#x %#x: transaction failed (%#x) reg: 0x%x\n",
__func__, sid, addr, status, offset);
WARN_ON(1);
return -EIO;
}
- if (status & PMIC_ARB_STATUS_DROPPED) {
+ if (status & mask->dropped) {
dev_err(&ctrl->dev, "%s: %#x %#x: transaction dropped (%#x)\n",
__func__, sid, addr, status);
return -EIO;
}
+ if (status & mask->crc) {
+ dev_err(&ctrl->dev, "%s: %#x %#x: CRC error (%#x)\n",
+ __func__, sid, addr, status);
+ return -EIO;
+ }
+
+ if (status & mask->parity) {
+ dev_err(&ctrl->dev, "%s: %#x %#x: parity error (%#x)\n",
+ __func__, sid, addr, status);
+ return -EIO;
+ }
+
+ if (status & mask->nack) {
+ dev_err(&ctrl->dev, "%s: %#x %#x: NACK error (%#x)\n",
+ __func__, sid, addr, status);
+ return -EIO;
+ }
+
return 0;
}
udelay(1);
@@ -2033,6 +2079,11 @@ static int spmi_pmic_arb_probe(struct platform_device *pdev)
else
pmic_arb->ver_ops = &pmic_arb_v8;
+ if (hw_ver < PMIC_ARB_VERSION_V8P5_MIN)
+ pmic_arb->chnl_status_mask = &chnl_status_mask;
+ else
+ pmic_arb->chnl_status_mask = &chnl_status_mask_v8p5;
+
err = pmic_arb->ver_ops->get_core_resources(pdev, core);
if (err)
return err;
--
2.43.0
^ permalink raw reply related
* [PATCH v2 1/2] dt-bindings: spmi: glymur-spmi-pmic-arb: Add compatible for Qualcomm Hawi SoC
From: Fenglin Wu @ 2026-04-03 0:55 UTC (permalink / raw)
To: Stephen Boyd, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Konrad Dybcio
Cc: Subbaraman Narayanamurthy, David Collins, linux-arm-msm,
linux-kernel, devicetree, kernel, Fenglin Wu
In-Reply-To: <20260402-hawi-spmi-v2-0-0bbe811fe3f4@oss.qualcomm.com>
The PMIC arbiter in the Qualcomm Hawi SoC is version v8.5, which
introduces parity and CRC checks for data received from the PMIC,
as well as NACK checks for command sequences except for read.
All other features in PMIC arbiter remain the same as the one in
the Qualcomm Glymur SoC, with the only differences being some
additional error status checks.
Therefore, add a string for "qcom,hawi-spmi-pmic-arb" as a compatible
entry for "qcom,glymur-spmi-pmic-arb".
Signed-off-by: Fenglin Wu <fenglin.wu@oss.qualcomm.com>
---
Documentation/devicetree/bindings/spmi/qcom,glymur-spmi-pmic-arb.yaml | 1 +
1 file changed, 1 insertion(+)
diff --git a/Documentation/devicetree/bindings/spmi/qcom,glymur-spmi-pmic-arb.yaml b/Documentation/devicetree/bindings/spmi/qcom,glymur-spmi-pmic-arb.yaml
index 3b5005b96c6d..1593a1183a36 100644
--- a/Documentation/devicetree/bindings/spmi/qcom,glymur-spmi-pmic-arb.yaml
+++ b/Documentation/devicetree/bindings/spmi/qcom,glymur-spmi-pmic-arb.yaml
@@ -25,6 +25,7 @@ properties:
oneOf:
- items:
- enum:
+ - qcom,hawi-spmi-pmic-arb
- qcom,kaanapali-spmi-pmic-arb
- const: qcom,glymur-spmi-pmic-arb
- enum:
--
2.43.0
^ permalink raw reply related
* [PATCH v2 0/2] spmi: pmic-arb: Add spmi-pmic-arb support for Qualcomm Hawi SoC
From: Fenglin Wu @ 2026-04-03 0:55 UTC (permalink / raw)
To: Stephen Boyd, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Konrad Dybcio
Cc: Subbaraman Narayanamurthy, David Collins, linux-arm-msm,
linux-kernel, devicetree, kernel, Fenglin Wu
Add compatible for Hawi SoC and add pmic-arb v8.5 support.
Signed-off-by: Fenglin Wu <fenglin.wu@oss.qualcomm.com>
---
Changes in v2:
- Revise patch 1 commit text to highlight the new features of the
PMIC arbiter in the Hawi SoC, and clarify how it is compatible
within the Glymur SoC.
- Link to v1: https://patch.msgid.link/20260401-hawi-spmi-v1-0-c40963041078@oss.qualcomm.com
---
Fenglin Wu (2):
dt-bindings: spmi: glymur-spmi-pmic-arb: Add compatible for Qualcomm Hawi SoC
spmi: spmi-pmic-arb: add support for PMIC arbiter v8.5
.../bindings/spmi/qcom,glymur-spmi-pmic-arb.yaml | 1 +
drivers/spmi/spmi-pmic-arb.c | 69 +++++++++++++++++++---
2 files changed, 61 insertions(+), 9 deletions(-)
---
base-commit: 840b0dd6b8c169e963f74265f508c54f1fe3c968
change-id: 20260323-hawi-spmi-a29ef97409a4
Best regards,
--
Fenglin Wu <fenglin.wu@oss.qualcomm.com>
^ permalink raw reply
* Re: [PATCH v5 2/3] arm64: dts: rockchip: refactor items from Orange Pi 5/b to prep for Pro
From: Andrew Lunn @ 2026-04-03 0:53 UTC (permalink / raw)
To: Dennis Gilmore
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Heiko Stuebner,
FUKAUMI Naoki, Hsun Lai, Jonas Karlman, Chaoyi Chen, John Clark,
Michael Opdenacker, Quentin Schulz, Chukun Pan, Alexey Charkov,
Peter Robinson, Michael Riesch, Mykola Kvach, Jimmy Hon,
devicetree, linux-arm-kernel, linux-rockchip, linux-kernel
In-Reply-To: <CAABkxwvnv7i=xg53qu4JDapBs6ATaMGh9iXZfi+od=CCxRxQUA@mail.gmail.com>
On Wed, Apr 01, 2026 at 08:27:30AM -0500, Dennis Gilmore wrote:
> Hi Andrew,
>
> On Wed, Apr 1, 2026 at 6:52 AM Andrew Lunn <andrew@lunn.ch> wrote:
> >
> > > +&gmac1 {
> > > + clock_in_out = "output";
> > > + phy-handle = <&rgmii_phy1>;
> > > + phy-mode = "rgmii-rxid";
> > > + pinctrl-0 = <&gmac1_miim
> > > + &gmac1_tx_bus2
> > > + &gmac1_rx_bus2
> > > + &gmac1_rgmii_clk
> > > + &gmac1_rgmii_bus>;
> > > + pinctrl-names = "default";
> > > + tx_delay = <0x42>;
> >
> > phy-mode = "rgmii-rxid" means the PCB provides the 2ns delay for
> > TX. This is unlikely to be correct. Please try "rgmii-id" and delete
> > the tx_delay.
>
> As I mentioned to you in v2 I do not have the affected hardware to
> test any changes. This patch is just moving the existing definition
> from the common dtsi to the two devices that have gmac1 wired up. I
> am not comfortable making changes here that I can not verify if they
> work or not.
Yes, sorry.
Please add this to the commit message, so i don't make the same point
again.
Andrew
^ permalink raw reply
* [PATCH v3 8/9] driver core: Replace dev->of_node_reused with DEV_FLAG_OF_NODE_REUSED
From: Douglas Anderson @ 2026-04-03 0:49 UTC (permalink / raw)
To: Greg Kroah-Hartman, Rafael J . Wysocki, Danilo Krummrich,
Alan Stern
Cc: Robin Murphy, Leon Romanovsky, Paul Burton, Saravana Kannan,
Alexander Lobakin, Eric Dumazet, Toshi Kani, Christoph Hellwig,
Alexey Kardashevskiy, Johan Hovold, Douglas Anderson,
alexander.stein, andrew, andrew, andriy.shevchenko, astewart,
bhelgaas, brgl, broonie, davem, devicetree, driver-core,
hkallweit1, jirislaby, joel, kees, kuba, lgirdwood,
linux-arm-kernel, linux-aspeed, linux-kernel, linux-pci,
linux-serial, linux-usb, linux, mani, netdev, pabeni, robh
In-Reply-To: <20260403005005.30424-1-dianders@chromium.org>
In C, bitfields are not necessarily safe to modify from multiple
threads without locking. Switch "of_node_reused" over to the "flags"
field so modifications are safe.
Cc: Johan Hovold <johan@kernel.org>
Signed-off-by: Douglas Anderson <dianders@chromium.org>
---
Not fixing any known bugs; problem is theoretical and found by code
inspection. Change is done somewhat manually and only lightly tested
(mostly compile-time tested).
Changes in v3:
- New
drivers/base/core.c | 2 +-
drivers/base/pinctrl.c | 2 +-
drivers/base/platform.c | 2 +-
drivers/net/pcs/pcs-xpcs-plat.c | 2 +-
drivers/of/device.c | 6 +++---
drivers/pci/of.c | 2 +-
drivers/pci/pwrctrl/core.c | 2 +-
drivers/regulator/bq257xx-regulator.c | 2 +-
drivers/regulator/rk808-regulator.c | 2 +-
drivers/tty/serial/serial_base_bus.c | 2 +-
drivers/usb/gadget/udc/aspeed-vhub/dev.c | 2 +-
include/linux/device.h | 6 +++---
12 files changed, 16 insertions(+), 16 deletions(-)
diff --git a/drivers/base/core.c b/drivers/base/core.c
index 00005777c21f..a87bd40499b6 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -5282,7 +5282,7 @@ void device_set_of_node_from_dev(struct device *dev, const struct device *dev2)
{
of_node_put(dev->of_node);
dev->of_node = of_node_get(dev2->of_node);
- dev->of_node_reused = true;
+ set_bit(DEV_FLAG_OF_NODE_REUSED, &dev->flags);
}
EXPORT_SYMBOL_GPL(device_set_of_node_from_dev);
diff --git a/drivers/base/pinctrl.c b/drivers/base/pinctrl.c
index 6e250272c843..62c228c75d50 100644
--- a/drivers/base/pinctrl.c
+++ b/drivers/base/pinctrl.c
@@ -24,7 +24,7 @@ int pinctrl_bind_pins(struct device *dev)
{
int ret;
- if (dev->of_node_reused)
+ if (test_bit(DEV_FLAG_OF_NODE_REUSED, &dev->flags))
return 0;
dev->pins = devm_kzalloc(dev, sizeof(*(dev->pins)), GFP_KERNEL);
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index d44591d52e36..5128ff7e5e78 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -856,7 +856,7 @@ struct platform_device *platform_device_register_full(
pdev->dev.parent = pdevinfo->parent;
pdev->dev.fwnode = pdevinfo->fwnode;
pdev->dev.of_node = of_node_get(to_of_node(pdev->dev.fwnode));
- pdev->dev.of_node_reused = pdevinfo->of_node_reused;
+ assign_bit(DEV_FLAG_OF_NODE_REUSED, &pdev->dev.flags, pdevinfo->of_node_reused);
if (pdevinfo->dma_mask) {
pdev->platform_dma_mask = pdevinfo->dma_mask;
diff --git a/drivers/net/pcs/pcs-xpcs-plat.c b/drivers/net/pcs/pcs-xpcs-plat.c
index b8c48f9effbf..c2722d8bd98a 100644
--- a/drivers/net/pcs/pcs-xpcs-plat.c
+++ b/drivers/net/pcs/pcs-xpcs-plat.c
@@ -349,7 +349,7 @@ static int xpcs_plat_init_dev(struct dw_xpcs_plat *pxpcs)
* up later. Make sure DD-core is aware of the OF-node being re-used.
*/
device_set_node(&mdiodev->dev, fwnode_handle_get(dev_fwnode(dev)));
- mdiodev->dev.of_node_reused = true;
+ set_bit(DEV_FLAG_OF_NODE_REUSED, &mdiodev->dev.flags);
/* Pass the data further so the DW XPCS driver core could use it */
mdiodev->dev.platform_data = (void *)device_get_match_data(dev);
diff --git a/drivers/of/device.c b/drivers/of/device.c
index f7e75e527667..fd77295a8c0f 100644
--- a/drivers/of/device.c
+++ b/drivers/of/device.c
@@ -26,7 +26,7 @@
const struct of_device_id *of_match_device(const struct of_device_id *matches,
const struct device *dev)
{
- if (!matches || !dev->of_node || dev->of_node_reused)
+ if (!matches || !dev->of_node || test_bit(DEV_FLAG_OF_NODE_REUSED, &dev->flags))
return NULL;
return of_match_node(matches, dev->of_node);
}
@@ -192,7 +192,7 @@ ssize_t of_device_modalias(struct device *dev, char *str, ssize_t len)
{
ssize_t sl;
- if (!dev || !dev->of_node || dev->of_node_reused)
+ if (!dev || !dev->of_node || test_bit(DEV_FLAG_OF_NODE_REUSED, &dev->flags))
return -ENODEV;
sl = of_modalias(dev->of_node, str, len - 2);
@@ -254,7 +254,7 @@ int of_device_uevent_modalias(const struct device *dev, struct kobj_uevent_env *
{
int sl;
- if ((!dev) || (!dev->of_node) || dev->of_node_reused)
+ if ((!dev) || (!dev->of_node) || test_bit(DEV_FLAG_OF_NODE_REUSED, &dev->flags))
return -ENODEV;
/* Devicetree modalias is tricky, we add it in 2 steps */
diff --git a/drivers/pci/of.c b/drivers/pci/of.c
index 9f8eb5df279e..197b60c5a660 100644
--- a/drivers/pci/of.c
+++ b/drivers/pci/of.c
@@ -38,7 +38,7 @@ int pci_set_of_node(struct pci_dev *dev)
struct device *pdev __free(put_device) =
bus_find_device_by_of_node(&platform_bus_type, node);
if (pdev)
- dev->bus->dev.of_node_reused = true;
+ set_bit(DEV_FLAG_OF_NODE_REUSED, &dev->bus->dev.flags);
device_set_node(&dev->dev, of_fwnode_handle(no_free_ptr(node)));
return 0;
diff --git a/drivers/pci/pwrctrl/core.c b/drivers/pci/pwrctrl/core.c
index 7754baed67f2..cfbe9b615b88 100644
--- a/drivers/pci/pwrctrl/core.c
+++ b/drivers/pci/pwrctrl/core.c
@@ -39,7 +39,7 @@ static int pci_pwrctrl_notify(struct notifier_block *nb, unsigned long action,
* If we got here then the PCI device is the second after the
* power control platform device. Mark its OF node as reused.
*/
- dev->of_node_reused = true;
+ set_bit(DEV_FLAG_OF_NODE_REUSED, &dev->flags);
break;
}
diff --git a/drivers/regulator/bq257xx-regulator.c b/drivers/regulator/bq257xx-regulator.c
index dab8f1ab4450..01d3139e1d87 100644
--- a/drivers/regulator/bq257xx-regulator.c
+++ b/drivers/regulator/bq257xx-regulator.c
@@ -143,7 +143,7 @@ static int bq257xx_regulator_probe(struct platform_device *pdev)
struct regulator_config cfg = {};
pdev->dev.of_node = pdev->dev.parent->of_node;
- pdev->dev.of_node_reused = true;
+ set_bit(DEV_FLAG_OF_NODE_REUSED, &pdev->dev.flags);
pdata = devm_kzalloc(&pdev->dev, sizeof(struct bq257xx_reg_data), GFP_KERNEL);
if (!pdata)
diff --git a/drivers/regulator/rk808-regulator.c b/drivers/regulator/rk808-regulator.c
index e66408f23bb6..375ea7861134 100644
--- a/drivers/regulator/rk808-regulator.c
+++ b/drivers/regulator/rk808-regulator.c
@@ -2115,7 +2115,7 @@ static int rk808_regulator_probe(struct platform_device *pdev)
int ret, i, nregulators;
pdev->dev.of_node = pdev->dev.parent->of_node;
- pdev->dev.of_node_reused = true;
+ set_bit(DEV_FLAG_OF_NODE_REUSED, &pdev->dev.flags);
regmap = dev_get_regmap(pdev->dev.parent, NULL);
if (!regmap)
diff --git a/drivers/tty/serial/serial_base_bus.c b/drivers/tty/serial/serial_base_bus.c
index a12935f6b992..86c6003bbebb 100644
--- a/drivers/tty/serial/serial_base_bus.c
+++ b/drivers/tty/serial/serial_base_bus.c
@@ -74,7 +74,7 @@ static int serial_base_device_init(struct uart_port *port,
dev->parent = parent_dev;
dev->bus = &serial_base_bus_type;
dev->release = release;
- dev->of_node_reused = true;
+ set_bit(DEV_FLAG_OF_NODE_REUSED, &dev->flags);
device_set_node(dev, fwnode_handle_get(dev_fwnode(parent_dev)));
diff --git a/drivers/usb/gadget/udc/aspeed-vhub/dev.c b/drivers/usb/gadget/udc/aspeed-vhub/dev.c
index 2ecd049dacc2..57048e3aa6bb 100644
--- a/drivers/usb/gadget/udc/aspeed-vhub/dev.c
+++ b/drivers/usb/gadget/udc/aspeed-vhub/dev.c
@@ -593,7 +593,7 @@ int ast_vhub_init_dev(struct ast_vhub *vhub, unsigned int idx)
d->gadget.max_speed = USB_SPEED_HIGH;
d->gadget.speed = USB_SPEED_UNKNOWN;
d->gadget.dev.of_node = vhub->pdev->dev.of_node;
- d->gadget.dev.of_node_reused = true;
+ set_bit(DEV_FLAG_OF_NODE_REUSED, &d->gadget.dev.flags);
rc = usb_add_gadget_udc(d->port_dev, &d->gadget);
if (rc != 0)
diff --git a/include/linux/device.h b/include/linux/device.h
index c2a6dba7a036..f6ca067bacca 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -482,6 +482,8 @@ struct device_physical_location {
* driver/bus sync_state() callback.
* @DEV_FLAG_DMA_COHERENT: This particular device is dma coherent, even if the
* architecture supports non-coherent devices.
+ * @DEV_FLAG_OF_NODE_REUSED: Set if the device-tree node is shared with an
+ * ancestor device.
*/
enum struct_device_flags {
DEV_FLAG_READY_TO_PROBE,
@@ -491,6 +493,7 @@ enum struct_device_flags {
DEV_FLAG_DMA_OPS_BYPASS,
DEV_FLAG_STATE_SYNCED,
DEV_FLAG_DMA_COHERENT,
+ DEV_FLAG_OF_NODE_REUSED,
};
/**
@@ -570,8 +573,6 @@ enum struct_device_flags {
*
* @offline_disabled: If set, the device is permanently online.
* @offline: Set after successful invocation of bus type's .offline().
- * @of_node_reused: Set if the device-tree node is shared with an ancestor
- * device.
* @flags: DEV_FLAG_XXX flags. Use atomic bitfield operations to modify.
*
* At the lowest level, every device in a Linux system is represented by an
@@ -678,7 +679,6 @@ struct device {
bool offline_disabled:1;
bool offline:1;
- bool of_node_reused:1;
unsigned long flags;
};
--
2.53.0.1213.gd9a14994de-goog
^ permalink raw reply related
* [PATCH v3 0/9] driver core: Fix some race conditions
From: Douglas Anderson @ 2026-04-03 0:49 UTC (permalink / raw)
To: Greg Kroah-Hartman, Rafael J . Wysocki, Danilo Krummrich,
Alan Stern
Cc: Robin Murphy, Leon Romanovsky, Paul Burton, Saravana Kannan,
Alexander Lobakin, Eric Dumazet, Toshi Kani, Christoph Hellwig,
Alexey Kardashevskiy, Johan Hovold, Douglas Anderson,
Andrew Morton, Frank.Li, Jason Gunthorpe, alex, alexander.stein,
andre.przywara, andrew, andrew, andriy.shevchenko, aou, ardb,
astewart, bhelgaas, brgl, broonie, catalin.marinas, chleroy,
davem, david, devicetree, dmaengine, driver-core, gbatra,
gregory.clement, hkallweit1, iommu, jirislaby, joel, joro, kees,
kevin.brodsky, kuba, lenb, lgirdwood, linux-acpi,
linux-arm-kernel, linux-aspeed, linux-cxl, linux-kernel,
linux-mips, linux-mm, linux-pci, linux-riscv, linux-serial,
linux-snps-arc, linux-usb, linux, linuxppc-dev, m.szyprowski,
maddy, mani, maz, miko.lenczewski, mpe, netdev, npiggin,
osalvador, oupton, pabeni, palmer, peter.ujfalusi, peterz, pjw,
robh, sebastian.hesselbarth, tglx, tsbogend, vgupta, vkoul, will,
willy, yangyicong, yeoreum.yun
The main goal of this series is to fix the observed bug talked about
in the first patch ("driver core: Don't let a device probe until it's
ready"). That patch fixes a problem that has been observed in the real
world and could land even if the rest of the patches are found
unacceptable or need to be spun.
That said, during patch review Danilo correctly pointed out that many
of the bitfield accesses in "struct device" are unsafe. I added a
bunch of patches in the series to address each one.
Danilo said he's most worried about "can_match", so I put that one
first. After that, I tried to transition bitfields to flags in reverse
order to when the bitfield was added.
Even if transitioning from bitfields to flags isn't truly needed for
correctness, it seems silly (and wasteful of space in struct device)
to have some in bitfields and some as flags. Thus I didn't spend time
for each bitfield showing that it's truly needed for correctness.
Transition was done semi manually. Presumably someone skilled at
coccinelle could do a better job, but I just used sed in a heavy-
handed manner and then reviewed/fixed the results, undoing anything my
script got wrong. My terrible/ugly script was:
var=can_match
caps="${var^^}"
for f in $(git grep -l "[>\.]${var}[^1-9_a-zA-Z\[]"); do
echo $f
sed -i~ -e "s/\([a-zA-Z_0-9\.>()-][a-zA-Z_0-9\.>()-]*\)->${var} = true/set_bit(DEV_FLAG_${caps}, \&\\1->flags)/" "$f"
sed -i~ -e "s/\([a-zA-Z_0-9\.>()-][a-zA-Z_0-9\.>()-]*\)\.${var} = true/set_bit(DEV_FLAG_${caps}, \&\\1.flags)/" "$f"
sed -i~ -e "s/\([a-zA-Z_0-9\.>()-][a-zA-Z_0-9\.>()-]*\)->${var} = false/clear_bit(DEV_FLAG_${caps}, \&\\1->flags)/" "$f"
sed -i~ -e "s/\([a-zA-Z_0-9\.>()-][a-zA-Z_0-9\.>()-]*\)\.${var} = false/clear_bit(DEV_FLAG_${caps}, \&\\1.flags)/" "$f"
sed -i~ -e "s/\([a-zA-Z_0-9\.>()-][a-zA-Z_0-9\.>()-]*\)->${var} = \([^;]*\)/assign_bit(DEV_FLAG_${caps}, \&\\1->flags, \\2)/" "$f"
sed -i~ -e "s/\([a-zA-Z_0-9\.>()-][a-zA-Z_0-9\.>()-]*\)\.${var} = \([^;]*\)/assign_bit(DEV_FLAG_${caps}, \&\\1.flags, \\2)/" "$f"
sed -i~ -e "s/\([a-zA-Z_0-9\.>()-][a-zA-Z_0-9\.>()-]*\)->${var}\([^1-9_a-zA-Z\[]\)/test_bit(DEV_FLAG_${caps}, \&\\1->flags)\\2/" "$f"
sed -i~ -e "s/\([a-zA-Z_0-9\.>()-][a-zA-Z_0-9\.>()-]*\)\.${var}\([^1-9_a-zA-Z\[]\)/test_bit(DEV_FLAG_${caps}, \&\\1.flags)\\2/" "$f"
done
NOTE: one potentially "controversial" choice I made in some patches
was to always reserve a flag ID even if a flag is only used under
certain CONFIG_ settings. This is a change from how things were
before. Keeping the numbering consistent and allowing easy
compile-testing of both CONFIG settings seemed worth it, especially
since it won't take up any extra space until we've added a lot more
flags.
I only marked the first patch as a "Fix" since it is the only one
fixing observed problems. Other patches could be considered fixes too
if folks want.
I tested the first patch in the series backported to kernel 6.6 on the
Pixel phone that was experiencing the race. I added extra printouts to
make sure that the problem was hitting / addressed. The rest of the
patches are tested with allmodconfig with arm32, arm64, ppc, and
x86. I boot tested on an arm64 Chromebook running mainline.
Changes in v3:
- Use a new "flags" bitfield
- Add missing \n in probe error message
Changes in v2:
- Instead of adjusting the ordering, use "ready_to_probe" flag
Douglas Anderson (9):
driver core: Don't let a device probe until it's ready
driver core: Replace dev->can_match with DEV_FLAG_CAN_MATCH
driver core: Replace dev->dma_iommu with DEV_FLAG_DMA_IOMMU
driver core: Replace dev->dma_skip_sync with DEV_FLAG_DMA_SKIP_SYNC
driver core: Replace dev->dma_ops_bypass with DEV_FLAG_DMA_OPS_BYPASS
driver core: Replace dev->state_synced with DEV_FLAG_STATE_SYNCED
driver core: Replace dev->dma_coherent with DEV_FLAG_DMA_COHERENT
driver core: Replace dev->of_node_reused with DEV_FLAG_OF_NODE_REUSED
driver core: Replace dev->offline + ->offline_disabled with DEV_FLAGs
arch/arc/mm/dma.c | 4 +-
arch/arm/mach-highbank/highbank.c | 2 +-
arch/arm/mach-mvebu/coherency.c | 2 +-
arch/arm/mm/dma-mapping-nommu.c | 4 +-
arch/arm/mm/dma-mapping.c | 30 +++----
arch/arm64/kernel/cpufeature.c | 2 +-
arch/arm64/mm/dma-mapping.c | 2 +-
arch/mips/mm/dma-noncoherent.c | 2 +-
arch/powerpc/kernel/dma-iommu.c | 8 +-
.../platforms/pseries/hotplug-memory.c | 4 +-
arch/riscv/mm/dma-noncoherent.c | 2 +-
drivers/acpi/scan.c | 3 +-
drivers/base/core.c | 55 +++++++-----
drivers/base/cpu.c | 4 +-
drivers/base/dd.c | 28 +++++--
drivers/base/memory.c | 2 +-
drivers/base/pinctrl.c | 2 +-
drivers/base/platform.c | 2 +-
drivers/dma/ti/k3-udma-glue.c | 6 +-
drivers/dma/ti/k3-udma.c | 6 +-
drivers/iommu/dma-iommu.c | 9 +-
drivers/iommu/iommu.c | 5 +-
drivers/net/pcs/pcs-xpcs-plat.c | 2 +-
drivers/of/device.c | 6 +-
drivers/pci/of.c | 2 +-
drivers/pci/pwrctrl/core.c | 2 +-
drivers/regulator/bq257xx-regulator.c | 2 +-
drivers/regulator/rk808-regulator.c | 2 +-
drivers/tty/serial/serial_base_bus.c | 2 +-
drivers/usb/gadget/udc/aspeed-vhub/dev.c | 2 +-
include/linux/device.h | 83 ++++++++++---------
include/linux/dma-map-ops.h | 6 +-
include/linux/dma-mapping.h | 2 +-
include/linux/iommu-dma.h | 4 +-
kernel/cpu.c | 4 +-
kernel/dma/mapping.c | 16 ++--
mm/hmm.c | 2 +-
37 files changed, 178 insertions(+), 143 deletions(-)
--
2.53.0.1213.gd9a14994de-goog
^ permalink raw reply
* Re: [PATCH v2 1/4] dt-bindings: sound: Add ti,tas675x
From: Sen Wang @ 2026-04-03 0:40 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: linux-sound, broonie, lgirdwood, robh, krzk+dt, conor+dt,
devicetree, perex, tiwai, shenghao-ding, kevin-lu, baojun.xu,
niranjan.hy, l-badrinarayanan, devarsht, v-singh1, linux-kernel
In-Reply-To: <20260402-funky-lionfish-of-grandeur-fadba6@quoll>
On 4/2/26 02:53, Krzysztof Kozlowski wrote:
> On Wed, Apr 01, 2026 at 05:28:42PM -0500, Sen Wang wrote:
>> Add device tree binding for the Texas Instruments TAS675x family
>> of four-channel Class-D audio amplifiers with integrated DSP.
>>
>> Signed-off-by: Sen Wang <sen@ti.com>
>
Hi Krzysztof, Thank you for your review.
> Please use subject prefixes matching the subsystem. You can get them for
> example with 'git log --oneline -- DIRECTORY_OR_FILE' on the directory
> your patch is touching. For bindings, the preferred subjects are
> explained here:
> https://www.kernel.org/doc/html/latest/devicetree/bindings/submitting-patches.html#i-for-patch-submitters
Understood, ASoC: dt-bindings: Add ti,tas67524. Apologies for the oversight.
>
>> ---
>> .../devicetree/bindings/sound/ti,tas675x.yaml | 278 ++++++++++++++++++
>
> Filename matching compatible, one of them.
>
>> 1 file changed, 278 insertions(+)
>> create mode 100644 Documentation/devicetree/bindings/sound/ti,tas675x.yaml
>>
>> diff --git a/Documentation/devicetree/bindings/sound/ti,tas675x.yaml b/Documentation/devicetree/bindings/sound/ti,tas675x.yaml
>> new file mode 100644
>> index 000000000000..23e4cc77b4ae
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/sound/ti,tas675x.yaml
>> @@ -0,0 +1,278 @@
>> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
>> +%YAML 1.2
>> +---
>> +$id: http://devicetree.org/schemas/sound/ti,tas675x.yaml#
>> +$schema: http://devicetree.org/meta-schemas/core.yaml#
>> +
>> +title: Texas Instruments TAS675x Audio Amplifier
>> +
>> +maintainers:
>> + - Sen Wang <sen@ti.com>
>> +
>> +description: |
>
> Do not need '|' unless you need to preserve formatting.
>
>> + The TAS675x family (TAS6754, TAS67524) are four-channel, digital-input,
>
> And devices are not compatible?
>
They're compatible, and I didn't have any differentiators for this
initial driver. So I should only keep one.
And also rename ti,tas675x.yaml to ti,tas67524.yaml.
>> + automotive Class-D audio amplifiers with load diagnostics and an integrated
>> + DSP for audio processing.
>> +
>> +allOf:
>> + - $ref: dai-common.yaml#
>> +
>> +properties:
>> + compatible:
>> + enum:
>> + - ti,tas6754
>> + - ti,tas67524
>
> Keep alphanumerical order (not natural).
>
>> +
>> + reg:
>> + maxItems: 1
>> +
>> + '#sound-dai-cells':
>> + const: 1
>> + description: |
>> + The device exposes three DAIs, selected by index.
>> + 0 - Standard Audio Path (Playback)
>> + 1 - Low-Latency Playback Path (Playback)
>> + 2 - Sensory Feedback (Capture - Vpredict and Isense)
>> + By default, all four channels of each DAI are active. Runtime
>> + reconfiguration is available through DAPM widgets.
>> +
>> + interrupts:
>> + maxItems: 1
>> + description:
>> + Active-low falling-edge interrupt from the FAULT pin. When provided,
>> + the driver uses IRQ-driven fault reporting instead of polling.
>> +
>> + pd-gpios:
>
> Use names from gpio-consumer-common
>
Okay
>> + maxItems: 1
>> + description:
>> + GPIO connected to the power-down (PD#) pin, active low. Controls the
>> + internal digital circuitry power state. When asserted the device enters
>> + full power-down mode and all register state is lost. Can be omitted if
>> + PD pin is hardwired or externally controlled.
>> +
>> + stby-gpios:
>> + maxItems: 1
>> + description:
>> + GPIO connected to the standby (STBY#) pin, active low. Controls the
>> + analog power stage. When asserted the device enters Deep Sleep mode
>> + but remains I2C-accessible with registers retained. Can be omitted if
>> + STBY pin is tied to PD or hardwired.
>> +
>> + dvdd-supply:
>> + description:
>> + Digital logic supply (1.62 V to 3.6 V). All three supply rails must
>> + be within their recommended operating ranges before the PD pin is
>> + released.
>> +
>> + pvdd-supply:
>> + description:
>> + Output FET power supply (4.5 V to 19 V). All three supply rails must
>> + be within their recommended operating ranges before the PD pin is
>> + released.
>> +
>> + vbat-supply:
>> + description:
>> + Battery supply for the Class-D output stage (4.5 V to 19 V). Optional
>> + when PVDD and VBAT are connected to the same supply rail. When absent,
>> + VBAT is assumed hardwired to PVDD.
>> +
>> + ti,fast-boot:
>> + type: boolean
>> + description:
>> + Skip DC load diagnostic sweep at power-on to reduce boot latency.
>> + Automatic diagnostics after fault conditions remain enabled. Hardware
>> + overcurrent protection is always active.
>> +
>> + ti,audio-slot-no:
>> + $ref: /schemas/types.yaml#/definitions/uint32
>> + description:
>> + TDM slot offset for the standard audio playback path via SDIN1. A value
>> + of 4 maps to slot 4. If omitted, slot assignment is derived from the
>> + tx_mask provided via set_tdm_slot(). Without either property, no slot
>> + mapping is configured.
>> +
>> + ti,llp-slot-no:
>> + $ref: /schemas/types.yaml#/definitions/uint32
>> + description:
>> + TDM slot offset for the low-latency playback path via SDIN1. If omitted,
>> + slot assignment is derived from the tx_mask provided via set_tdm_slot().
>> + Without either property, no slot mapping is configured. Disabled outside
>> + of LLP mode, and only relevant for TDM formats.
>> +
>> + ti,vpredict-slot-no:
>> + $ref: /schemas/types.yaml#/definitions/uint32
>> + description: |
>> + In TDM mode, enables Vpredict output and assigns its starting slot;
>> + four consecutive slots carry Vpredict Ch1-4 on SDOUT1. May coexist
>> + with ti,isense-slot-no using separate non-overlapping slots.
>> +
>> + In I2S mode, enables Vpredict output on SDOUT1 (Ch1/Ch2) and SDOUT2
>> + (Ch3/Ch4). The slot value is unused. Requires a GPIO configured as
>> + sdout2 for Ch3/Ch4; without it only Ch1/Ch2 are output. Mutually
>> + exclusive with ti,isense-slot-no; if both are set, Vpredict takes
>> + priority.
>> +
>> + Irrelevant in Left-J and Right-J modes.
>> +
>> + ti,isense-slot-no:
>> + $ref: /schemas/types.yaml#/definitions/uint32
>> + description: |
>> + In TDM mode, enables Isense output and assigns its starting slot;
>> + four consecutive slots carry Isense Ch1-4 on SDOUT1. May coexist
>> + with ti,vpredict-slot-no using separate non-overlapping slots.
>> +
>> + In I2S mode, enables Isense output on SDOUT1 (Ch1/Ch2) and SDOUT2
>> + (Ch3/Ch4). The slot value is unused. Requires a GPIO configured as
>> + sdout2 for Ch3/Ch4; without it only Ch1/Ch2 are output. Mutually
>> + exclusive with ti,vpredict-slot-no; Vpredict takes priority if both
>> + are set.
>> +
>> + Irrelevant in Left-J and Right-J modes.
>> +
>> + ti,gpio1-function:
>> + $ref: /schemas/types.yaml#/definitions/string
>> + description: |
>
> Do not need '|' unless you need to preserve formatting.
>
Understood, thanks a lot for your review and the tip. Will post a V3.
>> + Function for the GPIO_1 pin. When omitted, GPIO_1 remains in its
>> + power-on default state.
>
> Best regards,
> Krzysztof
>
^ permalink raw reply
* Re: [PATCh v3 04/14] ASoC: rsnd: Add RZ/G3E SoC probing and register map
From: Kuninori Morimoto @ 2026-04-03 0:36 UTC (permalink / raw)
To: Mark Brown
Cc: John Madieu, Liam Girdwood, Geert Uytterhoeven, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Jaroslav Kysela, Takashi Iwai,
Magnus Damm, Philipp Zabel, Claudiu Beznea, Biju Das, john.madieu,
linux-sound, linux-renesas-soc, devicetree, linux-kernel
In-Reply-To: <ca7da576-5280-456a-969c-aa4762803ee9@sirena.org.uk>
Hi John, Mark
Thank you for the patch
> > @@ -629,7 +632,9 @@ struct rsnd_priv {
> > #define RSND_GEN4 (4 << 0)
> > #define RSND_SOC_MASK (0xFF << 4)
> > #define RSND_SOC_E (1 << 4) /* E1/E2/E3 */
> > -
> > +#define RSND_RZ_MASK (0xFF << 8)
>
> This overlaps with RSND_SOC_MASK. That might be intentional but I'm
> really not sure and it's all kind of unclear.
Indeed.
But it seems the strange is RSND_SOC_MASK, it should be
- #define RSND_SOC_MASK (0xFF << 4)
+ #define RSND_SOC_MASK (0xF << 4)
I think it is good timing to have comment to clarify flag.
0x....DCBA
A: R-Car GenX
B: R-Car GenX identifier (if needed)
C: RZ series
D: RZ series identifier (if needed)
Thank you for your help !!
Best regards
---
Kuninori Morimoto
^ permalink raw reply
* [PATCH v2 2/2] pmdomain: qcom: rpmhpd: Add power domains for Hawi SoC
From: Fenglin Wu @ 2026-04-03 0:35 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Bjorn Andersson,
Ulf Hansson, Konrad Dybcio
Cc: Subbaraman Narayanamurthy, linux-arm-msm, devicetree,
linux-kernel, linux-pm, kernel, Fenglin Wu, Taniya Das
In-Reply-To: <20260402-haw-rpmhpd-v2-0-2bce0767f2ca@oss.qualcomm.com>
Add the RPMh power domains required for the Hawi SoC. This includes
new definitions for domains supplying specific hardware components:
- DCX: supplies VDD_DISP
- GBX: supplies VDD_GFX_BX
Reviewed-by: Taniya Das <taniya.das@oss.qualcomm.com>
Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Signed-off-by: Fenglin Wu <fenglin.wu@oss.qualcomm.com>
---
drivers/pmdomain/qcom/rpmhpd.c | 38 ++++++++++++++++++++++++++++++++++++++
1 file changed, 38 insertions(+)
diff --git a/drivers/pmdomain/qcom/rpmhpd.c b/drivers/pmdomain/qcom/rpmhpd.c
index 19849703be4a..f5ae2a63765d 100644
--- a/drivers/pmdomain/qcom/rpmhpd.c
+++ b/drivers/pmdomain/qcom/rpmhpd.c
@@ -102,11 +102,21 @@ static struct rpmhpd cx_ao_w_mx_parent = {
.res_name = "cx.lvl",
};
+static struct rpmhpd dcx = {
+ .pd = { .name = "dcx", },
+ .res_name = "dcx.lvl",
+};
+
static struct rpmhpd ebi = {
.pd = { .name = "ebi", },
.res_name = "ebi.lvl",
};
+static struct rpmhpd gbx = {
+ .pd = { .name = "gbx", },
+ .res_name = "gbx.lvl",
+};
+
static struct rpmhpd gfx = {
.pd = { .name = "gfx", },
.res_name = "gfx.lvl",
@@ -622,6 +632,33 @@ static const struct rpmhpd_desc kaanapali_desc = {
.num_pds = ARRAY_SIZE(kaanapali_rpmhpds),
};
+/* Hawi RPMH powerdomains */
+static struct rpmhpd *hawi_rpmhpds[] = {
+ [RPMHPD_CX] = &cx,
+ [RPMHPD_CX_AO] = &cx_ao,
+ [RPMHPD_DCX] = &dcx,
+ [RPMHPD_EBI] = &ebi,
+ [RPMHPD_GBX] = &gbx,
+ [RPMHPD_GFX] = &gfx,
+ [RPMHPD_GMXC] = &gmxc,
+ [RPMHPD_LCX] = &lcx,
+ [RPMHPD_LMX] = &lmx,
+ [RPMHPD_MMCX] = &mmcx,
+ [RPMHPD_MMCX_AO] = &mmcx_ao,
+ [RPMHPD_MX] = &mx,
+ [RPMHPD_MX_AO] = &mx_ao,
+ [RPMHPD_MXC] = &mxc,
+ [RPMHPD_MXC_AO] = &mxc_ao,
+ [RPMHPD_MSS] = &mss,
+ [RPMHPD_NSP] = &nsp,
+ [RPMHPD_NSP2] = &nsp2,
+};
+
+static const struct rpmhpd_desc hawi_desc = {
+ .rpmhpds = hawi_rpmhpds,
+ .num_pds = ARRAY_SIZE(hawi_rpmhpds),
+};
+
/* QDU1000/QRU1000 RPMH powerdomains */
static struct rpmhpd *qdu1000_rpmhpds[] = {
[QDU1000_CX] = &cx,
@@ -796,6 +833,7 @@ static const struct rpmhpd_desc qcs615_desc = {
static const struct of_device_id rpmhpd_match_table[] = {
{ .compatible = "qcom,glymur-rpmhpd", .data = &glymur_desc },
+ { .compatible = "qcom,hawi-rpmhpd", .data = &hawi_desc },
{ .compatible = "qcom,kaanapali-rpmhpd", .data = &kaanapali_desc },
{ .compatible = "qcom,milos-rpmhpd", .data = &milos_desc },
{ .compatible = "qcom,qcs615-rpmhpd", .data = &qcs615_desc },
--
2.43.0
^ permalink raw reply related
* [PATCH v2 1/2] dt-bindings: power: qcom,rpmhpd: Add RPMh power domain for Hawi SoC
From: Fenglin Wu @ 2026-04-03 0:35 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Bjorn Andersson,
Ulf Hansson, Konrad Dybcio
Cc: Subbaraman Narayanamurthy, linux-arm-msm, devicetree,
linux-kernel, linux-pm, kernel, Fenglin Wu
In-Reply-To: <20260402-haw-rpmhpd-v2-0-2bce0767f2ca@oss.qualcomm.com>
Document the RPMh power domain for Hawi SoC, and add definitions for
the new power domains which present in Hawi SoC:
- RPMHPD_DCX (Display Core X): supplies VDD_DISP for the display
subsystem
- RPMHPD_GBX (Graphics Box): supplies VDD_GFX_BX for the GPU/graphics
subsystem
Also, add constants for new power domain levels that supported in Hawi
SoC, including: LOW_SVS_D3_0, LOW_SVS_D1_0, LOW_SVS_D0_0, SVS_L2_0,
TURBO_L1_0/1/2, TURBO_L1_0/1/2.
Signed-off-by: Fenglin Wu <fenglin.wu@oss.qualcomm.com>
---
Documentation/devicetree/bindings/power/qcom,rpmpd.yaml | 1 +
include/dt-bindings/power/qcom,rpmhpd.h | 12 ++++++++++++
2 files changed, 13 insertions(+)
diff --git a/Documentation/devicetree/bindings/power/qcom,rpmpd.yaml b/Documentation/devicetree/bindings/power/qcom,rpmpd.yaml
index 27af5b8aa134..35a0e01c2015 100644
--- a/Documentation/devicetree/bindings/power/qcom,rpmpd.yaml
+++ b/Documentation/devicetree/bindings/power/qcom,rpmpd.yaml
@@ -18,6 +18,7 @@ properties:
oneOf:
- enum:
- qcom,glymur-rpmhpd
+ - qcom,hawi-rpmhpd
- qcom,kaanapali-rpmhpd
- qcom,mdm9607-rpmpd
- qcom,milos-rpmhpd
diff --git a/include/dt-bindings/power/qcom,rpmhpd.h b/include/dt-bindings/power/qcom,rpmhpd.h
index 06851363ae0e..67e2634fdc99 100644
--- a/include/dt-bindings/power/qcom,rpmhpd.h
+++ b/include/dt-bindings/power/qcom,rpmhpd.h
@@ -28,15 +28,20 @@
#define RPMHPD_XO 18
#define RPMHPD_NSP2 19
#define RPMHPD_GMXC 20
+#define RPMHPD_DCX 21
+#define RPMHPD_GBX 22
/* RPMh Power Domain performance levels */
#define RPMH_REGULATOR_LEVEL_RETENTION 16
#define RPMH_REGULATOR_LEVEL_MIN_SVS 48
+#define RPMH_REGULATOR_LEVEL_LOW_SVS_D3_0 49
#define RPMH_REGULATOR_LEVEL_LOW_SVS_D3 50
#define RPMH_REGULATOR_LEVEL_LOW_SVS_D2_1 51
#define RPMH_REGULATOR_LEVEL_LOW_SVS_D2 52
#define RPMH_REGULATOR_LEVEL_LOW_SVS_D1_1 54
+#define RPMH_REGULATOR_LEVEL_LOW_SVS_D1_0 55
#define RPMH_REGULATOR_LEVEL_LOW_SVS_D1 56
+#define RPMH_REGULATOR_LEVEL_LOW_SVS_D0_0 59
#define RPMH_REGULATOR_LEVEL_LOW_SVS_D0 60
#define RPMH_REGULATOR_LEVEL_LOW_SVS 64
#define RPMH_REGULATOR_LEVEL_LOW_SVS_P1 72
@@ -47,6 +52,7 @@
#define RPMH_REGULATOR_LEVEL_SVS_L0 144
#define RPMH_REGULATOR_LEVEL_SVS_L1 192
#define RPMH_REGULATOR_LEVEL_SVS_L2 224
+#define RPMH_REGULATOR_LEVEL_SVS_L2_0 225
#define RPMH_REGULATOR_LEVEL_NOM 256
#define RPMH_REGULATOR_LEVEL_NOM_L0 288
#define RPMH_REGULATOR_LEVEL_NOM_L1 320
@@ -54,8 +60,14 @@
#define RPMH_REGULATOR_LEVEL_TURBO 384
#define RPMH_REGULATOR_LEVEL_TURBO_L0 400
#define RPMH_REGULATOR_LEVEL_TURBO_L1 416
+#define RPMH_REGULATOR_LEVEL_TURBO_L1_0 417
+#define RPMH_REGULATOR_LEVEL_TURBO_L1_1 418
+#define RPMH_REGULATOR_LEVEL_TURBO_L1_2 419
#define RPMH_REGULATOR_LEVEL_TURBO_L2 432
#define RPMH_REGULATOR_LEVEL_TURBO_L3 448
+#define RPMH_REGULATOR_LEVEL_TURBO_L3_0 449
+#define RPMH_REGULATOR_LEVEL_TURBO_L3_1 450
+#define RPMH_REGULATOR_LEVEL_TURBO_L3_2 451
#define RPMH_REGULATOR_LEVEL_TURBO_L4 452
#define RPMH_REGULATOR_LEVEL_TURBO_L5 456
#define RPMH_REGULATOR_LEVEL_SUPER_TURBO 464
--
2.43.0
^ permalink raw reply related
* [PATCH v2 0/2] power: qcom,rpmpd: add RPMh power doamins support for Hawi SoC
From: Fenglin Wu @ 2026-04-03 0:35 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Bjorn Andersson,
Ulf Hansson, Konrad Dybcio
Cc: Subbaraman Narayanamurthy, linux-arm-msm, devicetree,
linux-kernel, linux-pm, kernel, Fenglin Wu, Taniya Das
Add constant definitions for the new power domains and new voltage
levels present in Hawi SoC. Also add RPMH power domain support for
Hawi SoC.
Signed-off-by: Fenglin Wu <fenglin.wu@oss.qualcomm.com>
---
Changes in v2:
- Squash patch 1 and 2 into a single binding change
- Add trailers for the new patch 2
- Link to v1: https://patch.msgid.link/20260401-haw-rpmhpd-v1-0-c830c79ed8f9@oss.qualcomm.com
---
Fenglin Wu (2):
dt-bindings: power: qcom,rpmhpd: Add RPMh power domain for Hawi SoC
pmdomain: qcom: rpmhpd: Add power domains for Hawi SoC
.../devicetree/bindings/power/qcom,rpmpd.yaml | 1 +
drivers/pmdomain/qcom/rpmhpd.c | 38 ++++++++++++++++++++++
include/dt-bindings/power/qcom,rpmhpd.h | 12 +++++++
3 files changed, 51 insertions(+)
---
base-commit: 33b1a2ee3a3df63e7a08e51e6de2b2d28ddf257f
change-id: 20260401-haw-rpmhpd-b40a68a3ce79
Best regards,
--
Fenglin Wu <fenglin.wu@oss.qualcomm.com>
^ permalink raw reply
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