* Re: [PATCH net-next v6 04/12] net: airoha: Move airoha_qdma pointer in airoha_gdm_dev struct
From: Lorenzo Bianconi @ 2026-05-13 8:45 UTC (permalink / raw)
To: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: Christian Marangi, Benjamin Larsson, linux-arm-kernel,
linux-mediatek, netdev, devicetree, Xuegang Lu
In-Reply-To: <20260511-airoha-eth-multi-serdes-v6-4-c899462c4f75@kernel.org>
[-- Attachment #1: Type: text/plain, Size: 18121 bytes --]
On May 11, Lorenzo Bianconi wrote:
> Move airoha_qdma pointer from airoha_gdm_port struct to airoha_gdm_dev
> one since the QDMA block used depends on the particular net_device
> WAN/LAN configuration and in the current codebase net_device pointer is
> associated to airoha_gdm_dev struct.
> This is a preliminary patch to support multiple net_devices connected
> to the same GDM{3,4} port via an external hw arbiter.
>
> Tested-by: Xuegang Lu <xuegang.lu@airoha.com>
> Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
> ---
> drivers/net/ethernet/airoha/airoha_eth.c | 105 +++++++++++++++----------------
> drivers/net/ethernet/airoha/airoha_eth.h | 9 ++-
> drivers/net/ethernet/airoha/airoha_ppe.c | 17 ++---
> 3 files changed, 64 insertions(+), 67 deletions(-)
>
> diff --git a/drivers/net/ethernet/airoha/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c
> index 18a89de4d58a..e0cd401bbf67 100644
> --- a/drivers/net/ethernet/airoha/airoha_eth.c
> +++ b/drivers/net/ethernet/airoha/airoha_eth.c
> @@ -71,9 +71,10 @@ static void airoha_qdma_irq_disable(struct airoha_irq_bank *irq_bank,
> airoha_qdma_set_irqmask(irq_bank, index, mask, 0);
> }
>
> -static void airoha_set_macaddr(struct airoha_gdm_port *port, const u8 *addr)
> +static void airoha_set_macaddr(struct airoha_gdm_dev *dev, const u8 *addr)
> {
> - struct airoha_eth *eth = port->qdma->eth;
> + struct airoha_gdm_port *port = dev->port;
> + struct airoha_eth *eth = dev->eth;
> u32 val, reg;
>
> reg = airoha_is_lan_gdm_port(port) ? REG_FE_LAN_MAC_H
> @@ -85,7 +86,7 @@ static void airoha_set_macaddr(struct airoha_gdm_port *port, const u8 *addr)
> airoha_fe_wr(eth, REG_FE_MAC_LMIN(reg), val);
> airoha_fe_wr(eth, REG_FE_MAC_LMAX(reg), val);
>
> - airoha_ppe_init_upd_mem(port);
> + airoha_ppe_init_upd_mem(dev);
> }
>
> static void airoha_set_gdm_port_fwd_cfg(struct airoha_eth *eth, u32 addr,
> @@ -101,10 +102,10 @@ static void airoha_set_gdm_port_fwd_cfg(struct airoha_eth *eth, u32 addr,
> FIELD_PREP(GDM_UCFQ_MASK, val));
> }
>
> -static int airoha_set_vip_for_gdm_port(struct airoha_gdm_port *port,
> - bool enable)
> +static int airoha_set_vip_for_gdm_port(struct airoha_gdm_dev *dev, bool enable)
> {
> - struct airoha_eth *eth = port->qdma->eth;
> + struct airoha_gdm_port *port = dev->port;
> + struct airoha_eth *eth = dev->eth;
> u32 vip_port;
>
> vip_port = eth->soc->ops.get_vip_port(port, port->nbq);
> @@ -858,10 +859,13 @@ static void airoha_qdma_wake_netdev_txqs(struct airoha_queue *q)
> if (!port)
> continue;
>
> - if (port->qdma != qdma)
> + dev = port->dev;
> + if (!dev)
> + continue;
> +
> + if (dev->qdma != qdma)
> continue;
>
> - dev = port->dev;
> for (j = 0; j < dev->dev->num_tx_queues; j++) {
> if (airoha_qdma_get_txq(qdma, j) != qid)
> continue;
> @@ -1562,9 +1566,10 @@ static void airoha_qdma_stop_napi(struct airoha_qdma *qdma)
> }
> }
>
> -static void airoha_update_hw_stats(struct airoha_gdm_port *port)
> +static void airoha_update_hw_stats(struct airoha_gdm_dev *dev)
> {
> - struct airoha_eth *eth = port->qdma->eth;
> + struct airoha_gdm_port *port = dev->port;
> + struct airoha_eth *eth = dev->eth;
> u32 val, i = 0;
>
> spin_lock(&port->stats.lock);
> @@ -1711,11 +1716,11 @@ static int airoha_dev_open(struct net_device *netdev)
> int err, len = ETH_HLEN + netdev->mtu + ETH_FCS_LEN;
> struct airoha_gdm_dev *dev = netdev_priv(netdev);
> struct airoha_gdm_port *port = dev->port;
> - struct airoha_qdma *qdma = port->qdma;
> + struct airoha_qdma *qdma = dev->qdma;
> u32 pse_port = FE_PSE_PORT_PPE1;
>
> netif_tx_start_all_queues(netdev);
> - err = airoha_set_vip_for_gdm_port(port, true);
> + err = airoha_set_vip_for_gdm_port(dev, true);
> if (err)
> return err;
>
> @@ -1751,11 +1756,11 @@ static int airoha_dev_stop(struct net_device *netdev)
> {
> struct airoha_gdm_dev *dev = netdev_priv(netdev);
> struct airoha_gdm_port *port = dev->port;
> - struct airoha_qdma *qdma = port->qdma;
> + struct airoha_qdma *qdma = dev->qdma;
> int i;
>
> netif_tx_disable(netdev);
> - airoha_set_vip_for_gdm_port(port, false);
> + airoha_set_vip_for_gdm_port(dev, false);
> for (i = 0; i < netdev->num_tx_queues; i++)
> netdev_tx_reset_subqueue(netdev, i);
>
> @@ -1781,21 +1786,21 @@ static int airoha_dev_stop(struct net_device *netdev)
> static int airoha_dev_set_macaddr(struct net_device *netdev, void *p)
> {
> struct airoha_gdm_dev *dev = netdev_priv(netdev);
> - struct airoha_gdm_port *port = dev->port;
> int err;
>
> err = eth_mac_addr(netdev, p);
> if (err)
> return err;
>
> - airoha_set_macaddr(port, netdev->dev_addr);
> + airoha_set_macaddr(dev, netdev->dev_addr);
>
> return 0;
> }
>
> -static int airoha_set_gdm2_loopback(struct airoha_gdm_port *port)
> +static int airoha_set_gdm2_loopback(struct airoha_gdm_dev *dev)
> {
> - struct airoha_eth *eth = port->qdma->eth;
> + struct airoha_gdm_port *port = dev->port;
> + struct airoha_eth *eth = dev->eth;
> u32 val, pse_port, chan;
> int i, src_port;
>
> @@ -1840,7 +1845,7 @@ static int airoha_set_gdm2_loopback(struct airoha_gdm_port *port)
> __field_prep(SP_CPORT_MASK(val), FE_PSE_PORT_CDM2));
>
> for (i = 0; i < eth->soc->num_ppe; i++)
> - airoha_ppe_set_cpu_port(port, i, AIROHA_GDM2_IDX);
> + airoha_ppe_set_cpu_port(dev, i, AIROHA_GDM2_IDX);
>
> if (port->id == AIROHA_GDM4_IDX && airoha_is_7581(eth)) {
> u32 mask = FC_ID_OF_SRC_PORT_MASK(port->nbq);
> @@ -1860,9 +1865,9 @@ static int airoha_dev_init(struct net_device *netdev)
> int i;
>
> /* QDMA0 is used for lan ports while QDMA1 is used for WAN ports */
> - port->qdma = ð->qdma[!airoha_is_lan_gdm_port(port)];
> - dev->dev->irq = port->qdma->irq_banks[0].irq;
> - airoha_set_macaddr(port, netdev->dev_addr);
> + dev->qdma = ð->qdma[!airoha_is_lan_gdm_port(port)];
> + dev->dev->irq = dev->qdma->irq_banks[0].irq;
> + airoha_set_macaddr(dev, netdev->dev_addr);
>
> switch (port->id) {
> case AIROHA_GDM3_IDX:
> @@ -1871,7 +1876,7 @@ static int airoha_dev_init(struct net_device *netdev)
> if (!eth->ports[1]) {
> int err;
>
> - err = airoha_set_gdm2_loopback(port);
> + err = airoha_set_gdm2_loopback(dev);
> if (err)
> return err;
> }
> @@ -1881,8 +1886,7 @@ static int airoha_dev_init(struct net_device *netdev)
> }
>
> for (i = 0; i < eth->soc->num_ppe; i++)
> - airoha_ppe_set_cpu_port(port, i,
> - airoha_get_fe_port(port));
> + airoha_ppe_set_cpu_port(dev, i, airoha_get_fe_port(dev));
>
> return 0;
> }
> @@ -1894,7 +1898,7 @@ static void airoha_dev_get_stats64(struct net_device *netdev,
> struct airoha_gdm_port *port = dev->port;
> unsigned int start;
>
> - airoha_update_hw_stats(port);
> + airoha_update_hw_stats(dev);
> do {
> start = u64_stats_fetch_begin(&port->stats.syncp);
> storage->rx_packets = port->stats.rx_ok_pkts;
> @@ -1914,8 +1918,8 @@ static int airoha_dev_change_mtu(struct net_device *netdev, int mtu)
> {
> struct airoha_gdm_dev *dev = netdev_priv(netdev);
> struct airoha_gdm_port *port = dev->port;
> - struct airoha_eth *eth = port->qdma->eth;
> u32 len = ETH_HLEN + mtu + ETH_FCS_LEN;
> + struct airoha_eth *eth = dev->eth;
>
> airoha_fe_rmw(eth, REG_GDM_LEN_CFG(port->id),
> GDM_LONG_LEN_MASK,
> @@ -1989,10 +1993,10 @@ static u32 airoha_get_dsa_tag(struct sk_buff *skb, struct net_device *dev)
> #endif
> }
>
> -int airoha_get_fe_port(struct airoha_gdm_port *port)
> +int airoha_get_fe_port(struct airoha_gdm_dev *dev)
> {
> - struct airoha_qdma *qdma = port->qdma;
> - struct airoha_eth *eth = qdma->eth;
> + struct airoha_gdm_port *port = dev->port;
> + struct airoha_eth *eth = dev->eth;
>
> switch (eth->soc->version) {
> case 0x7583:
> @@ -2009,8 +2013,7 @@ static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb,
> struct net_device *netdev)
> {
> struct airoha_gdm_dev *dev = netdev_priv(netdev);
> - struct airoha_gdm_port *port = dev->port;
> - struct airoha_qdma *qdma = port->qdma;
> + struct airoha_qdma *qdma = dev->qdma;
> u32 nr_frags, tag, msg0, msg1, len;
> struct airoha_queue_entry *e;
> struct netdev_queue *txq;
> @@ -2048,7 +2051,7 @@ static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb,
> }
> }
>
> - fport = airoha_get_fe_port(port);
> + fport = airoha_get_fe_port(dev);
> msg1 = FIELD_PREP(QDMA_ETH_TXMSG_FPORT_MASK, fport) |
> FIELD_PREP(QDMA_ETH_TXMSG_METER_MASK, 0x7f);
>
> @@ -2151,8 +2154,7 @@ static void airoha_ethtool_get_drvinfo(struct net_device *netdev,
> struct ethtool_drvinfo *info)
> {
> struct airoha_gdm_dev *dev = netdev_priv(netdev);
> - struct airoha_gdm_port *port = dev->port;
> - struct airoha_eth *eth = port->qdma->eth;
> + struct airoha_eth *eth = dev->eth;
>
> strscpy(info->driver, eth->dev->driver->name, sizeof(info->driver));
> strscpy(info->bus_info, dev_name(eth->dev), sizeof(info->bus_info));
> @@ -2165,7 +2167,7 @@ static void airoha_ethtool_get_mac_stats(struct net_device *netdev,
> struct airoha_gdm_port *port = dev->port;
> unsigned int start;
>
> - airoha_update_hw_stats(port);
> + airoha_update_hw_stats(dev);
> do {
> start = u64_stats_fetch_begin(&port->stats.syncp);
> stats->FramesTransmittedOK = port->stats.tx_ok_pkts;
> @@ -2205,7 +2207,7 @@ airoha_ethtool_get_rmon_stats(struct net_device *netdev,
> ARRAY_SIZE(hw_stats->rx_len) + 1);
>
> *ranges = airoha_ethtool_rmon_ranges;
> - airoha_update_hw_stats(port);
> + airoha_update_hw_stats(dev);
> do {
> int i;
>
> @@ -2225,18 +2227,17 @@ static int airoha_qdma_set_chan_tx_sched(struct net_device *netdev,
> const u16 *weights, u8 n_weights)
> {
> struct airoha_gdm_dev *dev = netdev_priv(netdev);
> - struct airoha_gdm_port *port = dev->port;
> int i;
>
> for (i = 0; i < AIROHA_NUM_TX_RING; i++)
> - airoha_qdma_clear(port->qdma, REG_QUEUE_CLOSE_CFG(channel),
> + airoha_qdma_clear(dev->qdma, REG_QUEUE_CLOSE_CFG(channel),
> TXQ_DISABLE_CHAN_QUEUE_MASK(channel, i));
>
> for (i = 0; i < n_weights; i++) {
> u32 status;
> int err;
>
> - airoha_qdma_wr(port->qdma, REG_TXWRR_WEIGHT_CFG,
> + airoha_qdma_wr(dev->qdma, REG_TXWRR_WEIGHT_CFG,
> TWRR_RW_CMD_MASK |
> FIELD_PREP(TWRR_CHAN_IDX_MASK, channel) |
> FIELD_PREP(TWRR_QUEUE_IDX_MASK, i) |
> @@ -2244,13 +2245,12 @@ static int airoha_qdma_set_chan_tx_sched(struct net_device *netdev,
> err = read_poll_timeout(airoha_qdma_rr, status,
> status & TWRR_RW_CMD_DONE,
> USEC_PER_MSEC, 10 * USEC_PER_MSEC,
> - true, port->qdma,
> - REG_TXWRR_WEIGHT_CFG);
> + true, dev->qdma, REG_TXWRR_WEIGHT_CFG);
> if (err)
> return err;
> }
>
> - airoha_qdma_rmw(port->qdma, REG_CHAN_QOS_MODE(channel >> 3),
> + airoha_qdma_rmw(dev->qdma, REG_CHAN_QOS_MODE(channel >> 3),
> CHAN_QOS_MODE_MASK(channel),
> __field_prep(CHAN_QOS_MODE_MASK(channel), mode));
>
> @@ -2316,9 +2316,9 @@ static int airoha_qdma_get_tx_ets_stats(struct net_device *netdev, int channel,
> struct airoha_gdm_dev *dev = netdev_priv(netdev);
> struct airoha_gdm_port *port = dev->port;
>
> - u64 cpu_tx_packets = airoha_qdma_rr(port->qdma,
> + u64 cpu_tx_packets = airoha_qdma_rr(dev->qdma,
> REG_CNTR_VAL(channel << 1));
> - u64 fwd_tx_packets = airoha_qdma_rr(port->qdma,
> + u64 fwd_tx_packets = airoha_qdma_rr(dev->qdma,
> REG_CNTR_VAL((channel << 1) + 1));
> u64 tx_packets = (cpu_tx_packets - port->cpu_tx_packets) +
> (fwd_tx_packets - port->fwd_tx_packets);
> @@ -2582,17 +2582,16 @@ static int airoha_qdma_set_tx_rate_limit(struct net_device *netdev,
> u32 bucket_size)
> {
> struct airoha_gdm_dev *dev = netdev_priv(netdev);
> - struct airoha_gdm_port *port = dev->port;
> int i, err;
>
> for (i = 0; i <= TRTCM_PEAK_MODE; i++) {
> - err = airoha_qdma_set_trtcm_config(port->qdma, channel,
> + err = airoha_qdma_set_trtcm_config(dev->qdma, channel,
> REG_EGRESS_TRTCM_CFG, i,
> !!rate, TRTCM_METER_MODE);
> if (err)
> return err;
>
> - err = airoha_qdma_set_trtcm_token_bucket(port->qdma, channel,
> + err = airoha_qdma_set_trtcm_token_bucket(dev->qdma, channel,
> REG_EGRESS_TRTCM_CFG,
> i, rate, bucket_size);
> if (err)
> @@ -2642,11 +2641,11 @@ static int airoha_tc_htb_alloc_leaf_queue(struct net_device *netdev,
> return 0;
> }
>
> -static int airoha_qdma_set_rx_meter(struct airoha_gdm_port *port,
> +static int airoha_qdma_set_rx_meter(struct airoha_gdm_dev *dev,
> u32 rate, u32 bucket_size,
> enum trtcm_unit_type unit_type)
> {
> - struct airoha_qdma *qdma = port->qdma;
> + struct airoha_qdma *qdma = dev->qdma;
> int i;
>
> for (i = 0; i < ARRAY_SIZE(qdma->q_rx); i++) {
> @@ -2725,7 +2724,6 @@ static int airoha_dev_tc_matchall(struct net_device *netdev,
> {
> enum trtcm_unit_type unit_type = TRTCM_BYTE_UNIT;
> struct airoha_gdm_dev *dev = netdev_priv(netdev);
> - struct airoha_gdm_port *port = dev->port;
> u32 rate = 0, bucket_size = 0;
>
> switch (f->command) {
> @@ -2750,7 +2748,7 @@ static int airoha_dev_tc_matchall(struct net_device *netdev,
> fallthrough;
> }
> case TC_CLSMATCHALL_DESTROY:
> - return airoha_qdma_set_rx_meter(port, rate, bucket_size,
> + return airoha_qdma_set_rx_meter(dev, rate, bucket_size,
> unit_type);
> default:
> return -EOPNOTSUPP;
> @@ -2762,8 +2760,7 @@ static int airoha_dev_setup_tc_block_cb(enum tc_setup_type type,
> {
> struct net_device *netdev = cb_priv;
> struct airoha_gdm_dev *dev = netdev_priv(netdev);
> - struct airoha_gdm_port *port = dev->port;
> - struct airoha_eth *eth = port->qdma->eth;
> + struct airoha_eth *eth = dev->eth;
>
> if (!tc_can_offload(netdev))
> return -EOPNOTSUPP;
> diff --git a/drivers/net/ethernet/airoha/airoha_eth.h b/drivers/net/ethernet/airoha/airoha_eth.h
> index c78cabbec753..f1eea492217c 100644
> --- a/drivers/net/ethernet/airoha/airoha_eth.h
> +++ b/drivers/net/ethernet/airoha/airoha_eth.h
> @@ -537,12 +537,12 @@ struct airoha_qdma {
>
> struct airoha_gdm_dev {
> struct airoha_gdm_port *port;
> + struct airoha_qdma *qdma;
> struct net_device *dev;
> struct airoha_eth *eth;
> };
>
> struct airoha_gdm_port {
> - struct airoha_qdma *qdma;
> struct airoha_gdm_dev *dev;
> int id;
> int nbq;
> @@ -666,19 +666,18 @@ static inline bool airoha_is_7583(struct airoha_eth *eth)
> return eth->soc->version == 0x7583;
> }
>
> -int airoha_get_fe_port(struct airoha_gdm_port *port);
> +int airoha_get_fe_port(struct airoha_gdm_dev *dev);
> bool airoha_is_valid_gdm_dev(struct airoha_eth *eth,
> struct airoha_gdm_dev *dev);
>
> -void airoha_ppe_set_cpu_port(struct airoha_gdm_port *port, u8 ppe_id,
> - u8 fport);
> +void airoha_ppe_set_cpu_port(struct airoha_gdm_dev *dev, u8 ppe_id, u8 fport);
> bool airoha_ppe_is_enabled(struct airoha_eth *eth, int index);
> void airoha_ppe_check_skb(struct airoha_ppe_dev *dev, struct sk_buff *skb,
> u16 hash, bool rx_wlan);
> int airoha_ppe_setup_tc_block_cb(struct airoha_ppe_dev *dev, void *type_data);
> int airoha_ppe_init(struct airoha_eth *eth);
> void airoha_ppe_deinit(struct airoha_eth *eth);
> -void airoha_ppe_init_upd_mem(struct airoha_gdm_port *port);
> +void airoha_ppe_init_upd_mem(struct airoha_gdm_dev *dev);
> u32 airoha_ppe_get_total_num_entries(struct airoha_ppe *ppe);
> struct airoha_foe_entry *airoha_ppe_foe_get_entry(struct airoha_ppe *ppe,
> u32 hash);
> diff --git a/drivers/net/ethernet/airoha/airoha_ppe.c b/drivers/net/ethernet/airoha/airoha_ppe.c
> index af7af4097b98..22f5f1bae730 100644
> --- a/drivers/net/ethernet/airoha/airoha_ppe.c
> +++ b/drivers/net/ethernet/airoha/airoha_ppe.c
> @@ -84,9 +84,9 @@ static u32 airoha_ppe_get_timestamp(struct airoha_ppe *ppe)
> AIROHA_FOE_IB1_BIND_TIMESTAMP);
> }
>
> -void airoha_ppe_set_cpu_port(struct airoha_gdm_port *port, u8 ppe_id, u8 fport)
> +void airoha_ppe_set_cpu_port(struct airoha_gdm_dev *dev, u8 ppe_id, u8 fport)
> {
> - struct airoha_qdma *qdma = port->qdma;
> + struct airoha_qdma *qdma = dev->qdma;
> struct airoha_eth *eth = qdma->eth;
> u8 qdma_id = qdma - ð->qdma[0];
> u32 fe_cpu_port;
> @@ -180,8 +180,8 @@ static void airoha_ppe_hw_init(struct airoha_ppe *ppe)
> if (!port)
> continue;
>
> - airoha_ppe_set_cpu_port(port, i,
> - airoha_get_fe_port(port));
> + airoha_ppe_set_cpu_port(port->dev, i,
> + airoha_get_fe_port(port->dev));
> }
> }
> }
> @@ -1473,11 +1473,12 @@ void airoha_ppe_check_skb(struct airoha_ppe_dev *dev, struct sk_buff *skb,
> airoha_ppe_foe_insert_entry(ppe, skb, hash, rx_wlan);
> }
>
> -void airoha_ppe_init_upd_mem(struct airoha_gdm_port *port)
> +void airoha_ppe_init_upd_mem(struct airoha_gdm_dev *dev)
> {
> - struct airoha_eth *eth = port->qdma->eth;
> - struct net_device *dev = port->dev->dev;
> - const u8 *addr = dev->dev_addr;
> + struct airoha_gdm_port *port = dev->port;
> + struct net_device *netdev = dev->dev;
> + struct airoha_eth *eth = dev->eth;
> + const u8 *addr = netdev->dev_addr;
> u32 val;
>
> val = (addr[2] << 24) | (addr[3] << 16) | (addr[4] << 8) | addr[5];
>
> --
> 2.54.0
>
Commenting on sashiko's report:
https://sashiko.dev/#/patchset/20260511-airoha-eth-multi-serdes-v6-0-c899462c4f75%40kernel.org
- This isn't a regression introduced by this patch, but is it safe to use
spin_lock() here instead of spin_lock_bh()?
- According to my understanding ndo_get_stats64 callback can't run softirq
context.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply
* Re: [PATCH] dt-bindings: Consolidate "sram" property definition
From: Vinod Koul @ 2026-05-13 8:22 UTC (permalink / raw)
To: Rob Herring (Arm)
Cc: Liu Ying, Philipp Zabel, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, David Airlie, Simona Vetter,
Krzysztof Kozlowski, Conor Dooley, Frank Li, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam, Rob Clark, Sean Paul,
Konrad Dybcio, Akhil P Oommen, Dmitry Baryshkov, Abhinav Kumar,
Jessica Zhang, Marijn Suijten, Nas Chung, Jackson Lee,
Mauro Carvalho Chehab, Mirela Rabulea, Detlev Casanova,
Ezequiel Garcia, Heiko Stuebner, Hugues Fruchet, Alain Volmat,
Maxime Coquelin, Alexandre Torgue, Andrew Lunn, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, MD Danish Anwar,
Roger Quadros, Parvathi Pudi, Mohan Reddy Putluru,
Bjorn Andersson, Mathieu Poirier, Neil Armstrong, Kevin Hilman,
Jerome Brunet, Martin Blumenstingl, Michal Simek, Mark Brown,
Matthias Brugger, AngeloGioacchino Del Regno, Linus Walleij,
Lorenzo Bianconi, Felix Fietkau, Andrew F. Davis, Hussain Khaja,
Suman Anna, Ben Levinsky, Tanmay Shah, Erwan Leray,
Fabrice Gasnier, Roger Quadros, dri-devel, devicetree, imx,
linux-arm-kernel, linux-kernel, linux-arm-msm, freedreno,
dmaengine, linux-media, linux-rockchip, linux-stm32, netdev,
linux-remoteproc, linux-amlogic, linux-spi, linux-mediatek
In-Reply-To: <20260511165942.2774868-1-robh@kernel.org>
On 11-05-26, 11:59, Rob Herring (Arm) wrote:
> The "sram" property has become a de facto standard property, so create a
> common schema for it and drop all the duplicated definitions.
Acked-by: Vinod Koul <vkoul@kernel.org>
--
~Vinod
^ permalink raw reply
* Re: [PATCH v5 4/6] dt-bindings: display: mediatek: tdshp: Add support for MT8196
From: CK Hu (胡俊光) @ 2026-05-13 8:03 UTC (permalink / raw)
To: matthias.bgg@gmail.com, tzimmermann@suse.de, simona@ffwll.ch,
chunkuang.hu@kernel.org, AngeloGioacchino Del Regno,
Jay Liu (刘博), airlied@gmail.com, krzk+dt@kernel.org,
robh@kernel.org, p.zabel@pengutronix.de,
maarten.lankhorst@linux.intel.com, mripard@kernel.org,
conor+dt@kernel.org
Cc: dri-devel@lists.freedesktop.org,
linux-mediatek@lists.infradead.org, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org,
linux-arm-kernel@lists.infradead.org
In-Reply-To: <20260427112131.23423-5-jay.liu@mediatek.com>
On Mon, 2026-04-27 at 19:20 +0800, Jay Liu wrote:
> Add tdshp hardware description for MediaTek MT8196 SoC
>
> Signed-off-by: Jay Liu <jay.liu@mediatek.com>
> ---
> .../display/mediatek/mediatek,tdshp.yaml | 46 +++++++++++++++++++
> 1 file changed, 46 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/display/mediatek/mediatek,tdshp.yaml
>
> diff --git a/Documentation/devicetree/bindings/display/mediatek/mediatek,tdshp.yaml b/Documentation/devicetree/bindings/display/mediatek/mediatek,tdshp.yaml
> new file mode 100644
> index 000000000000..50b24cc22420
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/display/mediatek/mediatek,tdshp.yaml
> @@ -0,0 +1,46 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: https://urldefense.com/v3/__http://devicetree.org/schemas/display/mediatek/mediatek,tdshp.yaml*__;Iw!!CTRNKA9wMg0ARbw!jvLiL6w7ScJqhkM0IyiLok4cwzb-e1gME-mO9r5lLT3JTrgaBBiiV1j8LFkmJkIafaGiBya2GJN6h38e$
> +$schema: https://urldefense.com/v3/__http://devicetree.org/meta-schemas/core.yaml*__;Iw!!CTRNKA9wMg0ARbw!jvLiL6w7ScJqhkM0IyiLok4cwzb-e1gME-mO9r5lLT3JTrgaBBiiV1j8LFkmJkIafaGiBya2GCPflrFz$
> +
> +title: MediaTek display 2D sharpness processor
> +
> +maintainers:
> + - Chun-Kuang Hu <chunkuang.hu@kernel.org>
> + - Philipp Zabel <p.zabel@pengutronix.de>
> +
> +description: |
> + MediaTek display 2D sharpness processor, namely TDSHP, provides a
a -> an
> + operation used to adjust sharpness in display system.
> +
> +properties:
> + compatible:
> + enum:
> + - mediatek,mt8196-disp-tdshp
> +
> + reg:
> + maxItems: 1
> +
> + clocks:
> + maxItems: 1
Refer to other display block binding document, and find out the common property.
Such as power-domains, gce-client-reg, ports.
Regards,
CK
> +
> +required:
> + - compatible
> + - reg
> + - clocks
> +
> +additionalProperties: false
> +
> +examples:
> + - |
> + soc {
> + #address-cells = <2>;
> + #size-cells = <2>;
> +
> + tdshp@321e0000 {
> + compatible = "mediatek,mt8196-disp-tdshp";
> + reg = <0 0x321e0000 0 0x1000>;
> + clocks = <&dispsys_config_clk 107>;
> + };
> + };
^ permalink raw reply
* Re: [PATCH v2 6/8] PCI: aardvark: Add 100 ms delay after link training
From: Hans Zhang @ 2026-05-13 7:34 UTC (permalink / raw)
To: Pali Rohár
Cc: bhelgaas, lpieralisi, kwilczynski, mani, vigneshr, jingoohan1,
thomas.petazzoni, ryder.lee, jianjun.wang, claudiu.beznea.uj,
mpillai, robh, s-vadapalli, linux-omap, linux-arm-kernel,
linux-mediatek, linux-renesas-soc, linux-pci, linux-kernel
In-Reply-To: <20260513072008.vol4htgbzquly2rb@pali>
On 5/13/26 15:20, Pali Rohár wrote:
> On Wednesday 13 May 2026 15:00:04 Hans Zhang wrote:
>>
>>
>> On 5/13/26 05:25, Pali Rohár wrote:
>>> On Wednesday 06 May 2026 23:23:44 Hans Zhang wrote:
>>>> The Aardvark PCIe controller driver waits for the link to come up but
>>>> does not implement the mandatory 100 ms delay after link training
>>>> completes for speeds greater than 5.0 GT/s (PCIe r6.0 sec 6.6.1).
>>>>
>>>> The driver already maintains a 'link_gen' field that holds the negotiated
>>>> link speed. Use it together with pcie_wait_after_link_train() to insert
>>>> the required delay immediately after confirming that the link is up.
>>>>
>>>> Signed-off-by: Hans Zhang <18255117159@163.com>
>>>> ---
>>>> drivers/pci/controller/pci-aardvark.c | 4 +++-
>>>> 1 file changed, 3 insertions(+), 1 deletion(-)
>>>>
>>>> diff --git a/drivers/pci/controller/pci-aardvark.c b/drivers/pci/controller/pci-aardvark.c
>>>> index e34bea1ff0ac..526351c21c49 100644
>>>> --- a/drivers/pci/controller/pci-aardvark.c
>>>> +++ b/drivers/pci/controller/pci-aardvark.c
>>>> @@ -350,8 +350,10 @@ static int advk_pcie_wait_for_link(struct advk_pcie *pcie)
>>>> /* check if the link is up or not */
>>>> for (retries = 0; retries < LINK_WAIT_MAX_RETRIES; retries++) {
>>>> - if (advk_pcie_link_up(pcie))
>>>> + if (advk_pcie_link_up(pcie)) {
>>>> + pcie_wait_after_link_train(pcie->link_gen);
>>>> return 0;
>>>> + }
>>>> usleep_range(LINK_WAIT_USLEEP_MIN, LINK_WAIT_USLEEP_MAX);
>>>> }
>>>> --
>>>> 2.34.1
>>>>
>>>
>>> Are you sure that this is correct to do? Have you checked the A3720
>>> Functional Specification which describes how to bring PCIe link up?
>>>
>>> A3720 PCIe controller is buggy and needs more timing hacks to make it
>>> behave. Playing with random sleeps can break its internal logic.
>>> I'm not sure if it could be safe without proper testing.
>>>
>>> And IIRC A3720 PCIe controller is just PCIe2.0 with 5 GT/s.
>>
>>
>> Hi Pali,
>>
>> 1. This driver does not support A3720.
>>
>> static const struct of_device_id advk_pcie_of_match_table[] = {
>> { .compatible = "marvell,armada-3700-pcie", },
>> {},
>> };
>> MODULE_DEVICE_TABLE(of, advk_pcie_of_match_table);
>>
>> If you need support for A3720, please submit the corresponding patch so that
>> Bjorn and Mani can review it.
>
> 3700 (or 37xx) is family and covers both a3710 and a3720. In most cases is the
> a3720 dominant and hence identifiers 3700 and 3720 are begin mixed.
>
>>
>> 2. If A3720 only supports GEN2, you can configure "max-link-speed" to be 2
>> in the DT. This will not affect the functionality of this patch.
>
> Whole A37xx supports only GEN2. And in DT files for 37xx should be
> already there max-link-speed.
>
> Seems that in advk_pcie_of_match_table there is no GEN3 device
> specified.
>
Hi Pali,
However, I saw many GEN3 assignments and conditions in the code.
ret = of_pci_get_max_link_speed(dev->of_node);
if (ret <= 0 || ret > 3)
pcie->link_gen = 3;
else
pcie->link_gen = ret;
static void advk_pcie_train_link(struct advk_pcie *pcie)
{
struct device *dev = &pcie->pdev->dev;
u32 reg;
int ret;
/*
* Setup PCIe rev / gen compliance based on device tree property
* 'max-link-speed' which also forces maximal link speed.
*/
reg = advk_readl(pcie, PCIE_CORE_CTRL0_REG);
reg &= ~PCIE_GEN_SEL_MSK;
if (pcie->link_gen == 3)
reg |= SPEED_GEN_3;
else if (pcie->link_gen == 2)
reg |= SPEED_GEN_2;
else
reg |= SPEED_GEN_1;
advk_writel(pcie, reg, PCIE_CORE_CTRL0_REG);
/*
* Set maximal link speed value also into PCIe Link Control 2 register.
* Armada 3700 Functional Specification says that default value is based
* on SPEED_GEN but tests showed that default value is always 8.0 GT/s.
*/
reg = advk_readl(pcie, PCIE_CORE_PCIEXP_CAP + PCI_EXP_LNKCTL2);
reg &= ~PCI_EXP_LNKCTL2_TLS;
if (pcie->link_gen == 3)
reg |= PCI_EXP_LNKCTL2_TLS_8_0GT;
else if (pcie->link_gen == 2)
reg |= PCI_EXP_LNKCTL2_TLS_5_0GT;
else
reg |= PCI_EXP_LNKCTL2_TLS_2_5GT;
advk_writel(pcie, reg, PCIE_CORE_PCIEXP_CAP + PCI_EXP_LNKCTL2);
....
If you are certain about the relevant information. Is it understandable
that we need to delete the code related to GEN3?
Best regards,
Hans
>> 3. This patch is a common delay requirement stipulated by the PCIe
>> specification. If it is greater than GEN2, then msleep(100) will be added;
>> otherwise, there will be no such delay.
>>
>> 4. For instance, we often come across the situation where some common APIs
>> are modified, and in many cases, their functionality does not require the
>> actual development board for verification. I believe that many other
>> developers and maintainers have modified different parts of the code. For
>> example, the recent submission:
>
> Switching one API to another is one thing. But changing code which looks
> to be critical, specially when it is known that hw has bugs, can cause
> breaking of existing boards.
>
>> commit 750277048afe7ce8ebfc0b120de7dfbc745058a7
>> Author: Nam Cao <namcao@linutronix.de>
>> Date: Thu Jun 26 16:47:53 2025 +0200
>>
>> PCI: aardvark: Switch to msi_create_parent_irq_domain()
>>
>> Switch to msi_create_parent_irq_domain() from
>> pci_msi_create_irq_domain()
>> which was using legacy MSI domain setup.
>>
>>
>> And many controller drivers have been modified.
>>
>>
>> Best regards,
>> Hans
>>
>>
^ permalink raw reply
* [PATCH v2] wifi: mt76: mt7925: Add coredump callback in pci_driver
From: JB Tsai @ 2026-05-13 7:23 UTC (permalink / raw)
To: nbd, lorenzo
Cc: linux-wireless, linux-mediatek, Deren.Wu, Sean.Wang, Quan.Zhou,
Ryder.Lee, Leon.Yen, litien.chang, jeff.hsu, jb.tsai, Jeff Hsu
From: Jeff Hsu <Jeff.Hsu@mediatek.com>
Register coredump callback(mt7925_coredump) in pci_driver,
it can let platform can trigger core dump to collect the
log and recover back after coredump complete without debugfs
Some platform not have debugfs
Signed-off-by: Jeff Hsu <Jeff.Hsu@mediatek.com>
---
drivers/net/wireless/mediatek/mt76/mt7925/mcu.c | 1 +
drivers/net/wireless/mediatek/mt76/mt7925/pci.c | 12 ++++++++++++
2 files changed, 13 insertions(+)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c
index 37cdf3e8a067..cd502166a7f9 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c
@@ -1014,6 +1014,7 @@ int mt7925_mcu_chip_config(struct mt792x_dev *dev, const char *cmd)
return mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD(CHIP_CONFIG),
&req, sizeof(req), false);
}
+EXPORT_SYMBOL_GPL(mt7925_mcu_chip_config);
int mt7925_mcu_set_deep_sleep(struct mt792x_dev *dev, bool enable)
{
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/pci.c b/drivers/net/wireless/mediatek/mt76/mt7925/pci.c
index c4161754c01d..57006cd75b1c 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/pci.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/pci.c
@@ -610,6 +610,17 @@ static int mt7925_pci_restore(struct device *device)
return _mt7925_pci_resume(device, true);
}
+static void mt7925_coredump(struct device *dev)
+{
+ struct pci_dev *pdev = to_pci_dev(dev);
+ struct mt76_dev *mdev = pci_get_drvdata(pdev);
+ struct mt792x_dev *dev_792x = container_of(mdev, struct mt792x_dev, mt76);
+
+ mt792x_mutex_acquire(dev_792x);
+ mt7925_mcu_chip_config(dev_792x, "assert");
+ mt792x_mutex_release(dev_792x);
+}
+
static const struct dev_pm_ops mt7925_pm_ops = {
.suspend = pm_sleep_ptr(mt7925_pci_suspend),
.resume = pm_sleep_ptr(mt7925_pci_resume),
@@ -626,6 +637,7 @@ static struct pci_driver mt7925_pci_driver = {
.remove = mt7925_pci_remove,
.shutdown = mt7925_pci_shutdown,
.driver.pm = pm_sleep_ptr(&mt7925_pm_ops),
+ .driver.coredump = mt7925_coredump,
};
module_pci_driver(mt7925_pci_driver);
--
2.45.2
^ permalink raw reply related
* Re: [PATCH v2 6/8] PCI: aardvark: Add 100 ms delay after link training
From: Pali Rohár @ 2026-05-13 7:20 UTC (permalink / raw)
To: Hans Zhang
Cc: bhelgaas, lpieralisi, kwilczynski, mani, vigneshr, jingoohan1,
thomas.petazzoni, ryder.lee, jianjun.wang, claudiu.beznea.uj,
mpillai, robh, s-vadapalli, linux-omap, linux-arm-kernel,
linux-mediatek, linux-renesas-soc, linux-pci, linux-kernel
In-Reply-To: <581e91fb-2e57-43ed-b79d-19dbf384b955@163.com>
On Wednesday 13 May 2026 15:00:04 Hans Zhang wrote:
>
>
> On 5/13/26 05:25, Pali Rohár wrote:
> > On Wednesday 06 May 2026 23:23:44 Hans Zhang wrote:
> > > The Aardvark PCIe controller driver waits for the link to come up but
> > > does not implement the mandatory 100 ms delay after link training
> > > completes for speeds greater than 5.0 GT/s (PCIe r6.0 sec 6.6.1).
> > >
> > > The driver already maintains a 'link_gen' field that holds the negotiated
> > > link speed. Use it together with pcie_wait_after_link_train() to insert
> > > the required delay immediately after confirming that the link is up.
> > >
> > > Signed-off-by: Hans Zhang <18255117159@163.com>
> > > ---
> > > drivers/pci/controller/pci-aardvark.c | 4 +++-
> > > 1 file changed, 3 insertions(+), 1 deletion(-)
> > >
> > > diff --git a/drivers/pci/controller/pci-aardvark.c b/drivers/pci/controller/pci-aardvark.c
> > > index e34bea1ff0ac..526351c21c49 100644
> > > --- a/drivers/pci/controller/pci-aardvark.c
> > > +++ b/drivers/pci/controller/pci-aardvark.c
> > > @@ -350,8 +350,10 @@ static int advk_pcie_wait_for_link(struct advk_pcie *pcie)
> > > /* check if the link is up or not */
> > > for (retries = 0; retries < LINK_WAIT_MAX_RETRIES; retries++) {
> > > - if (advk_pcie_link_up(pcie))
> > > + if (advk_pcie_link_up(pcie)) {
> > > + pcie_wait_after_link_train(pcie->link_gen);
> > > return 0;
> > > + }
> > > usleep_range(LINK_WAIT_USLEEP_MIN, LINK_WAIT_USLEEP_MAX);
> > > }
> > > --
> > > 2.34.1
> > >
> >
> > Are you sure that this is correct to do? Have you checked the A3720
> > Functional Specification which describes how to bring PCIe link up?
> >
> > A3720 PCIe controller is buggy and needs more timing hacks to make it
> > behave. Playing with random sleeps can break its internal logic.
> > I'm not sure if it could be safe without proper testing.
> >
> > And IIRC A3720 PCIe controller is just PCIe2.0 with 5 GT/s.
>
>
> Hi Pali,
>
> 1. This driver does not support A3720.
>
> static const struct of_device_id advk_pcie_of_match_table[] = {
> { .compatible = "marvell,armada-3700-pcie", },
> {},
> };
> MODULE_DEVICE_TABLE(of, advk_pcie_of_match_table);
>
> If you need support for A3720, please submit the corresponding patch so that
> Bjorn and Mani can review it.
3700 (or 37xx) is family and covers both a3710 and a3720. In most cases is the
a3720 dominant and hence identifiers 3700 and 3720 are begin mixed.
>
> 2. If A3720 only supports GEN2, you can configure "max-link-speed" to be 2
> in the DT. This will not affect the functionality of this patch.
Whole A37xx supports only GEN2. And in DT files for 37xx should be
already there max-link-speed.
Seems that in advk_pcie_of_match_table there is no GEN3 device
specified.
> 3. This patch is a common delay requirement stipulated by the PCIe
> specification. If it is greater than GEN2, then msleep(100) will be added;
> otherwise, there will be no such delay.
>
> 4. For instance, we often come across the situation where some common APIs
> are modified, and in many cases, their functionality does not require the
> actual development board for verification. I believe that many other
> developers and maintainers have modified different parts of the code. For
> example, the recent submission:
Switching one API to another is one thing. But changing code which looks
to be critical, specially when it is known that hw has bugs, can cause
breaking of existing boards.
> commit 750277048afe7ce8ebfc0b120de7dfbc745058a7
> Author: Nam Cao <namcao@linutronix.de>
> Date: Thu Jun 26 16:47:53 2025 +0200
>
> PCI: aardvark: Switch to msi_create_parent_irq_domain()
>
> Switch to msi_create_parent_irq_domain() from
> pci_msi_create_irq_domain()
> which was using legacy MSI domain setup.
>
>
> And many controller drivers have been modified.
>
>
> Best regards,
> Hans
>
>
^ permalink raw reply
* Re: [PATCH v2 6/8] PCI: aardvark: Add 100 ms delay after link training
From: Hans Zhang @ 2026-05-13 7:00 UTC (permalink / raw)
To: Pali Rohár
Cc: bhelgaas, lpieralisi, kwilczynski, mani, vigneshr, jingoohan1,
thomas.petazzoni, ryder.lee, jianjun.wang, claudiu.beznea.uj,
mpillai, robh, s-vadapalli, linux-omap, linux-arm-kernel,
linux-mediatek, linux-renesas-soc, linux-pci, linux-kernel
In-Reply-To: <20260512212531.jupoocz7acv22qyg@pali>
On 5/13/26 05:25, Pali Rohár wrote:
> On Wednesday 06 May 2026 23:23:44 Hans Zhang wrote:
>> The Aardvark PCIe controller driver waits for the link to come up but
>> does not implement the mandatory 100 ms delay after link training
>> completes for speeds greater than 5.0 GT/s (PCIe r6.0 sec 6.6.1).
>>
>> The driver already maintains a 'link_gen' field that holds the negotiated
>> link speed. Use it together with pcie_wait_after_link_train() to insert
>> the required delay immediately after confirming that the link is up.
>>
>> Signed-off-by: Hans Zhang <18255117159@163.com>
>> ---
>> drivers/pci/controller/pci-aardvark.c | 4 +++-
>> 1 file changed, 3 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/pci/controller/pci-aardvark.c b/drivers/pci/controller/pci-aardvark.c
>> index e34bea1ff0ac..526351c21c49 100644
>> --- a/drivers/pci/controller/pci-aardvark.c
>> +++ b/drivers/pci/controller/pci-aardvark.c
>> @@ -350,8 +350,10 @@ static int advk_pcie_wait_for_link(struct advk_pcie *pcie)
>>
>> /* check if the link is up or not */
>> for (retries = 0; retries < LINK_WAIT_MAX_RETRIES; retries++) {
>> - if (advk_pcie_link_up(pcie))
>> + if (advk_pcie_link_up(pcie)) {
>> + pcie_wait_after_link_train(pcie->link_gen);
>> return 0;
>> + }
>>
>> usleep_range(LINK_WAIT_USLEEP_MIN, LINK_WAIT_USLEEP_MAX);
>> }
>> --
>> 2.34.1
>>
>
> Are you sure that this is correct to do? Have you checked the A3720
> Functional Specification which describes how to bring PCIe link up?
>
> A3720 PCIe controller is buggy and needs more timing hacks to make it
> behave. Playing with random sleeps can break its internal logic.
> I'm not sure if it could be safe without proper testing.
>
> And IIRC A3720 PCIe controller is just PCIe2.0 with 5 GT/s.
Hi Pali,
1. This driver does not support A3720.
static const struct of_device_id advk_pcie_of_match_table[] = {
{ .compatible = "marvell,armada-3700-pcie", },
{},
};
MODULE_DEVICE_TABLE(of, advk_pcie_of_match_table);
If you need support for A3720, please submit the corresponding patch so
that Bjorn and Mani can review it.
2. If A3720 only supports GEN2, you can configure "max-link-speed" to be
2 in the DT. This will not affect the functionality of this patch.
3. This patch is a common delay requirement stipulated by the PCIe
specification. If it is greater than GEN2, then msleep(100) will be
added; otherwise, there will be no such delay.
4. For instance, we often come across the situation where some common
APIs are modified, and in many cases, their functionality does not
require the actual development board for verification. I believe that
many other developers and maintainers have modified different parts of
the code. For example, the recent submission:
commit 750277048afe7ce8ebfc0b120de7dfbc745058a7
Author: Nam Cao <namcao@linutronix.de>
Date: Thu Jun 26 16:47:53 2025 +0200
PCI: aardvark: Switch to msi_create_parent_irq_domain()
Switch to msi_create_parent_irq_domain() from
pci_msi_create_irq_domain()
which was using legacy MSI domain setup.
And many controller drivers have been modified.
Best regards,
Hans
^ permalink raw reply
* [PATCH] wifi: mt76: mt7921: fix uninitialized variable warning
From: Hongling Zeng @ 2026-05-13 2:14 UTC (permalink / raw)
To: nbd, lorenzo, ryder.lee, shayne.chen, sean.wang, matthias.bgg,
angelogioacchino.delregno, xiong.huang, madhurkumar004
Cc: linux-wireless, linux-kernel, linux-arm-kernel, linux-mediatek,
zhongling0719, Hongling Zeng, kernel test robot
Move the initialization of 'dev' before the error path that uses it.
This fixes the compiler warning:
drivers/net/wireless/mediatek/mt76/mt7921/pci.c:347:6: warning:
variable 'dev' is used uninitialized whenever 'if' condition is true
Fixes: 0d56655a74ef ("wifi: mt76: mt7921: fix resource leak in probe error path")
Reported-by: kernel test robot <lkp@intel.com>
Closes: https://lore.kernel.org/oe-kbuild-all/202605130432.S8Ozipm2-lkp@intel.com/
Signed-off-by: Hongling Zeng <zenghongling@kylinos.cn>
---
drivers/net/wireless/mediatek/mt76/mt7921/pci.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c
index 4bb436465a3d..49a37185f056 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c
@@ -343,13 +343,14 @@ static int mt7921_pci_probe(struct pci_dev *pdev,
pci_set_drvdata(pdev, mdev);
+ dev = container_of(mdev, struct mt792x_dev, mt76);
+
regs = pcim_iomap_region(pdev, 0, pci_name(pdev));
if (IS_ERR(regs)) {
ret = PTR_ERR(regs);
goto err_free_dev;
}
- dev = container_of(mdev, struct mt792x_dev, mt76);
dev->fw_features = features;
dev->hif_ops = &mt7921_pcie_ops;
dev->irq_map = &irq_map;
--
2.25.1
^ permalink raw reply related
* Re: [PATCH] wifi: mt76: mt7925: Add coredump callback in pci_driver
From: Sean Wang @ 2026-05-12 21:30 UTC (permalink / raw)
To: JB Tsai
Cc: nbd, lorenzo, linux-wireless, linux-mediatek, Deren.Wu, Sean.Wang,
Quan.Zhou, Ryder.Lee, Leon.Yen, litien.chang, jeff.hsu
In-Reply-To: <20260505055252.2558613-1-jb.tsai@mediatek.com>
Hi,
On Tue, May 5, 2026 at 12:53 AM JB Tsai <jb.tsai@mediatek.com> wrote:
>
> From: Jeff Hsu <Jeff.Hsu@mediatek.com>
>
> Register coredump callback(mt7925_coredump) in pci_driver,
> it can let platform can trigger core dump to collect the
> log and recover back after coredump complete without debugfs
>
> Some platform not have debugfs
>
> Signed-off-by: Jeff Hsu <Jeff.Hsu@mediatek.com>
> ---
> drivers/net/wireless/mediatek/mt76/mt7925/mcu.c | 1 +
> drivers/net/wireless/mediatek/mt76/mt7925/pci.c | 12 ++++++++++++
> 2 files changed, 13 insertions(+)
>
> diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c
> index 37cdf3e8a067..cd502166a7f9 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c
> +++ b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c
> @@ -1014,6 +1014,7 @@ int mt7925_mcu_chip_config(struct mt792x_dev *dev, const char *cmd)
> return mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD(CHIP_CONFIG),
> &req, sizeof(req), false);
> }
> +EXPORT_SYMBOL_GPL(mt7925_mcu_chip_config);
>
> int mt7925_mcu_set_deep_sleep(struct mt792x_dev *dev, bool enable)
> {
> diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/pci.c b/drivers/net/wireless/mediatek/mt76/mt7925/pci.c
> index c4161754c01d..5b3e62e5f157 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt7925/pci.c
> +++ b/drivers/net/wireless/mediatek/mt76/mt7925/pci.c
> @@ -610,6 +610,17 @@ static int mt7925_pci_restore(struct device *device)
> return _mt7925_pci_resume(device, true);
> }
>
> +static void mt7925_coredump(struct device *dev)
> +{
> + struct pci_dev *pdev = to_pci_dev(device);
There is a build error on this line.
../drivers/net/wireless/mediatek/mt76/mt7925/pci.c: In function
‘mt7925_coredump’:
../drivers/net/wireless/mediatek/mt76/mt7925/pci.c:682:43: error:
‘device’ undeclared (first use in this function)
682 | struct pci_dev *pdev = to_pci_dev(device);
| ^~~~~~
../include/linux/container_of.h:20:33: note: in definition of macro
‘container_of’
20 | void *__mptr = (void *)(ptr);
\
| ^~~
../drivers/net/wireless/mediatek/mt76/mt7925/pci.c:682:32: note: in
expansion of macro ‘to_pci_dev’
682 | struct pci_dev *pdev = to_pci_dev(device);
| ^~~~~~~~~~
../drivers/net/wireless/mediatek/mt76/mt7925/pci.c:682:43: note: each
undeclared identifier is reported only once for each function it
appears in
682 | struct pci_dev *pdev = to_pci_dev(device);
| ^~~~~~
../include/linux/container_of.h:20:33: note: in definition of macro
‘container_of’
20 | void *__mptr = (void *)(ptr);
> + struct mt76_dev *mdev = pci_get_drvdata(pdev);
> + struct mt792x_dev *dev_792x = container_of(mdev, struct mt792x_dev, mt76);
> +
> + mt792x_mutex_acquire(dev_792x);
> + mt7925_mcu_chip_config(dev_792x, "assert");
> + mt792x_mutex_release(dev_792x);
> +}
> +
> static const struct dev_pm_ops mt7925_pm_ops = {
> .suspend = pm_sleep_ptr(mt7925_pci_suspend),
> .resume = pm_sleep_ptr(mt7925_pci_resume),
> @@ -626,6 +637,7 @@ static struct pci_driver mt7925_pci_driver = {
> .remove = mt7925_pci_remove,
> .shutdown = mt7925_pci_shutdown,
> .driver.pm = pm_sleep_ptr(&mt7925_pm_ops),
> + .driver.coredump = mt7925_coredump,
> };
>
> module_pci_driver(mt7925_pci_driver);
> --
> 2.45.2
>
>
^ permalink raw reply
* Re: [PATCH v2 6/8] PCI: aardvark: Add 100 ms delay after link training
From: Pali Rohár @ 2026-05-12 21:25 UTC (permalink / raw)
To: Hans Zhang
Cc: bhelgaas, lpieralisi, kwilczynski, mani, vigneshr, jingoohan1,
thomas.petazzoni, ryder.lee, jianjun.wang, claudiu.beznea.uj,
mpillai, robh, s-vadapalli, linux-omap, linux-arm-kernel,
linux-mediatek, linux-renesas-soc, linux-pci, linux-kernel
In-Reply-To: <20260506152346.166056-7-18255117159@163.com>
On Wednesday 06 May 2026 23:23:44 Hans Zhang wrote:
> The Aardvark PCIe controller driver waits for the link to come up but
> does not implement the mandatory 100 ms delay after link training
> completes for speeds greater than 5.0 GT/s (PCIe r6.0 sec 6.6.1).
>
> The driver already maintains a 'link_gen' field that holds the negotiated
> link speed. Use it together with pcie_wait_after_link_train() to insert
> the required delay immediately after confirming that the link is up.
>
> Signed-off-by: Hans Zhang <18255117159@163.com>
> ---
> drivers/pci/controller/pci-aardvark.c | 4 +++-
> 1 file changed, 3 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/pci/controller/pci-aardvark.c b/drivers/pci/controller/pci-aardvark.c
> index e34bea1ff0ac..526351c21c49 100644
> --- a/drivers/pci/controller/pci-aardvark.c
> +++ b/drivers/pci/controller/pci-aardvark.c
> @@ -350,8 +350,10 @@ static int advk_pcie_wait_for_link(struct advk_pcie *pcie)
>
> /* check if the link is up or not */
> for (retries = 0; retries < LINK_WAIT_MAX_RETRIES; retries++) {
> - if (advk_pcie_link_up(pcie))
> + if (advk_pcie_link_up(pcie)) {
> + pcie_wait_after_link_train(pcie->link_gen);
> return 0;
> + }
>
> usleep_range(LINK_WAIT_USLEEP_MIN, LINK_WAIT_USLEEP_MAX);
> }
> --
> 2.34.1
>
Are you sure that this is correct to do? Have you checked the A3720
Functional Specification which describes how to bring PCIe link up?
A3720 PCIe controller is buggy and needs more timing hacks to make it
behave. Playing with random sleeps can break its internal logic.
I'm not sure if it could be safe without proper testing.
And IIRC A3720 PCIe controller is just PCIe2.0 with 5 GT/s.
^ permalink raw reply
* Re: [PATCH net-next v6 11/12] net: airoha: Support multiple LAN/WAN interfaces for hw MAC address configuration
From: Lorenzo Bianconi @ 2026-05-12 20:58 UTC (permalink / raw)
To: Benjamin Larsson
Cc: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Christian Marangi, linux-arm-kernel, linux-mediatek, netdev,
devicetree, Madhur Agrawal
In-Reply-To: <f4a11830-8a3f-4cc3-ab82-e6f02ca34ae8@genexis.eu>
[-- Attachment #1: Type: text/plain, Size: 3464 bytes --]
On May 12, Benjamin Larsson wrote:
> Hi.
>
> On 11/05/2026 12:49, Lorenzo Bianconi wrote:
> > The EN7581 and AN7583 SoCs provide registers to configure hardware LAN/WAN
> > MAC addresses, used to determine whether received traffic is destined for
> > this host or should be forwarded to another device.
> > The SoC hardware design assumes all interfaces configured as LAN (or WAN)
> > share a common upper MAC address, which is programmed into the
> > REG_FE_{LAN,WAN}_MAC_H register. The lower bytes of 'local' addresses can
> > be expressed as a range via the REG_FE_MAC_LMIN and REG_FE_MAC_LMAX
> > registers.
> > Previously, only a single interface was considered when programming these
> > registers. Extend the logic to derive the correct minimum and maximum
> > values for REG_FE_MAC_LMIN/REG_FE_MAC_LMAX when two or more interfaces are
> > configured as LAN or WAN.
> >
> > Tested-by: Madhur Agrawal <madhur.agrawal@airoha.com>
> > Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
> > ---
> > drivers/net/ethernet/airoha/airoha_eth.c | 75 +++++++++++++++++++++++++++-----
> > drivers/net/ethernet/airoha/airoha_eth.h | 2 +-
> > drivers/net/ethernet/airoha/airoha_ppe.c | 4 +-
> > 3 files changed, 66 insertions(+), 15 deletions(-)
> >
> > diff --git a/drivers/net/ethernet/airoha/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c
> > index 16c0ff9999da..533ffe20f833 100644
> > --- a/drivers/net/ethernet/airoha/airoha_eth.c
> > +++ b/drivers/net/ethernet/airoha/airoha_eth.c
> > @@ -71,20 +71,67 @@ static void airoha_qdma_irq_disable(struct airoha_irq_bank *irq_bank,
> > airoha_qdma_set_irqmask(irq_bank, index, mask, 0);
> > }
> > -static void airoha_set_macaddr(struct airoha_gdm_dev *dev, const u8 *addr)
> > +static int airoha_set_macaddr(struct airoha_gdm_dev *dev, const u8 *addr)
> > {
> > struct airoha_eth *eth = dev->eth;
> > - u32 val, reg;
> > + u8 ref_addr[ETH_ALEN] = {};
> > + u32 reg, val, lmin, lmax;
> > + int i;
> > +
> > + lmin = (addr[3] << 16) | (addr[4] << 8) | addr[5];
> > + lmax = lmin;
> > +
> > + for (i = 0; i < ARRAY_SIZE(eth->ports); i++) {
> > + struct airoha_gdm_port *port = eth->ports[i];
> > + int j;
> > +
> > + if (!port)
> > + continue;
> > +
> > + for (j = 0; j < ARRAY_SIZE(port->devs); j++) {
> > + struct airoha_gdm_dev *iter_dev;
> > + struct net_device *netdev;
> > +
> > + iter_dev = port->devs[j];
> > + if (!iter_dev || iter_dev == dev)
> > + continue;
> > +
> > + if (airoha_is_lan_gdm_dev(iter_dev) !=
> > + airoha_is_lan_gdm_dev(dev))
> > + continue;
> > +
> > + netdev = iter_dev->dev;
> > + if (netdev->reg_state != NETREG_REGISTERED)
> > + continue;
> > +
> > + ether_addr_copy(ref_addr, netdev->dev_addr);
> > + val = (netdev->dev_addr[3] << 16) |
> > + (netdev->dev_addr[4] << 8) | netdev->dev_addr[5];
> > + if (val < lmin)
> > + lmin = val;
> > + if (val > lmax)
> > + lmax = val;
> > + }
> > + }
> > +
> > + if (!is_zero_ether_addr(ref_addr) && memcmp(ref_addr, addr, 3)) {
> > + /* According to the HW design, hw mac address MS bits
> > + * must be the same for each net_device with the same
> > + * LAN/WAN configuration.
> > + */
> > + return -EINVAL;
> > + }
>
> Maybe this information should be relayed to the user somehow?
netdev_err()?
Regards,
Lorenzo
>
> MvH
>
> Benjamin Larsson
>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply
* Re: [PATCH net-next v6 03/12] net: airoha: Introduce airoha_gdm_dev struct
From: Lorenzo Bianconi @ 2026-05-12 20:55 UTC (permalink / raw)
To: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: Christian Marangi, Benjamin Larsson, linux-arm-kernel,
linux-mediatek, netdev, devicetree, Xuegang Lu
In-Reply-To: <20260511-airoha-eth-multi-serdes-v6-3-c899462c4f75@kernel.org>
[-- Attachment #1: Type: text/plain, Size: 31080 bytes --]
On May 11, Lorenzo Bianconi wrote:
> EN7581 and AN7583 SoCs support connecting multiple external SerDes to GDM3
> or GDM4 ports via a hw arbiter that manages the traffic in a TDM manner.
> As a result multiple net_devices can connect to the same GDM{3,4} port
> and there is a theoretical "1:n" relation between GDM port and
> net_devices.
> Introduce airoha_gdm_dev struct to collect net_device related info (e.g.
> net_device and external phy pointer). Please note this is just a
> preliminary patch and we are still supporting a single net_device for
> each GDM port. Subsequent patches will add support for multiple net_devices
> connected to the same GDM port.
>
> Tested-by: Xuegang Lu <xuegang.lu@airoha.com>
> Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
> ---
> drivers/net/ethernet/airoha/airoha_eth.c | 309 ++++++++++++++++++-------------
> drivers/net/ethernet/airoha/airoha_eth.h | 13 +-
> drivers/net/ethernet/airoha/airoha_ppe.c | 17 +-
> 3 files changed, 203 insertions(+), 136 deletions(-)
>
> diff --git a/drivers/net/ethernet/airoha/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c
> index 3fe2561c85f1..18a89de4d58a 100644
> --- a/drivers/net/ethernet/airoha/airoha_eth.c
> +++ b/drivers/net/ethernet/airoha/airoha_eth.c
> @@ -600,6 +600,7 @@ static int airoha_qdma_rx_process(struct airoha_queue *q, int budget)
> struct airoha_qdma_desc *desc = &q->desc[q->tail];
> u32 hash, reason, msg1, desc_ctrl;
> struct airoha_gdm_port *port;
> + struct net_device *netdev;
> int data_len, len, p;
> struct page *page;
>
> @@ -628,6 +629,7 @@ static int airoha_qdma_rx_process(struct airoha_queue *q, int budget)
> goto free_frag;
>
> port = eth->ports[p];
> + netdev = port->dev->dev;
> if (!q->skb) { /* first buffer */
> q->skb = napi_build_skb(e->buf - AIROHA_RX_HEADROOM,
> q->buf_size);
> @@ -637,8 +639,8 @@ static int airoha_qdma_rx_process(struct airoha_queue *q, int budget)
> skb_reserve(q->skb, AIROHA_RX_HEADROOM);
> __skb_put(q->skb, len);
> skb_mark_for_recycle(q->skb);
> - q->skb->dev = port->dev;
> - q->skb->protocol = eth_type_trans(q->skb, port->dev);
> + q->skb->dev = netdev;
> + q->skb->protocol = eth_type_trans(q->skb, netdev);
> q->skb->ip_summed = CHECKSUM_UNNECESSARY;
> skb_record_rx_queue(q->skb, qid);
> } else { /* scattered frame */
> @@ -656,7 +658,7 @@ static int airoha_qdma_rx_process(struct airoha_queue *q, int budget)
> if (FIELD_GET(QDMA_DESC_MORE_MASK, desc_ctrl))
> continue;
>
> - if (netdev_uses_dsa(port->dev)) {
> + if (netdev_uses_dsa(netdev)) {
> /* PPE module requires untagged packets to work
> * properly and it provides DSA port index via the
> * DMA descriptor. Report DSA tag to the DSA stack
> @@ -850,6 +852,7 @@ static void airoha_qdma_wake_netdev_txqs(struct airoha_queue *q)
>
> for (i = 0; i < ARRAY_SIZE(eth->ports); i++) {
> struct airoha_gdm_port *port = eth->ports[i];
> + struct airoha_gdm_dev *dev;
> int j;
>
> if (!port)
> @@ -858,11 +861,12 @@ static void airoha_qdma_wake_netdev_txqs(struct airoha_queue *q)
> if (port->qdma != qdma)
> continue;
>
> - for (j = 0; j < port->dev->num_tx_queues; j++) {
> + dev = port->dev;
> + for (j = 0; j < dev->dev->num_tx_queues; j++) {
> if (airoha_qdma_get_txq(qdma, j) != qid)
> continue;
>
> - netif_wake_subqueue(port->dev, j);
> + netif_wake_subqueue(dev->dev, j);
> }
> }
> q->txq_stopped = false;
> @@ -1702,19 +1706,20 @@ static void airoha_update_hw_stats(struct airoha_gdm_port *port)
> spin_unlock(&port->stats.lock);
> }
>
> -static int airoha_dev_open(struct net_device *dev)
> +static int airoha_dev_open(struct net_device *netdev)
> {
> - int err, len = ETH_HLEN + dev->mtu + ETH_FCS_LEN;
> - struct airoha_gdm_port *port = netdev_priv(dev);
> + int err, len = ETH_HLEN + netdev->mtu + ETH_FCS_LEN;
> + struct airoha_gdm_dev *dev = netdev_priv(netdev);
> + struct airoha_gdm_port *port = dev->port;
> struct airoha_qdma *qdma = port->qdma;
> u32 pse_port = FE_PSE_PORT_PPE1;
>
> - netif_tx_start_all_queues(dev);
> + netif_tx_start_all_queues(netdev);
> err = airoha_set_vip_for_gdm_port(port, true);
> if (err)
> return err;
>
> - if (netdev_uses_dsa(dev))
> + if (netdev_uses_dsa(netdev))
> airoha_fe_set(qdma->eth, REG_GDM_INGRESS_CFG(port->id),
> GDM_STAG_EN_MASK);
> else
> @@ -1742,16 +1747,17 @@ static int airoha_dev_open(struct net_device *dev)
> return 0;
> }
>
> -static int airoha_dev_stop(struct net_device *dev)
> +static int airoha_dev_stop(struct net_device *netdev)
> {
> - struct airoha_gdm_port *port = netdev_priv(dev);
> + struct airoha_gdm_dev *dev = netdev_priv(netdev);
> + struct airoha_gdm_port *port = dev->port;
> struct airoha_qdma *qdma = port->qdma;
> int i;
>
> - netif_tx_disable(dev);
> + netif_tx_disable(netdev);
> airoha_set_vip_for_gdm_port(port, false);
> - for (i = 0; i < dev->num_tx_queues; i++)
> - netdev_tx_reset_subqueue(dev, i);
> + for (i = 0; i < netdev->num_tx_queues; 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);
> @@ -1772,16 +1778,17 @@ static int airoha_dev_stop(struct net_device *dev)
> return 0;
> }
>
> -static int airoha_dev_set_macaddr(struct net_device *dev, void *p)
> +static int airoha_dev_set_macaddr(struct net_device *netdev, void *p)
> {
> - struct airoha_gdm_port *port = netdev_priv(dev);
> + struct airoha_gdm_dev *dev = netdev_priv(netdev);
> + struct airoha_gdm_port *port = dev->port;
> int err;
>
> - err = eth_mac_addr(dev, p);
> + err = eth_mac_addr(netdev, p);
> if (err)
> return err;
>
> - airoha_set_macaddr(port, dev->dev_addr);
> + airoha_set_macaddr(port, netdev->dev_addr);
>
> return 0;
> }
> @@ -1845,16 +1852,17 @@ static int airoha_set_gdm2_loopback(struct airoha_gdm_port *port)
> return 0;
> }
>
> -static int airoha_dev_init(struct net_device *dev)
> +static int airoha_dev_init(struct net_device *netdev)
> {
> - struct airoha_gdm_port *port = netdev_priv(dev);
> - struct airoha_eth *eth = port->eth;
> + struct airoha_gdm_dev *dev = netdev_priv(netdev);
> + struct airoha_gdm_port *port = dev->port;
> + struct airoha_eth *eth = dev->eth;
> int i;
>
> /* QDMA0 is used for lan ports while QDMA1 is used for WAN ports */
> port->qdma = ð->qdma[!airoha_is_lan_gdm_port(port)];
> - port->dev->irq = port->qdma->irq_banks[0].irq;
> - airoha_set_macaddr(port, dev->dev_addr);
> + dev->dev->irq = port->qdma->irq_banks[0].irq;
> + airoha_set_macaddr(port, netdev->dev_addr);
>
> switch (port->id) {
> case AIROHA_GDM3_IDX:
> @@ -1879,10 +1887,11 @@ static int airoha_dev_init(struct net_device *dev)
> return 0;
> }
>
> -static void airoha_dev_get_stats64(struct net_device *dev,
> +static void airoha_dev_get_stats64(struct net_device *netdev,
> struct rtnl_link_stats64 *storage)
> {
> - struct airoha_gdm_port *port = netdev_priv(dev);
> + struct airoha_gdm_dev *dev = netdev_priv(netdev);
> + struct airoha_gdm_port *port = dev->port;
> unsigned int start;
>
> airoha_update_hw_stats(port);
> @@ -1901,36 +1910,39 @@ static void airoha_dev_get_stats64(struct net_device *dev,
> } while (u64_stats_fetch_retry(&port->stats.syncp, start));
> }
>
> -static int airoha_dev_change_mtu(struct net_device *dev, int mtu)
> +static int airoha_dev_change_mtu(struct net_device *netdev, int mtu)
> {
> - struct airoha_gdm_port *port = netdev_priv(dev);
> + struct airoha_gdm_dev *dev = netdev_priv(netdev);
> + struct airoha_gdm_port *port = dev->port;
> struct airoha_eth *eth = port->qdma->eth;
> u32 len = ETH_HLEN + mtu + ETH_FCS_LEN;
>
> airoha_fe_rmw(eth, REG_GDM_LEN_CFG(port->id),
> GDM_LONG_LEN_MASK,
> FIELD_PREP(GDM_LONG_LEN_MASK, len));
> - WRITE_ONCE(dev->mtu, mtu);
> + WRITE_ONCE(netdev->mtu, mtu);
>
> return 0;
> }
>
> -static u16 airoha_dev_select_queue(struct net_device *dev, struct sk_buff *skb,
> +static u16 airoha_dev_select_queue(struct net_device *netdev,
> + struct sk_buff *skb,
> struct net_device *sb_dev)
> {
> - struct airoha_gdm_port *port = netdev_priv(dev);
> + struct airoha_gdm_dev *dev = netdev_priv(netdev);
> + struct airoha_gdm_port *port = dev->port;
> int queue, channel;
>
> /* For dsa device select QoS channel according to the dsa user port
> * index, rely on port id otherwise. Select QoS queue based on the
> * skb priority.
> */
> - channel = netdev_uses_dsa(dev) ? skb_get_queue_mapping(skb) : port->id;
> + channel = netdev_uses_dsa(netdev) ? skb_get_queue_mapping(skb) : port->id;
> channel = channel % AIROHA_NUM_QOS_CHANNELS;
> queue = (skb->priority - 1) % AIROHA_NUM_QOS_QUEUES; /* QoS queue */
> queue = channel * AIROHA_NUM_QOS_QUEUES + queue;
>
> - return queue < dev->num_tx_queues ? queue : 0;
> + return queue < netdev->num_tx_queues ? queue : 0;
> }
>
> static u32 airoha_get_dsa_tag(struct sk_buff *skb, struct net_device *dev)
> @@ -1994,9 +2006,10 @@ int airoha_get_fe_port(struct airoha_gdm_port *port)
> }
>
> static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb,
> - struct net_device *dev)
> + struct net_device *netdev)
> {
> - struct airoha_gdm_port *port = netdev_priv(dev);
> + struct airoha_gdm_dev *dev = netdev_priv(netdev);
> + struct airoha_gdm_port *port = dev->port;
> struct airoha_qdma *qdma = port->qdma;
> u32 nr_frags, tag, msg0, msg1, len;
> struct airoha_queue_entry *e;
> @@ -2009,7 +2022,7 @@ static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb,
> u8 fport;
>
> qid = airoha_qdma_get_txq(qdma, skb_get_queue_mapping(skb));
> - tag = airoha_get_dsa_tag(skb, dev);
> + tag = airoha_get_dsa_tag(skb, netdev);
>
> msg0 = FIELD_PREP(QDMA_ETH_TXMSG_CHAN_MASK,
> qid / AIROHA_NUM_QOS_QUEUES) |
> @@ -2045,7 +2058,7 @@ static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb,
>
> spin_lock_bh(&q->lock);
>
> - txq = skb_get_tx_queue(dev, skb);
> + txq = skb_get_tx_queue(netdev, skb);
> nr_frags = 1 + skb_shinfo(skb)->nr_frags;
>
> if (q->queued + nr_frags >= q->ndesc) {
> @@ -2069,9 +2082,9 @@ static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb,
> dma_addr_t addr;
> u32 val;
>
> - addr = dma_map_single(dev->dev.parent, data, len,
> + addr = dma_map_single(netdev->dev.parent, data, len,
> DMA_TO_DEVICE);
> - if (unlikely(dma_mapping_error(dev->dev.parent, addr)))
> + if (unlikely(dma_mapping_error(netdev->dev.parent, addr)))
> goto error_unmap;
>
> list_move_tail(&e->list, &tx_list);
> @@ -2120,7 +2133,7 @@ static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb,
>
> error_unmap:
> list_for_each_entry(e, &tx_list, list) {
> - dma_unmap_single(dev->dev.parent, e->dma_addr, e->dma_len,
> + dma_unmap_single(netdev->dev.parent, e->dma_addr, e->dma_len,
> DMA_TO_DEVICE);
> e->dma_addr = 0;
> }
> @@ -2129,25 +2142,27 @@ static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb,
> spin_unlock_bh(&q->lock);
> error:
> dev_kfree_skb_any(skb);
> - dev->stats.tx_dropped++;
> + netdev->stats.tx_dropped++;
>
> return NETDEV_TX_OK;
> }
>
> -static void airoha_ethtool_get_drvinfo(struct net_device *dev,
> +static void airoha_ethtool_get_drvinfo(struct net_device *netdev,
> struct ethtool_drvinfo *info)
> {
> - struct airoha_gdm_port *port = netdev_priv(dev);
> + struct airoha_gdm_dev *dev = netdev_priv(netdev);
> + struct airoha_gdm_port *port = dev->port;
> struct airoha_eth *eth = port->qdma->eth;
>
> strscpy(info->driver, eth->dev->driver->name, sizeof(info->driver));
> strscpy(info->bus_info, dev_name(eth->dev), sizeof(info->bus_info));
> }
>
> -static void airoha_ethtool_get_mac_stats(struct net_device *dev,
> +static void airoha_ethtool_get_mac_stats(struct net_device *netdev,
> struct ethtool_eth_mac_stats *stats)
> {
> - struct airoha_gdm_port *port = netdev_priv(dev);
> + struct airoha_gdm_dev *dev = netdev_priv(netdev);
> + struct airoha_gdm_port *port = dev->port;
> unsigned int start;
>
> airoha_update_hw_stats(port);
> @@ -2175,11 +2190,12 @@ static const struct ethtool_rmon_hist_range airoha_ethtool_rmon_ranges[] = {
> };
>
> static void
> -airoha_ethtool_get_rmon_stats(struct net_device *dev,
> +airoha_ethtool_get_rmon_stats(struct net_device *netdev,
> struct ethtool_rmon_stats *stats,
> const struct ethtool_rmon_hist_range **ranges)
> {
> - struct airoha_gdm_port *port = netdev_priv(dev);
> + struct airoha_gdm_dev *dev = netdev_priv(netdev);
> + struct airoha_gdm_port *port = dev->port;
> struct airoha_hw_stats *hw_stats = &port->stats;
> unsigned int start;
>
> @@ -2204,11 +2220,12 @@ airoha_ethtool_get_rmon_stats(struct net_device *dev,
> } while (u64_stats_fetch_retry(&port->stats.syncp, start));
> }
>
> -static int airoha_qdma_set_chan_tx_sched(struct net_device *dev,
> +static int airoha_qdma_set_chan_tx_sched(struct net_device *netdev,
> int channel, enum tx_sched_mode mode,
> const u16 *weights, u8 n_weights)
> {
> - struct airoha_gdm_port *port = netdev_priv(dev);
> + struct airoha_gdm_dev *dev = netdev_priv(netdev);
> + struct airoha_gdm_port *port = dev->port;
> int i;
>
> for (i = 0; i < AIROHA_NUM_TX_RING; i++)
> @@ -2293,10 +2310,12 @@ static int airoha_qdma_set_tx_ets_sched(struct net_device *dev, int channel,
> ARRAY_SIZE(w));
> }
>
> -static int airoha_qdma_get_tx_ets_stats(struct net_device *dev, int channel,
> +static int airoha_qdma_get_tx_ets_stats(struct net_device *netdev, int channel,
> struct tc_ets_qopt_offload *opt)
> {
> - struct airoha_gdm_port *port = netdev_priv(dev);
> + struct airoha_gdm_dev *dev = netdev_priv(netdev);
> + struct airoha_gdm_port *port = dev->port;
> +
> u64 cpu_tx_packets = airoha_qdma_rr(port->qdma,
> REG_CNTR_VAL(channel << 1));
> u64 fwd_tx_packets = airoha_qdma_rr(port->qdma,
> @@ -2558,11 +2577,12 @@ static int airoha_qdma_set_trtcm_token_bucket(struct airoha_qdma *qdma,
> mode, val);
> }
>
> -static int airoha_qdma_set_tx_rate_limit(struct net_device *dev,
> +static int airoha_qdma_set_tx_rate_limit(struct net_device *netdev,
> int channel, u32 rate,
> u32 bucket_size)
> {
> - struct airoha_gdm_port *port = netdev_priv(dev);
> + struct airoha_gdm_dev *dev = netdev_priv(netdev);
> + struct airoha_gdm_port *port = dev->port;
> int i, err;
>
> for (i = 0; i <= TRTCM_PEAK_MODE; i++) {
> @@ -2582,20 +2602,22 @@ static int airoha_qdma_set_tx_rate_limit(struct net_device *dev,
> return 0;
> }
>
> -static int airoha_tc_htb_alloc_leaf_queue(struct net_device *dev,
> +static int airoha_tc_htb_alloc_leaf_queue(struct net_device *netdev,
> struct tc_htb_qopt_offload *opt)
> {
> u32 channel = TC_H_MIN(opt->classid) % AIROHA_NUM_QOS_CHANNELS;
> u32 rate = div_u64(opt->rate, 1000) << 3; /* kbps */
> - int err, num_tx_queues = dev->real_num_tx_queues;
> - struct airoha_gdm_port *port = netdev_priv(dev);
> + int err, num_tx_queues = netdev->real_num_tx_queues;
> + struct airoha_gdm_dev *dev = netdev_priv(netdev);
> + struct airoha_gdm_port *port = dev->port;
>
> if (opt->parent_classid != TC_HTB_CLASSID_ROOT) {
> NL_SET_ERR_MSG_MOD(opt->extack, "invalid parent classid");
> return -EINVAL;
> }
>
> - err = airoha_qdma_set_tx_rate_limit(dev, channel, rate, opt->quantum);
> + err = airoha_qdma_set_tx_rate_limit(netdev, channel, rate,
> + opt->quantum);
> if (err) {
> NL_SET_ERR_MSG_MOD(opt->extack,
> "failed configuring htb offload");
> @@ -2605,9 +2627,10 @@ static int airoha_tc_htb_alloc_leaf_queue(struct net_device *dev,
> if (opt->command == TC_HTB_NODE_MODIFY)
> return 0;
>
> - err = netif_set_real_num_tx_queues(dev, num_tx_queues + 1);
> + err = netif_set_real_num_tx_queues(netdev, num_tx_queues + 1);
> if (err) {
> - airoha_qdma_set_tx_rate_limit(dev, channel, 0, opt->quantum);
> + airoha_qdma_set_tx_rate_limit(netdev, channel, 0,
> + opt->quantum);
> NL_SET_ERR_MSG_MOD(opt->extack,
> "failed setting real_num_tx_queues");
> return err;
> @@ -2697,11 +2720,12 @@ static int airoha_tc_matchall_act_validate(struct tc_cls_matchall_offload *f)
> return 0;
> }
>
> -static int airoha_dev_tc_matchall(struct net_device *dev,
> +static int airoha_dev_tc_matchall(struct net_device *netdev,
> struct tc_cls_matchall_offload *f)
> {
> enum trtcm_unit_type unit_type = TRTCM_BYTE_UNIT;
> - struct airoha_gdm_port *port = netdev_priv(dev);
> + struct airoha_gdm_dev *dev = netdev_priv(netdev);
> + struct airoha_gdm_port *port = dev->port;
> u32 rate = 0, bucket_size = 0;
>
> switch (f->command) {
> @@ -2736,18 +2760,19 @@ static int airoha_dev_tc_matchall(struct net_device *dev,
> static int airoha_dev_setup_tc_block_cb(enum tc_setup_type type,
> void *type_data, void *cb_priv)
> {
> - struct net_device *dev = cb_priv;
> - struct airoha_gdm_port *port = netdev_priv(dev);
> + struct net_device *netdev = cb_priv;
> + struct airoha_gdm_dev *dev = netdev_priv(netdev);
> + struct airoha_gdm_port *port = dev->port;
> struct airoha_eth *eth = port->qdma->eth;
>
> - if (!tc_can_offload(dev))
> + if (!tc_can_offload(netdev))
> return -EOPNOTSUPP;
>
> switch (type) {
> case TC_SETUP_CLSFLOWER:
> return airoha_ppe_setup_tc_block_cb(ð->ppe->dev, type_data);
> case TC_SETUP_CLSMATCHALL:
> - return airoha_dev_tc_matchall(dev, type_data);
> + return airoha_dev_tc_matchall(netdev, type_data);
> default:
> return -EOPNOTSUPP;
> }
> @@ -2794,47 +2819,51 @@ static int airoha_dev_setup_tc_block(struct net_device *dev,
> }
> }
>
> -static void airoha_tc_remove_htb_queue(struct net_device *dev, int queue)
> +static void airoha_tc_remove_htb_queue(struct net_device *netdev, int queue)
> {
> - struct airoha_gdm_port *port = netdev_priv(dev);
> + struct airoha_gdm_dev *dev = netdev_priv(netdev);
> + struct airoha_gdm_port *port = dev->port;
>
> - netif_set_real_num_tx_queues(dev, dev->real_num_tx_queues - 1);
> - airoha_qdma_set_tx_rate_limit(dev, queue + 1, 0, 0);
> + netif_set_real_num_tx_queues(netdev, netdev->real_num_tx_queues - 1);
> + airoha_qdma_set_tx_rate_limit(netdev, queue + 1, 0, 0);
> clear_bit(queue, port->qos_sq_bmap);
> }
>
> -static int airoha_tc_htb_delete_leaf_queue(struct net_device *dev,
> +static int airoha_tc_htb_delete_leaf_queue(struct net_device *netdev,
> struct tc_htb_qopt_offload *opt)
> {
> u32 channel = TC_H_MIN(opt->classid) % AIROHA_NUM_QOS_CHANNELS;
> - struct airoha_gdm_port *port = netdev_priv(dev);
> + struct airoha_gdm_dev *dev = netdev_priv(netdev);
> + struct airoha_gdm_port *port = dev->port;
>
> if (!test_bit(channel, port->qos_sq_bmap)) {
> NL_SET_ERR_MSG_MOD(opt->extack, "invalid queue id");
> return -EINVAL;
> }
>
> - airoha_tc_remove_htb_queue(dev, channel);
> + airoha_tc_remove_htb_queue(netdev, channel);
>
> return 0;
> }
>
> -static int airoha_tc_htb_destroy(struct net_device *dev)
> +static int airoha_tc_htb_destroy(struct net_device *netdev)
> {
> - struct airoha_gdm_port *port = netdev_priv(dev);
> + struct airoha_gdm_dev *dev = netdev_priv(netdev);
> + struct airoha_gdm_port *port = dev->port;
> int q;
>
> for_each_set_bit(q, port->qos_sq_bmap, AIROHA_NUM_QOS_CHANNELS)
> - airoha_tc_remove_htb_queue(dev, q);
> + airoha_tc_remove_htb_queue(netdev, q);
>
> return 0;
> }
>
> -static int airoha_tc_get_htb_get_leaf_queue(struct net_device *dev,
> +static int airoha_tc_get_htb_get_leaf_queue(struct net_device *netdev,
> struct tc_htb_qopt_offload *opt)
> {
> u32 channel = TC_H_MIN(opt->classid) % AIROHA_NUM_QOS_CHANNELS;
> - struct airoha_gdm_port *port = netdev_priv(dev);
> + struct airoha_gdm_dev *dev = netdev_priv(netdev);
> + struct airoha_gdm_port *port = dev->port;
>
> if (!test_bit(channel, port->qos_sq_bmap)) {
> NL_SET_ERR_MSG_MOD(opt->extack, "invalid queue id");
> @@ -2870,8 +2899,8 @@ static int airoha_tc_setup_qdisc_htb(struct net_device *dev,
> return 0;
> }
>
> -static int airoha_dev_tc_setup(struct net_device *dev, enum tc_setup_type type,
> - void *type_data)
> +static int airoha_dev_tc_setup(struct net_device *dev,
> + enum tc_setup_type type, void *type_data)
> {
> switch (type) {
> case TC_SETUP_QDISC_ETS:
> @@ -2937,25 +2966,81 @@ static void airoha_metadata_dst_free(struct airoha_gdm_port *port)
> }
> }
>
> -bool airoha_is_valid_gdm_port(struct airoha_eth *eth,
> - struct airoha_gdm_port *port)
> +bool airoha_is_valid_gdm_dev(struct airoha_eth *eth,
> + struct airoha_gdm_dev *dev)
> {
> int i;
>
> for (i = 0; i < ARRAY_SIZE(eth->ports); i++) {
> - if (eth->ports[i] == port)
> + struct airoha_gdm_port *port = eth->ports[i];
> +
> + if (!port)
> + continue;
> +
> + if (port->dev == dev)
> return true;
> }
>
> return false;
> }
>
> +static int airoha_alloc_gdm_device(struct airoha_eth *eth,
> + struct airoha_gdm_port *port,
> + struct device_node *np)
> +{
> + struct airoha_gdm_dev *dev;
> + struct net_device *netdev;
> + int err;
> +
> + netdev = devm_alloc_etherdev_mqs(eth->dev, sizeof(*dev),
> + AIROHA_NUM_NETDEV_TX_RINGS,
> + AIROHA_NUM_RX_RING);
> + if (!netdev) {
> + dev_err(eth->dev, "alloc_etherdev failed\n");
> + return -ENOMEM;
> + }
> +
> + netdev->netdev_ops = &airoha_netdev_ops;
> + netdev->ethtool_ops = &airoha_ethtool_ops;
> + netdev->max_mtu = AIROHA_MAX_MTU;
> + netdev->watchdog_timeo = 5 * HZ;
> + netdev->hw_features = NETIF_F_IP_CSUM | NETIF_F_RXCSUM | NETIF_F_TSO6 |
> + NETIF_F_IPV6_CSUM | NETIF_F_SG | NETIF_F_TSO |
> + NETIF_F_HW_TC;
> + netdev->features |= netdev->hw_features;
> + netdev->vlan_features = netdev->hw_features;
> + netdev->dev.of_node = np;
> + SET_NETDEV_DEV(netdev, eth->dev);
> +
> + /* reserve hw queues for HTB offloading */
> + err = netif_set_real_num_tx_queues(netdev, AIROHA_NUM_TX_RING);
> + if (err)
> + return err;
> +
> + err = of_get_ethdev_address(np, netdev);
> + if (err) {
> + if (err == -EPROBE_DEFER)
> + return err;
> +
> + eth_hw_addr_random(netdev);
> + dev_info(eth->dev, "generated random MAC address %pM\n",
> + netdev->dev_addr);
> + }
> +
> + dev = netdev_priv(netdev);
> + dev->dev = netdev;
> + dev->port = port;
> + port->dev = dev;
> + dev->eth = eth;
> +
> + return 0;
> +}
> +
> static int airoha_alloc_gdm_port(struct airoha_eth *eth,
> struct device_node *np)
> {
> const __be32 *id_ptr = of_get_property(np, "reg", NULL);
> struct airoha_gdm_port *port;
> - struct net_device *dev;
> int err, p;
> u32 id;
>
> @@ -2977,53 +3062,22 @@ static int airoha_alloc_gdm_port(struct airoha_eth *eth,
> return -EINVAL;
> }
>
> - dev = devm_alloc_etherdev_mqs(eth->dev, sizeof(*port),
> - AIROHA_NUM_NETDEV_TX_RINGS,
> - AIROHA_NUM_RX_RING);
> - if (!dev) {
> - dev_err(eth->dev, "alloc_etherdev failed\n");
> + port = devm_kzalloc(eth->dev, sizeof(*port), GFP_KERNEL);
> + if (!port)
> return -ENOMEM;
> - }
> -
> - dev->netdev_ops = &airoha_netdev_ops;
> - dev->ethtool_ops = &airoha_ethtool_ops;
> - dev->max_mtu = AIROHA_MAX_MTU;
> - dev->watchdog_timeo = 5 * HZ;
> - dev->hw_features = NETIF_F_IP_CSUM | NETIF_F_RXCSUM |
> - NETIF_F_TSO6 | NETIF_F_IPV6_CSUM |
> - NETIF_F_SG | NETIF_F_TSO |
> - NETIF_F_HW_TC;
> - dev->features |= dev->hw_features;
> - dev->vlan_features = dev->hw_features;
> - dev->dev.of_node = np;
> - SET_NETDEV_DEV(dev, eth->dev);
> -
> - /* reserve hw queues for HTB offloading */
> - err = netif_set_real_num_tx_queues(dev, AIROHA_NUM_TX_RING);
> - if (err)
> - return err;
> -
> - err = of_get_ethdev_address(np, dev);
> - if (err) {
> - if (err == -EPROBE_DEFER)
> - return err;
> -
> - eth_hw_addr_random(dev);
> - dev_info(eth->dev, "generated random MAC address %pM\n",
> - dev->dev_addr);
> - }
>
> - port = netdev_priv(dev);
> u64_stats_init(&port->stats.syncp);
> spin_lock_init(&port->stats.lock);
> - port->eth = eth;
> - port->dev = dev;
> port->id = id;
> /* XXX: Read nbq from DTS */
> port->nbq = id == AIROHA_GDM3_IDX && airoha_is_7581(eth) ? 4 : 0;
> eth->ports[p] = port;
>
> - return airoha_metadata_dst_alloc(port);
> + err = airoha_metadata_dst_alloc(port);
> + if (err)
> + return err;
> +
> + return airoha_alloc_gdm_device(eth, port, np);
> }
>
> static int airoha_register_gdm_devices(struct airoha_eth *eth)
> @@ -3037,7 +3091,7 @@ static int airoha_register_gdm_devices(struct airoha_eth *eth)
> if (!port)
> continue;
>
> - err = register_netdev(port->dev);
> + err = register_netdev(port->dev->dev);
> if (err)
> return err;
> }
> @@ -3146,12 +3200,14 @@ static int airoha_probe(struct platform_device *pdev)
>
> for (i = 0; i < ARRAY_SIZE(eth->ports); i++) {
> struct airoha_gdm_port *port = eth->ports[i];
> + struct airoha_gdm_dev *dev;
>
> if (!port)
> continue;
>
> - if (port->dev->reg_state == NETREG_REGISTERED)
> - unregister_netdev(port->dev);
> + dev = port->dev;
> + if (dev && dev->dev->reg_state == NETREG_REGISTERED)
> + unregister_netdev(dev->dev);
> airoha_metadata_dst_free(port);
> }
> airoha_hw_cleanup(eth);
> @@ -3172,11 +3228,14 @@ static void airoha_remove(struct platform_device *pdev)
>
> for (i = 0; i < ARRAY_SIZE(eth->ports); i++) {
> struct airoha_gdm_port *port = eth->ports[i];
> + struct airoha_gdm_dev *dev;
>
> if (!port)
> continue;
>
> - unregister_netdev(port->dev);
> + dev = port->dev;
> + if (dev)
> + unregister_netdev(dev->dev);
> airoha_metadata_dst_free(port);
> }
> airoha_hw_cleanup(eth);
> diff --git a/drivers/net/ethernet/airoha/airoha_eth.h b/drivers/net/ethernet/airoha/airoha_eth.h
> index d3781103abb5..c78cabbec753 100644
> --- a/drivers/net/ethernet/airoha/airoha_eth.h
> +++ b/drivers/net/ethernet/airoha/airoha_eth.h
> @@ -535,10 +535,15 @@ struct airoha_qdma {
> struct airoha_queue q_rx[AIROHA_NUM_RX_RING];
> };
>
> +struct airoha_gdm_dev {
> + struct airoha_gdm_port *port;
> + struct net_device *dev;
> + struct airoha_eth *eth;
> +};
> +
> struct airoha_gdm_port {
> struct airoha_qdma *qdma;
> - struct airoha_eth *eth;
> - struct net_device *dev;
> + struct airoha_gdm_dev *dev;
> int id;
> int nbq;
>
> @@ -662,8 +667,8 @@ static inline bool airoha_is_7583(struct airoha_eth *eth)
> }
>
> int airoha_get_fe_port(struct airoha_gdm_port *port);
> -bool airoha_is_valid_gdm_port(struct airoha_eth *eth,
> - struct airoha_gdm_port *port);
> +bool airoha_is_valid_gdm_dev(struct airoha_eth *eth,
> + struct airoha_gdm_dev *dev);
>
> void airoha_ppe_set_cpu_port(struct airoha_gdm_port *port, u8 ppe_id,
> u8 fport);
> diff --git a/drivers/net/ethernet/airoha/airoha_ppe.c b/drivers/net/ethernet/airoha/airoha_ppe.c
> index 26da519236bf..af7af4097b98 100644
> --- a/drivers/net/ethernet/airoha/airoha_ppe.c
> +++ b/drivers/net/ethernet/airoha/airoha_ppe.c
> @@ -298,12 +298,12 @@ static void airoha_ppe_foe_set_bridge_addrs(struct airoha_foe_bridge *br,
>
> static int airoha_ppe_foe_entry_prepare(struct airoha_eth *eth,
> struct airoha_foe_entry *hwe,
> - struct net_device *dev, int type,
> + struct net_device *netdev, int type,
> struct airoha_flow_data *data,
> int l4proto)
> {
> u32 qdata = FIELD_PREP(AIROHA_FOE_SHAPER_ID, 0x7f), ports_pad, val;
> - int wlan_etype = -EINVAL, dsa_port = airoha_get_dsa_port(&dev);
> + int wlan_etype = -EINVAL, dsa_port = airoha_get_dsa_port(&netdev);
> struct airoha_foe_mac_info_common *l2;
> u8 smac_id = 0xf;
>
> @@ -319,10 +319,11 @@ static int airoha_ppe_foe_entry_prepare(struct airoha_eth *eth,
> hwe->ib1 = val;
>
> val = FIELD_PREP(AIROHA_FOE_IB2_PORT_AG, 0x1f);
> - if (dev) {
> + if (netdev) {
> struct airoha_wdma_info info = {};
>
> - if (!airoha_ppe_get_wdma_info(dev, data->eth.h_dest, &info)) {
> + if (!airoha_ppe_get_wdma_info(netdev, data->eth.h_dest,
> + &info)) {
> val |= FIELD_PREP(AIROHA_FOE_IB2_NBQ, info.idx) |
> FIELD_PREP(AIROHA_FOE_IB2_PSE_PORT,
> FE_PSE_PORT_CDM4);
> @@ -332,12 +333,14 @@ static int airoha_ppe_foe_entry_prepare(struct airoha_eth *eth,
> FIELD_PREP(AIROHA_FOE_MAC_WDMA_WCID,
> info.wcid);
> } else {
> - struct airoha_gdm_port *port = netdev_priv(dev);
> + struct airoha_gdm_dev *dev = netdev_priv(netdev);
> + struct airoha_gdm_port *port;
> u8 pse_port, channel;
>
> - if (!airoha_is_valid_gdm_port(eth, port))
> + if (!airoha_is_valid_gdm_dev(eth, dev))
> return -EINVAL;
>
> + port = dev->port;
> if (dsa_port >= 0 || eth->ports[1])
> pse_port = port->id == 4 ? FE_PSE_PORT_GDM4
> : port->id;
> @@ -1473,7 +1476,7 @@ void airoha_ppe_check_skb(struct airoha_ppe_dev *dev, struct sk_buff *skb,
> void airoha_ppe_init_upd_mem(struct airoha_gdm_port *port)
> {
> struct airoha_eth *eth = port->qdma->eth;
> - struct net_device *dev = port->dev;
> + struct net_device *dev = port->dev->dev;
> const u8 *addr = dev->dev_addr;
> u32 val;
>
>
> --
> 2.54.0
>
Commenting on sashiko's report:
https://sashiko.dev/#/patchset/20260511-airoha-eth-multi-serdes-v6-0-c899462c4f75%40kernel.org
- This problem wasn't introduced by this patch, but does this function call lead
to out-of-bounds memory accesses?
- I do not think this is an issue, since airoha_eth driver supports just mtk as
dsa driver where we actually skb_push() MTK_HDR_LEN bytes in mtk_tag_xmit().
- This problem wasn't introduced by this patch, but does this incorrect bounds
accounting in HTB offload break QoS?
- I will fix this issue with a dedicated patch.
- This problem wasn't introduced by this patch, but does this leave the rate
limit active due to an off-by-one error?
- I will fix this issue with a dedicated patch.
- This problem wasn't introduced by this patch, but does this lead to a
use-after-free of the device tree node?
- This is fixed by a subsequent patch in the series.
Regards,
Lorenzo
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply
* Re: [PATCH net-next v6 02/12] net: airoha: Reserve RX headroom to avoid skb reallocation
From: Lorenzo Bianconi @ 2026-05-12 20:31 UTC (permalink / raw)
To: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: Christian Marangi, Benjamin Larsson, linux-arm-kernel,
linux-mediatek, netdev, devicetree, Xuegang Lu
In-Reply-To: <20260511-airoha-eth-multi-serdes-v6-2-c899462c4f75@kernel.org>
[-- Attachment #1: Type: text/plain, Size: 3105 bytes --]
On May 11, Lorenzo Bianconi wrote:
> Reserve NET_SKB_PAD + NET_IP_ALIGN bytes of headroom for received packets
> to avoid skb head reallocation when pushing protocol headers into the skb.
>
> Tested-by: Xuegang Lu <xuegang.lu@airoha.com>
> Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
> ---
> drivers/net/ethernet/airoha/airoha_eth.c | 12 ++++++++----
> drivers/net/ethernet/airoha/airoha_eth.h | 2 ++
> 2 files changed, 10 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/net/ethernet/airoha/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c
> index f71fb18197ec..3fe2561c85f1 100644
> --- a/drivers/net/ethernet/airoha/airoha_eth.c
> +++ b/drivers/net/ethernet/airoha/airoha_eth.c
> @@ -543,9 +543,10 @@ static int airoha_qdma_fill_rx_queue(struct airoha_queue *q)
> q->queued++;
> nframes++;
>
> + offset += AIROHA_RX_HEADROOM;
> e->buf = page_address(page) + offset;
> e->dma_addr = page_pool_get_dma_addr(page) + offset;
> - e->dma_len = SKB_WITH_OVERHEAD(q->buf_size);
> + e->dma_len = SKB_WITH_OVERHEAD(AIROHA_RX_LEN(q->buf_size));
>
> val = FIELD_PREP(QDMA_DESC_LEN_MASK, e->dma_len);
> WRITE_ONCE(desc->ctrl, cpu_to_le32(val));
> @@ -616,8 +617,9 @@ static int airoha_qdma_rx_process(struct airoha_queue *q, int budget)
>
> page = virt_to_head_page(e->buf);
> len = FIELD_GET(QDMA_DESC_LEN_MASK, desc_ctrl);
> - data_len = q->skb ? q->buf_size
> - : SKB_WITH_OVERHEAD(q->buf_size);
> + data_len = q->skb
> + ? AIROHA_RX_LEN(q->buf_size)
> + : SKB_WITH_OVERHEAD(AIROHA_RX_LEN(q->buf_size));
> if (!len || data_len < len)
> goto free_frag;
>
> @@ -627,10 +629,12 @@ static int airoha_qdma_rx_process(struct airoha_queue *q, int budget)
>
> port = eth->ports[p];
> if (!q->skb) { /* first buffer */
> - q->skb = napi_build_skb(e->buf, q->buf_size);
> + q->skb = napi_build_skb(e->buf - AIROHA_RX_HEADROOM,
> + q->buf_size);
> if (!q->skb)
> goto free_frag;
>
> + skb_reserve(q->skb, AIROHA_RX_HEADROOM);
> __skb_put(q->skb, len);
> skb_mark_for_recycle(q->skb);
> q->skb->dev = port->dev;
> diff --git a/drivers/net/ethernet/airoha/airoha_eth.h b/drivers/net/ethernet/airoha/airoha_eth.h
> index 58530d096de7..d3781103abb5 100644
> --- a/drivers/net/ethernet/airoha/airoha_eth.h
> +++ b/drivers/net/ethernet/airoha/airoha_eth.h
> @@ -32,6 +32,8 @@
> #define AIROHA_FE_MC_MAX_VLAN_TABLE 64
> #define AIROHA_FE_MC_MAX_VLAN_PORT 16
> #define AIROHA_NUM_TX_IRQ 2
> +#define AIROHA_RX_HEADROOM (NET_SKB_PAD + NET_IP_ALIGN)
> +#define AIROHA_RX_LEN(_n) ((_n) - AIROHA_RX_HEADROOM)
> #define HW_DSCP_NUM 2048
> #define IRQ_QUEUE_LEN(_n) ((_n) ? 1024 : 2048)
> #define TX_DSCP_NUM 1024
>
> --
> 2.54.0
>
commenting on sashiko's report:
https://sashiko.dev/#/patchset/20260511-airoha-eth-multi-serdes-v6-0-c899462c4f75%40kernel.org
- Does the length passed to dma_sync_single_for_cpu() also need to be updated
to match the new DMA length?
I will fix it in v7.
Regards,
Lorenzo
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply
* Re: [PATCH net-next v6 11/12] net: airoha: Support multiple LAN/WAN interfaces for hw MAC address configuration
From: Benjamin Larsson @ 2026-05-12 17:49 UTC (permalink / raw)
To: Lorenzo Bianconi, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Rob Herring, Krzysztof Kozlowski,
Conor Dooley
Cc: Christian Marangi, linux-arm-kernel, linux-mediatek, netdev,
devicetree, Madhur Agrawal
In-Reply-To: <20260511-airoha-eth-multi-serdes-v6-11-c899462c4f75@kernel.org>
Hi.
On 11/05/2026 12:49, Lorenzo Bianconi wrote:
> The EN7581 and AN7583 SoCs provide registers to configure hardware LAN/WAN
> MAC addresses, used to determine whether received traffic is destined for
> this host or should be forwarded to another device.
> The SoC hardware design assumes all interfaces configured as LAN (or WAN)
> share a common upper MAC address, which is programmed into the
> REG_FE_{LAN,WAN}_MAC_H register. The lower bytes of 'local' addresses can
> be expressed as a range via the REG_FE_MAC_LMIN and REG_FE_MAC_LMAX
> registers.
> Previously, only a single interface was considered when programming these
> registers. Extend the logic to derive the correct minimum and maximum
> values for REG_FE_MAC_LMIN/REG_FE_MAC_LMAX when two or more interfaces are
> configured as LAN or WAN.
>
> Tested-by: Madhur Agrawal <madhur.agrawal@airoha.com>
> Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
> ---
> drivers/net/ethernet/airoha/airoha_eth.c | 75 +++++++++++++++++++++++++++-----
> drivers/net/ethernet/airoha/airoha_eth.h | 2 +-
> drivers/net/ethernet/airoha/airoha_ppe.c | 4 +-
> 3 files changed, 66 insertions(+), 15 deletions(-)
>
> diff --git a/drivers/net/ethernet/airoha/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c
> index 16c0ff9999da..533ffe20f833 100644
> --- a/drivers/net/ethernet/airoha/airoha_eth.c
> +++ b/drivers/net/ethernet/airoha/airoha_eth.c
> @@ -71,20 +71,67 @@ static void airoha_qdma_irq_disable(struct airoha_irq_bank *irq_bank,
> airoha_qdma_set_irqmask(irq_bank, index, mask, 0);
> }
>
> -static void airoha_set_macaddr(struct airoha_gdm_dev *dev, const u8 *addr)
> +static int airoha_set_macaddr(struct airoha_gdm_dev *dev, const u8 *addr)
> {
> struct airoha_eth *eth = dev->eth;
> - u32 val, reg;
> + u8 ref_addr[ETH_ALEN] = {};
> + u32 reg, val, lmin, lmax;
> + int i;
> +
> + lmin = (addr[3] << 16) | (addr[4] << 8) | addr[5];
> + lmax = lmin;
> +
> + for (i = 0; i < ARRAY_SIZE(eth->ports); i++) {
> + struct airoha_gdm_port *port = eth->ports[i];
> + int j;
> +
> + if (!port)
> + continue;
> +
> + for (j = 0; j < ARRAY_SIZE(port->devs); j++) {
> + struct airoha_gdm_dev *iter_dev;
> + struct net_device *netdev;
> +
> + iter_dev = port->devs[j];
> + if (!iter_dev || iter_dev == dev)
> + continue;
> +
> + if (airoha_is_lan_gdm_dev(iter_dev) !=
> + airoha_is_lan_gdm_dev(dev))
> + continue;
> +
> + netdev = iter_dev->dev;
> + if (netdev->reg_state != NETREG_REGISTERED)
> + continue;
> +
> + ether_addr_copy(ref_addr, netdev->dev_addr);
> + val = (netdev->dev_addr[3] << 16) |
> + (netdev->dev_addr[4] << 8) | netdev->dev_addr[5];
> + if (val < lmin)
> + lmin = val;
> + if (val > lmax)
> + lmax = val;
> + }
> + }
> +
> + if (!is_zero_ether_addr(ref_addr) && memcmp(ref_addr, addr, 3)) {
> + /* According to the HW design, hw mac address MS bits
> + * must be the same for each net_device with the same
> + * LAN/WAN configuration.
> + */
> + return -EINVAL;
> + }
Maybe this information should be relayed to the user somehow?
MvH
Benjamin Larsson
^ permalink raw reply
* Re: [PATCH v2 01/16] dt-bindings: iio: adc: mt6359: generalize description for mt63xx series
From: Jonathan Cameron @ 2026-05-12 17:06 UTC (permalink / raw)
To: Roman Vivchar
Cc: David Lechner, Nuno Sá, Andy Shevchenko, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
AngeloGioacchino Del Regno, Sen Chu, Sean Wang, Macpaul Lin,
Lee Jones, Srinivas Kandagatla, Rafael J. Wysocki, Daniel Lezcano,
Zhang Rui, Lukasz Luba, linux-iio, devicetree, linux-kernel,
linux-arm-kernel, linux-mediatek, linux-pm, Ben Grisdale
In-Reply-To: <wTd36596tJhd0sPk-1MSi79xz14IBgTKXpD25tnKuRXLfGywkoenZ-wIDtOvRxEZL8xpqijZ0nxMsCFTOJgJq__y26VzCpe_9f0JQGWrJVo=@protonmail.com>
On Tue, 12 May 2026 13:55:26 +0000
Roman Vivchar <rva333@protonmail.com> wrote:
> On Tuesday, May 12th, 2026 at 4:13 PM, Jonathan Cameron <jic23@kernel.org> wrote:
>
> > On Tue, 12 May 2026 08:18:15 +0300
> > Roman Vivchar via B4 Relay <devnull+rva333.protonmail.com@kernel.org> wrote:
> >
> > > From: Roman Vivchar <rva333@protonmail.com>
> > >
> > > Update binding title to the MT63xx, since the list of compatibles already
> > > includes mt6363 and mt6373 which don't belong to the mt6350 family.
> > Hi Roman,
> >
> > Wild cards have a nasty habit of going wrong. I'd prefer to see
> > language like: MT6359 and similar PMIC AUXADC
>
> Hi Jonathan,
>
> I agree that it would be better to specify the exact PMIC models, however
> 'similar' wording might be a bit misleading here. As far as I know,
> the mt6363 and mt6373 use SPMI, while mt635x (and older models, like
> most of the mt63xx series) use PWRAP (a custom SPI-based protocol).
> The mt6323 has an older AUXADC revision which is not compatible
> with the mt635x driver.
>
> Would you prefer more explicit list like 'MT6323, MT6350 series, MT6363
> and MT6373 PMIC AUXADC'? It's a bit mess because some mt63xx
> (like mt6333) are sub-PMICs and use I2C instead of PWRAP.
Complete lists don't work because sooner or later they become too long
for a title (though they should be there elsewhere in the dt-binding!)
Perhaps something around: mt6359 and similar SoC ADCs including those accessed via ....
>
> > It is less important here than in many other places because the
> > file has an explicit list soon after this, but none the less
> > we've been bitten by this too often to think manufacturers won't
> > throw a completely non compatible part in the middle of a wild
> > card covered range.
> >
>
> Best regards,
> Roman
^ permalink raw reply
* Re: [PATCH v2 05/16] iio: adc: mediatek: add mt6323 PMIC AUXADC driver
From: Jonathan Cameron @ 2026-05-12 17:04 UTC (permalink / raw)
To: Roman Vivchar
Cc: Andy Shevchenko, David Lechner, Nuno Sá, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
AngeloGioacchino Del Regno, Sen Chu, Sean Wang, Macpaul Lin,
Lee Jones, Srinivas Kandagatla, Rafael J. Wysocki, Daniel Lezcano,
Zhang Rui, Lukasz Luba, linux-iio, devicetree, linux-kernel,
linux-arm-kernel, linux-mediatek, linux-pm, Ben Grisdale
In-Reply-To: <gWxamwTKyUeOF4QCsiIsrnh7DSWzIKFaY0h83qKq_0vg786xv1uFYhypix7BVO_ruG_vw3DrIsRhIKv5NAzl8hK72rjzPAjwAGU-rhkMgeA=@protonmail.com>
On Tue, 12 May 2026 14:34:55 +0000
Roman Vivchar <rva333@protonmail.com> wrote:
> On Tuesday, May 12th, 2026 at 4:29 PM, Jonathan Cameron <jic23@kernel.org> wrote:
>
> > On Tue, 12 May 2026 08:18:19 +0300
> > Roman Vivchar via B4 Relay <devnull+rva333.protonmail.com@kernel.org> wrote:
>
> ...
>
> > > +#define VOLTAGE_FULL_RANGE 1800
> > Probably better to have this inline - however if you do keep it
> > prefix t he define VOLTAGE_FULL_RANGE sounds too generic!
> >
> > > +#define AUXADC_PRECISE 32768
> > I'd put that inline. Little benefit it in having it up here...
>
> There was a mention about magic values in the v1 for the thermal patch [1].
> Andy, would it be better to use an inline style or a #define here?
> If the former, I'll rename the first constant to something like
> AUXADC_VOLTAGE_FULL_RANGE.
FWIW that isn't a magic value - it's 2**resolution and the one is a voltage
in mV. Those aren't normally the ones people care about defines for - those
apply when they are weird and wonderful things not related directly to physical
quantities.
Jonathan
>
> [1]: https://lore.kernel.org/linux-mediatek/afmnUG8dG0N0HpV6@ashevche-desk.local/
>
> Best regards,
> Roman
^ permalink raw reply
* Re: [PATCH v2 05/16] iio: adc: mediatek: add mt6323 PMIC AUXADC driver
From: Andy Shevchenko @ 2026-05-12 16:56 UTC (permalink / raw)
To: Roman Vivchar
Cc: Jonathan Cameron, Andy Shevchenko, David Lechner, Nuno Sá,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
AngeloGioacchino Del Regno, Sen Chu, Sean Wang, Macpaul Lin,
Lee Jones, Srinivas Kandagatla, Rafael J. Wysocki, Daniel Lezcano,
Zhang Rui, Lukasz Luba, linux-iio, devicetree, linux-kernel,
linux-arm-kernel, linux-mediatek, linux-pm, Ben Grisdale
In-Reply-To: <gWxamwTKyUeOF4QCsiIsrnh7DSWzIKFaY0h83qKq_0vg786xv1uFYhypix7BVO_ruG_vw3DrIsRhIKv5NAzl8hK72rjzPAjwAGU-rhkMgeA=@protonmail.com>
On Tue, May 12, 2026 at 02:34:55PM +0000, Roman Vivchar wrote:
> On Tuesday, May 12th, 2026 at 4:29 PM, Jonathan Cameron <jic23@kernel.org> wrote:
> > On Tue, 12 May 2026 08:18:19 +0300
> > Roman Vivchar via B4 Relay <devnull+rva333.protonmail.com@kernel.org> wrote:
...
> > > +#define VOLTAGE_FULL_RANGE 1800
> > Probably better to have this inline - however if you do keep it
> > prefix t he define VOLTAGE_FULL_RANGE sounds too generic!
> >
> > > +#define AUXADC_PRECISE 32768
> > I'd put that inline. Little benefit it in having it up here...
>
> There was a mention about magic values in the v1 for the thermal patch [1].
> Andy, would it be better to use an inline style or a #define here?
> If the former, I'll rename the first constant to something like
> AUXADC_VOLTAGE_FULL_RANGE.
If you use it inline, add a comment to explain the magic.
It will be a good compromise.
> [1]: https://lore.kernel.org/linux-mediatek/afmnUG8dG0N0HpV6@ashevche-desk.local/
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply
* Re: [PATCH v5 2/2] PCI: mediatek: Add support for EcoNet EN7528 SoC
From: Bjorn Helgaas @ 2026-05-12 16:55 UTC (permalink / raw)
To: Caleb James DeLisle
Cc: linux-pci, linux-mips, naseefkm, ryder.lee, lpieralisi,
kwilczynski, mani, robh, krzk+dt, conor+dt, matthias.bgg,
angelogioacchino.delregno, ansuelsmth, linux-mediatek, devicetree,
linux-kernel
In-Reply-To: <20260413140339.16238-3-cjd@cjdns.fr>
On Mon, Apr 13, 2026 at 02:03:39PM +0000, Caleb James DeLisle wrote:
> Add support for the PCIe present on the EcoNet EN7528 (and EN751221) SoCs.
>
> These SoCs have a mix of Gen1 and Gen2 capable ports, but the Gen2 ports
> require re-training after startup.
> +#include <asm-generic/errno-base.h>
Looks odd; why is this here? There are basically no other drivers
that do this.
> @@ -1149,6 +1234,46 @@ static int mtk_pcie_probe(struct platform_device *pdev)
> if (err)
> goto put_resources;
>
> + /* EN7528 PCIe initially comes up as Gen1 even if Gen2 is supported.
> + * The cannonical way to achieve Gen2 is to re-train the link
> + * immediately after setup. However, to save a lot of duplicated code
> + * we use pcie_retrain_link() which is usable once we have the pci_dev
> + * struct for the bridge, i.e. after pci_host_probe(). */
s/cannonical/canonical/
> + if (pcie->soc->quirks & MTK_PCIE_RETRAIN) {
> + int slot = of_get_pci_domain_nr(dev->of_node);
I suppose of_get_pci_domain_nr() is sort of an implicit way to
identify the Gen2 ports? Worth at least a comment about this DT
connection. Maybe it could be replaced by using
pcie_get_supported_speeds() or similar?
> + struct pci_dev *rc = NULL;
s/rc/rp/ to avoid confusing "root port" for "return code" or "root
complex".
> + int ret = -ENOENT;
> +
> + if (slot >= 0)
> + rc = pci_get_slot(host->bus, PCI_DEVFN(slot, 0));
Instead of fiddling with pci_get_slot(), which adds refcount issues
and artificial device/function number dependencies, I think it would
be better to iterate over the devices on host->bus, e.g., with
"for_each_pci_bridge(dev, host->bus)" as in iproc_pcie_setup().
> + if (rc) {
> + ret = -EOPNOTSUPP;
> +
> + /* pcie_retrain_link() is not an exported symbol but
> + * this driver supports being built as a loadable
> + * module. Someone using this on an EN7528 should make
> + * it builtin, or accept Gen1 PCI. */
> +#if IS_BUILTIN(CONFIG_PCIE_MEDIATEK)
> + ret = pcie_retrain_link(rc, true);
> +#endif
This looks like a confusing user experience if built as a module, with
no hint to the user about why the link is slower than it should be.
I guess "failed to retrain" is a bit of a hint, but it's not really a
clue about how to fix it.
> + }
> +
> + if (ret) {
> + dev_info(dev, "port%d failed to retrain %pe\n", slot,
> + ERR_PTR(ret));
This is basically an error path and there's nothing else to do, so if
you return directly here (especially if you factor this to a separate
function), the "normal" path below can be unindented.
> + } else {
> + u16 lnksta;
> + u32 speed;
> +
> + pcie_capability_read_word(rc, PCI_EXP_LNKSTA, &lnksta);
> + speed = lnksta & PCI_EXP_LNKSTA_CLS;
> +
> + dev_info(dev, "port%d link retrained, speed %s\n", slot,
> + pci_speed_string(pcie_link_speed[speed]));
> + }
> + }
Maybe factor the retrain block into a helper function.
I'm sort of squinting at this whole link retrain thing to begin with.
After the controller is configured correctly, the hardware is supposed
to train the link automatically by itself.
Did something change between mtk_pcie_startup_port_en7528() and now
that means the link will train at Gen2? Whatever that change is,
could it be done in mtk_pcie_startup_port_en7528()?
What happens when the downstream device is put in D3cold and the link
retrains after power is restored? Does it train at Gen2 then, without
assistance like this?
^ permalink raw reply
* Re: [PATCH 4/8] drm/panthor: Add support for protected memory allocation in panthor
From: Liviu Dudau @ 2026-05-12 15:38 UTC (permalink / raw)
To: Boris Brezillon
Cc: Marcin Ślusarz, Ketil Johnsen, David Airlie, Simona Vetter,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
Jonathan Corbet, Shuah Khan, Sumit Semwal, Benjamin Gaignard,
Brian Starkey, John Stultz, T.J. Mercier, Christian König,
Steven Price, Daniel Almeida, Alice Ryhl, Matthias Brugger,
AngeloGioacchino Del Regno, dri-devel, linux-doc, linux-kernel,
linux-media, linaro-mm-sig, linux-arm-kernel, linux-mediatek,
Florent Tomasin, nd
In-Reply-To: <20260512161111.0cb7000e@fedora>
On Tue, May 12, 2026 at 04:11:11PM +0200, Boris Brezillon wrote:
> On Tue, 12 May 2026 14:47:27 +0100
> Liviu Dudau <liviu.dudau@arm.com> wrote:
>
> > On Thu, May 07, 2026 at 01:53:56PM +0200, Boris Brezillon wrote:
> > > On Thu, 7 May 2026 11:02:26 +0200
> > > Marcin Ślusarz <marcin.slusarz@arm.com> wrote:
> > >
> > > > On Tue, May 05, 2026 at 06:15:23PM +0200, Boris Brezillon wrote:
> > > > > > @@ -277,9 +286,21 @@ int panthor_device_init(struct panthor_device *ptdev)
> > > > > > return ret;
> > > > > > }
> > > > > >
> > > > > > + /* If a protected heap name is specified but not found, defer the probe until created */
> > > > > > + if (protected_heap_name && strlen(protected_heap_name)) {
> > > > >
> > > > > Do we really need this strlen() > 0? Won't dma_heap_find() fail is the
> > > > > name is "" already?
> > > >
> > > > If dma_heap_find() will fail, then the whole probe with fail too.
> > > > This check prevents that.
> > >
> > > Yeah, that's also a questionable design choice. I mean, we can
> > > currently probe and boot the FW even though we never setup the
> > > protected FW sections, so why should we defer the probe here? Can't we
> > > just retry the next time a group with the protected bit is created and
> > > fail if we can find a protected heap?
> >
> > The problem we have with the current firmware is that it does a number of setup steps at "boot"
> > time only. One of the steps is preparing its internal structures for when it enters protected
> > mode and it stores them in the buffer passed in at firmware loading. We cannot later run the
> > process when we have a group with protected mode set.
>
> No, but we can force a full/slow reset and have that thing
> re-initialized, can't we? I mean, that's basically what we do when a
> fast reset fails: we re-initialize all the sections and reset again, at
> which point the FW should start from a fresh state, and be able to
> properly initialize the protected-related stuff if protected sections
> are populated. Am I missing something?
Right, we can do that. For some reason I keep associating the reset with the
error handling and not with "normal" operations.
Best regards,
Liviu
--
====================
| I would like to |
| fix the world, |
| but they're not |
| giving me the |
\ source code! /
---------------
¯\_(ツ)_/¯
^ permalink raw reply
* Re: [PATCH v2 05/16] iio: adc: mediatek: add mt6323 PMIC AUXADC driver
From: Roman Vivchar @ 2026-05-12 14:34 UTC (permalink / raw)
To: Jonathan Cameron, Andy Shevchenko
Cc: David Lechner, Nuno Sá, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Matthias Brugger, AngeloGioacchino Del Regno,
Sen Chu, Sean Wang, Macpaul Lin, Lee Jones, Srinivas Kandagatla,
Rafael J. Wysocki, Daniel Lezcano, Zhang Rui, Lukasz Luba,
linux-iio, devicetree, linux-kernel, linux-arm-kernel,
linux-mediatek, linux-pm, Ben Grisdale
In-Reply-To: <20260512142932.5c6801d1@jic23-huawei>
On Tuesday, May 12th, 2026 at 4:29 PM, Jonathan Cameron <jic23@kernel.org> wrote:
> On Tue, 12 May 2026 08:18:19 +0300
> Roman Vivchar via B4 Relay <devnull+rva333.protonmail.com@kernel.org> wrote:
...
> > +#define VOLTAGE_FULL_RANGE 1800
> Probably better to have this inline - however if you do keep it
> prefix t he define VOLTAGE_FULL_RANGE sounds too generic!
>
> > +#define AUXADC_PRECISE 32768
> I'd put that inline. Little benefit it in having it up here...
There was a mention about magic values in the v1 for the thermal patch [1].
Andy, would it be better to use an inline style or a #define here?
If the former, I'll rename the first constant to something like
AUXADC_VOLTAGE_FULL_RANGE.
[1]: https://lore.kernel.org/linux-mediatek/afmnUG8dG0N0HpV6@ashevche-desk.local/
Best regards,
Roman
^ permalink raw reply
* Re: [PATCH 4/8] drm/panthor: Add support for protected memory allocation in panthor
From: Boris Brezillon @ 2026-05-12 14:11 UTC (permalink / raw)
To: Liviu Dudau
Cc: Marcin Ślusarz, Ketil Johnsen, David Airlie, Simona Vetter,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
Jonathan Corbet, Shuah Khan, Sumit Semwal, Benjamin Gaignard,
Brian Starkey, John Stultz, T.J. Mercier, Christian König,
Steven Price, Daniel Almeida, Alice Ryhl, Matthias Brugger,
AngeloGioacchino Del Regno, dri-devel, linux-doc, linux-kernel,
linux-media, linaro-mm-sig, linux-arm-kernel, linux-mediatek,
Florent Tomasin, nd
In-Reply-To: <agMvb_jeRsO7tSS-@e142607>
On Tue, 12 May 2026 14:47:27 +0100
Liviu Dudau <liviu.dudau@arm.com> wrote:
> On Thu, May 07, 2026 at 01:53:56PM +0200, Boris Brezillon wrote:
> > On Thu, 7 May 2026 11:02:26 +0200
> > Marcin Ślusarz <marcin.slusarz@arm.com> wrote:
> >
> > > On Tue, May 05, 2026 at 06:15:23PM +0200, Boris Brezillon wrote:
> > > > > @@ -277,9 +286,21 @@ int panthor_device_init(struct panthor_device *ptdev)
> > > > > return ret;
> > > > > }
> > > > >
> > > > > + /* If a protected heap name is specified but not found, defer the probe until created */
> > > > > + if (protected_heap_name && strlen(protected_heap_name)) {
> > > >
> > > > Do we really need this strlen() > 0? Won't dma_heap_find() fail is the
> > > > name is "" already?
> > >
> > > If dma_heap_find() will fail, then the whole probe with fail too.
> > > This check prevents that.
> >
> > Yeah, that's also a questionable design choice. I mean, we can
> > currently probe and boot the FW even though we never setup the
> > protected FW sections, so why should we defer the probe here? Can't we
> > just retry the next time a group with the protected bit is created and
> > fail if we can find a protected heap?
>
> The problem we have with the current firmware is that it does a number of setup steps at "boot"
> time only. One of the steps is preparing its internal structures for when it enters protected
> mode and it stores them in the buffer passed in at firmware loading. We cannot later run the
> process when we have a group with protected mode set.
No, but we can force a full/slow reset and have that thing
re-initialized, can't we? I mean, that's basically what we do when a
fast reset fails: we re-initialize all the sections and reset again, at
which point the FW should start from a fresh state, and be able to
properly initialize the protected-related stuff if protected sections
are populated. Am I missing something?
^ permalink raw reply
* Re: [PATCH v2 01/16] dt-bindings: iio: adc: mt6359: generalize description for mt63xx series
From: Roman Vivchar @ 2026-05-12 13:55 UTC (permalink / raw)
To: Jonathan Cameron
Cc: David Lechner, Nuno Sá, Andy Shevchenko, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
AngeloGioacchino Del Regno, Sen Chu, Sean Wang, Macpaul Lin,
Lee Jones, Srinivas Kandagatla, Rafael J. Wysocki, Daniel Lezcano,
Zhang Rui, Lukasz Luba, linux-iio, devicetree, linux-kernel,
linux-arm-kernel, linux-mediatek, linux-pm, Ben Grisdale
In-Reply-To: <20260512141313.425535d9@jic23-huawei>
On Tuesday, May 12th, 2026 at 4:13 PM, Jonathan Cameron <jic23@kernel.org> wrote:
> On Tue, 12 May 2026 08:18:15 +0300
> Roman Vivchar via B4 Relay <devnull+rva333.protonmail.com@kernel.org> wrote:
>
> > From: Roman Vivchar <rva333@protonmail.com>
> >
> > Update binding title to the MT63xx, since the list of compatibles already
> > includes mt6363 and mt6373 which don't belong to the mt6350 family.
> Hi Roman,
>
> Wild cards have a nasty habit of going wrong. I'd prefer to see
> language like: MT6359 and similar PMIC AUXADC
Hi Jonathan,
I agree that it would be better to specify the exact PMIC models, however
'similar' wording might be a bit misleading here. As far as I know,
the mt6363 and mt6373 use SPMI, while mt635x (and older models, like
most of the mt63xx series) use PWRAP (a custom SPI-based protocol).
The mt6323 has an older AUXADC revision which is not compatible
with the mt635x driver.
Would you prefer more explicit list like 'MT6323, MT6350 series, MT6363
and MT6373 PMIC AUXADC'? It's a bit mess because some mt63xx
(like mt6333) are sub-PMICs and use I2C instead of PWRAP.
> It is less important here than in many other places because the
> file has an explicit list soon after this, but none the less
> we've been bitten by this too often to think manufacturers won't
> throw a completely non compatible part in the middle of a wild
> card covered range.
>
Best regards,
Roman
^ permalink raw reply
* Re: [PATCH 4/8] drm/panthor: Add support for protected memory allocation in panthor
From: Liviu Dudau @ 2026-05-12 13:47 UTC (permalink / raw)
To: Boris Brezillon
Cc: Marcin Ślusarz, Ketil Johnsen, David Airlie, Simona Vetter,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
Jonathan Corbet, Shuah Khan, Sumit Semwal, Benjamin Gaignard,
Brian Starkey, John Stultz, T.J. Mercier, Christian König,
Steven Price, Daniel Almeida, Alice Ryhl, Matthias Brugger,
AngeloGioacchino Del Regno, dri-devel, linux-doc, linux-kernel,
linux-media, linaro-mm-sig, linux-arm-kernel, linux-mediatek,
Florent Tomasin, nd
In-Reply-To: <20260507135356.5428d50d@fedora>
On Thu, May 07, 2026 at 01:53:56PM +0200, Boris Brezillon wrote:
> On Thu, 7 May 2026 11:02:26 +0200
> Marcin Ślusarz <marcin.slusarz@arm.com> wrote:
>
> > On Tue, May 05, 2026 at 06:15:23PM +0200, Boris Brezillon wrote:
> > > > @@ -277,9 +286,21 @@ int panthor_device_init(struct panthor_device *ptdev)
> > > > return ret;
> > > > }
> > > >
> > > > + /* If a protected heap name is specified but not found, defer the probe until created */
> > > > + if (protected_heap_name && strlen(protected_heap_name)) {
> > >
> > > Do we really need this strlen() > 0? Won't dma_heap_find() fail is the
> > > name is "" already?
> >
> > If dma_heap_find() will fail, then the whole probe with fail too.
> > This check prevents that.
>
> Yeah, that's also a questionable design choice. I mean, we can
> currently probe and boot the FW even though we never setup the
> protected FW sections, so why should we defer the probe here? Can't we
> just retry the next time a group with the protected bit is created and
> fail if we can find a protected heap?
The problem we have with the current firmware is that it does a number of setup steps at "boot"
time only. One of the steps is preparing its internal structures for when it enters protected
mode and it stores them in the buffer passed in at firmware loading. We cannot later run the
process when we have a group with protected mode set.
So unfortunately adding support for protected mode where the heap name is provided means we
have to try our best to set it up at boot time, or otherwise disable protected mode support.
Best regards,
Liviu
>
> > I'm not sure why it's needed at all, but if
> > it is really needed, then s/strlen(protected_heap_name)/protected_heap_name[0]/
> > would simplify this.
>
> It's not so much about how you do the test, and more about the case
> you're trying to protect against. I guess here you assume that
> panthor.protected_heap_name="" means "I don't have a protected heap for
> you". If it's deemed acceptable, this should most certainly be
> described somewhere.
>
> >
> > > > + ptdev->protm.heap = dma_heap_find(protected_heap_name);
> > > > + if (!ptdev->protm.heap) {
> > > > + drm_warn(&ptdev->base,
> > > > + "Protected heap \'%s\' not (yet) available - deferring probe",
> > > > + protected_heap_name);
> > > > + ret = -EPROBE_DEFER;
> > > > + goto err_rpm_put;
> > >
> > > If you move the heap retrieval before the rpm enablement, you can get
> > > rid of this goto err_rpm_put.
> > >
> > > > + }
> > > > + }
> > > > +
> > > > ret = panthor_hw_init(ptdev);
> > > > if (ret)
> > > > - goto err_rpm_put;
> > > > + goto err_dma_heap_put;
> > > >
> > > > ret = panthor_pwr_init(ptdev);
> > > > if (ret)
>
--
====================
| I would like to |
| fix the world, |
| but they're not |
| giving me the |
\ source code! /
---------------
¯\_(ツ)_/¯
^ permalink raw reply
* Re: [PATCH 3/8] drm/panthor: De-duplicate FW memory section sync
From: Liviu Dudau @ 2026-05-12 13:37 UTC (permalink / raw)
To: Ketil Johnsen
Cc: David Airlie, Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Jonathan Corbet, Shuah Khan, Sumit Semwal,
Benjamin Gaignard, Brian Starkey, John Stultz, T.J. Mercier,
Christian König, Boris Brezillon, Steven Price,
Daniel Almeida, Alice Ryhl, Matthias Brugger,
AngeloGioacchino Del Regno, dri-devel, linux-doc, linux-kernel,
linux-media, linaro-mm-sig, linux-arm-kernel, linux-mediatek
In-Reply-To: <20260505140516.1372388-4-ketil.johnsen@arm.com>
On Tue, May 05, 2026 at 04:05:09PM +0200, Ketil Johnsen wrote:
> Handle the sync to device of FW memory sections inside
> panthor_fw_init_section_mem() so that the callers do not have to.
>
> This small improvement is also critical for protected FW sections,
> so we avoid issuing memory transactions to protected memory from
> CPU running in normal mode.
>
> Signed-off-by: Ketil Johnsen <ketil.johnsen@arm.com>
Reviewed-by: Liviu Dudau <liviu.dudau@arm.com>
Best regards,
Liviu
> ---
> drivers/gpu/drm/panthor/panthor_fw.c | 22 ++++++----------------
> 1 file changed, 6 insertions(+), 16 deletions(-)
>
> diff --git a/drivers/gpu/drm/panthor/panthor_fw.c b/drivers/gpu/drm/panthor/panthor_fw.c
> index be0da5b1f3abf..0d07a133dc3af 100644
> --- a/drivers/gpu/drm/panthor/panthor_fw.c
> +++ b/drivers/gpu/drm/panthor/panthor_fw.c
> @@ -446,6 +446,7 @@ static void panthor_fw_init_section_mem(struct panthor_device *ptdev,
> struct panthor_fw_section *section)
> {
> bool was_mapped = !!section->mem->kmap;
> + struct sg_table *sgt;
> int ret;
>
> if (!section->data.size &&
> @@ -464,6 +465,11 @@ static void panthor_fw_init_section_mem(struct panthor_device *ptdev,
>
> if (!was_mapped)
> panthor_kernel_bo_vunmap(section->mem);
> +
> + /* An sgt should have been requested when the kernel BO was GPU-mapped. */
> + sgt = to_panthor_bo(section->mem->obj)->dmap.sgt;
> + if (!drm_WARN_ON_ONCE(&ptdev->base, !sgt))
> + dma_sync_sgtable_for_device(ptdev->base.dev, sgt, DMA_TO_DEVICE);
> }
>
> /**
> @@ -626,7 +632,6 @@ static int panthor_fw_load_section_entry(struct panthor_device *ptdev,
> section_size = hdr.va.end - hdr.va.start;
> if (section_size) {
> u32 cache_mode = hdr.flags & CSF_FW_BINARY_IFACE_ENTRY_CACHE_MODE_MASK;
> - struct panthor_gem_object *bo;
> u32 vm_map_flags = 0;
> u64 va = hdr.va.start;
>
> @@ -663,14 +668,6 @@ static int panthor_fw_load_section_entry(struct panthor_device *ptdev,
> }
>
> panthor_fw_init_section_mem(ptdev, section);
> -
> - bo = to_panthor_bo(section->mem->obj);
> -
> - /* An sgt should have been requested when the kernel BO was GPU-mapped. */
> - if (drm_WARN_ON_ONCE(&ptdev->base, !bo->dmap.sgt))
> - return -EINVAL;
> -
> - dma_sync_sgtable_for_device(ptdev->base.dev, bo->dmap.sgt, DMA_TO_DEVICE);
> }
>
> if (hdr.va.start == CSF_MCU_SHARED_REGION_START)
> @@ -724,17 +721,10 @@ panthor_reload_fw_sections(struct panthor_device *ptdev, bool full_reload)
> struct panthor_fw_section *section;
>
> list_for_each_entry(section, &ptdev->fw->sections, node) {
> - struct sg_table *sgt;
> -
> if (!full_reload && !(section->flags & CSF_FW_BINARY_IFACE_ENTRY_WR))
> continue;
>
> panthor_fw_init_section_mem(ptdev, section);
> -
> - /* An sgt should have been requested when the kernel BO was GPU-mapped. */
> - sgt = to_panthor_bo(section->mem->obj)->dmap.sgt;
> - if (!drm_WARN_ON_ONCE(&ptdev->base, !sgt))
> - dma_sync_sgtable_for_device(ptdev->base.dev, sgt, DMA_TO_DEVICE);
> }
> }
>
> --
> 2.43.0
>
--
====================
| I would like to |
| fix the world, |
| but they're not |
| giving me the |
\ source code! /
---------------
¯\_(ツ)_/¯
^ permalink raw reply
* Re: [PATCH v2 14/16] MAINTAINERS: add MediaTek mt6323 PMIC AUXADC driver maintainer
From: Jonathan Cameron @ 2026-05-12 13:36 UTC (permalink / raw)
To: Roman Vivchar via B4 Relay
Cc: rva333, David Lechner, Nuno Sá, Andy Shevchenko, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
AngeloGioacchino Del Regno, Sen Chu, Sean Wang, Macpaul Lin,
Lee Jones, Srinivas Kandagatla, Rafael J. Wysocki, Daniel Lezcano,
Zhang Rui, Lukasz Luba, linux-iio, devicetree, linux-kernel,
linux-arm-kernel, linux-mediatek, linux-pm, Ben Grisdale
In-Reply-To: <20260512-mt6323-v2-14-3efcba579e88@protonmail.com>
On Tue, 12 May 2026 08:18:28 +0300
Roman Vivchar via B4 Relay <devnull+rva333.protonmail.com@kernel.org> wrote:
> From: Roman Vivchar <rva333@protonmail.com>
>
> Add myself as MediaTek mt6323 AUXADC driver maintainer.
>
> Signed-off-by: Roman Vivchar <rva333@protonmail.com>
> ---
> MAINTAINERS | 5 +++++
> 1 file changed, 5 insertions(+)
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index d1cc0e12fe1f..52249c301633 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -16337,6 +16337,11 @@ S: Orphan
> F: Documentation/devicetree/bindings/mtd/mediatek,mtk-nfc.yaml
> F: drivers/mtd/nand/raw/mtk_*
>
> +MEDIATEK PMIC AUXADC DRIVER
Given this is one of quite a few Mediatek PMIC drivers, you either
need to be more specific in that title or offer to handle them all.
> +M: Roman Vivchar <rva333@protonmail.com>
> +S: Odd Fixes
> +F: drivers/iio/adc/mt6323-auxadc.c
> +
> MEDIATEK PMIC LED DRIVER
> M: Sen Chu <sen.chu@mediatek.com>
> M: Sean Wang <sean.wang@mediatek.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