1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2016 Cavium, Inc 3 */ 4 5 #include <assert.h> 6 #include <unistd.h> 7 #include <stdio.h> 8 #include <stdlib.h> 9 10 #include "nicvf_plat.h" 11 12 #define NICVF_MBOX_PF_RESPONSE_DELAY_US (1000) 13 14 static const char *mbox_message[NIC_MBOX_MSG_MAX] = { 15 [NIC_MBOX_MSG_INVALID] = "NIC_MBOX_MSG_INVALID", 16 [NIC_MBOX_MSG_READY] = "NIC_MBOX_MSG_READY", 17 [NIC_MBOX_MSG_ACK] = "NIC_MBOX_MSG_ACK", 18 [NIC_MBOX_MSG_NACK] = "NIC_MBOX_MSG_ACK", 19 [NIC_MBOX_MSG_QS_CFG] = "NIC_MBOX_MSG_QS_CFG", 20 [NIC_MBOX_MSG_RQ_CFG] = "NIC_MBOX_MSG_RQ_CFG", 21 [NIC_MBOX_MSG_SQ_CFG] = "NIC_MBOX_MSG_SQ_CFG", 22 [NIC_MBOX_MSG_RQ_DROP_CFG] = "NIC_MBOX_MSG_RQ_DROP_CFG", 23 [NIC_MBOX_MSG_SET_MAC] = "NIC_MBOX_MSG_SET_MAC", 24 [NIC_MBOX_MSG_SET_MAX_FRS] = "NIC_MBOX_MSG_SET_MAX_FRS", 25 [NIC_MBOX_MSG_CPI_CFG] = "NIC_MBOX_MSG_CPI_CFG", 26 [NIC_MBOX_MSG_RSS_SIZE] = "NIC_MBOX_MSG_RSS_SIZE", 27 [NIC_MBOX_MSG_RSS_CFG] = "NIC_MBOX_MSG_RSS_CFG", 28 [NIC_MBOX_MSG_RSS_CFG_CONT] = "NIC_MBOX_MSG_RSS_CFG_CONT", 29 [NIC_MBOX_MSG_RQ_BP_CFG] = "NIC_MBOX_MSG_RQ_BP_CFG", 30 [NIC_MBOX_MSG_RQ_SW_SYNC] = "NIC_MBOX_MSG_RQ_SW_SYNC", 31 [NIC_MBOX_MSG_BGX_LINK_CHANGE] = "NIC_MBOX_MSG_BGX_LINK_CHANGE", 32 [NIC_MBOX_MSG_ALLOC_SQS] = "NIC_MBOX_MSG_ALLOC_SQS", 33 [NIC_MBOX_MSG_LOOPBACK] = "NIC_MBOX_MSG_LOOPBACK", 34 [NIC_MBOX_MSG_RESET_STAT_COUNTER] = "NIC_MBOX_MSG_RESET_STAT_COUNTER", 35 [NIC_MBOX_MSG_CFG_DONE] = "NIC_MBOX_MSG_CFG_DONE", 36 [NIC_MBOX_MSG_SHUTDOWN] = "NIC_MBOX_MSG_SHUTDOWN", 37 }; 38 39 static inline const char * __rte_unused 40 nicvf_mbox_msg_str(int msg) 41 { 42 assert(msg >= 0 && msg < NIC_MBOX_MSG_MAX); 43 /* undefined messages */ 44 if (mbox_message[msg] == NULL) 45 msg = 0; 46 return mbox_message[msg]; 47 } 48 49 static inline void 50 nicvf_mbox_send_msg_to_pf_raw(struct nicvf *nic, struct nic_mbx *mbx) 51 { 52 uint64_t *mbx_data; 53 uint64_t mbx_addr; 54 int i; 55 56 mbx_addr = NIC_VF_PF_MAILBOX_0_1; 57 mbx_data = (uint64_t *)mbx; 58 for (i = 0; i < NIC_PF_VF_MAILBOX_SIZE; i++) { 59 nicvf_reg_write(nic, mbx_addr, *mbx_data); 60 mbx_data++; 61 mbx_addr += sizeof(uint64_t); 62 } 63 nicvf_mbox_log("msg sent %s (VF%d)", 64 nicvf_mbox_msg_str(mbx->msg.msg), nic->vf_id); 65 } 66 67 static inline void 68 nicvf_mbox_send_async_msg_to_pf(struct nicvf *nic, struct nic_mbx *mbx) 69 { 70 nicvf_mbox_send_msg_to_pf_raw(nic, mbx); 71 /* Messages without ack are racy!*/ 72 nicvf_delay_us(NICVF_MBOX_PF_RESPONSE_DELAY_US); 73 } 74 75 static inline int 76 nicvf_mbox_send_msg_to_pf(struct nicvf *nic, struct nic_mbx *mbx) 77 { 78 long timeout; 79 long sleep = 10; 80 int i, retry = 5; 81 82 for (i = 0; i < retry; i++) { 83 nic->pf_acked = false; 84 nic->pf_nacked = false; 85 nicvf_smp_wmb(); 86 87 nicvf_mbox_send_msg_to_pf_raw(nic, mbx); 88 /* Give some time to get PF response */ 89 nicvf_delay_us(NICVF_MBOX_PF_RESPONSE_DELAY_US); 90 timeout = NIC_MBOX_MSG_TIMEOUT; 91 while (timeout > 0) { 92 /* Periodic poll happens from nicvf_interrupt() */ 93 nicvf_smp_rmb(); 94 95 if (nic->pf_nacked) 96 return -EINVAL; 97 if (nic->pf_acked) 98 return 0; 99 100 nicvf_delay_us(NICVF_MBOX_PF_RESPONSE_DELAY_US); 101 timeout -= sleep; 102 } 103 nicvf_log_error("PF didn't ack to msg 0x%02x %s VF%d (%d/%d)", 104 mbx->msg.msg, nicvf_mbox_msg_str(mbx->msg.msg), 105 nic->vf_id, i, retry); 106 } 107 return -EBUSY; 108 } 109 110 111 int 112 nicvf_handle_mbx_intr(struct nicvf *nic) 113 { 114 struct nic_mbx mbx; 115 uint64_t *mbx_data = (uint64_t *)&mbx; 116 uint64_t mbx_addr = NIC_VF_PF_MAILBOX_0_1; 117 size_t i; 118 119 for (i = 0; i < NIC_PF_VF_MAILBOX_SIZE; i++) { 120 *mbx_data = nicvf_reg_read(nic, mbx_addr); 121 mbx_data++; 122 mbx_addr += sizeof(uint64_t); 123 } 124 125 /* Overwrite the message so we won't receive it again */ 126 nicvf_reg_write(nic, NIC_VF_PF_MAILBOX_0_1, 0x0); 127 128 nicvf_mbox_log("msg received id=0x%hhx %s (VF%d)", mbx.msg.msg, 129 nicvf_mbox_msg_str(mbx.msg.msg), nic->vf_id); 130 131 switch (mbx.msg.msg) { 132 case NIC_MBOX_MSG_READY: 133 nic->vf_id = mbx.nic_cfg.vf_id & 0x7F; 134 nic->tns_mode = mbx.nic_cfg.tns_mode & 0x7F; 135 nic->node = mbx.nic_cfg.node_id; 136 nic->sqs_mode = mbx.nic_cfg.sqs_mode; 137 nic->loopback_supported = mbx.nic_cfg.loopback_supported; 138 ether_addr_copy((struct ether_addr *)mbx.nic_cfg.mac_addr, 139 (struct ether_addr *)nic->mac_addr); 140 nic->pf_acked = true; 141 break; 142 case NIC_MBOX_MSG_ACK: 143 nic->pf_acked = true; 144 break; 145 case NIC_MBOX_MSG_NACK: 146 nic->pf_nacked = true; 147 break; 148 case NIC_MBOX_MSG_RSS_SIZE: 149 nic->rss_info.rss_size = mbx.rss_size.ind_tbl_size; 150 nic->pf_acked = true; 151 break; 152 case NIC_MBOX_MSG_BGX_LINK_CHANGE: 153 nic->link_up = mbx.link_status.link_up; 154 nic->duplex = mbx.link_status.duplex; 155 nic->speed = mbx.link_status.speed; 156 nic->pf_acked = true; 157 break; 158 case NIC_MBOX_MSG_ALLOC_SQS: 159 assert_primary(nic); 160 if (mbx.sqs_alloc.qs_count != nic->sqs_count) { 161 nicvf_log_error("Received %" PRIu8 "/%" PRIu8 162 " secondary qsets", 163 mbx.sqs_alloc.qs_count, 164 nic->sqs_count); 165 abort(); 166 } 167 for (i = 0; i < mbx.sqs_alloc.qs_count; i++) { 168 if (mbx.sqs_alloc.svf[i] != nic->snicvf[i]->vf_id) { 169 nicvf_log_error("Received secondary qset[%zu] " 170 "ID %" PRIu8 " expected %" 171 PRIu8, i, mbx.sqs_alloc.svf[i], 172 nic->snicvf[i]->vf_id); 173 abort(); 174 } 175 } 176 nic->pf_acked = true; 177 break; 178 default: 179 nicvf_log_error("Invalid message from PF, msg_id=0x%hhx %s", 180 mbx.msg.msg, nicvf_mbox_msg_str(mbx.msg.msg)); 181 break; 182 } 183 nicvf_smp_wmb(); 184 185 return mbx.msg.msg; 186 } 187 188 /* 189 * Checks if VF is able to communicate with PF 190 * and also gets the VNIC number this VF is associated to. 191 */ 192 int 193 nicvf_mbox_check_pf_ready(struct nicvf *nic) 194 { 195 struct nic_mbx mbx = { .msg = {.msg = NIC_MBOX_MSG_READY} }; 196 197 return nicvf_mbox_send_msg_to_pf(nic, &mbx); 198 } 199 200 int 201 nicvf_mbox_set_mac_addr(struct nicvf *nic, 202 const uint8_t mac[NICVF_MAC_ADDR_SIZE]) 203 { 204 struct nic_mbx mbx = { .msg = {0} }; 205 int i; 206 207 mbx.msg.msg = NIC_MBOX_MSG_SET_MAC; 208 mbx.mac.vf_id = nic->vf_id; 209 for (i = 0; i < 6; i++) 210 mbx.mac.mac_addr[i] = mac[i]; 211 212 return nicvf_mbox_send_msg_to_pf(nic, &mbx); 213 } 214 215 int 216 nicvf_mbox_config_cpi(struct nicvf *nic, uint32_t qcnt) 217 { 218 struct nic_mbx mbx = { .msg = { 0 } }; 219 220 mbx.msg.msg = NIC_MBOX_MSG_CPI_CFG; 221 mbx.cpi_cfg.vf_id = nic->vf_id; 222 mbx.cpi_cfg.cpi_alg = nic->cpi_alg; 223 mbx.cpi_cfg.rq_cnt = qcnt; 224 225 return nicvf_mbox_send_msg_to_pf(nic, &mbx); 226 } 227 228 int 229 nicvf_mbox_get_rss_size(struct nicvf *nic) 230 { 231 struct nic_mbx mbx = { .msg = { 0 } }; 232 233 mbx.msg.msg = NIC_MBOX_MSG_RSS_SIZE; 234 mbx.rss_size.vf_id = nic->vf_id; 235 236 /* Result will be stored in nic->rss_info.rss_size */ 237 return nicvf_mbox_send_msg_to_pf(nic, &mbx); 238 } 239 240 int 241 nicvf_mbox_config_rss(struct nicvf *nic) 242 { 243 struct nic_mbx mbx = { .msg = { 0 } }; 244 struct nicvf_rss_reta_info *rss = &nic->rss_info; 245 size_t tot_len = rss->rss_size; 246 size_t cur_len; 247 size_t cur_idx = 0; 248 size_t i; 249 250 mbx.rss_cfg.vf_id = nic->vf_id; 251 mbx.rss_cfg.hash_bits = rss->hash_bits; 252 mbx.rss_cfg.tbl_len = 0; 253 mbx.rss_cfg.tbl_offset = 0; 254 255 while (cur_idx < tot_len) { 256 cur_len = nicvf_min(tot_len - cur_idx, 257 (size_t)RSS_IND_TBL_LEN_PER_MBX_MSG); 258 mbx.msg.msg = (cur_idx > 0) ? 259 NIC_MBOX_MSG_RSS_CFG_CONT : NIC_MBOX_MSG_RSS_CFG; 260 mbx.rss_cfg.tbl_offset = cur_idx; 261 mbx.rss_cfg.tbl_len = cur_len; 262 for (i = 0; i < cur_len; i++) 263 mbx.rss_cfg.ind_tbl[i] = rss->ind_tbl[cur_idx++]; 264 265 if (nicvf_mbox_send_msg_to_pf(nic, &mbx)) 266 return NICVF_ERR_RSS_TBL_UPDATE; 267 } 268 269 return 0; 270 } 271 272 int 273 nicvf_mbox_rq_config(struct nicvf *nic, uint16_t qidx, 274 struct pf_rq_cfg *pf_rq_cfg) 275 { 276 struct nic_mbx mbx = { .msg = { 0 } }; 277 278 mbx.msg.msg = NIC_MBOX_MSG_RQ_CFG; 279 mbx.rq.qs_num = nic->vf_id; 280 mbx.rq.rq_num = qidx; 281 mbx.rq.cfg = pf_rq_cfg->value; 282 return nicvf_mbox_send_msg_to_pf(nic, &mbx); 283 } 284 285 int 286 nicvf_mbox_sq_config(struct nicvf *nic, uint16_t qidx) 287 { 288 struct nic_mbx mbx = { .msg = { 0 } }; 289 290 mbx.msg.msg = NIC_MBOX_MSG_SQ_CFG; 291 mbx.sq.qs_num = nic->vf_id; 292 mbx.sq.sq_num = qidx; 293 mbx.sq.sqs_mode = nic->sqs_mode; 294 mbx.sq.cfg = (nic->vf_id << 3) | qidx; 295 return nicvf_mbox_send_msg_to_pf(nic, &mbx); 296 } 297 298 int 299 nicvf_mbox_qset_config(struct nicvf *nic, struct pf_qs_cfg *qs_cfg) 300 { 301 struct nic_mbx mbx = { .msg = { 0 } }; 302 303 #if NICVF_BYTE_ORDER == NICVF_BIG_ENDIAN 304 qs_cfg->be = 1; 305 #endif 306 /* Send a mailbox msg to PF to config Qset */ 307 mbx.msg.msg = NIC_MBOX_MSG_QS_CFG; 308 mbx.qs.num = nic->vf_id; 309 mbx.qs.sqs_count = nic->sqs_count; 310 mbx.qs.cfg = qs_cfg->value; 311 return nicvf_mbox_send_msg_to_pf(nic, &mbx); 312 } 313 314 int 315 nicvf_mbox_request_sqs(struct nicvf *nic) 316 { 317 struct nic_mbx mbx = { .msg = { 0 } }; 318 size_t i; 319 320 assert_primary(nic); 321 assert(nic->sqs_count > 0); 322 assert(nic->sqs_count <= MAX_SQS_PER_VF); 323 324 mbx.sqs_alloc.msg = NIC_MBOX_MSG_ALLOC_SQS; 325 mbx.sqs_alloc.spec = 1; 326 mbx.sqs_alloc.qs_count = nic->sqs_count; 327 328 /* Set no of Rx/Tx queues in each of the SQsets */ 329 for (i = 0; i < nic->sqs_count; i++) 330 mbx.sqs_alloc.svf[i] = nic->snicvf[i]->vf_id; 331 332 return nicvf_mbox_send_msg_to_pf(nic, &mbx); 333 } 334 335 int 336 nicvf_mbox_rq_drop_config(struct nicvf *nic, uint16_t qidx, bool enable) 337 { 338 struct nic_mbx mbx = { .msg = { 0 } }; 339 struct pf_rq_drop_cfg *drop_cfg; 340 341 /* Enable CQ drop to reserve sufficient CQEs for all tx packets */ 342 mbx.msg.msg = NIC_MBOX_MSG_RQ_DROP_CFG; 343 mbx.rq.qs_num = nic->vf_id; 344 mbx.rq.rq_num = qidx; 345 drop_cfg = (struct pf_rq_drop_cfg *)&mbx.rq.cfg; 346 drop_cfg->value = 0; 347 if (enable) { 348 drop_cfg->cq_red = 1; 349 drop_cfg->cq_drop = 2; 350 } 351 return nicvf_mbox_send_msg_to_pf(nic, &mbx); 352 } 353 354 int 355 nicvf_mbox_update_hw_max_frs(struct nicvf *nic, uint16_t mtu) 356 { 357 struct nic_mbx mbx = { .msg = { 0 } }; 358 359 mbx.msg.msg = NIC_MBOX_MSG_SET_MAX_FRS; 360 mbx.frs.max_frs = mtu; 361 mbx.frs.vf_id = nic->vf_id; 362 return nicvf_mbox_send_msg_to_pf(nic, &mbx); 363 } 364 365 int 366 nicvf_mbox_rq_sync(struct nicvf *nic) 367 { 368 struct nic_mbx mbx = { .msg = { 0 } }; 369 370 /* Make sure all packets in the pipeline are written back into mem */ 371 mbx.msg.msg = NIC_MBOX_MSG_RQ_SW_SYNC; 372 mbx.rq.cfg = 0; 373 return nicvf_mbox_send_msg_to_pf(nic, &mbx); 374 } 375 376 int 377 nicvf_mbox_rq_bp_config(struct nicvf *nic, uint16_t qidx, bool enable) 378 { 379 struct nic_mbx mbx = { .msg = { 0 } }; 380 381 mbx.msg.msg = NIC_MBOX_MSG_RQ_BP_CFG; 382 mbx.rq.qs_num = nic->vf_id; 383 mbx.rq.rq_num = qidx; 384 mbx.rq.cfg = 0; 385 if (enable) 386 mbx.rq.cfg = (1ULL << 63) | (1ULL << 62) | (nic->vf_id << 0); 387 return nicvf_mbox_send_msg_to_pf(nic, &mbx); 388 } 389 390 int 391 nicvf_mbox_loopback_config(struct nicvf *nic, bool enable) 392 { 393 struct nic_mbx mbx = { .msg = { 0 } }; 394 395 mbx.lbk.msg = NIC_MBOX_MSG_LOOPBACK; 396 mbx.lbk.vf_id = nic->vf_id; 397 mbx.lbk.enable = enable; 398 return nicvf_mbox_send_msg_to_pf(nic, &mbx); 399 } 400 401 int 402 nicvf_mbox_reset_stat_counters(struct nicvf *nic, uint16_t rx_stat_mask, 403 uint8_t tx_stat_mask, uint16_t rq_stat_mask, 404 uint16_t sq_stat_mask) 405 { 406 struct nic_mbx mbx = { .msg = { 0 } }; 407 408 mbx.reset_stat.msg = NIC_MBOX_MSG_RESET_STAT_COUNTER; 409 mbx.reset_stat.rx_stat_mask = rx_stat_mask; 410 mbx.reset_stat.tx_stat_mask = tx_stat_mask; 411 mbx.reset_stat.rq_stat_mask = rq_stat_mask; 412 mbx.reset_stat.sq_stat_mask = sq_stat_mask; 413 return nicvf_mbox_send_msg_to_pf(nic, &mbx); 414 } 415 416 int 417 nicvf_mbox_set_link_up_down(struct nicvf *nic, bool enable) 418 { 419 struct nic_mbx mbx = { .msg = { 0 } }; 420 421 mbx.lbk.msg = NIC_MBOX_MSG_SET_LINK; 422 mbx.lbk.vf_id = nic->vf_id; 423 mbx.lbk.enable = enable; 424 return nicvf_mbox_send_msg_to_pf(nic, &mbx); 425 } 426 void 427 nicvf_mbox_shutdown(struct nicvf *nic) 428 { 429 struct nic_mbx mbx = { .msg = { 0 } }; 430 431 mbx.msg.msg = NIC_MBOX_MSG_SHUTDOWN; 432 nicvf_mbox_send_msg_to_pf(nic, &mbx); 433 } 434 435 void 436 nicvf_mbox_cfg_done(struct nicvf *nic) 437 { 438 struct nic_mbx mbx = { .msg = { 0 } }; 439 440 mbx.msg.msg = NIC_MBOX_MSG_CFG_DONE; 441 nicvf_mbox_send_async_msg_to_pf(nic, &mbx); 442 } 443