diff options
author | Vasu Dev <vasu.dev@intel.com> | 2010-03-23 10:41:45 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-03-24 14:11:38 -0400 |
commit | 669d3e0babb40018dd6e78f4093c13a2eac73866 (patch) | |
tree | b463681d16ac806ddc889b02623361c64047d281 /net/8021q | |
parent | 31b24b955c3ebbb6f3008a6374e61cf7c05a193c (diff) |
vlan: adds vlan_dev_select_queue
This is required to correctly select vlan tx queue for a driver
supporting multi tx queue with ndo_select_queue implemented since
currently selected vlan tx queue is unaligned to selected queue by
real net_devce ndo_select_queue.
Unaligned vlan tx queue selection causes thrash with higher vlan
tx lock contention for least fcoe traffic and wrong socket tx
queue_mapping for ixgbe having ndo_select_queue implemented.
-v2
As per Eric Dumazet<eric.dumazet@gmail.com> comments, mirrored
vlan net_device_ops to have them with and without vlan_dev_select_queue
and then select according to real dev ndo_select_queue present or not
for a vlan net_device. This is to completely skip vlan_dev_select_queue
calling for real net_device not supporting ndo_select_queue.
Signed-off-by: Vasu Dev <vasu.dev@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Acked-by: Eric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/8021q')
-rw-r--r-- | net/8021q/vlan_dev.c | 71 |
1 files changed, 68 insertions, 3 deletions
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index 9e83272fc5b0..2fd057c81bbf 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c | |||
@@ -361,6 +361,14 @@ static netdev_tx_t vlan_dev_hwaccel_hard_start_xmit(struct sk_buff *skb, | |||
361 | return ret; | 361 | return ret; |
362 | } | 362 | } |
363 | 363 | ||
364 | static u16 vlan_dev_select_queue(struct net_device *dev, struct sk_buff *skb) | ||
365 | { | ||
366 | struct net_device *rdev = vlan_dev_info(dev)->real_dev; | ||
367 | const struct net_device_ops *ops = rdev->netdev_ops; | ||
368 | |||
369 | return ops->ndo_select_queue(rdev, skb); | ||
370 | } | ||
371 | |||
364 | static int vlan_dev_change_mtu(struct net_device *dev, int new_mtu) | 372 | static int vlan_dev_change_mtu(struct net_device *dev, int new_mtu) |
365 | { | 373 | { |
366 | /* TODO: gotta make sure the underlying layer can handle it, | 374 | /* TODO: gotta make sure the underlying layer can handle it, |
@@ -688,7 +696,8 @@ static const struct header_ops vlan_header_ops = { | |||
688 | .parse = eth_header_parse, | 696 | .parse = eth_header_parse, |
689 | }; | 697 | }; |
690 | 698 | ||
691 | static const struct net_device_ops vlan_netdev_ops, vlan_netdev_accel_ops; | 699 | static const struct net_device_ops vlan_netdev_ops, vlan_netdev_accel_ops, |
700 | vlan_netdev_ops_sq, vlan_netdev_accel_ops_sq; | ||
692 | 701 | ||
693 | static int vlan_dev_init(struct net_device *dev) | 702 | static int vlan_dev_init(struct net_device *dev) |
694 | { | 703 | { |
@@ -722,11 +731,17 @@ static int vlan_dev_init(struct net_device *dev) | |||
722 | if (real_dev->features & NETIF_F_HW_VLAN_TX) { | 731 | if (real_dev->features & NETIF_F_HW_VLAN_TX) { |
723 | dev->header_ops = real_dev->header_ops; | 732 | dev->header_ops = real_dev->header_ops; |
724 | dev->hard_header_len = real_dev->hard_header_len; | 733 | dev->hard_header_len = real_dev->hard_header_len; |
725 | dev->netdev_ops = &vlan_netdev_accel_ops; | 734 | if (real_dev->netdev_ops->ndo_select_queue) |
735 | dev->netdev_ops = &vlan_netdev_accel_ops_sq; | ||
736 | else | ||
737 | dev->netdev_ops = &vlan_netdev_accel_ops; | ||
726 | } else { | 738 | } else { |
727 | dev->header_ops = &vlan_header_ops; | 739 | dev->header_ops = &vlan_header_ops; |
728 | dev->hard_header_len = real_dev->hard_header_len + VLAN_HLEN; | 740 | dev->hard_header_len = real_dev->hard_header_len + VLAN_HLEN; |
729 | dev->netdev_ops = &vlan_netdev_ops; | 741 | if (real_dev->netdev_ops->ndo_select_queue) |
742 | dev->netdev_ops = &vlan_netdev_ops_sq; | ||
743 | else | ||
744 | dev->netdev_ops = &vlan_netdev_ops; | ||
730 | } | 745 | } |
731 | 746 | ||
732 | if (is_vlan_dev(real_dev)) | 747 | if (is_vlan_dev(real_dev)) |
@@ -865,6 +880,56 @@ static const struct net_device_ops vlan_netdev_accel_ops = { | |||
865 | #endif | 880 | #endif |
866 | }; | 881 | }; |
867 | 882 | ||
883 | static const struct net_device_ops vlan_netdev_ops_sq = { | ||
884 | .ndo_select_queue = vlan_dev_select_queue, | ||
885 | .ndo_change_mtu = vlan_dev_change_mtu, | ||
886 | .ndo_init = vlan_dev_init, | ||
887 | .ndo_uninit = vlan_dev_uninit, | ||
888 | .ndo_open = vlan_dev_open, | ||
889 | .ndo_stop = vlan_dev_stop, | ||
890 | .ndo_start_xmit = vlan_dev_hard_start_xmit, | ||
891 | .ndo_validate_addr = eth_validate_addr, | ||
892 | .ndo_set_mac_address = vlan_dev_set_mac_address, | ||
893 | .ndo_set_rx_mode = vlan_dev_set_rx_mode, | ||
894 | .ndo_set_multicast_list = vlan_dev_set_rx_mode, | ||
895 | .ndo_change_rx_flags = vlan_dev_change_rx_flags, | ||
896 | .ndo_do_ioctl = vlan_dev_ioctl, | ||
897 | .ndo_neigh_setup = vlan_dev_neigh_setup, | ||
898 | .ndo_get_stats = vlan_dev_get_stats, | ||
899 | #if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE) | ||
900 | .ndo_fcoe_ddp_setup = vlan_dev_fcoe_ddp_setup, | ||
901 | .ndo_fcoe_ddp_done = vlan_dev_fcoe_ddp_done, | ||
902 | .ndo_fcoe_enable = vlan_dev_fcoe_enable, | ||
903 | .ndo_fcoe_disable = vlan_dev_fcoe_disable, | ||
904 | .ndo_fcoe_get_wwn = vlan_dev_fcoe_get_wwn, | ||
905 | #endif | ||
906 | }; | ||
907 | |||
908 | static const struct net_device_ops vlan_netdev_accel_ops_sq = { | ||
909 | .ndo_select_queue = vlan_dev_select_queue, | ||
910 | .ndo_change_mtu = vlan_dev_change_mtu, | ||
911 | .ndo_init = vlan_dev_init, | ||
912 | .ndo_uninit = vlan_dev_uninit, | ||
913 | .ndo_open = vlan_dev_open, | ||
914 | .ndo_stop = vlan_dev_stop, | ||
915 | .ndo_start_xmit = vlan_dev_hwaccel_hard_start_xmit, | ||
916 | .ndo_validate_addr = eth_validate_addr, | ||
917 | .ndo_set_mac_address = vlan_dev_set_mac_address, | ||
918 | .ndo_set_rx_mode = vlan_dev_set_rx_mode, | ||
919 | .ndo_set_multicast_list = vlan_dev_set_rx_mode, | ||
920 | .ndo_change_rx_flags = vlan_dev_change_rx_flags, | ||
921 | .ndo_do_ioctl = vlan_dev_ioctl, | ||
922 | .ndo_neigh_setup = vlan_dev_neigh_setup, | ||
923 | .ndo_get_stats = vlan_dev_get_stats, | ||
924 | #if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE) | ||
925 | .ndo_fcoe_ddp_setup = vlan_dev_fcoe_ddp_setup, | ||
926 | .ndo_fcoe_ddp_done = vlan_dev_fcoe_ddp_done, | ||
927 | .ndo_fcoe_enable = vlan_dev_fcoe_enable, | ||
928 | .ndo_fcoe_disable = vlan_dev_fcoe_disable, | ||
929 | .ndo_fcoe_get_wwn = vlan_dev_fcoe_get_wwn, | ||
930 | #endif | ||
931 | }; | ||
932 | |||
868 | void vlan_setup(struct net_device *dev) | 933 | void vlan_setup(struct net_device *dev) |
869 | { | 934 | { |
870 | ether_setup(dev); | 935 | ether_setup(dev); |