1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Huawei HiNIC PCI Express Linux driver 4 * Copyright(c) 2017 Huawei Technologies Co., Ltd 5 */ 6 7 #include <linux/kernel.h> 8 #include <linux/types.h> 9 #include <linux/errno.h> 10 #include <linux/pci.h> 11 #include <linux/device.h> 12 #include <linux/semaphore.h> 13 #include <linux/completion.h> 14 #include <linux/slab.h> 15 #include <net/devlink.h> 16 #include <asm/barrier.h> 17 18 #include "hinic_devlink.h" 19 #include "hinic_hw_if.h" 20 #include "hinic_hw_eqs.h" 21 #include "hinic_hw_api_cmd.h" 22 #include "hinic_hw_mgmt.h" 23 #include "hinic_hw_dev.h" 24 25 #define SYNC_MSG_ID_MASK 0x1FF 26 27 #define SYNC_MSG_ID(pf_to_mgmt) ((pf_to_mgmt)->sync_msg_id) 28 29 #define SYNC_MSG_ID_INC(pf_to_mgmt) (SYNC_MSG_ID(pf_to_mgmt) = \ 30 ((SYNC_MSG_ID(pf_to_mgmt) + 1) & \ 31 SYNC_MSG_ID_MASK)) 32 33 #define MSG_SZ_IS_VALID(in_size) ((in_size) <= MAX_MSG_LEN) 34 35 #define MGMT_MSG_LEN_MIN 20 36 #define MGMT_MSG_LEN_STEP 16 37 #define MGMT_MSG_RSVD_FOR_DEV 8 38 39 #define SEGMENT_LEN 48 40 41 #define MAX_PF_MGMT_BUF_SIZE 2048 42 43 /* Data should be SEG LEN size aligned */ 44 #define MAX_MSG_LEN 2016 45 46 #define MSG_NOT_RESP 0xFFFF 47 48 #define MGMT_MSG_TIMEOUT 5000 49 50 #define SET_FUNC_PORT_MBOX_TIMEOUT 30000 51 52 #define SET_FUNC_PORT_MGMT_TIMEOUT 25000 53 54 #define UPDATE_FW_MGMT_TIMEOUT 20000 55 56 #define mgmt_to_pfhwdev(pf_mgmt) \ 57 container_of(pf_mgmt, struct hinic_pfhwdev, pf_to_mgmt) 58 59 enum msg_segment_type { 60 NOT_LAST_SEGMENT = 0, 61 LAST_SEGMENT = 1, 62 }; 63 64 enum mgmt_direction_type { 65 MGMT_DIRECT_SEND = 0, 66 MGMT_RESP = 1, 67 }; 68 69 enum msg_ack_type { 70 MSG_ACK = 0, 71 MSG_NO_ACK = 1, 72 }; 73 74 /** 75 * hinic_register_mgmt_msg_cb - register msg handler for a msg from a module 76 * @pf_to_mgmt: PF to MGMT channel 77 * @mod: module in the chip that this handler will handle its messages 78 * @handle: private data for the callback 79 * @callback: the handler that will handle messages 80 **/ 81 void hinic_register_mgmt_msg_cb(struct hinic_pf_to_mgmt *pf_to_mgmt, 82 enum hinic_mod_type mod, 83 void *handle, 84 void (*callback)(void *handle, 85 u8 cmd, void *buf_in, 86 u16 in_size, void *buf_out, 87 u16 *out_size)) 88 { 89 struct hinic_mgmt_cb *mgmt_cb = &pf_to_mgmt->mgmt_cb[mod]; 90 91 mgmt_cb->cb = callback; 92 mgmt_cb->handle = handle; 93 mgmt_cb->state = HINIC_MGMT_CB_ENABLED; 94 } 95 96 /** 97 * hinic_unregister_mgmt_msg_cb - unregister msg handler for a msg from a module 98 * @pf_to_mgmt: PF to MGMT channel 99 * @mod: module in the chip that this handler handles its messages 100 **/ 101 void hinic_unregister_mgmt_msg_cb(struct hinic_pf_to_mgmt *pf_to_mgmt, 102 enum hinic_mod_type mod) 103 { 104 struct hinic_mgmt_cb *mgmt_cb = &pf_to_mgmt->mgmt_cb[mod]; 105 106 mgmt_cb->state &= ~HINIC_MGMT_CB_ENABLED; 107 108 while (mgmt_cb->state & HINIC_MGMT_CB_RUNNING) 109 schedule(); 110 111 mgmt_cb->cb = NULL; 112 } 113 114 /** 115 * prepare_header - prepare the header of the message 116 * @pf_to_mgmt: PF to MGMT channel 117 * @msg_len: the length of the message 118 * @mod: module in the chip that will get the message 119 * @ack_type: ask for response 120 * @direction: the direction of the message 121 * @cmd: command of the message 122 * @msg_id: message id 123 * 124 * Return the prepared header value 125 **/ 126 static u64 prepare_header(struct hinic_pf_to_mgmt *pf_to_mgmt, 127 u16 msg_len, enum hinic_mod_type mod, 128 enum msg_ack_type ack_type, 129 enum mgmt_direction_type direction, 130 u16 cmd, u16 msg_id) 131 { 132 struct hinic_hwif *hwif = pf_to_mgmt->hwif; 133 134 return HINIC_MSG_HEADER_SET(msg_len, MSG_LEN) | 135 HINIC_MSG_HEADER_SET(mod, MODULE) | 136 HINIC_MSG_HEADER_SET(SEGMENT_LEN, SEG_LEN) | 137 HINIC_MSG_HEADER_SET(ack_type, NO_ACK) | 138 HINIC_MSG_HEADER_SET(0, ASYNC_MGMT_TO_PF) | 139 HINIC_MSG_HEADER_SET(0, SEQID) | 140 HINIC_MSG_HEADER_SET(LAST_SEGMENT, LAST) | 141 HINIC_MSG_HEADER_SET(direction, DIRECTION) | 142 HINIC_MSG_HEADER_SET(cmd, CMD) | 143 HINIC_MSG_HEADER_SET(HINIC_HWIF_PCI_INTF(hwif), PCI_INTF) | 144 HINIC_MSG_HEADER_SET(HINIC_HWIF_PF_IDX(hwif), PF_IDX) | 145 HINIC_MSG_HEADER_SET(msg_id, MSG_ID); 146 } 147 148 /** 149 * prepare_mgmt_cmd - prepare the mgmt command 150 * @mgmt_cmd: pointer to the command to prepare 151 * @header: pointer of the header for the message 152 * @msg: the data of the message 153 * @msg_len: the length of the message 154 **/ 155 static void prepare_mgmt_cmd(u8 *mgmt_cmd, u64 *header, u8 *msg, u16 msg_len) 156 { 157 memset(mgmt_cmd, 0, MGMT_MSG_RSVD_FOR_DEV); 158 159 mgmt_cmd += MGMT_MSG_RSVD_FOR_DEV; 160 memcpy(mgmt_cmd, header, sizeof(*header)); 161 162 mgmt_cmd += sizeof(*header); 163 memcpy(mgmt_cmd, msg, msg_len); 164 } 165 166 /** 167 * mgmt_msg_len - calculate the total message length 168 * @msg_data_len: the length of the message data 169 * 170 * Return the total message length 171 **/ 172 static u16 mgmt_msg_len(u16 msg_data_len) 173 { 174 /* RSVD + HEADER_SIZE + DATA_LEN */ 175 u16 msg_len = MGMT_MSG_RSVD_FOR_DEV + sizeof(u64) + msg_data_len; 176 177 if (msg_len > MGMT_MSG_LEN_MIN) 178 msg_len = MGMT_MSG_LEN_MIN + 179 ALIGN((msg_len - MGMT_MSG_LEN_MIN), 180 MGMT_MSG_LEN_STEP); 181 else 182 msg_len = MGMT_MSG_LEN_MIN; 183 184 return msg_len; 185 } 186 187 /** 188 * send_msg_to_mgmt - send message to mgmt by API CMD 189 * @pf_to_mgmt: PF to MGMT channel 190 * @mod: module in the chip that will get the message 191 * @cmd: command of the message 192 * @data: the msg data 193 * @data_len: the msg data length 194 * @ack_type: ask for response 195 * @direction: the direction of the original message 196 * @resp_msg_id: msg id to response for 197 * 198 * Return 0 - Success, negative - Failure 199 **/ 200 static int send_msg_to_mgmt(struct hinic_pf_to_mgmt *pf_to_mgmt, 201 enum hinic_mod_type mod, u8 cmd, 202 u8 *data, u16 data_len, 203 enum msg_ack_type ack_type, 204 enum mgmt_direction_type direction, 205 u16 resp_msg_id) 206 { 207 struct hinic_api_cmd_chain *chain; 208 u64 header; 209 u16 msg_id; 210 211 msg_id = SYNC_MSG_ID(pf_to_mgmt); 212 213 if (direction == MGMT_RESP) { 214 header = prepare_header(pf_to_mgmt, data_len, mod, ack_type, 215 direction, cmd, resp_msg_id); 216 } else { 217 SYNC_MSG_ID_INC(pf_to_mgmt); 218 header = prepare_header(pf_to_mgmt, data_len, mod, ack_type, 219 direction, cmd, msg_id); 220 } 221 222 prepare_mgmt_cmd(pf_to_mgmt->sync_msg_buf, &header, data, data_len); 223 224 chain = pf_to_mgmt->cmd_chain[HINIC_API_CMD_WRITE_TO_MGMT_CPU]; 225 return hinic_api_cmd_write(chain, HINIC_NODE_ID_MGMT, 226 pf_to_mgmt->sync_msg_buf, 227 mgmt_msg_len(data_len)); 228 } 229 230 /** 231 * msg_to_mgmt_sync - send sync message to mgmt 232 * @pf_to_mgmt: PF to MGMT channel 233 * @mod: module in the chip that will get the message 234 * @cmd: command of the message 235 * @buf_in: the msg data 236 * @in_size: the msg data length 237 * @buf_out: response 238 * @out_size: response length 239 * @direction: the direction of the original message 240 * @resp_msg_id: msg id to response for 241 * 242 * Return 0 - Success, negative - Failure 243 **/ 244 static int msg_to_mgmt_sync(struct hinic_pf_to_mgmt *pf_to_mgmt, 245 enum hinic_mod_type mod, u8 cmd, 246 u8 *buf_in, u16 in_size, 247 u8 *buf_out, u16 *out_size, 248 enum mgmt_direction_type direction, 249 u16 resp_msg_id, u32 timeout) 250 { 251 struct hinic_hwif *hwif = pf_to_mgmt->hwif; 252 struct pci_dev *pdev = hwif->pdev; 253 struct hinic_recv_msg *recv_msg; 254 struct completion *recv_done; 255 unsigned long timeo; 256 u16 msg_id; 257 int err; 258 259 /* Lock the sync_msg_buf */ 260 down(&pf_to_mgmt->sync_msg_lock); 261 262 recv_msg = &pf_to_mgmt->recv_resp_msg_from_mgmt; 263 recv_done = &recv_msg->recv_done; 264 265 if (resp_msg_id == MSG_NOT_RESP) 266 msg_id = SYNC_MSG_ID(pf_to_mgmt); 267 else 268 msg_id = resp_msg_id; 269 270 init_completion(recv_done); 271 272 err = send_msg_to_mgmt(pf_to_mgmt, mod, cmd, buf_in, in_size, 273 MSG_ACK, direction, resp_msg_id); 274 if (err) { 275 dev_err(&pdev->dev, "Failed to send sync msg to mgmt\n"); 276 goto unlock_sync_msg; 277 } 278 279 timeo = msecs_to_jiffies(timeout ? timeout : MGMT_MSG_TIMEOUT); 280 281 if (!wait_for_completion_timeout(recv_done, timeo)) { 282 dev_err(&pdev->dev, "MGMT timeout, MSG id = %d\n", msg_id); 283 hinic_dump_aeq_info(pf_to_mgmt->hwdev); 284 err = -ETIMEDOUT; 285 goto unlock_sync_msg; 286 } 287 288 smp_rmb(); /* verify reading after completion */ 289 290 if (recv_msg->msg_id != msg_id) { 291 dev_err(&pdev->dev, "incorrect MSG for id = %d\n", msg_id); 292 err = -EFAULT; 293 goto unlock_sync_msg; 294 } 295 296 if ((buf_out) && (recv_msg->msg_len <= MAX_PF_MGMT_BUF_SIZE)) { 297 memcpy(buf_out, recv_msg->msg, recv_msg->msg_len); 298 *out_size = recv_msg->msg_len; 299 } 300 301 unlock_sync_msg: 302 up(&pf_to_mgmt->sync_msg_lock); 303 return err; 304 } 305 306 /** 307 * msg_to_mgmt_async - send message to mgmt without response 308 * @pf_to_mgmt: PF to MGMT channel 309 * @mod: module in the chip that will get the message 310 * @cmd: command of the message 311 * @buf_in: the msg data 312 * @in_size: the msg data length 313 * @direction: the direction of the original message 314 * @resp_msg_id: msg id to response for 315 * 316 * Return 0 - Success, negative - Failure 317 **/ 318 static int msg_to_mgmt_async(struct hinic_pf_to_mgmt *pf_to_mgmt, 319 enum hinic_mod_type mod, u8 cmd, 320 u8 *buf_in, u16 in_size, 321 enum mgmt_direction_type direction, 322 u16 resp_msg_id) 323 { 324 int err; 325 326 /* Lock the sync_msg_buf */ 327 down(&pf_to_mgmt->sync_msg_lock); 328 329 err = send_msg_to_mgmt(pf_to_mgmt, mod, cmd, buf_in, in_size, 330 MSG_NO_ACK, direction, resp_msg_id); 331 332 up(&pf_to_mgmt->sync_msg_lock); 333 return err; 334 } 335 336 /** 337 * hinic_msg_to_mgmt - send message to mgmt 338 * @pf_to_mgmt: PF to MGMT channel 339 * @mod: module in the chip that will get the message 340 * @cmd: command of the message 341 * @buf_in: the msg data 342 * @in_size: the msg data length 343 * @buf_out: response 344 * @out_size: returned response length 345 * @sync: sync msg or async msg 346 * 347 * Return 0 - Success, negative - Failure 348 **/ 349 int hinic_msg_to_mgmt(struct hinic_pf_to_mgmt *pf_to_mgmt, 350 enum hinic_mod_type mod, u8 cmd, 351 void *buf_in, u16 in_size, void *buf_out, u16 *out_size, 352 enum hinic_mgmt_msg_type sync) 353 { 354 struct hinic_hwif *hwif = pf_to_mgmt->hwif; 355 struct pci_dev *pdev = hwif->pdev; 356 u32 timeout = 0; 357 358 if (sync != HINIC_MGMT_MSG_SYNC) { 359 dev_err(&pdev->dev, "Invalid MGMT msg type\n"); 360 return -EINVAL; 361 } 362 363 if (!MSG_SZ_IS_VALID(in_size)) { 364 dev_err(&pdev->dev, "Invalid MGMT msg buffer size\n"); 365 return -EINVAL; 366 } 367 368 if (HINIC_IS_VF(hwif)) { 369 if (cmd == HINIC_PORT_CMD_SET_FUNC_STATE) 370 timeout = SET_FUNC_PORT_MBOX_TIMEOUT; 371 372 return hinic_mbox_to_pf(pf_to_mgmt->hwdev, mod, cmd, buf_in, 373 in_size, buf_out, out_size, timeout); 374 } else { 375 if (cmd == HINIC_PORT_CMD_SET_FUNC_STATE) 376 timeout = SET_FUNC_PORT_MGMT_TIMEOUT; 377 else if (cmd == HINIC_PORT_CMD_UPDATE_FW) 378 timeout = UPDATE_FW_MGMT_TIMEOUT; 379 380 return msg_to_mgmt_sync(pf_to_mgmt, mod, cmd, buf_in, in_size, 381 buf_out, out_size, MGMT_DIRECT_SEND, 382 MSG_NOT_RESP, timeout); 383 } 384 } 385 386 static void recv_mgmt_msg_work_handler(struct work_struct *work) 387 { 388 struct hinic_mgmt_msg_handle_work *mgmt_work = 389 container_of(work, struct hinic_mgmt_msg_handle_work, work); 390 struct hinic_pf_to_mgmt *pf_to_mgmt = mgmt_work->pf_to_mgmt; 391 struct pci_dev *pdev = pf_to_mgmt->hwif->pdev; 392 u8 *buf_out = pf_to_mgmt->mgmt_ack_buf; 393 struct hinic_mgmt_cb *mgmt_cb; 394 unsigned long cb_state; 395 u16 out_size = 0; 396 397 memset(buf_out, 0, MAX_PF_MGMT_BUF_SIZE); 398 399 if (mgmt_work->mod >= HINIC_MOD_MAX) { 400 dev_err(&pdev->dev, "Unknown MGMT MSG module = %d\n", 401 mgmt_work->mod); 402 kfree(mgmt_work->msg); 403 kfree(mgmt_work); 404 return; 405 } 406 407 mgmt_cb = &pf_to_mgmt->mgmt_cb[mgmt_work->mod]; 408 409 cb_state = cmpxchg(&mgmt_cb->state, 410 HINIC_MGMT_CB_ENABLED, 411 HINIC_MGMT_CB_ENABLED | HINIC_MGMT_CB_RUNNING); 412 413 if ((cb_state == HINIC_MGMT_CB_ENABLED) && (mgmt_cb->cb)) 414 mgmt_cb->cb(mgmt_cb->handle, mgmt_work->cmd, 415 mgmt_work->msg, mgmt_work->msg_len, 416 buf_out, &out_size); 417 else 418 dev_err(&pdev->dev, "No MGMT msg handler, mod: %d, cmd: %d\n", 419 mgmt_work->mod, mgmt_work->cmd); 420 421 mgmt_cb->state &= ~HINIC_MGMT_CB_RUNNING; 422 423 if (!mgmt_work->async_mgmt_to_pf) 424 /* MGMT sent sync msg, send the response */ 425 msg_to_mgmt_async(pf_to_mgmt, mgmt_work->mod, mgmt_work->cmd, 426 buf_out, out_size, MGMT_RESP, 427 mgmt_work->msg_id); 428 429 kfree(mgmt_work->msg); 430 kfree(mgmt_work); 431 } 432 433 /** 434 * mgmt_recv_msg_handler - handler for message from mgmt cpu 435 * @pf_to_mgmt: PF to MGMT channel 436 * @recv_msg: received message details 437 **/ 438 static void mgmt_recv_msg_handler(struct hinic_pf_to_mgmt *pf_to_mgmt, 439 struct hinic_recv_msg *recv_msg) 440 { 441 struct hinic_mgmt_msg_handle_work *mgmt_work = NULL; 442 struct pci_dev *pdev = pf_to_mgmt->hwif->pdev; 443 444 mgmt_work = kzalloc(sizeof(*mgmt_work), GFP_KERNEL); 445 if (!mgmt_work) { 446 dev_err(&pdev->dev, "Allocate mgmt work memory failed\n"); 447 return; 448 } 449 450 if (recv_msg->msg_len) { 451 mgmt_work->msg = kzalloc(recv_msg->msg_len, GFP_KERNEL); 452 if (!mgmt_work->msg) { 453 dev_err(&pdev->dev, "Allocate mgmt msg memory failed\n"); 454 kfree(mgmt_work); 455 return; 456 } 457 } 458 459 mgmt_work->pf_to_mgmt = pf_to_mgmt; 460 mgmt_work->msg_len = recv_msg->msg_len; 461 memcpy(mgmt_work->msg, recv_msg->msg, recv_msg->msg_len); 462 mgmt_work->msg_id = recv_msg->msg_id; 463 mgmt_work->mod = recv_msg->mod; 464 mgmt_work->cmd = recv_msg->cmd; 465 mgmt_work->async_mgmt_to_pf = recv_msg->async_mgmt_to_pf; 466 467 INIT_WORK(&mgmt_work->work, recv_mgmt_msg_work_handler); 468 queue_work(pf_to_mgmt->workq, &mgmt_work->work); 469 } 470 471 /** 472 * mgmt_resp_msg_handler - handler for a response message from mgmt cpu 473 * @pf_to_mgmt: PF to MGMT channel 474 * @recv_msg: received message details 475 **/ 476 static void mgmt_resp_msg_handler(struct hinic_pf_to_mgmt *pf_to_mgmt, 477 struct hinic_recv_msg *recv_msg) 478 { 479 wmb(); /* verify writing all, before reading */ 480 481 complete(&recv_msg->recv_done); 482 } 483 484 /** 485 * recv_mgmt_msg_handler - handler for a message from mgmt cpu 486 * @pf_to_mgmt: PF to MGMT channel 487 * @header: the header of the message 488 * @recv_msg: received message details 489 **/ 490 static void recv_mgmt_msg_handler(struct hinic_pf_to_mgmt *pf_to_mgmt, 491 u64 *header, struct hinic_recv_msg *recv_msg) 492 { 493 struct hinic_hwif *hwif = pf_to_mgmt->hwif; 494 struct pci_dev *pdev = hwif->pdev; 495 int seq_id, seg_len; 496 u8 *msg_body; 497 498 seq_id = HINIC_MSG_HEADER_GET(*header, SEQID); 499 seg_len = HINIC_MSG_HEADER_GET(*header, SEG_LEN); 500 501 if (seq_id >= (MAX_MSG_LEN / SEGMENT_LEN)) { 502 dev_err(&pdev->dev, "recv big mgmt msg\n"); 503 return; 504 } 505 506 msg_body = (u8 *)header + sizeof(*header); 507 memcpy(recv_msg->msg + seq_id * SEGMENT_LEN, msg_body, seg_len); 508 509 if (!HINIC_MSG_HEADER_GET(*header, LAST)) 510 return; 511 512 recv_msg->cmd = HINIC_MSG_HEADER_GET(*header, CMD); 513 recv_msg->mod = HINIC_MSG_HEADER_GET(*header, MODULE); 514 recv_msg->async_mgmt_to_pf = HINIC_MSG_HEADER_GET(*header, 515 ASYNC_MGMT_TO_PF); 516 recv_msg->msg_len = HINIC_MSG_HEADER_GET(*header, MSG_LEN); 517 recv_msg->msg_id = HINIC_MSG_HEADER_GET(*header, MSG_ID); 518 519 if (HINIC_MSG_HEADER_GET(*header, DIRECTION) == MGMT_RESP) 520 mgmt_resp_msg_handler(pf_to_mgmt, recv_msg); 521 else 522 mgmt_recv_msg_handler(pf_to_mgmt, recv_msg); 523 } 524 525 /** 526 * mgmt_msg_aeqe_handler - handler for a mgmt message event 527 * @handle: PF to MGMT channel 528 * @data: the header of the message 529 * @size: unused 530 **/ 531 static void mgmt_msg_aeqe_handler(void *handle, void *data, u8 size) 532 { 533 struct hinic_pf_to_mgmt *pf_to_mgmt = handle; 534 struct hinic_recv_msg *recv_msg; 535 u64 *header = (u64 *)data; 536 537 recv_msg = HINIC_MSG_HEADER_GET(*header, DIRECTION) == 538 MGMT_DIRECT_SEND ? 539 &pf_to_mgmt->recv_msg_from_mgmt : 540 &pf_to_mgmt->recv_resp_msg_from_mgmt; 541 542 recv_mgmt_msg_handler(pf_to_mgmt, header, recv_msg); 543 } 544 545 /** 546 * alloc_recv_msg - allocate receive message memory 547 * @pf_to_mgmt: PF to MGMT channel 548 * @recv_msg: pointer that will hold the allocated data 549 * 550 * Return 0 - Success, negative - Failure 551 **/ 552 static int alloc_recv_msg(struct hinic_pf_to_mgmt *pf_to_mgmt, 553 struct hinic_recv_msg *recv_msg) 554 { 555 struct hinic_hwif *hwif = pf_to_mgmt->hwif; 556 struct pci_dev *pdev = hwif->pdev; 557 558 recv_msg->msg = devm_kzalloc(&pdev->dev, MAX_PF_MGMT_BUF_SIZE, 559 GFP_KERNEL); 560 if (!recv_msg->msg) 561 return -ENOMEM; 562 563 recv_msg->buf_out = devm_kzalloc(&pdev->dev, MAX_PF_MGMT_BUF_SIZE, 564 GFP_KERNEL); 565 if (!recv_msg->buf_out) 566 return -ENOMEM; 567 568 return 0; 569 } 570 571 /** 572 * alloc_msg_buf - allocate all the message buffers of PF to MGMT channel 573 * @pf_to_mgmt: PF to MGMT channel 574 * 575 * Return 0 - Success, negative - Failure 576 **/ 577 static int alloc_msg_buf(struct hinic_pf_to_mgmt *pf_to_mgmt) 578 { 579 struct hinic_hwif *hwif = pf_to_mgmt->hwif; 580 struct pci_dev *pdev = hwif->pdev; 581 int err; 582 583 err = alloc_recv_msg(pf_to_mgmt, 584 &pf_to_mgmt->recv_msg_from_mgmt); 585 if (err) { 586 dev_err(&pdev->dev, "Failed to allocate recv msg\n"); 587 return err; 588 } 589 590 err = alloc_recv_msg(pf_to_mgmt, 591 &pf_to_mgmt->recv_resp_msg_from_mgmt); 592 if (err) { 593 dev_err(&pdev->dev, "Failed to allocate resp recv msg\n"); 594 return err; 595 } 596 597 pf_to_mgmt->sync_msg_buf = devm_kzalloc(&pdev->dev, 598 MAX_PF_MGMT_BUF_SIZE, 599 GFP_KERNEL); 600 if (!pf_to_mgmt->sync_msg_buf) 601 return -ENOMEM; 602 603 pf_to_mgmt->mgmt_ack_buf = devm_kzalloc(&pdev->dev, 604 MAX_PF_MGMT_BUF_SIZE, 605 GFP_KERNEL); 606 if (!pf_to_mgmt->mgmt_ack_buf) 607 return -ENOMEM; 608 609 return 0; 610 } 611 612 /** 613 * hinic_pf_to_mgmt_init - initialize PF to MGMT channel 614 * @pf_to_mgmt: PF to MGMT channel 615 * @hwif: HW interface the PF to MGMT will use for accessing HW 616 * 617 * Return 0 - Success, negative - Failure 618 **/ 619 int hinic_pf_to_mgmt_init(struct hinic_pf_to_mgmt *pf_to_mgmt, 620 struct hinic_hwif *hwif) 621 { 622 struct hinic_pfhwdev *pfhwdev = mgmt_to_pfhwdev(pf_to_mgmt); 623 struct hinic_hwdev *hwdev = &pfhwdev->hwdev; 624 struct pci_dev *pdev = hwif->pdev; 625 int err; 626 627 pf_to_mgmt->hwif = hwif; 628 pf_to_mgmt->hwdev = hwdev; 629 630 if (HINIC_IS_VF(hwif)) 631 return 0; 632 633 err = hinic_health_reporters_create(hwdev->devlink_dev); 634 if (err) 635 return err; 636 637 sema_init(&pf_to_mgmt->sync_msg_lock, 1); 638 pf_to_mgmt->workq = create_singlethread_workqueue("hinic_mgmt"); 639 if (!pf_to_mgmt->workq) { 640 dev_err(&pdev->dev, "Failed to initialize MGMT workqueue\n"); 641 hinic_health_reporters_destroy(hwdev->devlink_dev); 642 return -ENOMEM; 643 } 644 pf_to_mgmt->sync_msg_id = 0; 645 646 err = alloc_msg_buf(pf_to_mgmt); 647 if (err) { 648 dev_err(&pdev->dev, "Failed to allocate msg buffers\n"); 649 hinic_health_reporters_destroy(hwdev->devlink_dev); 650 return err; 651 } 652 653 err = hinic_api_cmd_init(pf_to_mgmt->cmd_chain, hwif); 654 if (err) { 655 dev_err(&pdev->dev, "Failed to initialize cmd chains\n"); 656 hinic_health_reporters_destroy(hwdev->devlink_dev); 657 return err; 658 } 659 660 hinic_aeq_register_hw_cb(&hwdev->aeqs, HINIC_MSG_FROM_MGMT_CPU, 661 pf_to_mgmt, 662 mgmt_msg_aeqe_handler); 663 return 0; 664 } 665 666 /** 667 * hinic_pf_to_mgmt_free - free PF to MGMT channel 668 * @pf_to_mgmt: PF to MGMT channel 669 **/ 670 void hinic_pf_to_mgmt_free(struct hinic_pf_to_mgmt *pf_to_mgmt) 671 { 672 struct hinic_pfhwdev *pfhwdev = mgmt_to_pfhwdev(pf_to_mgmt); 673 struct hinic_hwdev *hwdev = &pfhwdev->hwdev; 674 675 if (HINIC_IS_VF(hwdev->hwif)) 676 return; 677 678 hinic_aeq_unregister_hw_cb(&hwdev->aeqs, HINIC_MSG_FROM_MGMT_CPU); 679 hinic_api_cmd_free(pf_to_mgmt->cmd_chain); 680 destroy_workqueue(pf_to_mgmt->workq); 681 hinic_health_reporters_destroy(hwdev->devlink_dev); 682 } 683