hinic3: HW management interfaces

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>
This commit is contained in:
Fan Gong
2025-09-12 14:28:19 +08:00
committed by Paolo Abeni
parent cdb096c41b
commit 8a1c655f55
8 changed files with 152 additions and 0 deletions

View 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 \

View 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)
{

View 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);

View 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 @@ int hinic3_init_hwdev(struct pci_dev *pdev)
void hinic3_free_hwdev(struct hinic3_hwdev *hwdev)
{
hinic3_free_cfg_mgmt(hwdev);
destroy_workqueue(hwdev->workq);
hinic3_free_hwif(hwdev);
kfree(hwdev);

View 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;
}

View 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);
}

View File

@@ -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);
}

View 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