Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,26 +1,29 @@
From fae16fa0bb1f4203181aff0c7496518c2c8a4b9c Mon Sep 17 00:00:00 2001
Message-ID: <fae16fa0bb1f4203181aff0c7496518c2c8a4b9c.1771966444.git.lorenzo@kernel.org>
In-Reply-To: <2cd15ef3379025ea1ae1f6c36c70621aa578c270.1771966444.git.lorenzo@kernel.org>
References: <2cd15ef3379025ea1ae1f6c36c70621aa578c270.1771966444.git.lorenzo@kernel.org>
From 32bfd008c19f9ad55514181d8cd02e14bf384475 Mon Sep 17 00:00:00 2001
Message-ID: <32bfd008c19f9ad55514181d8cd02e14bf384475.1779348625.git.lorenzo@kernel.org>
In-Reply-To: <e15783f7c987e199ecf80b3d858ed5a86d33c508.1779348625.git.lorenzo@kernel.org>
References: <e15783f7c987e199ecf80b3d858ed5a86d33c508.1779348625.git.lorenzo@kernel.org>
From: Lorenzo Bianconi <lorenzo@kernel.org>
Date: Sat, 13 Dec 2025 10:06:45 +0100
Subject: [bpf-next 10/16] net: airoha: Rely on airoha_gdm_dev pointer in
airhoa_is_lan_gdm_port()
Subject: [PATCH 03/13] net: airoha: Rely on airoha_gdm_dev pointer in
airoha_is_lan_gdm_port()

Rename airhoa_is_lan_gdm_port in airhoa_is_lan_gdm_dev.
This is a preliminary patch to properly support multiple external phys
connected to the same GDM port.
Rename airoha_is_lan_gdm_port in airoha_is_lan_gdm_dev. Moreover, rely
on airoha_gdm_dev pointer in airoha_is_lan_gdm_dev() instead of
airoha_gdm_port one.
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 | 4 +---
drivers/net/ethernet/airoha/airoha_eth.c | 6 ++----
drivers/net/ethernet/airoha/airoha_eth.h | 4 +++-
drivers/net/ethernet/airoha/airoha_ppe.c | 2 +-
3 files changed, 5 insertions(+), 5 deletions(-)
3 files changed, 6 insertions(+), 6 deletions(-)

--- a/drivers/net/ethernet/airoha/airoha_eth.c
+++ b/drivers/net/ethernet/airoha/airoha_eth.c
@@ -81,12 +81,10 @@ static bool airhoa_is_phy_external(struc
@@ -82,12 +82,10 @@ static bool airhoa_is_phy_external(struc

static void airoha_set_macaddr(struct airoha_gdm_dev *dev, const u8 *addr)
{
Expand All @@ -34,8 +37,8 @@ Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
val = (addr[0] << 16) | (addr[1] << 8) | addr[2];
airoha_fe_wr(eth, reg, val);

@@ -324,7 +324,7 @@ static int airoha_ppe_foe_entry_prepare(
u8 ppe_id;
@@ -2020,7 +2018,7 @@ static int airoha_dev_init(struct net_de
int i;

/* QDMA0 is used for lan ports while QDMA1 is used for WAN ports */
- dev->qdma = &eth->qdma[!airoha_is_lan_gdm_port(port)];
Expand All @@ -45,9 +48,9 @@ Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>

--- a/drivers/net/ethernet/airoha/airoha_eth.h
+++ b/drivers/net/ethernet/airoha/airoha_eth.h
@@ -643,8 +643,10 @@ u32 airoha_rmw(void __iomem *base, u32 o
#define airoha_qdma_clear(qdma, offset, val) \
airoha_rmw((qdma)->regs, (offset), (val), 0)
@@ -663,8 +663,10 @@ static inline u16 airoha_qdma_get_txq(st
return qid % ARRAY_SIZE(qdma->q_tx);
}

-static inline bool airoha_is_lan_gdm_port(struct airoha_gdm_port *port)
+static inline bool airoha_is_lan_gdm_dev(struct airoha_gdm_dev *dev)
Expand All @@ -59,7 +62,7 @@ Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
* phy module.
--- a/drivers/net/ethernet/airoha/airoha_ppe.c
+++ b/drivers/net/ethernet/airoha/airoha_ppe.c
@@ -324,7 +324,7 @@ static int airoha_ppe_foe_entry_prepare(
@@ -365,7 +365,7 @@ static int airoha_ppe_foe_entry_prepare(
/* For downlink traffic consume SRAM memory for hw
* forwarding descriptors queue.
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
From 634d75285db77f3385aa85a1bf2b185396225100 Mon Sep 17 00:00:00 2001
Message-ID: <634d75285db77f3385aa85a1bf2b185396225100.1779348625.git.lorenzo@kernel.org>
In-Reply-To: <e15783f7c987e199ecf80b3d858ed5a86d33c508.1779348625.git.lorenzo@kernel.org>
References: <e15783f7c987e199ecf80b3d858ed5a86d33c508.1779348625.git.lorenzo@kernel.org>
From: Lorenzo Bianconi <lorenzo@kernel.org>
Date: Fri, 10 Apr 2026 14:35:32 +0200
Subject: [PATCH 04/13] net: airoha: Move qos_sq_bmap in airoha_gdm_dev struct

Since now multiple net_devices connected to different QDMA blocks can
share the same GDM port, qos_sq_bmap field can be overwritten with the
configuration obtained from a net_device connected to a different QDMA
block. In order to fix the issue move qos_sq_bmap field from
airoha_gdm_port struct to airoha_gdm_dev one.
Add qos_channel_map bitmap in airoha_qdma struct to track if a shared
QDMA channel is already in use by another net_device.

Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
drivers/net/ethernet/airoha/airoha_eth.c | 58 +++++++++++++++---------
drivers/net/ethernet/airoha/airoha_eth.h | 6 ++-
2 files changed, 40 insertions(+), 24 deletions(-)

--- a/drivers/net/ethernet/airoha/airoha_eth.c
+++ b/drivers/net/ethernet/airoha/airoha_eth.c
@@ -2793,30 +2793,40 @@ static int airoha_qdma_set_tx_rate_limit
return 0;
}

-static int airoha_tc_htb_alloc_leaf_queue(struct net_device *netdev,
- struct tc_htb_qopt_offload *opt)
+static int airoha_tc_htb_modify_queue(struct net_device *dev,
+ 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 = 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(netdev, channel, rate,
- opt->quantum);
- if (err) {
+ return airoha_qdma_set_tx_rate_limit(dev, channel, rate, opt->quantum);
+}
+
+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;
+ int err, num_tx_queues = netdev->real_num_tx_queues;
+ struct airoha_gdm_dev *dev = netdev_priv(netdev);
+ struct airoha_qdma *qdma = dev->qdma;
+
+ /* Here we need to check the requested QDMA channel is not already
+ * in use by another net_device running on the same QDMA block.
+ */
+ if (test_and_set_bit(channel, qdma->qos_channel_map)) {
NL_SET_ERR_MSG_MOD(opt->extack,
- "failed configuring htb offload");
- return err;
+ "qdma qos channel already in use");
+ return -EBUSY;
}

- if (opt->command == TC_HTB_NODE_MODIFY)
- return 0;
+ err = airoha_tc_htb_modify_queue(netdev, opt);
+ if (err)
+ goto error;

err = netif_set_real_num_tx_queues(netdev, num_tx_queues + 1);
if (err) {
@@ -2824,13 +2834,17 @@ static int airoha_tc_htb_alloc_leaf_queu
opt->quantum);
NL_SET_ERR_MSG_MOD(opt->extack,
"failed setting real_num_tx_queues");
- return err;
+ goto error;
}

- set_bit(channel, port->qos_sq_bmap);
+ set_bit(channel, dev->qos_sq_bmap);
opt->qid = AIROHA_NUM_TX_RING + channel;

return 0;
+error:
+ clear_bit(channel, qdma->qos_channel_map);
+
+ return err;
}

static int airoha_qdma_set_rx_meter(struct airoha_gdm_dev *dev,
@@ -3011,11 +3025,13 @@ static int airoha_dev_setup_tc_block(str
static void airoha_tc_remove_htb_queue(struct net_device *netdev, int queue)
{
struct airoha_gdm_dev *dev = netdev_priv(netdev);
- struct airoha_gdm_port *port = dev->port;
+ struct airoha_qdma *qdma = dev->qdma;

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);
+
+ clear_bit(queue, qdma->qos_channel_map);
+ clear_bit(queue, dev->qos_sq_bmap);
}

static int airoha_tc_htb_delete_leaf_queue(struct net_device *netdev,
@@ -3023,9 +3039,8 @@ static int airoha_tc_htb_delete_leaf_que
{
u32 channel = TC_H_MIN(opt->classid) % AIROHA_NUM_QOS_CHANNELS;
struct airoha_gdm_dev *dev = netdev_priv(netdev);
- struct airoha_gdm_port *port = dev->port;

- if (!test_bit(channel, port->qos_sq_bmap)) {
+ if (!test_bit(channel, dev->qos_sq_bmap)) {
NL_SET_ERR_MSG_MOD(opt->extack, "invalid queue id");
return -EINVAL;
}
@@ -3038,10 +3053,9 @@ static int airoha_tc_htb_delete_leaf_que
static int airoha_tc_htb_destroy(struct net_device *netdev)
{
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)
+ for_each_set_bit(q, dev->qos_sq_bmap, AIROHA_NUM_QOS_CHANNELS)
airoha_tc_remove_htb_queue(netdev, q);

return 0;
@@ -3052,9 +3066,8 @@ static int airoha_tc_get_htb_get_leaf_qu
{
u32 channel = TC_H_MIN(opt->classid) % AIROHA_NUM_QOS_CHANNELS;
struct airoha_gdm_dev *dev = netdev_priv(netdev);
- struct airoha_gdm_port *port = dev->port;

- if (!test_bit(channel, port->qos_sq_bmap)) {
+ if (!test_bit(channel, dev->qos_sq_bmap)) {
NL_SET_ERR_MSG_MOD(opt->extack, "invalid queue id");
return -EINVAL;
}
@@ -3073,6 +3086,7 @@ static int airoha_tc_setup_qdisc_htb(str
case TC_HTB_DESTROY:
return airoha_tc_htb_destroy(dev);
case TC_HTB_NODE_MODIFY:
+ return airoha_tc_htb_modify_queue(dev, opt);
case TC_HTB_LEAF_ALLOC_QUEUE:
return airoha_tc_htb_alloc_leaf_queue(dev, opt);
case TC_HTB_LEAF_DEL:
--- a/drivers/net/ethernet/airoha/airoha_eth.h
+++ b/drivers/net/ethernet/airoha/airoha_eth.h
@@ -544,6 +544,8 @@ struct airoha_qdma {

struct airoha_queue q_tx[AIROHA_NUM_TX_RING];
struct airoha_queue q_rx[AIROHA_NUM_RX_RING];
+
+ DECLARE_BITMAP(qos_channel_map, AIROHA_NUM_QOS_CHANNELS);
};

struct airoha_gdm_dev {
@@ -556,6 +558,8 @@ struct airoha_gdm_dev {
struct phylink *phylink;
struct phylink_config phylink_config;
#endif
+
+ DECLARE_BITMAP(qos_sq_bmap, AIROHA_NUM_QOS_CHANNELS);
};

struct airoha_gdm_port {
@@ -565,8 +569,6 @@ struct airoha_gdm_port {

struct airoha_hw_stats stats;

- DECLARE_BITMAP(qos_sq_bmap, AIROHA_NUM_QOS_CHANNELS);
-
/* qos stats counters */
u64 cpu_tx_packets;
u64 fwd_tx_packets;
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
From 00272dbf6a52241a21145631f22dc5f03891078b Mon Sep 17 00:00:00 2001
Message-ID: <00272dbf6a52241a21145631f22dc5f03891078b.1779348625.git.lorenzo@kernel.org>
In-Reply-To: <e15783f7c987e199ecf80b3d858ed5a86d33c508.1779348625.git.lorenzo@kernel.org>
References: <e15783f7c987e199ecf80b3d858ed5a86d33c508.1779348625.git.lorenzo@kernel.org>
From: Lorenzo Bianconi <lorenzo@kernel.org>
Date: Fri, 10 Apr 2026 14:47:08 +0200
Subject: [PATCH 05/13] net: airoha: Move {cpu,fwd}_tx_packets in
airoha_gdm_dev struct

Since now multiple net_devices connected to different QDMA blocks can
share the same GDM port, cpu_tx_packets and fwd_tx_packets fields can
be overwritten with the value from a different QDMA block. In order to
fix the issue move cpu_tx_packets and fwd_tx_packets fields from
airoha_gdm_port struct to airoha_gdm_dev one.

Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
drivers/net/ethernet/airoha/airoha_eth.c | 16 +++++++---------
drivers/net/ethernet/airoha/airoha_eth.h | 7 +++----
2 files changed, 10 insertions(+), 13 deletions(-)

--- a/drivers/net/ethernet/airoha/airoha_eth.c
+++ b/drivers/net/ethernet/airoha/airoha_eth.c
@@ -2506,19 +2506,17 @@ static int airoha_qdma_get_tx_ets_stats(
struct tc_ets_qopt_offload *opt)
{
struct airoha_gdm_dev *dev = netdev_priv(netdev);
- struct airoha_gdm_port *port = dev->port;
+ struct airoha_qdma *qdma = dev->qdma;

- u64 cpu_tx_packets = airoha_qdma_rr(dev->qdma,
- REG_CNTR_VAL(channel << 1));
- u64 fwd_tx_packets = airoha_qdma_rr(dev->qdma,
+ u64 cpu_tx_packets = airoha_qdma_rr(qdma, REG_CNTR_VAL(channel << 1));
+ u64 fwd_tx_packets = airoha_qdma_rr(qdma,
REG_CNTR_VAL((channel << 1) + 1));
- u64 tx_packets = (cpu_tx_packets - port->cpu_tx_packets) +
- (fwd_tx_packets - port->fwd_tx_packets);
+ u64 tx_packets = (cpu_tx_packets - dev->cpu_tx_packets) +
+ (fwd_tx_packets - dev->fwd_tx_packets);

_bstats_update(opt->stats.bstats, 0, tx_packets);
-
- port->cpu_tx_packets = cpu_tx_packets;
- port->fwd_tx_packets = fwd_tx_packets;
+ dev->cpu_tx_packets = cpu_tx_packets;
+ dev->fwd_tx_packets = fwd_tx_packets;

return 0;
}
--- a/drivers/net/ethernet/airoha/airoha_eth.h
+++ b/drivers/net/ethernet/airoha/airoha_eth.h
@@ -560,6 +560,9 @@ struct airoha_gdm_dev {
#endif

DECLARE_BITMAP(qos_sq_bmap, AIROHA_NUM_QOS_CHANNELS);
+ /* qos stats counters */
+ u64 cpu_tx_packets;
+ u64 fwd_tx_packets;
};

struct airoha_gdm_port {
@@ -569,10 +572,6 @@ struct airoha_gdm_port {

struct airoha_hw_stats stats;

- /* qos stats counters */
- u64 cpu_tx_packets;
- u64 fwd_tx_packets;
-
struct metadata_dst *dsa_meta[AIROHA_MAX_DSA_PORTS];
};

Loading
Loading