Skip to content

Commit

Permalink
vlan: add 802.1q netpoll support
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Benjamin LaHaise authored and David S. Miller committed Dec 9, 2011
1 parent 8af2a21 commit 6d4cdf4
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 0 deletions.
5 changes: 5 additions & 0 deletions net/8021q/vlan.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ struct vlan_pcpu_stats {
u32 tx_dropped;
};

struct netpoll;

/**
* struct vlan_dev_priv - VLAN private device data
* @nr_ingress_mappings: number of ingress priority mappings
Expand Down Expand Up @@ -68,6 +70,9 @@ struct vlan_dev_priv {

struct proc_dir_entry *dent;
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)
Expand Down
59 changes: 59 additions & 0 deletions net/8021q/vlan_dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#include "vlan.h"
#include "vlanproc.h"
#include <linux/if_vlan.h>
#include <linux/netpoll.h>

/*
* Rebuild the Ethernet MAC header. This is called after an ARP
Expand Down Expand Up @@ -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);
len = skb->len;
if (netpoll_tx_running(dev))
return skb->dev->netdev_ops->ndo_start_xmit(skb, skb->dev);
ret = dev_queue_xmit(skb);

if (likely(ret == NET_XMIT_SUCCESS || ret == NET_XMIT_CN)) {
Expand Down Expand Up @@ -660,6 +663,57 @@ static struct rtnl_link_stats64 *vlan_dev_get_stats64(struct net_device *dev, st
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 = {
.get_settings = vlan_ethtool_get_settings,
.get_drvinfo = vlan_ethtool_get_drvinfo,
Expand Down Expand Up @@ -687,6 +741,11 @@ static const struct net_device_ops vlan_netdev_ops = {
.ndo_fcoe_disable = vlan_dev_fcoe_disable,
.ndo_fcoe_get_wwn = vlan_dev_fcoe_get_wwn,
.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
.ndo_fix_features = vlan_dev_fix_features,
};
Expand Down

0 comments on commit 6d4cdf4

Please sign in to comment.