vlan: add 802.1q netpoll support
Add netpoll support to 802.1q vlan devices. Based on the netpoll support in the bridging code. Tested on a forced_eth device with netconsole. Signed-off-by: Benjamin LaHaise <bcrl@kvack.org> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
8af2a218de
commit
6d4cdf47d2
2 changed files with 64 additions and 0 deletions
|
@ -41,6 +41,8 @@ struct vlan_pcpu_stats {
|
||||||
u32 tx_dropped;
|
u32 tx_dropped;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct netpoll;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct vlan_dev_priv - VLAN private device data
|
* struct vlan_dev_priv - VLAN private device data
|
||||||
* @nr_ingress_mappings: number of ingress priority mappings
|
* @nr_ingress_mappings: number of ingress priority mappings
|
||||||
|
@ -68,6 +70,9 @@ struct vlan_dev_priv {
|
||||||
|
|
||||||
struct proc_dir_entry *dent;
|
struct proc_dir_entry *dent;
|
||||||
struct vlan_pcpu_stats __percpu *vlan_pcpu_stats;
|
struct vlan_pcpu_stats __percpu *vlan_pcpu_stats;
|
||||||
|
#ifdef CONFIG_NET_POLL_CONTROLLER
|
||||||
|
struct netpoll *netpoll;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline struct vlan_dev_priv *vlan_dev_priv(const struct net_device *dev)
|
static inline struct vlan_dev_priv *vlan_dev_priv(const struct net_device *dev)
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
#include "vlan.h"
|
#include "vlan.h"
|
||||||
#include "vlanproc.h"
|
#include "vlanproc.h"
|
||||||
#include <linux/if_vlan.h>
|
#include <linux/if_vlan.h>
|
||||||
|
#include <linux/netpoll.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Rebuild the Ethernet MAC header. This is called after an ARP
|
* Rebuild the Ethernet MAC header. This is called after an ARP
|
||||||
|
@ -158,6 +159,8 @@ static netdev_tx_t vlan_dev_hard_start_xmit(struct sk_buff *skb,
|
||||||
|
|
||||||
skb_set_dev(skb, vlan_dev_priv(dev)->real_dev);
|
skb_set_dev(skb, vlan_dev_priv(dev)->real_dev);
|
||||||
len = skb->len;
|
len = skb->len;
|
||||||
|
if (netpoll_tx_running(dev))
|
||||||
|
return skb->dev->netdev_ops->ndo_start_xmit(skb, skb->dev);
|
||||||
ret = dev_queue_xmit(skb);
|
ret = dev_queue_xmit(skb);
|
||||||
|
|
||||||
if (likely(ret == NET_XMIT_SUCCESS || ret == NET_XMIT_CN)) {
|
if (likely(ret == NET_XMIT_SUCCESS || ret == NET_XMIT_CN)) {
|
||||||
|
@ -660,6 +663,57 @@ static struct rtnl_link_stats64 *vlan_dev_get_stats64(struct net_device *dev, st
|
||||||
return stats;
|
return stats;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_NET_POLL_CONTROLLER
|
||||||
|
void vlan_dev_poll_controller(struct net_device *dev)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int vlan_dev_netpoll_setup(struct net_device *dev, struct netpoll_info *npinfo)
|
||||||
|
{
|
||||||
|
struct vlan_dev_priv *info = vlan_dev_priv(dev);
|
||||||
|
struct net_device *real_dev = info->real_dev;
|
||||||
|
struct netpoll *netpoll;
|
||||||
|
int err = 0;
|
||||||
|
|
||||||
|
netpoll = kzalloc(sizeof(*netpoll), GFP_KERNEL);
|
||||||
|
err = -ENOMEM;
|
||||||
|
if (!netpoll)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
netpoll->dev = real_dev;
|
||||||
|
strlcpy(netpoll->dev_name, real_dev->name, IFNAMSIZ);
|
||||||
|
|
||||||
|
err = __netpoll_setup(netpoll);
|
||||||
|
if (err) {
|
||||||
|
kfree(netpoll);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
info->netpoll = netpoll;
|
||||||
|
|
||||||
|
out:
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
void vlan_dev_netpoll_cleanup(struct net_device *dev)
|
||||||
|
{
|
||||||
|
struct vlan_dev_priv *info = vlan_dev_priv(dev);
|
||||||
|
struct netpoll *netpoll = info->netpoll;
|
||||||
|
|
||||||
|
if (!netpoll)
|
||||||
|
return;
|
||||||
|
|
||||||
|
info->netpoll = NULL;
|
||||||
|
|
||||||
|
/* Wait for transmitting packets to finish before freeing. */
|
||||||
|
synchronize_rcu_bh();
|
||||||
|
|
||||||
|
__netpoll_cleanup(netpoll);
|
||||||
|
kfree(netpoll);
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_NET_POLL_CONTROLLER */
|
||||||
|
|
||||||
static const struct ethtool_ops vlan_ethtool_ops = {
|
static const struct ethtool_ops vlan_ethtool_ops = {
|
||||||
.get_settings = vlan_ethtool_get_settings,
|
.get_settings = vlan_ethtool_get_settings,
|
||||||
.get_drvinfo = vlan_ethtool_get_drvinfo,
|
.get_drvinfo = vlan_ethtool_get_drvinfo,
|
||||||
|
@ -687,6 +741,11 @@ static const struct net_device_ops vlan_netdev_ops = {
|
||||||
.ndo_fcoe_disable = vlan_dev_fcoe_disable,
|
.ndo_fcoe_disable = vlan_dev_fcoe_disable,
|
||||||
.ndo_fcoe_get_wwn = vlan_dev_fcoe_get_wwn,
|
.ndo_fcoe_get_wwn = vlan_dev_fcoe_get_wwn,
|
||||||
.ndo_fcoe_ddp_target = vlan_dev_fcoe_ddp_target,
|
.ndo_fcoe_ddp_target = vlan_dev_fcoe_ddp_target,
|
||||||
|
#endif
|
||||||
|
#ifdef CONFIG_NET_POLL_CONTROLLER
|
||||||
|
.ndo_poll_controller = vlan_dev_poll_controller,
|
||||||
|
.ndo_netpoll_setup = vlan_dev_netpoll_setup,
|
||||||
|
.ndo_netpoll_cleanup = vlan_dev_netpoll_cleanup,
|
||||||
#endif
|
#endif
|
||||||
.ndo_fix_features = vlan_dev_fix_features,
|
.ndo_fix_features = vlan_dev_fix_features,
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue