af4fa78c90958c0ca28b464cf05f00dd759100b6
[openwrt/staging/thess.git] /
1 From 80369686737fe07c233a1152da0b84372dabdcd6 Mon Sep 17 00:00:00 2001
2 From: Lorenzo Bianconi <lorenzo@kernel.org>
3 Date: Fri, 28 Feb 2025 11:54:15 +0100
4 Subject: [PATCH 07/15] net: airoha: Enable support for multiple net_devices
5
6 In the current codebase airoha_eth driver supports just a single
7 net_device connected to the Packet Switch Engine (PSE) lan port (GDM1).
8 As shown in commit 23020f049327 ("net: airoha: Introduce ethernet
9 support for EN7581 SoC"), PSE can switch packets between four GDM ports.
10 Enable the capability to create a net_device for each GDM port of the
11 PSE module. Moreover, since the QDMA blocks can be shared between
12 net_devices, do not stop TX/RX DMA in airoha_dev_stop() if there are
13 active net_devices for this QDMA block.
14 This is a preliminary patch to enable flowtable hw offloading for EN7581
15 SoC.
16
17 Co-developed-by: Christian Marangi <ansuelsmth@gmail.com>
18 Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
19 Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
20 Signed-off-by: Paolo Abeni <pabeni@redhat.com>
21 ---
22 drivers/net/ethernet/airoha/airoha_eth.c | 35 ++++++++++++++----------
23 drivers/net/ethernet/airoha/airoha_eth.h | 4 ++-
24 2 files changed, 24 insertions(+), 15 deletions(-)
25
26 --- a/drivers/net/ethernet/airoha/airoha_eth.c
27 +++ b/drivers/net/ethernet/airoha/airoha_eth.c
28 @@ -1563,6 +1563,7 @@ static int airoha_dev_open(struct net_de
29 airoha_qdma_set(qdma, REG_QDMA_GLOBAL_CFG,
30 GLOBAL_CFG_TX_DMA_EN_MASK |
31 GLOBAL_CFG_RX_DMA_EN_MASK);
32 + atomic_inc(&qdma->users);
33
34 return 0;
35 }
36 @@ -1578,16 +1579,20 @@ static int airoha_dev_stop(struct net_de
37 if (err)
38 return err;
39
40 - airoha_qdma_clear(qdma, REG_QDMA_GLOBAL_CFG,
41 - GLOBAL_CFG_TX_DMA_EN_MASK |
42 - GLOBAL_CFG_RX_DMA_EN_MASK);
43 + for (i = 0; i < ARRAY_SIZE(qdma->q_tx); i++)
44 + netdev_tx_reset_subqueue(dev, i);
45
46 - for (i = 0; i < ARRAY_SIZE(qdma->q_tx); i++) {
47 - if (!qdma->q_tx[i].ndesc)
48 - continue;
49 + if (atomic_dec_and_test(&qdma->users)) {
50 + airoha_qdma_clear(qdma, REG_QDMA_GLOBAL_CFG,
51 + GLOBAL_CFG_TX_DMA_EN_MASK |
52 + GLOBAL_CFG_RX_DMA_EN_MASK);
53 +
54 + for (i = 0; i < ARRAY_SIZE(qdma->q_tx); i++) {
55 + if (!qdma->q_tx[i].ndesc)
56 + continue;
57
58 - airoha_qdma_cleanup_tx_queue(&qdma->q_tx[i]);
59 - netdev_tx_reset_subqueue(dev, i);
60 + airoha_qdma_cleanup_tx_queue(&qdma->q_tx[i]);
61 + }
62 }
63
64 return 0;
65 @@ -2330,13 +2335,14 @@ static void airoha_metadata_dst_free(str
66 }
67 }
68
69 -static int airoha_alloc_gdm_port(struct airoha_eth *eth, struct device_node *np)
70 +static int airoha_alloc_gdm_port(struct airoha_eth *eth,
71 + struct device_node *np, int index)
72 {
73 const __be32 *id_ptr = of_get_property(np, "reg", NULL);
74 struct airoha_gdm_port *port;
75 struct airoha_qdma *qdma;
76 struct net_device *dev;
77 - int err, index;
78 + int err, p;
79 u32 id;
80
81 if (!id_ptr) {
82 @@ -2345,14 +2351,14 @@ static int airoha_alloc_gdm_port(struct
83 }
84
85 id = be32_to_cpup(id_ptr);
86 - index = id - 1;
87 + p = id - 1;
88
89 if (!id || id > ARRAY_SIZE(eth->ports)) {
90 dev_err(eth->dev, "invalid gdm port id: %d\n", id);
91 return -EINVAL;
92 }
93
94 - if (eth->ports[index]) {
95 + if (eth->ports[p]) {
96 dev_err(eth->dev, "duplicate gdm port id: %d\n", id);
97 return -EINVAL;
98 }
99 @@ -2400,7 +2406,7 @@ static int airoha_alloc_gdm_port(struct
100 port->qdma = qdma;
101 port->dev = dev;
102 port->id = id;
103 - eth->ports[index] = port;
104 + eth->ports[p] = port;
105
106 err = airoha_metadata_dst_alloc(port);
107 if (err)
108 @@ -2472,6 +2478,7 @@ static int airoha_probe(struct platform_
109 for (i = 0; i < ARRAY_SIZE(eth->qdma); i++)
110 airoha_qdma_start_napi(&eth->qdma[i]);
111
112 + i = 0;
113 for_each_child_of_node(pdev->dev.of_node, np) {
114 if (!of_device_is_compatible(np, "airoha,eth-mac"))
115 continue;
116 @@ -2479,7 +2486,7 @@ static int airoha_probe(struct platform_
117 if (!of_device_is_available(np))
118 continue;
119
120 - err = airoha_alloc_gdm_port(eth, np);
121 + err = airoha_alloc_gdm_port(eth, np, i++);
122 if (err) {
123 of_node_put(np);
124 goto error_napi_stop;
125 --- a/drivers/net/ethernet/airoha/airoha_eth.h
126 +++ b/drivers/net/ethernet/airoha/airoha_eth.h
127 @@ -13,7 +13,7 @@
128 #include <linux/netdevice.h>
129 #include <linux/reset.h>
130
131 -#define AIROHA_MAX_NUM_GDM_PORTS 1
132 +#define AIROHA_MAX_NUM_GDM_PORTS 4
133 #define AIROHA_MAX_NUM_QDMA 2
134 #define AIROHA_MAX_DSA_PORTS 7
135 #define AIROHA_MAX_NUM_RSTS 3
136 @@ -212,6 +212,8 @@ struct airoha_qdma {
137 u32 irqmask[QDMA_INT_REG_MAX];
138 int irq;
139
140 + atomic_t users;
141 +
142 struct airoha_tx_irq_queue q_tx_irq[AIROHA_NUM_TX_IRQ];
143
144 struct airoha_queue q_tx[AIROHA_NUM_TX_RING];