OSDN Git Service

Linux 6.6-rc1
[tomoyo/tomoyo-test1.git] / drivers / net / ethernet / huawei / hinic / hinic_hw_dev.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/pci.h>
10 #include <linux/device.h>
11 #include <linux/errno.h>
12 #include <linux/slab.h>
13 #include <linux/bitops.h>
14 #include <linux/delay.h>
15 #include <linux/jiffies.h>
16 #include <linux/log2.h>
17 #include <linux/err.h>
18 #include <linux/netdevice.h>
19 #include <net/devlink.h>
20
21 #include "hinic_devlink.h"
22 #include "hinic_sriov.h"
23 #include "hinic_dev.h"
24 #include "hinic_hw_if.h"
25 #include "hinic_hw_eqs.h"
26 #include "hinic_hw_mgmt.h"
27 #include "hinic_hw_qp_ctxt.h"
28 #include "hinic_hw_qp.h"
29 #include "hinic_hw_io.h"
30 #include "hinic_hw_dev.h"
31
32 #define OUTBOUND_STATE_TIMEOUT          100
33 #define DB_STATE_TIMEOUT                100
34
35 #define MAX_IRQS(max_qps, num_aeqs, num_ceqs)   \
36                  (2 * (max_qps) + (num_aeqs) + (num_ceqs))
37
38 #define ADDR_IN_4BYTES(addr)            ((addr) >> 2)
39
40 enum intr_type {
41         INTR_MSIX_TYPE,
42 };
43
44 /**
45  * parse_capability - convert device capabilities to NIC capabilities
46  * @hwdev: the HW device to set and convert device capabilities for
47  * @dev_cap: device capabilities from FW
48  *
49  * Return 0 - Success, negative - Failure
50  **/
51 static int parse_capability(struct hinic_hwdev *hwdev,
52                             struct hinic_dev_cap *dev_cap)
53 {
54         struct hinic_cap *nic_cap = &hwdev->nic_cap;
55         int num_aeqs, num_ceqs, num_irqs;
56
57         if (!HINIC_IS_VF(hwdev->hwif) && dev_cap->intr_type != INTR_MSIX_TYPE)
58                 return -EFAULT;
59
60         num_aeqs = HINIC_HWIF_NUM_AEQS(hwdev->hwif);
61         num_ceqs = HINIC_HWIF_NUM_CEQS(hwdev->hwif);
62         num_irqs = HINIC_HWIF_NUM_IRQS(hwdev->hwif);
63
64         /* Each QP has its own (SQ + RQ) interrupts */
65         nic_cap->num_qps = (num_irqs - (num_aeqs + num_ceqs)) / 2;
66
67         if (nic_cap->num_qps > HINIC_Q_CTXT_MAX)
68                 nic_cap->num_qps = HINIC_Q_CTXT_MAX;
69
70         if (!HINIC_IS_VF(hwdev->hwif))
71                 nic_cap->max_qps = dev_cap->max_sqs + 1;
72         else
73                 nic_cap->max_qps = dev_cap->max_sqs;
74
75         if (nic_cap->num_qps > nic_cap->max_qps)
76                 nic_cap->num_qps = nic_cap->max_qps;
77
78         if (!HINIC_IS_VF(hwdev->hwif)) {
79                 nic_cap->max_vf = dev_cap->max_vf;
80                 nic_cap->max_vf_qps = dev_cap->max_vf_sqs + 1;
81         }
82
83         hwdev->port_id = dev_cap->port_id;
84
85         return 0;
86 }
87
88 /**
89  * get_capability - get device capabilities from FW
90  * @pfhwdev: the PF HW device to get capabilities for
91  *
92  * Return 0 - Success, negative - Failure
93  **/
94 static int get_capability(struct hinic_pfhwdev *pfhwdev)
95 {
96         struct hinic_hwdev *hwdev = &pfhwdev->hwdev;
97         struct hinic_hwif *hwif = hwdev->hwif;
98         struct pci_dev *pdev = hwif->pdev;
99         struct hinic_dev_cap dev_cap;
100         u16 out_len;
101         int err;
102
103         out_len = sizeof(dev_cap);
104
105         err = hinic_msg_to_mgmt(&pfhwdev->pf_to_mgmt, HINIC_MOD_CFGM,
106                                 HINIC_CFG_NIC_CAP, &dev_cap, sizeof(dev_cap),
107                                 &dev_cap, &out_len, HINIC_MGMT_MSG_SYNC);
108         if (err) {
109                 dev_err(&pdev->dev, "Failed to get capability from FW\n");
110                 return err;
111         }
112
113         return parse_capability(hwdev, &dev_cap);
114 }
115
116 /**
117  * get_dev_cap - get device capabilities
118  * @hwdev: the NIC HW device to get capabilities for
119  *
120  * Return 0 - Success, negative - Failure
121  **/
122 static int get_dev_cap(struct hinic_hwdev *hwdev)
123 {
124         struct hinic_hwif *hwif = hwdev->hwif;
125         struct pci_dev *pdev = hwif->pdev;
126         struct hinic_pfhwdev *pfhwdev;
127         int err;
128
129         switch (HINIC_FUNC_TYPE(hwif)) {
130         case HINIC_PPF:
131         case HINIC_PF:
132         case HINIC_VF:
133                 pfhwdev = container_of(hwdev, struct hinic_pfhwdev, hwdev);
134                 err = get_capability(pfhwdev);
135                 if (err) {
136                         dev_err(&pdev->dev, "Failed to get capability\n");
137                         return err;
138                 }
139                 break;
140         default:
141                 dev_err(&pdev->dev, "Unsupported PCI Function type\n");
142                 return -EINVAL;
143         }
144
145         return 0;
146 }
147
148 /**
149  * init_msix - enable the msix and save the entries
150  * @hwdev: the NIC HW device
151  *
152  * Return 0 - Success, negative - Failure
153  **/
154 static int init_msix(struct hinic_hwdev *hwdev)
155 {
156         struct hinic_hwif *hwif = hwdev->hwif;
157         struct pci_dev *pdev = hwif->pdev;
158         int nr_irqs, num_aeqs, num_ceqs;
159         int i, err;
160
161         num_aeqs = HINIC_HWIF_NUM_AEQS(hwif);
162         num_ceqs = HINIC_HWIF_NUM_CEQS(hwif);
163         nr_irqs = MAX_IRQS(HINIC_MAX_QPS, num_aeqs, num_ceqs);
164         if (nr_irqs > HINIC_HWIF_NUM_IRQS(hwif))
165                 nr_irqs = HINIC_HWIF_NUM_IRQS(hwif);
166
167         hwdev->msix_entries = devm_kcalloc(&pdev->dev, nr_irqs,
168                                            sizeof(*hwdev->msix_entries),
169                                            GFP_KERNEL);
170         if (!hwdev->msix_entries)
171                 return -ENOMEM;
172
173         for (i = 0; i < nr_irqs; i++)
174                 hwdev->msix_entries[i].entry = i;
175
176         err = pci_enable_msix_exact(pdev, hwdev->msix_entries, nr_irqs);
177         if (err) {
178                 dev_err(&pdev->dev, "Failed to enable pci msix\n");
179                 return err;
180         }
181
182         return 0;
183 }
184
185 /**
186  * disable_msix - disable the msix
187  * @hwdev: the NIC HW device
188  **/
189 static void disable_msix(struct hinic_hwdev *hwdev)
190 {
191         struct hinic_hwif *hwif = hwdev->hwif;
192         struct pci_dev *pdev = hwif->pdev;
193
194         pci_disable_msix(pdev);
195 }
196
197 /**
198  * hinic_port_msg_cmd - send port msg to mgmt
199  * @hwdev: the NIC HW device
200  * @cmd: the port command
201  * @buf_in: input buffer
202  * @in_size: input size
203  * @buf_out: output buffer
204  * @out_size: returned output size
205  *
206  * Return 0 - Success, negative - Failure
207  **/
208 int hinic_port_msg_cmd(struct hinic_hwdev *hwdev, enum hinic_port_cmd cmd,
209                        void *buf_in, u16 in_size, void *buf_out, u16 *out_size)
210 {
211         struct hinic_pfhwdev *pfhwdev;
212
213         pfhwdev = container_of(hwdev, struct hinic_pfhwdev, hwdev);
214
215         return hinic_msg_to_mgmt(&pfhwdev->pf_to_mgmt, HINIC_MOD_L2NIC, cmd,
216                                  buf_in, in_size, buf_out, out_size,
217                                  HINIC_MGMT_MSG_SYNC);
218 }
219
220 int hinic_hilink_msg_cmd(struct hinic_hwdev *hwdev, enum hinic_hilink_cmd cmd,
221                          void *buf_in, u16 in_size, void *buf_out,
222                          u16 *out_size)
223 {
224         struct hinic_pfhwdev *pfhwdev;
225
226         pfhwdev = container_of(hwdev, struct hinic_pfhwdev, hwdev);
227
228         return hinic_msg_to_mgmt(&pfhwdev->pf_to_mgmt, HINIC_MOD_HILINK, cmd,
229                                  buf_in, in_size, buf_out, out_size,
230                                  HINIC_MGMT_MSG_SYNC);
231 }
232
233 /**
234  * init_fw_ctxt- Init Firmware tables before network mgmt and io operations
235  * @hwdev: the NIC HW device
236  *
237  * Return 0 - Success, negative - Failure
238  **/
239 static int init_fw_ctxt(struct hinic_hwdev *hwdev)
240 {
241         struct hinic_hwif *hwif = hwdev->hwif;
242         struct pci_dev *pdev = hwif->pdev;
243         struct hinic_cmd_fw_ctxt fw_ctxt;
244         u16 out_size = sizeof(fw_ctxt);
245         int err;
246
247         fw_ctxt.func_idx = HINIC_HWIF_FUNC_IDX(hwif);
248         fw_ctxt.rx_buf_sz = HINIC_RX_BUF_SZ;
249
250         err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_FWCTXT_INIT,
251                                  &fw_ctxt, sizeof(fw_ctxt),
252                                  &fw_ctxt, &out_size);
253         if (err || out_size != sizeof(fw_ctxt) || fw_ctxt.status) {
254                 dev_err(&pdev->dev, "Failed to init FW ctxt, err: %d, status: 0x%x, out size: 0x%x\n",
255                         err, fw_ctxt.status, out_size);
256                 return -EIO;
257         }
258
259         return 0;
260 }
261
262 /**
263  * set_hw_ioctxt - set the shape of the IO queues in FW
264  * @hwdev: the NIC HW device
265  * @rq_depth: rq depth
266  * @sq_depth: sq depth
267  *
268  * Return 0 - Success, negative - Failure
269  **/
270 static int set_hw_ioctxt(struct hinic_hwdev *hwdev, unsigned int sq_depth,
271                          unsigned int rq_depth)
272 {
273         struct hinic_hwif *hwif = hwdev->hwif;
274         struct hinic_cmd_hw_ioctxt hw_ioctxt;
275         struct hinic_pfhwdev *pfhwdev;
276
277         hw_ioctxt.func_idx = HINIC_HWIF_FUNC_IDX(hwif);
278         hw_ioctxt.ppf_idx = HINIC_HWIF_PPF_IDX(hwif);
279
280         hw_ioctxt.set_cmdq_depth = HW_IOCTXT_SET_CMDQ_DEPTH_DEFAULT;
281         hw_ioctxt.cmdq_depth = 0;
282
283         hw_ioctxt.lro_en = 1;
284
285         hw_ioctxt.rq_depth  = ilog2(rq_depth);
286
287         hw_ioctxt.rx_buf_sz_idx = HINIC_RX_BUF_SZ_IDX;
288
289         hw_ioctxt.sq_depth  = ilog2(sq_depth);
290
291         pfhwdev = container_of(hwdev, struct hinic_pfhwdev, hwdev);
292
293         return hinic_msg_to_mgmt(&pfhwdev->pf_to_mgmt, HINIC_MOD_COMM,
294                                  HINIC_COMM_CMD_HWCTXT_SET,
295                                  &hw_ioctxt, sizeof(hw_ioctxt), NULL,
296                                  NULL, HINIC_MGMT_MSG_SYNC);
297 }
298
299 static int wait_for_outbound_state(struct hinic_hwdev *hwdev)
300 {
301         enum hinic_outbound_state outbound_state;
302         struct hinic_hwif *hwif = hwdev->hwif;
303         struct pci_dev *pdev = hwif->pdev;
304         unsigned long end;
305
306         end = jiffies + msecs_to_jiffies(OUTBOUND_STATE_TIMEOUT);
307         do {
308                 outbound_state = hinic_outbound_state_get(hwif);
309
310                 if (outbound_state == HINIC_OUTBOUND_ENABLE)
311                         return 0;
312
313                 msleep(20);
314         } while (time_before(jiffies, end));
315
316         dev_err(&pdev->dev, "Wait for OUTBOUND - Timeout\n");
317         return -EFAULT;
318 }
319
320 static int wait_for_db_state(struct hinic_hwdev *hwdev)
321 {
322         struct hinic_hwif *hwif = hwdev->hwif;
323         struct pci_dev *pdev = hwif->pdev;
324         enum hinic_db_state db_state;
325         unsigned long end;
326
327         end = jiffies + msecs_to_jiffies(DB_STATE_TIMEOUT);
328         do {
329                 db_state = hinic_db_state_get(hwif);
330
331                 if (db_state == HINIC_DB_ENABLE)
332                         return 0;
333
334                 msleep(20);
335         } while (time_before(jiffies, end));
336
337         dev_err(&pdev->dev, "Wait for DB - Timeout\n");
338         return -EFAULT;
339 }
340
341 /**
342  * clear_io_resources - set the IO resources as not active in the NIC
343  * @hwdev: the NIC HW device
344  *
345  * Return 0 - Success, negative - Failure
346  **/
347 static int clear_io_resources(struct hinic_hwdev *hwdev)
348 {
349         struct hinic_cmd_clear_io_res cmd_clear_io_res;
350         struct hinic_hwif *hwif = hwdev->hwif;
351         struct pci_dev *pdev = hwif->pdev;
352         struct hinic_pfhwdev *pfhwdev;
353         int err;
354
355         /* sleep 100ms to wait for firmware stopping I/O */
356         msleep(100);
357
358         cmd_clear_io_res.func_idx = HINIC_HWIF_FUNC_IDX(hwif);
359
360         pfhwdev = container_of(hwdev, struct hinic_pfhwdev, hwdev);
361
362         err = hinic_msg_to_mgmt(&pfhwdev->pf_to_mgmt, HINIC_MOD_COMM,
363                                 HINIC_COMM_CMD_IO_RES_CLEAR, &cmd_clear_io_res,
364                                 sizeof(cmd_clear_io_res), NULL, NULL,
365                                 HINIC_MGMT_MSG_SYNC);
366         if (err) {
367                 dev_err(&pdev->dev, "Failed to clear IO resources\n");
368                 return err;
369         }
370
371         return 0;
372 }
373
374 /**
375  * set_resources_state - set the state of the resources in the NIC
376  * @hwdev: the NIC HW device
377  * @state: the state to set
378  *
379  * Return 0 - Success, negative - Failure
380  **/
381 static int set_resources_state(struct hinic_hwdev *hwdev,
382                                enum hinic_res_state state)
383 {
384         struct hinic_cmd_set_res_state res_state;
385         struct hinic_hwif *hwif = hwdev->hwif;
386         struct hinic_pfhwdev *pfhwdev;
387
388         res_state.func_idx = HINIC_HWIF_FUNC_IDX(hwif);
389         res_state.state = state;
390
391         pfhwdev = container_of(hwdev, struct hinic_pfhwdev, hwdev);
392
393         return hinic_msg_to_mgmt(&pfhwdev->pf_to_mgmt,
394                                  HINIC_MOD_COMM,
395                                  HINIC_COMM_CMD_RES_STATE_SET,
396                                  &res_state, sizeof(res_state), NULL,
397                                  NULL, HINIC_MGMT_MSG_SYNC);
398 }
399
400 /**
401  * get_base_qpn - get the first qp number
402  * @hwdev: the NIC HW device
403  * @base_qpn: returned qp number
404  *
405  * Return 0 - Success, negative - Failure
406  **/
407 static int get_base_qpn(struct hinic_hwdev *hwdev, u16 *base_qpn)
408 {
409         struct hinic_cmd_base_qpn cmd_base_qpn;
410         struct hinic_hwif *hwif = hwdev->hwif;
411         u16 out_size = sizeof(cmd_base_qpn);
412         struct pci_dev *pdev = hwif->pdev;
413         int err;
414
415         cmd_base_qpn.func_idx = HINIC_HWIF_FUNC_IDX(hwif);
416
417         err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_GET_GLOBAL_QPN,
418                                  &cmd_base_qpn, sizeof(cmd_base_qpn),
419                                  &cmd_base_qpn, &out_size);
420         if (err || out_size != sizeof(cmd_base_qpn) || cmd_base_qpn.status) {
421                 dev_err(&pdev->dev, "Failed to get base qpn, err: %d, status: 0x%x, out size: 0x%x\n",
422                         err, cmd_base_qpn.status, out_size);
423                 return -EIO;
424         }
425
426         *base_qpn = cmd_base_qpn.qpn;
427         return 0;
428 }
429
430 /**
431  * hinic_hwdev_ifup - Preparing the HW for passing IO
432  * @hwdev: the NIC HW device
433  * @sq_depth: the send queue depth
434  * @rq_depth: the receive queue depth
435  *
436  * Return 0 - Success, negative - Failure
437  **/
438 int hinic_hwdev_ifup(struct hinic_hwdev *hwdev, u16 sq_depth, u16 rq_depth)
439 {
440         struct hinic_func_to_io *func_to_io = &hwdev->func_to_io;
441         struct hinic_cap *nic_cap = &hwdev->nic_cap;
442         struct hinic_hwif *hwif = hwdev->hwif;
443         int err, num_aeqs, num_ceqs, num_qps;
444         struct msix_entry *ceq_msix_entries;
445         struct msix_entry *sq_msix_entries;
446         struct msix_entry *rq_msix_entries;
447         struct pci_dev *pdev = hwif->pdev;
448         u16 base_qpn;
449
450         err = get_base_qpn(hwdev, &base_qpn);
451         if (err) {
452                 dev_err(&pdev->dev, "Failed to get global base qp number\n");
453                 return err;
454         }
455
456         num_aeqs = HINIC_HWIF_NUM_AEQS(hwif);
457         num_ceqs = HINIC_HWIF_NUM_CEQS(hwif);
458
459         ceq_msix_entries = &hwdev->msix_entries[num_aeqs];
460         func_to_io->hwdev = hwdev;
461         func_to_io->sq_depth = sq_depth;
462         func_to_io->rq_depth = rq_depth;
463         func_to_io->global_qpn = base_qpn;
464
465         err = hinic_io_init(func_to_io, hwif, nic_cap->max_qps, num_ceqs,
466                             ceq_msix_entries);
467         if (err) {
468                 dev_err(&pdev->dev, "Failed to init IO channel\n");
469                 return err;
470         }
471
472         num_qps = nic_cap->num_qps;
473         sq_msix_entries = &hwdev->msix_entries[num_aeqs + num_ceqs];
474         rq_msix_entries = &hwdev->msix_entries[num_aeqs + num_ceqs + num_qps];
475
476         err = hinic_io_create_qps(func_to_io, base_qpn, num_qps,
477                                   sq_msix_entries, rq_msix_entries);
478         if (err) {
479                 dev_err(&pdev->dev, "Failed to create QPs\n");
480                 goto err_create_qps;
481         }
482
483         err = wait_for_db_state(hwdev);
484         if (err) {
485                 dev_warn(&pdev->dev, "db - disabled, try again\n");
486                 hinic_db_state_set(hwif, HINIC_DB_ENABLE);
487         }
488
489         err = set_hw_ioctxt(hwdev, sq_depth, rq_depth);
490         if (err) {
491                 dev_err(&pdev->dev, "Failed to set HW IO ctxt\n");
492                 goto err_hw_ioctxt;
493         }
494
495         return 0;
496
497 err_hw_ioctxt:
498         hinic_io_destroy_qps(func_to_io, num_qps);
499
500 err_create_qps:
501         hinic_io_free(func_to_io);
502         return err;
503 }
504
505 /**
506  * hinic_hwdev_ifdown - Closing the HW for passing IO
507  * @hwdev: the NIC HW device
508  *
509  **/
510 void hinic_hwdev_ifdown(struct hinic_hwdev *hwdev)
511 {
512         struct hinic_func_to_io *func_to_io = &hwdev->func_to_io;
513         struct hinic_cap *nic_cap = &hwdev->nic_cap;
514
515         clear_io_resources(hwdev);
516
517         hinic_io_destroy_qps(func_to_io, nic_cap->num_qps);
518         hinic_io_free(func_to_io);
519 }
520
521 /**
522  * hinic_hwdev_cb_register - register callback handler for MGMT events
523  * @hwdev: the NIC HW device
524  * @cmd: the mgmt event
525  * @handle: private data for the handler
526  * @handler: event handler
527  **/
528 void hinic_hwdev_cb_register(struct hinic_hwdev *hwdev,
529                              enum hinic_mgmt_msg_cmd cmd, void *handle,
530                              void (*handler)(void *handle, void *buf_in,
531                                              u16 in_size, void *buf_out,
532                                              u16 *out_size))
533 {
534         struct hinic_pfhwdev *pfhwdev;
535         struct hinic_nic_cb *nic_cb;
536         u8 cmd_cb;
537
538         pfhwdev = container_of(hwdev, struct hinic_pfhwdev, hwdev);
539
540         cmd_cb = cmd - HINIC_MGMT_MSG_CMD_BASE;
541         nic_cb = &pfhwdev->nic_cb[cmd_cb];
542
543         nic_cb->handler = handler;
544         nic_cb->handle = handle;
545         nic_cb->cb_state = HINIC_CB_ENABLED;
546 }
547
548 /**
549  * hinic_hwdev_cb_unregister - unregister callback handler for MGMT events
550  * @hwdev: the NIC HW device
551  * @cmd: the mgmt event
552  **/
553 void hinic_hwdev_cb_unregister(struct hinic_hwdev *hwdev,
554                                enum hinic_mgmt_msg_cmd cmd)
555 {
556         struct hinic_hwif *hwif = hwdev->hwif;
557         struct hinic_pfhwdev *pfhwdev;
558         struct hinic_nic_cb *nic_cb;
559         u8 cmd_cb;
560
561         if (!HINIC_IS_PF(hwif) && !HINIC_IS_PPF(hwif))
562                 return;
563
564         pfhwdev = container_of(hwdev, struct hinic_pfhwdev, hwdev);
565
566         cmd_cb = cmd - HINIC_MGMT_MSG_CMD_BASE;
567         nic_cb = &pfhwdev->nic_cb[cmd_cb];
568
569         nic_cb->cb_state &= ~HINIC_CB_ENABLED;
570
571         while (nic_cb->cb_state & HINIC_CB_RUNNING)
572                 schedule();
573
574         nic_cb->handler = NULL;
575 }
576
577 /**
578  * nic_mgmt_msg_handler - nic mgmt event handler
579  * @handle: private data for the handler
580  * @cmd: message command
581  * @buf_in: input buffer
582  * @in_size: input size
583  * @buf_out: output buffer
584  * @out_size: returned output size
585  **/
586 static void nic_mgmt_msg_handler(void *handle, u8 cmd, void *buf_in,
587                                  u16 in_size, void *buf_out, u16 *out_size)
588 {
589         struct hinic_pfhwdev *pfhwdev = handle;
590         enum hinic_cb_state cb_state;
591         struct hinic_nic_cb *nic_cb;
592         struct hinic_hwdev *hwdev;
593         struct hinic_hwif *hwif;
594         struct pci_dev *pdev;
595         u8 cmd_cb;
596
597         hwdev = &pfhwdev->hwdev;
598         hwif = hwdev->hwif;
599         pdev = hwif->pdev;
600
601         if (cmd < HINIC_MGMT_MSG_CMD_BASE ||
602             cmd >= HINIC_MGMT_MSG_CMD_MAX) {
603                 dev_err(&pdev->dev, "unknown L2NIC event, cmd = %d\n", cmd);
604                 return;
605         }
606
607         cmd_cb = cmd - HINIC_MGMT_MSG_CMD_BASE;
608
609         nic_cb = &pfhwdev->nic_cb[cmd_cb];
610
611         cb_state = cmpxchg(&nic_cb->cb_state,
612                            HINIC_CB_ENABLED,
613                            HINIC_CB_ENABLED | HINIC_CB_RUNNING);
614
615         if (cb_state == HINIC_CB_ENABLED && nic_cb->handler)
616                 nic_cb->handler(nic_cb->handle, buf_in,
617                                 in_size, buf_out, out_size);
618         else
619                 dev_err(&pdev->dev, "Unhandled NIC Event %d\n", cmd);
620
621         nic_cb->cb_state &= ~HINIC_CB_RUNNING;
622 }
623
624 static void hinic_comm_recv_mgmt_self_cmd_reg(struct hinic_pfhwdev *pfhwdev,
625                                               u8 cmd,
626                                               comm_mgmt_self_msg_proc proc)
627 {
628         u8 cmd_idx;
629
630         cmd_idx = pfhwdev->proc.cmd_num;
631         if (cmd_idx >= HINIC_COMM_SELF_CMD_MAX) {
632                 dev_err(&pfhwdev->hwdev.hwif->pdev->dev,
633                         "Register recv mgmt process failed, cmd: 0x%x\n", cmd);
634                 return;
635         }
636
637         pfhwdev->proc.info[cmd_idx].cmd = cmd;
638         pfhwdev->proc.info[cmd_idx].proc = proc;
639         pfhwdev->proc.cmd_num++;
640 }
641
642 static void hinic_comm_recv_mgmt_self_cmd_unreg(struct hinic_pfhwdev *pfhwdev,
643                                                 u8 cmd)
644 {
645         u8 cmd_idx;
646
647         cmd_idx = pfhwdev->proc.cmd_num;
648         if (cmd_idx >= HINIC_COMM_SELF_CMD_MAX) {
649                 dev_err(&pfhwdev->hwdev.hwif->pdev->dev, "Unregister recv mgmt process failed, cmd: 0x%x\n",
650                         cmd);
651                 return;
652         }
653
654         for (cmd_idx = 0; cmd_idx < HINIC_COMM_SELF_CMD_MAX; cmd_idx++) {
655                 if (cmd == pfhwdev->proc.info[cmd_idx].cmd) {
656                         pfhwdev->proc.info[cmd_idx].cmd = 0;
657                         pfhwdev->proc.info[cmd_idx].proc = NULL;
658                         pfhwdev->proc.cmd_num--;
659                 }
660         }
661 }
662
663 static void comm_mgmt_msg_handler(void *handle, u8 cmd, void *buf_in,
664                                   u16 in_size, void *buf_out, u16 *out_size)
665 {
666         struct hinic_pfhwdev *pfhwdev = handle;
667         u8 cmd_idx;
668
669         for (cmd_idx = 0; cmd_idx < pfhwdev->proc.cmd_num; cmd_idx++) {
670                 if (cmd == pfhwdev->proc.info[cmd_idx].cmd) {
671                         if (!pfhwdev->proc.info[cmd_idx].proc) {
672                                 dev_warn(&pfhwdev->hwdev.hwif->pdev->dev,
673                                          "PF recv mgmt comm msg handle null, cmd: 0x%x\n",
674                                          cmd);
675                         } else {
676                                 pfhwdev->proc.info[cmd_idx].proc
677                                         (&pfhwdev->hwdev, buf_in, in_size,
678                                          buf_out, out_size);
679                         }
680
681                         return;
682                 }
683         }
684
685         dev_warn(&pfhwdev->hwdev.hwif->pdev->dev, "Received unknown mgmt cpu event: 0x%x\n",
686                  cmd);
687
688         *out_size = 0;
689 }
690
691 /* pf fault report event */
692 static void pf_fault_event_handler(void *dev, void *buf_in, u16 in_size,
693                                    void *buf_out, u16 *out_size)
694 {
695         struct hinic_cmd_fault_event *fault_event = buf_in;
696         struct hinic_hwdev *hwdev = dev;
697
698         if (in_size != sizeof(*fault_event)) {
699                 dev_err(&hwdev->hwif->pdev->dev, "Invalid fault event report, length: %d, should be %zu\n",
700                         in_size, sizeof(*fault_event));
701                 return;
702         }
703
704         if (!hwdev->devlink_dev || IS_ERR_OR_NULL(hwdev->devlink_dev->hw_fault_reporter))
705                 return;
706
707         devlink_health_report(hwdev->devlink_dev->hw_fault_reporter,
708                               "HW fatal error reported", &fault_event->event);
709 }
710
711 static void mgmt_watchdog_timeout_event_handler(void *dev,
712                                                 void *buf_in, u16 in_size,
713                                                 void *buf_out, u16 *out_size)
714 {
715         struct hinic_mgmt_watchdog_info *watchdog_info = buf_in;
716         struct hinic_hwdev *hwdev = dev;
717
718         if (in_size != sizeof(*watchdog_info)) {
719                 dev_err(&hwdev->hwif->pdev->dev, "Invalid mgmt watchdog report, length: %d, should be %zu\n",
720                         in_size, sizeof(*watchdog_info));
721                 return;
722         }
723
724         if (!hwdev->devlink_dev || IS_ERR_OR_NULL(hwdev->devlink_dev->fw_fault_reporter))
725                 return;
726
727         devlink_health_report(hwdev->devlink_dev->fw_fault_reporter,
728                               "FW fatal error reported", watchdog_info);
729 }
730
731 /**
732  * init_pfhwdev - Initialize the extended components of PF
733  * @pfhwdev: the HW device for PF
734  *
735  * Return 0 - success, negative - failure
736  **/
737 static int init_pfhwdev(struct hinic_pfhwdev *pfhwdev)
738 {
739         struct hinic_hwdev *hwdev = &pfhwdev->hwdev;
740         struct hinic_hwif *hwif = hwdev->hwif;
741         struct pci_dev *pdev = hwif->pdev;
742         int err;
743
744         err = hinic_pf_to_mgmt_init(&pfhwdev->pf_to_mgmt, hwif);
745         if (err) {
746                 dev_err(&pdev->dev, "Failed to initialize PF to MGMT channel\n");
747                 return err;
748         }
749
750         err = hinic_func_to_func_init(hwdev);
751         if (err) {
752                 dev_err(&hwif->pdev->dev, "Failed to init mailbox\n");
753                 hinic_pf_to_mgmt_free(&pfhwdev->pf_to_mgmt);
754                 return err;
755         }
756
757         if (!HINIC_IS_VF(hwif)) {
758                 hinic_register_mgmt_msg_cb(&pfhwdev->pf_to_mgmt,
759                                            HINIC_MOD_L2NIC, pfhwdev,
760                                            nic_mgmt_msg_handler);
761                 hinic_register_mgmt_msg_cb(&pfhwdev->pf_to_mgmt, HINIC_MOD_COMM,
762                                            pfhwdev, comm_mgmt_msg_handler);
763                 hinic_comm_recv_mgmt_self_cmd_reg(pfhwdev,
764                                                   HINIC_COMM_CMD_FAULT_REPORT,
765                                                   pf_fault_event_handler);
766                 hinic_comm_recv_mgmt_self_cmd_reg
767                         (pfhwdev, HINIC_COMM_CMD_WATCHDOG_INFO,
768                          mgmt_watchdog_timeout_event_handler);
769         } else {
770                 hinic_register_vf_mbox_cb(hwdev, HINIC_MOD_L2NIC,
771                                           nic_mgmt_msg_handler);
772         }
773
774         hinic_set_pf_action(hwif, HINIC_PF_MGMT_ACTIVE);
775         hinic_devlink_register(hwdev->devlink_dev);
776         return 0;
777 }
778
779 /**
780  * free_pfhwdev - Free the extended components of PF
781  * @pfhwdev: the HW device for PF
782  **/
783 static void free_pfhwdev(struct hinic_pfhwdev *pfhwdev)
784 {
785         struct hinic_hwdev *hwdev = &pfhwdev->hwdev;
786
787         hinic_devlink_unregister(hwdev->devlink_dev);
788         hinic_set_pf_action(hwdev->hwif, HINIC_PF_MGMT_INIT);
789
790         if (!HINIC_IS_VF(hwdev->hwif)) {
791                 hinic_comm_recv_mgmt_self_cmd_unreg(pfhwdev,
792                                                     HINIC_COMM_CMD_WATCHDOG_INFO);
793                 hinic_comm_recv_mgmt_self_cmd_unreg(pfhwdev,
794                                                     HINIC_COMM_CMD_FAULT_REPORT);
795                 hinic_unregister_mgmt_msg_cb(&pfhwdev->pf_to_mgmt,
796                                              HINIC_MOD_COMM);
797                 hinic_unregister_mgmt_msg_cb(&pfhwdev->pf_to_mgmt,
798                                              HINIC_MOD_L2NIC);
799         } else {
800                 hinic_unregister_vf_mbox_cb(hwdev, HINIC_MOD_L2NIC);
801         }
802
803         hinic_func_to_func_free(hwdev);
804
805         hinic_pf_to_mgmt_free(&pfhwdev->pf_to_mgmt);
806 }
807
808 static int hinic_l2nic_reset(struct hinic_hwdev *hwdev)
809 {
810         struct hinic_cmd_l2nic_reset l2nic_reset = {0};
811         u16 out_size = sizeof(l2nic_reset);
812         struct hinic_pfhwdev *pfhwdev;
813         int err;
814
815         pfhwdev = container_of(hwdev, struct hinic_pfhwdev, hwdev);
816
817         l2nic_reset.func_id = HINIC_HWIF_FUNC_IDX(hwdev->hwif);
818         /* 0 represents standard l2nic reset flow */
819         l2nic_reset.reset_flag = 0;
820
821         err = hinic_msg_to_mgmt(&pfhwdev->pf_to_mgmt, HINIC_MOD_COMM,
822                                 HINIC_COMM_CMD_L2NIC_RESET, &l2nic_reset,
823                                 sizeof(l2nic_reset), &l2nic_reset,
824                                 &out_size, HINIC_MGMT_MSG_SYNC);
825         if (err || !out_size || l2nic_reset.status) {
826                 dev_err(&hwdev->hwif->pdev->dev, "Failed to reset L2NIC resources, err: %d, status: 0x%x, out_size: 0x%x\n",
827                         err, l2nic_reset.status, out_size);
828                 return -EIO;
829         }
830
831         return 0;
832 }
833
834 static int hinic_get_interrupt_cfg(struct hinic_hwdev *hwdev,
835                                    struct hinic_msix_config *interrupt_info)
836 {
837         u16 out_size = sizeof(*interrupt_info);
838         struct hinic_pfhwdev *pfhwdev;
839         int err;
840
841         if (!hwdev || !interrupt_info)
842                 return -EINVAL;
843
844         pfhwdev = container_of(hwdev, struct hinic_pfhwdev, hwdev);
845
846         interrupt_info->func_id = HINIC_HWIF_FUNC_IDX(hwdev->hwif);
847
848         err = hinic_msg_to_mgmt(&pfhwdev->pf_to_mgmt, HINIC_MOD_COMM,
849                                 HINIC_COMM_CMD_MSI_CTRL_REG_RD_BY_UP,
850                                 interrupt_info, sizeof(*interrupt_info),
851                                 interrupt_info, &out_size, HINIC_MGMT_MSG_SYNC);
852         if (err || !out_size || interrupt_info->status) {
853                 dev_err(&hwdev->hwif->pdev->dev, "Failed to get interrupt config, err: %d, status: 0x%x, out size: 0x%x\n",
854                         err, interrupt_info->status, out_size);
855                 return -EIO;
856         }
857
858         return 0;
859 }
860
861 int hinic_set_interrupt_cfg(struct hinic_hwdev *hwdev,
862                             struct hinic_msix_config *interrupt_info)
863 {
864         u16 out_size = sizeof(*interrupt_info);
865         struct hinic_msix_config temp_info;
866         struct hinic_pfhwdev *pfhwdev;
867         int err;
868
869         if (!hwdev)
870                 return -EINVAL;
871
872         pfhwdev = container_of(hwdev, struct hinic_pfhwdev, hwdev);
873
874         interrupt_info->func_id = HINIC_HWIF_FUNC_IDX(hwdev->hwif);
875
876         err = hinic_get_interrupt_cfg(hwdev, &temp_info);
877         if (err)
878                 return -EINVAL;
879
880         interrupt_info->lli_credit_cnt = temp_info.lli_credit_cnt;
881         interrupt_info->lli_timer_cnt = temp_info.lli_timer_cnt;
882
883         err = hinic_msg_to_mgmt(&pfhwdev->pf_to_mgmt, HINIC_MOD_COMM,
884                                 HINIC_COMM_CMD_MSI_CTRL_REG_WR_BY_UP,
885                                 interrupt_info, sizeof(*interrupt_info),
886                                 interrupt_info, &out_size, HINIC_MGMT_MSG_SYNC);
887         if (err || !out_size || interrupt_info->status) {
888                 dev_err(&hwdev->hwif->pdev->dev, "Failed to get interrupt config, err: %d, status: 0x%x, out size: 0x%x\n",
889                         err, interrupt_info->status, out_size);
890                 return -EIO;
891         }
892
893         return 0;
894 }
895
896 /**
897  * hinic_init_hwdev - Initialize the NIC HW
898  * @pdev: the NIC pci device
899  * @devlink: the poniter of hinic devlink
900  *
901  * Return initialized NIC HW device
902  *
903  * Initialize the NIC HW device and return a pointer to it
904  **/
905 struct hinic_hwdev *hinic_init_hwdev(struct pci_dev *pdev, struct devlink *devlink)
906 {
907         struct hinic_pfhwdev *pfhwdev;
908         struct hinic_hwdev *hwdev;
909         struct hinic_hwif *hwif;
910         int err, num_aeqs;
911
912         hwif = devm_kzalloc(&pdev->dev, sizeof(*hwif), GFP_KERNEL);
913         if (!hwif)
914                 return ERR_PTR(-ENOMEM);
915
916         err = hinic_init_hwif(hwif, pdev);
917         if (err) {
918                 dev_err(&pdev->dev, "Failed to init HW interface\n");
919                 return ERR_PTR(err);
920         }
921
922         pfhwdev = devm_kzalloc(&pdev->dev, sizeof(*pfhwdev), GFP_KERNEL);
923         if (!pfhwdev) {
924                 err = -ENOMEM;
925                 goto err_pfhwdev_alloc;
926         }
927
928         hwdev = &pfhwdev->hwdev;
929         hwdev->hwif = hwif;
930         hwdev->devlink_dev = devlink_priv(devlink);
931         hwdev->devlink_dev->hwdev = hwdev;
932
933         err = init_msix(hwdev);
934         if (err) {
935                 dev_err(&pdev->dev, "Failed to init msix\n");
936                 goto err_init_msix;
937         }
938
939         err = wait_for_outbound_state(hwdev);
940         if (err) {
941                 dev_warn(&pdev->dev, "outbound - disabled, try again\n");
942                 hinic_outbound_state_set(hwif, HINIC_OUTBOUND_ENABLE);
943         }
944
945         num_aeqs = HINIC_HWIF_NUM_AEQS(hwif);
946
947         err = hinic_aeqs_init(&hwdev->aeqs, hwif, num_aeqs,
948                               HINIC_DEFAULT_AEQ_LEN, HINIC_EQ_PAGE_SIZE,
949                               hwdev->msix_entries);
950         if (err) {
951                 dev_err(&pdev->dev, "Failed to init async event queues\n");
952                 goto err_aeqs_init;
953         }
954
955         err = init_pfhwdev(pfhwdev);
956         if (err) {
957                 dev_err(&pdev->dev, "Failed to init PF HW device\n");
958                 goto err_init_pfhwdev;
959         }
960
961         err = hinic_l2nic_reset(hwdev);
962         if (err)
963                 goto err_l2nic_reset;
964
965         err = get_dev_cap(hwdev);
966         if (err) {
967                 dev_err(&pdev->dev, "Failed to get device capabilities\n");
968                 goto err_dev_cap;
969         }
970
971         mutex_init(&hwdev->func_to_io.nic_cfg.cfg_mutex);
972
973         err = hinic_vf_func_init(hwdev);
974         if (err) {
975                 dev_err(&pdev->dev, "Failed to init nic mbox\n");
976                 goto err_vf_func_init;
977         }
978
979         err = init_fw_ctxt(hwdev);
980         if (err) {
981                 dev_err(&pdev->dev, "Failed to init function table\n");
982                 goto err_init_fw_ctxt;
983         }
984
985         err = set_resources_state(hwdev, HINIC_RES_ACTIVE);
986         if (err) {
987                 dev_err(&pdev->dev, "Failed to set resources state\n");
988                 goto err_resources_state;
989         }
990
991         return hwdev;
992
993 err_resources_state:
994 err_init_fw_ctxt:
995         hinic_vf_func_free(hwdev);
996 err_vf_func_init:
997 err_l2nic_reset:
998 err_dev_cap:
999         free_pfhwdev(pfhwdev);
1000
1001 err_init_pfhwdev:
1002         hinic_aeqs_free(&hwdev->aeqs);
1003
1004 err_aeqs_init:
1005         disable_msix(hwdev);
1006
1007 err_init_msix:
1008 err_pfhwdev_alloc:
1009         hinic_free_hwif(hwif);
1010         if (err > 0)
1011                 err = -EIO;
1012         return ERR_PTR(err);
1013 }
1014
1015 /**
1016  * hinic_free_hwdev - Free the NIC HW device
1017  * @hwdev: the NIC HW device
1018  **/
1019 void hinic_free_hwdev(struct hinic_hwdev *hwdev)
1020 {
1021         struct hinic_pfhwdev *pfhwdev = container_of(hwdev,
1022                                                      struct hinic_pfhwdev,
1023                                                      hwdev);
1024
1025         set_resources_state(hwdev, HINIC_RES_CLEAN);
1026
1027         hinic_vf_func_free(hwdev);
1028
1029         free_pfhwdev(pfhwdev);
1030
1031         hinic_aeqs_free(&hwdev->aeqs);
1032
1033         disable_msix(hwdev);
1034
1035         hinic_free_hwif(hwdev->hwif);
1036 }
1037
1038 /**
1039  * hinic_hwdev_num_qps - return the number QPs available for use
1040  * @hwdev: the NIC HW device
1041  *
1042  * Return number QPs available for use
1043  **/
1044 int hinic_hwdev_num_qps(struct hinic_hwdev *hwdev)
1045 {
1046         struct hinic_cap *nic_cap = &hwdev->nic_cap;
1047
1048         return nic_cap->num_qps;
1049 }
1050
1051 /**
1052  * hinic_hwdev_get_sq - get SQ
1053  * @hwdev: the NIC HW device
1054  * @i: the position of the SQ
1055  *
1056  * Return: the SQ in the i position
1057  **/
1058 struct hinic_sq *hinic_hwdev_get_sq(struct hinic_hwdev *hwdev, int i)
1059 {
1060         struct hinic_func_to_io *func_to_io = &hwdev->func_to_io;
1061         struct hinic_qp *qp = &func_to_io->qps[i];
1062
1063         if (i >= hinic_hwdev_num_qps(hwdev))
1064                 return NULL;
1065
1066         return &qp->sq;
1067 }
1068
1069 /**
1070  * hinic_hwdev_get_rq - get RQ
1071  * @hwdev: the NIC HW device
1072  * @i: the position of the RQ
1073  *
1074  * Return: the RQ in the i position
1075  **/
1076 struct hinic_rq *hinic_hwdev_get_rq(struct hinic_hwdev *hwdev, int i)
1077 {
1078         struct hinic_func_to_io *func_to_io = &hwdev->func_to_io;
1079         struct hinic_qp *qp = &func_to_io->qps[i];
1080
1081         if (i >= hinic_hwdev_num_qps(hwdev))
1082                 return NULL;
1083
1084         return &qp->rq;
1085 }
1086
1087 /**
1088  * hinic_hwdev_msix_cnt_set - clear message attribute counters for msix entry
1089  * @hwdev: the NIC HW device
1090  * @msix_index: msix_index
1091  *
1092  * Return 0 - Success, negative - Failure
1093  **/
1094 int hinic_hwdev_msix_cnt_set(struct hinic_hwdev *hwdev, u16 msix_index)
1095 {
1096         return hinic_msix_attr_cnt_clear(hwdev->hwif, msix_index);
1097 }
1098
1099 /**
1100  * hinic_hwdev_msix_set - set message attribute for msix entry
1101  * @hwdev: the NIC HW device
1102  * @msix_index: msix_index
1103  * @pending_limit: the maximum pending interrupt events (unit 8)
1104  * @coalesc_timer: coalesc period for interrupt (unit 8 us)
1105  * @lli_timer_cfg: replenishing period for low latency credit (unit 8 us)
1106  * @lli_credit_limit: maximum credits for low latency msix messages (unit 8)
1107  * @resend_timer: maximum wait for resending msix (unit coalesc period)
1108  *
1109  * Return 0 - Success, negative - Failure
1110  **/
1111 int hinic_hwdev_msix_set(struct hinic_hwdev *hwdev, u16 msix_index,
1112                          u8 pending_limit, u8 coalesc_timer,
1113                          u8 lli_timer_cfg, u8 lli_credit_limit,
1114                          u8 resend_timer)
1115 {
1116         return hinic_msix_attr_set(hwdev->hwif, msix_index,
1117                                    pending_limit, coalesc_timer,
1118                                    lli_timer_cfg, lli_credit_limit,
1119                                    resend_timer);
1120 }
1121
1122 /**
1123  * hinic_hwdev_hw_ci_addr_set - set cons idx addr and attributes in HW for sq
1124  * @hwdev: the NIC HW device
1125  * @sq: send queue
1126  * @pending_limit: the maximum pending update ci events (unit 8)
1127  * @coalesc_timer: coalesc period for update ci (unit 8 us)
1128  *
1129  * Return 0 - Success, negative - Failure
1130  **/
1131 int hinic_hwdev_hw_ci_addr_set(struct hinic_hwdev *hwdev, struct hinic_sq *sq,
1132                                u8 pending_limit, u8 coalesc_timer)
1133 {
1134         struct hinic_qp *qp = container_of(sq, struct hinic_qp, sq);
1135         struct hinic_hwif *hwif = hwdev->hwif;
1136         struct hinic_pfhwdev *pfhwdev;
1137         struct hinic_cmd_hw_ci hw_ci;
1138
1139         hw_ci.dma_attr_off  = 0;
1140         hw_ci.pending_limit = pending_limit;
1141         hw_ci.coalesc_timer = coalesc_timer;
1142
1143         hw_ci.msix_en = 1;
1144         hw_ci.msix_entry_idx = sq->msix_entry;
1145
1146         hw_ci.func_idx = HINIC_HWIF_FUNC_IDX(hwif);
1147
1148         hw_ci.sq_id = qp->q_id;
1149
1150         hw_ci.ci_addr = ADDR_IN_4BYTES(sq->hw_ci_dma_addr);
1151
1152         pfhwdev = container_of(hwdev, struct hinic_pfhwdev, hwdev);
1153         return hinic_msg_to_mgmt(&pfhwdev->pf_to_mgmt,
1154                                  HINIC_MOD_COMM,
1155                                  HINIC_COMM_CMD_SQ_HI_CI_SET,
1156                                  &hw_ci, sizeof(hw_ci), NULL,
1157                                  NULL, HINIC_MGMT_MSG_SYNC);
1158 }
1159
1160 /**
1161  * hinic_hwdev_set_msix_state- set msix state
1162  * @hwdev: the NIC HW device
1163  * @msix_index: IRQ corresponding index number
1164  * @flag: msix state
1165  *
1166  **/
1167 void hinic_hwdev_set_msix_state(struct hinic_hwdev *hwdev, u16 msix_index,
1168                                 enum hinic_msix_state flag)
1169 {
1170         hinic_set_msix_state(hwdev->hwif, msix_index, flag);
1171 }
1172
1173 int hinic_get_board_info(struct hinic_hwdev *hwdev,
1174                          struct hinic_comm_board_info *board_info)
1175 {
1176         u16 out_size = sizeof(*board_info);
1177         struct hinic_pfhwdev *pfhwdev;
1178         int err;
1179
1180         if (!hwdev || !board_info)
1181                 return -EINVAL;
1182
1183         pfhwdev = container_of(hwdev, struct hinic_pfhwdev, hwdev);
1184
1185         err = hinic_msg_to_mgmt(&pfhwdev->pf_to_mgmt, HINIC_MOD_COMM,
1186                                 HINIC_COMM_CMD_GET_BOARD_INFO,
1187                                 board_info, sizeof(*board_info),
1188                                 board_info, &out_size, HINIC_MGMT_MSG_SYNC);
1189         if (err || board_info->status || !out_size) {
1190                 dev_err(&hwdev->hwif->pdev->dev,
1191                         "Failed to get board info, err: %d, status: 0x%x, out size: 0x%x\n",
1192                         err, board_info->status, out_size);
1193                 return -EIO;
1194         }
1195
1196         return 0;
1197 }