root/drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. hinic_register_mgmt_msg_cb
  2. hinic_unregister_mgmt_msg_cb
  3. prepare_header
  4. prepare_mgmt_cmd
  5. mgmt_msg_len
  6. send_msg_to_mgmt
  7. msg_to_mgmt_sync
  8. msg_to_mgmt_async
  9. hinic_msg_to_mgmt
  10. mgmt_recv_msg_handler
  11. mgmt_resp_msg_handler
  12. recv_mgmt_msg_handler
  13. mgmt_msg_aeqe_handler
  14. alloc_recv_msg
  15. alloc_msg_buf
  16. hinic_pf_to_mgmt_init
  17. hinic_pf_to_mgmt_free

   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         return msg_to_mgmt_sync(pf_to_mgmt, mod, cmd, buf_in, in_size,
 365                                 buf_out, out_size, MGMT_DIRECT_SEND,
 366                                 MSG_NOT_RESP, timeout);
 367 }
 368 
 369 /**
 370  * mgmt_recv_msg_handler - handler for message from mgmt cpu
 371  * @pf_to_mgmt: PF to MGMT channel
 372  * @recv_msg: received message details
 373  **/
 374 static void mgmt_recv_msg_handler(struct hinic_pf_to_mgmt *pf_to_mgmt,
 375                                   struct hinic_recv_msg *recv_msg)
 376 {
 377         struct hinic_hwif *hwif = pf_to_mgmt->hwif;
 378         struct pci_dev *pdev = hwif->pdev;
 379         u8 *buf_out = recv_msg->buf_out;
 380         struct hinic_mgmt_cb *mgmt_cb;
 381         unsigned long cb_state;
 382         u16 out_size = 0;
 383 
 384         if (recv_msg->mod >= HINIC_MOD_MAX) {
 385                 dev_err(&pdev->dev, "Unknown MGMT MSG module = %d\n",
 386                         recv_msg->mod);
 387                 return;
 388         }
 389 
 390         mgmt_cb = &pf_to_mgmt->mgmt_cb[recv_msg->mod];
 391 
 392         cb_state = cmpxchg(&mgmt_cb->state,
 393                            HINIC_MGMT_CB_ENABLED,
 394                            HINIC_MGMT_CB_ENABLED | HINIC_MGMT_CB_RUNNING);
 395 
 396         if ((cb_state == HINIC_MGMT_CB_ENABLED) && (mgmt_cb->cb))
 397                 mgmt_cb->cb(mgmt_cb->handle, recv_msg->cmd,
 398                             recv_msg->msg, recv_msg->msg_len,
 399                             buf_out, &out_size);
 400         else
 401                 dev_err(&pdev->dev, "No MGMT msg handler, mod = %d\n",
 402                         recv_msg->mod);
 403 
 404         mgmt_cb->state &= ~HINIC_MGMT_CB_RUNNING;
 405 
 406         if (!recv_msg->async_mgmt_to_pf)
 407                 /* MGMT sent sync msg, send the response */
 408                 msg_to_mgmt_async(pf_to_mgmt, recv_msg->mod, recv_msg->cmd,
 409                                   buf_out, out_size, MGMT_RESP,
 410                                   recv_msg->msg_id);
 411 }
 412 
 413 /**
 414  * mgmt_resp_msg_handler - handler for a response message from mgmt cpu
 415  * @pf_to_mgmt: PF to MGMT channel
 416  * @recv_msg: received message details
 417  **/
 418 static void mgmt_resp_msg_handler(struct hinic_pf_to_mgmt *pf_to_mgmt,
 419                                   struct hinic_recv_msg *recv_msg)
 420 {
 421         wmb();  /* verify writing all, before reading */
 422 
 423         complete(&recv_msg->recv_done);
 424 }
 425 
 426 /**
 427  * recv_mgmt_msg_handler - handler for a message from mgmt cpu
 428  * @pf_to_mgmt: PF to MGMT channel
 429  * @header: the header of the message
 430  * @recv_msg: received message details
 431  **/
 432 static void recv_mgmt_msg_handler(struct hinic_pf_to_mgmt *pf_to_mgmt,
 433                                   u64 *header, struct hinic_recv_msg *recv_msg)
 434 {
 435         struct hinic_hwif *hwif = pf_to_mgmt->hwif;
 436         struct pci_dev *pdev = hwif->pdev;
 437         int seq_id, seg_len;
 438         u8 *msg_body;
 439 
 440         seq_id = HINIC_MSG_HEADER_GET(*header, SEQID);
 441         seg_len = HINIC_MSG_HEADER_GET(*header, SEG_LEN);
 442 
 443         if (seq_id >= (MAX_MSG_LEN / SEGMENT_LEN)) {
 444                 dev_err(&pdev->dev, "recv big mgmt msg\n");
 445                 return;
 446         }
 447 
 448         msg_body = (u8 *)header + sizeof(*header);
 449         memcpy(recv_msg->msg + seq_id * SEGMENT_LEN, msg_body, seg_len);
 450 
 451         if (!HINIC_MSG_HEADER_GET(*header, LAST))
 452                 return;
 453 
 454         recv_msg->cmd = HINIC_MSG_HEADER_GET(*header, CMD);
 455         recv_msg->mod = HINIC_MSG_HEADER_GET(*header, MODULE);
 456         recv_msg->async_mgmt_to_pf = HINIC_MSG_HEADER_GET(*header,
 457                                                           ASYNC_MGMT_TO_PF);
 458         recv_msg->msg_len = HINIC_MSG_HEADER_GET(*header, MSG_LEN);
 459         recv_msg->msg_id = HINIC_MSG_HEADER_GET(*header, MSG_ID);
 460 
 461         if (HINIC_MSG_HEADER_GET(*header, DIRECTION) == MGMT_RESP)
 462                 mgmt_resp_msg_handler(pf_to_mgmt, recv_msg);
 463         else
 464                 mgmt_recv_msg_handler(pf_to_mgmt, recv_msg);
 465 }
 466 
 467 /**
 468  * mgmt_msg_aeqe_handler - handler for a mgmt message event
 469  * @handle: PF to MGMT channel
 470  * @data: the header of the message
 471  * @size: unused
 472  **/
 473 static void mgmt_msg_aeqe_handler(void *handle, void *data, u8 size)
 474 {
 475         struct hinic_pf_to_mgmt *pf_to_mgmt = handle;
 476         struct hinic_recv_msg *recv_msg;
 477         u64 *header = (u64 *)data;
 478 
 479         recv_msg = HINIC_MSG_HEADER_GET(*header, DIRECTION) ==
 480                    MGMT_DIRECT_SEND ?
 481                    &pf_to_mgmt->recv_msg_from_mgmt :
 482                    &pf_to_mgmt->recv_resp_msg_from_mgmt;
 483 
 484         recv_mgmt_msg_handler(pf_to_mgmt, header, recv_msg);
 485 }
 486 
 487 /**
 488  * alloc_recv_msg - allocate receive message memory
 489  * @pf_to_mgmt: PF to MGMT channel
 490  * @recv_msg: pointer that will hold the allocated data
 491  *
 492  * Return 0 - Success, negative - Failure
 493  **/
 494 static int alloc_recv_msg(struct hinic_pf_to_mgmt *pf_to_mgmt,
 495                           struct hinic_recv_msg *recv_msg)
 496 {
 497         struct hinic_hwif *hwif = pf_to_mgmt->hwif;
 498         struct pci_dev *pdev = hwif->pdev;
 499 
 500         recv_msg->msg = devm_kzalloc(&pdev->dev, MAX_PF_MGMT_BUF_SIZE,
 501                                      GFP_KERNEL);
 502         if (!recv_msg->msg)
 503                 return -ENOMEM;
 504 
 505         recv_msg->buf_out = devm_kzalloc(&pdev->dev, MAX_PF_MGMT_BUF_SIZE,
 506                                          GFP_KERNEL);
 507         if (!recv_msg->buf_out)
 508                 return -ENOMEM;
 509 
 510         return 0;
 511 }
 512 
 513 /**
 514  * alloc_msg_buf - allocate all the message buffers of PF to MGMT channel
 515  * @pf_to_mgmt: PF to MGMT channel
 516  *
 517  * Return 0 - Success, negative - Failure
 518  **/
 519 static int alloc_msg_buf(struct hinic_pf_to_mgmt *pf_to_mgmt)
 520 {
 521         struct hinic_hwif *hwif = pf_to_mgmt->hwif;
 522         struct pci_dev *pdev = hwif->pdev;
 523         int err;
 524 
 525         err = alloc_recv_msg(pf_to_mgmt,
 526                              &pf_to_mgmt->recv_msg_from_mgmt);
 527         if (err) {
 528                 dev_err(&pdev->dev, "Failed to allocate recv msg\n");
 529                 return err;
 530         }
 531 
 532         err = alloc_recv_msg(pf_to_mgmt,
 533                              &pf_to_mgmt->recv_resp_msg_from_mgmt);
 534         if (err) {
 535                 dev_err(&pdev->dev, "Failed to allocate resp recv msg\n");
 536                 return err;
 537         }
 538 
 539         pf_to_mgmt->sync_msg_buf = devm_kzalloc(&pdev->dev,
 540                                                 MAX_PF_MGMT_BUF_SIZE,
 541                                                 GFP_KERNEL);
 542         if (!pf_to_mgmt->sync_msg_buf)
 543                 return -ENOMEM;
 544 
 545         return 0;
 546 }
 547 
 548 /**
 549  * hinic_pf_to_mgmt_init - initialize PF to MGMT channel
 550  * @pf_to_mgmt: PF to MGMT channel
 551  * @hwif: HW interface the PF to MGMT will use for accessing HW
 552  *
 553  * Return 0 - Success, negative - Failure
 554  **/
 555 int hinic_pf_to_mgmt_init(struct hinic_pf_to_mgmt *pf_to_mgmt,
 556                           struct hinic_hwif *hwif)
 557 {
 558         struct hinic_pfhwdev *pfhwdev = mgmt_to_pfhwdev(pf_to_mgmt);
 559         struct hinic_hwdev *hwdev = &pfhwdev->hwdev;
 560         struct pci_dev *pdev = hwif->pdev;
 561         int err;
 562 
 563         pf_to_mgmt->hwif = hwif;
 564 
 565         sema_init(&pf_to_mgmt->sync_msg_lock, 1);
 566         pf_to_mgmt->sync_msg_id = 0;
 567 
 568         err = alloc_msg_buf(pf_to_mgmt);
 569         if (err) {
 570                 dev_err(&pdev->dev, "Failed to allocate msg buffers\n");
 571                 return err;
 572         }
 573 
 574         err = hinic_api_cmd_init(pf_to_mgmt->cmd_chain, hwif);
 575         if (err) {
 576                 dev_err(&pdev->dev, "Failed to initialize cmd chains\n");
 577                 return err;
 578         }
 579 
 580         hinic_aeq_register_hw_cb(&hwdev->aeqs, HINIC_MSG_FROM_MGMT_CPU,
 581                                  pf_to_mgmt,
 582                                  mgmt_msg_aeqe_handler);
 583         return 0;
 584 }
 585 
 586 /**
 587  * hinic_pf_to_mgmt_free - free PF to MGMT channel
 588  * @pf_to_mgmt: PF to MGMT channel
 589  **/
 590 void hinic_pf_to_mgmt_free(struct hinic_pf_to_mgmt *pf_to_mgmt)
 591 {
 592         struct hinic_pfhwdev *pfhwdev = mgmt_to_pfhwdev(pf_to_mgmt);
 593         struct hinic_hwdev *hwdev = &pfhwdev->hwdev;
 594 
 595         hinic_aeq_unregister_hw_cb(&hwdev->aeqs, HINIC_MSG_FROM_MGMT_CPU);
 596         hinic_api_cmd_free(pf_to_mgmt->cmd_chain);
 597 }

/* [<][>][^][v][top][bottom][index][help] */