hc
2023-12-09 b22da3d8526a935aa31e086e63f60ff3246cb61c
kernel/drivers/net/ethernet/huawei/hinic/hinic_hw_eqs.c
....@@ -1,16 +1,7 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * Huawei HiNIC PCI Express Linux driver
34 * 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
- *
145 */
156
167 #include <linux/kernel.h>
....@@ -26,6 +17,7 @@
2617 #include <asm/byteorder.h>
2718 #include <asm/barrier.h>
2819
20
+#include "hinic_hw_dev.h"
2921 #include "hinic_hw_csr.h"
3022 #include "hinic_hw_if.h"
3123 #include "hinic_hw_eqs.h"
....@@ -114,7 +106,7 @@
114106 * @aeqs: pointer to Async eqs of the chip
115107 * @event: aeq event to register callback for it
116108 * @handle: private data will be used by the callback
117
- * @hw_handler: callback function
109
+ * @hwe_handler: callback function
118110 **/
119111 void hinic_aeq_register_hw_cb(struct hinic_aeqs *aeqs,
120112 enum hinic_aeq_type event, void *handle,
....@@ -196,8 +188,9 @@
196188 /**
197189 * eq_update_ci - update the HW cons idx of event queue
198190 * @eq: the event queue to update the cons idx for
191
+ * @arm_state: the arm bit value of eq's interrupt
199192 **/
200
-static void eq_update_ci(struct hinic_eq *eq)
193
+static void eq_update_ci(struct hinic_eq *eq, u32 arm_state)
201194 {
202195 u32 val, addr = EQ_CONS_IDX_REG_ADDR(eq);
203196
....@@ -211,7 +204,7 @@
211204
212205 val |= HINIC_EQ_CI_SET(eq->cons_idx, IDX) |
213206 HINIC_EQ_CI_SET(eq->wrapped, WRAPPED) |
214
- HINIC_EQ_CI_SET(EQ_ARMED, INT_ARMED);
207
+ HINIC_EQ_CI_SET(arm_state, INT_ARMED);
215208
216209 val |= HINIC_EQ_CI_SET(eq_cons_idx_checksum_set(val), XOR_CHKSUM);
217210
....@@ -243,6 +236,8 @@
243236 /* HW toggles the wrapped bit, when it adds eq element */
244237 if (HINIC_EQ_ELEM_DESC_GET(aeqe_desc, WRAPPED) == eq->wrapped)
245238 break;
239
+
240
+ dma_rmb();
246241
247242 event = HINIC_EQ_ELEM_DESC_GET(aeqe_desc, TYPE);
248243 if (event >= HINIC_MAX_AEQ_EVENTS) {
....@@ -356,7 +351,7 @@
356351 else if (eq->type == HINIC_CEQ)
357352 ceq_irq_handler(eq);
358353
359
- eq_update_ci(eq);
354
+ eq_update_ci(eq, EQ_ARMED);
360355 }
361356
362357 /**
....@@ -374,11 +369,11 @@
374369
375370 /**
376371 * ceq_tasklet - the tasklet of the EQ that received the event
377
- * @ceq_data: the eq
372
+ * @t: the tasklet struct pointer
378373 **/
379
-static void ceq_tasklet(unsigned long ceq_data)
374
+static void ceq_tasklet(struct tasklet_struct *t)
380375 {
381
- struct hinic_eq *ceq = (struct hinic_eq *)ceq_data;
376
+ struct hinic_eq *ceq = from_tasklet(ceq, t, ceq_tasklet);
382377
383378 eq_irq_handler(ceq);
384379 }
....@@ -423,11 +418,11 @@
423418 return IRQ_HANDLED;
424419 }
425420
426
-static void set_ctrl0(struct hinic_eq *eq)
421
+static u32 get_ctrl0_val(struct hinic_eq *eq, u32 addr)
427422 {
428423 struct msix_entry *msix_entry = &eq->msix_entry;
429424 enum hinic_eq_type type = eq->type;
430
- u32 addr, val, ctrl0;
425
+ u32 val, ctrl0;
431426
432427 if (type == HINIC_AEQ) {
433428 /* RMW Ctrl0 */
....@@ -447,9 +442,7 @@
447442 HINIC_AEQ_CTRL_0_SET(EQ_INT_MODE_ARMED, INT_MODE);
448443
449444 val |= ctrl0;
450
-
451
- hinic_hwif_write_reg(eq->hwif, addr, val);
452
- } else if (type == HINIC_CEQ) {
445
+ } else {
453446 /* RMW Ctrl0 */
454447 addr = HINIC_CSR_CEQ_CTRL_0_ADDR(eq->q_id);
455448
....@@ -469,16 +462,28 @@
469462 HINIC_CEQ_CTRL_0_SET(EQ_INT_MODE_ARMED, INTR_MODE);
470463
471464 val |= ctrl0;
472
-
473
- hinic_hwif_write_reg(eq->hwif, addr, val);
474465 }
466
+ return val;
475467 }
476468
477
-static void set_ctrl1(struct hinic_eq *eq)
469
+static void set_ctrl0(struct hinic_eq *eq)
478470 {
471
+ u32 val, addr;
472
+
473
+ if (eq->type == HINIC_AEQ)
474
+ addr = HINIC_CSR_AEQ_CTRL_0_ADDR(eq->q_id);
475
+ else
476
+ addr = HINIC_CSR_CEQ_CTRL_0_ADDR(eq->q_id);
477
+
478
+ val = get_ctrl0_val(eq, addr);
479
+
480
+ hinic_hwif_write_reg(eq->hwif, addr, val);
481
+}
482
+
483
+static u32 get_ctrl1_val(struct hinic_eq *eq, u32 addr)
484
+{
485
+ u32 page_size_val, elem_size, val, ctrl1;
479486 enum hinic_eq_type type = eq->type;
480
- u32 page_size_val, elem_size;
481
- u32 addr, val, ctrl1;
482487
483488 if (type == HINIC_AEQ) {
484489 /* RMW Ctrl1 */
....@@ -498,9 +503,7 @@
498503 HINIC_AEQ_CTRL_1_SET(page_size_val, PAGE_SIZE);
499504
500505 val |= ctrl1;
501
-
502
- hinic_hwif_write_reg(eq->hwif, addr, val);
503
- } else if (type == HINIC_CEQ) {
506
+ } else {
504507 /* RMW Ctrl1 */
505508 addr = HINIC_CSR_CEQ_CTRL_1_ADDR(eq->q_id);
506509
....@@ -515,19 +518,70 @@
515518 HINIC_CEQ_CTRL_1_SET(page_size_val, PAGE_SIZE);
516519
517520 val |= ctrl1;
518
-
519
- hinic_hwif_write_reg(eq->hwif, addr, val);
520521 }
522
+ return val;
523
+}
524
+
525
+static void set_ctrl1(struct hinic_eq *eq)
526
+{
527
+ u32 addr, val;
528
+
529
+ if (eq->type == HINIC_AEQ)
530
+ addr = HINIC_CSR_AEQ_CTRL_1_ADDR(eq->q_id);
531
+ else
532
+ addr = HINIC_CSR_CEQ_CTRL_1_ADDR(eq->q_id);
533
+
534
+ val = get_ctrl1_val(eq, addr);
535
+
536
+ hinic_hwif_write_reg(eq->hwif, addr, val);
537
+}
538
+
539
+static int set_ceq_ctrl_reg(struct hinic_eq *eq)
540
+{
541
+ struct hinic_ceq_ctrl_reg ceq_ctrl = {0};
542
+ struct hinic_hwdev *hwdev = eq->hwdev;
543
+ u16 out_size = sizeof(ceq_ctrl);
544
+ u16 in_size = sizeof(ceq_ctrl);
545
+ struct hinic_pfhwdev *pfhwdev;
546
+ u32 addr;
547
+ int err;
548
+
549
+ pfhwdev = container_of(hwdev, struct hinic_pfhwdev, hwdev);
550
+
551
+ addr = HINIC_CSR_CEQ_CTRL_0_ADDR(eq->q_id);
552
+ ceq_ctrl.ctrl0 = get_ctrl0_val(eq, addr);
553
+ addr = HINIC_CSR_CEQ_CTRL_1_ADDR(eq->q_id);
554
+ ceq_ctrl.ctrl1 = get_ctrl1_val(eq, addr);
555
+
556
+ ceq_ctrl.func_id = HINIC_HWIF_FUNC_IDX(hwdev->hwif);
557
+ ceq_ctrl.q_id = eq->q_id;
558
+
559
+ err = hinic_msg_to_mgmt(&pfhwdev->pf_to_mgmt, HINIC_MOD_COMM,
560
+ HINIC_COMM_CMD_CEQ_CTRL_REG_WR_BY_UP,
561
+ &ceq_ctrl, in_size,
562
+ &ceq_ctrl, &out_size, HINIC_MGMT_MSG_SYNC);
563
+ if (err || !out_size || ceq_ctrl.status) {
564
+ dev_err(&hwdev->hwif->pdev->dev,
565
+ "Failed to set ceq %d ctrl reg, err: %d status: 0x%x, out_size: 0x%x\n",
566
+ eq->q_id, err, ceq_ctrl.status, out_size);
567
+ return -EFAULT;
568
+ }
569
+
570
+ return 0;
521571 }
522572
523573 /**
524574 * set_eq_ctrls - setting eq's ctrl registers
525575 * @eq: the Event Queue for setting
526576 **/
527
-static void set_eq_ctrls(struct hinic_eq *eq)
577
+static int set_eq_ctrls(struct hinic_eq *eq)
528578 {
579
+ if (HINIC_IS_VF(eq->hwif) && eq->type == HINIC_CEQ)
580
+ return set_ceq_ctrl_reg(eq);
581
+
529582 set_ctrl0(eq);
530583 set_ctrl1(eq);
584
+ return 0;
531585 }
532586
533587 /**
....@@ -577,26 +631,25 @@
577631 struct hinic_hwif *hwif = eq->hwif;
578632 struct pci_dev *pdev = hwif->pdev;
579633 u32 init_val, addr, val;
580
- size_t addr_size;
581634 int err, pg;
582635
583
- addr_size = eq->num_pages * sizeof(*eq->dma_addr);
584
- eq->dma_addr = devm_kzalloc(&pdev->dev, addr_size, GFP_KERNEL);
636
+ eq->dma_addr = devm_kcalloc(&pdev->dev, eq->num_pages,
637
+ sizeof(*eq->dma_addr), GFP_KERNEL);
585638 if (!eq->dma_addr)
586639 return -ENOMEM;
587640
588
- addr_size = eq->num_pages * sizeof(*eq->virt_addr);
589
- eq->virt_addr = devm_kzalloc(&pdev->dev, addr_size, GFP_KERNEL);
641
+ eq->virt_addr = devm_kcalloc(&pdev->dev, eq->num_pages,
642
+ sizeof(*eq->virt_addr), GFP_KERNEL);
590643 if (!eq->virt_addr) {
591644 err = -ENOMEM;
592645 goto err_virt_addr_alloc;
593646 }
594647
595648 for (pg = 0; pg < eq->num_pages; pg++) {
596
- eq->virt_addr[pg] = dma_zalloc_coherent(&pdev->dev,
597
- eq->page_size,
598
- &eq->dma_addr[pg],
599
- GFP_KERNEL);
649
+ eq->virt_addr[pg] = dma_alloc_coherent(&pdev->dev,
650
+ eq->page_size,
651
+ &eq->dma_addr[pg],
652
+ GFP_KERNEL);
600653 if (!eq->virt_addr[pg]) {
601654 err = -ENOMEM;
602655 goto err_dma_alloc;
....@@ -710,8 +763,13 @@
710763 return -EINVAL;
711764 }
712765
713
- set_eq_ctrls(eq);
714
- eq_update_ci(eq);
766
+ err = set_eq_ctrls(eq);
767
+ if (err) {
768
+ dev_err(&pdev->dev, "Failed to set eq ctrls\n");
769
+ return err;
770
+ }
771
+
772
+ eq_update_ci(eq, EQ_ARMED);
715773
716774 err = alloc_eq_pages(eq);
717775 if (err) {
....@@ -724,8 +782,7 @@
724782
725783 INIT_WORK(&aeq_work->work, eq_irq_work);
726784 } else if (type == HINIC_CEQ) {
727
- tasklet_init(&eq->ceq_tasklet, ceq_tasklet,
728
- (unsigned long)eq);
785
+ tasklet_setup(&eq->ceq_tasklet, ceq_tasklet);
729786 }
730787
731788 /* set the attributes of the msix entry */
....@@ -736,12 +793,15 @@
736793 HINIC_EQ_MSIX_LLI_CREDIT_LIMIT_DEFAULT,
737794 HINIC_EQ_MSIX_RESEND_TIMER_DEFAULT);
738795
739
- if (type == HINIC_AEQ)
740
- err = request_irq(entry.vector, aeq_interrupt, 0,
741
- "hinic_aeq", eq);
742
- else if (type == HINIC_CEQ)
743
- err = request_irq(entry.vector, ceq_interrupt, 0,
744
- "hinic_ceq", eq);
796
+ if (type == HINIC_AEQ) {
797
+ snprintf(eq->irq_name, sizeof(eq->irq_name), "hinic_aeq%d@pci:%s", eq->q_id,
798
+ pci_name(pdev));
799
+ err = request_irq(entry.vector, aeq_interrupt, 0, eq->irq_name, eq);
800
+ } else if (type == HINIC_CEQ) {
801
+ snprintf(eq->irq_name, sizeof(eq->irq_name), "hinic_ceq%d@pci:%s", eq->q_id,
802
+ pci_name(pdev));
803
+ err = request_irq(entry.vector, ceq_interrupt, 0, eq->irq_name, eq);
804
+ }
745805
746806 if (err) {
747807 dev_err(&pdev->dev, "Failed to request irq for the EQ\n");
....@@ -761,17 +821,27 @@
761821 **/
762822 static void remove_eq(struct hinic_eq *eq)
763823 {
764
- struct msix_entry *entry = &eq->msix_entry;
765
-
766
- free_irq(entry->vector, eq);
824
+ hinic_set_msix_state(eq->hwif, eq->msix_entry.entry,
825
+ HINIC_MSIX_DISABLE);
826
+ free_irq(eq->msix_entry.vector, eq);
767827
768828 if (eq->type == HINIC_AEQ) {
769829 struct hinic_eq_work *aeq_work = &eq->aeq_work;
770830
771831 cancel_work_sync(&aeq_work->work);
832
+ /* clear aeq_len to avoid hw access host memory */
833
+ hinic_hwif_write_reg(eq->hwif,
834
+ HINIC_CSR_AEQ_CTRL_1_ADDR(eq->q_id), 0);
772835 } else if (eq->type == HINIC_CEQ) {
773836 tasklet_kill(&eq->ceq_tasklet);
837
+ /* clear ceq_len to avoid hw access host memory */
838
+ hinic_hwif_write_reg(eq->hwif,
839
+ HINIC_CSR_CEQ_CTRL_1_ADDR(eq->q_id), 0);
774840 }
841
+
842
+ /* update cons_idx to avoid invalid interrupt */
843
+ eq->cons_idx = hinic_hwif_read_reg(eq->hwif, EQ_PROD_IDX_REG_ADDR(eq));
844
+ eq_update_ci(eq, EQ_NOT_ARMED);
775845
776846 free_eq_pages(eq);
777847 }
....@@ -856,6 +926,7 @@
856926 ceqs->num_ceqs = num_ceqs;
857927
858928 for (q_id = 0; q_id < num_ceqs; q_id++) {
929
+ ceqs->ceq[q_id].hwdev = ceqs->hwdev;
859930 err = init_eq(&ceqs->ceq[q_id], hwif, HINIC_CEQ, q_id, q_len,
860931 page_size, msix_entries[q_id]);
861932 if (err) {
....@@ -884,3 +955,42 @@
884955 for (q_id = 0; q_id < ceqs->num_ceqs; q_id++)
885956 remove_eq(&ceqs->ceq[q_id]);
886957 }
958
+
959
+void hinic_dump_ceq_info(struct hinic_hwdev *hwdev)
960
+{
961
+ struct hinic_eq *eq = NULL;
962
+ u32 addr, ci, pi;
963
+ int q_id;
964
+
965
+ for (q_id = 0; q_id < hwdev->func_to_io.ceqs.num_ceqs; q_id++) {
966
+ eq = &hwdev->func_to_io.ceqs.ceq[q_id];
967
+ addr = EQ_CONS_IDX_REG_ADDR(eq);
968
+ ci = hinic_hwif_read_reg(hwdev->hwif, addr);
969
+ addr = EQ_PROD_IDX_REG_ADDR(eq);
970
+ pi = hinic_hwif_read_reg(hwdev->hwif, addr);
971
+ dev_err(&hwdev->hwif->pdev->dev, "Ceq id: %d, ci: 0x%08x, sw_ci: 0x%08x, pi: 0x%x, tasklet_state: 0x%lx, wrap: %d, ceqe: 0x%x\n",
972
+ q_id, ci, eq->cons_idx, pi,
973
+ eq->ceq_tasklet.state,
974
+ eq->wrapped, be32_to_cpu(*(__be32 *)(GET_CURR_CEQ_ELEM(eq))));
975
+ }
976
+}
977
+
978
+void hinic_dump_aeq_info(struct hinic_hwdev *hwdev)
979
+{
980
+ struct hinic_aeq_elem *aeqe_pos = NULL;
981
+ struct hinic_eq *eq = NULL;
982
+ u32 addr, ci, pi;
983
+ int q_id;
984
+
985
+ for (q_id = 0; q_id < hwdev->aeqs.num_aeqs; q_id++) {
986
+ eq = &hwdev->aeqs.aeq[q_id];
987
+ addr = EQ_CONS_IDX_REG_ADDR(eq);
988
+ ci = hinic_hwif_read_reg(hwdev->hwif, addr);
989
+ addr = EQ_PROD_IDX_REG_ADDR(eq);
990
+ pi = hinic_hwif_read_reg(hwdev->hwif, addr);
991
+ aeqe_pos = GET_CURR_AEQ_ELEM(eq);
992
+ dev_err(&hwdev->hwif->pdev->dev, "Aeq id: %d, ci: 0x%08x, pi: 0x%x, work_state: 0x%x, wrap: %d, desc: 0x%x\n",
993
+ q_id, ci, pi, work_busy(&eq->aeq_work.work),
994
+ eq->wrapped, be32_to_cpu(aeqe_pos->desc));
995
+ }
996
+}