diff options
author | Rajesh Borundia <rajesh.borundia@qlogic.com> | 2010-08-19 01:08:25 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-08-19 19:52:38 -0400 |
commit | 4e8acb011f0e9e86e29b53ff051e699ba0c5726d (patch) | |
tree | a8f74029aa29ce99403f283a6c33368bda0762b9 /drivers/net/qlcnic | |
parent | 251b036a22f530aff26cf70f5cdb0cf64a072e46 (diff) |
qlcnic: configure port on eswitch
o Nic partition capable devices has embedded switch, this needs to support
various features like external switch.
Signed-off-by: Rajesh Borundia <rajesh.borundia@qlogic.com>
Signed-off-by: Amit Kumar Salecha <amit.salecha@qlogic.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/qlcnic')
-rw-r--r-- | drivers/net/qlcnic/qlcnic.h | 22 | ||||
-rw-r--r-- | drivers/net/qlcnic/qlcnic_ctx.c | 174 | ||||
-rw-r--r-- | drivers/net/qlcnic/qlcnic_hdr.h | 7 | ||||
-rw-r--r-- | drivers/net/qlcnic/qlcnic_main.c | 185 |
4 files changed, 254 insertions, 134 deletions
diff --git a/drivers/net/qlcnic/qlcnic.h b/drivers/net/qlcnic/qlcnic.h index d19836758c6e..9433a05555f1 100644 --- a/drivers/net/qlcnic/qlcnic.h +++ b/drivers/net/qlcnic/qlcnic.h | |||
@@ -556,6 +556,7 @@ struct qlcnic_recv_context { | |||
556 | #define QLCNIC_CDRP_CMD_GET_ESWITCH_STATUS 0x00000026 | 556 | #define QLCNIC_CDRP_CMD_GET_ESWITCH_STATUS 0x00000026 |
557 | #define QLCNIC_CDRP_CMD_SET_PORTMIRRORING 0x00000027 | 557 | #define QLCNIC_CDRP_CMD_SET_PORTMIRRORING 0x00000027 |
558 | #define QLCNIC_CDRP_CMD_CONFIGURE_ESWITCH 0x00000028 | 558 | #define QLCNIC_CDRP_CMD_CONFIGURE_ESWITCH 0x00000028 |
559 | #define QLCNIC_CDRP_CMD_GET_ESWITCH_PORT_CONFIG 0x00000029 | ||
559 | #define QLCNIC_CDRP_CMD_GET_ESWITCH_STATS 0x0000002a | 560 | #define QLCNIC_CDRP_CMD_GET_ESWITCH_STATS 0x0000002a |
560 | 561 | ||
561 | #define QLCNIC_RCODE_SUCCESS 0 | 562 | #define QLCNIC_RCODE_SUCCESS 0 |
@@ -1044,7 +1045,7 @@ struct qlcnic_pci_info { | |||
1044 | }; | 1045 | }; |
1045 | 1046 | ||
1046 | struct qlcnic_npar_info { | 1047 | struct qlcnic_npar_info { |
1047 | u16 vlan_id; | 1048 | u16 pvid; |
1048 | u16 min_bw; | 1049 | u16 min_bw; |
1049 | u16 max_bw; | 1050 | u16 max_bw; |
1050 | u8 phy_port; | 1051 | u8 phy_port; |
@@ -1052,11 +1053,13 @@ struct qlcnic_npar_info { | |||
1052 | u8 active; | 1053 | u8 active; |
1053 | u8 enable_pm; | 1054 | u8 enable_pm; |
1054 | u8 dest_npar; | 1055 | u8 dest_npar; |
1055 | u8 host_vlan_tag; | ||
1056 | u8 promisc_mode; | ||
1057 | u8 discard_tagged; | 1056 | u8 discard_tagged; |
1058 | u8 mac_learning; | 1057 | u8 mac_learning; |
1058 | u8 mac_anti_spoof; | ||
1059 | u8 promisc_mode; | ||
1060 | u8 offload_flags; | ||
1059 | }; | 1061 | }; |
1062 | |||
1060 | struct qlcnic_eswitch { | 1063 | struct qlcnic_eswitch { |
1061 | u8 port; | 1064 | u8 port; |
1062 | u8 active_vports; | 1065 | u8 active_vports; |
@@ -1088,7 +1091,6 @@ struct qlcnic_eswitch { | |||
1088 | #define IS_VALID_BW(bw) (bw >= MIN_BW && bw <= MAX_BW) | 1091 | #define IS_VALID_BW(bw) (bw >= MIN_BW && bw <= MAX_BW) |
1089 | #define IS_VALID_TX_QUEUES(que) (que > 0 && que <= MAX_TX_QUEUES) | 1092 | #define IS_VALID_TX_QUEUES(que) (que > 0 && que <= MAX_TX_QUEUES) |
1090 | #define IS_VALID_RX_QUEUES(que) (que > 0 && que <= MAX_RX_QUEUES) | 1093 | #define IS_VALID_RX_QUEUES(que) (que > 0 && que <= MAX_RX_QUEUES) |
1091 | #define IS_VALID_MODE(mode) (mode == 0 || mode == 1) | ||
1092 | 1094 | ||
1093 | struct qlcnic_pci_func_cfg { | 1095 | struct qlcnic_pci_func_cfg { |
1094 | u16 func_type; | 1096 | u16 func_type; |
@@ -1120,12 +1122,16 @@ struct qlcnic_pm_func_cfg { | |||
1120 | 1122 | ||
1121 | struct qlcnic_esw_func_cfg { | 1123 | struct qlcnic_esw_func_cfg { |
1122 | u16 vlan_id; | 1124 | u16 vlan_id; |
1125 | u8 op_mode; | ||
1126 | u8 op_type; | ||
1123 | u8 pci_func; | 1127 | u8 pci_func; |
1124 | u8 host_vlan_tag; | 1128 | u8 host_vlan_tag; |
1125 | u8 promisc_mode; | 1129 | u8 promisc_mode; |
1126 | u8 discard_tagged; | 1130 | u8 discard_tagged; |
1127 | u8 mac_learning; | 1131 | u8 mac_learning; |
1128 | u8 reserved; | 1132 | u8 mac_anti_spoof; |
1133 | u8 offload_flags; | ||
1134 | u8 reserved[5]; | ||
1129 | }; | 1135 | }; |
1130 | 1136 | ||
1131 | #define QLCNIC_STATS_VERSION 1 | 1137 | #define QLCNIC_STATS_VERSION 1 |
@@ -1276,8 +1282,10 @@ int qlcnic_get_eswitch_capabilities(struct qlcnic_adapter *, u8, | |||
1276 | int qlcnic_get_eswitch_status(struct qlcnic_adapter *, u8, | 1282 | int qlcnic_get_eswitch_status(struct qlcnic_adapter *, u8, |
1277 | struct qlcnic_eswitch *); | 1283 | struct qlcnic_eswitch *); |
1278 | int qlcnic_toggle_eswitch(struct qlcnic_adapter *, u8, u8); | 1284 | int qlcnic_toggle_eswitch(struct qlcnic_adapter *, u8, u8); |
1279 | int qlcnic_config_switch_port(struct qlcnic_adapter *, u8, int, u8, u8, | 1285 | int qlcnic_config_switch_port(struct qlcnic_adapter *, |
1280 | u8, u8, u16); | 1286 | struct qlcnic_esw_func_cfg *); |
1287 | int qlcnic_get_eswitch_port_config(struct qlcnic_adapter *, | ||
1288 | struct qlcnic_esw_func_cfg *); | ||
1281 | int qlcnic_config_port_mirroring(struct qlcnic_adapter *, u8, u8, u8); | 1289 | int qlcnic_config_port_mirroring(struct qlcnic_adapter *, u8, u8, u8); |
1282 | int qlcnic_get_port_stats(struct qlcnic_adapter *, const u8, const u8, | 1290 | int qlcnic_get_port_stats(struct qlcnic_adapter *, const u8, const u8, |
1283 | struct __qlcnic_esw_statistics *); | 1291 | struct __qlcnic_esw_statistics *); |
diff --git a/drivers/net/qlcnic/qlcnic_ctx.c b/drivers/net/qlcnic/qlcnic_ctx.c index 57c9b09bd16a..74ae3b0a5ea8 100644 --- a/drivers/net/qlcnic/qlcnic_ctx.c +++ b/drivers/net/qlcnic/qlcnic_ctx.c | |||
@@ -813,9 +813,8 @@ int qlcnic_get_eswitch_capabilities(struct qlcnic_adapter *adapter, u8 port, | |||
813 | arg2 = QLCRD32(adapter, QLCNIC_ARG2_CRB_OFFSET); | 813 | arg2 = QLCRD32(adapter, QLCNIC_ARG2_CRB_OFFSET); |
814 | 814 | ||
815 | eswitch->port = arg1 & 0xf; | 815 | eswitch->port = arg1 & 0xf; |
816 | eswitch->active_vports = LSB(arg2); | 816 | eswitch->max_ucast_filters = LSW(arg2); |
817 | eswitch->max_ucast_filters = MSB(arg2); | 817 | eswitch->max_active_vlans = MSW(arg2) & 0xfff; |
818 | eswitch->max_active_vlans = LSB(MSW(arg2)); | ||
819 | if (arg1 & BIT_6) | 818 | if (arg1 & BIT_6) |
820 | eswitch->flags |= QLCNIC_SWITCH_VLAN_FILTERING; | 819 | eswitch->flags |= QLCNIC_SWITCH_VLAN_FILTERING; |
821 | if (arg1 & BIT_7) | 820 | if (arg1 & BIT_7) |
@@ -943,47 +942,6 @@ int qlcnic_config_port_mirroring(struct qlcnic_adapter *adapter, u8 id, | |||
943 | return err; | 942 | return err; |
944 | } | 943 | } |
945 | 944 | ||
946 | /* Configure eSwitch port */ | ||
947 | int qlcnic_config_switch_port(struct qlcnic_adapter *adapter, u8 id, | ||
948 | int vlan_tagging, u8 discard_tagged, u8 promsc_mode, | ||
949 | u8 mac_learn, u8 pci_func, u16 vlan_id) | ||
950 | { | ||
951 | int err = -EIO; | ||
952 | u32 arg1; | ||
953 | struct qlcnic_eswitch *eswitch; | ||
954 | |||
955 | if (adapter->op_mode != QLCNIC_MGMT_FUNC) | ||
956 | return err; | ||
957 | |||
958 | eswitch = &adapter->eswitch[id]; | ||
959 | if (!(eswitch->flags & QLCNIC_SWITCH_ENABLE)) | ||
960 | return err; | ||
961 | |||
962 | arg1 = eswitch->port | (discard_tagged ? BIT_4 : 0); | ||
963 | arg1 |= (promsc_mode ? BIT_6 : 0) | (mac_learn ? BIT_7 : 0); | ||
964 | arg1 |= pci_func << 8; | ||
965 | if (vlan_tagging) | ||
966 | arg1 |= BIT_5 | (vlan_id << 16); | ||
967 | |||
968 | err = qlcnic_issue_cmd(adapter, | ||
969 | adapter->ahw.pci_func, | ||
970 | adapter->fw_hal_version, | ||
971 | arg1, | ||
972 | 0, | ||
973 | 0, | ||
974 | QLCNIC_CDRP_CMD_CONFIGURE_ESWITCH); | ||
975 | |||
976 | if (err != QLCNIC_RCODE_SUCCESS) { | ||
977 | dev_err(&adapter->pdev->dev, | ||
978 | "Failed to configure eswitch port%d\n", eswitch->port); | ||
979 | } else { | ||
980 | dev_info(&adapter->pdev->dev, | ||
981 | "Configured eSwitch for port %d\n", eswitch->port); | ||
982 | } | ||
983 | |||
984 | return err; | ||
985 | } | ||
986 | |||
987 | int qlcnic_get_port_stats(struct qlcnic_adapter *adapter, const u8 func, | 945 | int qlcnic_get_port_stats(struct qlcnic_adapter *adapter, const u8 func, |
988 | const u8 rx_tx, struct __qlcnic_esw_statistics *esw_stats) { | 946 | const u8 rx_tx, struct __qlcnic_esw_statistics *esw_stats) { |
989 | 947 | ||
@@ -1108,3 +1066,131 @@ err_ret: | |||
1108 | "rx_ctx=%d\n", func_esw, port, rx_tx); | 1066 | "rx_ctx=%d\n", func_esw, port, rx_tx); |
1109 | return -EIO; | 1067 | return -EIO; |
1110 | } | 1068 | } |
1069 | |||
1070 | static int | ||
1071 | __qlcnic_get_eswitch_port_config(struct qlcnic_adapter *adapter, | ||
1072 | u32 *arg1, u32 *arg2) | ||
1073 | { | ||
1074 | int err = -EIO; | ||
1075 | u8 pci_func; | ||
1076 | pci_func = (*arg1 >> 8); | ||
1077 | err = qlcnic_issue_cmd(adapter, | ||
1078 | adapter->ahw.pci_func, | ||
1079 | adapter->fw_hal_version, | ||
1080 | *arg1, | ||
1081 | 0, | ||
1082 | 0, | ||
1083 | QLCNIC_CDRP_CMD_GET_ESWITCH_PORT_CONFIG); | ||
1084 | |||
1085 | if (err == QLCNIC_RCODE_SUCCESS) { | ||
1086 | *arg1 = QLCRD32(adapter, QLCNIC_ARG1_CRB_OFFSET); | ||
1087 | *arg2 = QLCRD32(adapter, QLCNIC_ARG2_CRB_OFFSET); | ||
1088 | dev_info(&adapter->pdev->dev, | ||
1089 | "eSwitch port config for pci func%d\n", pci_func); | ||
1090 | } else { | ||
1091 | dev_err(&adapter->pdev->dev, | ||
1092 | "Failed to get eswitch port config%d\n", pci_func); | ||
1093 | } | ||
1094 | return err; | ||
1095 | } | ||
1096 | /* Configure eSwitch port | ||
1097 | op_mode = 0 for setting default port behavior | ||
1098 | op_mode = 1 for setting vlan id | ||
1099 | op_mode = 2 for deleting vlan id | ||
1100 | op_type = 0 for vlan_id | ||
1101 | op_type = 1 for port vlan_id | ||
1102 | */ | ||
1103 | int qlcnic_config_switch_port(struct qlcnic_adapter *adapter, | ||
1104 | struct qlcnic_esw_func_cfg *esw_cfg) | ||
1105 | { | ||
1106 | int err = -EIO; | ||
1107 | u32 arg1, arg2 = 0; | ||
1108 | u8 pci_func; | ||
1109 | |||
1110 | if (adapter->op_mode != QLCNIC_MGMT_FUNC) | ||
1111 | return err; | ||
1112 | pci_func = esw_cfg->pci_func; | ||
1113 | arg1 = (adapter->npars[pci_func].phy_port & BIT_0); | ||
1114 | arg1 |= (pci_func << 8); | ||
1115 | |||
1116 | if (__qlcnic_get_eswitch_port_config(adapter, &arg1, &arg2)) | ||
1117 | return err; | ||
1118 | arg1 &= ~(0x0ff << 8); | ||
1119 | arg1 |= (pci_func << 8); | ||
1120 | arg1 &= ~(BIT_2 | BIT_3); | ||
1121 | switch (esw_cfg->op_mode) { | ||
1122 | case QLCNIC_PORT_DEFAULTS: | ||
1123 | arg1 |= (BIT_4 | BIT_6 | BIT_7); | ||
1124 | arg2 |= (BIT_0 | BIT_1); | ||
1125 | if (adapter->capabilities & QLCNIC_FW_CAPABILITY_TSO) | ||
1126 | arg2 |= (BIT_2 | BIT_3); | ||
1127 | if (!(esw_cfg->discard_tagged)) | ||
1128 | arg1 &= ~BIT_4; | ||
1129 | if (!(esw_cfg->promisc_mode)) | ||
1130 | arg1 &= ~BIT_6; | ||
1131 | if (!(esw_cfg->mac_learning)) | ||
1132 | arg1 &= ~BIT_7; | ||
1133 | if (!(esw_cfg->mac_anti_spoof)) | ||
1134 | arg2 &= ~BIT_0; | ||
1135 | if (!(esw_cfg->offload_flags & BIT_0)) | ||
1136 | arg2 &= ~(BIT_1 | BIT_2 | BIT_3); | ||
1137 | if (!(esw_cfg->offload_flags & BIT_1)) | ||
1138 | arg2 &= ~BIT_2; | ||
1139 | if (!(esw_cfg->offload_flags & BIT_2)) | ||
1140 | arg2 &= ~BIT_3; | ||
1141 | break; | ||
1142 | case QLCNIC_ADD_VLAN: | ||
1143 | arg1 |= (BIT_2 | BIT_5); | ||
1144 | arg1 |= (esw_cfg->vlan_id << 16); | ||
1145 | break; | ||
1146 | case QLCNIC_DEL_VLAN: | ||
1147 | arg1 |= (BIT_3 | BIT_5); | ||
1148 | arg1 &= ~(0x0ffff << 16); | ||
1149 | default: | ||
1150 | return err; | ||
1151 | } | ||
1152 | |||
1153 | err = qlcnic_issue_cmd(adapter, | ||
1154 | adapter->ahw.pci_func, | ||
1155 | adapter->fw_hal_version, | ||
1156 | arg1, | ||
1157 | arg2, | ||
1158 | 0, | ||
1159 | QLCNIC_CDRP_CMD_CONFIGURE_ESWITCH); | ||
1160 | |||
1161 | if (err != QLCNIC_RCODE_SUCCESS) { | ||
1162 | dev_err(&adapter->pdev->dev, | ||
1163 | "Failed to configure eswitch port%d\n", pci_func); | ||
1164 | } else { | ||
1165 | dev_info(&adapter->pdev->dev, | ||
1166 | "Configured eSwitch for port %d\n", pci_func); | ||
1167 | } | ||
1168 | |||
1169 | return err; | ||
1170 | } | ||
1171 | |||
1172 | int | ||
1173 | qlcnic_get_eswitch_port_config(struct qlcnic_adapter *adapter, | ||
1174 | struct qlcnic_esw_func_cfg *esw_cfg) | ||
1175 | { | ||
1176 | u32 arg1, arg2; | ||
1177 | u8 phy_port; | ||
1178 | if (adapter->op_mode == QLCNIC_MGMT_FUNC) | ||
1179 | phy_port = adapter->npars[esw_cfg->pci_func].phy_port; | ||
1180 | else | ||
1181 | phy_port = adapter->physical_port; | ||
1182 | arg1 = phy_port; | ||
1183 | arg1 |= (esw_cfg->pci_func << 8); | ||
1184 | if (__qlcnic_get_eswitch_port_config(adapter, &arg1, &arg2)) | ||
1185 | return -EIO; | ||
1186 | |||
1187 | esw_cfg->discard_tagged = !!(arg1 & BIT_4); | ||
1188 | esw_cfg->host_vlan_tag = !!(arg1 & BIT_5); | ||
1189 | esw_cfg->promisc_mode = !!(arg1 & BIT_6); | ||
1190 | esw_cfg->mac_learning = !!(arg1 & BIT_7); | ||
1191 | esw_cfg->vlan_id = LSW(arg1 >> 16); | ||
1192 | esw_cfg->mac_anti_spoof = (arg2 & 0x1); | ||
1193 | esw_cfg->offload_flags = ((arg2 >> 1) & 0x7); | ||
1194 | |||
1195 | return 0; | ||
1196 | } | ||
diff --git a/drivers/net/qlcnic/qlcnic_hdr.h b/drivers/net/qlcnic/qlcnic_hdr.h index 39db4df0f650..eae03b5b0323 100644 --- a/drivers/net/qlcnic/qlcnic_hdr.h +++ b/drivers/net/qlcnic/qlcnic_hdr.h | |||
@@ -775,6 +775,7 @@ struct qlcnic_legacy_intr_set { | |||
775 | #define QLCNIC_DRV_OP_MODE 0x1b2170 | 775 | #define QLCNIC_DRV_OP_MODE 0x1b2170 |
776 | #define QLCNIC_MSIX_BASE 0x132110 | 776 | #define QLCNIC_MSIX_BASE 0x132110 |
777 | #define QLCNIC_MAX_PCI_FUNC 8 | 777 | #define QLCNIC_MAX_PCI_FUNC 8 |
778 | #define QLCNIC_MAX_VLAN_FILTERS 64 | ||
778 | 779 | ||
779 | /* PCI function operational mode */ | 780 | /* PCI function operational mode */ |
780 | enum { | 781 | enum { |
@@ -783,6 +784,12 @@ enum { | |||
783 | QLCNIC_NON_PRIV_FUNC = 2 | 784 | QLCNIC_NON_PRIV_FUNC = 2 |
784 | }; | 785 | }; |
785 | 786 | ||
787 | enum { | ||
788 | QLCNIC_PORT_DEFAULTS = 0, | ||
789 | QLCNIC_ADD_VLAN = 1, | ||
790 | QLCNIC_DEL_VLAN = 2 | ||
791 | }; | ||
792 | |||
786 | #define QLC_DEV_DRV_DEFAULT 0x11111111 | 793 | #define QLC_DEV_DRV_DEFAULT 0x11111111 |
787 | 794 | ||
788 | #define LSB(x) ((uint8_t)(x)) | 795 | #define LSB(x) ((uint8_t)(x)) |
diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c index c6f19c961c3d..7bb32859b928 100644 --- a/drivers/net/qlcnic/qlcnic_main.c +++ b/drivers/net/qlcnic/qlcnic_main.c | |||
@@ -506,7 +506,6 @@ qlcnic_init_pci_info(struct qlcnic_adapter *adapter) | |||
506 | adapter->npars[pfn].active = pci_info[i].active; | 506 | adapter->npars[pfn].active = pci_info[i].active; |
507 | adapter->npars[pfn].type = pci_info[i].type; | 507 | adapter->npars[pfn].type = pci_info[i].type; |
508 | adapter->npars[pfn].phy_port = pci_info[i].default_port; | 508 | adapter->npars[pfn].phy_port = pci_info[i].default_port; |
509 | adapter->npars[pfn].mac_learning = DEFAULT_MAC_LEARN; | ||
510 | adapter->npars[pfn].min_bw = pci_info[i].tx_min_bw; | 509 | adapter->npars[pfn].min_bw = pci_info[i].tx_min_bw; |
511 | adapter->npars[pfn].max_bw = pci_info[i].tx_max_bw; | 510 | adapter->npars[pfn].max_bw = pci_info[i].tx_max_bw; |
512 | } | 511 | } |
@@ -758,47 +757,64 @@ qlcnic_check_options(struct qlcnic_adapter *adapter) | |||
758 | } | 757 | } |
759 | 758 | ||
760 | static int | 759 | static int |
760 | qlcnic_reset_eswitch_config(struct qlcnic_adapter *adapter, | ||
761 | struct qlcnic_npar_info *npar, int pci_func) | ||
762 | { | ||
763 | struct qlcnic_esw_func_cfg esw_cfg; | ||
764 | esw_cfg.op_mode = QLCNIC_PORT_DEFAULTS; | ||
765 | esw_cfg.pci_func = pci_func; | ||
766 | esw_cfg.vlan_id = npar->pvid; | ||
767 | esw_cfg.mac_learning = npar->mac_learning; | ||
768 | esw_cfg.discard_tagged = npar->discard_tagged; | ||
769 | esw_cfg.mac_anti_spoof = npar->mac_anti_spoof; | ||
770 | esw_cfg.offload_flags = npar->offload_flags; | ||
771 | esw_cfg.promisc_mode = npar->promisc_mode; | ||
772 | if (qlcnic_config_switch_port(adapter, &esw_cfg)) | ||
773 | return -EIO; | ||
774 | |||
775 | esw_cfg.op_mode = QLCNIC_ADD_VLAN; | ||
776 | if (qlcnic_config_switch_port(adapter, &esw_cfg)) | ||
777 | return -EIO; | ||
778 | |||
779 | return 0; | ||
780 | } | ||
781 | |||
782 | static int | ||
761 | qlcnic_reset_npar_config(struct qlcnic_adapter *adapter) | 783 | qlcnic_reset_npar_config(struct qlcnic_adapter *adapter) |
762 | { | 784 | { |
763 | int i, err = 0; | 785 | int i, err; |
764 | struct qlcnic_npar_info *npar; | 786 | struct qlcnic_npar_info *npar; |
765 | struct qlcnic_info nic_info; | 787 | struct qlcnic_info nic_info; |
766 | 788 | ||
767 | if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED) || | 789 | if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED) || |
768 | !adapter->need_fw_reset) | 790 | !adapter->need_fw_reset || adapter->op_mode != QLCNIC_MGMT_FUNC) |
769 | return 0; | 791 | return 0; |
770 | 792 | ||
771 | if (adapter->op_mode == QLCNIC_MGMT_FUNC) { | 793 | /* Set the NPAR config data after FW reset */ |
772 | /* Set the NPAR config data after FW reset */ | 794 | for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) { |
773 | for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) { | 795 | npar = &adapter->npars[i]; |
774 | npar = &adapter->npars[i]; | 796 | if (npar->type != QLCNIC_TYPE_NIC) |
775 | if (npar->type != QLCNIC_TYPE_NIC) | 797 | continue; |
776 | continue; | 798 | err = qlcnic_get_nic_info(adapter, &nic_info, i); |
777 | err = qlcnic_get_nic_info(adapter, &nic_info, i); | 799 | if (err) |
778 | if (err) | 800 | return err; |
779 | goto err_out; | 801 | nic_info.min_tx_bw = npar->min_bw; |
780 | nic_info.min_tx_bw = npar->min_bw; | 802 | nic_info.max_tx_bw = npar->max_bw; |
781 | nic_info.max_tx_bw = npar->max_bw; | 803 | err = qlcnic_set_nic_info(adapter, &nic_info); |
782 | err = qlcnic_set_nic_info(adapter, &nic_info); | 804 | if (err) |
783 | if (err) | 805 | return err; |
784 | goto err_out; | ||
785 | |||
786 | if (npar->enable_pm) { | ||
787 | err = qlcnic_config_port_mirroring(adapter, | ||
788 | npar->dest_npar, 1, i); | ||
789 | if (err) | ||
790 | goto err_out; | ||
791 | 806 | ||
792 | } | 807 | if (npar->enable_pm) { |
793 | npar->mac_learning = DEFAULT_MAC_LEARN; | 808 | err = qlcnic_config_port_mirroring(adapter, |
794 | npar->host_vlan_tag = 0; | 809 | npar->dest_npar, 1, i); |
795 | npar->promisc_mode = 0; | 810 | if (err) |
796 | npar->discard_tagged = 0; | 811 | return err; |
797 | npar->vlan_id = 0; | ||
798 | } | 812 | } |
813 | err = qlcnic_reset_eswitch_config(adapter, npar, i); | ||
814 | if (err) | ||
815 | return err; | ||
799 | } | 816 | } |
800 | err_out: | 817 | return 0; |
801 | return err; | ||
802 | } | 818 | } |
803 | 819 | ||
804 | static int | 820 | static int |
@@ -863,12 +879,10 @@ wait_init: | |||
863 | 879 | ||
864 | QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_READY); | 880 | QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_READY); |
865 | qlcnic_idc_debug_info(adapter, 1); | 881 | qlcnic_idc_debug_info(adapter, 1); |
866 | |||
867 | qlcnic_check_options(adapter); | ||
868 | if (qlcnic_reset_npar_config(adapter)) | 882 | if (qlcnic_reset_npar_config(adapter)) |
869 | goto err_out; | 883 | goto err_out; |
870 | qlcnic_dev_set_npar_ready(adapter); | 884 | qlcnic_dev_set_npar_ready(adapter); |
871 | 885 | qlcnic_check_options(adapter); | |
872 | adapter->need_fw_reset = 0; | 886 | adapter->need_fw_reset = 0; |
873 | 887 | ||
874 | qlcnic_release_firmware(adapter); | 888 | qlcnic_release_firmware(adapter); |
@@ -3082,9 +3096,6 @@ validate_pm_config(struct qlcnic_adapter *adapter, | |||
3082 | if (adapter->npars[dest_pci_func].type != QLCNIC_TYPE_NIC) | 3096 | if (adapter->npars[dest_pci_func].type != QLCNIC_TYPE_NIC) |
3083 | return QL_STATUS_INVALID_PARAM; | 3097 | return QL_STATUS_INVALID_PARAM; |
3084 | 3098 | ||
3085 | if (!IS_VALID_MODE(pm_cfg[i].action)) | ||
3086 | return QL_STATUS_INVALID_PARAM; | ||
3087 | |||
3088 | s_esw_id = adapter->npars[src_pci_func].phy_port; | 3099 | s_esw_id = adapter->npars[src_pci_func].phy_port; |
3089 | d_esw_id = adapter->npars[dest_pci_func].phy_port; | 3100 | d_esw_id = adapter->npars[dest_pci_func].phy_port; |
3090 | 3101 | ||
@@ -3118,7 +3129,7 @@ qlcnic_sysfs_write_pm_config(struct file *filp, struct kobject *kobj, | |||
3118 | return ret; | 3129 | return ret; |
3119 | for (i = 0; i < count; i++) { | 3130 | for (i = 0; i < count; i++) { |
3120 | pci_func = pm_cfg[i].pci_func; | 3131 | pci_func = pm_cfg[i].pci_func; |
3121 | action = pm_cfg[i].action; | 3132 | action = !!pm_cfg[i].action; |
3122 | id = adapter->npars[pci_func].phy_port; | 3133 | id = adapter->npars[pci_func].phy_port; |
3123 | ret = qlcnic_config_port_mirroring(adapter, id, | 3134 | ret = qlcnic_config_port_mirroring(adapter, id, |
3124 | action, pci_func); | 3135 | action, pci_func); |
@@ -3129,7 +3140,7 @@ qlcnic_sysfs_write_pm_config(struct file *filp, struct kobject *kobj, | |||
3129 | for (i = 0; i < count; i++) { | 3140 | for (i = 0; i < count; i++) { |
3130 | pci_func = pm_cfg[i].pci_func; | 3141 | pci_func = pm_cfg[i].pci_func; |
3131 | id = adapter->npars[pci_func].phy_port; | 3142 | id = adapter->npars[pci_func].phy_port; |
3132 | adapter->npars[pci_func].enable_pm = pm_cfg[i].action; | 3143 | adapter->npars[pci_func].enable_pm = !!pm_cfg[i].action; |
3133 | adapter->npars[pci_func].dest_npar = id; | 3144 | adapter->npars[pci_func].dest_npar = id; |
3134 | } | 3145 | } |
3135 | return size; | 3146 | return size; |
@@ -3161,30 +3172,38 @@ qlcnic_sysfs_read_pm_config(struct file *filp, struct kobject *kobj, | |||
3161 | 3172 | ||
3162 | static int | 3173 | static int |
3163 | validate_esw_config(struct qlcnic_adapter *adapter, | 3174 | validate_esw_config(struct qlcnic_adapter *adapter, |
3164 | struct qlcnic_esw_func_cfg *esw_cfg, int count) | 3175 | struct qlcnic_esw_func_cfg *esw_cfg, int count) |
3165 | { | 3176 | { |
3166 | u8 pci_func; | 3177 | u8 pci_func; |
3167 | int i; | 3178 | int i; |
3168 | |||
3169 | for (i = 0; i < count; i++) { | 3179 | for (i = 0; i < count; i++) { |
3170 | pci_func = esw_cfg[i].pci_func; | 3180 | pci_func = esw_cfg[i].pci_func; |
3171 | if (pci_func >= QLCNIC_MAX_PCI_FUNC) | 3181 | if (pci_func >= QLCNIC_MAX_PCI_FUNC) |
3172 | return QL_STATUS_INVALID_PARAM; | 3182 | return QL_STATUS_INVALID_PARAM; |
3173 | 3183 | ||
3174 | if (adapter->npars[i].type != QLCNIC_TYPE_NIC) | 3184 | if (adapter->op_mode == QLCNIC_MGMT_FUNC) |
3175 | return QL_STATUS_INVALID_PARAM; | 3185 | if (adapter->npars[pci_func].type != QLCNIC_TYPE_NIC) |
3186 | return QL_STATUS_INVALID_PARAM; | ||
3176 | 3187 | ||
3177 | if (esw_cfg->host_vlan_tag == 1) | 3188 | switch (esw_cfg[i].op_mode) { |
3189 | case QLCNIC_PORT_DEFAULTS: | ||
3190 | break; | ||
3191 | case QLCNIC_ADD_VLAN: | ||
3178 | if (!IS_VALID_VLAN(esw_cfg[i].vlan_id)) | 3192 | if (!IS_VALID_VLAN(esw_cfg[i].vlan_id)) |
3179 | return QL_STATUS_INVALID_PARAM; | 3193 | return QL_STATUS_INVALID_PARAM; |
3180 | 3194 | if (!esw_cfg[i].op_type) | |
3181 | if (!IS_VALID_MODE(esw_cfg[i].promisc_mode) | 3195 | return QL_STATUS_INVALID_PARAM; |
3182 | || !IS_VALID_MODE(esw_cfg[i].host_vlan_tag) | 3196 | break; |
3183 | || !IS_VALID_MODE(esw_cfg[i].mac_learning) | 3197 | case QLCNIC_DEL_VLAN: |
3184 | || !IS_VALID_MODE(esw_cfg[i].discard_tagged)) | 3198 | if (!IS_VALID_VLAN(esw_cfg[i].vlan_id)) |
3199 | return QL_STATUS_INVALID_PARAM; | ||
3200 | if (!esw_cfg[i].op_type) | ||
3201 | return QL_STATUS_INVALID_PARAM; | ||
3202 | break; | ||
3203 | default: | ||
3185 | return QL_STATUS_INVALID_PARAM; | 3204 | return QL_STATUS_INVALID_PARAM; |
3205 | } | ||
3186 | } | 3206 | } |
3187 | |||
3188 | return 0; | 3207 | return 0; |
3189 | } | 3208 | } |
3190 | 3209 | ||
@@ -3195,8 +3214,9 @@ qlcnic_sysfs_write_esw_config(struct file *file, struct kobject *kobj, | |||
3195 | struct device *dev = container_of(kobj, struct device, kobj); | 3214 | struct device *dev = container_of(kobj, struct device, kobj); |
3196 | struct qlcnic_adapter *adapter = dev_get_drvdata(dev); | 3215 | struct qlcnic_adapter *adapter = dev_get_drvdata(dev); |
3197 | struct qlcnic_esw_func_cfg *esw_cfg; | 3216 | struct qlcnic_esw_func_cfg *esw_cfg; |
3217 | struct qlcnic_npar_info *npar; | ||
3198 | int count, rem, i, ret; | 3218 | int count, rem, i, ret; |
3199 | u8 id, pci_func; | 3219 | u8 pci_func; |
3200 | 3220 | ||
3201 | count = size / sizeof(struct qlcnic_esw_func_cfg); | 3221 | count = size / sizeof(struct qlcnic_esw_func_cfg); |
3202 | rem = size % sizeof(struct qlcnic_esw_func_cfg); | 3222 | rem = size % sizeof(struct qlcnic_esw_func_cfg); |
@@ -3209,28 +3229,28 @@ qlcnic_sysfs_write_esw_config(struct file *file, struct kobject *kobj, | |||
3209 | return ret; | 3229 | return ret; |
3210 | 3230 | ||
3211 | for (i = 0; i < count; i++) { | 3231 | for (i = 0; i < count; i++) { |
3212 | pci_func = esw_cfg[i].pci_func; | 3232 | if (qlcnic_config_switch_port(adapter, &esw_cfg[i])) |
3213 | id = adapter->npars[pci_func].phy_port; | 3233 | return QL_STATUS_INVALID_PARAM; |
3214 | ret = qlcnic_config_switch_port(adapter, id, | ||
3215 | esw_cfg[i].host_vlan_tag, | ||
3216 | esw_cfg[i].discard_tagged, | ||
3217 | esw_cfg[i].promisc_mode, | ||
3218 | esw_cfg[i].mac_learning, | ||
3219 | esw_cfg[i].pci_func, | ||
3220 | esw_cfg[i].vlan_id); | ||
3221 | if (ret) | ||
3222 | return ret; | ||
3223 | } | 3234 | } |
3224 | 3235 | ||
3225 | for (i = 0; i < count; i++) { | 3236 | for (i = 0; i < count; i++) { |
3226 | pci_func = esw_cfg[i].pci_func; | 3237 | pci_func = esw_cfg[i].pci_func; |
3227 | adapter->npars[pci_func].promisc_mode = esw_cfg[i].promisc_mode; | 3238 | npar = &adapter->npars[pci_func]; |
3228 | adapter->npars[pci_func].mac_learning = esw_cfg[i].mac_learning; | 3239 | switch (esw_cfg[i].op_mode) { |
3229 | adapter->npars[pci_func].vlan_id = esw_cfg[i].vlan_id; | 3240 | case QLCNIC_PORT_DEFAULTS: |
3230 | adapter->npars[pci_func].discard_tagged = | 3241 | npar->promisc_mode = esw_cfg[i].promisc_mode; |
3231 | esw_cfg[i].discard_tagged; | 3242 | npar->mac_learning = esw_cfg[i].mac_learning; |
3232 | adapter->npars[pci_func].host_vlan_tag = | 3243 | npar->offload_flags = esw_cfg[i].offload_flags; |
3233 | esw_cfg[i].host_vlan_tag; | 3244 | npar->mac_anti_spoof = esw_cfg[i].mac_anti_spoof; |
3245 | npar->discard_tagged = esw_cfg[i].discard_tagged; | ||
3246 | break; | ||
3247 | case QLCNIC_ADD_VLAN: | ||
3248 | npar->pvid = esw_cfg[i].vlan_id; | ||
3249 | break; | ||
3250 | case QLCNIC_DEL_VLAN: | ||
3251 | npar->pvid = 0; | ||
3252 | break; | ||
3253 | } | ||
3234 | } | 3254 | } |
3235 | 3255 | ||
3236 | return size; | 3256 | return size; |
@@ -3243,7 +3263,7 @@ qlcnic_sysfs_read_esw_config(struct file *file, struct kobject *kobj, | |||
3243 | struct device *dev = container_of(kobj, struct device, kobj); | 3263 | struct device *dev = container_of(kobj, struct device, kobj); |
3244 | struct qlcnic_adapter *adapter = dev_get_drvdata(dev); | 3264 | struct qlcnic_adapter *adapter = dev_get_drvdata(dev); |
3245 | struct qlcnic_esw_func_cfg esw_cfg[QLCNIC_MAX_PCI_FUNC]; | 3265 | struct qlcnic_esw_func_cfg esw_cfg[QLCNIC_MAX_PCI_FUNC]; |
3246 | int i; | 3266 | u8 i; |
3247 | 3267 | ||
3248 | if (size != sizeof(esw_cfg)) | 3268 | if (size != sizeof(esw_cfg)) |
3249 | return QL_STATUS_INVALID_PARAM; | 3269 | return QL_STATUS_INVALID_PARAM; |
@@ -3251,12 +3271,9 @@ qlcnic_sysfs_read_esw_config(struct file *file, struct kobject *kobj, | |||
3251 | for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) { | 3271 | for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) { |
3252 | if (adapter->npars[i].type != QLCNIC_TYPE_NIC) | 3272 | if (adapter->npars[i].type != QLCNIC_TYPE_NIC) |
3253 | continue; | 3273 | continue; |
3254 | 3274 | esw_cfg[i].pci_func = i; | |
3255 | esw_cfg[i].host_vlan_tag = adapter->npars[i].host_vlan_tag; | 3275 | if (qlcnic_get_eswitch_port_config(adapter, &esw_cfg[i])) |
3256 | esw_cfg[i].promisc_mode = adapter->npars[i].promisc_mode; | 3276 | return QL_STATUS_INVALID_PARAM; |
3257 | esw_cfg[i].discard_tagged = adapter->npars[i].discard_tagged; | ||
3258 | esw_cfg[i].vlan_id = adapter->npars[i].vlan_id; | ||
3259 | esw_cfg[i].mac_learning = adapter->npars[i].mac_learning; | ||
3260 | } | 3277 | } |
3261 | memcpy(buf, &esw_cfg, size); | 3278 | memcpy(buf, &esw_cfg, size); |
3262 | 3279 | ||
@@ -3580,15 +3597,16 @@ qlcnic_create_diag_entries(struct qlcnic_adapter *adapter) | |||
3580 | dev_info(dev, "failed to create crb sysfs entry\n"); | 3597 | dev_info(dev, "failed to create crb sysfs entry\n"); |
3581 | if (device_create_bin_file(dev, &bin_attr_mem)) | 3598 | if (device_create_bin_file(dev, &bin_attr_mem)) |
3582 | dev_info(dev, "failed to create mem sysfs entry\n"); | 3599 | dev_info(dev, "failed to create mem sysfs entry\n"); |
3583 | if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED) || | 3600 | if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED)) |
3584 | adapter->op_mode != QLCNIC_MGMT_FUNC) | 3601 | return; |
3602 | if (device_create_bin_file(dev, &bin_attr_esw_config)) | ||
3603 | dev_info(dev, "failed to create esw config sysfs entry"); | ||
3604 | if (adapter->op_mode != QLCNIC_MGMT_FUNC) | ||
3585 | return; | 3605 | return; |
3586 | if (device_create_bin_file(dev, &bin_attr_pci_config)) | 3606 | if (device_create_bin_file(dev, &bin_attr_pci_config)) |
3587 | dev_info(dev, "failed to create pci config sysfs entry"); | 3607 | dev_info(dev, "failed to create pci config sysfs entry"); |
3588 | if (device_create_bin_file(dev, &bin_attr_npar_config)) | 3608 | if (device_create_bin_file(dev, &bin_attr_npar_config)) |
3589 | dev_info(dev, "failed to create npar config sysfs entry"); | 3609 | dev_info(dev, "failed to create npar config sysfs entry"); |
3590 | if (device_create_bin_file(dev, &bin_attr_esw_config)) | ||
3591 | dev_info(dev, "failed to create esw config sysfs entry"); | ||
3592 | if (device_create_bin_file(dev, &bin_attr_pm_config)) | 3610 | if (device_create_bin_file(dev, &bin_attr_pm_config)) |
3593 | dev_info(dev, "failed to create pm config sysfs entry"); | 3611 | dev_info(dev, "failed to create pm config sysfs entry"); |
3594 | if (device_create_bin_file(dev, &bin_attr_esw_stats)) | 3612 | if (device_create_bin_file(dev, &bin_attr_esw_stats)) |
@@ -3607,12 +3625,13 @@ qlcnic_remove_diag_entries(struct qlcnic_adapter *adapter) | |||
3607 | device_remove_file(dev, &dev_attr_diag_mode); | 3625 | device_remove_file(dev, &dev_attr_diag_mode); |
3608 | device_remove_bin_file(dev, &bin_attr_crb); | 3626 | device_remove_bin_file(dev, &bin_attr_crb); |
3609 | device_remove_bin_file(dev, &bin_attr_mem); | 3627 | device_remove_bin_file(dev, &bin_attr_mem); |
3610 | if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED) || | 3628 | if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED)) |
3611 | adapter->op_mode != QLCNIC_MGMT_FUNC) | 3629 | return; |
3630 | device_remove_bin_file(dev, &bin_attr_esw_config); | ||
3631 | if (adapter->op_mode != QLCNIC_MGMT_FUNC) | ||
3612 | return; | 3632 | return; |
3613 | device_remove_bin_file(dev, &bin_attr_pci_config); | 3633 | device_remove_bin_file(dev, &bin_attr_pci_config); |
3614 | device_remove_bin_file(dev, &bin_attr_npar_config); | 3634 | device_remove_bin_file(dev, &bin_attr_npar_config); |
3615 | device_remove_bin_file(dev, &bin_attr_esw_config); | ||
3616 | device_remove_bin_file(dev, &bin_attr_pm_config); | 3635 | device_remove_bin_file(dev, &bin_attr_pm_config); |
3617 | device_remove_bin_file(dev, &bin_attr_esw_stats); | 3636 | device_remove_bin_file(dev, &bin_attr_esw_stats); |
3618 | } | 3637 | } |