From ff6076314339e079806d9d2f3de9c9b768e94db1 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Fri, 14 Mar 2014 20:47:49 -0700 Subject: netpoll: Add netpoll_rx_processing Add a helper netpoll_rx_processing that reports when netpoll has receive side processing to perform. Signed-off-by: "Eric W. Biederman" Signed-off-by: David S. Miller --- include/linux/netpoll.h | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) (limited to 'include/linux/netpoll.h') diff --git a/include/linux/netpoll.h b/include/linux/netpoll.h index fbfdb9d8d3a7..479d15c97770 100644 --- a/include/linux/netpoll.h +++ b/include/linux/netpoll.h @@ -82,14 +82,24 @@ static inline void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb) local_irq_restore(flags); } - +#ifdef CONFIG_NETPOLL_TRAP +static inline bool netpoll_rx_processing(struct netpoll_info *npinfo) +{ + return !list_empty(&npinfo->rx_np); +} +#else +static inline bool netpoll_rx_processing(struct netpoll_info *npinfo) +{ + return false; +} +#endif #ifdef CONFIG_NETPOLL static inline bool netpoll_rx_on(struct sk_buff *skb) { struct netpoll_info *npinfo = rcu_dereference_bh(skb->dev->npinfo); - return npinfo && (!list_empty(&npinfo->rx_np) || npinfo->rx_flags); + return npinfo && (netpoll_rx_processing(npinfo) || npinfo->rx_flags); } static inline bool netpoll_rx(struct sk_buff *skb) @@ -105,8 +115,8 @@ static inline bool netpoll_rx(struct sk_buff *skb) npinfo = rcu_dereference_bh(skb->dev->npinfo); spin_lock(&npinfo->rx_lock); - /* check rx_flags again with the lock held */ - if (npinfo->rx_flags && __netpoll_rx(skb, npinfo)) + /* check rx_processing again with the lock held */ + if (netpoll_rx_processing(npinfo) && __netpoll_rx(skb, npinfo)) ret = true; spin_unlock(&npinfo->rx_lock); -- cgit v1.2.3 From b6bacd550c33124ea76291bd84ac42c8d30767eb Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Fri, 14 Mar 2014 20:48:28 -0700 Subject: netpoll: Don't drop all received packets. Change the strategy of netpoll from dropping all packets received during netpoll_poll_dev to calling napi poll with a budget of 0 (to avoid processing drivers rx queue), and to ignore packets received with netif_rx (those will safely be placed on the backlog queue). All of the netpoll supporting drivers have been reviewed to ensure either thay use netif_rx or that a budget of 0 is supported by their napi poll routine and that a budget of 0 will not process the drivers rx queues. Not dropping packets makes NETPOLL_RX_DROP unnecesary so it is removed. npinfo->rx_flags is removed as rx_flags with just the NETPOLL_RX_ENABLED flag becomes just a redundant mirror of list_empty(&npinfo->rx_np). Signed-off-by: "Eric W. Biederman" Signed-off-by: David S. Miller --- include/linux/netpoll.h | 3 +-- net/core/netpoll.c | 17 ++++++----------- 2 files changed, 7 insertions(+), 13 deletions(-) (limited to 'include/linux/netpoll.h') diff --git a/include/linux/netpoll.h b/include/linux/netpoll.h index 479d15c97770..154f9776056c 100644 --- a/include/linux/netpoll.h +++ b/include/linux/netpoll.h @@ -39,7 +39,6 @@ struct netpoll { struct netpoll_info { atomic_t refcnt; - unsigned long rx_flags; spinlock_t rx_lock; struct semaphore dev_lock; struct list_head rx_np; /* netpolls that registered an rx_skb_hook */ @@ -99,7 +98,7 @@ static inline bool netpoll_rx_on(struct sk_buff *skb) { struct netpoll_info *npinfo = rcu_dereference_bh(skb->dev->npinfo); - return npinfo && (netpoll_rx_processing(npinfo) || npinfo->rx_flags); + return npinfo && netpoll_rx_processing(npinfo); } static inline bool netpoll_rx(struct sk_buff *skb) diff --git a/net/core/netpoll.c b/net/core/netpoll.c index ef83a2530e98..793dc04d2f19 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -51,8 +51,6 @@ static atomic_t trapped; DEFINE_STATIC_SRCU(netpoll_srcu); #define USEC_PER_POLL 50 -#define NETPOLL_RX_ENABLED 1 -#define NETPOLL_RX_DROP 2 #define MAX_SKB_SIZE \ (sizeof(struct ethhdr) + \ @@ -193,7 +191,8 @@ static void netpoll_poll_dev(struct net_device *dev) { const struct net_device_ops *ops; struct netpoll_info *ni = rcu_dereference_bh(dev->npinfo); - int budget = 16; + bool rx_processing = netpoll_rx_processing(ni); + int budget = rx_processing? 16 : 0; /* Don't do any rx activity if the dev_lock mutex is held * the dev_open/close paths use this to block netpoll activity @@ -207,8 +206,8 @@ static void netpoll_poll_dev(struct net_device *dev) return; } - ni->rx_flags |= NETPOLL_RX_DROP; - atomic_inc(&trapped); + if (rx_processing) + atomic_inc(&trapped); ops = dev->netdev_ops; if (!ops->ndo_poll_controller) { @@ -221,8 +220,8 @@ static void netpoll_poll_dev(struct net_device *dev) poll_napi(dev, budget); - atomic_dec(&trapped); - ni->rx_flags &= ~NETPOLL_RX_DROP; + if (rx_processing) + atomic_dec(&trapped); up(&ni->dev_lock); @@ -1050,7 +1049,6 @@ int __netpoll_setup(struct netpoll *np, struct net_device *ndev, gfp_t gfp) goto out; } - npinfo->rx_flags = 0; INIT_LIST_HEAD(&npinfo->rx_np); spin_lock_init(&npinfo->rx_lock); @@ -1076,7 +1074,6 @@ int __netpoll_setup(struct netpoll *np, struct net_device *ndev, gfp_t gfp) if (np->rx_skb_hook) { spin_lock_irqsave(&npinfo->rx_lock, flags); - npinfo->rx_flags |= NETPOLL_RX_ENABLED; list_add_tail(&np->rx, &npinfo->rx_np); spin_unlock_irqrestore(&npinfo->rx_lock, flags); } @@ -1258,8 +1255,6 @@ void __netpoll_cleanup(struct netpoll *np) if (!list_empty(&npinfo->rx_np)) { spin_lock_irqsave(&npinfo->rx_lock, flags); list_del(&np->rx); - if (list_empty(&npinfo->rx_np)) - npinfo->rx_flags &= ~NETPOLL_RX_ENABLED; spin_unlock_irqrestore(&npinfo->rx_lock, flags); } -- cgit v1.2.3 From ad8d475244b4112a0f5331e78d043d3a4c9eb37e Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Fri, 14 Mar 2014 20:49:43 -0700 Subject: netpoll: Move netpoll_trap under CONFIG_NETPOLL_TRAP Now that we no longer need to receive packets to safely drain the network drivers receive queue move netpoll_trap and netpoll_set_trap under CONFIG_NETPOLL_TRAP Making netpoll_trap and netpoll_set_trap noop inline functions when CONFIG_NETPOLL_TRAP is not set. Signed-off-by: "Eric W. Biederman" Signed-off-by: David S. Miller --- include/linux/netpoll.h | 11 +++++++++-- net/core/netpoll.c | 14 +++++++++----- 2 files changed, 18 insertions(+), 7 deletions(-) (limited to 'include/linux/netpoll.h') diff --git a/include/linux/netpoll.h b/include/linux/netpoll.h index 154f9776056c..ab9aaaff8d04 100644 --- a/include/linux/netpoll.h +++ b/include/linux/netpoll.h @@ -65,8 +65,6 @@ void netpoll_print_options(struct netpoll *np); int netpoll_parse_options(struct netpoll *np, char *opt); int __netpoll_setup(struct netpoll *np, struct net_device *ndev, gfp_t gfp); int netpoll_setup(struct netpoll *np); -int netpoll_trap(void); -void netpoll_set_trap(int trap); void __netpoll_cleanup(struct netpoll *np); void __netpoll_free_async(struct netpoll *np); void netpoll_cleanup(struct netpoll *np); @@ -82,11 +80,20 @@ static inline void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb) } #ifdef CONFIG_NETPOLL_TRAP +int netpoll_trap(void); +void netpoll_set_trap(int trap); static inline bool netpoll_rx_processing(struct netpoll_info *npinfo) { return !list_empty(&npinfo->rx_np); } #else +static inline int netpoll_trap(void) +{ + return 0; +} +static inline void netpoll_set_trap(int trap) +{ +} static inline bool netpoll_rx_processing(struct netpoll_info *npinfo) { return false; diff --git a/net/core/netpoll.c b/net/core/netpoll.c index 793dc04d2f19..0e45835f1737 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -46,7 +46,9 @@ static struct sk_buff_head skb_pool; +#ifdef CONFIG_NETPOLL_TRAP static atomic_t trapped; +#endif DEFINE_STATIC_SRCU(netpoll_srcu); @@ -207,7 +209,7 @@ static void netpoll_poll_dev(struct net_device *dev) } if (rx_processing) - atomic_inc(&trapped); + netpoll_set_trap(1); ops = dev->netdev_ops; if (!ops->ndo_poll_controller) { @@ -221,7 +223,7 @@ static void netpoll_poll_dev(struct net_device *dev) poll_napi(dev, budget); if (rx_processing) - atomic_dec(&trapped); + netpoll_set_trap(0); up(&ni->dev_lock); @@ -776,10 +778,10 @@ int __netpoll_rx(struct sk_buff *skb, struct netpoll_info *npinfo) goto out; /* check if netpoll clients need ARP */ - if (skb->protocol == htons(ETH_P_ARP) && atomic_read(&trapped)) { + if (skb->protocol == htons(ETH_P_ARP) && netpoll_trap()) { skb_queue_tail(&npinfo->neigh_tx, skb); return 1; - } else if (pkt_is_ns(skb) && atomic_read(&trapped)) { + } else if (pkt_is_ns(skb) && netpoll_trap()) { skb_queue_tail(&npinfo->neigh_tx, skb); return 1; } @@ -896,7 +898,7 @@ int __netpoll_rx(struct sk_buff *skb, struct netpoll_info *npinfo) return 1; out: - if (atomic_read(&trapped)) { + if (netpoll_trap()) { kfree_skb(skb); return 1; } @@ -1302,6 +1304,7 @@ out: } EXPORT_SYMBOL(netpoll_cleanup); +#ifdef CONFIG_NETPOLL_TRAP int netpoll_trap(void) { return atomic_read(&trapped); @@ -1316,3 +1319,4 @@ void netpoll_set_trap(int trap) atomic_dec(&trapped); } EXPORT_SYMBOL(netpoll_set_trap); +#endif /* CONFIG_NETPOLL_TRAP */ -- cgit v1.2.3 From e1bd4d3d7dd2a4a0e731ffe07c439927c23f16ea Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Fri, 14 Mar 2014 20:50:58 -0700 Subject: netpoll: Move all receive processing under CONFIG_NETPOLL_TRAP Make rx_skb_hook, and rx in struct netpoll depend on CONFIG_NETPOLL_TRAP Make rx_lock, rx_np, and neigh_tx in struct netpoll_info depend on CONFIG_NETPOLL_TRAP Make the functions netpoll_rx_on, netpoll_rx, and netpoll_receive_skb no-ops when CONFIG_NETPOLL_TRAP is not set. Only build netpoll_neigh_reply, checksum_udp service_neigh_queue, pkt_is_ns, and __netpoll_rx when CONFIG_NETPOLL_TRAP is defined. Add helper functions netpoll_trap_setup, netpoll_trap_setup_info, netpoll_trap_cleanup, and netpoll_trap_cleanup_info that initialize and cleanup the struct netpoll and struct netpoll_info receive specific fields when CONFIG_NETPOLL_TRAP is enabled and do nothing otherwise. Signed-off-by: "Eric W. Biederman" Signed-off-by: David S. Miller --- include/linux/netpoll.h | 73 ++++++++++++++++++++++++-------------------- net/core/netpoll.c | 81 ++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 104 insertions(+), 50 deletions(-) (limited to 'include/linux/netpoll.h') diff --git a/include/linux/netpoll.h b/include/linux/netpoll.h index ab9aaaff8d04..a0632af88d8b 100644 --- a/include/linux/netpoll.h +++ b/include/linux/netpoll.h @@ -24,32 +24,38 @@ struct netpoll { struct net_device *dev; char dev_name[IFNAMSIZ]; const char *name; - void (*rx_skb_hook)(struct netpoll *np, int source, struct sk_buff *skb, - int offset, int len); union inet_addr local_ip, remote_ip; bool ipv6; u16 local_port, remote_port; u8 remote_mac[ETH_ALEN]; - struct list_head rx; /* rx_np list element */ struct work_struct cleanup_work; + +#ifdef CONFIG_NETPOLL_TRAP + void (*rx_skb_hook)(struct netpoll *np, int source, struct sk_buff *skb, + int offset, int len); + struct list_head rx; /* rx_np list element */ +#endif }; struct netpoll_info { atomic_t refcnt; - spinlock_t rx_lock; struct semaphore dev_lock; - struct list_head rx_np; /* netpolls that registered an rx_skb_hook */ - struct sk_buff_head neigh_tx; /* list of neigh requests to reply to */ struct sk_buff_head txq; struct delayed_work tx_work; struct netpoll *netpoll; struct rcu_head rcu; + +#ifdef CONFIG_NETPOLL_TRAP + spinlock_t rx_lock; + struct list_head rx_np; /* netpolls that registered an rx_skb_hook */ + struct sk_buff_head neigh_tx; /* list of neigh requests to reply to */ +#endif }; #ifdef CONFIG_NETPOLL @@ -68,7 +74,6 @@ int netpoll_setup(struct netpoll *np); void __netpoll_cleanup(struct netpoll *np); void __netpoll_free_async(struct netpoll *np); void netpoll_cleanup(struct netpoll *np); -int __netpoll_rx(struct sk_buff *skb, struct netpoll_info *npinfo); void netpoll_send_skb_on_dev(struct netpoll *np, struct sk_buff *skb, struct net_device *dev); static inline void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb) @@ -82,25 +87,12 @@ static inline void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb) #ifdef CONFIG_NETPOLL_TRAP int netpoll_trap(void); void netpoll_set_trap(int trap); +int __netpoll_rx(struct sk_buff *skb, struct netpoll_info *npinfo); static inline bool netpoll_rx_processing(struct netpoll_info *npinfo) { return !list_empty(&npinfo->rx_np); } -#else -static inline int netpoll_trap(void) -{ - return 0; -} -static inline void netpoll_set_trap(int trap) -{ -} -static inline bool netpoll_rx_processing(struct netpoll_info *npinfo) -{ - return false; -} -#endif -#ifdef CONFIG_NETPOLL static inline bool netpoll_rx_on(struct sk_buff *skb) { struct netpoll_info *npinfo = rcu_dereference_bh(skb->dev->npinfo); @@ -138,6 +130,33 @@ static inline int netpoll_receive_skb(struct sk_buff *skb) return 0; } +#else +static inline int netpoll_trap(void) +{ + return 0; +} +static inline void netpoll_set_trap(int trap) +{ +} +static inline bool netpoll_rx_processing(struct netpoll_info *npinfo) +{ + return false; +} +static inline bool netpoll_rx(struct sk_buff *skb) +{ + return false; +} +static inline bool netpoll_rx_on(struct sk_buff *skb) +{ + return false; +} +static inline int netpoll_receive_skb(struct sk_buff *skb) +{ + return 0; +} +#endif + +#ifdef CONFIG_NETPOLL static inline void *netpoll_poll_lock(struct napi_struct *napi) { struct net_device *dev = napi->dev; @@ -166,18 +185,6 @@ static inline bool netpoll_tx_running(struct net_device *dev) } #else -static inline bool netpoll_rx(struct sk_buff *skb) -{ - return false; -} -static inline bool netpoll_rx_on(struct sk_buff *skb) -{ - return false; -} -static inline int netpoll_receive_skb(struct sk_buff *skb) -{ - return 0; -} static inline void *netpoll_poll_lock(struct napi_struct *napi) { return NULL; diff --git a/net/core/netpoll.c b/net/core/netpoll.c index b69bb3f1ba3f..eed8b1d2d302 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -48,6 +48,7 @@ static struct sk_buff_head skb_pool; #ifdef CONFIG_NETPOLL_TRAP static atomic_t trapped; +static void netpoll_neigh_reply(struct sk_buff *skb, struct netpoll_info *npinfo); #endif DEFINE_STATIC_SRCU(netpoll_srcu); @@ -61,7 +62,6 @@ DEFINE_STATIC_SRCU(netpoll_srcu); MAX_UDP_CHUNK) static void zap_completion_queue(void); -static void netpoll_neigh_reply(struct sk_buff *skb, struct netpoll_info *npinfo); static void netpoll_async_cleanup(struct work_struct *work); static unsigned int carrier_timeout = 4; @@ -109,6 +109,7 @@ static void queue_process(struct work_struct *work) } } +#ifdef CONFIG_NETPOLL_TRAP static __sum16 checksum_udp(struct sk_buff *skb, struct udphdr *uh, unsigned short ulen, __be32 saddr, __be32 daddr) { @@ -127,6 +128,7 @@ static __sum16 checksum_udp(struct sk_buff *skb, struct udphdr *uh, return __skb_checksum_complete(skb); } +#endif /* CONFIG_NETPOLL_TRAP */ /* * Check whether delayed processing was scheduled for our NIC. If so, @@ -179,6 +181,7 @@ static void poll_napi(struct net_device *dev, int budget) } } +#ifdef CONFIG_NETPOLL_TRAP static void service_neigh_queue(struct net_device *dev, struct netpoll_info *npi) { @@ -197,6 +200,12 @@ static void service_neigh_queue(struct net_device *dev, while ((skb = skb_dequeue(&npi->neigh_tx))) netpoll_neigh_reply(skb, npi); } +#else /* !CONFIG_NETPOLL_TRAP */ +static inline void service_neigh_queue(struct net_device *dev, + struct netpoll_info *npi) +{ +} +#endif /* CONFIG_NETPOLL_TRAP */ static void netpoll_poll_dev(struct net_device *dev) { @@ -522,6 +531,7 @@ void netpoll_send_udp(struct netpoll *np, const char *msg, int len) } EXPORT_SYMBOL(netpoll_send_udp); +#ifdef CONFIG_NETPOLL_TRAP static void netpoll_neigh_reply(struct sk_buff *skb, struct netpoll_info *npinfo) { int size, type = ARPOP_REPLY; @@ -900,6 +910,55 @@ out: return 0; } +static void netpoll_trap_setup_info(struct netpoll_info *npinfo) +{ + INIT_LIST_HEAD(&npinfo->rx_np); + spin_lock_init(&npinfo->rx_lock); + skb_queue_head_init(&npinfo->neigh_tx); +} + +static void netpoll_trap_cleanup_info(struct netpoll_info *npinfo) +{ + skb_queue_purge(&npinfo->neigh_tx); +} + +static void netpoll_trap_setup(struct netpoll *np, struct netpoll_info *npinfo) +{ + unsigned long flags; + if (np->rx_skb_hook) { + spin_lock_irqsave(&npinfo->rx_lock, flags); + list_add_tail(&np->rx, &npinfo->rx_np); + spin_unlock_irqrestore(&npinfo->rx_lock, flags); + } +} + +static void netpoll_trap_cleanup(struct netpoll *np, struct netpoll_info *npinfo) +{ + unsigned long flags; + if (!list_empty(&npinfo->rx_np)) { + spin_lock_irqsave(&npinfo->rx_lock, flags); + list_del(&np->rx); + spin_unlock_irqrestore(&npinfo->rx_lock, flags); + } +} + +#else /* !CONFIG_NETPOLL_TRAP */ +static inline void netpoll_trap_setup_info(struct netpoll_info *npinfo) +{ +} +static inline void netpoll_trap_cleanup_info(struct netpoll_info *npinfo) +{ +} +static inline +void netpoll_trap_setup(struct netpoll *np, struct netpoll_info *npinfo) +{ +} +static inline +void netpoll_trap_cleanup(struct netpoll *np, struct netpoll_info *npinfo) +{ +} +#endif /* CONFIG_NETPOLL_TRAP */ + void netpoll_print_options(struct netpoll *np) { np_info(np, "local port %d\n", np->local_port); @@ -1023,7 +1082,6 @@ int __netpoll_setup(struct netpoll *np, struct net_device *ndev, gfp_t gfp) { struct netpoll_info *npinfo; const struct net_device_ops *ops; - unsigned long flags; int err; np->dev = ndev; @@ -1045,11 +1103,9 @@ int __netpoll_setup(struct netpoll *np, struct net_device *ndev, gfp_t gfp) goto out; } - INIT_LIST_HEAD(&npinfo->rx_np); + netpoll_trap_setup_info(npinfo); - spin_lock_init(&npinfo->rx_lock); sema_init(&npinfo->dev_lock, 1); - skb_queue_head_init(&npinfo->neigh_tx); skb_queue_head_init(&npinfo->txq); INIT_DELAYED_WORK(&npinfo->tx_work, queue_process); @@ -1068,11 +1124,7 @@ int __netpoll_setup(struct netpoll *np, struct net_device *ndev, gfp_t gfp) npinfo->netpoll = np; - if (np->rx_skb_hook) { - spin_lock_irqsave(&npinfo->rx_lock, flags); - list_add_tail(&np->rx, &npinfo->rx_np); - spin_unlock_irqrestore(&npinfo->rx_lock, flags); - } + netpoll_trap_setup(np, npinfo); /* last thing to do is link it to the net device structure */ rcu_assign_pointer(ndev->npinfo, npinfo); @@ -1222,7 +1274,7 @@ static void rcu_cleanup_netpoll_info(struct rcu_head *rcu_head) struct netpoll_info *npinfo = container_of(rcu_head, struct netpoll_info, rcu); - skb_queue_purge(&npinfo->neigh_tx); + netpoll_trap_cleanup_info(npinfo); skb_queue_purge(&npinfo->txq); /* we can't call cancel_delayed_work_sync here, as we are in softirq */ @@ -1238,7 +1290,6 @@ static void rcu_cleanup_netpoll_info(struct rcu_head *rcu_head) void __netpoll_cleanup(struct netpoll *np) { struct netpoll_info *npinfo; - unsigned long flags; /* rtnl_dereference would be preferable here but * rcu_cleanup_netpoll path can put us in here safely without @@ -1248,11 +1299,7 @@ void __netpoll_cleanup(struct netpoll *np) if (!npinfo) return; - if (!list_empty(&npinfo->rx_np)) { - spin_lock_irqsave(&npinfo->rx_lock, flags); - list_del(&np->rx); - spin_unlock_irqrestore(&npinfo->rx_lock, flags); - } + netpoll_trap_cleanup(np, npinfo); synchronize_srcu(&netpoll_srcu); -- cgit v1.2.3 From 9c62a68d13119a1ca9718381d97b0cb415ff4e9d Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Fri, 14 Mar 2014 20:51:52 -0700 Subject: netpoll: Remove dead packet receive code (CONFIG_NETPOLL_TRAP) The netpoll packet receive code only becomes active if the netpoll rx_skb_hook is implemented, and there is not a single implementation of the netpoll rx_skb_hook in the kernel. All of the out of tree implementations I have found all call netpoll_poll which was removed from the kernel in 2011, so this change should not add any additional breakage. There are problems with the netpoll packet receive code. __netpoll_rx does not call dev_kfree_skb_irq or dev_kfree_skb_any in hard irq context. netpoll_neigh_reply leaks every skb it receives. Reception of packets does not work successfully on stacked devices (aka bonding, team, bridge, and vlans). Given that the netpoll packet receive code is buggy, there are no out of tree users that will be merged soon, and the code has not been used for in tree for a decade let's just remove it. Reverting this commit can server as a starting point for anyone who wants to resurrect netpoll packet reception support. Acked-by: Eric Dumazet Signed-off-by: "Eric W. Biederman" Signed-off-by: David S. Miller --- drivers/net/Kconfig | 5 - include/linux/netdevice.h | 17 -- include/linux/netpoll.h | 84 -------- net/core/dev.c | 11 +- net/core/netpoll.c | 520 +--------------------------------------------- 5 files changed, 2 insertions(+), 635 deletions(-) (limited to 'include/linux/netpoll.h') diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 494b888a6568..89402c3b64f8 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -177,11 +177,6 @@ config NETCONSOLE_DYNAMIC config NETPOLL def_bool NETCONSOLE -config NETPOLL_TRAP - bool "Netpoll traffic trapping" - default n - depends on NETPOLL - config NET_POLL_CONTROLLER def_bool NETPOLL diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index b8d8c805fd75..4b6d12c7b803 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -1979,9 +1979,6 @@ struct net_device *__dev_get_by_index(struct net *net, int ifindex); struct net_device *dev_get_by_index_rcu(struct net *net, int ifindex); int netdev_get_name(struct net *net, char *name, int ifindex); int dev_restart(struct net_device *dev); -#ifdef CONFIG_NETPOLL_TRAP -int netpoll_trap(void); -#endif int skb_gro_receive(struct sk_buff **head, struct sk_buff *skb); static inline unsigned int skb_gro_offset(const struct sk_buff *skb) @@ -2186,12 +2183,6 @@ static inline void netif_tx_start_all_queues(struct net_device *dev) static inline void netif_tx_wake_queue(struct netdev_queue *dev_queue) { -#ifdef CONFIG_NETPOLL_TRAP - if (netpoll_trap()) { - netif_tx_start_queue(dev_queue); - return; - } -#endif if (test_and_clear_bit(__QUEUE_STATE_DRV_XOFF, &dev_queue->state)) __netif_schedule(dev_queue->qdisc); } @@ -2435,10 +2426,6 @@ static inline void netif_start_subqueue(struct net_device *dev, u16 queue_index) static inline void netif_stop_subqueue(struct net_device *dev, u16 queue_index) { struct netdev_queue *txq = netdev_get_tx_queue(dev, queue_index); -#ifdef CONFIG_NETPOLL_TRAP - if (netpoll_trap()) - return; -#endif netif_tx_stop_queue(txq); } @@ -2473,10 +2460,6 @@ static inline bool netif_subqueue_stopped(const struct net_device *dev, static inline void netif_wake_subqueue(struct net_device *dev, u16 queue_index) { struct netdev_queue *txq = netdev_get_tx_queue(dev, queue_index); -#ifdef CONFIG_NETPOLL_TRAP - if (netpoll_trap()) - return; -#endif if (test_and_clear_bit(__QUEUE_STATE_DRV_XOFF, &txq->state)) __netif_schedule(txq->qdisc); } diff --git a/include/linux/netpoll.h b/include/linux/netpoll.h index a0632af88d8b..1b475a5a7239 100644 --- a/include/linux/netpoll.h +++ b/include/linux/netpoll.h @@ -31,12 +31,6 @@ struct netpoll { u8 remote_mac[ETH_ALEN]; struct work_struct cleanup_work; - -#ifdef CONFIG_NETPOLL_TRAP - void (*rx_skb_hook)(struct netpoll *np, int source, struct sk_buff *skb, - int offset, int len); - struct list_head rx; /* rx_np list element */ -#endif }; struct netpoll_info { @@ -50,12 +44,6 @@ struct netpoll_info { struct netpoll *netpoll; struct rcu_head rcu; - -#ifdef CONFIG_NETPOLL_TRAP - spinlock_t rx_lock; - struct list_head rx_np; /* netpolls that registered an rx_skb_hook */ - struct sk_buff_head neigh_tx; /* list of neigh requests to reply to */ -#endif }; #ifdef CONFIG_NETPOLL @@ -84,78 +72,6 @@ static inline void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb) local_irq_restore(flags); } -#ifdef CONFIG_NETPOLL_TRAP -int netpoll_trap(void); -void netpoll_set_trap(int trap); -int __netpoll_rx(struct sk_buff *skb, struct netpoll_info *npinfo); -static inline bool netpoll_rx_processing(struct netpoll_info *npinfo) -{ - return !list_empty(&npinfo->rx_np); -} - -static inline bool netpoll_rx_on(struct sk_buff *skb) -{ - struct netpoll_info *npinfo = rcu_dereference_bh(skb->dev->npinfo); - - return npinfo && netpoll_rx_processing(npinfo); -} - -static inline bool netpoll_rx(struct sk_buff *skb) -{ - struct netpoll_info *npinfo; - unsigned long flags; - bool ret = false; - - local_irq_save(flags); - - if (!netpoll_rx_on(skb)) - goto out; - - npinfo = rcu_dereference_bh(skb->dev->npinfo); - spin_lock(&npinfo->rx_lock); - /* check rx_processing again with the lock held */ - if (netpoll_rx_processing(npinfo) && __netpoll_rx(skb, npinfo)) - ret = true; - spin_unlock(&npinfo->rx_lock); - -out: - local_irq_restore(flags); - return ret; -} - -static inline int netpoll_receive_skb(struct sk_buff *skb) -{ - if (!list_empty(&skb->dev->napi_list)) - return netpoll_rx(skb); - return 0; -} - -#else -static inline int netpoll_trap(void) -{ - return 0; -} -static inline void netpoll_set_trap(int trap) -{ -} -static inline bool netpoll_rx_processing(struct netpoll_info *npinfo) -{ - return false; -} -static inline bool netpoll_rx(struct sk_buff *skb) -{ - return false; -} -static inline bool netpoll_rx_on(struct sk_buff *skb) -{ - return false; -} -static inline int netpoll_receive_skb(struct sk_buff *skb) -{ - return 0; -} -#endif - #ifdef CONFIG_NETPOLL static inline void *netpoll_poll_lock(struct napi_struct *napi) { diff --git a/net/core/dev.c b/net/core/dev.c index 587f9fb85d73..55f8e64c03a2 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -3231,10 +3231,6 @@ static int netif_rx_internal(struct sk_buff *skb) { int ret; - /* if netpoll wants it, pretend we never saw it */ - if (netpoll_rx(skb)) - return NET_RX_DROP; - net_timestamp_check(netdev_tstamp_prequeue, skb); trace_netif_rx(skb); @@ -3520,10 +3516,6 @@ static int __netif_receive_skb_core(struct sk_buff *skb, bool pfmemalloc) trace_netif_receive_skb(skb); - /* if we've gotten here through NAPI, check netpoll */ - if (netpoll_receive_skb(skb)) - goto out; - orig_dev = skb->dev; skb_reset_network_header(skb); @@ -3650,7 +3642,6 @@ drop: unlock: rcu_read_unlock(); -out: return ret; } @@ -3875,7 +3866,7 @@ static enum gro_result dev_gro_receive(struct napi_struct *napi, struct sk_buff int same_flow; enum gro_result ret; - if (!(skb->dev->features & NETIF_F_GRO) || netpoll_rx_on(skb)) + if (!(skb->dev->features & NETIF_F_GRO)) goto normal; if (skb_is_gso(skb) || skb_has_frag_list(skb)) diff --git a/net/core/netpoll.c b/net/core/netpoll.c index eed8b1d2d302..7291dde93469 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -46,11 +46,6 @@ static struct sk_buff_head skb_pool; -#ifdef CONFIG_NETPOLL_TRAP -static atomic_t trapped; -static void netpoll_neigh_reply(struct sk_buff *skb, struct netpoll_info *npinfo); -#endif - DEFINE_STATIC_SRCU(netpoll_srcu); #define USEC_PER_POLL 50 @@ -109,27 +104,6 @@ static void queue_process(struct work_struct *work) } } -#ifdef CONFIG_NETPOLL_TRAP -static __sum16 checksum_udp(struct sk_buff *skb, struct udphdr *uh, - unsigned short ulen, __be32 saddr, __be32 daddr) -{ - __wsum psum; - - if (uh->check == 0 || skb_csum_unnecessary(skb)) - return 0; - - psum = csum_tcpudp_nofold(saddr, daddr, ulen, IPPROTO_UDP, 0); - - if (skb->ip_summed == CHECKSUM_COMPLETE && - !csum_fold(csum_add(psum, skb->csum))) - return 0; - - skb->csum = psum; - - return __skb_checksum_complete(skb); -} -#endif /* CONFIG_NETPOLL_TRAP */ - /* * Check whether delayed processing was scheduled for our NIC. If so, * we attempt to grab the poll lock and use ->poll() to pump the card. @@ -140,11 +114,6 @@ static __sum16 checksum_udp(struct sk_buff *skb, struct udphdr *uh, * trylock here and interrupts are already disabled in the softirq * case. Further, we test the poll_owner to avoid recursion on UP * systems where the lock doesn't exist. - * - * In cases where there is bi-directional communications, reading only - * one message at a time can lead to packets being dropped by the - * network adapter, forcing superfluous retries and possibly timeouts. - * Thus, we set our budget to greater than 1. */ static int poll_one_napi(struct napi_struct *napi, int budget) { @@ -181,38 +150,11 @@ static void poll_napi(struct net_device *dev, int budget) } } -#ifdef CONFIG_NETPOLL_TRAP -static void service_neigh_queue(struct net_device *dev, - struct netpoll_info *npi) -{ - struct sk_buff *skb; - if (dev->flags & IFF_SLAVE) { - struct net_device *bond_dev; - struct netpoll_info *bond_ni; - - bond_dev = netdev_master_upper_dev_get_rcu(dev); - bond_ni = rcu_dereference_bh(bond_dev->npinfo); - while ((skb = skb_dequeue(&npi->neigh_tx))) { - skb->dev = bond_dev; - skb_queue_tail(&bond_ni->neigh_tx, skb); - } - } - while ((skb = skb_dequeue(&npi->neigh_tx))) - netpoll_neigh_reply(skb, npi); -} -#else /* !CONFIG_NETPOLL_TRAP */ -static inline void service_neigh_queue(struct net_device *dev, - struct netpoll_info *npi) -{ -} -#endif /* CONFIG_NETPOLL_TRAP */ - static void netpoll_poll_dev(struct net_device *dev) { const struct net_device_ops *ops; struct netpoll_info *ni = rcu_dereference_bh(dev->npinfo); - bool rx_processing = netpoll_rx_processing(ni); - int budget = rx_processing? 16 : 0; + int budget = 0; /* Don't do any rx activity if the dev_lock mutex is held * the dev_open/close paths use this to block netpoll activity @@ -226,9 +168,6 @@ static void netpoll_poll_dev(struct net_device *dev) return; } - if (rx_processing) - netpoll_set_trap(1); - ops = dev->netdev_ops; if (!ops->ndo_poll_controller) { up(&ni->dev_lock); @@ -240,13 +179,8 @@ static void netpoll_poll_dev(struct net_device *dev) poll_napi(dev, budget); - if (rx_processing) - netpoll_set_trap(0); - up(&ni->dev_lock); - service_neigh_queue(dev, ni); - zap_completion_queue(); } @@ -531,434 +465,6 @@ void netpoll_send_udp(struct netpoll *np, const char *msg, int len) } EXPORT_SYMBOL(netpoll_send_udp); -#ifdef CONFIG_NETPOLL_TRAP -static void netpoll_neigh_reply(struct sk_buff *skb, struct netpoll_info *npinfo) -{ - int size, type = ARPOP_REPLY; - __be32 sip, tip; - unsigned char *sha; - struct sk_buff *send_skb; - struct netpoll *np, *tmp; - unsigned long flags; - int hlen, tlen; - int hits = 0, proto; - - if (!netpoll_rx_processing(npinfo)) - return; - - /* Before checking the packet, we do some early - inspection whether this is interesting at all */ - spin_lock_irqsave(&npinfo->rx_lock, flags); - list_for_each_entry_safe(np, tmp, &npinfo->rx_np, rx) { - if (np->dev == skb->dev) - hits++; - } - spin_unlock_irqrestore(&npinfo->rx_lock, flags); - - /* No netpoll struct is using this dev */ - if (!hits) - return; - - proto = ntohs(eth_hdr(skb)->h_proto); - if (proto == ETH_P_ARP) { - struct arphdr *arp; - unsigned char *arp_ptr; - /* No arp on this interface */ - if (skb->dev->flags & IFF_NOARP) - return; - - if (!pskb_may_pull(skb, arp_hdr_len(skb->dev))) - return; - - skb_reset_network_header(skb); - skb_reset_transport_header(skb); - arp = arp_hdr(skb); - - if ((arp->ar_hrd != htons(ARPHRD_ETHER) && - arp->ar_hrd != htons(ARPHRD_IEEE802)) || - arp->ar_pro != htons(ETH_P_IP) || - arp->ar_op != htons(ARPOP_REQUEST)) - return; - - arp_ptr = (unsigned char *)(arp+1); - /* save the location of the src hw addr */ - sha = arp_ptr; - arp_ptr += skb->dev->addr_len; - memcpy(&sip, arp_ptr, 4); - arp_ptr += 4; - /* If we actually cared about dst hw addr, - it would get copied here */ - arp_ptr += skb->dev->addr_len; - memcpy(&tip, arp_ptr, 4); - - /* Should we ignore arp? */ - if (ipv4_is_loopback(tip) || ipv4_is_multicast(tip)) - return; - - size = arp_hdr_len(skb->dev); - - spin_lock_irqsave(&npinfo->rx_lock, flags); - list_for_each_entry_safe(np, tmp, &npinfo->rx_np, rx) { - if (tip != np->local_ip.ip) - continue; - - hlen = LL_RESERVED_SPACE(np->dev); - tlen = np->dev->needed_tailroom; - send_skb = find_skb(np, size + hlen + tlen, hlen); - if (!send_skb) - continue; - - skb_reset_network_header(send_skb); - arp = (struct arphdr *) skb_put(send_skb, size); - send_skb->dev = skb->dev; - send_skb->protocol = htons(ETH_P_ARP); - - /* Fill the device header for the ARP frame */ - if (dev_hard_header(send_skb, skb->dev, ETH_P_ARP, - sha, np->dev->dev_addr, - send_skb->len) < 0) { - kfree_skb(send_skb); - continue; - } - - /* - * Fill out the arp protocol part. - * - * we only support ethernet device type, - * which (according to RFC 1390) should - * always equal 1 (Ethernet). - */ - - arp->ar_hrd = htons(np->dev->type); - arp->ar_pro = htons(ETH_P_IP); - arp->ar_hln = np->dev->addr_len; - arp->ar_pln = 4; - arp->ar_op = htons(type); - - arp_ptr = (unsigned char *)(arp + 1); - memcpy(arp_ptr, np->dev->dev_addr, np->dev->addr_len); - arp_ptr += np->dev->addr_len; - memcpy(arp_ptr, &tip, 4); - arp_ptr += 4; - memcpy(arp_ptr, sha, np->dev->addr_len); - arp_ptr += np->dev->addr_len; - memcpy(arp_ptr, &sip, 4); - - netpoll_send_skb(np, send_skb); - - /* If there are several rx_skb_hooks for the same - * address we're fine by sending a single reply - */ - break; - } - spin_unlock_irqrestore(&npinfo->rx_lock, flags); - } else if( proto == ETH_P_IPV6) { -#if IS_ENABLED(CONFIG_IPV6) - struct nd_msg *msg; - u8 *lladdr = NULL; - struct ipv6hdr *hdr; - struct icmp6hdr *icmp6h; - const struct in6_addr *saddr; - const struct in6_addr *daddr; - struct inet6_dev *in6_dev = NULL; - struct in6_addr *target; - - in6_dev = in6_dev_get(skb->dev); - if (!in6_dev || !in6_dev->cnf.accept_ra) - return; - - if (!pskb_may_pull(skb, skb->len)) - return; - - msg = (struct nd_msg *)skb_transport_header(skb); - - __skb_push(skb, skb->data - skb_transport_header(skb)); - - if (ipv6_hdr(skb)->hop_limit != 255) - return; - if (msg->icmph.icmp6_code != 0) - return; - if (msg->icmph.icmp6_type != NDISC_NEIGHBOUR_SOLICITATION) - return; - - saddr = &ipv6_hdr(skb)->saddr; - daddr = &ipv6_hdr(skb)->daddr; - - size = sizeof(struct icmp6hdr) + sizeof(struct in6_addr); - - spin_lock_irqsave(&npinfo->rx_lock, flags); - list_for_each_entry_safe(np, tmp, &npinfo->rx_np, rx) { - if (!ipv6_addr_equal(daddr, &np->local_ip.in6)) - continue; - - hlen = LL_RESERVED_SPACE(np->dev); - tlen = np->dev->needed_tailroom; - send_skb = find_skb(np, size + hlen + tlen, hlen); - if (!send_skb) - continue; - - send_skb->protocol = htons(ETH_P_IPV6); - send_skb->dev = skb->dev; - - skb_reset_network_header(send_skb); - hdr = (struct ipv6hdr *) skb_put(send_skb, sizeof(struct ipv6hdr)); - *(__be32*)hdr = htonl(0x60000000); - hdr->payload_len = htons(size); - hdr->nexthdr = IPPROTO_ICMPV6; - hdr->hop_limit = 255; - hdr->saddr = *saddr; - hdr->daddr = *daddr; - - icmp6h = (struct icmp6hdr *) skb_put(send_skb, sizeof(struct icmp6hdr)); - icmp6h->icmp6_type = NDISC_NEIGHBOUR_ADVERTISEMENT; - icmp6h->icmp6_router = 0; - icmp6h->icmp6_solicited = 1; - - target = (struct in6_addr *) skb_put(send_skb, sizeof(struct in6_addr)); - *target = msg->target; - icmp6h->icmp6_cksum = csum_ipv6_magic(saddr, daddr, size, - IPPROTO_ICMPV6, - csum_partial(icmp6h, - size, 0)); - - if (dev_hard_header(send_skb, skb->dev, ETH_P_IPV6, - lladdr, np->dev->dev_addr, - send_skb->len) < 0) { - kfree_skb(send_skb); - continue; - } - - netpoll_send_skb(np, send_skb); - - /* If there are several rx_skb_hooks for the same - * address, we're fine by sending a single reply - */ - break; - } - spin_unlock_irqrestore(&npinfo->rx_lock, flags); -#endif - } -} - -static bool pkt_is_ns(struct sk_buff *skb) -{ - struct nd_msg *msg; - struct ipv6hdr *hdr; - - if (skb->protocol != htons(ETH_P_ARP)) - return false; - if (!pskb_may_pull(skb, sizeof(struct ipv6hdr) + sizeof(struct nd_msg))) - return false; - - msg = (struct nd_msg *)skb_transport_header(skb); - __skb_push(skb, skb->data - skb_transport_header(skb)); - hdr = ipv6_hdr(skb); - - if (hdr->nexthdr != IPPROTO_ICMPV6) - return false; - if (hdr->hop_limit != 255) - return false; - if (msg->icmph.icmp6_code != 0) - return false; - if (msg->icmph.icmp6_type != NDISC_NEIGHBOUR_SOLICITATION) - return false; - - return true; -} - -int __netpoll_rx(struct sk_buff *skb, struct netpoll_info *npinfo) -{ - int proto, len, ulen, data_len; - int hits = 0, offset; - const struct iphdr *iph; - struct udphdr *uh; - struct netpoll *np, *tmp; - uint16_t source; - - if (!netpoll_rx_processing(npinfo)) - goto out; - - if (skb->dev->type != ARPHRD_ETHER) - goto out; - - /* check if netpoll clients need ARP */ - if (skb->protocol == htons(ETH_P_ARP) && netpoll_trap()) { - skb_queue_tail(&npinfo->neigh_tx, skb); - return 1; - } else if (pkt_is_ns(skb) && netpoll_trap()) { - skb_queue_tail(&npinfo->neigh_tx, skb); - return 1; - } - - if (skb->protocol == cpu_to_be16(ETH_P_8021Q)) { - skb = vlan_untag(skb); - if (unlikely(!skb)) - goto out; - } - - proto = ntohs(eth_hdr(skb)->h_proto); - if (proto != ETH_P_IP && proto != ETH_P_IPV6) - goto out; - if (skb->pkt_type == PACKET_OTHERHOST) - goto out; - if (skb_shared(skb)) - goto out; - - if (proto == ETH_P_IP) { - if (!pskb_may_pull(skb, sizeof(struct iphdr))) - goto out; - iph = (struct iphdr *)skb->data; - if (iph->ihl < 5 || iph->version != 4) - goto out; - if (!pskb_may_pull(skb, iph->ihl*4)) - goto out; - iph = (struct iphdr *)skb->data; - if (ip_fast_csum((u8 *)iph, iph->ihl) != 0) - goto out; - - len = ntohs(iph->tot_len); - if (skb->len < len || len < iph->ihl*4) - goto out; - - /* - * Our transport medium may have padded the buffer out. - * Now We trim to the true length of the frame. - */ - if (pskb_trim_rcsum(skb, len)) - goto out; - - iph = (struct iphdr *)skb->data; - if (iph->protocol != IPPROTO_UDP) - goto out; - - len -= iph->ihl*4; - uh = (struct udphdr *)(((char *)iph) + iph->ihl*4); - offset = (unsigned char *)(uh + 1) - skb->data; - ulen = ntohs(uh->len); - data_len = skb->len - offset; - source = ntohs(uh->source); - - if (ulen != len) - goto out; - if (checksum_udp(skb, uh, ulen, iph->saddr, iph->daddr)) - goto out; - list_for_each_entry_safe(np, tmp, &npinfo->rx_np, rx) { - if (np->local_ip.ip && np->local_ip.ip != iph->daddr) - continue; - if (np->remote_ip.ip && np->remote_ip.ip != iph->saddr) - continue; - if (np->local_port && np->local_port != ntohs(uh->dest)) - continue; - - np->rx_skb_hook(np, source, skb, offset, data_len); - hits++; - } - } else { -#if IS_ENABLED(CONFIG_IPV6) - const struct ipv6hdr *ip6h; - - if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) - goto out; - ip6h = (struct ipv6hdr *)skb->data; - if (ip6h->version != 6) - goto out; - len = ntohs(ip6h->payload_len); - if (!len) - goto out; - if (len + sizeof(struct ipv6hdr) > skb->len) - goto out; - if (pskb_trim_rcsum(skb, len + sizeof(struct ipv6hdr))) - goto out; - ip6h = ipv6_hdr(skb); - if (!pskb_may_pull(skb, sizeof(struct udphdr))) - goto out; - uh = udp_hdr(skb); - offset = (unsigned char *)(uh + 1) - skb->data; - ulen = ntohs(uh->len); - data_len = skb->len - offset; - source = ntohs(uh->source); - if (ulen != skb->len) - goto out; - if (udp6_csum_init(skb, uh, IPPROTO_UDP)) - goto out; - list_for_each_entry_safe(np, tmp, &npinfo->rx_np, rx) { - if (!ipv6_addr_equal(&np->local_ip.in6, &ip6h->daddr)) - continue; - if (!ipv6_addr_equal(&np->remote_ip.in6, &ip6h->saddr)) - continue; - if (np->local_port && np->local_port != ntohs(uh->dest)) - continue; - - np->rx_skb_hook(np, source, skb, offset, data_len); - hits++; - } -#endif - } - - if (!hits) - goto out; - - kfree_skb(skb); - return 1; - -out: - if (netpoll_trap()) { - kfree_skb(skb); - return 1; - } - - return 0; -} - -static void netpoll_trap_setup_info(struct netpoll_info *npinfo) -{ - INIT_LIST_HEAD(&npinfo->rx_np); - spin_lock_init(&npinfo->rx_lock); - skb_queue_head_init(&npinfo->neigh_tx); -} - -static void netpoll_trap_cleanup_info(struct netpoll_info *npinfo) -{ - skb_queue_purge(&npinfo->neigh_tx); -} - -static void netpoll_trap_setup(struct netpoll *np, struct netpoll_info *npinfo) -{ - unsigned long flags; - if (np->rx_skb_hook) { - spin_lock_irqsave(&npinfo->rx_lock, flags); - list_add_tail(&np->rx, &npinfo->rx_np); - spin_unlock_irqrestore(&npinfo->rx_lock, flags); - } -} - -static void netpoll_trap_cleanup(struct netpoll *np, struct netpoll_info *npinfo) -{ - unsigned long flags; - if (!list_empty(&npinfo->rx_np)) { - spin_lock_irqsave(&npinfo->rx_lock, flags); - list_del(&np->rx); - spin_unlock_irqrestore(&npinfo->rx_lock, flags); - } -} - -#else /* !CONFIG_NETPOLL_TRAP */ -static inline void netpoll_trap_setup_info(struct netpoll_info *npinfo) -{ -} -static inline void netpoll_trap_cleanup_info(struct netpoll_info *npinfo) -{ -} -static inline -void netpoll_trap_setup(struct netpoll *np, struct netpoll_info *npinfo) -{ -} -static inline -void netpoll_trap_cleanup(struct netpoll *np, struct netpoll_info *npinfo) -{ -} -#endif /* CONFIG_NETPOLL_TRAP */ - void netpoll_print_options(struct netpoll *np) { np_info(np, "local port %d\n", np->local_port); @@ -1103,8 +609,6 @@ int __netpoll_setup(struct netpoll *np, struct net_device *ndev, gfp_t gfp) goto out; } - netpoll_trap_setup_info(npinfo); - sema_init(&npinfo->dev_lock, 1); skb_queue_head_init(&npinfo->txq); INIT_DELAYED_WORK(&npinfo->tx_work, queue_process); @@ -1124,8 +628,6 @@ int __netpoll_setup(struct netpoll *np, struct net_device *ndev, gfp_t gfp) npinfo->netpoll = np; - netpoll_trap_setup(np, npinfo); - /* last thing to do is link it to the net device structure */ rcu_assign_pointer(ndev->npinfo, npinfo); @@ -1274,7 +776,6 @@ static void rcu_cleanup_netpoll_info(struct rcu_head *rcu_head) struct netpoll_info *npinfo = container_of(rcu_head, struct netpoll_info, rcu); - netpoll_trap_cleanup_info(npinfo); skb_queue_purge(&npinfo->txq); /* we can't call cancel_delayed_work_sync here, as we are in softirq */ @@ -1299,8 +800,6 @@ void __netpoll_cleanup(struct netpoll *np) if (!npinfo) return; - netpoll_trap_cleanup(np, npinfo); - synchronize_srcu(&netpoll_srcu); if (atomic_dec_and_test(&npinfo->refcnt)) { @@ -1344,20 +843,3 @@ out: rtnl_unlock(); } EXPORT_SYMBOL(netpoll_cleanup); - -#ifdef CONFIG_NETPOLL_TRAP -int netpoll_trap(void) -{ - return atomic_read(&trapped); -} -EXPORT_SYMBOL(netpoll_trap); - -void netpoll_set_trap(int trap) -{ - if (trap) - atomic_inc(&trapped); - else - atomic_dec(&trapped); -} -EXPORT_SYMBOL(netpoll_set_trap); -#endif /* CONFIG_NETPOLL_TRAP */ -- cgit v1.2.3 From a8779ec1c5e60548b7b661a8d74a8cecf7775690 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Thu, 27 Mar 2014 15:36:38 -0700 Subject: netpoll: Remove gfp parameter from __netpoll_setup The gfp parameter was added in: commit 47be03a28cc6c80e3aa2b3e8ed6d960ff0c5c0af Author: Amerigo Wang Date: Fri Aug 10 01:24:37 2012 +0000 netpoll: use GFP_ATOMIC in slave_enable_netpoll() and __netpoll_setup() slave_enable_netpoll() and __netpoll_setup() may be called with read_lock() held, so should use GFP_ATOMIC to allocate memory. Eric suggested to pass gfp flags to __netpoll_setup(). Cc: Eric Dumazet Cc: "David S. Miller" Reported-by: Dan Carpenter Signed-off-by: Eric Dumazet Signed-off-by: Cong Wang Signed-off-by: David S. Miller The reason for the gfp parameter was removed in: commit c4cdef9b7183159c23c7302aaf270d64c549f557 Author: dingtianhong Date: Tue Jul 23 15:25:27 2013 +0800 bonding: don't call slave_xxx_netpoll under spinlocks The slave_xxx_netpoll will call synchronize_rcu_bh(), so the function may schedule and sleep, it should't be called under spinlocks. bond_netpoll_setup() and bond_netpoll_cleanup() are always protected by rtnl lock, it is no need to take the read lock, as the slave list couldn't be changed outside rtnl lock. Signed-off-by: Ding Tianhong Cc: Jay Vosburgh Cc: Andy Gospodarek Signed-off-by: David S. Miller Nothing else that calls __netpoll_setup or ndo_netpoll_setup requires a gfp paramter, so remove the gfp parameter from both of these functions making the code clearer. Signed-off-by: "Eric W. Biederman" Signed-off-by: David S. Miller --- drivers/net/bonding/bond_main.c | 6 +++--- drivers/net/team/team.c | 16 +++++++--------- include/linux/netdevice.h | 3 +-- include/linux/netpoll.h | 2 +- net/8021q/vlan_dev.c | 7 +++---- net/bridge/br_device.c | 15 +++++++-------- net/bridge/br_if.c | 2 +- net/bridge/br_private.h | 4 ++-- net/core/netpoll.c | 8 ++++---- 9 files changed, 29 insertions(+), 34 deletions(-) (limited to 'include/linux/netpoll.h') diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 5be34b72a048..95a6ca7d9e51 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -922,12 +922,12 @@ static inline int slave_enable_netpoll(struct slave *slave) struct netpoll *np; int err = 0; - np = kzalloc(sizeof(*np), GFP_ATOMIC); + np = kzalloc(sizeof(*np), GFP_KERNEL); err = -ENOMEM; if (!np) goto out; - err = __netpoll_setup(np, slave->dev, GFP_ATOMIC); + err = __netpoll_setup(np, slave->dev); if (err) { kfree(np); goto out; @@ -962,7 +962,7 @@ static void bond_netpoll_cleanup(struct net_device *bond_dev) slave_disable_netpoll(slave); } -static int bond_netpoll_setup(struct net_device *dev, struct netpoll_info *ni, gfp_t gfp) +static int bond_netpoll_setup(struct net_device *dev, struct netpoll_info *ni) { struct bonding *bond = netdev_priv(dev); struct list_head *iter; diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c index 2b1a1d61072c..33008c1d1d67 100644 --- a/drivers/net/team/team.c +++ b/drivers/net/team/team.c @@ -1031,8 +1031,7 @@ static void team_port_leave(struct team *team, struct team_port *port) } #ifdef CONFIG_NET_POLL_CONTROLLER -static int team_port_enable_netpoll(struct team *team, struct team_port *port, - gfp_t gfp) +static int team_port_enable_netpoll(struct team *team, struct team_port *port) { struct netpoll *np; int err; @@ -1040,11 +1039,11 @@ static int team_port_enable_netpoll(struct team *team, struct team_port *port, if (!team->dev->npinfo) return 0; - np = kzalloc(sizeof(*np), gfp); + np = kzalloc(sizeof(*np), GFP_KERNEL); if (!np) return -ENOMEM; - err = __netpoll_setup(np, port->dev, gfp); + err = __netpoll_setup(np, port->dev); if (err) { kfree(np); return err; @@ -1067,8 +1066,7 @@ static void team_port_disable_netpoll(struct team_port *port) kfree(np); } #else -static int team_port_enable_netpoll(struct team *team, struct team_port *port, - gfp_t gfp) +static int team_port_enable_netpoll(struct team *team, struct team_port *port) { return 0; } @@ -1156,7 +1154,7 @@ static int team_port_add(struct team *team, struct net_device *port_dev) goto err_vids_add; } - err = team_port_enable_netpoll(team, port, GFP_KERNEL); + err = team_port_enable_netpoll(team, port); if (err) { netdev_err(dev, "Failed to enable netpoll on device %s\n", portname); @@ -1850,7 +1848,7 @@ static void team_netpoll_cleanup(struct net_device *dev) } static int team_netpoll_setup(struct net_device *dev, - struct netpoll_info *npifo, gfp_t gfp) + struct netpoll_info *npifo) { struct team *team = netdev_priv(dev); struct team_port *port; @@ -1858,7 +1856,7 @@ static int team_netpoll_setup(struct net_device *dev, mutex_lock(&team->lock); list_for_each_entry(port, &team->port_list, list) { - err = team_port_enable_netpoll(team, port, gfp); + err = team_port_enable_netpoll(team, port); if (err) { __team_netpoll_cleanup(team); break; diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 159c7e7945f8..0d8c8718980a 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -1037,8 +1037,7 @@ struct net_device_ops { #ifdef CONFIG_NET_POLL_CONTROLLER void (*ndo_poll_controller)(struct net_device *dev); int (*ndo_netpoll_setup)(struct net_device *dev, - struct netpoll_info *info, - gfp_t gfp); + struct netpoll_info *info); void (*ndo_netpoll_cleanup)(struct net_device *dev); #endif #ifdef CONFIG_NET_RX_BUSY_POLL diff --git a/include/linux/netpoll.h b/include/linux/netpoll.h index 1b475a5a7239..893b9e66060e 100644 --- a/include/linux/netpoll.h +++ b/include/linux/netpoll.h @@ -57,7 +57,7 @@ static inline void netpoll_rx_enable(struct net_device *dev) { return; } void netpoll_send_udp(struct netpoll *np, const char *msg, int len); void netpoll_print_options(struct netpoll *np); int netpoll_parse_options(struct netpoll *np, char *opt); -int __netpoll_setup(struct netpoll *np, struct net_device *ndev, gfp_t gfp); +int __netpoll_setup(struct netpoll *np, struct net_device *ndev); int netpoll_setup(struct netpoll *np); void __netpoll_cleanup(struct netpoll *np); void __netpoll_free_async(struct netpoll *np); diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index 4f3e9073cb49..a78bebeca4d9 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c @@ -707,20 +707,19 @@ static void vlan_dev_poll_controller(struct net_device *dev) return; } -static int vlan_dev_netpoll_setup(struct net_device *dev, struct netpoll_info *npinfo, - gfp_t gfp) +static int vlan_dev_netpoll_setup(struct net_device *dev, struct netpoll_info *npinfo) { struct vlan_dev_priv *vlan = vlan_dev_priv(dev); struct net_device *real_dev = vlan->real_dev; struct netpoll *netpoll; int err = 0; - netpoll = kzalloc(sizeof(*netpoll), gfp); + netpoll = kzalloc(sizeof(*netpoll), GFP_KERNEL); err = -ENOMEM; if (!netpoll) goto out; - err = __netpoll_setup(netpoll, real_dev, gfp); + err = __netpoll_setup(netpoll, real_dev); if (err) { kfree(netpoll); goto out; diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c index f2a08477e0f5..0dd01a05bd59 100644 --- a/net/bridge/br_device.c +++ b/net/bridge/br_device.c @@ -218,16 +218,16 @@ static void br_netpoll_cleanup(struct net_device *dev) br_netpoll_disable(p); } -static int __br_netpoll_enable(struct net_bridge_port *p, gfp_t gfp) +static int __br_netpoll_enable(struct net_bridge_port *p) { struct netpoll *np; int err; - np = kzalloc(sizeof(*p->np), gfp); + np = kzalloc(sizeof(*p->np), GFP_KERNEL); if (!np) return -ENOMEM; - err = __netpoll_setup(np, p->dev, gfp); + err = __netpoll_setup(np, p->dev); if (err) { kfree(np); return err; @@ -237,16 +237,15 @@ static int __br_netpoll_enable(struct net_bridge_port *p, gfp_t gfp) return err; } -int br_netpoll_enable(struct net_bridge_port *p, gfp_t gfp) +int br_netpoll_enable(struct net_bridge_port *p) { if (!p->br->dev->npinfo) return 0; - return __br_netpoll_enable(p, gfp); + return __br_netpoll_enable(p); } -static int br_netpoll_setup(struct net_device *dev, struct netpoll_info *ni, - gfp_t gfp) +static int br_netpoll_setup(struct net_device *dev, struct netpoll_info *ni) { struct net_bridge *br = netdev_priv(dev); struct net_bridge_port *p; @@ -255,7 +254,7 @@ static int br_netpoll_setup(struct net_device *dev, struct netpoll_info *ni, list_for_each_entry(p, &br->port_list, list) { if (!p->dev) continue; - err = __br_netpoll_enable(p, gfp); + err = __br_netpoll_enable(p); if (err) goto fail; } diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index 54d207d3a31c..5262b8617eb9 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c @@ -366,7 +366,7 @@ int br_add_if(struct net_bridge *br, struct net_device *dev) if (err) goto err2; - err = br_netpoll_enable(p, GFP_KERNEL); + err = br_netpoll_enable(p); if (err) goto err3; diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index e1ca1dc916a4..06811d79f89f 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -349,7 +349,7 @@ static inline void br_netpoll_send_skb(const struct net_bridge_port *p, netpoll_send_skb(np, skb); } -int br_netpoll_enable(struct net_bridge_port *p, gfp_t gfp); +int br_netpoll_enable(struct net_bridge_port *p); void br_netpoll_disable(struct net_bridge_port *p); #else static inline void br_netpoll_send_skb(const struct net_bridge_port *p, @@ -357,7 +357,7 @@ static inline void br_netpoll_send_skb(const struct net_bridge_port *p, { } -static inline int br_netpoll_enable(struct net_bridge_port *p, gfp_t gfp) +static inline int br_netpoll_enable(struct net_bridge_port *p) { return 0; } diff --git a/net/core/netpoll.c b/net/core/netpoll.c index 41c4e9ce1141..2c6379da295c 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -584,7 +584,7 @@ int netpoll_parse_options(struct netpoll *np, char *opt) } EXPORT_SYMBOL(netpoll_parse_options); -int __netpoll_setup(struct netpoll *np, struct net_device *ndev, gfp_t gfp) +int __netpoll_setup(struct netpoll *np, struct net_device *ndev) { struct netpoll_info *npinfo; const struct net_device_ops *ops; @@ -603,7 +603,7 @@ int __netpoll_setup(struct netpoll *np, struct net_device *ndev, gfp_t gfp) } if (!ndev->npinfo) { - npinfo = kmalloc(sizeof(*npinfo), gfp); + npinfo = kmalloc(sizeof(*npinfo), GFP_KERNEL); if (!npinfo) { err = -ENOMEM; goto out; @@ -617,7 +617,7 @@ int __netpoll_setup(struct netpoll *np, struct net_device *ndev, gfp_t gfp) ops = np->dev->netdev_ops; if (ops->ndo_netpoll_setup) { - err = ops->ndo_netpoll_setup(ndev, npinfo, gfp); + err = ops->ndo_netpoll_setup(ndev, npinfo); if (err) goto free_npinfo; } @@ -749,7 +749,7 @@ int netpoll_setup(struct netpoll *np) /* fill up the skb queue */ refill_skbs(); - err = __netpoll_setup(np, ndev, GFP_KERNEL); + err = __netpoll_setup(np, ndev); if (err) goto put; -- cgit v1.2.3 From 66b5552fc2dfbaa6445b1bdadd10c9305ce261bd Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Thu, 27 Mar 2014 15:39:03 -0700 Subject: netpoll: Rename netpoll_rx_enable/disable to netpoll_poll_disable/enable The netpoll_rx_enable and netpoll_rx_disable functions have always controlled polling the network drivers transmit and receive queues. Rename them to netpoll_poll_enable and netpoll_poll_disable to make their functionality clear. Signed-off-by: "Eric W. Biederman" Signed-off-by: David S. Miller --- include/linux/netpoll.h | 8 ++++---- net/core/dev.c | 8 ++++---- net/core/netpoll.c | 8 ++++---- 3 files changed, 12 insertions(+), 12 deletions(-) (limited to 'include/linux/netpoll.h') diff --git a/include/linux/netpoll.h b/include/linux/netpoll.h index 893b9e66060e..b25ee9ffdbe6 100644 --- a/include/linux/netpoll.h +++ b/include/linux/netpoll.h @@ -47,11 +47,11 @@ struct netpoll_info { }; #ifdef CONFIG_NETPOLL -extern void netpoll_rx_disable(struct net_device *dev); -extern void netpoll_rx_enable(struct net_device *dev); +extern void netpoll_poll_disable(struct net_device *dev); +extern void netpoll_poll_enable(struct net_device *dev); #else -static inline void netpoll_rx_disable(struct net_device *dev) { return; } -static inline void netpoll_rx_enable(struct net_device *dev) { return; } +static inline void netpoll_poll_disable(struct net_device *dev) { return; } +static inline void netpoll_poll_enable(struct net_device *dev) { return; } #endif void netpoll_send_udp(struct netpoll *np, const char *msg, int len); diff --git a/net/core/dev.c b/net/core/dev.c index 8d55fe780e3f..778b2036a9e7 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1245,7 +1245,7 @@ static int __dev_open(struct net_device *dev) * If we don't do this there is a chance ndo_poll_controller * or ndo_poll may be running while we open the device */ - netpoll_rx_disable(dev); + netpoll_poll_disable(dev); ret = call_netdevice_notifiers(NETDEV_PRE_UP, dev); ret = notifier_to_errno(ret); @@ -1260,7 +1260,7 @@ static int __dev_open(struct net_device *dev) if (!ret && ops->ndo_open) ret = ops->ndo_open(dev); - netpoll_rx_enable(dev); + netpoll_poll_enable(dev); if (ret) clear_bit(__LINK_STATE_START, &dev->state); @@ -1314,7 +1314,7 @@ static int __dev_close_many(struct list_head *head) list_for_each_entry(dev, head, close_list) { /* Temporarily disable netpoll until the interface is down */ - netpoll_rx_disable(dev); + netpoll_poll_disable(dev); call_netdevice_notifiers(NETDEV_GOING_DOWN, dev); @@ -1346,7 +1346,7 @@ static int __dev_close_many(struct list_head *head) dev->flags &= ~IFF_UP; net_dmaengine_put(); - netpoll_rx_enable(dev); + netpoll_poll_enable(dev); } return 0; diff --git a/net/core/netpoll.c b/net/core/netpoll.c index e2492d176ae7..9fd88875faff 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -214,7 +214,7 @@ static void netpoll_poll_dev(struct net_device *dev) zap_completion_queue(); } -void netpoll_rx_disable(struct net_device *dev) +void netpoll_poll_disable(struct net_device *dev) { struct netpoll_info *ni; int idx; @@ -225,9 +225,9 @@ void netpoll_rx_disable(struct net_device *dev) down(&ni->dev_lock); srcu_read_unlock(&netpoll_srcu, idx); } -EXPORT_SYMBOL(netpoll_rx_disable); +EXPORT_SYMBOL(netpoll_poll_disable); -void netpoll_rx_enable(struct net_device *dev) +void netpoll_poll_enable(struct net_device *dev) { struct netpoll_info *ni; rcu_read_lock(); @@ -236,7 +236,7 @@ void netpoll_rx_enable(struct net_device *dev) up(&ni->dev_lock); rcu_read_unlock(); } -EXPORT_SYMBOL(netpoll_rx_enable); +EXPORT_SYMBOL(netpoll_poll_enable); static void refill_skbs(void) { -- cgit v1.2.3