From: Chiqijun chiqijun@huawei.com
driver inclusion category: bugfix bugzilla: 4472
-----------------------------------------------------------------------
A VF in 1822 needs to consume 1M + 48k of VF space, and each PCI-bridge reserves io memory of 4M, so after hot-plugging more than 3 network cards, there will be insufficient bar space. To solve this problem, modify the bar space size in the 1822 SDI bare metal and virtual machine scenarios.
Signed-off-by: Chiqijun chiqijun@huawei.com Reviewed-by: Luoshaokai luoshaokai@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- drivers/net/ethernet/huawei/hinic/hinic_csr.h | 4 ++ drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.h | 7 ++ drivers/net/ethernet/huawei/hinic/hinic_hwdev.h | 6 -- drivers/net/ethernet/huawei/hinic/hinic_hwif.c | 75 +++++++++++++++++++--- drivers/net/ethernet/huawei/hinic/hinic_hwif.h | 2 + drivers/net/ethernet/huawei/hinic/hinic_lld.c | 19 ++++-- drivers/net/ethernet/huawei/hinic/hinic_port_cmd.h | 2 + 7 files changed, 93 insertions(+), 22 deletions(-)
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_csr.h b/drivers/net/ethernet/huawei/hinic/hinic_csr.h index 85c3221..76025e5 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_csr.h +++ b/drivers/net/ethernet/huawei/hinic/hinic_csr.h @@ -125,6 +125,10 @@ #define HINIC_CEQ_CONS_IDX_0_ADDR_BASE 0x1008 #define HINIC_CEQ_CONS_IDX_1_ADDR_BASE 0x100C
+/* For multi-host mgmt + * CEQ_CTRL_0_ADDR: bit26~29: uP write vf mode is normal(0x0),bmgw(0x1), + * vmgw(0x2) + */ #define HINIC_CSR_CEQ_CTRL_0_ADDR(idx) \ (HINIC_CEQ_CTRL_0_ADDR_BASE + (idx) * HINIC_EQ_OFF_STRIDE)
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.h b/drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.h index 272a3d9..563188ab 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.h +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.h @@ -393,6 +393,12 @@ struct acl_service_cap { u32 scqc_sz; /* 64B */ };
+enum hinic_chip_mode { + CHIP_MODE_NORMAL, + CHIP_MODE_BMGW, + CHIP_MODE_VMGW, +}; + bool hinic_support_nic(void *hwdev, struct nic_service_cap *cap); bool hinic_support_roce(void *hwdev, struct rdma_service_cap *cap); bool hinic_support_fcoe(void *hwdev, struct fcoe_service_cap *cap); @@ -553,4 +559,5 @@ struct hinic_func_nic_state { u16 hinic_global_func_id_hw(void *hwdev); bool hinic_func_for_pt(void *hwdev); bool hinic_func_for_hwpt(void *hwdev); +u32 hinic_get_db_size(void *cfg_reg_base, enum hinic_chip_mode *chip_mode); #endif diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hwdev.h b/drivers/net/ethernet/huawei/hinic/hinic_hwdev.h index 89a761c..24391d0 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hwdev.h +++ b/drivers/net/ethernet/huawei/hinic/hinic_hwdev.h @@ -240,12 +240,6 @@ struct hinic_heartbeat_enhanced {
#define HINIC_BOARD_TYPE_MULTI_HOST_ETH_25GE 12
-enum hinic_chip_mode { - CHIP_MODE_NORMAL, - CHIP_MODE_BMGW, - CHIP_MODE_VMGW, -}; - /* new version of roce qp not limited by power of 2 */ #define HINIC_CMD_VER_ROCE_QP 1 /* new version for add function id in multi-host */ diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hwif.c b/drivers/net/ethernet/huawei/hinic/hinic_hwif.c index d7066951f..1fc0fa5 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hwif.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_hwif.c @@ -283,14 +283,19 @@ static void set_mpf(struct hinic_hwif *hwif) hinic_hwif_write_reg(hwif, addr, val); }
-static void init_db_area_idx(struct hinic_free_db_area *free_db_area) +static void init_db_area_idx(struct hinic_hwif *hwif) { + struct hinic_free_db_area *free_db_area; + u32 db_max_areas; u32 i;
- for (i = 0; i < HINIC_DB_MAX_AREAS; i++) + free_db_area = &hwif->free_db_area; + db_max_areas = hwif->db_size / HINIC_DB_PAGE_SIZE; + + for (i = 0; i < db_max_areas; i++) free_db_area->db_idx[i] = i;
- free_db_area->num_free = HINIC_DB_MAX_AREAS; + free_db_area->num_free = db_max_areas;
spin_lock_init(&free_db_area->idx_lock); } @@ -298,6 +303,7 @@ static void init_db_area_idx(struct hinic_free_db_area *free_db_area) static int get_db_idx(struct hinic_hwif *hwif, u32 *idx) { struct hinic_free_db_area *free_db_area = &hwif->free_db_area; + u32 db_max_areas = hwif->db_size / HINIC_DB_PAGE_SIZE; u32 pos; u32 pg_idx;
@@ -312,14 +318,14 @@ static int get_db_idx(struct hinic_hwif *hwif, u32 *idx) free_db_area->num_free--;
pos = free_db_area->alloc_pos++; - pos &= HINIC_DB_MAX_AREAS - 1; + pos &= db_max_areas - 1;
pg_idx = free_db_area->db_idx[pos];
free_db_area->db_idx[pos] = 0xFFFFFFFF;
/* pg_idx out of range */ - if (pg_idx >= HINIC_DB_MAX_AREAS) + if (pg_idx >= db_max_areas) goto retry;
spin_unlock(&free_db_area->idx_lock); @@ -332,15 +338,16 @@ static int get_db_idx(struct hinic_hwif *hwif, u32 *idx) static void free_db_idx(struct hinic_hwif *hwif, u32 idx) { struct hinic_free_db_area *free_db_area = &hwif->free_db_area; + u32 db_max_areas = hwif->db_size / HINIC_DB_PAGE_SIZE; u32 pos;
- if (idx >= HINIC_DB_MAX_AREAS) + if (idx >= db_max_areas) return;
spin_lock(&free_db_area->idx_lock);
pos = free_db_area->return_pos++; - pos &= HINIC_DB_MAX_AREAS - 1; + pos &= db_max_areas - 1;
free_db_area->db_idx[pos] = idx;
@@ -386,7 +393,7 @@ int hinic_alloc_db_addr(void *hwdev, void __iomem **db_base,
*db_base = hwif->db_base + idx * HINIC_DB_PAGE_SIZE;
- if (!dwqe_base) + if (!dwqe_base || hwif->chip_mode != CHIP_MODE_NORMAL) return 0;
offset = ((u64)idx) << PAGE_SHIFT; @@ -433,7 +440,9 @@ int hinic_alloc_db_phy_addr(void *hwdev, u64 *db_base, u64 *dwqe_base) return -EFAULT;
*db_base = hwif->db_base_phy + idx * HINIC_DB_PAGE_SIZE; - *dwqe_base = *db_base + HINIC_DB_DWQE_SIZE; + + if (hwif->chip_mode == CHIP_MODE_NORMAL) + *dwqe_base = *db_base + HINIC_DB_DWQE_SIZE;
return 0; } @@ -559,7 +568,13 @@ int hinic_init_hwif(struct hinic_hwdev *hwdev, void *cfg_reg_base, hwif->db_base_phy = db_base_phy; hwif->db_base = db_base; hwif->dwqe_mapping = dwqe_mapping; - init_db_area_idx(&hwif->free_db_area); + + hwif->db_size = hinic_get_db_size(cfg_reg_base, &hwif->chip_mode); + + sdk_info(hwdev->dev_hdl, "Doorbell size: 0x%x, chip mode: %d\n", + hwif->db_size, hwif->chip_mode); + + init_db_area_idx(hwif);
err = wait_hwif_ready(hwdev); if (err) { @@ -924,3 +939,43 @@ u8 hinic_ppf_idx(void *hwdev) return hwif->attr.ppf_idx; } EXPORT_SYMBOL(hinic_ppf_idx); + +#define CEQ_CTRL_0_CHIP_MODE_SHIFT 26 +#define CEQ_CTRL_0_CHIP_MODE_MASK 0xFU +#define CEQ_CTRL_0_GET(val, member) \ + (((val) >> CEQ_CTRL_0_##member##_SHIFT) & \ + CEQ_CTRL_0_##member##_MASK) + +/** + * hinic_get_db_size - get db size ceq ctrl: bit26~29: uP write vf mode is + * normal(0x0), bmgw(0x1) or vmgw(0x2) and normal mode db size is 512k, + * bmgw or vmgw mode db size is 256k + * @cfg_reg_base: pointer to cfg_reg_base + * @chip_mode: pointer to chip_mode + */ +u32 hinic_get_db_size(void *cfg_reg_base, enum hinic_chip_mode *chip_mode) +{ + u32 attr0, ctrl0; + + attr0 = be32_to_cpu(readl((u8 __iomem *)cfg_reg_base + + HINIC_CSR_FUNC_ATTR0_ADDR)); + + /* PF is always normal mode & db size is 512K */ + if (HINIC_AF0_GET(attr0, FUNC_TYPE) != TYPE_VF) { + *chip_mode = CHIP_MODE_NORMAL; + return HINIC_DB_DWQE_SIZE; + } + + ctrl0 = be32_to_cpu(readl((u8 __iomem *)cfg_reg_base + + HINIC_CSR_CEQ_CTRL_0_ADDR(0))); + + *chip_mode = CEQ_CTRL_0_GET(ctrl0, CHIP_MODE); + + switch (*chip_mode) { + case CHIP_MODE_VMGW: + case CHIP_MODE_BMGW: + return HINIC_GW_VF_DB_SIZE; + default: + return HINIC_DB_DWQE_SIZE; + } +} diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hwif.h b/drivers/net/ethernet/huawei/hinic/hinic_hwif.h index e5ac81a..9cd2ad8 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hwif.h +++ b/drivers/net/ethernet/huawei/hinic/hinic_hwif.h @@ -64,6 +64,8 @@ struct hinic_hwif { struct hinic_func_attr attr;
void *pdev; + enum hinic_chip_mode chip_mode; + u32 db_size; };
struct hinic_dma_addr_align { diff --git a/drivers/net/ethernet/huawei/hinic/hinic_lld.c b/drivers/net/ethernet/huawei/hinic/hinic_lld.c index 18d29c3..1636bb4 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_lld.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_lld.c @@ -43,8 +43,6 @@ #define HINIC_PCI_DB_BAR 4 #define HINIC_PCI_VENDOR_ID 0x19e5
-#define HINIC_DB_DWQE_SIZE 0x00080000 - #define SELF_TEST_BAR_ADDR_OFFSET 0x883c
#define HINIC_SECOND_BASE (1000) @@ -131,6 +129,7 @@ struct hinic_pcidev { struct work_struct slave_nic_work; struct workqueue_struct *slave_nic_init_workq; struct delayed_work slave_nic_init_dwork; + enum hinic_chip_mode chip_mode; bool nic_cur_enable; bool nic_des_enable; }; @@ -1836,6 +1835,7 @@ void hinic_event_process(void *adapter, struct hinic_event_info *event)
static int mapping_bar(struct pci_dev *pdev, struct hinic_pcidev *pci_adapter) { + u32 db_dwqe_size; u64 dwqe_addr;
pci_adapter->cfg_reg_base = @@ -1854,19 +1854,25 @@ static int mapping_bar(struct pci_dev *pdev, struct hinic_pcidev *pci_adapter) goto map_intr_bar_err; }
+ db_dwqe_size = hinic_get_db_size(pci_adapter->cfg_reg_base, + &pci_adapter->chip_mode); + pci_adapter->db_base_phy = pci_resource_start(pdev, HINIC_PCI_DB_BAR); pci_adapter->db_base = ioremap(pci_adapter->db_base_phy, - HINIC_DB_DWQE_SIZE); + db_dwqe_size); if (!pci_adapter->db_base) { sdk_err(&pci_adapter->pcidev->dev, "Failed to map doorbell regs\n"); goto map_db_err; }
- dwqe_addr = pci_adapter->db_base_phy + HINIC_DB_DWQE_SIZE; + if (pci_adapter->chip_mode != CHIP_MODE_NORMAL) + return 0; + + dwqe_addr = pci_adapter->db_base_phy + db_dwqe_size;
/* arm do not support call ioremap_wc() */ - pci_adapter->dwqe_mapping = __ioremap(dwqe_addr, HINIC_DB_DWQE_SIZE, + pci_adapter->dwqe_mapping = __ioremap(dwqe_addr, db_dwqe_size, __pgprot(PROT_DEVICE_nGnRnE)); if (!pci_adapter->dwqe_mapping) { sdk_err(&pci_adapter->pcidev->dev, "Failed to io_mapping_create_wc\n"); @@ -1889,7 +1895,8 @@ static int mapping_bar(struct pci_dev *pdev, struct hinic_pcidev *pci_adapter)
static void unmapping_bar(struct hinic_pcidev *pci_adapter) { - iounmap(pci_adapter->dwqe_mapping); + if (pci_adapter->chip_mode == CHIP_MODE_NORMAL) + iounmap(pci_adapter->dwqe_mapping);
iounmap(pci_adapter->db_base); iounmap(pci_adapter->intr_reg_base); diff --git a/drivers/net/ethernet/huawei/hinic/hinic_port_cmd.h b/drivers/net/ethernet/huawei/hinic/hinic_port_cmd.h index c24c155..8730565 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_port_cmd.h +++ b/drivers/net/ethernet/huawei/hinic/hinic_port_cmd.h @@ -527,6 +527,8 @@ enum hinic_pf_status {
/* total doorbell or direct wqe size is 512kB, db num: 128, dwqe: 128 */ #define HINIC_DB_DWQE_SIZE 0x00080000 +/* BMGW & VMGW VF db size 256k, have no dwqe space */ +#define HINIC_GW_VF_DB_SIZE 0x00040000
/* db/dwqe page size: 4K */ #define HINIC_DB_PAGE_SIZE 0x00001000ULL