From 08f87f769b595151be1afeff53e144f543faa614 Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Wed, 06 Dec 2023 09:51:13 +0000 Subject: [PATCH] add dts config --- kernel/drivers/net/ethernet/huawei/hinic/hinic_hw_if.c | 141 ++++++++++++++++++++++++++++++++++++++++------ 1 files changed, 122 insertions(+), 19 deletions(-) diff --git a/kernel/drivers/net/ethernet/huawei/hinic/hinic_hw_if.c b/kernel/drivers/net/ethernet/huawei/hinic/hinic_hw_if.c index 823a170..efbaed3 100644 --- a/kernel/drivers/net/ethernet/huawei/hinic/hinic_hw_if.c +++ b/kernel/drivers/net/ethernet/huawei/hinic/hinic_hw_if.c @@ -1,16 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Huawei HiNIC PCI Express Linux driver * Copyright(c) 2017 Huawei Technologies Co., Ltd - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * */ #include <linux/pci.h> @@ -19,6 +10,7 @@ #include <linux/io.h> #include <linux/types.h> #include <linux/bitops.h> +#include <linux/delay.h> #include "hinic_hw_csr.h" #include "hinic_hw_if.h" @@ -26,6 +18,10 @@ #define PCIE_ATTR_ENTRY 0 #define VALID_MSIX_IDX(attr, msix_index) ((msix_index) < (attr)->num_irqs) + +#define WAIT_HWIF_READY_TIMEOUT 10000 + +#define HINIC_SELFTEST_RESULT 0x883C /** * hinic_msix_attr_set - set message attribute for msix entry @@ -124,8 +120,12 @@ **/ void hinic_set_pf_action(struct hinic_hwif *hwif, enum hinic_pf_action action) { - u32 attr5 = hinic_hwif_read_reg(hwif, HINIC_CSR_FUNC_ATTR5_ADDR); + u32 attr5; + if (HINIC_IS_VF(hwif)) + return; + + attr5 = hinic_hwif_read_reg(hwif, HINIC_CSR_FUNC_ATTR5_ADDR); attr5 = HINIC_FA5_CLEAR(attr5, PF_ACTION); attr5 |= HINIC_FA5_SET(action, PF_ACTION); @@ -168,6 +168,22 @@ hinic_hwif_write_reg(hwif, HINIC_CSR_FUNC_ATTR4_ADDR, attr4); } +void hinic_set_msix_state(struct hinic_hwif *hwif, u16 msix_idx, + enum hinic_msix_state flag) +{ + u32 offset = msix_idx * HINIC_PCI_MSIX_ENTRY_SIZE + + HINIC_PCI_MSIX_ENTRY_VECTOR_CTRL; + u32 mask_bits; + + mask_bits = readl(hwif->intr_regs_base + offset); + mask_bits &= ~HINIC_PCI_MSIX_ENTRY_CTRL_MASKBIT; + + if (flag) + mask_bits |= HINIC_PCI_MSIX_ENTRY_CTRL_MASKBIT; + + writel(mask_bits, hwif->intr_regs_base + offset); +} + /** * hwif_ready - test if the HW is ready for use * @hwif: the HW interface of a pci function device @@ -176,18 +192,37 @@ **/ static int hwif_ready(struct hinic_hwif *hwif) { - struct pci_dev *pdev = hwif->pdev; u32 addr, attr1; addr = HINIC_CSR_FUNC_ATTR1_ADDR; attr1 = hinic_hwif_read_reg(hwif, addr); - if (!HINIC_FA1_GET(attr1, INIT_STATUS)) { - dev_err(&pdev->dev, "hwif status is not ready\n"); - return -EFAULT; + if (!HINIC_FA1_GET(attr1, MGMT_INIT_STATUS)) + return -EBUSY; + + if (HINIC_IS_VF(hwif)) { + if (!HINIC_FA1_GET(attr1, PF_INIT_STATUS)) + return -EBUSY; } return 0; +} + +static int wait_hwif_ready(struct hinic_hwif *hwif) +{ + unsigned long timeout = 0; + + do { + if (!hwif_ready(hwif)) + return 0; + + usleep_range(999, 1000); + timeout++; + } while (timeout <= WAIT_HWIF_READY_TIMEOUT); + + dev_err(&hwif->pdev->dev, "Wait for hwif timeout\n"); + + return -EBUSY; } /** @@ -195,8 +230,10 @@ * @hwif: the HW interface of a pci function device * @attr0: the first attribute that was read from the hw * @attr1: the second attribute that was read from the hw + * @attr2: the third attribute that was read from the hw **/ -static void set_hwif_attr(struct hinic_hwif *hwif, u32 attr0, u32 attr1) +static void set_hwif_attr(struct hinic_hwif *hwif, u32 attr0, u32 attr1, + u32 attr2) { hwif->attr.func_idx = HINIC_FA0_GET(attr0, FUNC_IDX); hwif->attr.pf_idx = HINIC_FA0_GET(attr0, PF_IDX); @@ -207,6 +244,8 @@ hwif->attr.num_ceqs = BIT(HINIC_FA1_GET(attr1, CEQS_PER_FUNC)); hwif->attr.num_irqs = BIT(HINIC_FA1_GET(attr1, IRQS_PER_FUNC)); hwif->attr.num_dma_attr = BIT(HINIC_FA1_GET(attr1, DMA_ATTR_PER_FUNC)); + hwif->attr.global_vf_id_of_pf = HINIC_FA2_GET(attr2, + GLOBAL_VF_ID_OF_PF); } /** @@ -215,7 +254,7 @@ **/ static void read_hwif_attr(struct hinic_hwif *hwif) { - u32 addr, attr0, attr1; + u32 addr, attr0, attr1, attr2; addr = HINIC_CSR_FUNC_ATTR0_ADDR; attr0 = hinic_hwif_read_reg(hwif, addr); @@ -223,7 +262,10 @@ addr = HINIC_CSR_FUNC_ATTR1_ADDR; attr1 = hinic_hwif_read_reg(hwif, addr); - set_hwif_attr(hwif, attr0, attr1); + addr = HINIC_CSR_FUNC_ATTR2_ADDR; + attr2 = hinic_hwif_read_reg(hwif, addr); + + set_hwif_attr(hwif, attr0, attr1, attr2); } /** @@ -302,6 +344,54 @@ HINIC_PCIE_SNOOP, HINIC_PCIE_TPH_DISABLE); } +u16 hinic_glb_pf_vf_offset(struct hinic_hwif *hwif) +{ + if (!hwif) + return 0; + + return hwif->attr.global_vf_id_of_pf; +} + +u16 hinic_global_func_id_hw(struct hinic_hwif *hwif) +{ + u32 addr, attr0; + + addr = HINIC_CSR_FUNC_ATTR0_ADDR; + attr0 = hinic_hwif_read_reg(hwif, addr); + + return HINIC_FA0_GET(attr0, FUNC_IDX); +} + +u16 hinic_pf_id_of_vf_hw(struct hinic_hwif *hwif) +{ + u32 addr, attr0; + + addr = HINIC_CSR_FUNC_ATTR0_ADDR; + attr0 = hinic_hwif_read_reg(hwif, addr); + + return HINIC_FA0_GET(attr0, PF_IDX); +} + +static void __print_selftest_reg(struct hinic_hwif *hwif) +{ + u32 addr, attr0, attr1; + + addr = HINIC_CSR_FUNC_ATTR1_ADDR; + attr1 = hinic_hwif_read_reg(hwif, addr); + + if (attr1 == HINIC_PCIE_LINK_DOWN) { + dev_err(&hwif->pdev->dev, "PCIE is link down\n"); + return; + } + + addr = HINIC_CSR_FUNC_ATTR0_ADDR; + attr0 = hinic_hwif_read_reg(hwif, addr); + if (HINIC_FA0_GET(attr0, FUNC_TYPE) != HINIC_VF && + !HINIC_FA0_GET(attr0, PCI_INTF_IDX)) + dev_err(&hwif->pdev->dev, "Selftest reg: 0x%08x\n", + hinic_hwif_read_reg(hwif, HINIC_SELFTEST_RESULT)); +} + /** * hinic_init_hwif - initialize the hw interface * @hwif: the HW interface of a pci function device @@ -321,9 +411,17 @@ return -ENOMEM; } - err = hwif_ready(hwif); + hwif->intr_regs_base = pci_ioremap_bar(pdev, HINIC_PCI_INTR_REGS_BAR); + if (!hwif->intr_regs_base) { + dev_err(&pdev->dev, "Failed to map configuration regs\n"); + err = -ENOMEM; + goto err_map_intr_bar; + } + + err = wait_hwif_ready(hwif); if (err) { dev_err(&pdev->dev, "HW interface is not ready\n"); + __print_selftest_reg(hwif); goto err_hwif_ready; } @@ -337,7 +435,11 @@ return 0; err_hwif_ready: + iounmap(hwif->intr_regs_base); + +err_map_intr_bar: iounmap(hwif->cfg_regs_bar); + return err; } @@ -347,5 +449,6 @@ **/ void hinic_free_hwif(struct hinic_hwif *hwif) { + iounmap(hwif->intr_regs_base); iounmap(hwif->cfg_regs_bar); } -- Gitblit v1.6.2