]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
hinic3: HW management interfaces
authorFan Gong <gongfan1@huawei.com>
Fri, 12 Sep 2025 06:28:19 +0000 (14:28 +0800)
committerPaolo Abeni <pabeni@redhat.com>
Tue, 16 Sep 2025 08:49:06 +0000 (10:49 +0200)
Initialize hardware management config of irq, aeq and ceq.
These will send hardware messages to driver.

Co-developed-by: Zhu Yikai <zhuyikai1@h-partners.com>
Signed-off-by: Zhu Yikai <zhuyikai1@h-partners.com>
Signed-off-by: Fan Gong <gongfan1@huawei.com>
Link: https://patch.msgid.link/91c2ec3178bd1f28b4f9c509fd49b86a289ff79e.1757653621.git.zhuyikai1@h-partners.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
drivers/net/ethernet/huawei/hinic3/Makefile
drivers/net/ethernet/huawei/hinic3/hinic3_hw_cfg.c
drivers/net/ethernet/huawei/hinic3/hinic3_hw_cfg.h
drivers/net/ethernet/huawei/hinic3/hinic3_hwdev.c
drivers/net/ethernet/huawei/hinic3/hinic3_hwif.c
drivers/net/ethernet/huawei/hinic3/hinic3_lld.c
drivers/net/ethernet/huawei/hinic3/hinic3_mgmt.c [new file with mode: 0644]
drivers/net/ethernet/huawei/hinic3/hinic3_mgmt.h

index 2a0ed8e2c63e96e673d986b8dc41a0544b5fd960..a9f055cfef523079a9acf6b2b2fa2cd65fa73a40 100644 (file)
@@ -14,6 +14,7 @@ hinic3-objs := hinic3_cmdq.o \
               hinic3_lld.o \
               hinic3_main.o \
               hinic3_mbox.o \
+              hinic3_mgmt.o \
               hinic3_netdev_ops.o \
               hinic3_nic_cfg.o \
               hinic3_nic_io.o \
index 0599fc4f3fb0793da8271ab0576331b18514322a..8db5e2c9ff10fa849158d6c5a51c6735646ef741 100644 (file)
@@ -8,6 +8,108 @@
 #include "hinic3_hwif.h"
 #include "hinic3_mbox.h"
 
+static int hinic3_init_irq_info(struct hinic3_hwdev *hwdev)
+{
+       struct hinic3_cfg_mgmt_info *cfg_mgmt = hwdev->cfg_mgmt;
+       struct hinic3_hwif *hwif = hwdev->hwif;
+       u16 intr_num = hwif->attr.num_irqs;
+       struct hinic3_irq_info *irq_info;
+       u16 intr_needed;
+
+       intr_needed = hwif->attr.msix_flex_en ? (hwif->attr.num_aeqs +
+                     hwif->attr.num_ceqs + hwif->attr.num_sq) : intr_num;
+       if (intr_needed > intr_num) {
+               dev_warn(hwdev->dev, "Irq num cfg %d is less than the needed irq num %d msix_flex_en %d\n",
+                        intr_num, intr_needed, hwdev->hwif->attr.msix_flex_en);
+               intr_needed = intr_num;
+       }
+
+       irq_info = &cfg_mgmt->irq_info;
+       irq_info->irq = kcalloc(intr_num, sizeof(struct hinic3_irq),
+                               GFP_KERNEL);
+       if (!irq_info->irq)
+               return -ENOMEM;
+
+       irq_info->num_irq_hw = intr_needed;
+       mutex_init(&irq_info->irq_mutex);
+
+       return 0;
+}
+
+static int hinic3_init_irq_alloc_info(struct hinic3_hwdev *hwdev)
+{
+       struct hinic3_cfg_mgmt_info *cfg_mgmt = hwdev->cfg_mgmt;
+       struct hinic3_irq *irq = cfg_mgmt->irq_info.irq;
+       u16 nreq = cfg_mgmt->irq_info.num_irq_hw;
+       struct pci_dev *pdev = hwdev->pdev;
+       int actual_irq;
+       u16 i;
+
+       actual_irq = pci_alloc_irq_vectors(pdev, 2, nreq, PCI_IRQ_MSIX);
+       if (actual_irq < 0) {
+               dev_err(hwdev->dev, "Alloc msix entries with threshold 2 failed. actual_irq: %d\n",
+                       actual_irq);
+               return -ENOMEM;
+       }
+
+       nreq = actual_irq;
+       cfg_mgmt->irq_info.num_irq = nreq;
+
+       for (i = 0; i < nreq; ++i) {
+               irq[i].msix_entry_idx = i;
+               irq[i].irq_id = pci_irq_vector(pdev, i);
+               irq[i].allocated = false;
+       }
+
+       return 0;
+}
+
+int hinic3_init_cfg_mgmt(struct hinic3_hwdev *hwdev)
+{
+       struct hinic3_cfg_mgmt_info *cfg_mgmt;
+       int err;
+
+       cfg_mgmt = kzalloc(sizeof(*cfg_mgmt), GFP_KERNEL);
+       if (!cfg_mgmt)
+               return -ENOMEM;
+
+       hwdev->cfg_mgmt = cfg_mgmt;
+
+       err = hinic3_init_irq_info(hwdev);
+       if (err) {
+               dev_err(hwdev->dev, "Failed to init hinic3_irq_mgmt_info, err: %d\n",
+                       err);
+               goto err_free_cfg_mgmt;
+       }
+
+       err = hinic3_init_irq_alloc_info(hwdev);
+       if (err) {
+               dev_err(hwdev->dev, "Failed to init hinic3_irq_info, err: %d\n",
+                       err);
+               goto err_free_irq_info;
+       }
+
+       return 0;
+
+err_free_irq_info:
+       kfree(cfg_mgmt->irq_info.irq);
+       cfg_mgmt->irq_info.irq = NULL;
+err_free_cfg_mgmt:
+       kfree(cfg_mgmt);
+
+       return err;
+}
+
+void hinic3_free_cfg_mgmt(struct hinic3_hwdev *hwdev)
+{
+       struct hinic3_cfg_mgmt_info *cfg_mgmt = hwdev->cfg_mgmt;
+
+       pci_free_irq_vectors(hwdev->pdev);
+       kfree(cfg_mgmt->irq_info.irq);
+       cfg_mgmt->irq_info.irq = NULL;
+       kfree(cfg_mgmt);
+}
+
 int hinic3_alloc_irqs(struct hinic3_hwdev *hwdev, u16 num,
                      struct msix_entry *alloc_arr, u16 *act_num)
 {
index e017b1ae9f0544f088302370822a2f2035344da7..5978cbd56fb286dafe98722d2c0d6091913be81d 100644 (file)
@@ -42,6 +42,9 @@ struct hinic3_cfg_mgmt_info {
        struct hinic3_dev_cap  cap;
 };
 
+int hinic3_init_cfg_mgmt(struct hinic3_hwdev *hwdev);
+void hinic3_free_cfg_mgmt(struct hinic3_hwdev *hwdev);
+
 int hinic3_alloc_irqs(struct hinic3_hwdev *hwdev, u16 num,
                      struct msix_entry *alloc_arr, u16 *act_num);
 void hinic3_free_irq(struct hinic3_hwdev *hwdev, u32 irq_id);
index 09e8b0dce7b3e659da466bdd65d3a70c1c66323c..d941b365b5746c2022322d41cc16f64ba9a95133 100644 (file)
@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0
 // Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved.
 
+#include "hinic3_eqs.h"
 #include "hinic3_hw_comm.h"
 #include "hinic3_hwdev.h"
 #include "hinic3_hwif.h"
@@ -46,8 +47,16 @@ int hinic3_init_hwdev(struct pci_dev *pdev)
                goto err_free_hwif;
        }
 
+       err = hinic3_init_cfg_mgmt(hwdev);
+       if (err) {
+               dev_err(hwdev->dev, "Failed to init config mgmt\n");
+               goto err_destroy_workqueue;
+       }
+
        return 0;
 
+err_destroy_workqueue:
+       destroy_workqueue(hwdev->workq);
 err_free_hwif:
        hinic3_free_hwif(hwdev);
 err_free_hwdev:
@@ -59,6 +68,7 @@ err_free_hwdev:
 
 void hinic3_free_hwdev(struct hinic3_hwdev *hwdev)
 {
+       hinic3_free_cfg_mgmt(hwdev);
        destroy_workqueue(hwdev->workq);
        hinic3_free_hwif(hwdev);
        kfree(hwdev);
index 90b8e211587fc462cec53471f5b85d1e47c2712f..f07bcab51ba58ebbf1717f19ac06e452eab74ece 100644 (file)
@@ -144,6 +144,18 @@ static int init_hwif_attr(struct hinic3_hwdev *hwdev)
 
        set_hwif_attr(&hwif->attr, attr0, attr1, attr2, attr3, attr6);
 
+       if (!hwif->attr.num_ceqs) {
+               dev_err(hwdev->dev, "Ceq num cfg in fw is zero\n");
+               return -EFAULT;
+       }
+
+       if (!hwif->attr.num_irqs) {
+               dev_err(hwdev->dev,
+                       "Irq num cfg in fw is zero, msix_flex_en %d\n",
+                       hwif->attr.msix_flex_en);
+               return -EFAULT;
+       }
+
        return 0;
 }
 
index 9f3d6af71cc8867edd210e72af3c7aaac5a88479..10477fb9cc340e13eec55023c4f3978190258bd4 100644 (file)
@@ -308,6 +308,7 @@ static void hinic3_func_uninit(struct pci_dev *pdev)
 {
        struct hinic3_pcidev *pci_adapter = pci_get_drvdata(pdev);
 
+       hinic3_flush_mgmt_workq(pci_adapter->hwdev);
        hinic3_detach_aux_devices(pci_adapter->hwdev);
        hinic3_free_hwdev(pci_adapter->hwdev);
 }
diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_mgmt.c b/drivers/net/ethernet/huawei/hinic3/hinic3_mgmt.c
new file mode 100644 (file)
index 0000000..c38d10c
--- /dev/null
@@ -0,0 +1,21 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved.
+
+#include "hinic3_eqs.h"
+#include "hinic3_hwdev.h"
+#include "hinic3_mbox.h"
+#include "hinic3_mgmt.h"
+
+void hinic3_flush_mgmt_workq(struct hinic3_hwdev *hwdev)
+{
+       if (hwdev->aeqs)
+               flush_workqueue(hwdev->aeqs->workq);
+}
+
+void hinic3_mgmt_msg_aeqe_handler(struct hinic3_hwdev *hwdev, u8 *header,
+                                 u8 size)
+{
+       if (MBOX_MSG_HEADER_GET(*(__force __le64 *)header, SOURCE) ==
+                               MBOX_MSG_FROM_MBOX)
+               hinic3_mbox_func_aeqe_handler(hwdev, header, size);
+}
index 4edabeb32112214a716093e92832c02fbb5f0cff..bbef3b32a6eca5632b0b730dc372ea414e1f0410 100644 (file)
@@ -9,5 +9,7 @@
 struct hinic3_hwdev;
 
 void hinic3_flush_mgmt_workq(struct hinic3_hwdev *hwdev);
+void hinic3_mgmt_msg_aeqe_handler(struct hinic3_hwdev *hwdev,
+                                 u8 *header, u8 size);
 
 #endif