提交 e67c958c 编写于 作者: C Chiqijun 提交者: Yang Yingliang

net/hinic: Support doorbell BAR size of 256K in SDI mode

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: NChiqijun <chiqijun@huawei.com>
Reviewed-by: NLuoshaokai <luoshaokai@huawei.com>
Signed-off-by: NYang Yingliang <yangyingliang@huawei.com>
上级 470c344d
......@@ -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)
......
......@@ -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 @@ u16 hinic_pf_id_of_vf_hw(void *hwdev);
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
......@@ -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 */
......
......@@ -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;
}
}
......@@ -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 {
......
......@@ -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);
......
......@@ -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
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册