GNU Linux-libre 4.14.332-gnu1
[releases.git] / drivers / net / ethernet / huawei / hinic / hinic_hw_dev.c
1 /*
2  * Huawei HiNIC PCI Express Linux driver
3  * Copyright(c) 2017 Huawei Technologies Co., Ltd
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms and conditions of the GNU General Public License,
7  * version 2, as published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  * for more details.
13  *
14  */
15
16 #include <linux/kernel.h>
17 #include <linux/types.h>
18 #include <linux/pci.h>
19 #include <linux/device.h>
20 #include <linux/errno.h>
21 #include <linux/slab.h>
22 #include <linux/bitops.h>
23 #include <linux/delay.h>
24 #include <linux/jiffies.h>
25 #include <linux/log2.h>
26 #include <linux/err.h>
27
28 #include "hinic_hw_if.h"
29 #include "hinic_hw_eqs.h"
30 #include "hinic_hw_mgmt.h"
31 #include "hinic_hw_qp_ctxt.h"
32 #include "hinic_hw_qp.h"
33 #include "hinic_hw_io.h"
34 #include "hinic_hw_dev.h"
35
36 #define IO_STATUS_TIMEOUT               100
37 #define OUTBOUND_STATE_TIMEOUT          100
38 #define DB_STATE_TIMEOUT                100
39
40 #define MAX_IRQS(max_qps, num_aeqs, num_ceqs)   \
41                  (2 * (max_qps) + (num_aeqs) + (num_ceqs))
42
43 #define ADDR_IN_4BYTES(addr)            ((addr) >> 2)
44
45 enum intr_type {
46         INTR_MSIX_TYPE,
47 };
48
49 enum io_status {
50         IO_STOPPED = 0,
51         IO_RUNNING = 1,
52 };
53
54 enum hw_ioctxt_set_cmdq_depth {
55         HW_IOCTXT_SET_CMDQ_DEPTH_DEFAULT,
56 };
57
58 /* HW struct */
59 struct hinic_dev_cap {
60         u8      status;
61         u8      version;
62         u8      rsvd0[6];
63
64         u8      rsvd1[5];
65         u8      intr_type;
66         u8      rsvd2[66];
67         u16     max_sqs;
68         u16     max_rqs;
69         u8      rsvd3[208];
70 };
71
72 /**
73  * get_capability - convert device capabilities to NIC capabilities
74  * @hwdev: the HW device to set and convert device capabilities for
75  * @dev_cap: device capabilities from FW
76  *
77  * Return 0 - Success, negative - Failure
78  **/
79 static int get_capability(struct hinic_hwdev *hwdev,
80                           struct hinic_dev_cap *dev_cap)
81 {
82         struct hinic_cap *nic_cap = &hwdev->nic_cap;
83         int num_aeqs, num_ceqs, num_irqs;
84
85         if (!HINIC_IS_PF(hwdev->hwif) && !HINIC_IS_PPF(hwdev->hwif))
86                 return -EINVAL;
87
88         if (dev_cap->intr_type != INTR_MSIX_TYPE)
89                 return -EFAULT;
90
91         num_aeqs = HINIC_HWIF_NUM_AEQS(hwdev->hwif);
92         num_ceqs = HINIC_HWIF_NUM_CEQS(hwdev->hwif);
93         num_irqs = HINIC_HWIF_NUM_IRQS(hwdev->hwif);
94
95         /* Each QP has its own (SQ + RQ) interrupts */
96         nic_cap->num_qps = (num_irqs - (num_aeqs + num_ceqs)) / 2;
97
98         if (nic_cap->num_qps > HINIC_Q_CTXT_MAX)
99                 nic_cap->num_qps = HINIC_Q_CTXT_MAX;
100
101         /* num_qps must be power of 2 */
102         nic_cap->num_qps = BIT(fls(nic_cap->num_qps) - 1);
103
104         nic_cap->max_qps = dev_cap->max_sqs + 1;
105         if (nic_cap->max_qps != (dev_cap->max_rqs + 1))
106                 return -EFAULT;
107
108         if (nic_cap->num_qps > nic_cap->max_qps)
109                 nic_cap->num_qps = nic_cap->max_qps;
110
111         return 0;
112 }
113
114 /**
115  * get_cap_from_fw - get device capabilities from FW
116  * @pfhwdev: the PF HW device to get capabilities for
117  *
118  * Return 0 - Success, negative - Failure
119  **/
120 static int get_cap_from_fw(struct hinic_pfhwdev *pfhwdev)
121 {
122         struct hinic_hwdev *hwdev = &pfhwdev->hwdev;
123         struct hinic_hwif *hwif = hwdev->hwif;
124         struct pci_dev *pdev = hwif->pdev;
125         struct hinic_dev_cap dev_cap;
126         u16 in_len, out_len;
127         int err;
128
129         in_len = 0;
130         out_len = sizeof(dev_cap);
131
132         err = hinic_msg_to_mgmt(&pfhwdev->pf_to_mgmt, HINIC_MOD_CFGM,
133                                 HINIC_CFG_NIC_CAP, &dev_cap, in_len, &dev_cap,
134                                 &out_len, HINIC_MGMT_MSG_SYNC);
135         if (err) {
136                 dev_err(&pdev->dev, "Failed to get capability from FW\n");
137                 return err;
138         }
139
140         return get_capability(hwdev, &dev_cap);
141 }
142
143 /**
144  * get_dev_cap - get device capabilities
145  * @hwdev: the NIC HW device to get capabilities for
146  *
147  * Return 0 - Success, negative - Failure
148  **/
149 static int get_dev_cap(struct hinic_hwdev *hwdev)
150 {
151         struct hinic_hwif *hwif = hwdev->hwif;
152         struct pci_dev *pdev = hwif->pdev;
153         struct hinic_pfhwdev *pfhwdev;
154         int err;
155
156         switch (HINIC_FUNC_TYPE(hwif)) {
157         case HINIC_PPF:
158         case HINIC_PF:
159                 pfhwdev = container_of(hwdev, struct hinic_pfhwdev, hwdev);
160
161                 err = get_cap_from_fw(pfhwdev);
162                 if (err) {
163                         dev_err(&pdev->dev, "Failed to get capability from FW\n");
164                         return err;
165                 }
166                 break;
167
168         default:
169                 dev_err(&pdev->dev, "Unsupported PCI Function type\n");
170                 return -EINVAL;
171         }
172
173         return 0;
174 }
175
176 /**
177  * init_msix - enable the msix and save the entries
178  * @hwdev: the NIC HW device
179  *
180  * Return 0 - Success, negative - Failure
181  **/
182 static int init_msix(struct hinic_hwdev *hwdev)
183 {
184         struct hinic_hwif *hwif = hwdev->hwif;
185         struct pci_dev *pdev = hwif->pdev;
186         int nr_irqs, num_aeqs, num_ceqs;
187         size_t msix_entries_size;
188         int i, err;
189
190         num_aeqs = HINIC_HWIF_NUM_AEQS(hwif);
191         num_ceqs = HINIC_HWIF_NUM_CEQS(hwif);
192         nr_irqs = MAX_IRQS(HINIC_MAX_QPS, num_aeqs, num_ceqs);
193         if (nr_irqs > HINIC_HWIF_NUM_IRQS(hwif))
194                 nr_irqs = HINIC_HWIF_NUM_IRQS(hwif);
195
196         msix_entries_size = nr_irqs * sizeof(*hwdev->msix_entries);
197         hwdev->msix_entries = devm_kzalloc(&pdev->dev, msix_entries_size,
198                                            GFP_KERNEL);
199         if (!hwdev->msix_entries)
200                 return -ENOMEM;
201
202         for (i = 0; i < nr_irqs; i++)
203                 hwdev->msix_entries[i].entry = i;
204
205         err = pci_enable_msix_exact(pdev, hwdev->msix_entries, nr_irqs);
206         if (err) {
207                 dev_err(&pdev->dev, "Failed to enable pci msix\n");
208                 return err;
209         }
210
211         return 0;
212 }
213
214 /**
215  * disable_msix - disable the msix
216  * @hwdev: the NIC HW device
217  **/
218 static void disable_msix(struct hinic_hwdev *hwdev)
219 {
220         struct hinic_hwif *hwif = hwdev->hwif;
221         struct pci_dev *pdev = hwif->pdev;
222
223         pci_disable_msix(pdev);
224 }
225
226 /**
227  * hinic_port_msg_cmd - send port msg to mgmt
228  * @hwdev: the NIC HW device
229  * @cmd: the port command
230  * @buf_in: input buffer
231  * @in_size: input size
232  * @buf_out: output buffer
233  * @out_size: returned output size
234  *
235  * Return 0 - Success, negative - Failure
236  **/
237 int hinic_port_msg_cmd(struct hinic_hwdev *hwdev, enum hinic_port_cmd cmd,
238                        void *buf_in, u16 in_size, void *buf_out, u16 *out_size)
239 {
240         struct hinic_hwif *hwif = hwdev->hwif;
241         struct pci_dev *pdev = hwif->pdev;
242         struct hinic_pfhwdev *pfhwdev;
243
244         if (!HINIC_IS_PF(hwif) && !HINIC_IS_PPF(hwif)) {
245                 dev_err(&pdev->dev, "unsupported PCI Function type\n");
246                 return -EINVAL;
247         }
248
249         pfhwdev = container_of(hwdev, struct hinic_pfhwdev, hwdev);
250
251         return hinic_msg_to_mgmt(&pfhwdev->pf_to_mgmt, HINIC_MOD_L2NIC, cmd,
252                                  buf_in, in_size, buf_out, out_size,
253                                  HINIC_MGMT_MSG_SYNC);
254 }
255
256 /**
257  * init_fw_ctxt- Init Firmware tables before network mgmt and io operations
258  * @hwdev: the NIC HW device
259  *
260  * Return 0 - Success, negative - Failure
261  **/
262 static int init_fw_ctxt(struct hinic_hwdev *hwdev)
263 {
264         struct hinic_hwif *hwif = hwdev->hwif;
265         struct pci_dev *pdev = hwif->pdev;
266         struct hinic_cmd_fw_ctxt fw_ctxt;
267         struct hinic_pfhwdev *pfhwdev;
268         u16 out_size;
269         int err;
270
271         if (!HINIC_IS_PF(hwif) && !HINIC_IS_PPF(hwif)) {
272                 dev_err(&pdev->dev, "Unsupported PCI Function type\n");
273                 return -EINVAL;
274         }
275
276         fw_ctxt.func_idx = HINIC_HWIF_FUNC_IDX(hwif);
277         fw_ctxt.rx_buf_sz = HINIC_RX_BUF_SZ;
278
279         pfhwdev = container_of(hwdev, struct hinic_pfhwdev, hwdev);
280
281         err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_FWCTXT_INIT,
282                                  &fw_ctxt, sizeof(fw_ctxt),
283                                  &fw_ctxt, &out_size);
284         if (err || (out_size != sizeof(fw_ctxt)) || fw_ctxt.status) {
285                 dev_err(&pdev->dev, "Failed to init FW ctxt, ret = %d\n",
286                         fw_ctxt.status);
287                 return -EFAULT;
288         }
289
290         return 0;
291 }
292
293 /**
294  * set_hw_ioctxt - set the shape of the IO queues in FW
295  * @hwdev: the NIC HW device
296  * @rq_depth: rq depth
297  * @sq_depth: sq depth
298  *
299  * Return 0 - Success, negative - Failure
300  **/
301 static int set_hw_ioctxt(struct hinic_hwdev *hwdev, unsigned int rq_depth,
302                          unsigned int sq_depth)
303 {
304         struct hinic_hwif *hwif = hwdev->hwif;
305         struct hinic_cmd_hw_ioctxt hw_ioctxt;
306         struct pci_dev *pdev = hwif->pdev;
307         struct hinic_pfhwdev *pfhwdev;
308
309         if (!HINIC_IS_PF(hwif) && !HINIC_IS_PPF(hwif)) {
310                 dev_err(&pdev->dev, "Unsupported PCI Function type\n");
311                 return -EINVAL;
312         }
313
314         hw_ioctxt.func_idx = HINIC_HWIF_FUNC_IDX(hwif);
315         hw_ioctxt.ppf_idx = HINIC_HWIF_PPF_IDX(hwif);
316
317         hw_ioctxt.set_cmdq_depth = HW_IOCTXT_SET_CMDQ_DEPTH_DEFAULT;
318         hw_ioctxt.cmdq_depth = 0;
319
320         hw_ioctxt.rq_depth  = ilog2(rq_depth);
321
322         hw_ioctxt.rx_buf_sz_idx = HINIC_RX_BUF_SZ_IDX;
323
324         hw_ioctxt.sq_depth  = ilog2(sq_depth);
325
326         pfhwdev = container_of(hwdev, struct hinic_pfhwdev, hwdev);
327
328         return hinic_msg_to_mgmt(&pfhwdev->pf_to_mgmt, HINIC_MOD_COMM,
329                                  HINIC_COMM_CMD_HWCTXT_SET,
330                                  &hw_ioctxt, sizeof(hw_ioctxt), NULL,
331                                  NULL, HINIC_MGMT_MSG_SYNC);
332 }
333
334 static int wait_for_outbound_state(struct hinic_hwdev *hwdev)
335 {
336         enum hinic_outbound_state outbound_state;
337         struct hinic_hwif *hwif = hwdev->hwif;
338         struct pci_dev *pdev = hwif->pdev;
339         unsigned long end;
340
341         end = jiffies + msecs_to_jiffies(OUTBOUND_STATE_TIMEOUT);
342         do {
343                 outbound_state = hinic_outbound_state_get(hwif);
344
345                 if (outbound_state == HINIC_OUTBOUND_ENABLE)
346                         return 0;
347
348                 msleep(20);
349         } while (time_before(jiffies, end));
350
351         dev_err(&pdev->dev, "Wait for OUTBOUND - Timeout\n");
352         return -EFAULT;
353 }
354
355 static int wait_for_db_state(struct hinic_hwdev *hwdev)
356 {
357         struct hinic_hwif *hwif = hwdev->hwif;
358         struct pci_dev *pdev = hwif->pdev;
359         enum hinic_db_state db_state;
360         unsigned long end;
361
362         end = jiffies + msecs_to_jiffies(DB_STATE_TIMEOUT);
363         do {
364                 db_state = hinic_db_state_get(hwif);
365
366                 if (db_state == HINIC_DB_ENABLE)
367                         return 0;
368
369                 msleep(20);
370         } while (time_before(jiffies, end));
371
372         dev_err(&pdev->dev, "Wait for DB - Timeout\n");
373         return -EFAULT;
374 }
375
376 /**
377  * clear_io_resource - set the IO resources as not active in the NIC
378  * @hwdev: the NIC HW device
379  *
380  * Return 0 - Success, negative - Failure
381  **/
382 static int clear_io_resources(struct hinic_hwdev *hwdev)
383 {
384         struct hinic_cmd_clear_io_res cmd_clear_io_res;
385         struct hinic_hwif *hwif = hwdev->hwif;
386         struct pci_dev *pdev = hwif->pdev;
387         struct hinic_pfhwdev *pfhwdev;
388         int err;
389
390         if (!HINIC_IS_PF(hwif) && !HINIC_IS_PPF(hwif)) {
391                 dev_err(&pdev->dev, "Unsupported PCI Function type\n");
392                 return -EINVAL;
393         }
394
395         /* sleep 100ms to wait for firmware stopping I/O */
396         msleep(100);
397
398         cmd_clear_io_res.func_idx = HINIC_HWIF_FUNC_IDX(hwif);
399
400         pfhwdev = container_of(hwdev, struct hinic_pfhwdev, hwdev);
401
402         err = hinic_msg_to_mgmt(&pfhwdev->pf_to_mgmt, HINIC_MOD_COMM,
403                                 HINIC_COMM_CMD_IO_RES_CLEAR, &cmd_clear_io_res,
404                                 sizeof(cmd_clear_io_res), NULL, NULL,
405                                 HINIC_MGMT_MSG_SYNC);
406         if (err) {
407                 dev_err(&pdev->dev, "Failed to clear IO resources\n");
408                 return err;
409         }
410
411         return 0;
412 }
413
414 /**
415  * set_resources_state - set the state of the resources in the NIC
416  * @hwdev: the NIC HW device
417  * @state: the state to set
418  *
419  * Return 0 - Success, negative - Failure
420  **/
421 static int set_resources_state(struct hinic_hwdev *hwdev,
422                                enum hinic_res_state state)
423 {
424         struct hinic_cmd_set_res_state res_state;
425         struct hinic_hwif *hwif = hwdev->hwif;
426         struct pci_dev *pdev = hwif->pdev;
427         struct hinic_pfhwdev *pfhwdev;
428
429         if (!HINIC_IS_PF(hwif) && !HINIC_IS_PPF(hwif)) {
430                 dev_err(&pdev->dev, "Unsupported PCI Function type\n");
431                 return -EINVAL;
432         }
433
434         res_state.func_idx = HINIC_HWIF_FUNC_IDX(hwif);
435         res_state.state = state;
436
437         pfhwdev = container_of(hwdev, struct hinic_pfhwdev, hwdev);
438
439         return hinic_msg_to_mgmt(&pfhwdev->pf_to_mgmt,
440                                  HINIC_MOD_COMM,
441                                  HINIC_COMM_CMD_RES_STATE_SET,
442                                  &res_state, sizeof(res_state), NULL,
443                                  NULL, HINIC_MGMT_MSG_SYNC);
444 }
445
446 /**
447  * get_base_qpn - get the first qp number
448  * @hwdev: the NIC HW device
449  * @base_qpn: returned qp number
450  *
451  * Return 0 - Success, negative - Failure
452  **/
453 static int get_base_qpn(struct hinic_hwdev *hwdev, u16 *base_qpn)
454 {
455         struct hinic_cmd_base_qpn cmd_base_qpn;
456         struct hinic_hwif *hwif = hwdev->hwif;
457         struct pci_dev *pdev = hwif->pdev;
458         u16 out_size;
459         int err;
460
461         cmd_base_qpn.func_idx = HINIC_HWIF_FUNC_IDX(hwif);
462
463         err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_GET_GLOBAL_QPN,
464                                  &cmd_base_qpn, sizeof(cmd_base_qpn),
465                                  &cmd_base_qpn, &out_size);
466         if (err || (out_size != sizeof(cmd_base_qpn)) || cmd_base_qpn.status) {
467                 dev_err(&pdev->dev, "Failed to get base qpn, status = %d\n",
468                         cmd_base_qpn.status);
469                 return -EFAULT;
470         }
471
472         *base_qpn = cmd_base_qpn.qpn;
473         return 0;
474 }
475
476 /**
477  * hinic_hwdev_ifup - Preparing the HW for passing IO
478  * @hwdev: the NIC HW device
479  *
480  * Return 0 - Success, negative - Failure
481  **/
482 int hinic_hwdev_ifup(struct hinic_hwdev *hwdev)
483 {
484         struct hinic_func_to_io *func_to_io = &hwdev->func_to_io;
485         struct hinic_cap *nic_cap = &hwdev->nic_cap;
486         struct hinic_hwif *hwif = hwdev->hwif;
487         int err, num_aeqs, num_ceqs, num_qps;
488         struct msix_entry *ceq_msix_entries;
489         struct msix_entry *sq_msix_entries;
490         struct msix_entry *rq_msix_entries;
491         struct pci_dev *pdev = hwif->pdev;
492         u16 base_qpn;
493
494         err = get_base_qpn(hwdev, &base_qpn);
495         if (err) {
496                 dev_err(&pdev->dev, "Failed to get global base qp number\n");
497                 return err;
498         }
499
500         num_aeqs = HINIC_HWIF_NUM_AEQS(hwif);
501         num_ceqs = HINIC_HWIF_NUM_CEQS(hwif);
502
503         ceq_msix_entries = &hwdev->msix_entries[num_aeqs];
504
505         err = hinic_io_init(func_to_io, hwif, nic_cap->max_qps, num_ceqs,
506                             ceq_msix_entries);
507         if (err) {
508                 dev_err(&pdev->dev, "Failed to init IO channel\n");
509                 return err;
510         }
511
512         num_qps = nic_cap->num_qps;
513         sq_msix_entries = &hwdev->msix_entries[num_aeqs + num_ceqs];
514         rq_msix_entries = &hwdev->msix_entries[num_aeqs + num_ceqs + num_qps];
515
516         err = hinic_io_create_qps(func_to_io, base_qpn, num_qps,
517                                   sq_msix_entries, rq_msix_entries);
518         if (err) {
519                 dev_err(&pdev->dev, "Failed to create QPs\n");
520                 goto err_create_qps;
521         }
522
523         err = wait_for_db_state(hwdev);
524         if (err) {
525                 dev_warn(&pdev->dev, "db - disabled, try again\n");
526                 hinic_db_state_set(hwif, HINIC_DB_ENABLE);
527         }
528
529         err = set_hw_ioctxt(hwdev, HINIC_SQ_DEPTH, HINIC_RQ_DEPTH);
530         if (err) {
531                 dev_err(&pdev->dev, "Failed to set HW IO ctxt\n");
532                 goto err_hw_ioctxt;
533         }
534
535         return 0;
536
537 err_hw_ioctxt:
538         hinic_io_destroy_qps(func_to_io, num_qps);
539
540 err_create_qps:
541         hinic_io_free(func_to_io);
542         return err;
543 }
544
545 /**
546  * hinic_hwdev_ifdown - Closing the HW for passing IO
547  * @hwdev: the NIC HW device
548  *
549  **/
550 void hinic_hwdev_ifdown(struct hinic_hwdev *hwdev)
551 {
552         struct hinic_func_to_io *func_to_io = &hwdev->func_to_io;
553         struct hinic_cap *nic_cap = &hwdev->nic_cap;
554
555         clear_io_resources(hwdev);
556
557         hinic_io_destroy_qps(func_to_io, nic_cap->num_qps);
558         hinic_io_free(func_to_io);
559 }
560
561 /**
562  * hinic_hwdev_cb_register - register callback handler for MGMT events
563  * @hwdev: the NIC HW device
564  * @cmd: the mgmt event
565  * @handle: private data for the handler
566  * @handler: event handler
567  **/
568 void hinic_hwdev_cb_register(struct hinic_hwdev *hwdev,
569                              enum hinic_mgmt_msg_cmd cmd, void *handle,
570                              void (*handler)(void *handle, void *buf_in,
571                                              u16 in_size, void *buf_out,
572                                              u16 *out_size))
573 {
574         struct hinic_hwif *hwif = hwdev->hwif;
575         struct pci_dev *pdev = hwif->pdev;
576         struct hinic_pfhwdev *pfhwdev;
577         struct hinic_nic_cb *nic_cb;
578         u8 cmd_cb;
579
580         if (!HINIC_IS_PF(hwif) && !HINIC_IS_PPF(hwif)) {
581                 dev_err(&pdev->dev, "unsupported PCI Function type\n");
582                 return;
583         }
584
585         pfhwdev = container_of(hwdev, struct hinic_pfhwdev, hwdev);
586
587         cmd_cb = cmd - HINIC_MGMT_MSG_CMD_BASE;
588         nic_cb = &pfhwdev->nic_cb[cmd_cb];
589
590         nic_cb->handler = handler;
591         nic_cb->handle = handle;
592         nic_cb->cb_state = HINIC_CB_ENABLED;
593 }
594
595 /**
596  * hinic_hwdev_cb_unregister - unregister callback handler for MGMT events
597  * @hwdev: the NIC HW device
598  * @cmd: the mgmt event
599  **/
600 void hinic_hwdev_cb_unregister(struct hinic_hwdev *hwdev,
601                                enum hinic_mgmt_msg_cmd cmd)
602 {
603         struct hinic_hwif *hwif = hwdev->hwif;
604         struct pci_dev *pdev = hwif->pdev;
605         struct hinic_pfhwdev *pfhwdev;
606         struct hinic_nic_cb *nic_cb;
607         u8 cmd_cb;
608
609         if (!HINIC_IS_PF(hwif) && !HINIC_IS_PPF(hwif)) {
610                 dev_err(&pdev->dev, "unsupported PCI Function type\n");
611                 return;
612         }
613
614         pfhwdev = container_of(hwdev, struct hinic_pfhwdev, hwdev);
615
616         cmd_cb = cmd - HINIC_MGMT_MSG_CMD_BASE;
617         nic_cb = &pfhwdev->nic_cb[cmd_cb];
618
619         nic_cb->cb_state &= ~HINIC_CB_ENABLED;
620
621         while (nic_cb->cb_state & HINIC_CB_RUNNING)
622                 schedule();
623
624         nic_cb->handler = NULL;
625 }
626
627 /**
628  * nic_mgmt_msg_handler - nic mgmt event handler
629  * @handle: private data for the handler
630  * @buf_in: input buffer
631  * @in_size: input size
632  * @buf_out: output buffer
633  * @out_size: returned output size
634  **/
635 static void nic_mgmt_msg_handler(void *handle, u8 cmd, void *buf_in,
636                                  u16 in_size, void *buf_out, u16 *out_size)
637 {
638         struct hinic_pfhwdev *pfhwdev = handle;
639         enum hinic_cb_state cb_state;
640         struct hinic_nic_cb *nic_cb;
641         struct hinic_hwdev *hwdev;
642         struct hinic_hwif *hwif;
643         struct pci_dev *pdev;
644         u8 cmd_cb;
645
646         hwdev = &pfhwdev->hwdev;
647         hwif = hwdev->hwif;
648         pdev = hwif->pdev;
649
650         if ((cmd < HINIC_MGMT_MSG_CMD_BASE) ||
651             (cmd >= HINIC_MGMT_MSG_CMD_MAX)) {
652                 dev_err(&pdev->dev, "unknown L2NIC event, cmd = %d\n", cmd);
653                 return;
654         }
655
656         cmd_cb = cmd - HINIC_MGMT_MSG_CMD_BASE;
657
658         nic_cb = &pfhwdev->nic_cb[cmd_cb];
659
660         cb_state = cmpxchg(&nic_cb->cb_state,
661                            HINIC_CB_ENABLED,
662                            HINIC_CB_ENABLED | HINIC_CB_RUNNING);
663
664         if ((cb_state == HINIC_CB_ENABLED) && (nic_cb->handler))
665                 nic_cb->handler(nic_cb->handle, buf_in,
666                                 in_size, buf_out, out_size);
667         else
668                 dev_err(&pdev->dev, "Unhandled NIC Event %d\n", cmd);
669
670         nic_cb->cb_state &= ~HINIC_CB_RUNNING;
671 }
672
673 /**
674  * init_pfhwdev - Initialize the extended components of PF
675  * @pfhwdev: the HW device for PF
676  *
677  * Return 0 - success, negative - failure
678  **/
679 static int init_pfhwdev(struct hinic_pfhwdev *pfhwdev)
680 {
681         struct hinic_hwdev *hwdev = &pfhwdev->hwdev;
682         struct hinic_hwif *hwif = hwdev->hwif;
683         struct pci_dev *pdev = hwif->pdev;
684         int err;
685
686         err = hinic_pf_to_mgmt_init(&pfhwdev->pf_to_mgmt, hwif);
687         if (err) {
688                 dev_err(&pdev->dev, "Failed to initialize PF to MGMT channel\n");
689                 return err;
690         }
691
692         hinic_register_mgmt_msg_cb(&pfhwdev->pf_to_mgmt, HINIC_MOD_L2NIC,
693                                    pfhwdev, nic_mgmt_msg_handler);
694
695         hinic_set_pf_action(hwif, HINIC_PF_MGMT_ACTIVE);
696         return 0;
697 }
698
699 /**
700  * free_pfhwdev - Free the extended components of PF
701  * @pfhwdev: the HW device for PF
702  **/
703 static void free_pfhwdev(struct hinic_pfhwdev *pfhwdev)
704 {
705         struct hinic_hwdev *hwdev = &pfhwdev->hwdev;
706
707         hinic_set_pf_action(hwdev->hwif, HINIC_PF_MGMT_INIT);
708
709         hinic_unregister_mgmt_msg_cb(&pfhwdev->pf_to_mgmt, HINIC_MOD_L2NIC);
710
711         hinic_pf_to_mgmt_free(&pfhwdev->pf_to_mgmt);
712 }
713
714 /**
715  * hinic_init_hwdev - Initialize the NIC HW
716  * @pdev: the NIC pci device
717  *
718  * Return initialized NIC HW device
719  *
720  * Initialize the NIC HW device and return a pointer to it
721  **/
722 struct hinic_hwdev *hinic_init_hwdev(struct pci_dev *pdev)
723 {
724         struct hinic_pfhwdev *pfhwdev;
725         struct hinic_hwdev *hwdev;
726         struct hinic_hwif *hwif;
727         int err, num_aeqs;
728
729         hwif = devm_kzalloc(&pdev->dev, sizeof(*hwif), GFP_KERNEL);
730         if (!hwif)
731                 return ERR_PTR(-ENOMEM);
732
733         err = hinic_init_hwif(hwif, pdev);
734         if (err) {
735                 dev_err(&pdev->dev, "Failed to init HW interface\n");
736                 return ERR_PTR(err);
737         }
738
739         if (!HINIC_IS_PF(hwif) && !HINIC_IS_PPF(hwif)) {
740                 dev_err(&pdev->dev, "Unsupported PCI Function type\n");
741                 err = -EFAULT;
742                 goto err_func_type;
743         }
744
745         pfhwdev = devm_kzalloc(&pdev->dev, sizeof(*pfhwdev), GFP_KERNEL);
746         if (!pfhwdev) {
747                 err = -ENOMEM;
748                 goto err_pfhwdev_alloc;
749         }
750
751         hwdev = &pfhwdev->hwdev;
752         hwdev->hwif = hwif;
753
754         err = init_msix(hwdev);
755         if (err) {
756                 dev_err(&pdev->dev, "Failed to init msix\n");
757                 goto err_init_msix;
758         }
759
760         err = wait_for_outbound_state(hwdev);
761         if (err) {
762                 dev_warn(&pdev->dev, "outbound - disabled, try again\n");
763                 hinic_outbound_state_set(hwif, HINIC_OUTBOUND_ENABLE);
764         }
765
766         num_aeqs = HINIC_HWIF_NUM_AEQS(hwif);
767
768         err = hinic_aeqs_init(&hwdev->aeqs, hwif, num_aeqs,
769                               HINIC_DEFAULT_AEQ_LEN, HINIC_EQ_PAGE_SIZE,
770                               hwdev->msix_entries);
771         if (err) {
772                 dev_err(&pdev->dev, "Failed to init async event queues\n");
773                 goto err_aeqs_init;
774         }
775
776         err = init_pfhwdev(pfhwdev);
777         if (err) {
778                 dev_err(&pdev->dev, "Failed to init PF HW device\n");
779                 goto err_init_pfhwdev;
780         }
781
782         err = get_dev_cap(hwdev);
783         if (err) {
784                 dev_err(&pdev->dev, "Failed to get device capabilities\n");
785                 goto err_dev_cap;
786         }
787
788         err = init_fw_ctxt(hwdev);
789         if (err) {
790                 dev_err(&pdev->dev, "Failed to init function table\n");
791                 goto err_init_fw_ctxt;
792         }
793
794         err = set_resources_state(hwdev, HINIC_RES_ACTIVE);
795         if (err) {
796                 dev_err(&pdev->dev, "Failed to set resources state\n");
797                 goto err_resources_state;
798         }
799
800         return hwdev;
801
802 err_resources_state:
803 err_init_fw_ctxt:
804 err_dev_cap:
805         free_pfhwdev(pfhwdev);
806
807 err_init_pfhwdev:
808         hinic_aeqs_free(&hwdev->aeqs);
809
810 err_aeqs_init:
811         disable_msix(hwdev);
812
813 err_init_msix:
814 err_pfhwdev_alloc:
815 err_func_type:
816         hinic_free_hwif(hwif);
817         return ERR_PTR(err);
818 }
819
820 /**
821  * hinic_free_hwdev - Free the NIC HW device
822  * @hwdev: the NIC HW device
823  **/
824 void hinic_free_hwdev(struct hinic_hwdev *hwdev)
825 {
826         struct hinic_pfhwdev *pfhwdev = container_of(hwdev,
827                                                      struct hinic_pfhwdev,
828                                                      hwdev);
829
830         set_resources_state(hwdev, HINIC_RES_CLEAN);
831
832         free_pfhwdev(pfhwdev);
833
834         hinic_aeqs_free(&hwdev->aeqs);
835
836         disable_msix(hwdev);
837
838         hinic_free_hwif(hwdev->hwif);
839 }
840
841 /**
842  * hinic_hwdev_num_qps - return the number QPs available for use
843  * @hwdev: the NIC HW device
844  *
845  * Return number QPs available for use
846  **/
847 int hinic_hwdev_num_qps(struct hinic_hwdev *hwdev)
848 {
849         struct hinic_cap *nic_cap = &hwdev->nic_cap;
850
851         return nic_cap->num_qps;
852 }
853
854 /**
855  * hinic_hwdev_get_sq - get SQ
856  * @hwdev: the NIC HW device
857  * @i: the position of the SQ
858  *
859  * Return: the SQ in the i position
860  **/
861 struct hinic_sq *hinic_hwdev_get_sq(struct hinic_hwdev *hwdev, int i)
862 {
863         struct hinic_func_to_io *func_to_io = &hwdev->func_to_io;
864         struct hinic_qp *qp = &func_to_io->qps[i];
865
866         if (i >= hinic_hwdev_num_qps(hwdev))
867                 return NULL;
868
869         return &qp->sq;
870 }
871
872 /**
873  * hinic_hwdev_get_sq - get RQ
874  * @hwdev: the NIC HW device
875  * @i: the position of the RQ
876  *
877  * Return: the RQ in the i position
878  **/
879 struct hinic_rq *hinic_hwdev_get_rq(struct hinic_hwdev *hwdev, int i)
880 {
881         struct hinic_func_to_io *func_to_io = &hwdev->func_to_io;
882         struct hinic_qp *qp = &func_to_io->qps[i];
883
884         if (i >= hinic_hwdev_num_qps(hwdev))
885                 return NULL;
886
887         return &qp->rq;
888 }
889
890 /**
891  * hinic_hwdev_msix_cnt_set - clear message attribute counters for msix entry
892  * @hwdev: the NIC HW device
893  * @msix_index: msix_index
894  *
895  * Return 0 - Success, negative - Failure
896  **/
897 int hinic_hwdev_msix_cnt_set(struct hinic_hwdev *hwdev, u16 msix_index)
898 {
899         return hinic_msix_attr_cnt_clear(hwdev->hwif, msix_index);
900 }
901
902 /**
903  * hinic_hwdev_msix_set - set message attribute for msix entry
904  * @hwdev: the NIC HW device
905  * @msix_index: msix_index
906  * @pending_limit: the maximum pending interrupt events (unit 8)
907  * @coalesc_timer: coalesc period for interrupt (unit 8 us)
908  * @lli_timer: replenishing period for low latency credit (unit 8 us)
909  * @lli_credit_limit: maximum credits for low latency msix messages (unit 8)
910  * @resend_timer: maximum wait for resending msix (unit coalesc period)
911  *
912  * Return 0 - Success, negative - Failure
913  **/
914 int hinic_hwdev_msix_set(struct hinic_hwdev *hwdev, u16 msix_index,
915                          u8 pending_limit, u8 coalesc_timer,
916                          u8 lli_timer_cfg, u8 lli_credit_limit,
917                          u8 resend_timer)
918 {
919         return hinic_msix_attr_set(hwdev->hwif, msix_index,
920                                    pending_limit, coalesc_timer,
921                                    lli_timer_cfg, lli_credit_limit,
922                                    resend_timer);
923 }
924
925 /**
926  * hinic_hwdev_hw_ci_addr_set - set cons idx addr and attributes in HW for sq
927  * @hwdev: the NIC HW device
928  * @sq: send queue
929  * @pending_limit: the maximum pending update ci events (unit 8)
930  * @coalesc_timer: coalesc period for update ci (unit 8 us)
931  *
932  * Return 0 - Success, negative - Failure
933  **/
934 int hinic_hwdev_hw_ci_addr_set(struct hinic_hwdev *hwdev, struct hinic_sq *sq,
935                                u8 pending_limit, u8 coalesc_timer)
936 {
937         struct hinic_qp *qp = container_of(sq, struct hinic_qp, sq);
938         struct hinic_hwif *hwif = hwdev->hwif;
939         struct pci_dev *pdev = hwif->pdev;
940         struct hinic_pfhwdev *pfhwdev;
941         struct hinic_cmd_hw_ci hw_ci;
942
943         if (!HINIC_IS_PF(hwif) && !HINIC_IS_PPF(hwif)) {
944                 dev_err(&pdev->dev, "Unsupported PCI Function type\n");
945                 return -EINVAL;
946         }
947
948         hw_ci.dma_attr_off  = 0;
949         hw_ci.pending_limit = pending_limit;
950         hw_ci.coalesc_timer = coalesc_timer;
951
952         hw_ci.msix_en = 1;
953         hw_ci.msix_entry_idx = sq->msix_entry;
954
955         hw_ci.func_idx = HINIC_HWIF_FUNC_IDX(hwif);
956
957         hw_ci.sq_id = qp->q_id;
958
959         hw_ci.ci_addr = ADDR_IN_4BYTES(sq->hw_ci_dma_addr);
960
961         pfhwdev = container_of(hwdev, struct hinic_pfhwdev, hwdev);
962         return hinic_msg_to_mgmt(&pfhwdev->pf_to_mgmt,
963                                  HINIC_MOD_COMM,
964                                  HINIC_COMM_CMD_SQ_HI_CI_SET,
965                                  &hw_ci, sizeof(hw_ci), NULL,
966                                  NULL, HINIC_MGMT_MSG_SYNC);
967 }