]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
Octeontx2-vf: Fix max packet length errors
authorHariprasad Kelam <hkelam@marvell.com>
Thu, 21 Aug 2025 06:25:28 +0000 (11:55 +0530)
committerJakub Kicinski <kuba@kernel.org>
Fri, 22 Aug 2025 22:53:04 +0000 (15:53 -0700)
Once driver submits the packets to the hardware, each packet
traverse through multiple transmit levels in the following
order:
SMQ -> TL4 -> TL3 -> TL2 -> TL1

The SMQ supports configurable minimum and maximum packet sizes.
It enters to a hang state, if driver submits packets with
out of bound lengths.

To avoid the same, implement packet length validation before
submitting packets to the hardware. Increment tx_dropped counter
on failure.

Fixes: 3184fb5ba96e ("octeontx2-vf: Virtual function driver support")
Fixes: 22f858796758 ("octeontx2-pf: Add basic net_device_ops")
Fixes: 3ca6c4c882a7 ("octeontx2-pf: Add packet transmission support")
Signed-off-by: Hariprasad Kelam <hkelam@marvell.com>
Link: https://patch.msgid.link/20250821062528.1697992-1-hkelam@marvell.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c
drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h
drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c
drivers/net/ethernet/marvell/octeontx2/nic/rep.c
drivers/net/ethernet/marvell/octeontx2/nic/rep.h

index f674729124e691a4da12e9a61c5dacb50725c1db..aff17c37ddde07d4b8ee7a58edfbcd0ad3670346 100644 (file)
@@ -124,7 +124,9 @@ void otx2_get_dev_stats(struct otx2_nic *pfvf)
                               dev_stats->rx_ucast_frames;
 
        dev_stats->tx_bytes = OTX2_GET_TX_STATS(TX_OCTS);
-       dev_stats->tx_drops = OTX2_GET_TX_STATS(TX_DROP);
+       dev_stats->tx_drops = OTX2_GET_TX_STATS(TX_DROP) +
+                              (unsigned long)atomic_long_read(&dev_stats->tx_discards);
+
        dev_stats->tx_bcast_frames = OTX2_GET_TX_STATS(TX_BCAST);
        dev_stats->tx_mcast_frames = OTX2_GET_TX_STATS(TX_MCAST);
        dev_stats->tx_ucast_frames = OTX2_GET_TX_STATS(TX_UCAST);
index e3765b73c434dde5067f53d07a12cdf3843f22d4..1c8a3c078a647db5b1f99dd8437c1e18bb8abcb9 100644 (file)
@@ -153,6 +153,7 @@ struct otx2_dev_stats {
        u64 tx_bcast_frames;
        u64 tx_mcast_frames;
        u64 tx_drops;
+       atomic_long_t tx_discards;
 };
 
 /* Driver counted stats */
index b23585c5e5c2429d7bdc5c855c0a8163a5ea0a4e..5027fae0aa77a68d70a89f5554762fd47fb3cab2 100644 (file)
@@ -2220,6 +2220,7 @@ static netdev_tx_t otx2_xmit(struct sk_buff *skb, struct net_device *netdev)
 {
        struct otx2_nic *pf = netdev_priv(netdev);
        int qidx = skb_get_queue_mapping(skb);
+       struct otx2_dev_stats *dev_stats;
        struct otx2_snd_queue *sq;
        struct netdev_queue *txq;
        int sq_idx;
@@ -2232,6 +2233,8 @@ static netdev_tx_t otx2_xmit(struct sk_buff *skb, struct net_device *netdev)
        /* Check for minimum and maximum packet length */
        if (skb->len <= ETH_HLEN ||
            (!skb_shinfo(skb)->gso_size && skb->len > pf->tx_max_pktlen)) {
+               dev_stats = &pf->hw.dev_stats;
+               atomic_long_inc(&dev_stats->tx_discards);
                dev_kfree_skb(skb);
                return NETDEV_TX_OK;
        }
index 5589fccd370b8a2bc168227600bc209613e0259b..7ebb6e656884ae82e212fb8d84e23f407062e4ae 100644 (file)
@@ -417,9 +417,19 @@ static netdev_tx_t otx2vf_xmit(struct sk_buff *skb, struct net_device *netdev)
 {
        struct otx2_nic *vf = netdev_priv(netdev);
        int qidx = skb_get_queue_mapping(skb);
+       struct otx2_dev_stats *dev_stats;
        struct otx2_snd_queue *sq;
        struct netdev_queue *txq;
 
+       /* Check for minimum and maximum packet length */
+       if (skb->len <= ETH_HLEN ||
+           (!skb_shinfo(skb)->gso_size && skb->len > vf->tx_max_pktlen)) {
+               dev_stats = &vf->hw.dev_stats;
+               atomic_long_inc(&dev_stats->tx_discards);
+               dev_kfree_skb(skb);
+               return NETDEV_TX_OK;
+       }
+
        sq = &vf->qset.sq[qidx];
        txq = netdev_get_tx_queue(netdev, qidx);
 
index 25af98034e2ec7392bec6a7d0954e14ab85d7edc..b476733a0234554763de34c27decc94b60c73cb5 100644 (file)
@@ -371,7 +371,8 @@ static void rvu_rep_get_stats(struct work_struct *work)
        stats->rx_mcast_frames = rsp->rx.mcast;
        stats->tx_bytes = rsp->tx.octs;
        stats->tx_frames = rsp->tx.ucast + rsp->tx.bcast + rsp->tx.mcast;
-       stats->tx_drops = rsp->tx.drop;
+       stats->tx_drops = rsp->tx.drop +
+                         (unsigned long)atomic_long_read(&stats->tx_discards);
 exit:
        mutex_unlock(&priv->mbox.lock);
 }
@@ -418,6 +419,16 @@ static netdev_tx_t rvu_rep_xmit(struct sk_buff *skb, struct net_device *dev)
        struct otx2_nic *pf = rep->mdev;
        struct otx2_snd_queue *sq;
        struct netdev_queue *txq;
+       struct rep_stats *stats;
+
+       /* Check for minimum and maximum packet length */
+       if (skb->len <= ETH_HLEN ||
+           (!skb_shinfo(skb)->gso_size && skb->len > pf->tx_max_pktlen)) {
+               stats = &rep->stats;
+               atomic_long_inc(&stats->tx_discards);
+               dev_kfree_skb(skb);
+               return NETDEV_TX_OK;
+       }
 
        sq = &pf->qset.sq[rep->rep_id];
        txq = netdev_get_tx_queue(dev, 0);
index 38446b3e4f13cc67cf1352680342bb6496781710..5bc9e2c7d800b42a4665bdc3e2a526ac06966cc2 100644 (file)
@@ -27,6 +27,7 @@ struct rep_stats {
        u64 tx_bytes;
        u64 tx_frames;
        u64 tx_drops;
+       atomic_long_t tx_discards;
 };
 
 struct rep_dev {