summaryrefslogtreecommitdiffstats
path: root/net/8021q/vlan_dev.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/8021q/vlan_dev.c')
-rw-r--r--net/8021q/vlan_dev.c86
1 files changed, 76 insertions, 10 deletions
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
index 9e83272fc5b0..b5249c5fd4d3 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -21,6 +21,7 @@
*/
#include <linux/module.h>
+#include <linux/slab.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
@@ -361,6 +362,14 @@ static netdev_tx_t vlan_dev_hwaccel_hard_start_xmit(struct sk_buff *skb,
return ret;
}
+static u16 vlan_dev_select_queue(struct net_device *dev, struct sk_buff *skb)
+{
+ struct net_device *rdev = vlan_dev_info(dev)->real_dev;
+ const struct net_device_ops *ops = rdev->netdev_ops;
+
+ return ops->ndo_select_queue(rdev, skb);
+}
+
static int vlan_dev_change_mtu(struct net_device *dev, int new_mtu)
{
/* TODO: gotta make sure the underlying layer can handle it,
@@ -461,7 +470,7 @@ static int vlan_dev_open(struct net_device *dev)
return -ENETDOWN;
if (compare_ether_addr(dev->dev_addr, real_dev->dev_addr)) {
- err = dev_unicast_add(real_dev, dev->dev_addr);
+ err = dev_uc_add(real_dev, dev->dev_addr);
if (err < 0)
goto out;
}
@@ -490,7 +499,7 @@ clear_allmulti:
dev_set_allmulti(real_dev, -1);
del_unicast:
if (compare_ether_addr(dev->dev_addr, real_dev->dev_addr))
- dev_unicast_delete(real_dev, dev->dev_addr);
+ dev_uc_del(real_dev, dev->dev_addr);
out:
netif_carrier_off(dev);
return err;
@@ -505,14 +514,14 @@ static int vlan_dev_stop(struct net_device *dev)
vlan_gvrp_request_leave(dev);
dev_mc_unsync(real_dev, dev);
- dev_unicast_unsync(real_dev, dev);
+ dev_uc_unsync(real_dev, dev);
if (dev->flags & IFF_ALLMULTI)
dev_set_allmulti(real_dev, -1);
if (dev->flags & IFF_PROMISC)
dev_set_promiscuity(real_dev, -1);
if (compare_ether_addr(dev->dev_addr, real_dev->dev_addr))
- dev_unicast_delete(real_dev, dev->dev_addr);
+ dev_uc_del(real_dev, dev->dev_addr);
netif_carrier_off(dev);
return 0;
@@ -531,13 +540,13 @@ static int vlan_dev_set_mac_address(struct net_device *dev, void *p)
goto out;
if (compare_ether_addr(addr->sa_data, real_dev->dev_addr)) {
- err = dev_unicast_add(real_dev, addr->sa_data);
+ err = dev_uc_add(real_dev, addr->sa_data);
if (err < 0)
return err;
}
if (compare_ether_addr(dev->dev_addr, real_dev->dev_addr))
- dev_unicast_delete(real_dev, dev->dev_addr);
+ dev_uc_del(real_dev, dev->dev_addr);
out:
memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
@@ -654,7 +663,7 @@ static void vlan_dev_change_rx_flags(struct net_device *dev, int change)
static void vlan_dev_set_rx_mode(struct net_device *vlan_dev)
{
dev_mc_sync(vlan_dev_info(vlan_dev)->real_dev, vlan_dev);
- dev_unicast_sync(vlan_dev_info(vlan_dev)->real_dev, vlan_dev);
+ dev_uc_sync(vlan_dev_info(vlan_dev)->real_dev, vlan_dev);
}
/*
@@ -688,7 +697,8 @@ static const struct header_ops vlan_header_ops = {
.parse = eth_header_parse,
};
-static const struct net_device_ops vlan_netdev_ops, vlan_netdev_accel_ops;
+static const struct net_device_ops vlan_netdev_ops, vlan_netdev_accel_ops,
+ vlan_netdev_ops_sq, vlan_netdev_accel_ops_sq;
static int vlan_dev_init(struct net_device *dev)
{
@@ -722,11 +732,17 @@ static int vlan_dev_init(struct net_device *dev)
if (real_dev->features & NETIF_F_HW_VLAN_TX) {
dev->header_ops = real_dev->header_ops;
dev->hard_header_len = real_dev->hard_header_len;
- dev->netdev_ops = &vlan_netdev_accel_ops;
+ if (real_dev->netdev_ops->ndo_select_queue)
+ dev->netdev_ops = &vlan_netdev_accel_ops_sq;
+ else
+ dev->netdev_ops = &vlan_netdev_accel_ops;
} else {
dev->header_ops = &vlan_header_ops;
dev->hard_header_len = real_dev->hard_header_len + VLAN_HLEN;
- dev->netdev_ops = &vlan_netdev_ops;
+ if (real_dev->netdev_ops->ndo_select_queue)
+ dev->netdev_ops = &vlan_netdev_ops_sq;
+ else
+ dev->netdev_ops = &vlan_netdev_ops;
}
if (is_vlan_dev(real_dev))
@@ -865,6 +881,56 @@ static const struct net_device_ops vlan_netdev_accel_ops = {
#endif
};
+static const struct net_device_ops vlan_netdev_ops_sq = {
+ .ndo_select_queue = vlan_dev_select_queue,
+ .ndo_change_mtu = vlan_dev_change_mtu,
+ .ndo_init = vlan_dev_init,
+ .ndo_uninit = vlan_dev_uninit,
+ .ndo_open = vlan_dev_open,
+ .ndo_stop = vlan_dev_stop,
+ .ndo_start_xmit = vlan_dev_hard_start_xmit,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = vlan_dev_set_mac_address,
+ .ndo_set_rx_mode = vlan_dev_set_rx_mode,
+ .ndo_set_multicast_list = vlan_dev_set_rx_mode,
+ .ndo_change_rx_flags = vlan_dev_change_rx_flags,
+ .ndo_do_ioctl = vlan_dev_ioctl,
+ .ndo_neigh_setup = vlan_dev_neigh_setup,
+ .ndo_get_stats = vlan_dev_get_stats,
+#if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE)
+ .ndo_fcoe_ddp_setup = vlan_dev_fcoe_ddp_setup,
+ .ndo_fcoe_ddp_done = vlan_dev_fcoe_ddp_done,
+ .ndo_fcoe_enable = vlan_dev_fcoe_enable,
+ .ndo_fcoe_disable = vlan_dev_fcoe_disable,
+ .ndo_fcoe_get_wwn = vlan_dev_fcoe_get_wwn,
+#endif
+};
+
+static const struct net_device_ops vlan_netdev_accel_ops_sq = {
+ .ndo_select_queue = vlan_dev_select_queue,
+ .ndo_change_mtu = vlan_dev_change_mtu,
+ .ndo_init = vlan_dev_init,
+ .ndo_uninit = vlan_dev_uninit,
+ .ndo_open = vlan_dev_open,
+ .ndo_stop = vlan_dev_stop,
+ .ndo_start_xmit = vlan_dev_hwaccel_hard_start_xmit,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = vlan_dev_set_mac_address,
+ .ndo_set_rx_mode = vlan_dev_set_rx_mode,
+ .ndo_set_multicast_list = vlan_dev_set_rx_mode,
+ .ndo_change_rx_flags = vlan_dev_change_rx_flags,
+ .ndo_do_ioctl = vlan_dev_ioctl,
+ .ndo_neigh_setup = vlan_dev_neigh_setup,
+ .ndo_get_stats = vlan_dev_get_stats,
+#if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE)
+ .ndo_fcoe_ddp_setup = vlan_dev_fcoe_ddp_setup,
+ .ndo_fcoe_ddp_done = vlan_dev_fcoe_ddp_done,
+ .ndo_fcoe_enable = vlan_dev_fcoe_enable,
+ .ndo_fcoe_disable = vlan_dev_fcoe_disable,
+ .ndo_fcoe_get_wwn = vlan_dev_fcoe_get_wwn,
+#endif
+};
+
void vlan_setup(struct net_device *dev)
{
ether_setup(dev);