diff options
author | Roopa Prabhu <roprabhu@cisco.com> | 2010-12-08 08:19:58 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-12-10 18:39:42 -0500 |
commit | 319d7e847355ec7e03d3c865917b2b0e2e592fb8 (patch) | |
tree | a900c8007e8060e03e5d26939051716d0543921a /drivers | |
parent | a8d764b9832d3cc86019f71916665dd2d337d7c2 (diff) |
enic: Add ndo_set_rx_mode support for enic vnics
Add ndo_set_rx_mode support to register unicast and multicast
address filters for enic devices
Signed-off-by: Roopa Prabhu <roprabhu@cisco.com>
Signed-off-by: Vasanthy Kolluri <vkolluri@cisco.com>
Signed-off-by: David Wang <dwang2@cisco.com>
Signed-off-by: Christian Benvenuti <benve@cisco.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/enic/enic.h | 4 | ||||
-rw-r--r-- | drivers/net/enic/enic_main.c | 121 | ||||
-rw-r--r-- | drivers/net/enic/enic_res.h | 1 |
3 files changed, 102 insertions, 24 deletions
diff --git a/drivers/net/enic/enic.h b/drivers/net/enic/enic.h index 70672541364e..8f374c1e2caf 100644 --- a/drivers/net/enic/enic.h +++ b/drivers/net/enic/enic.h | |||
@@ -32,7 +32,7 @@ | |||
32 | 32 | ||
33 | #define DRV_NAME "enic" | 33 | #define DRV_NAME "enic" |
34 | #define DRV_DESCRIPTION "Cisco VIC Ethernet NIC Driver" | 34 | #define DRV_DESCRIPTION "Cisco VIC Ethernet NIC Driver" |
35 | #define DRV_VERSION "1.4.1.7" | 35 | #define DRV_VERSION "1.4.1.8" |
36 | #define DRV_COPYRIGHT "Copyright 2008-2010 Cisco Systems, Inc" | 36 | #define DRV_COPYRIGHT "Copyright 2008-2010 Cisco Systems, Inc" |
37 | 37 | ||
38 | #define ENIC_BARS_MAX 6 | 38 | #define ENIC_BARS_MAX 6 |
@@ -78,8 +78,10 @@ struct enic { | |||
78 | spinlock_t devcmd_lock; | 78 | spinlock_t devcmd_lock; |
79 | u8 mac_addr[ETH_ALEN]; | 79 | u8 mac_addr[ETH_ALEN]; |
80 | u8 mc_addr[ENIC_MULTICAST_PERFECT_FILTERS][ETH_ALEN]; | 80 | u8 mc_addr[ENIC_MULTICAST_PERFECT_FILTERS][ETH_ALEN]; |
81 | u8 uc_addr[ENIC_UNICAST_PERFECT_FILTERS][ETH_ALEN]; | ||
81 | unsigned int flags; | 82 | unsigned int flags; |
82 | unsigned int mc_count; | 83 | unsigned int mc_count; |
84 | unsigned int uc_count; | ||
83 | int csum_rx_enabled; | 85 | int csum_rx_enabled; |
84 | u32 port_mtu; | 86 | u32 port_mtu; |
85 | u32 rx_coalesce_usecs; | 87 | u32 rx_coalesce_usecs; |
diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c index 9f293fa24768..1931f156777c 100644 --- a/drivers/net/enic/enic_main.c +++ b/drivers/net/enic/enic_main.c | |||
@@ -1002,7 +1002,7 @@ static int enic_dev_packet_filter(struct enic *enic, int directed, | |||
1002 | return err; | 1002 | return err; |
1003 | } | 1003 | } |
1004 | 1004 | ||
1005 | static int enic_dev_add_multicast_addr(struct enic *enic, u8 *addr) | 1005 | static int enic_dev_add_addr(struct enic *enic, u8 *addr) |
1006 | { | 1006 | { |
1007 | int err; | 1007 | int err; |
1008 | 1008 | ||
@@ -1013,7 +1013,7 @@ static int enic_dev_add_multicast_addr(struct enic *enic, u8 *addr) | |||
1013 | return err; | 1013 | return err; |
1014 | } | 1014 | } |
1015 | 1015 | ||
1016 | static int enic_dev_del_multicast_addr(struct enic *enic, u8 *addr) | 1016 | static int enic_dev_del_addr(struct enic *enic, u8 *addr) |
1017 | { | 1017 | { |
1018 | int err; | 1018 | int err; |
1019 | 1019 | ||
@@ -1024,29 +1024,19 @@ static int enic_dev_del_multicast_addr(struct enic *enic, u8 *addr) | |||
1024 | return err; | 1024 | return err; |
1025 | } | 1025 | } |
1026 | 1026 | ||
1027 | /* netif_tx_lock held, BHs disabled */ | 1027 | static void enic_add_multicast_addr_list(struct enic *enic) |
1028 | static void enic_set_multicast_list(struct net_device *netdev) | ||
1029 | { | 1028 | { |
1030 | struct enic *enic = netdev_priv(netdev); | 1029 | struct net_device *netdev = enic->netdev; |
1031 | struct netdev_hw_addr *ha; | 1030 | struct netdev_hw_addr *ha; |
1032 | int directed = 1; | ||
1033 | int multicast = (netdev->flags & IFF_MULTICAST) ? 1 : 0; | ||
1034 | int broadcast = (netdev->flags & IFF_BROADCAST) ? 1 : 0; | ||
1035 | int promisc = (netdev->flags & IFF_PROMISC) ? 1 : 0; | ||
1036 | unsigned int mc_count = netdev_mc_count(netdev); | 1031 | unsigned int mc_count = netdev_mc_count(netdev); |
1037 | int allmulti = (netdev->flags & IFF_ALLMULTI) || | ||
1038 | mc_count > ENIC_MULTICAST_PERFECT_FILTERS; | ||
1039 | unsigned int flags = netdev->flags | (allmulti ? IFF_ALLMULTI : 0); | ||
1040 | u8 mc_addr[ENIC_MULTICAST_PERFECT_FILTERS][ETH_ALEN]; | 1032 | u8 mc_addr[ENIC_MULTICAST_PERFECT_FILTERS][ETH_ALEN]; |
1041 | unsigned int i, j; | 1033 | unsigned int i, j; |
1042 | 1034 | ||
1043 | if (mc_count > ENIC_MULTICAST_PERFECT_FILTERS) | 1035 | if (mc_count > ENIC_MULTICAST_PERFECT_FILTERS) { |
1036 | netdev_warn(netdev, "Registering only %d out of %d " | ||
1037 | "multicast addresses\n", | ||
1038 | ENIC_MULTICAST_PERFECT_FILTERS, mc_count); | ||
1044 | mc_count = ENIC_MULTICAST_PERFECT_FILTERS; | 1039 | mc_count = ENIC_MULTICAST_PERFECT_FILTERS; |
1045 | |||
1046 | if (enic->flags != flags) { | ||
1047 | enic->flags = flags; | ||
1048 | enic_dev_packet_filter(enic, directed, | ||
1049 | multicast, broadcast, promisc, allmulti); | ||
1050 | } | 1040 | } |
1051 | 1041 | ||
1052 | /* Is there an easier way? Trying to minimize to | 1042 | /* Is there an easier way? Trying to minimize to |
@@ -1068,7 +1058,7 @@ static void enic_set_multicast_list(struct net_device *netdev) | |||
1068 | mc_addr[j]) == 0) | 1058 | mc_addr[j]) == 0) |
1069 | break; | 1059 | break; |
1070 | if (j == mc_count) | 1060 | if (j == mc_count) |
1071 | enic_dev_del_multicast_addr(enic, enic->mc_addr[i]); | 1061 | enic_dev_del_addr(enic, enic->mc_addr[i]); |
1072 | } | 1062 | } |
1073 | 1063 | ||
1074 | for (i = 0; i < mc_count; i++) { | 1064 | for (i = 0; i < mc_count; i++) { |
@@ -1077,7 +1067,7 @@ static void enic_set_multicast_list(struct net_device *netdev) | |||
1077 | enic->mc_addr[j]) == 0) | 1067 | enic->mc_addr[j]) == 0) |
1078 | break; | 1068 | break; |
1079 | if (j == enic->mc_count) | 1069 | if (j == enic->mc_count) |
1080 | enic_dev_add_multicast_addr(enic, mc_addr[i]); | 1070 | enic_dev_add_addr(enic, mc_addr[i]); |
1081 | } | 1071 | } |
1082 | 1072 | ||
1083 | /* Save the list to compare against next time | 1073 | /* Save the list to compare against next time |
@@ -1089,6 +1079,89 @@ static void enic_set_multicast_list(struct net_device *netdev) | |||
1089 | enic->mc_count = mc_count; | 1079 | enic->mc_count = mc_count; |
1090 | } | 1080 | } |
1091 | 1081 | ||
1082 | static void enic_add_unicast_addr_list(struct enic *enic) | ||
1083 | { | ||
1084 | struct net_device *netdev = enic->netdev; | ||
1085 | struct netdev_hw_addr *ha; | ||
1086 | unsigned int uc_count = netdev_uc_count(netdev); | ||
1087 | u8 uc_addr[ENIC_UNICAST_PERFECT_FILTERS][ETH_ALEN]; | ||
1088 | unsigned int i, j; | ||
1089 | |||
1090 | if (uc_count > ENIC_UNICAST_PERFECT_FILTERS) { | ||
1091 | netdev_warn(netdev, "Registering only %d out of %d " | ||
1092 | "unicast addresses\n", | ||
1093 | ENIC_UNICAST_PERFECT_FILTERS, uc_count); | ||
1094 | uc_count = ENIC_UNICAST_PERFECT_FILTERS; | ||
1095 | } | ||
1096 | |||
1097 | /* Is there an easier way? Trying to minimize to | ||
1098 | * calls to add/del unicast addrs. We keep the | ||
1099 | * addrs from the last call in enic->uc_addr and | ||
1100 | * look for changes to add/del. | ||
1101 | */ | ||
1102 | |||
1103 | i = 0; | ||
1104 | netdev_for_each_uc_addr(ha, netdev) { | ||
1105 | if (i == uc_count) | ||
1106 | break; | ||
1107 | memcpy(uc_addr[i++], ha->addr, ETH_ALEN); | ||
1108 | } | ||
1109 | |||
1110 | for (i = 0; i < enic->uc_count; i++) { | ||
1111 | for (j = 0; j < uc_count; j++) | ||
1112 | if (compare_ether_addr(enic->uc_addr[i], | ||
1113 | uc_addr[j]) == 0) | ||
1114 | break; | ||
1115 | if (j == uc_count) | ||
1116 | enic_dev_del_addr(enic, enic->uc_addr[i]); | ||
1117 | } | ||
1118 | |||
1119 | for (i = 0; i < uc_count; i++) { | ||
1120 | for (j = 0; j < enic->uc_count; j++) | ||
1121 | if (compare_ether_addr(uc_addr[i], | ||
1122 | enic->uc_addr[j]) == 0) | ||
1123 | break; | ||
1124 | if (j == enic->uc_count) | ||
1125 | enic_dev_add_addr(enic, uc_addr[i]); | ||
1126 | } | ||
1127 | |||
1128 | /* Save the list to compare against next time | ||
1129 | */ | ||
1130 | |||
1131 | for (i = 0; i < uc_count; i++) | ||
1132 | memcpy(enic->uc_addr[i], uc_addr[i], ETH_ALEN); | ||
1133 | |||
1134 | enic->uc_count = uc_count; | ||
1135 | } | ||
1136 | |||
1137 | /* netif_tx_lock held, BHs disabled */ | ||
1138 | static void enic_set_rx_mode(struct net_device *netdev) | ||
1139 | { | ||
1140 | struct enic *enic = netdev_priv(netdev); | ||
1141 | int directed = 1; | ||
1142 | int multicast = (netdev->flags & IFF_MULTICAST) ? 1 : 0; | ||
1143 | int broadcast = (netdev->flags & IFF_BROADCAST) ? 1 : 0; | ||
1144 | int promisc = (netdev->flags & IFF_PROMISC) || | ||
1145 | netdev_uc_count(netdev) > ENIC_UNICAST_PERFECT_FILTERS; | ||
1146 | int allmulti = (netdev->flags & IFF_ALLMULTI) || | ||
1147 | netdev_mc_count(netdev) > ENIC_MULTICAST_PERFECT_FILTERS; | ||
1148 | unsigned int flags = netdev->flags | | ||
1149 | (allmulti ? IFF_ALLMULTI : 0) | | ||
1150 | (promisc ? IFF_PROMISC : 0); | ||
1151 | |||
1152 | if (enic->flags != flags) { | ||
1153 | enic->flags = flags; | ||
1154 | enic_dev_packet_filter(enic, directed, | ||
1155 | multicast, broadcast, promisc, allmulti); | ||
1156 | } | ||
1157 | |||
1158 | if (!promisc) { | ||
1159 | enic_add_unicast_addr_list(enic); | ||
1160 | if (!allmulti) | ||
1161 | enic_add_multicast_addr_list(enic); | ||
1162 | } | ||
1163 | } | ||
1164 | |||
1092 | /* rtnl lock is held */ | 1165 | /* rtnl lock is held */ |
1093 | static void enic_vlan_rx_register(struct net_device *netdev, | 1166 | static void enic_vlan_rx_register(struct net_device *netdev, |
1094 | struct vlan_group *vlan_group) | 1167 | struct vlan_group *vlan_group) |
@@ -1852,7 +1925,7 @@ static int enic_open(struct net_device *netdev) | |||
1852 | vnic_rq_enable(&enic->rq[i]); | 1925 | vnic_rq_enable(&enic->rq[i]); |
1853 | 1926 | ||
1854 | enic_dev_add_station_addr(enic); | 1927 | enic_dev_add_station_addr(enic); |
1855 | enic_set_multicast_list(netdev); | 1928 | enic_set_rx_mode(netdev); |
1856 | 1929 | ||
1857 | netif_wake_queue(netdev); | 1930 | netif_wake_queue(netdev); |
1858 | 1931 | ||
@@ -2328,7 +2401,8 @@ static const struct net_device_ops enic_netdev_dynamic_ops = { | |||
2328 | .ndo_start_xmit = enic_hard_start_xmit, | 2401 | .ndo_start_xmit = enic_hard_start_xmit, |
2329 | .ndo_get_stats = enic_get_stats, | 2402 | .ndo_get_stats = enic_get_stats, |
2330 | .ndo_validate_addr = eth_validate_addr, | 2403 | .ndo_validate_addr = eth_validate_addr, |
2331 | .ndo_set_multicast_list = enic_set_multicast_list, | 2404 | .ndo_set_rx_mode = enic_set_rx_mode, |
2405 | .ndo_set_multicast_list = enic_set_rx_mode, | ||
2332 | .ndo_set_mac_address = enic_set_mac_address_dynamic, | 2406 | .ndo_set_mac_address = enic_set_mac_address_dynamic, |
2333 | .ndo_change_mtu = enic_change_mtu, | 2407 | .ndo_change_mtu = enic_change_mtu, |
2334 | .ndo_vlan_rx_register = enic_vlan_rx_register, | 2408 | .ndo_vlan_rx_register = enic_vlan_rx_register, |
@@ -2349,7 +2423,8 @@ static const struct net_device_ops enic_netdev_ops = { | |||
2349 | .ndo_get_stats = enic_get_stats, | 2423 | .ndo_get_stats = enic_get_stats, |
2350 | .ndo_validate_addr = eth_validate_addr, | 2424 | .ndo_validate_addr = eth_validate_addr, |
2351 | .ndo_set_mac_address = enic_set_mac_address, | 2425 | .ndo_set_mac_address = enic_set_mac_address, |
2352 | .ndo_set_multicast_list = enic_set_multicast_list, | 2426 | .ndo_set_rx_mode = enic_set_rx_mode, |
2427 | .ndo_set_multicast_list = enic_set_rx_mode, | ||
2353 | .ndo_change_mtu = enic_change_mtu, | 2428 | .ndo_change_mtu = enic_change_mtu, |
2354 | .ndo_vlan_rx_register = enic_vlan_rx_register, | 2429 | .ndo_vlan_rx_register = enic_vlan_rx_register, |
2355 | .ndo_vlan_rx_add_vid = enic_vlan_rx_add_vid, | 2430 | .ndo_vlan_rx_add_vid = enic_vlan_rx_add_vid, |
diff --git a/drivers/net/enic/enic_res.h b/drivers/net/enic/enic_res.h index 9a103d9ef9e2..25be2734c3fe 100644 --- a/drivers/net/enic/enic_res.h +++ b/drivers/net/enic/enic_res.h | |||
@@ -34,6 +34,7 @@ | |||
34 | #define ENIC_MAX_MTU 9000 | 34 | #define ENIC_MAX_MTU 9000 |
35 | 35 | ||
36 | #define ENIC_MULTICAST_PERFECT_FILTERS 32 | 36 | #define ENIC_MULTICAST_PERFECT_FILTERS 32 |
37 | #define ENIC_UNICAST_PERFECT_FILTERS 32 | ||
37 | 38 | ||
38 | #define ENIC_NON_TSO_MAX_DESC 16 | 39 | #define ENIC_NON_TSO_MAX_DESC 16 |
39 | 40 | ||