From 120ae502af169310aa53359d4faf2494dcee6927 Mon Sep 17 00:00:00 2001 From: Tallapragada Kalyan Date: Thu, 9 Jun 2022 09:32:38 +0530 Subject: [PATCH 267/281] net: set skb's fast_xmit flag in dev_fast_xmit API set skb's fast_xmit flag in dev_fast_xmit API for linear packets WiFi tx path can avoid some overhead due to checks based on this flag Change-Id: Ied29f9d615d0cf48dd9dcd7fcf0fb210eb259a8f Signed-off-by: Tallapragada Kalyan --- include/linux/skbuff.h | 2 ++ net/core/dev.c | 4 ++++ 2 files changed, 6 insertions(+) --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -990,6 +990,8 @@ struct sk_buff { __u8 csum_not_inet:1; #endif __u8 fast_forwarded:1; + /* Linear packets processed by dev_fast_xmit() */ + __u8 fast_xmit:1; /* 1 or 3 bit hole */ #if defined(CONFIG_NET_SCHED) || defined(CONFIG_NET_XGRESS) --- a/net/core/dev.c +++ b/net/core/dev.c @@ -4305,6 +4305,144 @@ struct netdev_queue *netdev_core_pick_tx } /** + * dev_fast_xmit_vp - fast xmit the skb to a PPE virtual port + * @skb:buffer to transmit + * @dev: the device to be transmited to + * sucessful return true + * failed return false + */ +bool dev_fast_xmit_vp(struct sk_buff *skb, + struct net_device *dev) +{ + struct netdev_queue *txq; + int cpu; + netdev_tx_t rc; + + if (unlikely(!(dev->flags & IFF_UP))) { + return false; + } + + if (unlikely(skb_is_nonlinear(skb))) { + return false; + } + + rcu_read_lock_bh(); + cpu = smp_processor_id(); + + /* + * TODO: Skip this altogether and eventually move this call to ppe_vp + * this would avoid multiple function calls when giving packet to wifi VAP. + */ + txq = netdev_core_pick_tx(dev, skb, NULL); + + if (likely(txq->xmit_lock_owner != cpu)) { +#define FAST_VP_HARD_TX_LOCK(txq, cpu) { \ + __netif_tx_lock(txq, cpu); \ +} + +#define FAST_VP_HARD_TX_UNLOCK(txq) { \ + __netif_tx_unlock(txq); \ +} + skb->fast_xmit = 1; + FAST_VP_HARD_TX_LOCK(txq, cpu); + if (likely(!netif_xmit_stopped(txq))) { + rc = netdev_start_xmit(skb, dev, txq, 0); + if (unlikely(!dev_xmit_complete(rc))) { + FAST_VP_HARD_TX_UNLOCK(txq); + goto q_xmit; + } + FAST_VP_HARD_TX_UNLOCK(txq); + rcu_read_unlock_bh(); + return true; + } + FAST_VP_HARD_TX_UNLOCK(txq); + } +q_xmit: + skb->fast_xmit = 0; + rcu_read_unlock_bh(); + return false; +} +EXPORT_SYMBOL(dev_fast_xmit_vp); + +/** + * dev_fast_xmit - fast xmit the skb + * @skb:buffer to transmit + * @dev: the device to be transmited to + * @features: the skb features could bed used + * sucessful return true + * failed return false + */ +bool dev_fast_xmit(struct sk_buff *skb, + struct net_device *dev, + netdev_features_t features) +{ + struct netdev_queue *txq; + int cpu; + netdev_tx_t rc; + + /* the fast_xmit flag will avoid multiple checks in wifi xmit path */ + if (likely(!skb_is_nonlinear(skb))) + skb->fast_xmit = 1; + + if (unlikely(!(dev->flags & IFF_UP))) { + return false; + } + + if (unlikely(skb_needs_linearize(skb, features))) { + return false; + } + + rcu_read_lock_bh(); + cpu = smp_processor_id(); + + /* If device don't need the dst, release it now, otherwise make sure + * the refcount increased. + */ + if (likely(dev->priv_flags & IFF_XMIT_DST_RELEASE)) { + skb_dst_drop(skb); + } else { + skb_dst_force(skb); + } + + txq = netdev_core_pick_tx(dev, skb, NULL); + + if (likely(txq->xmit_lock_owner != cpu)) { +#define FAST_HARD_TX_LOCK(features, txq, cpu) { \ + if ((features & NETIF_F_LLTX) == 0) { \ + __netif_tx_lock(txq, cpu); \ + } else { \ + __netif_tx_acquire(txq); \ + } \ +} + +#define FAST_HARD_TX_UNLOCK(features, txq) { \ + if ((features & NETIF_F_LLTX) == 0) { \ + __netif_tx_unlock(txq); \ + } else { \ + __netif_tx_release(txq); \ + } \ +} + netdev_features_t dev_features = dev->features; + FAST_HARD_TX_LOCK(dev_features, txq, cpu); + if (likely(!netif_xmit_stopped(txq))) { + rc = netdev_start_xmit(skb, dev, txq, 0); + if (unlikely(!dev_xmit_complete(rc))) { + FAST_HARD_TX_UNLOCK(dev_features, txq); + goto fail; + } + FAST_HARD_TX_UNLOCK(dev_features, txq); + rcu_read_unlock_bh(); + return true; + } + FAST_HARD_TX_UNLOCK(dev_features, txq); + } +fail: + rcu_read_unlock_bh(); + return false; +} +EXPORT_SYMBOL(dev_fast_xmit); + +/** * __dev_queue_xmit() - transmit a buffer * @skb: buffer to transmit * @sb_dev: suboordinate device used for L2 forwarding offload