* [v4 Patch 2/3] bridge: make bridge support netpoll
2010-04-27 7:55 [v4 Patch 1/3] netpoll: add generic support for bridge and bonding devices Amerigo Wang
@ 2010-04-27 7:55 ` Amerigo Wang
2010-04-27 22:23 ` David Miller
2010-04-27 7:56 ` [v4 Patch 3/3] bonding: make bonding " Amerigo Wang
` (2 subsequent siblings)
3 siblings, 1 reply; 9+ messages in thread
From: Amerigo Wang @ 2010-04-27 7:55 UTC (permalink / raw)
To: linux-kernel
Cc: Stephen Hemminger, netdev, bridge, Andy Gospodarek, Neil Horman,
Amerigo Wang, Jeff Moyer, Matt Mackall, bonding-devel,
Jay Vosburgh, David Miller
Based on the previous patch, make bridge support netpoll by:
1) implement the 2 methods to support netpoll for bridge;
2) modify netpoll during forwarding packets via bridge;
3) disable netpoll support of bridge when a netpoll-unabled device
is added to bridge;
4) enable netpoll support when all underlying devices support netpoll.
Cc: David Miller <davem@davemloft.net>
Cc: Neil Horman <nhorman@tuxdriver.com>
Cc: Stephen Hemminger <shemminger@linux-foundation.org>
Cc: Matt Mackall <mpm@selenic.com>
Signed-off-by: WANG Cong <amwang@redhat.com>
---
Index: linux-2.6/net/bridge/br_device.c
===================================================================
--- linux-2.6.orig/net/bridge/br_device.c
+++ linux-2.6/net/bridge/br_device.c
@@ -13,8 +13,10 @@
#include <linux/kernel.h>
#include <linux/netdevice.h>
+#include <linux/netpoll.h>
#include <linux/etherdevice.h>
#include <linux/ethtool.h>
+#include <linux/list.h>
#include <asm/uaccess.h>
#include "br_private.h"
@@ -162,6 +164,59 @@ static int br_set_tx_csum(struct net_dev
return 0;
}
+#ifdef CONFIG_NET_POLL_CONTROLLER
+bool br_devices_support_netpoll(struct net_bridge *br)
+{
+ struct net_bridge_port *p;
+ bool ret = true;
+ int count = 0;
+ unsigned long flags;
+
+ spin_lock_irqsave(&br->lock, flags);
+ list_for_each_entry(p, &br->port_list, list) {
+ count++;
+ if (p->dev->priv_flags & IFF_DISABLE_NETPOLL
+ || !p->dev->netdev_ops->ndo_poll_controller)
+ ret = false;
+ }
+ spin_unlock_irqrestore(&br->lock, flags);
+ return count != 0 && ret;
+}
+
+static void br_poll_controller(struct net_device *br_dev)
+{
+ struct netpoll *np = br_dev->npinfo->netpoll;
+
+ if (np->real_dev != br_dev)
+ netpoll_poll_dev(np->real_dev);
+}
+
+void br_netpoll_cleanup(struct net_device *br_dev)
+{
+ struct net_bridge *br = netdev_priv(br_dev);
+ struct net_bridge_port *p, *n;
+ const struct net_device_ops *ops;
+
+ br->dev->npinfo = NULL;
+ list_for_each_entry_safe(p, n, &br->port_list, list) {
+ if (p->dev) {
+ ops = p->dev->netdev_ops;
+ if (ops->ndo_netpoll_cleanup)
+ ops->ndo_netpoll_cleanup(p->dev);
+ else
+ p->dev->npinfo = NULL;
+ }
+ }
+}
+
+#else
+
+void br_netpoll_cleanup(struct net_device *br_dev)
+{
+}
+
+#endif
+
static const struct ethtool_ops br_ethtool_ops = {
.get_drvinfo = br_getinfo,
.get_link = ethtool_op_get_link,
@@ -184,6 +239,10 @@ static const struct net_device_ops br_ne
.ndo_set_multicast_list = br_dev_set_multicast_list,
.ndo_change_mtu = br_change_mtu,
.ndo_do_ioctl = br_dev_ioctl,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_netpoll_cleanup = br_netpoll_cleanup,
+ .ndo_poll_controller = br_poll_controller,
+#endif
};
void br_dev_setup(struct net_device *dev)
Index: linux-2.6/net/bridge/br_forward.c
===================================================================
--- linux-2.6.orig/net/bridge/br_forward.c
+++ linux-2.6/net/bridge/br_forward.c
@@ -15,6 +15,7 @@
#include <linux/slab.h>
#include <linux/kernel.h>
#include <linux/netdevice.h>
+#include <linux/netpoll.h>
#include <linux/skbuff.h>
#include <linux/if_vlan.h>
#include <linux/netfilter_bridge.h>
@@ -50,7 +51,13 @@ int br_dev_queue_push_xmit(struct sk_buf
else {
skb_push(skb, ETH_HLEN);
- dev_queue_xmit(skb);
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ if (unlikely(skb->dev->priv_flags & IFF_IN_NETPOLL)) {
+ netpoll_send_skb(skb->dev->npinfo->netpoll, skb);
+ skb->dev->priv_flags &= ~IFF_IN_NETPOLL;
+ } else
+#endif
+ dev_queue_xmit(skb);
}
}
@@ -66,9 +73,23 @@ int br_forward_finish(struct sk_buff *sk
static void __br_deliver(const struct net_bridge_port *to, struct sk_buff *skb)
{
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ struct net_bridge *br = to->br;
+ if (unlikely(br->dev->priv_flags & IFF_IN_NETPOLL)) {
+ struct netpoll *np;
+ to->dev->npinfo = skb->dev->npinfo;
+ np = skb->dev->npinfo->netpoll;
+ np->real_dev = np->dev = to->dev;
+ to->dev->priv_flags |= IFF_IN_NETPOLL;
+ }
+#endif
skb->dev = to->dev;
NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_OUT, skb, NULL, skb->dev,
br_forward_finish);
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ if (skb->dev->npinfo)
+ skb->dev->npinfo->netpoll->dev = br->dev;
+#endif
}
static void __br_forward(const struct net_bridge_port *to, struct sk_buff *skb)
Index: linux-2.6/net/bridge/br_if.c
===================================================================
--- linux-2.6.orig/net/bridge/br_if.c
+++ linux-2.6/net/bridge/br_if.c
@@ -13,6 +13,7 @@
#include <linux/kernel.h>
#include <linux/netdevice.h>
+#include <linux/netpoll.h>
#include <linux/ethtool.h>
#include <linux/if_arp.h>
#include <linux/module.h>
@@ -153,6 +154,14 @@ static void del_nbp(struct net_bridge_po
kobject_uevent(&p->kobj, KOBJ_REMOVE);
kobject_del(&p->kobj);
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ if (br_devices_support_netpoll(br))
+ br->dev->priv_flags &= ~IFF_DISABLE_NETPOLL;
+ if (dev->netdev_ops->ndo_netpoll_cleanup)
+ dev->netdev_ops->ndo_netpoll_cleanup(dev);
+ else
+ dev->npinfo = NULL;
+#endif
call_rcu(&p->rcu, destroy_nbp_rcu);
}
@@ -165,6 +174,8 @@ static void del_br(struct net_bridge *br
del_nbp(p);
}
+ br_netpoll_cleanup(br->dev);
+
del_timer_sync(&br->gc_timer);
br_sysfs_delbr(br->dev);
@@ -438,6 +449,20 @@ int br_add_if(struct net_bridge *br, str
kobject_uevent(&p->kobj, KOBJ_ADD);
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ if (br_devices_support_netpoll(br)) {
+ br->dev->priv_flags &= ~IFF_DISABLE_NETPOLL;
+ if (br->dev->npinfo)
+ dev->npinfo = br->dev->npinfo;
+ } else if (!(br->dev->priv_flags & IFF_DISABLE_NETPOLL)) {
+ br->dev->priv_flags |= IFF_DISABLE_NETPOLL;
+ printk(KERN_INFO "New device %s does not support netpoll\n",
+ dev->name);
+ printk(KERN_INFO "Disabling netpoll for %s\n",
+ br->dev->name);
+ }
+#endif
+
return 0;
err2:
br_fdb_delete_by_port(br, p, 1);
Index: linux-2.6/net/bridge/br_private.h
===================================================================
--- linux-2.6.orig/net/bridge/br_private.h
+++ linux-2.6/net/bridge/br_private.h
@@ -233,6 +233,8 @@ static inline int br_is_root_bridge(cons
extern void br_dev_setup(struct net_device *dev);
extern netdev_tx_t br_dev_xmit(struct sk_buff *skb,
struct net_device *dev);
+extern bool br_devices_support_netpoll(struct net_bridge *br);
+extern void br_netpoll_cleanup(struct net_device *br_dev);
/* br_fdb.c */
extern int br_fdb_init(void);
^ permalink raw reply [flat|nested] 9+ messages in thread* Re: [v4 Patch 2/3] bridge: make bridge support netpoll
2010-04-27 7:55 ` [v4 Patch 2/3] bridge: make bridge support netpoll Amerigo Wang
@ 2010-04-27 22:23 ` David Miller
0 siblings, 0 replies; 9+ messages in thread
From: David Miller @ 2010-04-27 22:23 UTC (permalink / raw)
To: amwang
Cc: linux-kernel, shemminger, netdev, bridge, gospo, nhorman, jmoyer,
mpm, bonding-devel, fubar
From: Amerigo Wang <amwang@redhat.com>
Date: Tue, 27 Apr 2010 03:55:56 -0400
> + if (p->dev->priv_flags & IFF_DISABLE_NETPOLL
> + || !p->dev->netdev_ops->ndo_poll_controller)
"||" goes on first line, and indentation on second line is incorrect.
See my comments from patch #1.
^ permalink raw reply [flat|nested] 9+ messages in thread
* [v4 Patch 3/3] bonding: make bonding support netpoll
2010-04-27 7:55 [v4 Patch 1/3] netpoll: add generic support for bridge and bonding devices Amerigo Wang
2010-04-27 7:55 ` [v4 Patch 2/3] bridge: make bridge support netpoll Amerigo Wang
@ 2010-04-27 7:56 ` Amerigo Wang
2010-04-27 22:24 ` David Miller
2010-04-27 22:22 ` [v4 Patch 1/3] netpoll: add generic support for bridge and bonding devices David Miller
2010-04-28 4:02 ` Dongdong Deng
3 siblings, 1 reply; 9+ messages in thread
From: Amerigo Wang @ 2010-04-27 7:56 UTC (permalink / raw)
To: linux-kernel
Cc: Matt Mackall, netdev, bridge, Andy Gospodarek, Neil Horman,
Amerigo Wang, Jeff Moyer, Stephen Hemminger, bonding-devel,
Jay Vosburgh, David Miller
Based on Andy's work, but I modified a lot.
Similar to the patch for bridge, this patch does:
1) implement the 2 methods to support netpoll for bonding;
2) modify netpoll during forwarding packets via bonding;
3) disable netpoll support of bonding when a netpoll-unabled device
is added to bonding;
4) enable netpoll support when all underlying devices support netpoll.
Cc: Andy Gospodarek <gospo@redhat.com>
Cc: Jeff Moyer <jmoyer@redhat.com>
Cc: Matt Mackall <mpm@selenic.com>
Cc: Neil Horman <nhorman@tuxdriver.com>
Cc: Jay Vosburgh <fubar@us.ibm.com>
Cc: David Miller <davem@davemloft.net>
Signed-off-by: WANG Cong <amwang@redhat.com>
---
Index: linux-2.6/drivers/net/bonding/bond_main.c
===================================================================
--- linux-2.6.orig/drivers/net/bonding/bond_main.c
+++ linux-2.6/drivers/net/bonding/bond_main.c
@@ -59,6 +59,7 @@
#include <linux/uaccess.h>
#include <linux/errno.h>
#include <linux/netdevice.h>
+#include <linux/netpoll.h>
#include <linux/inetdevice.h>
#include <linux/igmp.h>
#include <linux/etherdevice.h>
@@ -430,7 +431,18 @@ int bond_dev_queue_xmit(struct bonding *
}
skb->priority = 1;
- dev_queue_xmit(skb);
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ if (unlikely(bond->dev->priv_flags & IFF_IN_NETPOLL)) {
+ struct netpoll *np = bond->dev->npinfo->netpoll;
+ slave_dev->npinfo = bond->dev->npinfo;
+ np->real_dev = np->dev = skb->dev;
+ slave_dev->priv_flags |= IFF_IN_NETPOLL;
+ netpoll_send_skb(np, skb);
+ slave_dev->priv_flags &= ~IFF_IN_NETPOLL;
+ np->dev = bond->dev;
+ } else
+#endif
+ dev_queue_xmit(skb);
return 0;
}
@@ -1329,6 +1341,61 @@ static void bond_detach_slave(struct bon
bond->slave_cnt--;
}
+#ifdef CONFIG_NET_POLL_CONTROLLER
+/*
+ * You must hold read lock on bond->lock before calling this.
+ */
+static bool slaves_support_netpoll(struct net_device *bond_dev)
+{
+ struct bonding *bond = netdev_priv(bond_dev);
+ struct slave *slave;
+ int i = 0;
+ bool ret = true;
+
+ bond_for_each_slave(bond, slave, i) {
+ if ((slave->dev->priv_flags & IFF_DISABLE_NETPOLL)
+ || !slave->dev->netdev_ops->ndo_poll_controller)
+ ret = false;
+ }
+ return i != 0 && ret;
+}
+
+static void bond_poll_controller(struct net_device *bond_dev)
+{
+ struct net_device *dev = bond_dev->npinfo->netpoll->real_dev;
+ if (dev != bond_dev)
+ netpoll_poll_dev(dev);
+}
+
+static void bond_netpoll_cleanup(struct net_device *bond_dev)
+{
+ struct bonding *bond = netdev_priv(bond_dev);
+ struct slave *slave;
+ const struct net_device_ops *ops;
+ int i;
+
+ read_lock(&bond->lock);
+ bond_dev->npinfo = NULL;
+ bond_for_each_slave(bond, slave, i) {
+ if (slave->dev) {
+ ops = slave->dev->netdev_ops;
+ if (ops->ndo_netpoll_cleanup)
+ ops->ndo_netpoll_cleanup(slave->dev);
+ else
+ slave->dev->npinfo = NULL;
+ }
+ }
+ read_unlock(&bond->lock);
+}
+
+#else
+
+static void bond_netpoll_cleanup(struct net_device *bond_dev)
+{
+}
+
+#endif
+
/*---------------------------------- IOCTL ----------------------------------*/
static int bond_sethwaddr(struct net_device *bond_dev,
@@ -1735,6 +1802,18 @@ int bond_enslave(struct net_device *bond
bond_set_carrier(bond);
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ if (slaves_support_netpoll(bond_dev)) {
+ bond_dev->priv_flags &= ~IFF_DISABLE_NETPOLL;
+ if (bond_dev->npinfo)
+ slave_dev->npinfo = bond_dev->npinfo;
+ } else if (!(bond_dev->priv_flags & IFF_DISABLE_NETPOLL)) {
+ bond_dev->priv_flags |= IFF_DISABLE_NETPOLL;
+ pr_info("New slave device %s does not support netpoll\n",
+ slave_dev->name);
+ pr_info("Disabling netpoll support for %s\n", bond_dev->name);
+ }
+#endif
read_unlock(&bond->lock);
res = bond_create_slave_symlinks(bond_dev, slave_dev);
@@ -1801,6 +1880,7 @@ int bond_release(struct net_device *bond
return -EINVAL;
}
+ netdev_bonding_change(bond_dev, NETDEV_BONDING_DESLAVE);
write_lock_bh(&bond->lock);
slave = bond_get_slave_by_dev(bond, slave_dev);
@@ -1929,6 +2009,17 @@ int bond_release(struct net_device *bond
netdev_set_master(slave_dev, NULL);
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ read_lock_bh(&bond->lock);
+ if (slaves_support_netpoll(bond_dev))
+ bond_dev->priv_flags &= ~IFF_DISABLE_NETPOLL;
+ read_unlock_bh(&bond->lock);
+ if (slave_dev->netdev_ops->ndo_netpoll_cleanup)
+ slave_dev->netdev_ops->ndo_netpoll_cleanup(slave_dev);
+ else
+ slave_dev->npinfo = NULL;
+#endif
+
/* close slave before restoring its mac address */
dev_close(slave_dev);
@@ -4448,6 +4539,10 @@ static const struct net_device_ops bond_
.ndo_vlan_rx_register = bond_vlan_rx_register,
.ndo_vlan_rx_add_vid = bond_vlan_rx_add_vid,
.ndo_vlan_rx_kill_vid = bond_vlan_rx_kill_vid,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_netpoll_cleanup = bond_netpoll_cleanup,
+ .ndo_poll_controller = bond_poll_controller,
+#endif
};
static void bond_destructor(struct net_device *bond_dev)
@@ -4541,6 +4636,8 @@ static void bond_uninit(struct net_devic
{
struct bonding *bond = netdev_priv(bond_dev);
+ bond_netpoll_cleanup(bond_dev);
+
/* Release the bonded slaves */
bond_release_all(bond_dev);
^ permalink raw reply [flat|nested] 9+ messages in thread* Re: [v4 Patch 3/3] bonding: make bonding support netpoll
2010-04-27 7:56 ` [v4 Patch 3/3] bonding: make bonding " Amerigo Wang
@ 2010-04-27 22:24 ` David Miller
2010-04-28 2:08 ` Cong Wang
0 siblings, 1 reply; 9+ messages in thread
From: David Miller @ 2010-04-27 22:24 UTC (permalink / raw)
To: amwang
Cc: linux-kernel, mpm, netdev, bridge, gospo, nhorman, jmoyer,
shemminger, bonding-devel, fubar
From: Amerigo Wang <amwang@redhat.com>
Date: Tue, 27 Apr 2010 03:56:09 -0400
> + if ((slave->dev->priv_flags & IFF_DISABLE_NETPOLL)
> + || !slave->dev->netdev_ops->ndo_poll_controller)
"|| on first line please, plus fix second line's indentation as per
comments given in patch #1 and #2
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [v4 Patch 3/3] bonding: make bonding support netpoll
2010-04-27 22:24 ` David Miller
@ 2010-04-28 2:08 ` Cong Wang
0 siblings, 0 replies; 9+ messages in thread
From: Cong Wang @ 2010-04-28 2:08 UTC (permalink / raw)
To: David Miller
Cc: linux-kernel, mpm, netdev, bridge, gospo, nhorman, jmoyer,
shemminger, bonding-devel, fubar
David Miller wrote:
> From: Amerigo Wang <amwang@redhat.com>
> Date: Tue, 27 Apr 2010 03:56:09 -0400
>
>> + if ((slave->dev->priv_flags & IFF_DISABLE_NETPOLL)
>> + || !slave->dev->netdev_ops->ndo_poll_controller)
>
> "|| on first line please, plus fix second line's indentation as per
> comments given in patch #1 and #2
Thanks, David!
I will fix all of this style problem.
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [v4 Patch 1/3] netpoll: add generic support for bridge and bonding devices
2010-04-27 7:55 [v4 Patch 1/3] netpoll: add generic support for bridge and bonding devices Amerigo Wang
2010-04-27 7:55 ` [v4 Patch 2/3] bridge: make bridge support netpoll Amerigo Wang
2010-04-27 7:56 ` [v4 Patch 3/3] bonding: make bonding " Amerigo Wang
@ 2010-04-27 22:22 ` David Miller
2010-04-28 4:02 ` Dongdong Deng
3 siblings, 0 replies; 9+ messages in thread
From: David Miller @ 2010-04-27 22:22 UTC (permalink / raw)
To: amwang
Cc: linux-kernel, mpm, netdev, bridge, gospo, nhorman, jmoyer,
shemminger, bonding-devel, fubar
From: Amerigo Wang <amwang@redhat.com>
Date: Tue, 27 Apr 2010 03:55:41 -0400
> + if (ndev->priv_flags & IFF_DISABLE_NETPOLL
> + || !ndev->netdev_ops->ndo_poll_controller) {
" ||" goes on first line, not second, and second line needs to be indented
properly so that "!ndev->..." matches up with "ndev->priv_flags ..." on
the previous line.
^ permalink raw reply [flat|nested] 9+ messages in thread* Re: [v4 Patch 1/3] netpoll: add generic support for bridge and bonding devices
2010-04-27 7:55 [v4 Patch 1/3] netpoll: add generic support for bridge and bonding devices Amerigo Wang
` (2 preceding siblings ...)
2010-04-27 22:22 ` [v4 Patch 1/3] netpoll: add generic support for bridge and bonding devices David Miller
@ 2010-04-28 4:02 ` Dongdong Deng
2010-04-28 9:59 ` Cong Wang
3 siblings, 1 reply; 9+ messages in thread
From: Dongdong Deng @ 2010-04-28 4:02 UTC (permalink / raw)
To: Amerigo Wang
Cc: linux-kernel, Matt Mackall, netdev, bridge, Andy Gospodarek,
Neil Horman, Jeff Moyer, Stephen Hemminger, bonding-devel,
Jay Vosburgh, David Miller
On Tue, Apr 27, 2010 at 3:55 PM, Amerigo Wang <amwang@redhat.com> wrote:
> V4:
> Use "unlikely" to mark netpoll call path, suggested by Stephen.
> Handle NETDEV_GOING_DOWN case.
>
> V3:
> Update to latest Linus' tree.
> Fix deadlocks when releasing slaves of bonding devices.
> Thanks to Andy.
>
> V2:
> Fix some bugs of previous version.
> Remove ->netpoll_setup and ->netpoll_xmit, they are not necessary.
> Don't poll all underlying devices, poll ->real_dev in struct netpoll.
> Thanks to David for suggesting above.
>
> ------------>
>
> This whole patchset is for adding netpoll support to bridge and bonding
> devices. I already tested it for bridge, bonding, bridge over bonding,
> and bonding over bridge. It looks fine now.
>
>
> To make bridge and bonding support netpoll, we need to adjust
> some netpoll generic code. This patch does the following things:
>
> 1) introduce two new priv_flags for struct net_device:
> IFF_IN_NETPOLL which identifies we are processing a netpoll;
> IFF_DISABLE_NETPOLL is used to disable netpoll support for a device
> at run-time;
>
> 2) introduce one new method for netdev_ops:
> ->ndo_netpoll_cleanup() is used to clean up netpoll when a device is
> removed.
>
> 3) introduce netpoll_poll_dev() which takes a struct net_device * parameter;
> export netpoll_send_skb() and netpoll_poll_dev() which will be used later;
>
> 4) hide a pointer to struct netpoll in struct netpoll_info, ditto.
>
> 5) introduce ->real_dev for struct netpoll.
>
> 6) introduce a new status NETDEV_BONDING_DESLAE, which is used to disable
> netconsole before releasing a slave, to avoid deadlocks.
>
> Cc: David Miller <davem@davemloft.net>
> Cc: Neil Horman <nhorman@tuxdriver.com>
> Signed-off-by: WANG Cong <amwang@redhat.com>
>
> ---
>
> Index: linux-2.6/include/linux/if.h
> ===================================================================
> --- linux-2.6.orig/include/linux/if.h
> +++ linux-2.6/include/linux/if.h
> @@ -71,6 +71,8 @@
> * release skb->dst
> */
> #define IFF_DONT_BRIDGE 0x800 /* disallow bridging this ether dev */
> +#define IFF_IN_NETPOLL 0x1000 /* whether we are processing netpoll */
> +#define IFF_DISABLE_NETPOLL 0x2000 /* disable netpoll at run-time */
>
> #define IF_GET_IFACE 0x0001 /* for querying only */
> #define IF_GET_PROTO 0x0002
> Index: linux-2.6/include/linux/netdevice.h
> ===================================================================
> --- linux-2.6.orig/include/linux/netdevice.h
> +++ linux-2.6/include/linux/netdevice.h
> @@ -667,6 +667,7 @@ struct net_device_ops {
> unsigned short vid);
> #ifdef CONFIG_NET_POLL_CONTROLLER
> void (*ndo_poll_controller)(struct net_device *dev);
> + void (*ndo_netpoll_cleanup)(struct net_device *dev);
> #endif
> int (*ndo_set_vf_mac)(struct net_device *dev,
> int queue, u8 *mac);
> Index: linux-2.6/include/linux/netpoll.h
> ===================================================================
> --- linux-2.6.orig/include/linux/netpoll.h
> +++ linux-2.6/include/linux/netpoll.h
> @@ -14,6 +14,7 @@
>
> struct netpoll {
> struct net_device *dev;
> + struct net_device *real_dev;
> char dev_name[IFNAMSIZ];
> const char *name;
> void (*rx_hook)(struct netpoll *, int, char *, int);
> @@ -36,8 +37,11 @@ struct netpoll_info {
> struct sk_buff_head txq;
>
> struct delayed_work tx_work;
> +
> + struct netpoll *netpoll;
> };
>
> +void netpoll_poll_dev(struct net_device *dev);
> void netpoll_poll(struct netpoll *np);
> void netpoll_send_udp(struct netpoll *np, const char *msg, int len);
> void netpoll_print_options(struct netpoll *np);
> @@ -47,6 +51,7 @@ int netpoll_trap(void);
> void netpoll_set_trap(int trap);
> void netpoll_cleanup(struct netpoll *np);
> int __netpoll_rx(struct sk_buff *skb);
> +void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb);
>
>
> #ifdef CONFIG_NETPOLL
> Index: linux-2.6/net/core/netpoll.c
> ===================================================================
> --- linux-2.6.orig/net/core/netpoll.c
> +++ linux-2.6/net/core/netpoll.c
> @@ -179,9 +179,8 @@ static void service_arp_queue(struct net
> }
> }
>
> -void netpoll_poll(struct netpoll *np)
> +void netpoll_poll_dev(struct net_device *dev)
> {
> - struct net_device *dev = np->dev;
> const struct net_device_ops *ops;
>
> if (!dev || !netif_running(dev))
> @@ -201,6 +200,11 @@ void netpoll_poll(struct netpoll *np)
> zap_completion_queue();
> }
>
> +void netpoll_poll(struct netpoll *np)
> +{
> + netpoll_poll_dev(np->dev);
> +}
> +
> static void refill_skbs(void)
> {
> struct sk_buff *skb;
> @@ -282,7 +286,7 @@ static int netpoll_owner_active(struct n
> return 0;
> }
>
> -static void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb)
> +void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb)
> {
> int status = NETDEV_TX_BUSY;
> unsigned long tries;
> @@ -308,7 +312,9 @@ static void netpoll_send_skb(struct netp
> tries > 0; --tries) {
> if (__netif_tx_trylock(txq)) {
> if (!netif_tx_queue_stopped(txq)) {
> + dev->priv_flags |= IFF_IN_NETPOLL;
> status = ops->ndo_start_xmit(skb, dev);
> + dev->priv_flags &= ~IFF_IN_NETPOLL;
> if (status == NETDEV_TX_OK)
> txq_trans_update(txq);
> }
> @@ -756,7 +762,10 @@ int netpoll_setup(struct netpoll *np)
> atomic_inc(&npinfo->refcnt);
> }
>
> - if (!ndev->netdev_ops->ndo_poll_controller) {
> + npinfo->netpoll = np;
> +
> + if (ndev->priv_flags & IFF_DISABLE_NETPOLL
> + || !ndev->netdev_ops->ndo_poll_controller) {
> printk(KERN_ERR "%s: %s doesn't support polling, aborting.\n",
> np->name, np->dev_name);
> err = -ENOTSUPP;
> @@ -878,6 +887,7 @@ void netpoll_cleanup(struct netpoll *np)
> }
>
> if (atomic_dec_and_test(&npinfo->refcnt)) {
> + const struct net_device_ops *ops;
> skb_queue_purge(&npinfo->arp_tx);
> skb_queue_purge(&npinfo->txq);
> cancel_rearming_delayed_work(&npinfo->tx_work);
> @@ -885,7 +895,11 @@ void netpoll_cleanup(struct netpoll *np)
> /* clean after last, unfinished work */
> __skb_queue_purge(&npinfo->txq);
> kfree(npinfo);
> - np->dev->npinfo = NULL;
> + ops = np->dev->netdev_ops;
> + if (ops->ndo_netpoll_cleanup)
> + ops->ndo_netpoll_cleanup(np->dev);
> + else
> + np->dev->npinfo = NULL;
+ if (ops->ndo_netpoll_cleanup)
+ ops->ndo_netpoll_cleanup(np->dev);
+ np->dev->npinfo = NULL;
I think it is good to set np->dev->npinfo to NULL even though we have
the netpoll_cleanup opt.
Regards
Dongdong
> }
> }
>
> @@ -908,6 +922,7 @@ void netpoll_set_trap(int trap)
> atomic_dec(&trapped);
> }
>
> +EXPORT_SYMBOL(netpoll_send_skb);
> EXPORT_SYMBOL(netpoll_set_trap);
> EXPORT_SYMBOL(netpoll_trap);
> EXPORT_SYMBOL(netpoll_print_options);
> @@ -915,4 +930,5 @@ EXPORT_SYMBOL(netpoll_parse_options);
> EXPORT_SYMBOL(netpoll_setup);
> EXPORT_SYMBOL(netpoll_cleanup);
> EXPORT_SYMBOL(netpoll_send_udp);
> +EXPORT_SYMBOL(netpoll_poll_dev);
> EXPORT_SYMBOL(netpoll_poll);
> Index: linux-2.6/drivers/net/netconsole.c
> ===================================================================
> --- linux-2.6.orig/drivers/net/netconsole.c
> +++ linux-2.6/drivers/net/netconsole.c
> @@ -665,7 +665,8 @@ static int netconsole_netdev_event(struc
> struct netconsole_target *nt;
> struct net_device *dev = ptr;
>
> - if (!(event == NETDEV_CHANGENAME || event == NETDEV_UNREGISTER))
> + if (!(event == NETDEV_CHANGENAME || event == NETDEV_UNREGISTER ||
> + event == NETDEV_BONDING_DESLAVE || event == NETDEV_GOING_DOWN))
> goto done;
>
> spin_lock_irqsave(&target_list_lock, flags);
> @@ -677,19 +678,21 @@ static int netconsole_netdev_event(struc
> strlcpy(nt->np.dev_name, dev->name, IFNAMSIZ);
> break;
> case NETDEV_UNREGISTER:
> - if (!nt->enabled)
> - break;
> netpoll_cleanup(&nt->np);
> + /* Fall through */
> + case NETDEV_GOING_DOWN:
> + case NETDEV_BONDING_DESLAVE:
> nt->enabled = 0;
> - printk(KERN_INFO "netconsole: network logging stopped"
> - ", interface %s unregistered\n",
> - dev->name);
> break;
> }
> }
> netconsole_target_put(nt);
> }
> spin_unlock_irqrestore(&target_list_lock, flags);
> + if (event == NETDEV_UNREGISTER || event == NETDEV_BONDING_DESLAVE)
> + printk(KERN_INFO "netconsole: network logging stopped, "
> + "interface %s %s\n", dev->name,
> + event == NETDEV_UNREGISTER ? "unregistered" : "released slaves");
>
> done:
> return NOTIFY_DONE;
> Index: linux-2.6/include/linux/notifier.h
> ===================================================================
> --- linux-2.6.orig/include/linux/notifier.h
> +++ linux-2.6/include/linux/notifier.h
> @@ -203,6 +203,7 @@ static inline int notifier_to_errno(int
> #define NETDEV_BONDING_NEWTYPE 0x000F
> #define NETDEV_POST_INIT 0x0010
> #define NETDEV_UNREGISTER_BATCH 0x0011
> +#define NETDEV_BONDING_DESLAVE 0x0012
>
> #define SYS_DOWN 0x0001 /* Notify of system down */
> #define SYS_RESTART SYS_DOWN
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at http://www.tux.org/lkml/
>
^ permalink raw reply [flat|nested] 9+ messages in thread* Re: [v4 Patch 1/3] netpoll: add generic support for bridge and bonding devices
2010-04-28 4:02 ` Dongdong Deng
@ 2010-04-28 9:59 ` Cong Wang
0 siblings, 0 replies; 9+ messages in thread
From: Cong Wang @ 2010-04-28 9:59 UTC (permalink / raw)
To: Dongdong Deng
Cc: linux-kernel, Matt Mackall, netdev, bridge, Andy Gospodarek,
Neil Horman, Jeff Moyer, Stephen Hemminger, bonding-devel,
Jay Vosburgh, David Miller
Dongdong Deng wrote:
>
>
> + if (ops->ndo_netpoll_cleanup)
> + ops->ndo_netpoll_cleanup(np->dev);
> + np->dev->npinfo = NULL;
>
> I think it is good to set np->dev->npinfo to NULL even though we have
> the netpoll_cleanup opt.
>
This is redundant, since ->ndo_netpoll_cleanup will set it.
Thanks.
^ permalink raw reply [flat|nested] 9+ messages in thread