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