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