1
1

airoha: Do not allow to disable LRO if the QDMA is shared

Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
Link: https://github.com/openwrt/openwrt/pull/23439
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
This commit is contained in:
Lorenzo Bianconi 2026-05-19 19:54:25 +02:00 committed by Christian Marangi
parent cb4e665da0
commit 9e512f7f0b
No known key found for this signature in database
GPG Key ID: AC001D09ADBFEAD7

View File

@ -21,7 +21,7 @@ Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
#include <uapi/linux/ppp_defs.h> #include <uapi/linux/ppp_defs.h>
#include "airoha_regs.h" #include "airoha_regs.h"
@@ -439,6 +440,41 @@ static void airoha_fe_crsn_qsel_init(str @@ -439,6 +440,47 @@ static void airoha_fe_crsn_qsel_init(str
CDM_CRSN_QSEL_Q1)); CDM_CRSN_QSEL_Q1));
} }
@ -59,11 +59,17 @@ Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
+ for (i = 0; i < AIROHA_MAX_NUM_LRO_QUEUES; i++) + for (i = 0; i < AIROHA_MAX_NUM_LRO_QUEUES; i++)
+ airoha_fe_clear(eth, REG_CDM_LRO_RXQ(id, i), LRO_RXQ_MASK(i)); + airoha_fe_clear(eth, REG_CDM_LRO_RXQ(id, i), LRO_RXQ_MASK(i));
+} +}
+
+static bool airoha_fe_lro_is_enabled(struct airoha_eth *eth, int qdma_id)
+{
+ return airoha_fe_get(eth, REG_CDM_LRO_EN(qdma_id + 1),
+ LRO_RXQ_EN_MASK);
+}
+ +
static int airoha_fe_init(struct airoha_eth *eth) static int airoha_fe_init(struct airoha_eth *eth)
{ {
airoha_fe_maccr_init(eth); airoha_fe_maccr_init(eth);
@@ -603,9 +639,78 @@ static int airoha_qdma_get_gdm_port(stru @@ -603,9 +645,78 @@ static int airoha_qdma_get_gdm_port(stru
return port >= ARRAY_SIZE(eth->ports) ? -EINVAL : port; return port >= ARRAY_SIZE(eth->ports) ? -EINVAL : port;
} }
@ -142,7 +148,7 @@ Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
struct airoha_qdma *qdma = q->qdma; struct airoha_qdma *qdma = q->qdma;
struct airoha_eth *eth = qdma->eth; struct airoha_eth *eth = qdma->eth;
int qid = q - &qdma->q_rx[0]; int qid = q - &qdma->q_rx[0];
@@ -652,9 +757,14 @@ static int airoha_qdma_rx_process(struct @@ -652,9 +763,14 @@ static int airoha_qdma_rx_process(struct
__skb_put(q->skb, len); __skb_put(q->skb, len);
skb_mark_for_recycle(q->skb); skb_mark_for_recycle(q->skb);
q->skb->dev = port->dev; q->skb->dev = port->dev;
@ -158,7 +164,7 @@ Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
} else { /* scattered frame */ } else { /* scattered frame */
struct skb_shared_info *shinfo = skb_shinfo(q->skb); struct skb_shared_info *shinfo = skb_shinfo(q->skb);
int nr_frags = shinfo->nr_frags; int nr_frags = shinfo->nr_frags;
@@ -743,23 +853,19 @@ static int airoha_qdma_rx_napi_poll(stru @@ -743,23 +859,19 @@ static int airoha_qdma_rx_napi_poll(stru
static int airoha_qdma_init_rx_queue(struct airoha_queue *q, static int airoha_qdma_init_rx_queue(struct airoha_queue *q,
struct airoha_qdma *qdma, int ndesc) struct airoha_qdma *qdma, int ndesc)
{ {
@ -185,7 +191,7 @@ Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
q->entry = devm_kzalloc(eth->dev, ndesc * sizeof(*q->entry), q->entry = devm_kzalloc(eth->dev, ndesc * sizeof(*q->entry),
GFP_KERNEL); GFP_KERNEL);
if (!q->entry) if (!q->entry)
@@ -770,6 +876,12 @@ static int airoha_qdma_init_rx_queue(str @@ -770,6 +882,12 @@ static int airoha_qdma_init_rx_queue(str
if (!q->desc) if (!q->desc)
return -ENOMEM; return -ENOMEM;
@ -198,7 +204,7 @@ Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
q->page_pool = page_pool_create(&pp_params); q->page_pool = page_pool_create(&pp_params);
if (IS_ERR(q->page_pool)) { if (IS_ERR(q->page_pool)) {
int err = PTR_ERR(q->page_pool); int err = PTR_ERR(q->page_pool);
@@ -778,6 +890,7 @@ static int airoha_qdma_init_rx_queue(str @@ -778,6 +896,7 @@ static int airoha_qdma_init_rx_queue(str
return err; return err;
} }
@ -206,7 +212,7 @@ Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
q->ndesc = ndesc; q->ndesc = ndesc;
netif_napi_add(eth->napi_dev, &q->napi, airoha_qdma_rx_napi_poll); netif_napi_add(eth->napi_dev, &q->napi, airoha_qdma_rx_napi_poll);
@@ -2032,6 +2145,45 @@ int airoha_get_fe_port(struct airoha_gdm @@ -2032,6 +2151,64 @@ int airoha_get_fe_port(struct airoha_gdm
} }
} }
@ -219,13 +225,17 @@ Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
+ struct airoha_qdma *qdma = port->qdma; + struct airoha_qdma *qdma = port->qdma;
+ struct airoha_eth *eth = qdma->eth; + struct airoha_eth *eth = qdma->eth;
+ int qdma_id = qdma - &eth->qdma[0]; + int qdma_id = qdma - &eth->qdma[0];
+ int i;
+ +
+ if (!(diff & NETIF_F_LRO)) + if (!(diff & NETIF_F_LRO))
+ return 0; + return 0;
+ +
+ /* reset LRO configuration */ + /* reset LRO configuration */
+ if (features & NETIF_F_LRO) { + if (features & NETIF_F_LRO) {
+ int i, lro_queue_index = 0; + int lro_queue_index = 0;
+
+ if (airoha_fe_lro_is_enabled(eth, qdma_id))
+ return 0;
+ +
+ for (i = 0; i < ARRAY_SIZE(qdma->q_rx); i++) { + for (i = 0; i < ARRAY_SIZE(qdma->q_rx); i++) {
+ struct airoha_queue *q = &qdma->q_rx[i]; + struct airoha_queue *q = &qdma->q_rx[i];
@ -243,6 +253,21 @@ Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
+ lro_queue_index++; + lro_queue_index++;
+ } + }
+ } else { + } else {
+ for (i = 0; i < ARRAY_SIZE(eth->ports); i++) {
+ struct airoha_gdm_port *p = eth->ports[i];
+
+ if (!p)
+ continue;
+
+ if (p->qdma != qdma)
+ continue;
+
+ if (p->dev == dev)
+ continue;
+
+ if (p->dev->features & NETIF_F_LRO)
+ return 0;
+ }
+ airoha_fe_lro_disable(eth, qdma_id); + airoha_fe_lro_disable(eth, qdma_id);
+ } + }
+ +
@ -252,7 +277,7 @@ Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb, static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb,
struct net_device *dev) struct net_device *dev)
{ {
@@ -2931,6 +3083,7 @@ static const struct net_device_ops airoh @@ -2931,6 +3108,7 @@ static const struct net_device_ops airoh
.ndo_stop = airoha_dev_stop, .ndo_stop = airoha_dev_stop,
.ndo_change_mtu = airoha_dev_change_mtu, .ndo_change_mtu = airoha_dev_change_mtu,
.ndo_select_queue = airoha_dev_select_queue, .ndo_select_queue = airoha_dev_select_queue,
@ -260,7 +285,7 @@ Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
.ndo_start_xmit = airoha_dev_xmit, .ndo_start_xmit = airoha_dev_xmit,
.ndo_get_stats64 = airoha_dev_get_stats64, .ndo_get_stats64 = airoha_dev_get_stats64,
.ndo_set_mac_address = airoha_dev_set_macaddr, .ndo_set_mac_address = airoha_dev_set_macaddr,
@@ -3153,12 +3306,9 @@ static int airoha_alloc_gdm_port(struct @@ -3148,12 +3326,9 @@ static int airoha_alloc_gdm_port(struct
dev->ethtool_ops = &airoha_ethtool_ops; dev->ethtool_ops = &airoha_ethtool_ops;
dev->max_mtu = AIROHA_MAX_MTU; dev->max_mtu = AIROHA_MAX_MTU;
dev->watchdog_timeo = 5 * HZ; dev->watchdog_timeo = 5 * HZ;