diff options
Diffstat (limited to 'net/8021q/vlan_dev.c')
-rw-r--r-- | net/8021q/vlan_dev.c | 72 |
1 files changed, 69 insertions, 3 deletions
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index 9e83272fc5b0..29b6348c8d4d 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c | |||
@@ -21,6 +21,7 @@ | |||
21 | */ | 21 | */ |
22 | 22 | ||
23 | #include <linux/module.h> | 23 | #include <linux/module.h> |
24 | #include <linux/slab.h> | ||
24 | #include <linux/skbuff.h> | 25 | #include <linux/skbuff.h> |
25 | #include <linux/netdevice.h> | 26 | #include <linux/netdevice.h> |
26 | #include <linux/etherdevice.h> | 27 | #include <linux/etherdevice.h> |
@@ -361,6 +362,14 @@ static netdev_tx_t vlan_dev_hwaccel_hard_start_xmit(struct sk_buff *skb, | |||
361 | return ret; | 362 | return ret; |
362 | } | 363 | } |
363 | 364 | ||
365 | static u16 vlan_dev_select_queue(struct net_device *dev, struct sk_buff *skb) | ||
366 | { | ||
367 | struct net_device *rdev = vlan_dev_info(dev)->real_dev; | ||
368 | const struct net_device_ops *ops = rdev->netdev_ops; | ||
369 | |||
370 | return ops->ndo_select_queue(rdev, skb); | ||
371 | } | ||
372 | |||
364 | static int vlan_dev_change_mtu(struct net_device *dev, int new_mtu) | 373 | static int vlan_dev_change_mtu(struct net_device *dev, int new_mtu) |
365 | { | 374 | { |
366 | /* TODO: gotta make sure the underlying layer can handle it, | 375 | /* TODO: gotta make sure the underlying layer can handle it, |
@@ -688,7 +697,8 @@ static const struct header_ops vlan_header_ops = { | |||
688 | .parse = eth_header_parse, | 697 | .parse = eth_header_parse, |
689 | }; | 698 | }; |
690 | 699 | ||
691 | static const struct net_device_ops vlan_netdev_ops, vlan_netdev_accel_ops; | 700 | static const struct net_device_ops vlan_netdev_ops, vlan_netdev_accel_ops, |
701 | vlan_netdev_ops_sq, vlan_netdev_accel_ops_sq; | ||
692 | 702 | ||
693 | static int vlan_dev_init(struct net_device *dev) | 703 | static int vlan_dev_init(struct net_device *dev) |
694 | { | 704 | { |
@@ -722,11 +732,17 @@ static int vlan_dev_init(struct net_device *dev) | |||
722 | if (real_dev->features & NETIF_F_HW_VLAN_TX) { | 732 | if (real_dev->features & NETIF_F_HW_VLAN_TX) { |
723 | dev->header_ops = real_dev->header_ops; | 733 | dev->header_ops = real_dev->header_ops; |
724 | dev->hard_header_len = real_dev->hard_header_len; | 734 | dev->hard_header_len = real_dev->hard_header_len; |
725 | dev->netdev_ops = &vlan_netdev_accel_ops; | 735 | if (real_dev->netdev_ops->ndo_select_queue) |
736 | dev->netdev_ops = &vlan_netdev_accel_ops_sq; | ||
737 | else | ||
738 | dev->netdev_ops = &vlan_netdev_accel_ops; | ||
726 | } else { | 739 | } else { |
727 | dev->header_ops = &vlan_header_ops; | 740 | dev->header_ops = &vlan_header_ops; |
728 | dev->hard_header_len = real_dev->hard_header_len + VLAN_HLEN; | 741 | dev->hard_header_len = real_dev->hard_header_len + VLAN_HLEN; |
729 | dev->netdev_ops = &vlan_netdev_ops; | 742 | if (real_dev->netdev_ops->ndo_select_queue) |
743 | dev->netdev_ops = &vlan_netdev_ops_sq; | ||
744 | else | ||
745 | dev->netdev_ops = &vlan_netdev_ops; | ||
730 | } | 746 | } |
731 | 747 | ||
732 | if (is_vlan_dev(real_dev)) | 748 | if (is_vlan_dev(real_dev)) |
@@ -865,6 +881,56 @@ static const struct net_device_ops vlan_netdev_accel_ops = { | |||
865 | #endif | 881 | #endif |
866 | }; | 882 | }; |
867 | 883 | ||
884 | static const struct net_device_ops vlan_netdev_ops_sq = { | ||
885 | .ndo_select_queue = vlan_dev_select_queue, | ||
886 | .ndo_change_mtu = vlan_dev_change_mtu, | ||
887 | .ndo_init = vlan_dev_init, | ||
888 | .ndo_uninit = vlan_dev_uninit, | ||
889 | .ndo_open = vlan_dev_open, | ||
890 | .ndo_stop = vlan_dev_stop, | ||
891 | .ndo_start_xmit = vlan_dev_hard_start_xmit, | ||
892 | .ndo_validate_addr = eth_validate_addr, | ||
893 | .ndo_set_mac_address = vlan_dev_set_mac_address, | ||
894 | .ndo_set_rx_mode = vlan_dev_set_rx_mode, | ||
895 | .ndo_set_multicast_list = vlan_dev_set_rx_mode, | ||
896 | .ndo_change_rx_flags = vlan_dev_change_rx_flags, | ||
897 | .ndo_do_ioctl = vlan_dev_ioctl, | ||
898 | .ndo_neigh_setup = vlan_dev_neigh_setup, | ||
899 | .ndo_get_stats = vlan_dev_get_stats, | ||
900 | #if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE) | ||
901 | .ndo_fcoe_ddp_setup = vlan_dev_fcoe_ddp_setup, | ||
902 | .ndo_fcoe_ddp_done = vlan_dev_fcoe_ddp_done, | ||
903 | .ndo_fcoe_enable = vlan_dev_fcoe_enable, | ||
904 | .ndo_fcoe_disable = vlan_dev_fcoe_disable, | ||
905 | .ndo_fcoe_get_wwn = vlan_dev_fcoe_get_wwn, | ||
906 | #endif | ||
907 | }; | ||
908 | |||
909 | static const struct net_device_ops vlan_netdev_accel_ops_sq = { | ||
910 | .ndo_select_queue = vlan_dev_select_queue, | ||
911 | .ndo_change_mtu = vlan_dev_change_mtu, | ||
912 | .ndo_init = vlan_dev_init, | ||
913 | .ndo_uninit = vlan_dev_uninit, | ||
914 | .ndo_open = vlan_dev_open, | ||
915 | .ndo_stop = vlan_dev_stop, | ||
916 | .ndo_start_xmit = vlan_dev_hwaccel_hard_start_xmit, | ||
917 | .ndo_validate_addr = eth_validate_addr, | ||
918 | .ndo_set_mac_address = vlan_dev_set_mac_address, | ||
919 | .ndo_set_rx_mode = vlan_dev_set_rx_mode, | ||
920 | .ndo_set_multicast_list = vlan_dev_set_rx_mode, | ||
921 | .ndo_change_rx_flags = vlan_dev_change_rx_flags, | ||
922 | .ndo_do_ioctl = vlan_dev_ioctl, | ||
923 | .ndo_neigh_setup = vlan_dev_neigh_setup, | ||
924 | .ndo_get_stats = vlan_dev_get_stats, | ||
925 | #if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE) | ||
926 | .ndo_fcoe_ddp_setup = vlan_dev_fcoe_ddp_setup, | ||
927 | .ndo_fcoe_ddp_done = vlan_dev_fcoe_ddp_done, | ||
928 | .ndo_fcoe_enable = vlan_dev_fcoe_enable, | ||
929 | .ndo_fcoe_disable = vlan_dev_fcoe_disable, | ||
930 | .ndo_fcoe_get_wwn = vlan_dev_fcoe_get_wwn, | ||
931 | #endif | ||
932 | }; | ||
933 | |||
868 | void vlan_setup(struct net_device *dev) | 934 | void vlan_setup(struct net_device *dev) |
869 | { | 935 | { |
870 | ether_setup(dev); | 936 | ether_setup(dev); |