1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2017 Huawei Technologies Co., Ltd 3 */ 4 5 #include "hinic_compat.h" 6 #include "hinic_csr.h" 7 #include "hinic_pmd_hwdev.h" 8 #include "hinic_pmd_hwif.h" 9 #include "hinic_pmd_mgmt.h" 10 #include "hinic_pmd_mbox.h" 11 12 #define BUF_OUT_DEFAULT_SIZE 1 13 14 #define MAX_PF_MGMT_BUF_SIZE 2048UL 15 16 #define MGMT_MSG_SIZE_MIN 20 17 #define MGMT_MSG_SIZE_STEP 16 18 #define MGMT_MSG_RSVD_FOR_DEV 8 19 20 #define MGMT_MSG_TIMEOUT 5000 /* millisecond */ 21 22 #define SYNC_MSG_ID_MASK 0x1FF 23 #define ASYNC_MSG_ID_MASK 0x1FF 24 #define ASYNC_MSG_FLAG 0x200 25 26 #define MSG_NO_RESP 0xFFFF 27 28 #define MAX_MSG_SZ 2016 29 30 #define MSG_SZ_IS_VALID(in_size) ((in_size) <= MAX_MSG_SZ) 31 32 #define SYNC_MSG_ID(pf_to_mgmt) ((pf_to_mgmt)->sync_msg_id) 33 34 #define SYNC_MSG_ID_INC(pf_to_mgmt) (SYNC_MSG_ID(pf_to_mgmt) = \ 35 (SYNC_MSG_ID(pf_to_mgmt) + 1) & SYNC_MSG_ID_MASK) 36 37 #define ASYNC_MSG_ID(pf_to_mgmt) ((pf_to_mgmt)->async_msg_id) 38 39 #define ASYNC_MSG_ID_INC(pf_to_mgmt) (ASYNC_MSG_ID(pf_to_mgmt) = \ 40 ((ASYNC_MSG_ID(pf_to_mgmt) + 1) & ASYNC_MSG_ID_MASK) \ 41 | ASYNC_MSG_FLAG) 42 43 #define HINIC_SEQ_ID_MAX_VAL 42 44 #define HINIC_MSG_SEG_LEN 48 45 46 #define GET_CURR_AEQ_ELEM(eq) GET_AEQ_ELEM((eq), (eq)->cons_idx) 47 48 #define EQ_ELEM_DESC_TYPE_SHIFT 0 49 #define EQ_ELEM_DESC_SRC_SHIFT 7 50 #define EQ_ELEM_DESC_SIZE_SHIFT 8 51 #define EQ_ELEM_DESC_WRAPPED_SHIFT 31 52 53 #define EQ_ELEM_DESC_TYPE_MASK 0x7FU 54 #define EQ_ELEM_DESC_SRC_MASK 0x1U 55 #define EQ_ELEM_DESC_SIZE_MASK 0xFFU 56 #define EQ_ELEM_DESC_WRAPPED_MASK 0x1U 57 58 #define EQ_MSIX_RESEND_TIMER_CLEAR 1 59 60 #define EQ_ELEM_DESC_GET(val, member) \ 61 (((val) >> EQ_ELEM_DESC_##member##_SHIFT) & \ 62 EQ_ELEM_DESC_##member##_MASK) 63 64 #define HINIC_MGMT_CHANNEL_STATUS_SHIFT 0x0 65 #define HINIC_MGMT_CHANNEL_STATUS_MASK 0x1 66 67 #define HINIC_GET_MGMT_CHANNEL_STATUS(val, member) \ 68 (((val) >> HINIC_##member##_SHIFT) & HINIC_##member##_MASK) 69 70 #define HINIC_MSG_TO_MGMT_MAX_LEN 2016 71 72 /** 73 * mgmt_msg_len - calculate the total message length 74 * @msg_data_len: the length of the message data 75 * Return: the total message length 76 */ 77 static u16 mgmt_msg_len(u16 msg_data_len) 78 { 79 /* u64 - the size of the header */ 80 u16 msg_size = (u16)(MGMT_MSG_RSVD_FOR_DEV + sizeof(u64) + 81 msg_data_len); 82 83 if (msg_size > MGMT_MSG_SIZE_MIN) 84 msg_size = MGMT_MSG_SIZE_MIN + 85 ALIGN((msg_size - MGMT_MSG_SIZE_MIN), 86 MGMT_MSG_SIZE_STEP); 87 else 88 msg_size = MGMT_MSG_SIZE_MIN; 89 90 return msg_size; 91 } 92 93 /** 94 * prepare_header - prepare the header of the message 95 * @pf_to_mgmt: PF to MGMT channel 96 * @header: pointer of the header to prepare 97 * @msg_len: the length of the message 98 * @mod: module in the chip that will get the message 99 * @ack_type: the type to response 100 * @direction: the direction of the original message 101 * @cmd: the command to do 102 * @msg_id: message id 103 */ 104 static void prepare_header(struct hinic_msg_pf_to_mgmt *pf_to_mgmt, 105 u64 *header, int msg_len, enum hinic_mod_type mod, 106 enum hinic_msg_ack_type ack_type, 107 enum hinic_msg_direction_type direction, 108 u8 cmd, u32 msg_id) 109 { 110 struct hinic_hwif *hwif = pf_to_mgmt->hwdev->hwif; 111 112 *header = HINIC_MSG_HEADER_SET(msg_len, MSG_LEN) | 113 HINIC_MSG_HEADER_SET(mod, MODULE) | 114 HINIC_MSG_HEADER_SET(msg_len, SEG_LEN) | 115 HINIC_MSG_HEADER_SET(ack_type, NO_ACK) | 116 HINIC_MSG_HEADER_SET(0, ASYNC_MGMT_TO_PF) | 117 HINIC_MSG_HEADER_SET(0, SEQID) | 118 HINIC_MSG_HEADER_SET(LAST_SEGMENT, LAST) | 119 HINIC_MSG_HEADER_SET(direction, DIRECTION) | 120 HINIC_MSG_HEADER_SET(cmd, CMD) | 121 HINIC_MSG_HEADER_SET(HINIC_PCI_INTF_IDX(hwif), PCI_INTF_IDX) | 122 HINIC_MSG_HEADER_SET(hwif->attr.port_to_port_idx, P2P_IDX) | 123 HINIC_MSG_HEADER_SET(msg_id, MSG_ID); 124 } 125 126 /** 127 * prepare_mgmt_cmd - prepare the mgmt command 128 * @mgmt_cmd: pointer to the command to prepare 129 * @header: pointer of the header to prepare 130 * @msg: the data of the message 131 * @msg_len: the length of the message 132 */ 133 static void prepare_mgmt_cmd(u8 *mgmt_cmd, u64 *header, void *msg, 134 int msg_len) 135 { 136 u32 cmd_buf_max = MAX_PF_MGMT_BUF_SIZE; 137 138 memset(mgmt_cmd, 0, MGMT_MSG_RSVD_FOR_DEV); 139 140 mgmt_cmd += MGMT_MSG_RSVD_FOR_DEV; 141 cmd_buf_max -= MGMT_MSG_RSVD_FOR_DEV; 142 memcpy(mgmt_cmd, header, sizeof(*header)); 143 144 mgmt_cmd += sizeof(*header); 145 cmd_buf_max -= sizeof(*header); 146 memcpy(mgmt_cmd, msg, msg_len); 147 } 148 149 /** 150 * alloc_recv_msg - allocate received message memory 151 * @recv_msg: pointer that will hold the allocated data 152 * Return: 0 - success, negative - failure 153 */ 154 static int alloc_recv_msg(struct hinic_recv_msg *recv_msg) 155 { 156 int err; 157 158 recv_msg->msg = kzalloc(MAX_PF_MGMT_BUF_SIZE, GFP_KERNEL); 159 if (!recv_msg->msg) { 160 PMD_DRV_LOG(ERR, "Allocate recv msg buf failed"); 161 return -ENOMEM; 162 } 163 164 recv_msg->buf_out = kzalloc(MAX_PF_MGMT_BUF_SIZE, GFP_KERNEL); 165 if (!recv_msg->buf_out) { 166 PMD_DRV_LOG(ERR, "Allocate recv msg output buf failed"); 167 err = -ENOMEM; 168 goto alloc_buf_out_err; 169 } 170 171 return 0; 172 173 alloc_buf_out_err: 174 kfree(recv_msg->msg); 175 return err; 176 } 177 178 /** 179 * free_recv_msg - free received message memory 180 * @recv_msg: pointer that holds the allocated data 181 */ 182 static void free_recv_msg(struct hinic_recv_msg *recv_msg) 183 { 184 kfree(recv_msg->buf_out); 185 kfree(recv_msg->msg); 186 } 187 188 /** 189 * alloc_msg_buf - allocate all the message buffers of PF to MGMT channel 190 * @pf_to_mgmt: PF to MGMT channel 191 * Return: 0 - success, negative - failure 192 */ 193 static int alloc_msg_buf(struct hinic_msg_pf_to_mgmt *pf_to_mgmt) 194 { 195 int err; 196 197 err = alloc_recv_msg(&pf_to_mgmt->recv_msg_from_mgmt); 198 if (err) { 199 PMD_DRV_LOG(ERR, "Allocate recv msg failed"); 200 return err; 201 } 202 203 err = alloc_recv_msg(&pf_to_mgmt->recv_resp_msg_from_mgmt); 204 if (err) { 205 PMD_DRV_LOG(ERR, "Allocate resp recv msg failed"); 206 goto alloc_msg_for_resp_err; 207 } 208 209 pf_to_mgmt->async_msg_buf = kzalloc(MAX_PF_MGMT_BUF_SIZE, GFP_KERNEL); 210 if (!pf_to_mgmt->async_msg_buf) { 211 PMD_DRV_LOG(ERR, "Allocate async msg buf failed"); 212 err = -ENOMEM; 213 goto async_msg_buf_err; 214 } 215 216 pf_to_mgmt->sync_msg_buf = kzalloc(MAX_PF_MGMT_BUF_SIZE, GFP_KERNEL); 217 if (!pf_to_mgmt->sync_msg_buf) { 218 PMD_DRV_LOG(ERR, "Allocate sync msg buf failed"); 219 err = -ENOMEM; 220 goto sync_msg_buf_err; 221 } 222 223 return 0; 224 225 sync_msg_buf_err: 226 kfree(pf_to_mgmt->async_msg_buf); 227 228 async_msg_buf_err: 229 free_recv_msg(&pf_to_mgmt->recv_resp_msg_from_mgmt); 230 231 alloc_msg_for_resp_err: 232 free_recv_msg(&pf_to_mgmt->recv_msg_from_mgmt); 233 234 return err; 235 } 236 237 /** 238 * free_msg_buf - free all the message buffers of PF to MGMT channel 239 * @pf_to_mgmt: PF to MGMT channel 240 * Return: 0 - success, negative - failure 241 */ 242 static void free_msg_buf(struct hinic_msg_pf_to_mgmt *pf_to_mgmt) 243 { 244 kfree(pf_to_mgmt->sync_msg_buf); 245 kfree(pf_to_mgmt->async_msg_buf); 246 247 free_recv_msg(&pf_to_mgmt->recv_resp_msg_from_mgmt); 248 free_recv_msg(&pf_to_mgmt->recv_msg_from_mgmt); 249 } 250 251 static int hinic_get_mgmt_channel_status(void *hwdev) 252 { 253 struct hinic_hwif *hwif = ((struct hinic_hwdev *)hwdev)->hwif; 254 u32 val; 255 256 if (hinic_func_type((struct hinic_hwdev *)hwdev) == TYPE_VF) 257 return false; 258 259 val = hinic_hwif_read_reg(hwif, HINIC_ICPL_RESERVD_ADDR); 260 261 return HINIC_GET_MGMT_CHANNEL_STATUS(val, MGMT_CHANNEL_STATUS); 262 } 263 264 /** 265 * send_msg_to_mgmt_async - send async message 266 * @pf_to_mgmt: PF to MGMT channel 267 * @mod: module in the chip that will get the message 268 * @cmd: command of the message 269 * @msg: the data of the message 270 * @msg_len: the length of the message 271 * @direction: the direction of the original message 272 * @resp_msg_id: message id of response 273 * Return: 0 - success, negative - failure 274 */ 275 static int send_msg_to_mgmt_async(struct hinic_msg_pf_to_mgmt *pf_to_mgmt, 276 enum hinic_mod_type mod, u8 cmd, 277 void *msg, u16 msg_len, 278 enum hinic_msg_direction_type direction, 279 u16 resp_msg_id) 280 { 281 void *mgmt_cmd = pf_to_mgmt->async_msg_buf; 282 struct hinic_api_cmd_chain *chain; 283 u64 header; 284 u16 cmd_size = mgmt_msg_len(msg_len); 285 286 if (direction == HINIC_MSG_RESPONSE) 287 prepare_header(pf_to_mgmt, &header, msg_len, mod, HINIC_MSG_ACK, 288 direction, cmd, resp_msg_id); 289 else 290 prepare_header(pf_to_mgmt, &header, msg_len, mod, HINIC_MSG_ACK, 291 direction, cmd, ASYNC_MSG_ID(pf_to_mgmt)); 292 293 prepare_mgmt_cmd((u8 *)mgmt_cmd, &header, msg, msg_len); 294 295 chain = pf_to_mgmt->cmd_chain[HINIC_API_CMD_WRITE_ASYNC_TO_MGMT_CPU]; 296 297 return hinic_api_cmd_write(chain, HINIC_NODE_ID_MGMT_HOST, mgmt_cmd, 298 cmd_size); 299 } 300 301 /** 302 * send_msg_to_mgmt_sync - send async message 303 * @pf_to_mgmt: PF to MGMT channel 304 * @mod: module in the chip that will get the message 305 * @cmd: command of the message 306 * @msg: the msg data 307 * @msg_len: the msg data length 308 * @ack_type: indicate mgmt command whether need ack or not 309 * @direction: the direction of the original message 310 * @resp_msg_id: msg id to response for 311 * Return: 0 - success, negative - failure 312 */ 313 static int send_msg_to_mgmt_sync(struct hinic_msg_pf_to_mgmt *pf_to_mgmt, 314 enum hinic_mod_type mod, u8 cmd, 315 void *msg, u16 msg_len, 316 enum hinic_msg_ack_type ack_type, 317 enum hinic_msg_direction_type direction, 318 __rte_unused u16 resp_msg_id) 319 { 320 void *mgmt_cmd = pf_to_mgmt->sync_msg_buf; 321 struct hinic_api_cmd_chain *chain; 322 u64 header; 323 u16 cmd_size = mgmt_msg_len(msg_len); 324 325 /* If fw is hot active, return failed */ 326 if (hinic_get_mgmt_channel_status(pf_to_mgmt->hwdev)) { 327 if (mod == HINIC_MOD_COMM || mod == HINIC_MOD_L2NIC) 328 return HINIC_DEV_BUSY_ACTIVE_FW; 329 else 330 return -EBUSY; 331 } 332 333 if (direction == HINIC_MSG_RESPONSE) 334 prepare_header(pf_to_mgmt, &header, msg_len, mod, ack_type, 335 direction, cmd, resp_msg_id); 336 else 337 prepare_header(pf_to_mgmt, &header, msg_len, mod, ack_type, 338 direction, cmd, SYNC_MSG_ID(pf_to_mgmt)); 339 340 prepare_mgmt_cmd((u8 *)mgmt_cmd, &header, msg, msg_len); 341 342 chain = pf_to_mgmt->cmd_chain[HINIC_API_CMD_PMD_WRITE_TO_MGMT]; 343 344 return hinic_api_cmd_write(chain, HINIC_NODE_ID_MGMT_HOST, 345 mgmt_cmd, cmd_size); 346 } 347 348 /** 349 * hinic_pf_to_mgmt_init - initialize PF to MGMT channel 350 * @hwdev: the pointer to the private hardware device object 351 * Return: 0 - success, negative - failure 352 */ 353 static int hinic_pf_to_mgmt_init(struct hinic_hwdev *hwdev) 354 { 355 struct hinic_msg_pf_to_mgmt *pf_to_mgmt; 356 int err; 357 358 pf_to_mgmt = kzalloc(sizeof(*pf_to_mgmt), GFP_KERNEL); 359 if (!pf_to_mgmt) { 360 PMD_DRV_LOG(ERR, "Allocate pf to mgmt mem failed"); 361 return -ENOMEM; 362 } 363 364 hwdev->pf_to_mgmt = pf_to_mgmt; 365 pf_to_mgmt->hwdev = hwdev; 366 367 err = hinic_mutex_init(&pf_to_mgmt->sync_msg_mutex, NULL); 368 if (err) 369 goto mutex_init_err; 370 371 err = alloc_msg_buf(pf_to_mgmt); 372 if (err) { 373 PMD_DRV_LOG(ERR, "Allocate msg buffers failed"); 374 goto alloc_msg_buf_err; 375 } 376 377 err = hinic_api_cmd_init(hwdev, pf_to_mgmt->cmd_chain); 378 if (err) { 379 PMD_DRV_LOG(ERR, "Init the api cmd chains failed"); 380 goto api_cmd_init_err; 381 } 382 383 return 0; 384 385 api_cmd_init_err: 386 free_msg_buf(pf_to_mgmt); 387 388 alloc_msg_buf_err: 389 hinic_mutex_destroy(&pf_to_mgmt->sync_msg_mutex); 390 391 mutex_init_err: 392 kfree(pf_to_mgmt); 393 394 return err; 395 } 396 397 /** 398 * hinic_pf_to_mgmt_free - free PF to MGMT channel 399 * @hwdev: the pointer to the private hardware device object 400 */ 401 static void hinic_pf_to_mgmt_free(struct hinic_hwdev *hwdev) 402 { 403 struct hinic_msg_pf_to_mgmt *pf_to_mgmt = hwdev->pf_to_mgmt; 404 405 hinic_api_cmd_free(pf_to_mgmt->cmd_chain); 406 free_msg_buf(pf_to_mgmt); 407 hinic_mutex_destroy(&pf_to_mgmt->sync_msg_mutex); 408 kfree(pf_to_mgmt); 409 } 410 411 static int 412 hinic_pf_to_mgmt_sync(struct hinic_hwdev *hwdev, 413 enum hinic_mod_type mod, u8 cmd, void *buf_in, u16 in_size, 414 void *buf_out, u16 *out_size, u32 timeout) 415 { 416 struct hinic_msg_pf_to_mgmt *pf_to_mgmt = hwdev->pf_to_mgmt; 417 struct hinic_recv_msg *recv_msg; 418 u32 timeo; 419 int err, i; 420 421 err = hinic_mutex_lock(&pf_to_mgmt->sync_msg_mutex); 422 if (err) 423 return err; 424 425 SYNC_MSG_ID_INC(pf_to_mgmt); 426 recv_msg = &pf_to_mgmt->recv_resp_msg_from_mgmt; 427 428 err = send_msg_to_mgmt_sync(pf_to_mgmt, mod, cmd, buf_in, in_size, 429 HINIC_MSG_ACK, HINIC_MSG_DIRECT_SEND, 430 MSG_NO_RESP); 431 if (err) { 432 PMD_DRV_LOG(ERR, "Send msg to mgmt failed"); 433 goto unlock_sync_msg; 434 } 435 436 timeo = msecs_to_jiffies(timeout ? timeout : MGMT_MSG_TIMEOUT); 437 for (i = 0; i < pf_to_mgmt->rx_aeq->poll_retry_nr; i++) { 438 err = hinic_aeq_poll_msg(pf_to_mgmt->rx_aeq, timeo, NULL); 439 if (err) { 440 PMD_DRV_LOG(ERR, "Poll mgmt rsp timeout, mod=%d cmd=%d msg_id=%u rc=%d", 441 mod, cmd, pf_to_mgmt->sync_msg_id, err); 442 err = -ETIMEDOUT; 443 hinic_dump_aeq_info(hwdev); 444 goto unlock_sync_msg; 445 } else { 446 if (mod == recv_msg->mod && cmd == recv_msg->cmd && 447 recv_msg->msg_id == pf_to_mgmt->sync_msg_id) { 448 /* the expected response polled */ 449 break; 450 } 451 PMD_DRV_LOG(ERR, "AEQ[%d] poll(mod=%d, cmd=%d, msg_id=%u) an " 452 "unexpected(mod=%d, cmd=%d, msg_id=%u) response", 453 pf_to_mgmt->rx_aeq->q_id, mod, cmd, 454 pf_to_mgmt->sync_msg_id, recv_msg->mod, 455 recv_msg->cmd, recv_msg->msg_id); 456 } 457 } 458 459 if (i == pf_to_mgmt->rx_aeq->poll_retry_nr) { 460 PMD_DRV_LOG(ERR, "Get %d unexpected mgmt rsp from AEQ[%d], poll mgmt rsp failed", 461 i, pf_to_mgmt->rx_aeq->q_id); 462 err = -EBADMSG; 463 goto unlock_sync_msg; 464 } 465 466 rte_smp_rmb(); 467 if (recv_msg->msg_len && buf_out && out_size) { 468 if (recv_msg->msg_len <= *out_size) { 469 memcpy(buf_out, recv_msg->msg, 470 recv_msg->msg_len); 471 *out_size = recv_msg->msg_len; 472 } else { 473 PMD_DRV_LOG(ERR, "Mgmt rsp's msg len: %u overflow.", 474 recv_msg->msg_len); 475 err = -ERANGE; 476 } 477 } 478 479 unlock_sync_msg: 480 if (err && out_size) 481 *out_size = 0; 482 (void)hinic_mutex_unlock(&pf_to_mgmt->sync_msg_mutex); 483 return err; 484 } 485 486 int hinic_msg_to_mgmt_sync(void *hwdev, enum hinic_mod_type mod, u8 cmd, 487 void *buf_in, u16 in_size, 488 void *buf_out, u16 *out_size, u32 timeout) 489 { 490 int rc = HINIC_ERROR; 491 492 if (!hwdev || in_size > HINIC_MSG_TO_MGMT_MAX_LEN) 493 return -EINVAL; 494 495 if (hinic_func_type(hwdev) == TYPE_VF) { 496 rc = hinic_mbox_to_pf(hwdev, mod, cmd, buf_in, in_size, 497 buf_out, out_size, timeout); 498 } else { 499 rc = hinic_pf_to_mgmt_sync(hwdev, mod, cmd, buf_in, in_size, 500 buf_out, out_size, timeout); 501 } 502 503 return rc; 504 } 505 506 int hinic_msg_to_mgmt_no_ack(void *hwdev, enum hinic_mod_type mod, u8 cmd, 507 void *buf_in, u16 in_size) 508 { 509 struct hinic_msg_pf_to_mgmt *pf_to_mgmt = 510 ((struct hinic_hwdev *)hwdev)->pf_to_mgmt; 511 int err = -EINVAL; 512 513 if (!MSG_SZ_IS_VALID(in_size)) { 514 PMD_DRV_LOG(ERR, "Mgmt msg buffer size is invalid"); 515 return err; 516 } 517 518 err = hinic_mutex_lock(&pf_to_mgmt->sync_msg_mutex); 519 if (err) 520 return err; 521 522 err = send_msg_to_mgmt_sync(pf_to_mgmt, mod, cmd, buf_in, in_size, 523 HINIC_MSG_NO_ACK, HINIC_MSG_DIRECT_SEND, 524 MSG_NO_RESP); 525 526 (void)hinic_mutex_unlock(&pf_to_mgmt->sync_msg_mutex); 527 528 return err; 529 } 530 531 static bool check_mgmt_seq_id_and_seg_len(struct hinic_recv_msg *recv_msg, 532 u8 seq_id, u8 seg_len, u16 msg_id) 533 { 534 if (seq_id > HINIC_SEQ_ID_MAX_VAL || seg_len > HINIC_MSG_SEG_LEN) 535 return false; 536 537 if (seq_id == 0) { 538 recv_msg->seq_id = seq_id; 539 recv_msg->msg_id = msg_id; 540 } else { 541 if ((seq_id != recv_msg->seq_id + 1) || 542 msg_id != recv_msg->msg_id) { 543 recv_msg->seq_id = 0; 544 return false; 545 } 546 recv_msg->seq_id = seq_id; 547 } 548 549 return true; 550 } 551 552 /** 553 * hinic_mgmt_recv_msg_handler - handler for message from mgmt cpu 554 * @pf_to_mgmt: PF to MGMT channel 555 * @recv_msg: received message details 556 * @param: customized parameter 557 */ 558 static void hinic_mgmt_recv_msg_handler(struct hinic_msg_pf_to_mgmt *pf_to_mgmt, 559 struct hinic_recv_msg *recv_msg, 560 void *param) 561 { 562 void *buf_out = recv_msg->buf_out; 563 u16 out_size = 0; 564 565 switch (recv_msg->mod) { 566 case HINIC_MOD_COMM: 567 hinic_comm_async_event_handle(pf_to_mgmt->hwdev, 568 recv_msg->cmd, recv_msg->msg, 569 recv_msg->msg_len, 570 buf_out, &out_size); 571 break; 572 case HINIC_MOD_L2NIC: 573 hinic_l2nic_async_event_handle(pf_to_mgmt->hwdev, param, 574 recv_msg->cmd, recv_msg->msg, 575 recv_msg->msg_len, 576 buf_out, &out_size); 577 break; 578 case HINIC_MOD_HILINK: 579 hinic_hilink_async_event_handle(pf_to_mgmt->hwdev, 580 recv_msg->cmd, recv_msg->msg, 581 recv_msg->msg_len, 582 buf_out, &out_size); 583 break; 584 default: 585 PMD_DRV_LOG(ERR, "No handler, mod: %d", recv_msg->mod); 586 break; 587 } 588 589 if (!recv_msg->async_mgmt_to_pf) { 590 if (!out_size) 591 out_size = BUF_OUT_DEFAULT_SIZE; 592 593 /* MGMT sent sync msg, send the response */ 594 (void)send_msg_to_mgmt_async(pf_to_mgmt, recv_msg->mod, 595 recv_msg->cmd, buf_out, out_size, 596 HINIC_MSG_RESPONSE, 597 recv_msg->msg_id); 598 } 599 } 600 601 /** 602 * recv_mgmt_msg_handler - handler a message from mgmt cpu 603 * @pf_to_mgmt: PF to MGMT channel 604 * @header: the header of the message 605 * @recv_msg: received message details 606 * @param: customized parameter 607 * Return: 0 when aeq is response message, -1 default result, 608 * and when wrong message or not last message 609 */ 610 static int recv_mgmt_msg_handler(struct hinic_msg_pf_to_mgmt *pf_to_mgmt, 611 u8 *header, struct hinic_recv_msg *recv_msg, 612 void *param) 613 { 614 u64 msg_header = *((u64 *)header); 615 void *msg_body = header + sizeof(msg_header); 616 u8 *dest_msg; 617 u8 seq_id, seq_len; 618 u32 msg_buf_max = MAX_PF_MGMT_BUF_SIZE; 619 u8 front_id; 620 u16 msg_id; 621 622 seq_id = HINIC_MSG_HEADER_GET(msg_header, SEQID); 623 seq_len = HINIC_MSG_HEADER_GET(msg_header, SEG_LEN); 624 front_id = recv_msg->seq_id; 625 msg_id = HINIC_MSG_HEADER_GET(msg_header, MSG_ID); 626 627 if (!check_mgmt_seq_id_and_seg_len(recv_msg, seq_id, seq_len, msg_id)) { 628 PMD_DRV_LOG(ERR, 629 "Mgmt msg sequence and segment check failed, " 630 "func id: 0x%x, front id: 0x%x, current id: 0x%x, seg len: 0x%x " 631 "front msg_id: %d, cur msg_id: %d", 632 hinic_global_func_id(pf_to_mgmt->hwdev), 633 front_id, seq_id, seq_len, recv_msg->msg_id, msg_id); 634 return HINIC_ERROR; 635 } 636 637 dest_msg = (u8 *)recv_msg->msg + seq_id * HINIC_MSG_SEG_LEN; 638 msg_buf_max -= seq_id * HINIC_MSG_SEG_LEN; 639 memcpy(dest_msg, msg_body, seq_len); 640 641 if (!HINIC_MSG_HEADER_GET(msg_header, LAST)) 642 return HINIC_ERROR; 643 644 recv_msg->cmd = HINIC_MSG_HEADER_GET(msg_header, CMD); 645 recv_msg->mod = HINIC_MSG_HEADER_GET(msg_header, MODULE); 646 recv_msg->async_mgmt_to_pf = HINIC_MSG_HEADER_GET(msg_header, 647 ASYNC_MGMT_TO_PF); 648 recv_msg->msg_len = HINIC_MSG_HEADER_GET(msg_header, MSG_LEN); 649 recv_msg->msg_id = HINIC_MSG_HEADER_GET(msg_header, MSG_ID); 650 651 if (HINIC_MSG_HEADER_GET(msg_header, DIRECTION) == HINIC_MSG_RESPONSE) 652 return HINIC_OK; 653 654 hinic_mgmt_recv_msg_handler(pf_to_mgmt, recv_msg, param); 655 656 return HINIC_ERROR; 657 } 658 659 /** 660 * hinic_mgmt_msg_aeqe_handler - handler for a mgmt message event 661 * @hwdev: the pointer to the private hardware device object 662 * @header: the header of the message 663 * @size: unused 664 * @param: customized parameter 665 * Return: 0 when aeq is response message, 666 * -1 default result, and when wrong message or not last message 667 */ 668 static int hinic_mgmt_msg_aeqe_handler(void *hwdev, u8 *header, 669 __rte_unused u8 size, void *param) 670 { 671 struct hinic_msg_pf_to_mgmt *pf_to_mgmt = 672 ((struct hinic_hwdev *)hwdev)->pf_to_mgmt; 673 struct hinic_recv_msg *recv_msg; 674 675 recv_msg = (HINIC_MSG_HEADER_GET(*(u64 *)header, DIRECTION) == 676 HINIC_MSG_DIRECT_SEND) ? 677 &pf_to_mgmt->recv_msg_from_mgmt : 678 &pf_to_mgmt->recv_resp_msg_from_mgmt; 679 680 return recv_mgmt_msg_handler(pf_to_mgmt, header, recv_msg, param); 681 } 682 683 static int hinic_handle_aeqe(void *handle, enum hinic_aeq_type event, 684 u8 *data, u8 size, void *param) 685 { 686 int rc = 0; 687 688 switch (event) { 689 case HINIC_MSG_FROM_MGMT_CPU: 690 rc = hinic_mgmt_msg_aeqe_handler(handle, data, size, param); 691 break; 692 case HINIC_MBX_FROM_FUNC: 693 rc = hinic_mbox_func_aeqe_handler(handle, data, size, param); 694 break; 695 default: 696 PMD_DRV_LOG(ERR, "Unknown event type: 0x%x, size: %d", 697 event, size); 698 rc = HINIC_ERROR; 699 break; 700 } 701 702 return rc; 703 } 704 705 /** 706 * hinic_aeq_poll_msg - poll one or continue aeqe, and call dedicated process 707 * @eq: aeq of the chip 708 * @timeout: 0 - poll all aeqe in eq, used in interrupt mode, 709 * > 0 - poll aeq until get aeqe with 'last' field set to 1, 710 * used in polling mode. 711 * @param: customized parameter 712 * Return: 0 - Success, EIO - poll timeout, ENODEV - swe not support 713 */ 714 int hinic_aeq_poll_msg(struct hinic_eq *eq, u32 timeout, void *param) 715 { 716 struct hinic_aeq_elem *aeqe_pos; 717 enum hinic_aeq_type event; 718 u32 aeqe_desc = 0; 719 u16 i; 720 u8 size; 721 int done = HINIC_ERROR; 722 int err = -EFAULT; 723 unsigned long end; 724 725 for (i = 0; ((timeout == 0) && (i < eq->eq_len)) || 726 ((timeout > 0) && (done != HINIC_OK) && (i < eq->eq_len)); i++) { 727 err = -EIO; 728 end = jiffies + msecs_to_jiffies(timeout); 729 do { 730 aeqe_pos = GET_CURR_AEQ_ELEM(eq); 731 rte_rmb(); 732 733 /* Data in HW is in Big endian Format */ 734 aeqe_desc = be32_to_cpu(aeqe_pos->desc); 735 736 /* HW updates wrapped bit, 737 * when it adds eq element event 738 */ 739 if (EQ_ELEM_DESC_GET(aeqe_desc, WRAPPED) 740 != eq->wrapped) { 741 err = 0; 742 break; 743 } 744 745 if (timeout != 0) 746 usleep(1000); 747 } while (time_before(jiffies, end)); 748 749 if (err != HINIC_OK) /*poll time out*/ 750 break; 751 752 event = EQ_ELEM_DESC_GET(aeqe_desc, TYPE); 753 if (EQ_ELEM_DESC_GET(aeqe_desc, SRC)) { 754 PMD_DRV_LOG(ERR, "AEQ sw event not support %d", event); 755 return -ENODEV; 756 757 } else { 758 size = EQ_ELEM_DESC_GET(aeqe_desc, SIZE); 759 done = hinic_handle_aeqe(eq->hwdev, event, 760 aeqe_pos->aeqe_data, 761 size, param); 762 } 763 764 eq->cons_idx++; 765 if (eq->cons_idx == eq->eq_len) { 766 eq->cons_idx = 0; 767 eq->wrapped = !eq->wrapped; 768 } 769 } 770 771 eq_update_ci(eq); 772 773 return err; 774 } 775 776 int hinic_comm_pf_to_mgmt_init(struct hinic_hwdev *hwdev) 777 { 778 int rc; 779 780 /* VF do not support send msg to mgmt directly */ 781 if (hinic_func_type(hwdev) == TYPE_VF) 782 return 0; 783 784 rc = hinic_pf_to_mgmt_init(hwdev); 785 if (rc) 786 return rc; 787 788 hwdev->pf_to_mgmt->rx_aeq = &hwdev->aeqs->aeq[HINIC_MGMT_RSP_AEQN]; 789 790 return 0; 791 } 792 793 void hinic_comm_pf_to_mgmt_free(struct hinic_hwdev *hwdev) 794 { 795 /* VF do not support send msg to mgmt directly */ 796 if (hinic_func_type(hwdev) == TYPE_VF) 797 return; 798 799 hinic_pf_to_mgmt_free(hwdev); 800 } 801 802 void hinic_dev_handle_aeq_event(struct hinic_hwdev *hwdev, void *param) 803 { 804 struct hinic_eq *aeq = &hwdev->aeqs->aeq[0]; 805 806 /* clear resend timer cnt register */ 807 hinic_misx_intr_clear_resend_bit(hwdev, aeq->eq_irq.msix_entry_idx, 808 EQ_MSIX_RESEND_TIMER_CLEAR); 809 (void)hinic_aeq_poll_msg(aeq, 0, param); 810 } 811