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 | |
| 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>
| -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); |
