diff options
author | dingtianhong <dingtianhong@huawei.com> | 2014-05-30 04:00:56 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-06-02 19:05:24 -0400 |
commit | 688cea83f4396fa98b77a126ed278b89daccccdc (patch) | |
tree | ae3349b41460cf5cfb9fe1a09ae1e613e619171f /drivers/net/macvlan.c | |
parent | 7d507ac28ab9a17f28fd8c8be82f9255a1f72834 (diff) |
macvlan: add netpoll support
Add netpoll support to macvlan devices. Based on the netpoll support in the 802.1q vlan code.
Tested and macvlan could work well with netconsole.
Signed-off-by: Ding Tianhong <dingtianhong@huawei.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/macvlan.c')
-rw-r--r-- | drivers/net/macvlan.c | 66 |
1 files changed, 65 insertions, 1 deletions
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c index d2dbcfc68ee4..eee9106d1da1 100644 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <linux/workqueue.h> | 33 | #include <linux/workqueue.h> |
34 | #include <net/rtnetlink.h> | 34 | #include <net/rtnetlink.h> |
35 | #include <net/xfrm.h> | 35 | #include <net/xfrm.h> |
36 | #include <linux/netpoll.h> | ||
36 | 37 | ||
37 | #define MACVLAN_HASH_SIZE (1 << BITS_PER_BYTE) | 38 | #define MACVLAN_HASH_SIZE (1 << BITS_PER_BYTE) |
38 | 39 | ||
@@ -357,12 +358,26 @@ xmit_world: | |||
357 | return dev_queue_xmit(skb); | 358 | return dev_queue_xmit(skb); |
358 | } | 359 | } |
359 | 360 | ||
361 | static inline netdev_tx_t macvlan_netpoll_send_skb(struct macvlan_dev *vlan, struct sk_buff *skb) | ||
362 | { | ||
363 | #ifdef CONFIG_NET_POLL_CONTROLLER | ||
364 | if (vlan->netpoll) | ||
365 | netpoll_send_skb(vlan->netpoll, skb); | ||
366 | #else | ||
367 | BUG(); | ||
368 | #endif | ||
369 | return NETDEV_TX_OK; | ||
370 | } | ||
371 | |||
360 | static netdev_tx_t macvlan_start_xmit(struct sk_buff *skb, | 372 | static netdev_tx_t macvlan_start_xmit(struct sk_buff *skb, |
361 | struct net_device *dev) | 373 | struct net_device *dev) |
362 | { | 374 | { |
363 | unsigned int len = skb->len; | 375 | unsigned int len = skb->len; |
364 | int ret; | 376 | int ret; |
365 | const struct macvlan_dev *vlan = netdev_priv(dev); | 377 | struct macvlan_dev *vlan = netdev_priv(dev); |
378 | |||
379 | if (unlikely(netpoll_tx_running(dev))) | ||
380 | return macvlan_netpoll_send_skb(vlan, skb); | ||
366 | 381 | ||
367 | if (vlan->fwd_priv) { | 382 | if (vlan->fwd_priv) { |
368 | skb->dev = vlan->lowerdev; | 383 | skb->dev = vlan->lowerdev; |
@@ -788,6 +803,50 @@ static netdev_features_t macvlan_fix_features(struct net_device *dev, | |||
788 | return features; | 803 | return features; |
789 | } | 804 | } |
790 | 805 | ||
806 | #ifdef CONFIG_NET_POLL_CONTROLLER | ||
807 | static void macvlan_dev_poll_controller(struct net_device *dev) | ||
808 | { | ||
809 | return; | ||
810 | } | ||
811 | |||
812 | static int macvlan_dev_netpoll_setup(struct net_device *dev, struct netpoll_info *npinfo) | ||
813 | { | ||
814 | struct macvlan_dev *vlan = netdev_priv(dev); | ||
815 | struct net_device *real_dev = vlan->lowerdev; | ||
816 | struct netpoll *netpoll; | ||
817 | int err = 0; | ||
818 | |||
819 | netpoll = kzalloc(sizeof(*netpoll), GFP_KERNEL); | ||
820 | err = -ENOMEM; | ||
821 | if (!netpoll) | ||
822 | goto out; | ||
823 | |||
824 | err = __netpoll_setup(netpoll, real_dev); | ||
825 | if (err) { | ||
826 | kfree(netpoll); | ||
827 | goto out; | ||
828 | } | ||
829 | |||
830 | vlan->netpoll = netpoll; | ||
831 | |||
832 | out: | ||
833 | return err; | ||
834 | } | ||
835 | |||
836 | static void macvlan_dev_netpoll_cleanup(struct net_device *dev) | ||
837 | { | ||
838 | struct macvlan_dev *vlan = netdev_priv(dev); | ||
839 | struct netpoll *netpoll = vlan->netpoll; | ||
840 | |||
841 | if (!netpoll) | ||
842 | return; | ||
843 | |||
844 | vlan->netpoll = NULL; | ||
845 | |||
846 | __netpoll_free_async(netpoll); | ||
847 | } | ||
848 | #endif /* CONFIG_NET_POLL_CONTROLLER */ | ||
849 | |||
791 | static const struct ethtool_ops macvlan_ethtool_ops = { | 850 | static const struct ethtool_ops macvlan_ethtool_ops = { |
792 | .get_link = ethtool_op_get_link, | 851 | .get_link = ethtool_op_get_link, |
793 | .get_settings = macvlan_ethtool_get_settings, | 852 | .get_settings = macvlan_ethtool_get_settings, |
@@ -813,6 +872,11 @@ static const struct net_device_ops macvlan_netdev_ops = { | |||
813 | .ndo_fdb_del = macvlan_fdb_del, | 872 | .ndo_fdb_del = macvlan_fdb_del, |
814 | .ndo_fdb_dump = ndo_dflt_fdb_dump, | 873 | .ndo_fdb_dump = ndo_dflt_fdb_dump, |
815 | .ndo_get_lock_subclass = macvlan_get_nest_level, | 874 | .ndo_get_lock_subclass = macvlan_get_nest_level, |
875 | #ifdef CONFIG_NET_POLL_CONTROLLER | ||
876 | .ndo_poll_controller = macvlan_dev_poll_controller, | ||
877 | .ndo_netpoll_setup = macvlan_dev_netpoll_setup, | ||
878 | .ndo_netpoll_cleanup = macvlan_dev_netpoll_cleanup, | ||
879 | #endif | ||
816 | }; | 880 | }; |
817 | 881 | ||
818 | void macvlan_common_setup(struct net_device *dev) | 882 | void macvlan_common_setup(struct net_device *dev) |