mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-14 17:06:24 -04:00
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:
@@ -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 \
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
21
drivers/net/ethernet/huawei/hinic3/hinic3_mgmt.c
Normal file
21
drivers/net/ethernet/huawei/hinic3/hinic3_mgmt.c
Normal 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);
|
||||
}
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user