diff options
Diffstat (limited to 'drivers/net/cxgb4vf/t4vf_hw.c')
-rw-r--r-- | drivers/net/cxgb4vf/t4vf_hw.c | 133 |
1 files changed, 94 insertions, 39 deletions
diff --git a/drivers/net/cxgb4vf/t4vf_hw.c b/drivers/net/cxgb4vf/t4vf_hw.c index ea1c123f0cb4..192db226ec7f 100644 --- a/drivers/net/cxgb4vf/t4vf_hw.c +++ b/drivers/net/cxgb4vf/t4vf_hw.c | |||
@@ -116,7 +116,7 @@ static void dump_mbox(struct adapter *adapter, const char *tag, u32 mbox_data) | |||
116 | int t4vf_wr_mbox_core(struct adapter *adapter, const void *cmd, int size, | 116 | int t4vf_wr_mbox_core(struct adapter *adapter, const void *cmd, int size, |
117 | void *rpl, bool sleep_ok) | 117 | void *rpl, bool sleep_ok) |
118 | { | 118 | { |
119 | static int delay[] = { | 119 | static const int delay[] = { |
120 | 1, 1, 3, 5, 10, 10, 20, 50, 100 | 120 | 1, 1, 3, 5, 10, 10, 20, 50, 100 |
121 | }; | 121 | }; |
122 | 122 | ||
@@ -147,9 +147,20 @@ int t4vf_wr_mbox_core(struct adapter *adapter, const void *cmd, int size, | |||
147 | /* | 147 | /* |
148 | * Write the command array into the Mailbox Data register array and | 148 | * Write the command array into the Mailbox Data register array and |
149 | * transfer ownership of the mailbox to the firmware. | 149 | * transfer ownership of the mailbox to the firmware. |
150 | * | ||
151 | * For the VFs, the Mailbox Data "registers" are actually backed by | ||
152 | * T4's "MA" interface rather than PL Registers (as is the case for | ||
153 | * the PFs). Because these are in different coherency domains, the | ||
154 | * write to the VF's PL-register-backed Mailbox Control can race in | ||
155 | * front of the writes to the MA-backed VF Mailbox Data "registers". | ||
156 | * So we need to do a read-back on at least one byte of the VF Mailbox | ||
157 | * Data registers before doing the write to the VF Mailbox Control | ||
158 | * register. | ||
150 | */ | 159 | */ |
151 | for (i = 0, p = cmd; i < size; i += 8) | 160 | for (i = 0, p = cmd; i < size; i += 8) |
152 | t4_write_reg64(adapter, mbox_data + i, be64_to_cpu(*p++)); | 161 | t4_write_reg64(adapter, mbox_data + i, be64_to_cpu(*p++)); |
162 | t4_read_reg(adapter, mbox_data); /* flush write */ | ||
163 | |||
153 | t4_write_reg(adapter, mbox_ctl, | 164 | t4_write_reg(adapter, mbox_ctl, |
154 | MBMSGVALID | MBOWNER(MBOX_OWNER_FW)); | 165 | MBMSGVALID | MBOWNER(MBOX_OWNER_FW)); |
155 | t4_read_reg(adapter, mbox_ctl); /* flush write */ | 166 | t4_read_reg(adapter, mbox_ctl); /* flush write */ |
@@ -160,7 +171,7 @@ int t4vf_wr_mbox_core(struct adapter *adapter, const void *cmd, int size, | |||
160 | delay_idx = 0; | 171 | delay_idx = 0; |
161 | ms = delay[0]; | 172 | ms = delay[0]; |
162 | 173 | ||
163 | for (i = 0; i < 500; i += ms) { | 174 | for (i = 0; i < FW_CMD_MAX_TIMEOUT; i += ms) { |
164 | if (sleep_ok) { | 175 | if (sleep_ok) { |
165 | ms = delay[delay_idx]; | 176 | ms = delay[delay_idx]; |
166 | if (delay_idx < ARRAY_SIZE(delay) - 1) | 177 | if (delay_idx < ARRAY_SIZE(delay) - 1) |
@@ -326,6 +337,25 @@ int __devinit t4vf_port_init(struct adapter *adapter, int pidx) | |||
326 | } | 337 | } |
327 | 338 | ||
328 | /** | 339 | /** |
340 | * t4vf_fw_reset - issue a reset to FW | ||
341 | * @adapter: the adapter | ||
342 | * | ||
343 | * Issues a reset command to FW. For a Physical Function this would | ||
344 | * result in the Firmware reseting all of its state. For a Virtual | ||
345 | * Function this just resets the state associated with the VF. | ||
346 | */ | ||
347 | int t4vf_fw_reset(struct adapter *adapter) | ||
348 | { | ||
349 | struct fw_reset_cmd cmd; | ||
350 | |||
351 | memset(&cmd, 0, sizeof(cmd)); | ||
352 | cmd.op_to_write = cpu_to_be32(FW_CMD_OP(FW_RESET_CMD) | | ||
353 | FW_CMD_WRITE); | ||
354 | cmd.retval_len16 = cpu_to_be32(FW_LEN16(cmd)); | ||
355 | return t4vf_wr_mbox(adapter, &cmd, sizeof(cmd), NULL); | ||
356 | } | ||
357 | |||
358 | /** | ||
329 | * t4vf_query_params - query FW or device parameters | 359 | * t4vf_query_params - query FW or device parameters |
330 | * @adapter: the adapter | 360 | * @adapter: the adapter |
331 | * @nparams: the number of parameters | 361 | * @nparams: the number of parameters |
@@ -995,48 +1025,72 @@ int t4vf_alloc_mac_filt(struct adapter *adapter, unsigned int viid, bool free, | |||
995 | unsigned int naddr, const u8 **addr, u16 *idx, | 1025 | unsigned int naddr, const u8 **addr, u16 *idx, |
996 | u64 *hash, bool sleep_ok) | 1026 | u64 *hash, bool sleep_ok) |
997 | { | 1027 | { |
998 | int i, ret; | 1028 | int offset, ret = 0; |
1029 | unsigned nfilters = 0; | ||
1030 | unsigned int rem = naddr; | ||
999 | struct fw_vi_mac_cmd cmd, rpl; | 1031 | struct fw_vi_mac_cmd cmd, rpl; |
1000 | struct fw_vi_mac_exact *p; | ||
1001 | size_t len16; | ||
1002 | 1032 | ||
1003 | if (naddr > ARRAY_SIZE(cmd.u.exact)) | 1033 | if (naddr > FW_CLS_TCAM_NUM_ENTRIES) |
1004 | return -EINVAL; | 1034 | return -EINVAL; |
1005 | len16 = DIV_ROUND_UP(offsetof(struct fw_vi_mac_cmd, | ||
1006 | u.exact[naddr]), 16); | ||
1007 | 1035 | ||
1008 | memset(&cmd, 0, sizeof(cmd)); | 1036 | for (offset = 0; offset < naddr; /**/) { |
1009 | cmd.op_to_viid = cpu_to_be32(FW_CMD_OP(FW_VI_MAC_CMD) | | 1037 | unsigned int fw_naddr = (rem < ARRAY_SIZE(cmd.u.exact) |
1010 | FW_CMD_REQUEST | | 1038 | ? rem |
1011 | FW_CMD_WRITE | | 1039 | : ARRAY_SIZE(cmd.u.exact)); |
1012 | (free ? FW_CMD_EXEC : 0) | | 1040 | size_t len16 = DIV_ROUND_UP(offsetof(struct fw_vi_mac_cmd, |
1013 | FW_VI_MAC_CMD_VIID(viid)); | 1041 | u.exact[fw_naddr]), 16); |
1014 | cmd.freemacs_to_len16 = cpu_to_be32(FW_VI_MAC_CMD_FREEMACS(free) | | 1042 | struct fw_vi_mac_exact *p; |
1015 | FW_CMD_LEN16(len16)); | 1043 | int i; |
1044 | |||
1045 | memset(&cmd, 0, sizeof(cmd)); | ||
1046 | cmd.op_to_viid = cpu_to_be32(FW_CMD_OP(FW_VI_MAC_CMD) | | ||
1047 | FW_CMD_REQUEST | | ||
1048 | FW_CMD_WRITE | | ||
1049 | (free ? FW_CMD_EXEC : 0) | | ||
1050 | FW_VI_MAC_CMD_VIID(viid)); | ||
1051 | cmd.freemacs_to_len16 = | ||
1052 | cpu_to_be32(FW_VI_MAC_CMD_FREEMACS(free) | | ||
1053 | FW_CMD_LEN16(len16)); | ||
1054 | |||
1055 | for (i = 0, p = cmd.u.exact; i < fw_naddr; i++, p++) { | ||
1056 | p->valid_to_idx = cpu_to_be16( | ||
1057 | FW_VI_MAC_CMD_VALID | | ||
1058 | FW_VI_MAC_CMD_IDX(FW_VI_MAC_ADD_MAC)); | ||
1059 | memcpy(p->macaddr, addr[offset+i], sizeof(p->macaddr)); | ||
1060 | } | ||
1016 | 1061 | ||
1017 | for (i = 0, p = cmd.u.exact; i < naddr; i++, p++) { | ||
1018 | p->valid_to_idx = | ||
1019 | cpu_to_be16(FW_VI_MAC_CMD_VALID | | ||
1020 | FW_VI_MAC_CMD_IDX(FW_VI_MAC_ADD_MAC)); | ||
1021 | memcpy(p->macaddr, addr[i], sizeof(p->macaddr)); | ||
1022 | } | ||
1023 | 1062 | ||
1024 | ret = t4vf_wr_mbox_core(adapter, &cmd, sizeof(cmd), &rpl, sleep_ok); | 1063 | ret = t4vf_wr_mbox_core(adapter, &cmd, sizeof(cmd), &rpl, |
1025 | if (ret) | 1064 | sleep_ok); |
1026 | return ret; | 1065 | if (ret && ret != -ENOMEM) |
1027 | 1066 | break; | |
1028 | for (i = 0, p = rpl.u.exact; i < naddr; i++, p++) { | 1067 | |
1029 | u16 index = FW_VI_MAC_CMD_IDX_GET(be16_to_cpu(p->valid_to_idx)); | 1068 | for (i = 0, p = rpl.u.exact; i < fw_naddr; i++, p++) { |
1030 | 1069 | u16 index = FW_VI_MAC_CMD_IDX_GET( | |
1031 | if (idx) | 1070 | be16_to_cpu(p->valid_to_idx)); |
1032 | idx[i] = (index >= FW_CLS_TCAM_NUM_ENTRIES | 1071 | |
1033 | ? 0xffff | 1072 | if (idx) |
1034 | : index); | 1073 | idx[offset+i] = |
1035 | if (index < FW_CLS_TCAM_NUM_ENTRIES) | 1074 | (index >= FW_CLS_TCAM_NUM_ENTRIES |
1036 | ret++; | 1075 | ? 0xffff |
1037 | else if (hash) | 1076 | : index); |
1038 | *hash |= (1 << hash_mac_addr(addr[i])); | 1077 | if (index < FW_CLS_TCAM_NUM_ENTRIES) |
1078 | nfilters++; | ||
1079 | else if (hash) | ||
1080 | *hash |= (1ULL << hash_mac_addr(addr[offset+i])); | ||
1081 | } | ||
1082 | |||
1083 | free = false; | ||
1084 | offset += fw_naddr; | ||
1085 | rem -= fw_naddr; | ||
1039 | } | 1086 | } |
1087 | |||
1088 | /* | ||
1089 | * If there were no errors or we merely ran out of room in our MAC | ||
1090 | * address arena, return the number of filters actually written. | ||
1091 | */ | ||
1092 | if (ret == 0 || ret == -ENOMEM) | ||
1093 | ret = nfilters; | ||
1040 | return ret; | 1094 | return ret; |
1041 | } | 1095 | } |
1042 | 1096 | ||
@@ -1257,7 +1311,7 @@ int t4vf_eth_eq_free(struct adapter *adapter, unsigned int eqid) | |||
1257 | */ | 1311 | */ |
1258 | int t4vf_handle_fw_rpl(struct adapter *adapter, const __be64 *rpl) | 1312 | int t4vf_handle_fw_rpl(struct adapter *adapter, const __be64 *rpl) |
1259 | { | 1313 | { |
1260 | struct fw_cmd_hdr *cmd_hdr = (struct fw_cmd_hdr *)rpl; | 1314 | const struct fw_cmd_hdr *cmd_hdr = (const struct fw_cmd_hdr *)rpl; |
1261 | u8 opcode = FW_CMD_OP_GET(be32_to_cpu(cmd_hdr->hi)); | 1315 | u8 opcode = FW_CMD_OP_GET(be32_to_cpu(cmd_hdr->hi)); |
1262 | 1316 | ||
1263 | switch (opcode) { | 1317 | switch (opcode) { |
@@ -1265,7 +1319,8 @@ int t4vf_handle_fw_rpl(struct adapter *adapter, const __be64 *rpl) | |||
1265 | /* | 1319 | /* |
1266 | * Link/module state change message. | 1320 | * Link/module state change message. |
1267 | */ | 1321 | */ |
1268 | const struct fw_port_cmd *port_cmd = (void *)rpl; | 1322 | const struct fw_port_cmd *port_cmd = |
1323 | (const struct fw_port_cmd *)rpl; | ||
1269 | u32 word; | 1324 | u32 word; |
1270 | int action, port_id, link_ok, speed, fc, pidx; | 1325 | int action, port_id, link_ok, speed, fc, pidx; |
1271 | 1326 | ||