[RFC PATCH net-next v2] ppp: enable TX scatter-gather
From: Qingfang Deng <dqfext@gmail.com>
Date: 2025-09-09 01:27:58
Also in:
lkml
Subsystem:
networking drivers, ppp protocol drivers and compressors, the rest · Maintainers:
Andrew Lunn, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Linus Torvalds
When chan->direct_xmit is true, and no compressors are in use, PPP prepends its header to a skb, and calls dev_queue_xmit directly. In this mode the skb does not need to be linearized. Enable NETIF_F_SG and NETIF_F_FRAGLIST, and add .ndo_fix_features() callback to conditionally disable them if a linear skb is required. This is required to support PPPoE GSO. Signed-off-by: Qingfang Deng <dqfext@gmail.com> --- RFC v2: Dynamically update netdev features with ndo_fix_features() callback. Link to RFC v1: https://lore.kernel.org/netdev/20250904021328.24329-1-dqfext@gmail.com/ (local) drivers/net/ppp/ppp_generic.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+)
diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c
index f9f0f16c41d1..22e17f8fb61f 100644
--- a/drivers/net/ppp/ppp_generic.c
+++ b/drivers/net/ppp/ppp_generic.c@@ -835,6 +835,10 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ppp_unlock(ppp); if (cflags & SC_CCP_OPEN) ppp_ccp_closed(ppp); + + rtnl_lock(); + netdev_update_features(ppp->dev); + rtnl_unlock(); err = 0; break;
@@ -1545,6 +1549,22 @@ ppp_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats64) dev_fetch_sw_netstats(stats64, dev->tstats); } +static netdev_features_t +ppp_fix_features(struct net_device *dev, netdev_features_t features) +{ + struct ppp *ppp = netdev_priv(dev); + + ppp_lock(ppp); + /* Allow SG/FRAGLIST only when we have direct-xmit, and no compression + * path that wants a linear skb. + */ + if (!(dev->priv_flags & IFF_NO_QUEUE) || + (ppp->flags & (SC_COMP_TCP | SC_CCP_OPEN | SC_CCP_UP))) + features &= ~(NETIF_F_SG | NETIF_F_FRAGLIST); + ppp_unlock(ppp); + return features; +} + static int ppp_dev_init(struct net_device *dev) { struct ppp *ppp;
@@ -1619,6 +1639,7 @@ static const struct net_device_ops ppp_netdev_ops = { .ndo_start_xmit = ppp_start_xmit, .ndo_siocdevprivate = ppp_net_siocdevprivate, .ndo_get_stats64 = ppp_get_stats64, + .ndo_fix_features = ppp_fix_features, .ndo_fill_forward_path = ppp_fill_forward_path, };
@@ -1641,6 +1662,8 @@ static void ppp_setup(struct net_device *dev) dev->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST; dev->priv_destructor = ppp_dev_priv_destructor; dev->pcpu_stat_type = NETDEV_PCPU_STAT_TSTATS; + dev->hw_features = NETIF_F_SG | NETIF_F_FRAGLIST; + dev->features = dev->hw_features; netif_keep_dst(dev); }
@@ -3537,6 +3560,12 @@ ppp_connect_channel(struct channel *pch, int unit) spin_unlock(&pch->upl); out: mutex_unlock(&pn->all_ppp_mutex); + if (ret == 0) { + rtnl_lock(); + netdev_update_features(ppp->dev); + rtnl_unlock(); + } + return ret; }
--
2.43.0