mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-09-04 20:19:47 +08:00
Octeontx2-vf: Fix max packet length errors
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:3184fb5ba9
("octeontx2-vf: Virtual function driver support") Fixes:22f8587967
("octeontx2-pf: Add basic net_device_ops") Fixes:3ca6c4c882
("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>
This commit is contained in:
parent
abadf0ff63
commit
a64494aafc
@ -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);
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -27,6 +27,7 @@ struct rep_stats {
|
||||
u64 tx_bytes;
|
||||
u64 tx_frames;
|
||||
u64 tx_drops;
|
||||
atomic_long_t tx_discards;
|
||||
};
|
||||
|
||||
struct rep_dev {
|
||||
|
Loading…
Reference in New Issue
Block a user