GNU Linux-libre 6.8.9-gnu
[releases.git] / drivers / net / ethernet / huawei / hinic / hinic_hw_mgmt.c
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  * @timeout: time-out period of waiting for response
242  *
243  * Return 0 - Success, negative - Failure
244  **/
245 static int msg_to_mgmt_sync(struct hinic_pf_to_mgmt *pf_to_mgmt,
246                             enum hinic_mod_type mod, u8 cmd,
247                             u8 *buf_in, u16 in_size,
248                             u8 *buf_out, u16 *out_size,
249                             enum mgmt_direction_type direction,
250                             u16 resp_msg_id, u32 timeout)
251 {
252         struct hinic_hwif *hwif = pf_to_mgmt->hwif;
253         struct pci_dev *pdev = hwif->pdev;
254         struct hinic_recv_msg *recv_msg;
255         struct completion *recv_done;
256         unsigned long timeo;
257         u16 msg_id;
258         int err;
259
260         /* Lock the sync_msg_buf */
261         down(&pf_to_mgmt->sync_msg_lock);
262
263         recv_msg = &pf_to_mgmt->recv_resp_msg_from_mgmt;
264         recv_done = &recv_msg->recv_done;
265
266         if (resp_msg_id == MSG_NOT_RESP)
267                 msg_id = SYNC_MSG_ID(pf_to_mgmt);
268         else
269                 msg_id = resp_msg_id;
270
271         init_completion(recv_done);
272
273         err = send_msg_to_mgmt(pf_to_mgmt, mod, cmd, buf_in, in_size,
274                                MSG_ACK, direction, resp_msg_id);
275         if (err) {
276                 dev_err(&pdev->dev, "Failed to send sync msg to mgmt\n");
277                 goto unlock_sync_msg;
278         }
279
280         timeo = msecs_to_jiffies(timeout ? timeout : MGMT_MSG_TIMEOUT);
281
282         if (!wait_for_completion_timeout(recv_done, timeo)) {
283                 dev_err(&pdev->dev, "MGMT timeout, MSG id = %d\n", msg_id);
284                 hinic_dump_aeq_info(pf_to_mgmt->hwdev);
285                 err = -ETIMEDOUT;
286                 goto unlock_sync_msg;
287         }
288
289         smp_rmb();      /* verify reading after completion */
290
291         if (recv_msg->msg_id != msg_id) {
292                 dev_err(&pdev->dev, "incorrect MSG for id = %d\n", msg_id);
293                 err = -EFAULT;
294                 goto unlock_sync_msg;
295         }
296
297         if (buf_out && recv_msg->msg_len <= MAX_PF_MGMT_BUF_SIZE) {
298                 memcpy(buf_out, recv_msg->msg, recv_msg->msg_len);
299                 *out_size = recv_msg->msg_len;
300         }
301
302 unlock_sync_msg:
303         up(&pf_to_mgmt->sync_msg_lock);
304         return err;
305 }
306
307 /**
308  * msg_to_mgmt_async - send message to mgmt without response
309  * @pf_to_mgmt: PF to MGMT channel
310  * @mod: module in the chip that will get the message
311  * @cmd: command of the message
312  * @buf_in: the msg data
313  * @in_size: the msg data length
314  * @direction: the direction of the original message
315  * @resp_msg_id: msg id to response for
316  *
317  * Return 0 - Success, negative - Failure
318  **/
319 static int msg_to_mgmt_async(struct hinic_pf_to_mgmt *pf_to_mgmt,
320                              enum hinic_mod_type mod, u8 cmd,
321                              u8 *buf_in, u16 in_size,
322                              enum mgmt_direction_type direction,
323                              u16 resp_msg_id)
324 {
325         int err;
326
327         /* Lock the sync_msg_buf */
328         down(&pf_to_mgmt->sync_msg_lock);
329
330         err = send_msg_to_mgmt(pf_to_mgmt, mod, cmd, buf_in, in_size,
331                                MSG_NO_ACK, direction, resp_msg_id);
332
333         up(&pf_to_mgmt->sync_msg_lock);
334         return err;
335 }
336
337 /**
338  * hinic_msg_to_mgmt - send message to mgmt
339  * @pf_to_mgmt: PF to MGMT channel
340  * @mod: module in the chip that will get the message
341  * @cmd: command of the message
342  * @buf_in: the msg data
343  * @in_size: the msg data length
344  * @buf_out: response
345  * @out_size: returned response length
346  * @sync: sync msg or async msg
347  *
348  * Return 0 - Success, negative - Failure
349  **/
350 int hinic_msg_to_mgmt(struct hinic_pf_to_mgmt *pf_to_mgmt,
351                       enum hinic_mod_type mod, u8 cmd,
352                       void *buf_in, u16 in_size, void *buf_out, u16 *out_size,
353                       enum hinic_mgmt_msg_type sync)
354 {
355         struct hinic_hwif *hwif = pf_to_mgmt->hwif;
356         struct pci_dev *pdev = hwif->pdev;
357         u32 timeout = 0;
358
359         if (sync != HINIC_MGMT_MSG_SYNC) {
360                 dev_err(&pdev->dev, "Invalid MGMT msg type\n");
361                 return -EINVAL;
362         }
363
364         if (!MSG_SZ_IS_VALID(in_size)) {
365                 dev_err(&pdev->dev, "Invalid MGMT msg buffer size\n");
366                 return -EINVAL;
367         }
368
369         if (HINIC_IS_VF(hwif)) {
370                 if (cmd == HINIC_PORT_CMD_SET_FUNC_STATE)
371                         timeout = SET_FUNC_PORT_MBOX_TIMEOUT;
372
373                 return hinic_mbox_to_pf(pf_to_mgmt->hwdev, mod, cmd, buf_in,
374                                         in_size, buf_out, out_size, timeout);
375         } else {
376                 if (cmd == HINIC_PORT_CMD_SET_FUNC_STATE)
377                         timeout = SET_FUNC_PORT_MGMT_TIMEOUT;
378                 else if (cmd == HINIC_PORT_CMD_UPDATE_FW)
379                         timeout = UPDATE_FW_MGMT_TIMEOUT;
380
381                 return msg_to_mgmt_sync(pf_to_mgmt, mod, cmd, buf_in, in_size,
382                                 buf_out, out_size, MGMT_DIRECT_SEND,
383                                 MSG_NOT_RESP, timeout);
384         }
385 }
386
387 static void recv_mgmt_msg_work_handler(struct work_struct *work)
388 {
389         struct hinic_mgmt_msg_handle_work *mgmt_work =
390                 container_of(work, struct hinic_mgmt_msg_handle_work, work);
391         struct hinic_pf_to_mgmt *pf_to_mgmt = mgmt_work->pf_to_mgmt;
392         struct pci_dev *pdev = pf_to_mgmt->hwif->pdev;
393         u8 *buf_out = pf_to_mgmt->mgmt_ack_buf;
394         struct hinic_mgmt_cb *mgmt_cb;
395         unsigned long cb_state;
396         u16 out_size = 0;
397
398         memset(buf_out, 0, MAX_PF_MGMT_BUF_SIZE);
399
400         if (mgmt_work->mod >= HINIC_MOD_MAX) {
401                 dev_err(&pdev->dev, "Unknown MGMT MSG module = %d\n",
402                         mgmt_work->mod);
403                 kfree(mgmt_work->msg);
404                 kfree(mgmt_work);
405                 return;
406         }
407
408         mgmt_cb = &pf_to_mgmt->mgmt_cb[mgmt_work->mod];
409
410         cb_state = cmpxchg(&mgmt_cb->state,
411                            HINIC_MGMT_CB_ENABLED,
412                            HINIC_MGMT_CB_ENABLED | HINIC_MGMT_CB_RUNNING);
413
414         if (cb_state == HINIC_MGMT_CB_ENABLED && mgmt_cb->cb)
415                 mgmt_cb->cb(mgmt_cb->handle, mgmt_work->cmd,
416                             mgmt_work->msg, mgmt_work->msg_len,
417                             buf_out, &out_size);
418         else
419                 dev_err(&pdev->dev, "No MGMT msg handler, mod: %d, cmd: %d\n",
420                         mgmt_work->mod, mgmt_work->cmd);
421
422         mgmt_cb->state &= ~HINIC_MGMT_CB_RUNNING;
423
424         if (!mgmt_work->async_mgmt_to_pf)
425                 /* MGMT sent sync msg, send the response */
426                 msg_to_mgmt_async(pf_to_mgmt, mgmt_work->mod, mgmt_work->cmd,
427                                   buf_out, out_size, MGMT_RESP,
428                                   mgmt_work->msg_id);
429
430         kfree(mgmt_work->msg);
431         kfree(mgmt_work);
432 }
433
434 /**
435  * mgmt_recv_msg_handler - handler for message from mgmt cpu
436  * @pf_to_mgmt: PF to MGMT channel
437  * @recv_msg: received message details
438  **/
439 static void mgmt_recv_msg_handler(struct hinic_pf_to_mgmt *pf_to_mgmt,
440                                   struct hinic_recv_msg *recv_msg)
441 {
442         struct hinic_mgmt_msg_handle_work *mgmt_work = NULL;
443
444         mgmt_work = kzalloc(sizeof(*mgmt_work), GFP_KERNEL);
445         if (!mgmt_work)
446                 return;
447
448         if (recv_msg->msg_len) {
449                 mgmt_work->msg = kzalloc(recv_msg->msg_len, GFP_KERNEL);
450                 if (!mgmt_work->msg) {
451                         kfree(mgmt_work);
452                         return;
453                 }
454         }
455
456         mgmt_work->pf_to_mgmt = pf_to_mgmt;
457         mgmt_work->msg_len = recv_msg->msg_len;
458         memcpy(mgmt_work->msg, recv_msg->msg, recv_msg->msg_len);
459         mgmt_work->msg_id = recv_msg->msg_id;
460         mgmt_work->mod = recv_msg->mod;
461         mgmt_work->cmd = recv_msg->cmd;
462         mgmt_work->async_mgmt_to_pf = recv_msg->async_mgmt_to_pf;
463
464         INIT_WORK(&mgmt_work->work, recv_mgmt_msg_work_handler);
465         queue_work(pf_to_mgmt->workq, &mgmt_work->work);
466 }
467
468 /**
469  * mgmt_resp_msg_handler - handler for a response message from mgmt cpu
470  * @pf_to_mgmt: PF to MGMT channel
471  * @recv_msg: received message details
472  **/
473 static void mgmt_resp_msg_handler(struct hinic_pf_to_mgmt *pf_to_mgmt,
474                                   struct hinic_recv_msg *recv_msg)
475 {
476         wmb();  /* verify writing all, before reading */
477
478         complete(&recv_msg->recv_done);
479 }
480
481 /**
482  * recv_mgmt_msg_handler - handler for a message from mgmt cpu
483  * @pf_to_mgmt: PF to MGMT channel
484  * @header: the header of the message
485  * @recv_msg: received message details
486  **/
487 static void recv_mgmt_msg_handler(struct hinic_pf_to_mgmt *pf_to_mgmt,
488                                   u64 *header, struct hinic_recv_msg *recv_msg)
489 {
490         struct hinic_hwif *hwif = pf_to_mgmt->hwif;
491         struct pci_dev *pdev = hwif->pdev;
492         int seq_id, seg_len;
493         u8 *msg_body;
494
495         seq_id = HINIC_MSG_HEADER_GET(*header, SEQID);
496         seg_len = HINIC_MSG_HEADER_GET(*header, SEG_LEN);
497
498         if (seq_id >= (MAX_MSG_LEN / SEGMENT_LEN)) {
499                 dev_err(&pdev->dev, "recv big mgmt msg\n");
500                 return;
501         }
502
503         msg_body = (u8 *)header + sizeof(*header);
504         memcpy(recv_msg->msg + seq_id * SEGMENT_LEN, msg_body, seg_len);
505
506         if (!HINIC_MSG_HEADER_GET(*header, LAST))
507                 return;
508
509         recv_msg->cmd = HINIC_MSG_HEADER_GET(*header, CMD);
510         recv_msg->mod = HINIC_MSG_HEADER_GET(*header, MODULE);
511         recv_msg->async_mgmt_to_pf = HINIC_MSG_HEADER_GET(*header,
512                                                           ASYNC_MGMT_TO_PF);
513         recv_msg->msg_len = HINIC_MSG_HEADER_GET(*header, MSG_LEN);
514         recv_msg->msg_id = HINIC_MSG_HEADER_GET(*header, MSG_ID);
515
516         if (HINIC_MSG_HEADER_GET(*header, DIRECTION) == MGMT_RESP)
517                 mgmt_resp_msg_handler(pf_to_mgmt, recv_msg);
518         else
519                 mgmt_recv_msg_handler(pf_to_mgmt, recv_msg);
520 }
521
522 /**
523  * mgmt_msg_aeqe_handler - handler for a mgmt message event
524  * @handle: PF to MGMT channel
525  * @data: the header of the message
526  * @size: unused
527  **/
528 static void mgmt_msg_aeqe_handler(void *handle, void *data, u8 size)
529 {
530         struct hinic_pf_to_mgmt *pf_to_mgmt = handle;
531         struct hinic_recv_msg *recv_msg;
532         u64 *header = (u64 *)data;
533
534         recv_msg = HINIC_MSG_HEADER_GET(*header, DIRECTION) ==
535                    MGMT_DIRECT_SEND ?
536                    &pf_to_mgmt->recv_msg_from_mgmt :
537                    &pf_to_mgmt->recv_resp_msg_from_mgmt;
538
539         recv_mgmt_msg_handler(pf_to_mgmt, header, recv_msg);
540 }
541
542 /**
543  * alloc_recv_msg - allocate receive message memory
544  * @pf_to_mgmt: PF to MGMT channel
545  * @recv_msg: pointer that will hold the allocated data
546  *
547  * Return 0 - Success, negative - Failure
548  **/
549 static int alloc_recv_msg(struct hinic_pf_to_mgmt *pf_to_mgmt,
550                           struct hinic_recv_msg *recv_msg)
551 {
552         struct hinic_hwif *hwif = pf_to_mgmt->hwif;
553         struct pci_dev *pdev = hwif->pdev;
554
555         recv_msg->msg = devm_kzalloc(&pdev->dev, MAX_PF_MGMT_BUF_SIZE,
556                                      GFP_KERNEL);
557         if (!recv_msg->msg)
558                 return -ENOMEM;
559
560         recv_msg->buf_out = devm_kzalloc(&pdev->dev, MAX_PF_MGMT_BUF_SIZE,
561                                          GFP_KERNEL);
562         if (!recv_msg->buf_out)
563                 return -ENOMEM;
564
565         return 0;
566 }
567
568 /**
569  * alloc_msg_buf - allocate all the message buffers of PF to MGMT channel
570  * @pf_to_mgmt: PF to MGMT channel
571  *
572  * Return 0 - Success, negative - Failure
573  **/
574 static int alloc_msg_buf(struct hinic_pf_to_mgmt *pf_to_mgmt)
575 {
576         struct hinic_hwif *hwif = pf_to_mgmt->hwif;
577         struct pci_dev *pdev = hwif->pdev;
578         int err;
579
580         err = alloc_recv_msg(pf_to_mgmt,
581                              &pf_to_mgmt->recv_msg_from_mgmt);
582         if (err) {
583                 dev_err(&pdev->dev, "Failed to allocate recv msg\n");
584                 return err;
585         }
586
587         err = alloc_recv_msg(pf_to_mgmt,
588                              &pf_to_mgmt->recv_resp_msg_from_mgmt);
589         if (err) {
590                 dev_err(&pdev->dev, "Failed to allocate resp recv msg\n");
591                 return err;
592         }
593
594         pf_to_mgmt->sync_msg_buf = devm_kzalloc(&pdev->dev,
595                                                 MAX_PF_MGMT_BUF_SIZE,
596                                                 GFP_KERNEL);
597         if (!pf_to_mgmt->sync_msg_buf)
598                 return -ENOMEM;
599
600         pf_to_mgmt->mgmt_ack_buf = devm_kzalloc(&pdev->dev,
601                                                 MAX_PF_MGMT_BUF_SIZE,
602                                                 GFP_KERNEL);
603         if (!pf_to_mgmt->mgmt_ack_buf)
604                 return -ENOMEM;
605
606         return 0;
607 }
608
609 /**
610  * hinic_pf_to_mgmt_init - initialize PF to MGMT channel
611  * @pf_to_mgmt: PF to MGMT channel
612  * @hwif: HW interface the PF to MGMT will use for accessing HW
613  *
614  * Return 0 - Success, negative - Failure
615  **/
616 int hinic_pf_to_mgmt_init(struct hinic_pf_to_mgmt *pf_to_mgmt,
617                           struct hinic_hwif *hwif)
618 {
619         struct hinic_pfhwdev *pfhwdev = mgmt_to_pfhwdev(pf_to_mgmt);
620         struct hinic_hwdev *hwdev = &pfhwdev->hwdev;
621         struct pci_dev *pdev = hwif->pdev;
622         int err;
623
624         pf_to_mgmt->hwif = hwif;
625         pf_to_mgmt->hwdev = hwdev;
626
627         if (HINIC_IS_VF(hwif))
628                 return 0;
629
630         err = hinic_health_reporters_create(hwdev->devlink_dev);
631         if (err)
632                 return err;
633
634         sema_init(&pf_to_mgmt->sync_msg_lock, 1);
635         pf_to_mgmt->workq = create_singlethread_workqueue("hinic_mgmt");
636         if (!pf_to_mgmt->workq) {
637                 dev_err(&pdev->dev, "Failed to initialize MGMT workqueue\n");
638                 hinic_health_reporters_destroy(hwdev->devlink_dev);
639                 return -ENOMEM;
640         }
641         pf_to_mgmt->sync_msg_id = 0;
642
643         err = alloc_msg_buf(pf_to_mgmt);
644         if (err) {
645                 dev_err(&pdev->dev, "Failed to allocate msg buffers\n");
646                 destroy_workqueue(pf_to_mgmt->workq);
647                 hinic_health_reporters_destroy(hwdev->devlink_dev);
648                 return err;
649         }
650
651         err = hinic_api_cmd_init(pf_to_mgmt->cmd_chain, hwif);
652         if (err) {
653                 dev_err(&pdev->dev, "Failed to initialize cmd chains\n");
654                 destroy_workqueue(pf_to_mgmt->workq);
655                 hinic_health_reporters_destroy(hwdev->devlink_dev);
656                 return err;
657         }
658
659         hinic_aeq_register_hw_cb(&hwdev->aeqs, HINIC_MSG_FROM_MGMT_CPU,
660                                  pf_to_mgmt,
661                                  mgmt_msg_aeqe_handler);
662         return 0;
663 }
664
665 /**
666  * hinic_pf_to_mgmt_free - free PF to MGMT channel
667  * @pf_to_mgmt: PF to MGMT channel
668  **/
669 void hinic_pf_to_mgmt_free(struct hinic_pf_to_mgmt *pf_to_mgmt)
670 {
671         struct hinic_pfhwdev *pfhwdev = mgmt_to_pfhwdev(pf_to_mgmt);
672         struct hinic_hwdev *hwdev = &pfhwdev->hwdev;
673
674         if (HINIC_IS_VF(hwdev->hwif))
675                 return;
676
677         hinic_aeq_unregister_hw_cb(&hwdev->aeqs, HINIC_MSG_FROM_MGMT_CPU);
678         hinic_api_cmd_free(pf_to_mgmt->cmd_chain);
679         destroy_workqueue(pf_to_mgmt->workq);
680         hinic_health_reporters_destroy(hwdev->devlink_dev);
681 }