diff options
author | Shahed Shaikh <shahed.shaikh@qlogic.com> | 2013-05-21 05:27:01 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-05-22 17:52:40 -0400 |
commit | 147a90887baa98d73db1fa7ed9e755bf48960c21 (patch) | |
tree | a86f12f683de6ca93113ded2498b89748dd0f8b5 /drivers/net/ethernet | |
parent | 0ce54ce4aaef1389fb8d640271748ace257cb763 (diff) |
qlcnic: Fix updating netdev->features
o After change in EPORT features of 82xx adapter, netdev->features needs to
be updated to reflect EPORT feature updates but driver was manipulating
netdev->features at wrong place.
o This patch uses netdev_update_features() and .ndo_fix_features() to
update netdev->features properly.
Signed-off-by: Shahed Shaikh <shahed.shaikh@qlogic.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet')
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic.h | 6 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c | 49 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c | 49 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c | 3 |
4 files changed, 61 insertions, 46 deletions
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h index 019c5f78732e..c1b693cb3df3 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h | |||
@@ -907,8 +907,11 @@ struct qlcnic_ipaddr { | |||
907 | #define QLCNIC_FW_HANG 0x4000 | 907 | #define QLCNIC_FW_HANG 0x4000 |
908 | #define QLCNIC_FW_LRO_MSS_CAP 0x8000 | 908 | #define QLCNIC_FW_LRO_MSS_CAP 0x8000 |
909 | #define QLCNIC_TX_INTR_SHARED 0x10000 | 909 | #define QLCNIC_TX_INTR_SHARED 0x10000 |
910 | #define QLCNIC_APP_CHANGED_FLAGS 0x20000 | ||
910 | #define QLCNIC_IS_MSI_FAMILY(adapter) \ | 911 | #define QLCNIC_IS_MSI_FAMILY(adapter) \ |
911 | ((adapter)->flags & (QLCNIC_MSI_ENABLED | QLCNIC_MSIX_ENABLED)) | 912 | ((adapter)->flags & (QLCNIC_MSI_ENABLED | QLCNIC_MSIX_ENABLED)) |
913 | #define QLCNIC_IS_TSO_CAPABLE(adapter) \ | ||
914 | ((adapter)->ahw->capabilities & QLCNIC_FW_CAPABILITY_TSO) | ||
912 | 915 | ||
913 | #define QLCNIC_DEF_NUM_STS_DESC_RINGS 4 | 916 | #define QLCNIC_DEF_NUM_STS_DESC_RINGS 4 |
914 | #define QLCNIC_MSIX_TBL_SPACE 8192 | 917 | #define QLCNIC_MSIX_TBL_SPACE 8192 |
@@ -1034,6 +1037,7 @@ struct qlcnic_adapter { | |||
1034 | spinlock_t rx_mac_learn_lock; | 1037 | spinlock_t rx_mac_learn_lock; |
1035 | u32 file_prd_off; /*File fw product offset*/ | 1038 | u32 file_prd_off; /*File fw product offset*/ |
1036 | u32 fw_version; | 1039 | u32 fw_version; |
1040 | u32 offload_flags; | ||
1037 | const struct firmware *fw; | 1041 | const struct firmware *fw; |
1038 | }; | 1042 | }; |
1039 | 1043 | ||
@@ -1542,6 +1546,8 @@ void qlcnic_add_lb_filter(struct qlcnic_adapter *, struct sk_buff *, int, u16); | |||
1542 | int qlcnic_83xx_configure_opmode(struct qlcnic_adapter *adapter); | 1546 | int qlcnic_83xx_configure_opmode(struct qlcnic_adapter *adapter); |
1543 | int qlcnic_read_mac_addr(struct qlcnic_adapter *); | 1547 | int qlcnic_read_mac_addr(struct qlcnic_adapter *); |
1544 | int qlcnic_setup_netdev(struct qlcnic_adapter *, struct net_device *, int); | 1548 | int qlcnic_setup_netdev(struct qlcnic_adapter *, struct net_device *, int); |
1549 | void qlcnic_set_netdev_features(struct qlcnic_adapter *, | ||
1550 | struct qlcnic_esw_func_cfg *); | ||
1545 | void qlcnic_sriov_vf_schedule_multi(struct net_device *); | 1551 | void qlcnic_sriov_vf_schedule_multi(struct net_device *); |
1546 | void qlcnic_vf_add_mc_list(struct net_device *, u16); | 1552 | void qlcnic_vf_add_mc_list(struct net_device *, u16); |
1547 | 1553 | ||
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c index 6a6512ba9f38..106a12f2a02f 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c | |||
@@ -973,16 +973,57 @@ int qlcnic_change_mtu(struct net_device *netdev, int mtu) | |||
973 | return rc; | 973 | return rc; |
974 | } | 974 | } |
975 | 975 | ||
976 | static netdev_features_t qlcnic_process_flags(struct qlcnic_adapter *adapter, | ||
977 | netdev_features_t features) | ||
978 | { | ||
979 | u32 offload_flags = adapter->offload_flags; | ||
980 | |||
981 | if (offload_flags & BIT_0) { | ||
982 | features |= NETIF_F_RXCSUM | NETIF_F_IP_CSUM | | ||
983 | NETIF_F_IPV6_CSUM; | ||
984 | adapter->rx_csum = 1; | ||
985 | if (QLCNIC_IS_TSO_CAPABLE(adapter)) { | ||
986 | if (!(offload_flags & BIT_1)) | ||
987 | features &= ~NETIF_F_TSO; | ||
988 | else | ||
989 | features |= NETIF_F_TSO; | ||
990 | |||
991 | if (!(offload_flags & BIT_2)) | ||
992 | features &= ~NETIF_F_TSO6; | ||
993 | else | ||
994 | features |= NETIF_F_TSO6; | ||
995 | } | ||
996 | } else { | ||
997 | features &= ~(NETIF_F_RXCSUM | | ||
998 | NETIF_F_IP_CSUM | | ||
999 | NETIF_F_IPV6_CSUM); | ||
1000 | |||
1001 | if (QLCNIC_IS_TSO_CAPABLE(adapter)) | ||
1002 | features &= ~(NETIF_F_TSO | NETIF_F_TSO6); | ||
1003 | adapter->rx_csum = 0; | ||
1004 | } | ||
1005 | |||
1006 | return features; | ||
1007 | } | ||
976 | 1008 | ||
977 | netdev_features_t qlcnic_fix_features(struct net_device *netdev, | 1009 | netdev_features_t qlcnic_fix_features(struct net_device *netdev, |
978 | netdev_features_t features) | 1010 | netdev_features_t features) |
979 | { | 1011 | { |
980 | struct qlcnic_adapter *adapter = netdev_priv(netdev); | 1012 | struct qlcnic_adapter *adapter = netdev_priv(netdev); |
1013 | netdev_features_t changed; | ||
981 | 1014 | ||
982 | if ((adapter->flags & QLCNIC_ESWITCH_ENABLED) && | 1015 | if (qlcnic_82xx_check(adapter) && |
983 | qlcnic_82xx_check(adapter)) { | 1016 | (adapter->flags & QLCNIC_ESWITCH_ENABLED)) { |
984 | netdev_features_t changed = features ^ netdev->features; | 1017 | if (adapter->flags & QLCNIC_APP_CHANGED_FLAGS) { |
985 | features ^= changed & (NETIF_F_ALL_CSUM | NETIF_F_RXCSUM); | 1018 | features = qlcnic_process_flags(adapter, features); |
1019 | } else { | ||
1020 | changed = features ^ netdev->features; | ||
1021 | features ^= changed & (NETIF_F_RXCSUM | | ||
1022 | NETIF_F_IP_CSUM | | ||
1023 | NETIF_F_IPV6_CSUM | | ||
1024 | NETIF_F_TSO | | ||
1025 | NETIF_F_TSO6); | ||
1026 | } | ||
986 | } | 1027 | } |
987 | 1028 | ||
988 | if (!(features & NETIF_F_RXCSUM)) | 1029 | if (!(features & NETIF_F_RXCSUM)) |
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c index 0da38df51793..aeb26a850679 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c | |||
@@ -84,14 +84,9 @@ static int qlcnic_start_firmware(struct qlcnic_adapter *); | |||
84 | static void qlcnic_free_lb_filters_mem(struct qlcnic_adapter *adapter); | 84 | static void qlcnic_free_lb_filters_mem(struct qlcnic_adapter *adapter); |
85 | static void qlcnic_dev_set_npar_ready(struct qlcnic_adapter *); | 85 | static void qlcnic_dev_set_npar_ready(struct qlcnic_adapter *); |
86 | static int qlcnicvf_start_firmware(struct qlcnic_adapter *); | 86 | static int qlcnicvf_start_firmware(struct qlcnic_adapter *); |
87 | static void qlcnic_set_netdev_features(struct qlcnic_adapter *, | ||
88 | struct qlcnic_esw_func_cfg *); | ||
89 | static int qlcnic_vlan_rx_add(struct net_device *, __be16, u16); | 87 | static int qlcnic_vlan_rx_add(struct net_device *, __be16, u16); |
90 | static int qlcnic_vlan_rx_del(struct net_device *, __be16, u16); | 88 | static int qlcnic_vlan_rx_del(struct net_device *, __be16, u16); |
91 | 89 | ||
92 | #define QLCNIC_IS_TSO_CAPABLE(adapter) \ | ||
93 | ((adapter)->ahw->capabilities & QLCNIC_FW_CAPABILITY_TSO) | ||
94 | |||
95 | static u32 qlcnic_vlan_tx_check(struct qlcnic_adapter *adapter) | 90 | static u32 qlcnic_vlan_tx_check(struct qlcnic_adapter *adapter) |
96 | { | 91 | { |
97 | struct qlcnic_hardware_context *ahw = adapter->ahw; | 92 | struct qlcnic_hardware_context *ahw = adapter->ahw; |
@@ -1074,8 +1069,6 @@ void qlcnic_set_eswitch_port_features(struct qlcnic_adapter *adapter, | |||
1074 | 1069 | ||
1075 | if (!esw_cfg->promisc_mode) | 1070 | if (!esw_cfg->promisc_mode) |
1076 | adapter->flags |= QLCNIC_PROMISC_DISABLED; | 1071 | adapter->flags |= QLCNIC_PROMISC_DISABLED; |
1077 | |||
1078 | qlcnic_set_netdev_features(adapter, esw_cfg); | ||
1079 | } | 1072 | } |
1080 | 1073 | ||
1081 | int qlcnic_set_eswitch_port_config(struct qlcnic_adapter *adapter) | 1074 | int qlcnic_set_eswitch_port_config(struct qlcnic_adapter *adapter) |
@@ -1090,51 +1083,23 @@ int qlcnic_set_eswitch_port_config(struct qlcnic_adapter *adapter) | |||
1090 | return -EIO; | 1083 | return -EIO; |
1091 | qlcnic_set_vlan_config(adapter, &esw_cfg); | 1084 | qlcnic_set_vlan_config(adapter, &esw_cfg); |
1092 | qlcnic_set_eswitch_port_features(adapter, &esw_cfg); | 1085 | qlcnic_set_eswitch_port_features(adapter, &esw_cfg); |
1086 | qlcnic_set_netdev_features(adapter, &esw_cfg); | ||
1093 | 1087 | ||
1094 | return 0; | 1088 | return 0; |
1095 | } | 1089 | } |
1096 | 1090 | ||
1097 | static void | 1091 | void qlcnic_set_netdev_features(struct qlcnic_adapter *adapter, |
1098 | qlcnic_set_netdev_features(struct qlcnic_adapter *adapter, | 1092 | struct qlcnic_esw_func_cfg *esw_cfg) |
1099 | struct qlcnic_esw_func_cfg *esw_cfg) | ||
1100 | { | 1093 | { |
1101 | struct net_device *netdev = adapter->netdev; | 1094 | struct net_device *netdev = adapter->netdev; |
1102 | unsigned long features, vlan_features; | ||
1103 | 1095 | ||
1104 | if (qlcnic_83xx_check(adapter)) | 1096 | if (qlcnic_83xx_check(adapter)) |
1105 | return; | 1097 | return; |
1106 | 1098 | ||
1107 | features = (NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_RXCSUM | | 1099 | adapter->offload_flags = esw_cfg->offload_flags; |
1108 | NETIF_F_IPV6_CSUM | NETIF_F_GRO); | 1100 | adapter->flags |= QLCNIC_APP_CHANGED_FLAGS; |
1109 | vlan_features = (NETIF_F_SG | NETIF_F_IP_CSUM | | 1101 | netdev_update_features(netdev); |
1110 | NETIF_F_IPV6_CSUM); | 1102 | adapter->flags &= ~QLCNIC_APP_CHANGED_FLAGS; |
1111 | |||
1112 | if (QLCNIC_IS_TSO_CAPABLE(adapter)) { | ||
1113 | features |= (NETIF_F_TSO | NETIF_F_TSO6); | ||
1114 | vlan_features |= (NETIF_F_TSO | NETIF_F_TSO6); | ||
1115 | } | ||
1116 | |||
1117 | if (netdev->features & NETIF_F_LRO) | ||
1118 | features |= NETIF_F_LRO; | ||
1119 | |||
1120 | if (esw_cfg->offload_flags & BIT_0) { | ||
1121 | netdev->features |= features; | ||
1122 | adapter->rx_csum = 1; | ||
1123 | if (!(esw_cfg->offload_flags & BIT_1)) { | ||
1124 | netdev->features &= ~NETIF_F_TSO; | ||
1125 | features &= ~NETIF_F_TSO; | ||
1126 | } | ||
1127 | if (!(esw_cfg->offload_flags & BIT_2)) { | ||
1128 | netdev->features &= ~NETIF_F_TSO6; | ||
1129 | features &= ~NETIF_F_TSO6; | ||
1130 | } | ||
1131 | } else { | ||
1132 | netdev->features &= ~features; | ||
1133 | features &= ~features; | ||
1134 | adapter->rx_csum = 0; | ||
1135 | } | ||
1136 | |||
1137 | netdev->vlan_features = (features & vlan_features); | ||
1138 | } | 1103 | } |
1139 | 1104 | ||
1140 | static int | 1105 | static int |
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c index 4e22e794a186..e7a2fe21b649 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c | |||
@@ -544,6 +544,9 @@ static ssize_t qlcnic_sysfs_write_esw_config(struct file *file, | |||
544 | switch (esw_cfg[i].op_mode) { | 544 | switch (esw_cfg[i].op_mode) { |
545 | case QLCNIC_PORT_DEFAULTS: | 545 | case QLCNIC_PORT_DEFAULTS: |
546 | qlcnic_set_eswitch_port_features(adapter, &esw_cfg[i]); | 546 | qlcnic_set_eswitch_port_features(adapter, &esw_cfg[i]); |
547 | rtnl_lock(); | ||
548 | qlcnic_set_netdev_features(adapter, &esw_cfg[i]); | ||
549 | rtnl_unlock(); | ||
547 | break; | 550 | break; |
548 | case QLCNIC_ADD_VLAN: | 551 | case QLCNIC_ADD_VLAN: |
549 | qlcnic_set_vlan_config(adapter, &esw_cfg[i]); | 552 | qlcnic_set_vlan_config(adapter, &esw_cfg[i]); |