Merge branch 'for-next-early' into for-next
The early for-next branch was based on v4.14-rc2, while the shared pull request I got from Mellanox used a v4.14-rc4 base. I'm making the branch that was the shared Mellanox pull request the new for-next branch and merging the early for-next branch into it. Signed-off-by: Doug Ledford <dledford@redhat.com>
This commit is contained in:
@@ -1,10 +1,31 @@
|
||||
config INFINIBAND_HNS
|
||||
tristate "HNS RoCE Driver"
|
||||
depends on NET_VENDOR_HISILICON
|
||||
depends on (ARM64 || (COMPILE_TEST && 64BIT)) && HNS && HNS_DSAF && HNS_ENET
|
||||
depends on ARM64 || (COMPILE_TEST && 64BIT)
|
||||
---help---
|
||||
This is a RoCE/RDMA driver for the Hisilicon RoCE engine. The engine
|
||||
is used in Hisilicon Hi1610 and more further ICT SoC.
|
||||
is used in Hisilicon Hip06 and more further ICT SoC based on
|
||||
platform device.
|
||||
|
||||
To compile this driver as a module, choose M here: the module
|
||||
will be called hns-roce.
|
||||
|
||||
config INFINIBAND_HNS_HIP06
|
||||
tristate "Hisilicon Hip06 Family RoCE support"
|
||||
depends on INFINIBAND_HNS && HNS && HNS_DSAF && HNS_ENET
|
||||
---help---
|
||||
RoCE driver support for Hisilicon RoCE engine in Hisilicon Hip06 and
|
||||
Hip07 SoC. These RoCE engines are platform devices.
|
||||
|
||||
To compile this driver as a module, choose M here: the module
|
||||
will be called hns-roce-hw-v1.
|
||||
|
||||
config INFINIBAND_HNS_HIP08
|
||||
tristate "Hisilicon Hip08 Family RoCE support"
|
||||
depends on INFINIBAND_HNS && PCI && HNS3
|
||||
---help---
|
||||
RoCE driver support for Hisilicon RoCE engine in Hisilicon Hip08 SoC.
|
||||
The RoCE engine is a PCI device.
|
||||
|
||||
To compile this driver as a module, choose M here: the module
|
||||
will be called hns-roce-hw-v2.
|
||||
|
@@ -2,7 +2,13 @@
|
||||
# Makefile for the Hisilicon RoCE drivers.
|
||||
#
|
||||
|
||||
ccflags-y := -Idrivers/net/ethernet/hisilicon/hns3
|
||||
|
||||
obj-$(CONFIG_INFINIBAND_HNS) += hns-roce.o
|
||||
hns-roce-objs := hns_roce_main.o hns_roce_cmd.o hns_roce_eq.o hns_roce_pd.o \
|
||||
hns_roce_ah.o hns_roce_hem.o hns_roce_mr.o hns_roce_qp.o \
|
||||
hns_roce_cq.o hns_roce_alloc.o hns_roce_hw_v1.o
|
||||
hns_roce_cq.o hns_roce_alloc.o
|
||||
obj-$(CONFIG_INFINIBAND_HNS_HIP06) += hns-roce-hw-v1.o
|
||||
hns-roce-hw-v1-objs := hns_roce_hw_v1.o
|
||||
obj-$(CONFIG_INFINIBAND_HNS_HIP08) += hns-roce-hw-v2.o
|
||||
hns-roce-hw-v2-objs := hns_roce_hw_v2.o
|
||||
|
@@ -44,7 +44,7 @@ struct ib_ah *hns_roce_create_ah(struct ib_pd *ibpd,
|
||||
struct ib_udata *udata)
|
||||
{
|
||||
struct hns_roce_dev *hr_dev = to_hr_dev(ibpd->device);
|
||||
struct device *dev = &hr_dev->pdev->dev;
|
||||
struct device *dev = hr_dev->dev;
|
||||
struct ib_gid_attr gid_attr;
|
||||
struct hns_roce_ah *ah;
|
||||
u16 vlan_tag = 0xffff;
|
||||
|
@@ -67,6 +67,7 @@ void hns_roce_bitmap_free(struct hns_roce_bitmap *bitmap, unsigned long obj,
|
||||
{
|
||||
hns_roce_bitmap_free_range(bitmap, obj, 1, rr);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(hns_roce_bitmap_free);
|
||||
|
||||
int hns_roce_bitmap_alloc_range(struct hns_roce_bitmap *bitmap, int cnt,
|
||||
int align, unsigned long *obj)
|
||||
@@ -160,7 +161,7 @@ void hns_roce_buf_free(struct hns_roce_dev *hr_dev, u32 size,
|
||||
struct hns_roce_buf *buf)
|
||||
{
|
||||
int i;
|
||||
struct device *dev = &hr_dev->pdev->dev;
|
||||
struct device *dev = hr_dev->dev;
|
||||
u32 bits_per_long = BITS_PER_LONG;
|
||||
|
||||
if (buf->nbufs == 1) {
|
||||
@@ -171,12 +172,13 @@ void hns_roce_buf_free(struct hns_roce_dev *hr_dev, u32 size,
|
||||
|
||||
for (i = 0; i < buf->nbufs; ++i)
|
||||
if (buf->page_list[i].buf)
|
||||
dma_free_coherent(&hr_dev->pdev->dev, PAGE_SIZE,
|
||||
dma_free_coherent(dev, PAGE_SIZE,
|
||||
buf->page_list[i].buf,
|
||||
buf->page_list[i].map);
|
||||
kfree(buf->page_list);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(hns_roce_buf_free);
|
||||
|
||||
int hns_roce_buf_alloc(struct hns_roce_dev *hr_dev, u32 size, u32 max_direct,
|
||||
struct hns_roce_buf *buf)
|
||||
@@ -184,7 +186,7 @@ int hns_roce_buf_alloc(struct hns_roce_dev *hr_dev, u32 size, u32 max_direct,
|
||||
int i = 0;
|
||||
dma_addr_t t;
|
||||
struct page **pages;
|
||||
struct device *dev = &hr_dev->pdev->dev;
|
||||
struct device *dev = hr_dev->dev;
|
||||
u32 bits_per_long = BITS_PER_LONG;
|
||||
|
||||
/* SQ/RQ buf lease than one page, SQ + RQ = 8K */
|
||||
|
@@ -38,69 +38,7 @@
|
||||
|
||||
#define CMD_POLL_TOKEN 0xffff
|
||||
#define CMD_MAX_NUM 32
|
||||
#define STATUS_MASK 0xff
|
||||
#define CMD_TOKEN_MASK 0x1f
|
||||
#define GO_BIT_TIMEOUT_MSECS 10000
|
||||
|
||||
enum {
|
||||
HCR_TOKEN_OFFSET = 0x14,
|
||||
HCR_STATUS_OFFSET = 0x18,
|
||||
HCR_GO_BIT = 15,
|
||||
};
|
||||
|
||||
static int cmd_pending(struct hns_roce_dev *hr_dev)
|
||||
{
|
||||
u32 status = readl(hr_dev->cmd.hcr + HCR_TOKEN_OFFSET);
|
||||
|
||||
return (!!(status & (1 << HCR_GO_BIT)));
|
||||
}
|
||||
|
||||
/* this function should be serialized with "hcr_mutex" */
|
||||
static int __hns_roce_cmd_mbox_post_hw(struct hns_roce_dev *hr_dev,
|
||||
u64 in_param, u64 out_param,
|
||||
u32 in_modifier, u8 op_modifier, u16 op,
|
||||
u16 token, int event)
|
||||
{
|
||||
struct hns_roce_cmdq *cmd = &hr_dev->cmd;
|
||||
struct device *dev = &hr_dev->pdev->dev;
|
||||
u32 __iomem *hcr = (u32 *)cmd->hcr;
|
||||
int ret = -EAGAIN;
|
||||
unsigned long end;
|
||||
u32 val = 0;
|
||||
|
||||
end = msecs_to_jiffies(GO_BIT_TIMEOUT_MSECS) + jiffies;
|
||||
while (cmd_pending(hr_dev)) {
|
||||
if (time_after(jiffies, end)) {
|
||||
dev_dbg(dev, "jiffies=%d end=%d\n", (int)jiffies,
|
||||
(int)end);
|
||||
goto out;
|
||||
}
|
||||
cond_resched();
|
||||
}
|
||||
|
||||
roce_set_field(val, ROCEE_MB6_ROCEE_MB_CMD_M, ROCEE_MB6_ROCEE_MB_CMD_S,
|
||||
op);
|
||||
roce_set_field(val, ROCEE_MB6_ROCEE_MB_CMD_MDF_M,
|
||||
ROCEE_MB6_ROCEE_MB_CMD_MDF_S, op_modifier);
|
||||
roce_set_bit(val, ROCEE_MB6_ROCEE_MB_EVENT_S, event);
|
||||
roce_set_bit(val, ROCEE_MB6_ROCEE_MB_HW_RUN_S, 1);
|
||||
roce_set_field(val, ROCEE_MB6_ROCEE_MB_TOKEN_M,
|
||||
ROCEE_MB6_ROCEE_MB_TOKEN_S, token);
|
||||
|
||||
__raw_writeq(cpu_to_le64(in_param), hcr + 0);
|
||||
__raw_writeq(cpu_to_le64(out_param), hcr + 2);
|
||||
__raw_writel(cpu_to_le32(in_modifier), hcr + 4);
|
||||
/* Memory barrier */
|
||||
wmb();
|
||||
|
||||
__raw_writel(cpu_to_le32(val), hcr + 5);
|
||||
|
||||
mmiowb();
|
||||
ret = 0;
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int hns_roce_cmd_mbox_post_hw(struct hns_roce_dev *hr_dev, u64 in_param,
|
||||
u64 out_param, u32 in_modifier,
|
||||
@@ -108,12 +46,11 @@ static int hns_roce_cmd_mbox_post_hw(struct hns_roce_dev *hr_dev, u64 in_param,
|
||||
int event)
|
||||
{
|
||||
struct hns_roce_cmdq *cmd = &hr_dev->cmd;
|
||||
int ret = -EAGAIN;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&cmd->hcr_mutex);
|
||||
ret = __hns_roce_cmd_mbox_post_hw(hr_dev, in_param, out_param,
|
||||
in_modifier, op_modifier, op, token,
|
||||
event);
|
||||
ret = hr_dev->hw->post_mbox(hr_dev, in_param, out_param, in_modifier,
|
||||
op_modifier, op, token, event);
|
||||
mutex_unlock(&cmd->hcr_mutex);
|
||||
|
||||
return ret;
|
||||
@@ -125,10 +62,7 @@ static int __hns_roce_cmd_mbox_poll(struct hns_roce_dev *hr_dev, u64 in_param,
|
||||
u8 op_modifier, u16 op,
|
||||
unsigned long timeout)
|
||||
{
|
||||
struct device *dev = &hr_dev->pdev->dev;
|
||||
u8 __iomem *hcr = hr_dev->cmd.hcr;
|
||||
unsigned long end = 0;
|
||||
u32 status = 0;
|
||||
struct device *dev = hr_dev->dev;
|
||||
int ret;
|
||||
|
||||
ret = hns_roce_cmd_mbox_post_hw(hr_dev, in_param, out_param,
|
||||
@@ -136,29 +70,10 @@ static int __hns_roce_cmd_mbox_poll(struct hns_roce_dev *hr_dev, u64 in_param,
|
||||
CMD_POLL_TOKEN, 0);
|
||||
if (ret) {
|
||||
dev_err(dev, "[cmd_poll]hns_roce_cmd_mbox_post_hw failed\n");
|
||||
goto out;
|
||||
return ret;
|
||||
}
|
||||
|
||||
end = msecs_to_jiffies(timeout) + jiffies;
|
||||
while (cmd_pending(hr_dev) && time_before(jiffies, end))
|
||||
cond_resched();
|
||||
|
||||
if (cmd_pending(hr_dev)) {
|
||||
dev_err(dev, "[cmd_poll]hw run cmd TIMEDOUT!\n");
|
||||
ret = -ETIMEDOUT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
status = le32_to_cpu((__force __be32)
|
||||
__raw_readl(hcr + HCR_STATUS_OFFSET));
|
||||
if ((status & STATUS_MASK) != 0x1) {
|
||||
dev_err(dev, "mailbox status 0x%x!\n", status);
|
||||
ret = -EBUSY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
return ret;
|
||||
return hr_dev->hw->chk_mbox(hr_dev, timeout);
|
||||
}
|
||||
|
||||
static int hns_roce_cmd_mbox_poll(struct hns_roce_dev *hr_dev, u64 in_param,
|
||||
@@ -196,9 +111,9 @@ static int __hns_roce_cmd_mbox_wait(struct hns_roce_dev *hr_dev, u64 in_param,
|
||||
unsigned long timeout)
|
||||
{
|
||||
struct hns_roce_cmdq *cmd = &hr_dev->cmd;
|
||||
struct device *dev = &hr_dev->pdev->dev;
|
||||
struct hns_roce_cmd_context *context;
|
||||
int ret = 0;
|
||||
struct device *dev = hr_dev->dev;
|
||||
int ret;
|
||||
|
||||
spin_lock(&cmd->context_lock);
|
||||
WARN_ON(cmd->free_head < 0);
|
||||
@@ -269,17 +184,17 @@ int hns_roce_cmd_mbox(struct hns_roce_dev *hr_dev, u64 in_param, u64 out_param,
|
||||
in_modifier, op_modifier, op,
|
||||
timeout);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(hns_roce_cmd_mbox);
|
||||
|
||||
int hns_roce_cmd_init(struct hns_roce_dev *hr_dev)
|
||||
{
|
||||
struct device *dev = &hr_dev->pdev->dev;
|
||||
struct device *dev = hr_dev->dev;
|
||||
|
||||
mutex_init(&hr_dev->cmd.hcr_mutex);
|
||||
sema_init(&hr_dev->cmd.poll_sem, 1);
|
||||
hr_dev->cmd.use_events = 0;
|
||||
hr_dev->cmd.toggle = 1;
|
||||
hr_dev->cmd.max_cmds = CMD_MAX_NUM;
|
||||
hr_dev->cmd.hcr = hr_dev->reg_base + ROCEE_MB1_REG;
|
||||
hr_dev->cmd.pool = dma_pool_create("hns_roce_cmd", dev,
|
||||
HNS_ROCE_MAILBOX_SIZE,
|
||||
HNS_ROCE_MAILBOX_SIZE, 0);
|
||||
@@ -356,6 +271,7 @@ struct hns_roce_cmd_mailbox
|
||||
|
||||
return mailbox;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(hns_roce_alloc_cmd_mailbox);
|
||||
|
||||
void hns_roce_free_cmd_mailbox(struct hns_roce_dev *hr_dev,
|
||||
struct hns_roce_cmd_mailbox *mailbox)
|
||||
@@ -366,3 +282,4 @@ void hns_roce_free_cmd_mailbox(struct hns_roce_dev *hr_dev,
|
||||
dma_pool_free(hr_dev->cmd.pool, mailbox->buf, mailbox->dma);
|
||||
kfree(mailbox);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(hns_roce_free_cmd_mailbox);
|
||||
|
@@ -36,6 +36,56 @@
|
||||
#define HNS_ROCE_MAILBOX_SIZE 4096
|
||||
#define HNS_ROCE_CMD_TIMEOUT_MSECS 10000
|
||||
|
||||
enum {
|
||||
/* QPC BT commands */
|
||||
HNS_ROCE_CMD_WRITE_QPC_BT0 = 0x0,
|
||||
HNS_ROCE_CMD_WRITE_QPC_BT1 = 0x1,
|
||||
HNS_ROCE_CMD_WRITE_QPC_BT2 = 0x2,
|
||||
HNS_ROCE_CMD_READ_QPC_BT0 = 0x4,
|
||||
HNS_ROCE_CMD_READ_QPC_BT1 = 0x5,
|
||||
HNS_ROCE_CMD_READ_QPC_BT2 = 0x6,
|
||||
HNS_ROCE_CMD_DESTROY_QPC_BT0 = 0x8,
|
||||
HNS_ROCE_CMD_DESTROY_QPC_BT1 = 0x9,
|
||||
HNS_ROCE_CMD_DESTROY_QPC_BT2 = 0xa,
|
||||
|
||||
/* QPC operation */
|
||||
HNS_ROCE_CMD_MODIFY_QPC = 0x41,
|
||||
HNS_ROCE_CMD_QUERY_QPC = 0x42,
|
||||
|
||||
/* CQC BT commands */
|
||||
HNS_ROCE_CMD_WRITE_CQC_BT0 = 0x10,
|
||||
HNS_ROCE_CMD_WRITE_CQC_BT1 = 0x11,
|
||||
HNS_ROCE_CMD_WRITE_CQC_BT2 = 0x12,
|
||||
HNS_ROCE_CMD_READ_CQC_BT0 = 0x14,
|
||||
HNS_ROCE_CMD_READ_CQC_BT1 = 0x15,
|
||||
HNS_ROCE_CMD_READ_CQC_BT2 = 0x1b,
|
||||
HNS_ROCE_CMD_DESTROY_CQC_BT0 = 0x18,
|
||||
HNS_ROCE_CMD_DESTROY_CQC_BT1 = 0x19,
|
||||
HNS_ROCE_CMD_DESTROY_CQC_BT2 = 0x1a,
|
||||
|
||||
/* MPT BT commands */
|
||||
HNS_ROCE_CMD_WRITE_MPT_BT0 = 0x20,
|
||||
HNS_ROCE_CMD_WRITE_MPT_BT1 = 0x21,
|
||||
HNS_ROCE_CMD_WRITE_MPT_BT2 = 0x22,
|
||||
HNS_ROCE_CMD_READ_MPT_BT0 = 0x24,
|
||||
HNS_ROCE_CMD_READ_MPT_BT1 = 0x25,
|
||||
HNS_ROCE_CMD_READ_MPT_BT2 = 0x26,
|
||||
HNS_ROCE_CMD_DESTROY_MPT_BT0 = 0x28,
|
||||
HNS_ROCE_CMD_DESTROY_MPT_BT1 = 0x29,
|
||||
HNS_ROCE_CMD_DESTROY_MPT_BT2 = 0x2a,
|
||||
|
||||
/* SRQC BT commands */
|
||||
HNS_ROCE_CMD_WRITE_SRQC_BT0 = 0x30,
|
||||
HNS_ROCE_CMD_WRITE_SRQC_BT1 = 0x31,
|
||||
HNS_ROCE_CMD_WRITE_SRQC_BT2 = 0x32,
|
||||
HNS_ROCE_CMD_READ_SRQC_BT0 = 0x34,
|
||||
HNS_ROCE_CMD_READ_SRQC_BT1 = 0x35,
|
||||
HNS_ROCE_CMD_READ_SRQC_BT2 = 0x36,
|
||||
HNS_ROCE_CMD_DESTROY_SRQC_BT0 = 0x38,
|
||||
HNS_ROCE_CMD_DESTROY_SRQC_BT1 = 0x39,
|
||||
HNS_ROCE_CMD_DESTROY_SRQC_BT2 = 0x3a,
|
||||
};
|
||||
|
||||
enum {
|
||||
/* TPT commands */
|
||||
HNS_ROCE_CMD_SW2HW_MPT = 0xd,
|
||||
|
@@ -341,6 +341,7 @@
|
||||
#define ROCEE_BT_CMD_L_REG 0x200
|
||||
|
||||
#define ROCEE_MB1_REG 0x210
|
||||
#define ROCEE_MB6_REG 0x224
|
||||
#define ROCEE_DB_SQ_L_0_REG 0x230
|
||||
#define ROCEE_DB_OTHERS_L_0_REG 0x238
|
||||
#define ROCEE_QP1C_CFG0_0_REG 0x270
|
||||
@@ -362,4 +363,26 @@
|
||||
#define ROCEE_ECC_UCERR_ALM0_REG 0xB34
|
||||
#define ROCEE_ECC_CERR_ALM0_REG 0xB40
|
||||
|
||||
/* V2 ROCEE REG */
|
||||
#define ROCEE_TX_CMQ_BASEADDR_L_REG 0x07000
|
||||
#define ROCEE_TX_CMQ_BASEADDR_H_REG 0x07004
|
||||
#define ROCEE_TX_CMQ_DEPTH_REG 0x07008
|
||||
#define ROCEE_TX_CMQ_TAIL_REG 0x07010
|
||||
#define ROCEE_TX_CMQ_HEAD_REG 0x07014
|
||||
|
||||
#define ROCEE_RX_CMQ_BASEADDR_L_REG 0x07018
|
||||
#define ROCEE_RX_CMQ_BASEADDR_H_REG 0x0701c
|
||||
#define ROCEE_RX_CMQ_DEPTH_REG 0x07020
|
||||
#define ROCEE_RX_CMQ_TAIL_REG 0x07024
|
||||
#define ROCEE_RX_CMQ_HEAD_REG 0x07028
|
||||
|
||||
#define ROCEE_VF_SMAC_CFG0_REG 0x12000
|
||||
#define ROCEE_VF_SMAC_CFG1_REG 0x12004
|
||||
|
||||
#define ROCEE_VF_SGID_CFG0_REG 0x10000
|
||||
#define ROCEE_VF_SGID_CFG1_REG 0x10004
|
||||
#define ROCEE_VF_SGID_CFG2_REG 0x10008
|
||||
#define ROCEE_VF_SGID_CFG3_REG 0x1000c
|
||||
#define ROCEE_VF_SGID_CFG4_REG 0x10010
|
||||
|
||||
#endif /* _HNS_ROCE_COMMON_H */
|
||||
|
@@ -58,7 +58,7 @@ static void hns_roce_ib_cq_event(struct hns_roce_cq *hr_cq,
|
||||
if (event_type != HNS_ROCE_EVENT_TYPE_CQ_ID_INVALID &&
|
||||
event_type != HNS_ROCE_EVENT_TYPE_CQ_ACCESS_ERROR &&
|
||||
event_type != HNS_ROCE_EVENT_TYPE_CQ_OVERFLOW) {
|
||||
dev_err(&hr_dev->pdev->dev,
|
||||
dev_err(hr_dev->dev,
|
||||
"hns_roce_ib: Unexpected event type 0x%x on CQ %06lx\n",
|
||||
event_type, hr_cq->cqn);
|
||||
return;
|
||||
@@ -85,17 +85,23 @@ static int hns_roce_cq_alloc(struct hns_roce_dev *hr_dev, int nent,
|
||||
struct hns_roce_uar *hr_uar,
|
||||
struct hns_roce_cq *hr_cq, int vector)
|
||||
{
|
||||
struct hns_roce_cmd_mailbox *mailbox = NULL;
|
||||
struct hns_roce_cq_table *cq_table = NULL;
|
||||
struct device *dev = &hr_dev->pdev->dev;
|
||||
struct hns_roce_cmd_mailbox *mailbox;
|
||||
struct hns_roce_hem_table *mtt_table;
|
||||
struct hns_roce_cq_table *cq_table;
|
||||
struct device *dev = hr_dev->dev;
|
||||
dma_addr_t dma_handle;
|
||||
u64 *mtts = NULL;
|
||||
int ret = 0;
|
||||
u64 *mtts;
|
||||
int ret;
|
||||
|
||||
cq_table = &hr_dev->cq_table;
|
||||
|
||||
/* Get the physical address of cq buf */
|
||||
mtts = hns_roce_table_find(&hr_dev->mr_table.mtt_table,
|
||||
if (hns_roce_check_whether_mhop(hr_dev, HEM_TYPE_CQE))
|
||||
mtt_table = &hr_dev->mr_table.mtt_cqe_table;
|
||||
else
|
||||
mtt_table = &hr_dev->mr_table.mtt_table;
|
||||
|
||||
mtts = hns_roce_table_find(hr_dev, mtt_table,
|
||||
hr_mtt->first_seg, &dma_handle);
|
||||
if (!mtts) {
|
||||
dev_err(dev, "CQ alloc.Failed to find cq buf addr.\n");
|
||||
@@ -182,21 +188,22 @@ static int hns_roce_hw2sw_cq(struct hns_roce_dev *dev,
|
||||
void hns_roce_free_cq(struct hns_roce_dev *hr_dev, struct hns_roce_cq *hr_cq)
|
||||
{
|
||||
struct hns_roce_cq_table *cq_table = &hr_dev->cq_table;
|
||||
struct device *dev = &hr_dev->pdev->dev;
|
||||
struct device *dev = hr_dev->dev;
|
||||
int ret;
|
||||
|
||||
ret = hns_roce_hw2sw_cq(hr_dev, NULL, hr_cq->cqn);
|
||||
if (ret)
|
||||
dev_err(dev, "HW2SW_CQ failed (%d) for CQN %06lx\n", ret,
|
||||
hr_cq->cqn);
|
||||
if (hr_dev->eq_table.eq) {
|
||||
/* Waiting interrupt process procedure carried out */
|
||||
synchronize_irq(hr_dev->eq_table.eq[hr_cq->vector].irq);
|
||||
|
||||
/* Waiting interrupt process procedure carried out */
|
||||
synchronize_irq(hr_dev->eq_table.eq[hr_cq->vector].irq);
|
||||
|
||||
/* wait for all interrupt processed */
|
||||
if (atomic_dec_and_test(&hr_cq->refcount))
|
||||
complete(&hr_cq->free);
|
||||
wait_for_completion(&hr_cq->free);
|
||||
/* wait for all interrupt processed */
|
||||
if (atomic_dec_and_test(&hr_cq->refcount))
|
||||
complete(&hr_cq->free);
|
||||
wait_for_completion(&hr_cq->free);
|
||||
}
|
||||
|
||||
spin_lock_irq(&cq_table->lock);
|
||||
radix_tree_delete(&cq_table->tree, hr_cq->cqn);
|
||||
@@ -205,6 +212,7 @@ void hns_roce_free_cq(struct hns_roce_dev *hr_dev, struct hns_roce_cq *hr_cq)
|
||||
hns_roce_table_put(hr_dev, &cq_table->table, hr_cq->cqn);
|
||||
hns_roce_bitmap_free(&cq_table->bitmap, hr_cq->cqn, BITMAP_NO_RR);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(hns_roce_free_cq);
|
||||
|
||||
static int hns_roce_ib_get_cq_umem(struct hns_roce_dev *hr_dev,
|
||||
struct ib_ucontext *context,
|
||||
@@ -218,6 +226,10 @@ static int hns_roce_ib_get_cq_umem(struct hns_roce_dev *hr_dev,
|
||||
if (IS_ERR(*umem))
|
||||
return PTR_ERR(*umem);
|
||||
|
||||
if (hns_roce_check_whether_mhop(hr_dev, HEM_TYPE_CQE))
|
||||
buf->hr_mtt.mtt_type = MTT_TYPE_CQE;
|
||||
else
|
||||
buf->hr_mtt.mtt_type = MTT_TYPE_WQE;
|
||||
ret = hns_roce_mtt_init(hr_dev, ib_umem_page_count(*umem),
|
||||
(*umem)->page_shift, &buf->hr_mtt);
|
||||
if (ret)
|
||||
@@ -247,6 +259,11 @@ static int hns_roce_ib_alloc_cq_buf(struct hns_roce_dev *hr_dev,
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
if (hns_roce_check_whether_mhop(hr_dev, HEM_TYPE_CQE))
|
||||
buf->hr_mtt.mtt_type = MTT_TYPE_CQE;
|
||||
else
|
||||
buf->hr_mtt.mtt_type = MTT_TYPE_WQE;
|
||||
|
||||
ret = hns_roce_mtt_init(hr_dev, buf->hr_buf.npages,
|
||||
buf->hr_buf.page_shift, &buf->hr_mtt);
|
||||
if (ret)
|
||||
@@ -281,13 +298,13 @@ struct ib_cq *hns_roce_ib_create_cq(struct ib_device *ib_dev,
|
||||
struct ib_udata *udata)
|
||||
{
|
||||
struct hns_roce_dev *hr_dev = to_hr_dev(ib_dev);
|
||||
struct device *dev = &hr_dev->pdev->dev;
|
||||
struct device *dev = hr_dev->dev;
|
||||
struct hns_roce_ib_create_cq ucmd;
|
||||
struct hns_roce_cq *hr_cq = NULL;
|
||||
struct hns_roce_uar *uar = NULL;
|
||||
int vector = attr->comp_vector;
|
||||
int cq_entries = attr->cqe;
|
||||
int ret = 0;
|
||||
int ret;
|
||||
|
||||
if (cq_entries < 1 || cq_entries > hr_dev->caps.max_cqes) {
|
||||
dev_err(dev, "Creat CQ failed. entries=%d, max=%d\n",
|
||||
@@ -295,13 +312,12 @@ struct ib_cq *hns_roce_ib_create_cq(struct ib_device *ib_dev,
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
hr_cq = kmalloc(sizeof(*hr_cq), GFP_KERNEL);
|
||||
hr_cq = kzalloc(sizeof(*hr_cq), GFP_KERNEL);
|
||||
if (!hr_cq)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
/* In v1 engine, parameter verification */
|
||||
if (cq_entries < HNS_ROCE_MIN_CQE_NUM)
|
||||
cq_entries = HNS_ROCE_MIN_CQE_NUM;
|
||||
if (hr_dev->caps.min_cqes)
|
||||
cq_entries = max(cq_entries, hr_dev->caps.min_cqes);
|
||||
|
||||
cq_entries = roundup_pow_of_two((unsigned int)cq_entries);
|
||||
hr_cq->ib_cq.cqe = cq_entries - 1;
|
||||
@@ -335,8 +351,8 @@ struct ib_cq *hns_roce_ib_create_cq(struct ib_device *ib_dev,
|
||||
}
|
||||
|
||||
uar = &hr_dev->priv_uar;
|
||||
hr_cq->cq_db_l = hr_dev->reg_base + ROCEE_DB_OTHERS_L_0_REG +
|
||||
0x1000 * uar->index;
|
||||
hr_cq->cq_db_l = hr_dev->reg_base + hr_dev->odb_offset +
|
||||
DB_REG_OFFSET * uar->index;
|
||||
}
|
||||
|
||||
/* Allocate cq index, fill cq_context */
|
||||
@@ -353,7 +369,7 @@ struct ib_cq *hns_roce_ib_create_cq(struct ib_device *ib_dev,
|
||||
* problems if tptr is set to zero here, so we initialze it in user
|
||||
* space.
|
||||
*/
|
||||
if (!context)
|
||||
if (!context && hr_cq->tptr_addr)
|
||||
*hr_cq->tptr_addr = 0;
|
||||
|
||||
/* Get created cq handler and carry out event */
|
||||
@@ -385,6 +401,7 @@ err_cq:
|
||||
kfree(hr_cq);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(hns_roce_ib_create_cq);
|
||||
|
||||
int hns_roce_ib_destroy_cq(struct ib_cq *ib_cq)
|
||||
{
|
||||
@@ -410,10 +427,11 @@ int hns_roce_ib_destroy_cq(struct ib_cq *ib_cq)
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(hns_roce_ib_destroy_cq);
|
||||
|
||||
void hns_roce_cq_completion(struct hns_roce_dev *hr_dev, u32 cqn)
|
||||
{
|
||||
struct device *dev = &hr_dev->pdev->dev;
|
||||
struct device *dev = hr_dev->dev;
|
||||
struct hns_roce_cq *cq;
|
||||
|
||||
cq = radix_tree_lookup(&hr_dev->cq_table.tree,
|
||||
@@ -429,7 +447,7 @@ void hns_roce_cq_completion(struct hns_roce_dev *hr_dev, u32 cqn)
|
||||
void hns_roce_cq_event(struct hns_roce_dev *hr_dev, u32 cqn, int event_type)
|
||||
{
|
||||
struct hns_roce_cq_table *cq_table = &hr_dev->cq_table;
|
||||
struct device *dev = &hr_dev->pdev->dev;
|
||||
struct device *dev = hr_dev->dev;
|
||||
struct hns_roce_cq *cq;
|
||||
|
||||
cq = radix_tree_lookup(&cq_table->tree,
|
||||
|
@@ -78,6 +78,8 @@
|
||||
#define HNS_ROCE_MAX_GID_NUM 16
|
||||
#define HNS_ROCE_GID_SIZE 16
|
||||
|
||||
#define HNS_ROCE_HOP_NUM_0 0xff
|
||||
|
||||
#define BITMAP_NO_RR 0
|
||||
#define BITMAP_RR 1
|
||||
|
||||
@@ -168,6 +170,11 @@ enum {
|
||||
HNS_ROCE_OPCODE_RDMA_WITH_IMM_RECEIVE = 0x07,
|
||||
};
|
||||
|
||||
enum hns_roce_mtt_type {
|
||||
MTT_TYPE_WQE,
|
||||
MTT_TYPE_CQE,
|
||||
};
|
||||
|
||||
#define HNS_ROCE_CMD_SUCCESS 1
|
||||
|
||||
#define HNS_ROCE_PORT_DOWN 0
|
||||
@@ -232,12 +239,17 @@ struct hns_roce_hem_table {
|
||||
int lowmem;
|
||||
struct mutex mutex;
|
||||
struct hns_roce_hem **hem;
|
||||
u64 **bt_l1;
|
||||
dma_addr_t *bt_l1_dma_addr;
|
||||
u64 **bt_l0;
|
||||
dma_addr_t *bt_l0_dma_addr;
|
||||
};
|
||||
|
||||
struct hns_roce_mtt {
|
||||
unsigned long first_seg;
|
||||
int order;
|
||||
int page_shift;
|
||||
unsigned long first_seg;
|
||||
int order;
|
||||
int page_shift;
|
||||
enum hns_roce_mtt_type mtt_type;
|
||||
};
|
||||
|
||||
/* Only support 4K page size for mr register */
|
||||
@@ -255,6 +267,19 @@ struct hns_roce_mr {
|
||||
int type; /* MR's register type */
|
||||
u64 *pbl_buf;/* MR's PBL space */
|
||||
dma_addr_t pbl_dma_addr; /* MR's PBL space PA */
|
||||
u32 pbl_size;/* PA number in the PBL */
|
||||
u64 pbl_ba;/* page table address */
|
||||
u32 l0_chunk_last_num;/* L0 last number */
|
||||
u32 l1_chunk_last_num;/* L1 last number */
|
||||
u64 **pbl_bt_l2;/* PBL BT L2 */
|
||||
u64 **pbl_bt_l1;/* PBL BT L1 */
|
||||
u64 *pbl_bt_l0;/* PBL BT L0 */
|
||||
dma_addr_t *pbl_l2_dma_addr;/* PBL BT L2 dma addr */
|
||||
dma_addr_t *pbl_l1_dma_addr;/* PBL BT L1 dma addr */
|
||||
dma_addr_t pbl_l0_dma_addr;/* PBL BT L0 dma addr */
|
||||
u32 pbl_ba_pg_sz;/* BT chunk page size */
|
||||
u32 pbl_buf_pg_sz;/* buf chunk page size */
|
||||
u32 pbl_hop_num;/* multi-hop number */
|
||||
};
|
||||
|
||||
struct hns_roce_mr_table {
|
||||
@@ -262,6 +287,8 @@ struct hns_roce_mr_table {
|
||||
struct hns_roce_buddy mtt_buddy;
|
||||
struct hns_roce_hem_table mtt_table;
|
||||
struct hns_roce_hem_table mtpt_table;
|
||||
struct hns_roce_buddy mtt_cqe_buddy;
|
||||
struct hns_roce_hem_table mtt_cqe_table;
|
||||
};
|
||||
|
||||
struct hns_roce_wq {
|
||||
@@ -277,6 +304,12 @@ struct hns_roce_wq {
|
||||
void __iomem *db_reg_l;
|
||||
};
|
||||
|
||||
struct hns_roce_sge {
|
||||
int sge_cnt; /* SGE num */
|
||||
int offset;
|
||||
int sge_shift;/* SGE size */
|
||||
};
|
||||
|
||||
struct hns_roce_buf_list {
|
||||
void *buf;
|
||||
dma_addr_t map;
|
||||
@@ -367,7 +400,6 @@ struct hns_roce_cmd_context {
|
||||
|
||||
struct hns_roce_cmdq {
|
||||
struct dma_pool *pool;
|
||||
u8 __iomem *hcr;
|
||||
struct mutex hcr_mutex;
|
||||
struct semaphore poll_sem;
|
||||
/*
|
||||
@@ -429,6 +461,9 @@ struct hns_roce_qp {
|
||||
|
||||
atomic_t refcount;
|
||||
struct completion free;
|
||||
|
||||
struct hns_roce_sge sge;
|
||||
u32 next_sge;
|
||||
};
|
||||
|
||||
struct hns_roce_sqp {
|
||||
@@ -439,7 +474,6 @@ struct hns_roce_ib_iboe {
|
||||
spinlock_t lock;
|
||||
struct net_device *netdevs[HNS_ROCE_MAX_PORTS];
|
||||
struct notifier_block nb;
|
||||
struct notifier_block nb_inet;
|
||||
u8 phy_port[HNS_ROCE_MAX_PORTS];
|
||||
};
|
||||
|
||||
@@ -477,16 +511,20 @@ struct hns_roce_caps {
|
||||
u32 max_wqes; /* 16k */
|
||||
u32 max_sq_desc_sz; /* 64 */
|
||||
u32 max_rq_desc_sz; /* 64 */
|
||||
u32 max_srq_desc_sz;
|
||||
int max_qp_init_rdma;
|
||||
int max_qp_dest_rdma;
|
||||
int num_cqs;
|
||||
int max_cqes;
|
||||
int min_cqes;
|
||||
u32 min_wqes;
|
||||
int reserved_cqs;
|
||||
int num_aeq_vectors; /* 1 */
|
||||
int num_comp_vectors; /* 32 ceq */
|
||||
int num_other_vectors;
|
||||
int num_mtpts;
|
||||
u32 num_mtt_segs;
|
||||
u32 num_cqe_segs;
|
||||
int reserved_mrws;
|
||||
int reserved_uars;
|
||||
int num_pds;
|
||||
@@ -499,19 +537,50 @@ struct hns_roce_caps {
|
||||
int qpc_entry_sz;
|
||||
int irrl_entry_sz;
|
||||
int cqc_entry_sz;
|
||||
u32 pbl_ba_pg_sz;
|
||||
u32 pbl_buf_pg_sz;
|
||||
u32 pbl_hop_num;
|
||||
int aeqe_depth;
|
||||
int ceqe_depth[HNS_ROCE_COMP_VEC_NUM];
|
||||
enum ib_mtu max_mtu;
|
||||
u32 qpc_bt_num;
|
||||
u32 srqc_bt_num;
|
||||
u32 cqc_bt_num;
|
||||
u32 mpt_bt_num;
|
||||
u32 qpc_ba_pg_sz;
|
||||
u32 qpc_buf_pg_sz;
|
||||
u32 qpc_hop_num;
|
||||
u32 srqc_ba_pg_sz;
|
||||
u32 srqc_buf_pg_sz;
|
||||
u32 srqc_hop_num;
|
||||
u32 cqc_ba_pg_sz;
|
||||
u32 cqc_buf_pg_sz;
|
||||
u32 cqc_hop_num;
|
||||
u32 mpt_ba_pg_sz;
|
||||
u32 mpt_buf_pg_sz;
|
||||
u32 mpt_hop_num;
|
||||
u32 mtt_ba_pg_sz;
|
||||
u32 mtt_buf_pg_sz;
|
||||
u32 mtt_hop_num;
|
||||
u32 cqe_ba_pg_sz;
|
||||
u32 cqe_buf_pg_sz;
|
||||
u32 cqe_hop_num;
|
||||
};
|
||||
|
||||
struct hns_roce_hw {
|
||||
int (*reset)(struct hns_roce_dev *hr_dev, bool enable);
|
||||
void (*hw_profile)(struct hns_roce_dev *hr_dev);
|
||||
int (*cmq_init)(struct hns_roce_dev *hr_dev);
|
||||
void (*cmq_exit)(struct hns_roce_dev *hr_dev);
|
||||
int (*hw_profile)(struct hns_roce_dev *hr_dev);
|
||||
int (*hw_init)(struct hns_roce_dev *hr_dev);
|
||||
void (*hw_exit)(struct hns_roce_dev *hr_dev);
|
||||
int (*post_mbox)(struct hns_roce_dev *hr_dev, u64 in_param,
|
||||
u64 out_param, u32 in_modifier, u8 op_modifier, u16 op,
|
||||
u16 token, int event);
|
||||
int (*chk_mbox)(struct hns_roce_dev *hr_dev, unsigned long timeout);
|
||||
void (*set_gid)(struct hns_roce_dev *hr_dev, u8 port, int gid_index,
|
||||
union ib_gid *gid);
|
||||
void (*set_mac)(struct hns_roce_dev *hr_dev, u8 phy_port, u8 *addr);
|
||||
int (*set_mac)(struct hns_roce_dev *hr_dev, u8 phy_port, u8 *addr);
|
||||
void (*set_mtu)(struct hns_roce_dev *hr_dev, u8 phy_port,
|
||||
enum ib_mtu mtu);
|
||||
int (*write_mtpt)(void *mb_buf, struct hns_roce_mr *mr,
|
||||
@@ -519,8 +588,11 @@ struct hns_roce_hw {
|
||||
void (*write_cqc)(struct hns_roce_dev *hr_dev,
|
||||
struct hns_roce_cq *hr_cq, void *mb_buf, u64 *mtts,
|
||||
dma_addr_t dma_handle, int nent, u32 vector);
|
||||
int (*set_hem)(struct hns_roce_dev *hr_dev,
|
||||
struct hns_roce_hem_table *table, int obj, int step_idx);
|
||||
int (*clear_hem)(struct hns_roce_dev *hr_dev,
|
||||
struct hns_roce_hem_table *table, int obj);
|
||||
struct hns_roce_hem_table *table, int obj,
|
||||
int step_idx);
|
||||
int (*query_qp)(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr,
|
||||
int qp_attr_mask, struct ib_qp_init_attr *qp_init_attr);
|
||||
int (*modify_qp)(struct ib_qp *ibqp, const struct ib_qp_attr *attr,
|
||||
@@ -535,12 +607,13 @@ struct hns_roce_hw {
|
||||
int (*poll_cq)(struct ib_cq *ibcq, int num_entries, struct ib_wc *wc);
|
||||
int (*dereg_mr)(struct hns_roce_dev *hr_dev, struct hns_roce_mr *mr);
|
||||
int (*destroy_cq)(struct ib_cq *ibcq);
|
||||
void *priv;
|
||||
};
|
||||
|
||||
struct hns_roce_dev {
|
||||
struct ib_device ib_dev;
|
||||
struct platform_device *pdev;
|
||||
struct pci_dev *pci_dev;
|
||||
struct device *dev;
|
||||
struct hns_roce_uar priv_uar;
|
||||
const char *irq_names[HNS_ROCE_MAX_IRQ_NUM];
|
||||
spinlock_t sm_lock;
|
||||
@@ -569,9 +642,12 @@ struct hns_roce_dev {
|
||||
|
||||
int cmd_mod;
|
||||
int loop_idc;
|
||||
u32 sdb_offset;
|
||||
u32 odb_offset;
|
||||
dma_addr_t tptr_dma_addr; /*only for hw v1*/
|
||||
u32 tptr_size; /*only for hw v1*/
|
||||
struct hns_roce_hw *hw;
|
||||
const struct hns_roce_hw *hw;
|
||||
void *priv;
|
||||
};
|
||||
|
||||
static inline struct hns_roce_dev *to_hr_dev(struct ib_device *ib_dev)
|
||||
@@ -723,6 +799,7 @@ int hns_roce_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
|
||||
int attr_mask, struct ib_udata *udata);
|
||||
void *get_recv_wqe(struct hns_roce_qp *hr_qp, int n);
|
||||
void *get_send_wqe(struct hns_roce_qp *hr_qp, int n);
|
||||
void *get_send_extend_sge(struct hns_roce_qp *hr_qp, int n);
|
||||
bool hns_roce_wq_overflow(struct hns_roce_wq *hr_wq, int nreq,
|
||||
struct ib_cq *ib_cq);
|
||||
enum hns_roce_qp_state to_hns_roce_state(enum ib_qp_state state);
|
||||
@@ -749,7 +826,7 @@ void hns_roce_cq_completion(struct hns_roce_dev *hr_dev, u32 cqn);
|
||||
void hns_roce_cq_event(struct hns_roce_dev *hr_dev, u32 cqn, int event_type);
|
||||
void hns_roce_qp_event(struct hns_roce_dev *hr_dev, u32 qpn, int event_type);
|
||||
int hns_get_gid_index(struct hns_roce_dev *hr_dev, u8 port, int gid_index);
|
||||
|
||||
extern struct hns_roce_hw hns_roce_hw_v1;
|
||||
int hns_roce_init(struct hns_roce_dev *hr_dev);
|
||||
void hns_roce_exit(struct hns_roce_dev *hr_dev);
|
||||
|
||||
#endif /* _HNS_ROCE_DEVICE_H */
|
||||
|
@@ -558,7 +558,7 @@ static int hns_roce_create_eq(struct hns_roce_dev *hr_dev,
|
||||
writel(eqshift_val, eqc);
|
||||
|
||||
/* Configure eq extended address 12~44bit */
|
||||
writel((u32)(eq->buf_list[0].map >> 12), (u8 *)eqc + 4);
|
||||
writel((u32)(eq->buf_list[0].map >> 12), eqc + 4);
|
||||
|
||||
/*
|
||||
* Configure eq extended address 45~49 bit.
|
||||
@@ -572,13 +572,13 @@ static int hns_roce_create_eq(struct hns_roce_dev *hr_dev,
|
||||
roce_set_field(eqcuridx_val,
|
||||
ROCEE_CAEP_AEQE_CUR_IDX_CAEP_AEQE_CUR_IDX_M,
|
||||
ROCEE_CAEP_AEQE_CUR_IDX_CAEP_AEQE_CUR_IDX_S, 0);
|
||||
writel(eqcuridx_val, (u8 *)eqc + 8);
|
||||
writel(eqcuridx_val, eqc + 8);
|
||||
|
||||
/* Configure eq consumer index */
|
||||
roce_set_field(eqconsindx_val,
|
||||
ROCEE_CAEP_AEQE_CONS_IDX_CAEP_AEQE_CONS_IDX_M,
|
||||
ROCEE_CAEP_AEQE_CONS_IDX_CAEP_AEQE_CONS_IDX_S, 0);
|
||||
writel(eqconsindx_val, (u8 *)eqc + 0xc);
|
||||
writel(eqconsindx_val, eqc + 0xc);
|
||||
|
||||
return 0;
|
||||
|
||||
|
@@ -42,8 +42,162 @@
|
||||
#define DMA_ADDR_T_SHIFT 12
|
||||
#define BT_BA_SHIFT 32
|
||||
|
||||
struct hns_roce_hem *hns_roce_alloc_hem(struct hns_roce_dev *hr_dev, int npages,
|
||||
gfp_t gfp_mask)
|
||||
bool hns_roce_check_whether_mhop(struct hns_roce_dev *hr_dev, u32 type)
|
||||
{
|
||||
if ((hr_dev->caps.qpc_hop_num && type == HEM_TYPE_QPC) ||
|
||||
(hr_dev->caps.mpt_hop_num && type == HEM_TYPE_MTPT) ||
|
||||
(hr_dev->caps.cqc_hop_num && type == HEM_TYPE_CQC) ||
|
||||
(hr_dev->caps.srqc_hop_num && type == HEM_TYPE_SRQC) ||
|
||||
(hr_dev->caps.cqe_hop_num && type == HEM_TYPE_CQE) ||
|
||||
(hr_dev->caps.mtt_hop_num && type == HEM_TYPE_MTT))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(hns_roce_check_whether_mhop);
|
||||
|
||||
static bool hns_roce_check_hem_null(struct hns_roce_hem **hem, u64 start_idx,
|
||||
u32 bt_chunk_num)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < bt_chunk_num; i++)
|
||||
if (hem[start_idx + i])
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool hns_roce_check_bt_null(u64 **bt, u64 start_idx, u32 bt_chunk_num)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < bt_chunk_num; i++)
|
||||
if (bt[start_idx + i])
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int hns_roce_get_bt_num(u32 table_type, u32 hop_num)
|
||||
{
|
||||
if (check_whether_bt_num_3(table_type, hop_num))
|
||||
return 3;
|
||||
else if (check_whether_bt_num_2(table_type, hop_num))
|
||||
return 2;
|
||||
else if (check_whether_bt_num_1(table_type, hop_num))
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hns_roce_calc_hem_mhop(struct hns_roce_dev *hr_dev,
|
||||
struct hns_roce_hem_table *table, unsigned long *obj,
|
||||
struct hns_roce_hem_mhop *mhop)
|
||||
{
|
||||
struct device *dev = hr_dev->dev;
|
||||
u32 chunk_ba_num;
|
||||
u32 table_idx;
|
||||
u32 bt_num;
|
||||
u32 chunk_size;
|
||||
|
||||
switch (table->type) {
|
||||
case HEM_TYPE_QPC:
|
||||
mhop->buf_chunk_size = 1 << (hr_dev->caps.qpc_buf_pg_sz
|
||||
+ PAGE_SHIFT);
|
||||
mhop->bt_chunk_size = 1 << (hr_dev->caps.qpc_ba_pg_sz
|
||||
+ PAGE_SHIFT);
|
||||
mhop->ba_l0_num = hr_dev->caps.qpc_bt_num;
|
||||
mhop->hop_num = hr_dev->caps.qpc_hop_num;
|
||||
break;
|
||||
case HEM_TYPE_MTPT:
|
||||
mhop->buf_chunk_size = 1 << (hr_dev->caps.mpt_buf_pg_sz
|
||||
+ PAGE_SHIFT);
|
||||
mhop->bt_chunk_size = 1 << (hr_dev->caps.mpt_ba_pg_sz
|
||||
+ PAGE_SHIFT);
|
||||
mhop->ba_l0_num = hr_dev->caps.mpt_bt_num;
|
||||
mhop->hop_num = hr_dev->caps.mpt_hop_num;
|
||||
break;
|
||||
case HEM_TYPE_CQC:
|
||||
mhop->buf_chunk_size = 1 << (hr_dev->caps.cqc_buf_pg_sz
|
||||
+ PAGE_SHIFT);
|
||||
mhop->bt_chunk_size = 1 << (hr_dev->caps.cqc_ba_pg_sz
|
||||
+ PAGE_SHIFT);
|
||||
mhop->ba_l0_num = hr_dev->caps.cqc_bt_num;
|
||||
mhop->hop_num = hr_dev->caps.cqc_hop_num;
|
||||
break;
|
||||
case HEM_TYPE_SRQC:
|
||||
mhop->buf_chunk_size = 1 << (hr_dev->caps.srqc_buf_pg_sz
|
||||
+ PAGE_SHIFT);
|
||||
mhop->bt_chunk_size = 1 << (hr_dev->caps.srqc_ba_pg_sz
|
||||
+ PAGE_SHIFT);
|
||||
mhop->ba_l0_num = hr_dev->caps.srqc_bt_num;
|
||||
mhop->hop_num = hr_dev->caps.srqc_hop_num;
|
||||
break;
|
||||
case HEM_TYPE_MTT:
|
||||
mhop->buf_chunk_size = 1 << (hr_dev->caps.mtt_buf_pg_sz
|
||||
+ PAGE_SHIFT);
|
||||
mhop->bt_chunk_size = 1 << (hr_dev->caps.mtt_ba_pg_sz
|
||||
+ PAGE_SHIFT);
|
||||
mhop->ba_l0_num = mhop->bt_chunk_size / 8;
|
||||
mhop->hop_num = hr_dev->caps.mtt_hop_num;
|
||||
break;
|
||||
case HEM_TYPE_CQE:
|
||||
mhop->buf_chunk_size = 1 << (hr_dev->caps.cqe_buf_pg_sz
|
||||
+ PAGE_SHIFT);
|
||||
mhop->bt_chunk_size = 1 << (hr_dev->caps.cqe_ba_pg_sz
|
||||
+ PAGE_SHIFT);
|
||||
mhop->ba_l0_num = mhop->bt_chunk_size / 8;
|
||||
mhop->hop_num = hr_dev->caps.cqe_hop_num;
|
||||
break;
|
||||
default:
|
||||
dev_err(dev, "Table %d not support multi-hop addressing!\n",
|
||||
table->type);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!obj)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* QPC/MTPT/CQC/SRQC alloc hem for buffer pages.
|
||||
* MTT/CQE alloc hem for bt pages.
|
||||
*/
|
||||
bt_num = hns_roce_get_bt_num(table->type, mhop->hop_num);
|
||||
chunk_ba_num = mhop->bt_chunk_size / 8;
|
||||
chunk_size = table->type < HEM_TYPE_MTT ? mhop->buf_chunk_size :
|
||||
mhop->bt_chunk_size;
|
||||
table_idx = (*obj & (table->num_obj - 1)) /
|
||||
(chunk_size / table->obj_size);
|
||||
switch (bt_num) {
|
||||
case 3:
|
||||
mhop->l2_idx = table_idx & (chunk_ba_num - 1);
|
||||
mhop->l1_idx = table_idx / chunk_ba_num & (chunk_ba_num - 1);
|
||||
mhop->l0_idx = table_idx / chunk_ba_num / chunk_ba_num;
|
||||
break;
|
||||
case 2:
|
||||
mhop->l1_idx = table_idx & (chunk_ba_num - 1);
|
||||
mhop->l0_idx = table_idx / chunk_ba_num;
|
||||
break;
|
||||
case 1:
|
||||
mhop->l0_idx = table_idx;
|
||||
break;
|
||||
default:
|
||||
dev_err(dev, "Table %d not support hop_num = %d!\n",
|
||||
table->type, mhop->hop_num);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (mhop->l0_idx >= mhop->ba_l0_num)
|
||||
mhop->l0_idx %= mhop->ba_l0_num;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(hns_roce_calc_hem_mhop);
|
||||
|
||||
static struct hns_roce_hem *hns_roce_alloc_hem(struct hns_roce_dev *hr_dev,
|
||||
int npages,
|
||||
unsigned long hem_alloc_size,
|
||||
gfp_t gfp_mask)
|
||||
{
|
||||
struct hns_roce_hem_chunk *chunk = NULL;
|
||||
struct hns_roce_hem *hem;
|
||||
@@ -61,7 +215,7 @@ struct hns_roce_hem *hns_roce_alloc_hem(struct hns_roce_dev *hr_dev, int npages,
|
||||
hem->refcount = 0;
|
||||
INIT_LIST_HEAD(&hem->chunk_list);
|
||||
|
||||
order = get_order(HNS_ROCE_HEM_ALLOC_SIZE);
|
||||
order = get_order(hem_alloc_size);
|
||||
|
||||
while (npages > 0) {
|
||||
if (!chunk) {
|
||||
@@ -84,7 +238,7 @@ struct hns_roce_hem *hns_roce_alloc_hem(struct hns_roce_dev *hr_dev, int npages,
|
||||
* memory, directly return fail.
|
||||
*/
|
||||
mem = &chunk->mem[chunk->npages];
|
||||
buf = dma_alloc_coherent(&hr_dev->pdev->dev, PAGE_SIZE << order,
|
||||
buf = dma_alloc_coherent(hr_dev->dev, PAGE_SIZE << order,
|
||||
&sg_dma_address(mem), gfp_mask);
|
||||
if (!buf)
|
||||
goto fail;
|
||||
@@ -115,7 +269,7 @@ void hns_roce_free_hem(struct hns_roce_dev *hr_dev, struct hns_roce_hem *hem)
|
||||
|
||||
list_for_each_entry_safe(chunk, tmp, &hem->chunk_list, list) {
|
||||
for (i = 0; i < chunk->npages; ++i)
|
||||
dma_free_coherent(&hr_dev->pdev->dev,
|
||||
dma_free_coherent(hr_dev->dev,
|
||||
chunk->mem[i].length,
|
||||
lowmem_page_address(sg_page(&chunk->mem[i])),
|
||||
sg_dma_address(&chunk->mem[i]));
|
||||
@@ -128,8 +282,8 @@ void hns_roce_free_hem(struct hns_roce_dev *hr_dev, struct hns_roce_hem *hem)
|
||||
static int hns_roce_set_hem(struct hns_roce_dev *hr_dev,
|
||||
struct hns_roce_hem_table *table, unsigned long obj)
|
||||
{
|
||||
struct device *dev = &hr_dev->pdev->dev;
|
||||
spinlock_t *lock = &hr_dev->bt_cmd_lock;
|
||||
struct device *dev = hr_dev->dev;
|
||||
unsigned long end = 0;
|
||||
unsigned long flags;
|
||||
struct hns_roce_hem_iter iter;
|
||||
@@ -209,13 +363,184 @@ static int hns_roce_set_hem(struct hns_roce_dev *hr_dev,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int hns_roce_table_mhop_get(struct hns_roce_dev *hr_dev,
|
||||
struct hns_roce_hem_table *table,
|
||||
unsigned long obj)
|
||||
{
|
||||
struct device *dev = hr_dev->dev;
|
||||
struct hns_roce_hem_mhop mhop;
|
||||
struct hns_roce_hem_iter iter;
|
||||
u32 buf_chunk_size;
|
||||
u32 bt_chunk_size;
|
||||
u32 chunk_ba_num;
|
||||
u32 hop_num;
|
||||
u32 size;
|
||||
u32 bt_num;
|
||||
u64 hem_idx;
|
||||
u64 bt_l1_idx = 0;
|
||||
u64 bt_l0_idx = 0;
|
||||
u64 bt_ba;
|
||||
unsigned long mhop_obj = obj;
|
||||
int bt_l1_allocated = 0;
|
||||
int bt_l0_allocated = 0;
|
||||
int step_idx;
|
||||
int ret;
|
||||
|
||||
ret = hns_roce_calc_hem_mhop(hr_dev, table, &mhop_obj, &mhop);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
buf_chunk_size = mhop.buf_chunk_size;
|
||||
bt_chunk_size = mhop.bt_chunk_size;
|
||||
hop_num = mhop.hop_num;
|
||||
chunk_ba_num = bt_chunk_size / 8;
|
||||
|
||||
bt_num = hns_roce_get_bt_num(table->type, hop_num);
|
||||
switch (bt_num) {
|
||||
case 3:
|
||||
hem_idx = mhop.l0_idx * chunk_ba_num * chunk_ba_num +
|
||||
mhop.l1_idx * chunk_ba_num + mhop.l2_idx;
|
||||
bt_l1_idx = mhop.l0_idx * chunk_ba_num + mhop.l1_idx;
|
||||
bt_l0_idx = mhop.l0_idx;
|
||||
break;
|
||||
case 2:
|
||||
hem_idx = mhop.l0_idx * chunk_ba_num + mhop.l1_idx;
|
||||
bt_l0_idx = mhop.l0_idx;
|
||||
break;
|
||||
case 1:
|
||||
hem_idx = mhop.l0_idx;
|
||||
break;
|
||||
default:
|
||||
dev_err(dev, "Table %d not support hop_num = %d!\n",
|
||||
table->type, hop_num);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mutex_lock(&table->mutex);
|
||||
|
||||
if (table->hem[hem_idx]) {
|
||||
++table->hem[hem_idx]->refcount;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* alloc L1 BA's chunk */
|
||||
if ((check_whether_bt_num_3(table->type, hop_num) ||
|
||||
check_whether_bt_num_2(table->type, hop_num)) &&
|
||||
!table->bt_l0[bt_l0_idx]) {
|
||||
table->bt_l0[bt_l0_idx] = dma_alloc_coherent(dev, bt_chunk_size,
|
||||
&(table->bt_l0_dma_addr[bt_l0_idx]),
|
||||
GFP_KERNEL);
|
||||
if (!table->bt_l0[bt_l0_idx]) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
bt_l0_allocated = 1;
|
||||
|
||||
/* set base address to hardware */
|
||||
if (table->type < HEM_TYPE_MTT) {
|
||||
step_idx = 0;
|
||||
if (hr_dev->hw->set_hem(hr_dev, table, obj, step_idx)) {
|
||||
ret = -ENODEV;
|
||||
dev_err(dev, "set HEM base address to HW failed!\n");
|
||||
goto err_dma_alloc_l1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* alloc L2 BA's chunk */
|
||||
if (check_whether_bt_num_3(table->type, hop_num) &&
|
||||
!table->bt_l1[bt_l1_idx]) {
|
||||
table->bt_l1[bt_l1_idx] = dma_alloc_coherent(dev, bt_chunk_size,
|
||||
&(table->bt_l1_dma_addr[bt_l1_idx]),
|
||||
GFP_KERNEL);
|
||||
if (!table->bt_l1[bt_l1_idx]) {
|
||||
ret = -ENOMEM;
|
||||
goto err_dma_alloc_l1;
|
||||
}
|
||||
bt_l1_allocated = 1;
|
||||
*(table->bt_l0[bt_l0_idx] + mhop.l1_idx) =
|
||||
table->bt_l1_dma_addr[bt_l1_idx];
|
||||
|
||||
/* set base address to hardware */
|
||||
step_idx = 1;
|
||||
if (hr_dev->hw->set_hem(hr_dev, table, obj, step_idx)) {
|
||||
ret = -ENODEV;
|
||||
dev_err(dev, "set HEM base address to HW failed!\n");
|
||||
goto err_alloc_hem_buf;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* alloc buffer space chunk for QPC/MTPT/CQC/SRQC.
|
||||
* alloc bt space chunk for MTT/CQE.
|
||||
*/
|
||||
size = table->type < HEM_TYPE_MTT ? buf_chunk_size : bt_chunk_size;
|
||||
table->hem[hem_idx] = hns_roce_alloc_hem(hr_dev,
|
||||
size >> PAGE_SHIFT,
|
||||
size,
|
||||
(table->lowmem ? GFP_KERNEL :
|
||||
GFP_HIGHUSER) | __GFP_NOWARN);
|
||||
if (!table->hem[hem_idx]) {
|
||||
ret = -ENOMEM;
|
||||
goto err_alloc_hem_buf;
|
||||
}
|
||||
|
||||
hns_roce_hem_first(table->hem[hem_idx], &iter);
|
||||
bt_ba = hns_roce_hem_addr(&iter);
|
||||
|
||||
if (table->type < HEM_TYPE_MTT) {
|
||||
if (hop_num == 2) {
|
||||
*(table->bt_l1[bt_l1_idx] + mhop.l2_idx) = bt_ba;
|
||||
step_idx = 2;
|
||||
} else if (hop_num == 1) {
|
||||
*(table->bt_l0[bt_l0_idx] + mhop.l1_idx) = bt_ba;
|
||||
step_idx = 1;
|
||||
} else if (hop_num == HNS_ROCE_HOP_NUM_0) {
|
||||
step_idx = 0;
|
||||
}
|
||||
|
||||
/* set HEM base address to hardware */
|
||||
if (hr_dev->hw->set_hem(hr_dev, table, obj, step_idx)) {
|
||||
ret = -ENODEV;
|
||||
dev_err(dev, "set HEM base address to HW failed!\n");
|
||||
goto err_alloc_hem_buf;
|
||||
}
|
||||
} else if (hop_num == 2) {
|
||||
*(table->bt_l0[bt_l0_idx] + mhop.l1_idx) = bt_ba;
|
||||
}
|
||||
|
||||
++table->hem[hem_idx]->refcount;
|
||||
goto out;
|
||||
|
||||
err_alloc_hem_buf:
|
||||
if (bt_l1_allocated) {
|
||||
dma_free_coherent(dev, bt_chunk_size, table->bt_l1[bt_l1_idx],
|
||||
table->bt_l1_dma_addr[bt_l1_idx]);
|
||||
table->bt_l1[bt_l1_idx] = NULL;
|
||||
}
|
||||
|
||||
err_dma_alloc_l1:
|
||||
if (bt_l0_allocated) {
|
||||
dma_free_coherent(dev, bt_chunk_size, table->bt_l0[bt_l0_idx],
|
||||
table->bt_l0_dma_addr[bt_l0_idx]);
|
||||
table->bt_l0[bt_l0_idx] = NULL;
|
||||
}
|
||||
|
||||
out:
|
||||
mutex_unlock(&table->mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int hns_roce_table_get(struct hns_roce_dev *hr_dev,
|
||||
struct hns_roce_hem_table *table, unsigned long obj)
|
||||
{
|
||||
struct device *dev = &hr_dev->pdev->dev;
|
||||
struct device *dev = hr_dev->dev;
|
||||
int ret = 0;
|
||||
unsigned long i;
|
||||
|
||||
if (hns_roce_check_whether_mhop(hr_dev, table->type))
|
||||
return hns_roce_table_mhop_get(hr_dev, table, obj);
|
||||
|
||||
i = (obj & (table->num_obj - 1)) / (HNS_ROCE_TABLE_CHUNK_SIZE /
|
||||
table->obj_size);
|
||||
|
||||
@@ -228,6 +553,7 @@ int hns_roce_table_get(struct hns_roce_dev *hr_dev,
|
||||
|
||||
table->hem[i] = hns_roce_alloc_hem(hr_dev,
|
||||
HNS_ROCE_TABLE_CHUNK_SIZE >> PAGE_SHIFT,
|
||||
HNS_ROCE_HEM_ALLOC_SIZE,
|
||||
(table->lowmem ? GFP_KERNEL :
|
||||
GFP_HIGHUSER) | __GFP_NOWARN);
|
||||
if (!table->hem[i]) {
|
||||
@@ -237,6 +563,8 @@ int hns_roce_table_get(struct hns_roce_dev *hr_dev,
|
||||
|
||||
/* Set HEM base address(128K/page, pa) to Hardware */
|
||||
if (hns_roce_set_hem(hr_dev, table, obj)) {
|
||||
hns_roce_free_hem(hr_dev, table->hem[i]);
|
||||
table->hem[i] = NULL;
|
||||
ret = -ENODEV;
|
||||
dev_err(dev, "set HEM base address to HW failed.\n");
|
||||
goto out;
|
||||
@@ -248,12 +576,131 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void hns_roce_table_mhop_put(struct hns_roce_dev *hr_dev,
|
||||
struct hns_roce_hem_table *table,
|
||||
unsigned long obj,
|
||||
int check_refcount)
|
||||
{
|
||||
struct device *dev = hr_dev->dev;
|
||||
struct hns_roce_hem_mhop mhop;
|
||||
unsigned long mhop_obj = obj;
|
||||
u32 bt_chunk_size;
|
||||
u32 chunk_ba_num;
|
||||
u32 hop_num;
|
||||
u32 start_idx;
|
||||
u32 bt_num;
|
||||
u64 hem_idx;
|
||||
u64 bt_l1_idx = 0;
|
||||
int ret;
|
||||
|
||||
ret = hns_roce_calc_hem_mhop(hr_dev, table, &mhop_obj, &mhop);
|
||||
if (ret)
|
||||
return;
|
||||
|
||||
bt_chunk_size = mhop.bt_chunk_size;
|
||||
hop_num = mhop.hop_num;
|
||||
chunk_ba_num = bt_chunk_size / 8;
|
||||
|
||||
bt_num = hns_roce_get_bt_num(table->type, hop_num);
|
||||
switch (bt_num) {
|
||||
case 3:
|
||||
hem_idx = mhop.l0_idx * chunk_ba_num * chunk_ba_num +
|
||||
mhop.l1_idx * chunk_ba_num + mhop.l2_idx;
|
||||
bt_l1_idx = mhop.l0_idx * chunk_ba_num + mhop.l1_idx;
|
||||
break;
|
||||
case 2:
|
||||
hem_idx = mhop.l0_idx * chunk_ba_num + mhop.l1_idx;
|
||||
break;
|
||||
case 1:
|
||||
hem_idx = mhop.l0_idx;
|
||||
break;
|
||||
default:
|
||||
dev_err(dev, "Table %d not support hop_num = %d!\n",
|
||||
table->type, hop_num);
|
||||
return;
|
||||
}
|
||||
|
||||
mutex_lock(&table->mutex);
|
||||
|
||||
if (check_refcount && (--table->hem[hem_idx]->refcount > 0)) {
|
||||
mutex_unlock(&table->mutex);
|
||||
return;
|
||||
}
|
||||
|
||||
if (table->type < HEM_TYPE_MTT && hop_num == 1) {
|
||||
if (hr_dev->hw->clear_hem(hr_dev, table, obj, 1))
|
||||
dev_warn(dev, "Clear HEM base address failed.\n");
|
||||
} else if (table->type < HEM_TYPE_MTT && hop_num == 2) {
|
||||
if (hr_dev->hw->clear_hem(hr_dev, table, obj, 2))
|
||||
dev_warn(dev, "Clear HEM base address failed.\n");
|
||||
} else if (table->type < HEM_TYPE_MTT &&
|
||||
hop_num == HNS_ROCE_HOP_NUM_0) {
|
||||
if (hr_dev->hw->clear_hem(hr_dev, table, obj, 0))
|
||||
dev_warn(dev, "Clear HEM base address failed.\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* free buffer space chunk for QPC/MTPT/CQC/SRQC.
|
||||
* free bt space chunk for MTT/CQE.
|
||||
*/
|
||||
hns_roce_free_hem(hr_dev, table->hem[hem_idx]);
|
||||
table->hem[hem_idx] = NULL;
|
||||
|
||||
if (check_whether_bt_num_2(table->type, hop_num)) {
|
||||
start_idx = mhop.l0_idx * chunk_ba_num;
|
||||
if (hns_roce_check_hem_null(table->hem, start_idx,
|
||||
chunk_ba_num)) {
|
||||
if (table->type < HEM_TYPE_MTT &&
|
||||
hr_dev->hw->clear_hem(hr_dev, table, obj, 0))
|
||||
dev_warn(dev, "Clear HEM base address failed.\n");
|
||||
|
||||
dma_free_coherent(dev, bt_chunk_size,
|
||||
table->bt_l0[mhop.l0_idx],
|
||||
table->bt_l0_dma_addr[mhop.l0_idx]);
|
||||
table->bt_l0[mhop.l0_idx] = NULL;
|
||||
}
|
||||
} else if (check_whether_bt_num_3(table->type, hop_num)) {
|
||||
start_idx = mhop.l0_idx * chunk_ba_num * chunk_ba_num +
|
||||
mhop.l1_idx * chunk_ba_num;
|
||||
if (hns_roce_check_hem_null(table->hem, start_idx,
|
||||
chunk_ba_num)) {
|
||||
if (hr_dev->hw->clear_hem(hr_dev, table, obj, 1))
|
||||
dev_warn(dev, "Clear HEM base address failed.\n");
|
||||
|
||||
dma_free_coherent(dev, bt_chunk_size,
|
||||
table->bt_l1[bt_l1_idx],
|
||||
table->bt_l1_dma_addr[bt_l1_idx]);
|
||||
table->bt_l1[bt_l1_idx] = NULL;
|
||||
|
||||
start_idx = mhop.l0_idx * chunk_ba_num;
|
||||
if (hns_roce_check_bt_null(table->bt_l1, start_idx,
|
||||
chunk_ba_num)) {
|
||||
if (hr_dev->hw->clear_hem(hr_dev, table, obj,
|
||||
0))
|
||||
dev_warn(dev, "Clear HEM base address failed.\n");
|
||||
|
||||
dma_free_coherent(dev, bt_chunk_size,
|
||||
table->bt_l0[mhop.l0_idx],
|
||||
table->bt_l0_dma_addr[mhop.l0_idx]);
|
||||
table->bt_l0[mhop.l0_idx] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mutex_unlock(&table->mutex);
|
||||
}
|
||||
|
||||
void hns_roce_table_put(struct hns_roce_dev *hr_dev,
|
||||
struct hns_roce_hem_table *table, unsigned long obj)
|
||||
{
|
||||
struct device *dev = &hr_dev->pdev->dev;
|
||||
struct device *dev = hr_dev->dev;
|
||||
unsigned long i;
|
||||
|
||||
if (hns_roce_check_whether_mhop(hr_dev, table->type)) {
|
||||
hns_roce_table_mhop_put(hr_dev, table, obj, 1);
|
||||
return;
|
||||
}
|
||||
|
||||
i = (obj & (table->num_obj - 1)) /
|
||||
(HNS_ROCE_TABLE_CHUNK_SIZE / table->obj_size);
|
||||
|
||||
@@ -261,7 +708,7 @@ void hns_roce_table_put(struct hns_roce_dev *hr_dev,
|
||||
|
||||
if (--table->hem[i]->refcount == 0) {
|
||||
/* Clear HEM base address */
|
||||
if (hr_dev->hw->clear_hem(hr_dev, table, obj))
|
||||
if (hr_dev->hw->clear_hem(hr_dev, table, obj, 0))
|
||||
dev_warn(dev, "Clear HEM base address failed.\n");
|
||||
|
||||
hns_roce_free_hem(hr_dev, table->hem[i]);
|
||||
@@ -271,23 +718,46 @@ void hns_roce_table_put(struct hns_roce_dev *hr_dev,
|
||||
mutex_unlock(&table->mutex);
|
||||
}
|
||||
|
||||
void *hns_roce_table_find(struct hns_roce_hem_table *table, unsigned long obj,
|
||||
dma_addr_t *dma_handle)
|
||||
void *hns_roce_table_find(struct hns_roce_dev *hr_dev,
|
||||
struct hns_roce_hem_table *table,
|
||||
unsigned long obj, dma_addr_t *dma_handle)
|
||||
{
|
||||
struct hns_roce_hem_chunk *chunk;
|
||||
unsigned long idx;
|
||||
int i;
|
||||
int offset, dma_offset;
|
||||
struct hns_roce_hem_mhop mhop;
|
||||
struct hns_roce_hem *hem;
|
||||
struct page *page = NULL;
|
||||
unsigned long mhop_obj = obj;
|
||||
unsigned long idx;
|
||||
int offset, dma_offset;
|
||||
int i, j;
|
||||
u32 hem_idx = 0;
|
||||
|
||||
if (!table->lowmem)
|
||||
return NULL;
|
||||
|
||||
mutex_lock(&table->mutex);
|
||||
idx = (obj & (table->num_obj - 1)) * table->obj_size;
|
||||
hem = table->hem[idx / HNS_ROCE_TABLE_CHUNK_SIZE];
|
||||
dma_offset = offset = idx % HNS_ROCE_TABLE_CHUNK_SIZE;
|
||||
|
||||
if (!hns_roce_check_whether_mhop(hr_dev, table->type)) {
|
||||
idx = (obj & (table->num_obj - 1)) * table->obj_size;
|
||||
hem = table->hem[idx / HNS_ROCE_TABLE_CHUNK_SIZE];
|
||||
dma_offset = offset = idx % HNS_ROCE_TABLE_CHUNK_SIZE;
|
||||
} else {
|
||||
hns_roce_calc_hem_mhop(hr_dev, table, &mhop_obj, &mhop);
|
||||
/* mtt mhop */
|
||||
i = mhop.l0_idx;
|
||||
j = mhop.l1_idx;
|
||||
if (mhop.hop_num == 2)
|
||||
hem_idx = i * (mhop.bt_chunk_size / 8) + j;
|
||||
else if (mhop.hop_num == 1 ||
|
||||
mhop.hop_num == HNS_ROCE_HOP_NUM_0)
|
||||
hem_idx = i;
|
||||
|
||||
hem = table->hem[hem_idx];
|
||||
dma_offset = offset = (obj & (table->num_obj - 1)) *
|
||||
table->obj_size % mhop.bt_chunk_size;
|
||||
if (mhop.hop_num == 2)
|
||||
dma_offset = offset = 0;
|
||||
}
|
||||
|
||||
if (!hem)
|
||||
goto out;
|
||||
@@ -314,14 +784,21 @@ out:
|
||||
mutex_unlock(&table->mutex);
|
||||
return page ? lowmem_page_address(page) + offset : NULL;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(hns_roce_table_find);
|
||||
|
||||
int hns_roce_table_get_range(struct hns_roce_dev *hr_dev,
|
||||
struct hns_roce_hem_table *table,
|
||||
unsigned long start, unsigned long end)
|
||||
{
|
||||
struct hns_roce_hem_mhop mhop;
|
||||
unsigned long inc = HNS_ROCE_TABLE_CHUNK_SIZE / table->obj_size;
|
||||
unsigned long i = 0;
|
||||
int ret = 0;
|
||||
unsigned long i;
|
||||
int ret;
|
||||
|
||||
if (hns_roce_check_whether_mhop(hr_dev, table->type)) {
|
||||
hns_roce_calc_hem_mhop(hr_dev, table, NULL, &mhop);
|
||||
inc = mhop.bt_chunk_size / table->obj_size;
|
||||
}
|
||||
|
||||
/* Allocate MTT entry memory according to chunk(128K) */
|
||||
for (i = start; i <= end; i += inc) {
|
||||
@@ -344,10 +821,17 @@ void hns_roce_table_put_range(struct hns_roce_dev *hr_dev,
|
||||
struct hns_roce_hem_table *table,
|
||||
unsigned long start, unsigned long end)
|
||||
{
|
||||
struct hns_roce_hem_mhop mhop;
|
||||
unsigned long inc = HNS_ROCE_TABLE_CHUNK_SIZE / table->obj_size;
|
||||
unsigned long i;
|
||||
|
||||
if (hns_roce_check_whether_mhop(hr_dev, table->type)) {
|
||||
hns_roce_calc_hem_mhop(hr_dev, table, NULL, &mhop);
|
||||
inc = mhop.bt_chunk_size / table->obj_size;
|
||||
}
|
||||
|
||||
for (i = start; i <= end;
|
||||
i += HNS_ROCE_TABLE_CHUNK_SIZE / table->obj_size)
|
||||
i += inc)
|
||||
hns_roce_table_put(hr_dev, table, i);
|
||||
}
|
||||
|
||||
@@ -356,15 +840,119 @@ int hns_roce_init_hem_table(struct hns_roce_dev *hr_dev,
|
||||
unsigned long obj_size, unsigned long nobj,
|
||||
int use_lowmem)
|
||||
{
|
||||
struct device *dev = hr_dev->dev;
|
||||
unsigned long obj_per_chunk;
|
||||
unsigned long num_hem;
|
||||
|
||||
obj_per_chunk = HNS_ROCE_TABLE_CHUNK_SIZE / obj_size;
|
||||
num_hem = (nobj + obj_per_chunk - 1) / obj_per_chunk;
|
||||
if (!hns_roce_check_whether_mhop(hr_dev, type)) {
|
||||
obj_per_chunk = HNS_ROCE_TABLE_CHUNK_SIZE / obj_size;
|
||||
num_hem = (nobj + obj_per_chunk - 1) / obj_per_chunk;
|
||||
|
||||
table->hem = kcalloc(num_hem, sizeof(*table->hem), GFP_KERNEL);
|
||||
if (!table->hem)
|
||||
return -ENOMEM;
|
||||
table->hem = kcalloc(num_hem, sizeof(*table->hem), GFP_KERNEL);
|
||||
if (!table->hem)
|
||||
return -ENOMEM;
|
||||
} else {
|
||||
unsigned long buf_chunk_size;
|
||||
unsigned long bt_chunk_size;
|
||||
unsigned long bt_chunk_num;
|
||||
unsigned long num_bt_l0 = 0;
|
||||
u32 hop_num;
|
||||
|
||||
switch (type) {
|
||||
case HEM_TYPE_QPC:
|
||||
buf_chunk_size = 1 << (hr_dev->caps.qpc_buf_pg_sz
|
||||
+ PAGE_SHIFT);
|
||||
bt_chunk_size = 1 << (hr_dev->caps.qpc_ba_pg_sz
|
||||
+ PAGE_SHIFT);
|
||||
num_bt_l0 = hr_dev->caps.qpc_bt_num;
|
||||
hop_num = hr_dev->caps.qpc_hop_num;
|
||||
break;
|
||||
case HEM_TYPE_MTPT:
|
||||
buf_chunk_size = 1 << (hr_dev->caps.mpt_buf_pg_sz
|
||||
+ PAGE_SHIFT);
|
||||
bt_chunk_size = 1 << (hr_dev->caps.mpt_ba_pg_sz
|
||||
+ PAGE_SHIFT);
|
||||
num_bt_l0 = hr_dev->caps.mpt_bt_num;
|
||||
hop_num = hr_dev->caps.mpt_hop_num;
|
||||
break;
|
||||
case HEM_TYPE_CQC:
|
||||
buf_chunk_size = 1 << (hr_dev->caps.cqc_buf_pg_sz
|
||||
+ PAGE_SHIFT);
|
||||
bt_chunk_size = 1 << (hr_dev->caps.cqc_ba_pg_sz
|
||||
+ PAGE_SHIFT);
|
||||
num_bt_l0 = hr_dev->caps.cqc_bt_num;
|
||||
hop_num = hr_dev->caps.cqc_hop_num;
|
||||
break;
|
||||
case HEM_TYPE_SRQC:
|
||||
buf_chunk_size = 1 << (hr_dev->caps.srqc_buf_pg_sz
|
||||
+ PAGE_SHIFT);
|
||||
bt_chunk_size = 1 << (hr_dev->caps.srqc_ba_pg_sz
|
||||
+ PAGE_SHIFT);
|
||||
num_bt_l0 = hr_dev->caps.srqc_bt_num;
|
||||
hop_num = hr_dev->caps.srqc_hop_num;
|
||||
break;
|
||||
case HEM_TYPE_MTT:
|
||||
buf_chunk_size = 1 << (hr_dev->caps.mtt_ba_pg_sz
|
||||
+ PAGE_SHIFT);
|
||||
bt_chunk_size = buf_chunk_size;
|
||||
hop_num = hr_dev->caps.mtt_hop_num;
|
||||
break;
|
||||
case HEM_TYPE_CQE:
|
||||
buf_chunk_size = 1 << (hr_dev->caps.cqe_ba_pg_sz
|
||||
+ PAGE_SHIFT);
|
||||
bt_chunk_size = buf_chunk_size;
|
||||
hop_num = hr_dev->caps.cqe_hop_num;
|
||||
break;
|
||||
default:
|
||||
dev_err(dev,
|
||||
"Table %d not support to init hem table here!\n",
|
||||
type);
|
||||
return -EINVAL;
|
||||
}
|
||||
obj_per_chunk = buf_chunk_size / obj_size;
|
||||
num_hem = (nobj + obj_per_chunk - 1) / obj_per_chunk;
|
||||
bt_chunk_num = bt_chunk_size / 8;
|
||||
if (table->type >= HEM_TYPE_MTT)
|
||||
num_bt_l0 = bt_chunk_num;
|
||||
|
||||
table->hem = kcalloc(num_hem, sizeof(*table->hem),
|
||||
GFP_KERNEL);
|
||||
if (!table->hem)
|
||||
goto err_kcalloc_hem_buf;
|
||||
|
||||
if (check_whether_bt_num_3(table->type, hop_num)) {
|
||||
unsigned long num_bt_l1;
|
||||
|
||||
num_bt_l1 = (num_hem + bt_chunk_num - 1) /
|
||||
bt_chunk_num;
|
||||
table->bt_l1 = kcalloc(num_bt_l1,
|
||||
sizeof(*table->bt_l1),
|
||||
GFP_KERNEL);
|
||||
if (!table->bt_l1)
|
||||
goto err_kcalloc_bt_l1;
|
||||
|
||||
table->bt_l1_dma_addr = kcalloc(num_bt_l1,
|
||||
sizeof(*table->bt_l1_dma_addr),
|
||||
GFP_KERNEL);
|
||||
|
||||
if (!table->bt_l1_dma_addr)
|
||||
goto err_kcalloc_l1_dma;
|
||||
}
|
||||
|
||||
if (check_whether_bt_num_2(table->type, hop_num) ||
|
||||
check_whether_bt_num_3(table->type, hop_num)) {
|
||||
table->bt_l0 = kcalloc(num_bt_l0, sizeof(*table->bt_l0),
|
||||
GFP_KERNEL);
|
||||
if (!table->bt_l0)
|
||||
goto err_kcalloc_bt_l0;
|
||||
|
||||
table->bt_l0_dma_addr = kcalloc(num_bt_l0,
|
||||
sizeof(*table->bt_l0_dma_addr),
|
||||
GFP_KERNEL);
|
||||
if (!table->bt_l0_dma_addr)
|
||||
goto err_kcalloc_l0_dma;
|
||||
}
|
||||
}
|
||||
|
||||
table->type = type;
|
||||
table->num_hem = num_hem;
|
||||
@@ -374,18 +962,72 @@ int hns_roce_init_hem_table(struct hns_roce_dev *hr_dev,
|
||||
mutex_init(&table->mutex);
|
||||
|
||||
return 0;
|
||||
|
||||
err_kcalloc_l0_dma:
|
||||
kfree(table->bt_l0);
|
||||
table->bt_l0 = NULL;
|
||||
|
||||
err_kcalloc_bt_l0:
|
||||
kfree(table->bt_l1_dma_addr);
|
||||
table->bt_l1_dma_addr = NULL;
|
||||
|
||||
err_kcalloc_l1_dma:
|
||||
kfree(table->bt_l1);
|
||||
table->bt_l1 = NULL;
|
||||
|
||||
err_kcalloc_bt_l1:
|
||||
kfree(table->hem);
|
||||
table->hem = NULL;
|
||||
|
||||
err_kcalloc_hem_buf:
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
static void hns_roce_cleanup_mhop_hem_table(struct hns_roce_dev *hr_dev,
|
||||
struct hns_roce_hem_table *table)
|
||||
{
|
||||
struct hns_roce_hem_mhop mhop;
|
||||
u32 buf_chunk_size;
|
||||
int i;
|
||||
u64 obj;
|
||||
|
||||
hns_roce_calc_hem_mhop(hr_dev, table, NULL, &mhop);
|
||||
buf_chunk_size = table->type < HEM_TYPE_MTT ? mhop.buf_chunk_size :
|
||||
mhop.bt_chunk_size;
|
||||
|
||||
for (i = 0; i < table->num_hem; ++i) {
|
||||
obj = i * buf_chunk_size / table->obj_size;
|
||||
if (table->hem[i])
|
||||
hns_roce_table_mhop_put(hr_dev, table, obj, 0);
|
||||
}
|
||||
|
||||
kfree(table->hem);
|
||||
table->hem = NULL;
|
||||
kfree(table->bt_l1);
|
||||
table->bt_l1 = NULL;
|
||||
kfree(table->bt_l1_dma_addr);
|
||||
table->bt_l1_dma_addr = NULL;
|
||||
kfree(table->bt_l0);
|
||||
table->bt_l0 = NULL;
|
||||
kfree(table->bt_l0_dma_addr);
|
||||
table->bt_l0_dma_addr = NULL;
|
||||
}
|
||||
|
||||
void hns_roce_cleanup_hem_table(struct hns_roce_dev *hr_dev,
|
||||
struct hns_roce_hem_table *table)
|
||||
{
|
||||
struct device *dev = &hr_dev->pdev->dev;
|
||||
struct device *dev = hr_dev->dev;
|
||||
unsigned long i;
|
||||
|
||||
if (hns_roce_check_whether_mhop(hr_dev, table->type)) {
|
||||
hns_roce_cleanup_mhop_hem_table(hr_dev, table);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < table->num_hem; ++i)
|
||||
if (table->hem[i]) {
|
||||
if (hr_dev->hw->clear_hem(hr_dev, table,
|
||||
i * HNS_ROCE_TABLE_CHUNK_SIZE / table->obj_size))
|
||||
i * HNS_ROCE_TABLE_CHUNK_SIZE / table->obj_size, 0))
|
||||
dev_err(dev, "Clear HEM base address failed.\n");
|
||||
|
||||
hns_roce_free_hem(hr_dev, table->hem[i]);
|
||||
@@ -401,4 +1043,7 @@ void hns_roce_cleanup_hem(struct hns_roce_dev *hr_dev)
|
||||
hns_roce_cleanup_hem_table(hr_dev, &hr_dev->qp_table.qp_table);
|
||||
hns_roce_cleanup_hem_table(hr_dev, &hr_dev->mr_table.mtpt_table);
|
||||
hns_roce_cleanup_hem_table(hr_dev, &hr_dev->mr_table.mtt_table);
|
||||
if (hns_roce_check_whether_mhop(hr_dev, HEM_TYPE_CQE))
|
||||
hns_roce_cleanup_hem_table(hr_dev,
|
||||
&hr_dev->mr_table.mtt_cqe_table);
|
||||
}
|
||||
|
@@ -47,6 +47,7 @@ enum {
|
||||
|
||||
/* UNMAP HEM */
|
||||
HEM_TYPE_MTT,
|
||||
HEM_TYPE_CQE,
|
||||
HEM_TYPE_IRRL,
|
||||
};
|
||||
|
||||
@@ -54,6 +55,18 @@ enum {
|
||||
((256 - sizeof(struct list_head) - 2 * sizeof(int)) / \
|
||||
(sizeof(struct scatterlist)))
|
||||
|
||||
#define check_whether_bt_num_3(type, hop_num) \
|
||||
(type < HEM_TYPE_MTT && hop_num == 2)
|
||||
|
||||
#define check_whether_bt_num_2(type, hop_num) \
|
||||
((type < HEM_TYPE_MTT && hop_num == 1) || \
|
||||
(type >= HEM_TYPE_MTT && hop_num == 2))
|
||||
|
||||
#define check_whether_bt_num_1(type, hop_num) \
|
||||
((type < HEM_TYPE_MTT && hop_num == HNS_ROCE_HOP_NUM_0) || \
|
||||
(type >= HEM_TYPE_MTT && hop_num == 1) || \
|
||||
(type >= HEM_TYPE_MTT && hop_num == HNS_ROCE_HOP_NUM_0))
|
||||
|
||||
enum {
|
||||
HNS_ROCE_HEM_PAGE_SHIFT = 12,
|
||||
HNS_ROCE_HEM_PAGE_SIZE = 1 << HNS_ROCE_HEM_PAGE_SHIFT,
|
||||
@@ -77,12 +90,23 @@ struct hns_roce_hem_iter {
|
||||
int page_idx;
|
||||
};
|
||||
|
||||
struct hns_roce_hem_mhop {
|
||||
u32 hop_num;
|
||||
u32 buf_chunk_size;
|
||||
u32 bt_chunk_size;
|
||||
u32 ba_l0_num;
|
||||
u32 l0_idx;/* level 0 base address table index */
|
||||
u32 l1_idx;/* level 1 base address table index */
|
||||
u32 l2_idx;/* level 2 base address table index */
|
||||
};
|
||||
|
||||
void hns_roce_free_hem(struct hns_roce_dev *hr_dev, struct hns_roce_hem *hem);
|
||||
int hns_roce_table_get(struct hns_roce_dev *hr_dev,
|
||||
struct hns_roce_hem_table *table, unsigned long obj);
|
||||
void hns_roce_table_put(struct hns_roce_dev *hr_dev,
|
||||
struct hns_roce_hem_table *table, unsigned long obj);
|
||||
void *hns_roce_table_find(struct hns_roce_hem_table *table, unsigned long obj,
|
||||
void *hns_roce_table_find(struct hns_roce_dev *hr_dev,
|
||||
struct hns_roce_hem_table *table, unsigned long obj,
|
||||
dma_addr_t *dma_handle);
|
||||
int hns_roce_table_get_range(struct hns_roce_dev *hr_dev,
|
||||
struct hns_roce_hem_table *table,
|
||||
@@ -97,6 +121,10 @@ int hns_roce_init_hem_table(struct hns_roce_dev *hr_dev,
|
||||
void hns_roce_cleanup_hem_table(struct hns_roce_dev *hr_dev,
|
||||
struct hns_roce_hem_table *table);
|
||||
void hns_roce_cleanup_hem(struct hns_roce_dev *hr_dev);
|
||||
int hns_roce_calc_hem_mhop(struct hns_roce_dev *hr_dev,
|
||||
struct hns_roce_hem_table *table, unsigned long *obj,
|
||||
struct hns_roce_hem_mhop *mhop);
|
||||
bool hns_roce_check_whether_mhop(struct hns_roce_dev *hr_dev, u32 type);
|
||||
|
||||
static inline void hns_roce_hem_first(struct hns_roce_hem *hem,
|
||||
struct hns_roce_hem_iter *iter)
|
||||
@@ -105,7 +133,7 @@ static inline void hns_roce_hem_first(struct hns_roce_hem *hem,
|
||||
iter->chunk = list_empty(&hem->chunk_list) ? NULL :
|
||||
list_entry(hem->chunk_list.next,
|
||||
struct hns_roce_hem_chunk, list);
|
||||
iter->page_idx = 0;
|
||||
iter->page_idx = 0;
|
||||
}
|
||||
|
||||
static inline int hns_roce_hem_last(struct hns_roce_hem_iter *iter)
|
||||
|
@@ -34,6 +34,7 @@
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <rdma/ib_umem.h>
|
||||
#include "hns_roce_common.h"
|
||||
#include "hns_roce_device.h"
|
||||
@@ -56,8 +57,8 @@ static void set_raddr_seg(struct hns_roce_wqe_raddr_seg *rseg, u64 remote_addr,
|
||||
rseg->len = 0;
|
||||
}
|
||||
|
||||
int hns_roce_v1_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
|
||||
struct ib_send_wr **bad_wr)
|
||||
static int hns_roce_v1_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
|
||||
struct ib_send_wr **bad_wr)
|
||||
{
|
||||
struct hns_roce_dev *hr_dev = to_hr_dev(ibqp->device);
|
||||
struct hns_roce_ah *ah = to_hr_ah(ud_wr(wr)->ah);
|
||||
@@ -316,8 +317,8 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int hns_roce_v1_post_recv(struct ib_qp *ibqp, struct ib_recv_wr *wr,
|
||||
struct ib_recv_wr **bad_wr)
|
||||
static int hns_roce_v1_post_recv(struct ib_qp *ibqp, struct ib_recv_wr *wr,
|
||||
struct ib_recv_wr **bad_wr)
|
||||
{
|
||||
int ret = 0;
|
||||
int nreq = 0;
|
||||
@@ -472,7 +473,7 @@ static void hns_roce_set_sdb_ext(struct hns_roce_dev *hr_dev, u32 ext_sdb_alept,
|
||||
dma_addr_t sdb_dma_addr;
|
||||
u32 val;
|
||||
|
||||
priv = (struct hns_roce_v1_priv *)hr_dev->hw->priv;
|
||||
priv = (struct hns_roce_v1_priv *)hr_dev->priv;
|
||||
db = &priv->db_table;
|
||||
|
||||
/* Configure extend SDB threshold */
|
||||
@@ -511,7 +512,7 @@ static void hns_roce_set_odb_ext(struct hns_roce_dev *hr_dev, u32 ext_odb_alept,
|
||||
dma_addr_t odb_dma_addr;
|
||||
u32 val;
|
||||
|
||||
priv = (struct hns_roce_v1_priv *)hr_dev->hw->priv;
|
||||
priv = (struct hns_roce_v1_priv *)hr_dev->priv;
|
||||
db = &priv->db_table;
|
||||
|
||||
/* Configure extend ODB threshold */
|
||||
@@ -547,7 +548,7 @@ static int hns_roce_db_ext_init(struct hns_roce_dev *hr_dev, u32 sdb_ext_mod,
|
||||
dma_addr_t odb_dma_addr;
|
||||
int ret = 0;
|
||||
|
||||
priv = (struct hns_roce_v1_priv *)hr_dev->hw->priv;
|
||||
priv = (struct hns_roce_v1_priv *)hr_dev->priv;
|
||||
db = &priv->db_table;
|
||||
|
||||
db->ext_db = kmalloc(sizeof(*db->ext_db), GFP_KERNEL);
|
||||
@@ -668,7 +669,7 @@ static int hns_roce_v1_rsv_lp_qp(struct hns_roce_dev *hr_dev)
|
||||
u8 port = 0;
|
||||
u8 sl;
|
||||
|
||||
priv = (struct hns_roce_v1_priv *)hr_dev->hw->priv;
|
||||
priv = (struct hns_roce_v1_priv *)hr_dev->priv;
|
||||
free_mr = &priv->free_mr;
|
||||
|
||||
/* Reserved cq for loop qp */
|
||||
@@ -816,7 +817,7 @@ static void hns_roce_v1_release_lp_qp(struct hns_roce_dev *hr_dev)
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
priv = (struct hns_roce_v1_priv *)hr_dev->hw->priv;
|
||||
priv = (struct hns_roce_v1_priv *)hr_dev->priv;
|
||||
free_mr = &priv->free_mr;
|
||||
|
||||
for (i = 0; i < HNS_ROCE_V1_RESV_QP; i++) {
|
||||
@@ -850,7 +851,7 @@ static int hns_roce_db_init(struct hns_roce_dev *hr_dev)
|
||||
u32 odb_evt_mod;
|
||||
int ret = 0;
|
||||
|
||||
priv = (struct hns_roce_v1_priv *)hr_dev->hw->priv;
|
||||
priv = (struct hns_roce_v1_priv *)hr_dev->priv;
|
||||
db = &priv->db_table;
|
||||
|
||||
memset(db, 0, sizeof(*db));
|
||||
@@ -876,7 +877,7 @@ static int hns_roce_db_init(struct hns_roce_dev *hr_dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void hns_roce_v1_recreate_lp_qp_work_fn(struct work_struct *work)
|
||||
static void hns_roce_v1_recreate_lp_qp_work_fn(struct work_struct *work)
|
||||
{
|
||||
struct hns_roce_recreate_lp_qp_work *lp_qp_work;
|
||||
struct hns_roce_dev *hr_dev;
|
||||
@@ -906,11 +907,13 @@ static int hns_roce_v1_recreate_lp_qp(struct hns_roce_dev *hr_dev)
|
||||
unsigned long end =
|
||||
msecs_to_jiffies(HNS_ROCE_V1_RECREATE_LP_QP_TIMEOUT_MSECS) + jiffies;
|
||||
|
||||
priv = (struct hns_roce_v1_priv *)hr_dev->hw->priv;
|
||||
priv = (struct hns_roce_v1_priv *)hr_dev->priv;
|
||||
free_mr = &priv->free_mr;
|
||||
|
||||
lp_qp_work = kzalloc(sizeof(struct hns_roce_recreate_lp_qp_work),
|
||||
GFP_KERNEL);
|
||||
if (!lp_qp_work)
|
||||
return -ENOMEM;
|
||||
|
||||
INIT_WORK(&(lp_qp_work->work), hns_roce_v1_recreate_lp_qp_work_fn);
|
||||
|
||||
@@ -982,7 +985,7 @@ static void hns_roce_v1_mr_free_work_fn(struct work_struct *work)
|
||||
hr_dev = to_hr_dev(mr_work->ib_dev);
|
||||
dev = &hr_dev->pdev->dev;
|
||||
|
||||
priv = (struct hns_roce_v1_priv *)hr_dev->hw->priv;
|
||||
priv = (struct hns_roce_v1_priv *)hr_dev->priv;
|
||||
free_mr = &priv->free_mr;
|
||||
mr_free_cq = free_mr->mr_free_cq;
|
||||
|
||||
@@ -1001,6 +1004,11 @@ static void hns_roce_v1_mr_free_work_fn(struct work_struct *work)
|
||||
}
|
||||
}
|
||||
|
||||
if (!ne) {
|
||||
dev_err(dev, "Reserved loop qp is absent!\n");
|
||||
goto free_work;
|
||||
}
|
||||
|
||||
do {
|
||||
ret = hns_roce_v1_poll_cq(&mr_free_cq->ib_cq, ne, wc);
|
||||
if (ret < 0) {
|
||||
@@ -1025,7 +1033,8 @@ free_work:
|
||||
kfree(mr_work);
|
||||
}
|
||||
|
||||
int hns_roce_v1_dereg_mr(struct hns_roce_dev *hr_dev, struct hns_roce_mr *mr)
|
||||
static int hns_roce_v1_dereg_mr(struct hns_roce_dev *hr_dev,
|
||||
struct hns_roce_mr *mr)
|
||||
{
|
||||
struct device *dev = &hr_dev->pdev->dev;
|
||||
struct hns_roce_mr_free_work *mr_work;
|
||||
@@ -1038,7 +1047,7 @@ int hns_roce_v1_dereg_mr(struct hns_roce_dev *hr_dev, struct hns_roce_mr *mr)
|
||||
int npages;
|
||||
int ret = 0;
|
||||
|
||||
priv = (struct hns_roce_v1_priv *)hr_dev->hw->priv;
|
||||
priv = (struct hns_roce_v1_priv *)hr_dev->priv;
|
||||
free_mr = &priv->free_mr;
|
||||
|
||||
if (mr->enabled) {
|
||||
@@ -1103,7 +1112,7 @@ static void hns_roce_db_free(struct hns_roce_dev *hr_dev)
|
||||
struct hns_roce_v1_priv *priv;
|
||||
struct hns_roce_db_table *db;
|
||||
|
||||
priv = (struct hns_roce_v1_priv *)hr_dev->hw->priv;
|
||||
priv = (struct hns_roce_v1_priv *)hr_dev->priv;
|
||||
db = &priv->db_table;
|
||||
|
||||
if (db->sdb_ext_mod) {
|
||||
@@ -1133,7 +1142,7 @@ static int hns_roce_raq_init(struct hns_roce_dev *hr_dev)
|
||||
struct hns_roce_raq_table *raq;
|
||||
struct device *dev = &hr_dev->pdev->dev;
|
||||
|
||||
priv = (struct hns_roce_v1_priv *)hr_dev->hw->priv;
|
||||
priv = (struct hns_roce_v1_priv *)hr_dev->priv;
|
||||
raq = &priv->raq_table;
|
||||
|
||||
raq->e_raq_buf = kzalloc(sizeof(*(raq->e_raq_buf)), GFP_KERNEL);
|
||||
@@ -1210,7 +1219,7 @@ static void hns_roce_raq_free(struct hns_roce_dev *hr_dev)
|
||||
struct hns_roce_v1_priv *priv;
|
||||
struct hns_roce_raq_table *raq;
|
||||
|
||||
priv = (struct hns_roce_v1_priv *)hr_dev->hw->priv;
|
||||
priv = (struct hns_roce_v1_priv *)hr_dev->priv;
|
||||
raq = &priv->raq_table;
|
||||
|
||||
dma_free_coherent(dev, HNS_ROCE_V1_RAQ_SIZE, raq->e_raq_buf->buf,
|
||||
@@ -1244,7 +1253,7 @@ static int hns_roce_bt_init(struct hns_roce_dev *hr_dev)
|
||||
struct hns_roce_v1_priv *priv;
|
||||
int ret;
|
||||
|
||||
priv = (struct hns_roce_v1_priv *)hr_dev->hw->priv;
|
||||
priv = (struct hns_roce_v1_priv *)hr_dev->priv;
|
||||
|
||||
priv->bt_table.qpc_buf.buf = dma_alloc_coherent(dev,
|
||||
HNS_ROCE_BT_RSV_BUF_SIZE, &priv->bt_table.qpc_buf.map,
|
||||
@@ -1286,7 +1295,7 @@ static void hns_roce_bt_free(struct hns_roce_dev *hr_dev)
|
||||
struct device *dev = &hr_dev->pdev->dev;
|
||||
struct hns_roce_v1_priv *priv;
|
||||
|
||||
priv = (struct hns_roce_v1_priv *)hr_dev->hw->priv;
|
||||
priv = (struct hns_roce_v1_priv *)hr_dev->priv;
|
||||
|
||||
dma_free_coherent(dev, HNS_ROCE_BT_RSV_BUF_SIZE,
|
||||
priv->bt_table.cqc_buf.buf, priv->bt_table.cqc_buf.map);
|
||||
@@ -1304,7 +1313,7 @@ static int hns_roce_tptr_init(struct hns_roce_dev *hr_dev)
|
||||
struct hns_roce_buf_list *tptr_buf;
|
||||
struct hns_roce_v1_priv *priv;
|
||||
|
||||
priv = (struct hns_roce_v1_priv *)hr_dev->hw->priv;
|
||||
priv = (struct hns_roce_v1_priv *)hr_dev->priv;
|
||||
tptr_buf = &priv->tptr_table.tptr_buf;
|
||||
|
||||
/*
|
||||
@@ -1330,7 +1339,7 @@ static void hns_roce_tptr_free(struct hns_roce_dev *hr_dev)
|
||||
struct hns_roce_buf_list *tptr_buf;
|
||||
struct hns_roce_v1_priv *priv;
|
||||
|
||||
priv = (struct hns_roce_v1_priv *)hr_dev->hw->priv;
|
||||
priv = (struct hns_roce_v1_priv *)hr_dev->priv;
|
||||
tptr_buf = &priv->tptr_table.tptr_buf;
|
||||
|
||||
dma_free_coherent(dev, HNS_ROCE_V1_TPTR_BUF_SIZE,
|
||||
@@ -1344,7 +1353,7 @@ static int hns_roce_free_mr_init(struct hns_roce_dev *hr_dev)
|
||||
struct hns_roce_v1_priv *priv;
|
||||
int ret = 0;
|
||||
|
||||
priv = (struct hns_roce_v1_priv *)hr_dev->hw->priv;
|
||||
priv = (struct hns_roce_v1_priv *)hr_dev->priv;
|
||||
free_mr = &priv->free_mr;
|
||||
|
||||
free_mr->free_mr_wq = create_singlethread_workqueue("hns_roce_free_mr");
|
||||
@@ -1368,7 +1377,7 @@ static void hns_roce_free_mr_free(struct hns_roce_dev *hr_dev)
|
||||
struct hns_roce_free_mr *free_mr;
|
||||
struct hns_roce_v1_priv *priv;
|
||||
|
||||
priv = (struct hns_roce_v1_priv *)hr_dev->hw->priv;
|
||||
priv = (struct hns_roce_v1_priv *)hr_dev->priv;
|
||||
free_mr = &priv->free_mr;
|
||||
|
||||
flush_workqueue(free_mr->free_mr_wq);
|
||||
@@ -1383,7 +1392,7 @@ static void hns_roce_free_mr_free(struct hns_roce_dev *hr_dev)
|
||||
* @enable: true -- drop reset, false -- reset
|
||||
* return 0 - success , negative --fail
|
||||
*/
|
||||
int hns_roce_v1_reset(struct hns_roce_dev *hr_dev, bool dereset)
|
||||
static int hns_roce_v1_reset(struct hns_roce_dev *hr_dev, bool dereset)
|
||||
{
|
||||
struct device_node *dsaf_node;
|
||||
struct device *dev = &hr_dev->pdev->dev;
|
||||
@@ -1432,7 +1441,7 @@ static int hns_roce_des_qp_init(struct hns_roce_dev *hr_dev)
|
||||
struct hns_roce_v1_priv *priv;
|
||||
struct hns_roce_des_qp *des_qp;
|
||||
|
||||
priv = (struct hns_roce_v1_priv *)hr_dev->hw->priv;
|
||||
priv = (struct hns_roce_v1_priv *)hr_dev->priv;
|
||||
des_qp = &priv->des_qp;
|
||||
|
||||
des_qp->requeue_flag = 1;
|
||||
@@ -1450,7 +1459,7 @@ static void hns_roce_des_qp_free(struct hns_roce_dev *hr_dev)
|
||||
struct hns_roce_v1_priv *priv;
|
||||
struct hns_roce_des_qp *des_qp;
|
||||
|
||||
priv = (struct hns_roce_v1_priv *)hr_dev->hw->priv;
|
||||
priv = (struct hns_roce_v1_priv *)hr_dev->priv;
|
||||
des_qp = &priv->des_qp;
|
||||
|
||||
des_qp->requeue_flag = 0;
|
||||
@@ -1458,7 +1467,7 @@ static void hns_roce_des_qp_free(struct hns_roce_dev *hr_dev)
|
||||
destroy_workqueue(des_qp->qp_wq);
|
||||
}
|
||||
|
||||
void hns_roce_v1_profile(struct hns_roce_dev *hr_dev)
|
||||
static int hns_roce_v1_profile(struct hns_roce_dev *hr_dev)
|
||||
{
|
||||
int i = 0;
|
||||
struct hns_roce_caps *caps = &hr_dev->caps;
|
||||
@@ -1474,7 +1483,9 @@ void hns_roce_v1_profile(struct hns_roce_dev *hr_dev)
|
||||
|
||||
caps->num_qps = HNS_ROCE_V1_MAX_QP_NUM;
|
||||
caps->max_wqes = HNS_ROCE_V1_MAX_WQE_NUM;
|
||||
caps->min_wqes = HNS_ROCE_MIN_WQE_NUM;
|
||||
caps->num_cqs = HNS_ROCE_V1_MAX_CQ_NUM;
|
||||
caps->min_cqes = HNS_ROCE_MIN_CQE_NUM;
|
||||
caps->max_cqes = HNS_ROCE_V1_MAX_CQE_NUM;
|
||||
caps->max_sq_sg = HNS_ROCE_V1_SG_NUM;
|
||||
caps->max_rq_sg = HNS_ROCE_V1_SG_NUM;
|
||||
@@ -1524,9 +1535,11 @@ void hns_roce_v1_profile(struct hns_roce_dev *hr_dev)
|
||||
caps->local_ca_ack_delay = le32_to_cpu(roce_read(hr_dev,
|
||||
ROCEE_ACK_DELAY_REG));
|
||||
caps->max_mtu = IB_MTU_2048;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hns_roce_v1_init(struct hns_roce_dev *hr_dev)
|
||||
static int hns_roce_v1_init(struct hns_roce_dev *hr_dev)
|
||||
{
|
||||
int ret;
|
||||
u32 val;
|
||||
@@ -1605,7 +1618,7 @@ error_failed_raq_init:
|
||||
return ret;
|
||||
}
|
||||
|
||||
void hns_roce_v1_exit(struct hns_roce_dev *hr_dev)
|
||||
static void hns_roce_v1_exit(struct hns_roce_dev *hr_dev)
|
||||
{
|
||||
hns_roce_port_enable(hr_dev, HNS_ROCE_PORT_DOWN);
|
||||
hns_roce_free_mr_free(hr_dev);
|
||||
@@ -1616,8 +1629,81 @@ void hns_roce_v1_exit(struct hns_roce_dev *hr_dev)
|
||||
hns_roce_db_free(hr_dev);
|
||||
}
|
||||
|
||||
void hns_roce_v1_set_gid(struct hns_roce_dev *hr_dev, u8 port, int gid_index,
|
||||
union ib_gid *gid)
|
||||
static int hns_roce_v1_cmd_pending(struct hns_roce_dev *hr_dev)
|
||||
{
|
||||
u32 status = readl(hr_dev->reg_base + ROCEE_MB6_REG);
|
||||
|
||||
return (!!(status & (1 << HCR_GO_BIT)));
|
||||
}
|
||||
|
||||
static int hns_roce_v1_post_mbox(struct hns_roce_dev *hr_dev, u64 in_param,
|
||||
u64 out_param, u32 in_modifier, u8 op_modifier,
|
||||
u16 op, u16 token, int event)
|
||||
{
|
||||
u32 __iomem *hcr = (u32 __iomem *)(hr_dev->reg_base + ROCEE_MB1_REG);
|
||||
unsigned long end;
|
||||
u32 val = 0;
|
||||
|
||||
end = msecs_to_jiffies(GO_BIT_TIMEOUT_MSECS) + jiffies;
|
||||
while (hns_roce_v1_cmd_pending(hr_dev)) {
|
||||
if (time_after(jiffies, end)) {
|
||||
dev_err(hr_dev->dev, "jiffies=%d end=%d\n",
|
||||
(int)jiffies, (int)end);
|
||||
return -EAGAIN;
|
||||
}
|
||||
cond_resched();
|
||||
}
|
||||
|
||||
roce_set_field(val, ROCEE_MB6_ROCEE_MB_CMD_M, ROCEE_MB6_ROCEE_MB_CMD_S,
|
||||
op);
|
||||
roce_set_field(val, ROCEE_MB6_ROCEE_MB_CMD_MDF_M,
|
||||
ROCEE_MB6_ROCEE_MB_CMD_MDF_S, op_modifier);
|
||||
roce_set_bit(val, ROCEE_MB6_ROCEE_MB_EVENT_S, event);
|
||||
roce_set_bit(val, ROCEE_MB6_ROCEE_MB_HW_RUN_S, 1);
|
||||
roce_set_field(val, ROCEE_MB6_ROCEE_MB_TOKEN_M,
|
||||
ROCEE_MB6_ROCEE_MB_TOKEN_S, token);
|
||||
|
||||
__raw_writeq(cpu_to_le64(in_param), hcr + 0);
|
||||
__raw_writeq(cpu_to_le64(out_param), hcr + 2);
|
||||
__raw_writel(cpu_to_le32(in_modifier), hcr + 4);
|
||||
/* Memory barrier */
|
||||
wmb();
|
||||
|
||||
__raw_writel(cpu_to_le32(val), hcr + 5);
|
||||
|
||||
mmiowb();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hns_roce_v1_chk_mbox(struct hns_roce_dev *hr_dev,
|
||||
unsigned long timeout)
|
||||
{
|
||||
u8 __iomem *hcr = hr_dev->reg_base + ROCEE_MB1_REG;
|
||||
unsigned long end = 0;
|
||||
u32 status = 0;
|
||||
|
||||
end = msecs_to_jiffies(timeout) + jiffies;
|
||||
while (hns_roce_v1_cmd_pending(hr_dev) && time_before(jiffies, end))
|
||||
cond_resched();
|
||||
|
||||
if (hns_roce_v1_cmd_pending(hr_dev)) {
|
||||
dev_err(hr_dev->dev, "[cmd_poll]hw run cmd TIMEDOUT!\n");
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
status = le32_to_cpu((__force __be32)
|
||||
__raw_readl(hcr + HCR_STATUS_OFFSET));
|
||||
if ((status & STATUS_MASK) != 0x1) {
|
||||
dev_err(hr_dev->dev, "mailbox status 0x%x!\n", status);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void hns_roce_v1_set_gid(struct hns_roce_dev *hr_dev, u8 port,
|
||||
int gid_index, union ib_gid *gid)
|
||||
{
|
||||
u32 *p = NULL;
|
||||
u8 gid_idx = 0;
|
||||
@@ -1641,7 +1727,8 @@ void hns_roce_v1_set_gid(struct hns_roce_dev *hr_dev, u8 port, int gid_index,
|
||||
(HNS_ROCE_V1_GID_NUM * gid_idx));
|
||||
}
|
||||
|
||||
void hns_roce_v1_set_mac(struct hns_roce_dev *hr_dev, u8 phy_port, u8 *addr)
|
||||
static int hns_roce_v1_set_mac(struct hns_roce_dev *hr_dev, u8 phy_port,
|
||||
u8 *addr)
|
||||
{
|
||||
u32 reg_smac_l;
|
||||
u16 reg_smac_h;
|
||||
@@ -1654,8 +1741,13 @@ void hns_roce_v1_set_mac(struct hns_roce_dev *hr_dev, u8 phy_port, u8 *addr)
|
||||
* because of smac not equal to dmac.
|
||||
* We Need to release and create reserved qp again.
|
||||
*/
|
||||
if (hr_dev->hw->dereg_mr && hns_roce_v1_recreate_lp_qp(hr_dev))
|
||||
dev_warn(&hr_dev->pdev->dev, "recreate lp qp timeout!\n");
|
||||
if (hr_dev->hw->dereg_mr) {
|
||||
int ret;
|
||||
|
||||
ret = hns_roce_v1_recreate_lp_qp(hr_dev);
|
||||
if (ret && ret != -ETIMEDOUT)
|
||||
return ret;
|
||||
}
|
||||
|
||||
p = (u32 *)(&addr[0]);
|
||||
reg_smac_l = *p;
|
||||
@@ -1670,10 +1762,12 @@ void hns_roce_v1_set_mac(struct hns_roce_dev *hr_dev, u8 phy_port, u8 *addr)
|
||||
ROCEE_SMAC_H_ROCEE_SMAC_H_S, reg_smac_h);
|
||||
roce_write(hr_dev, ROCEE_SMAC_H_0_REG + phy_port * PHY_PORT_OFFSET,
|
||||
val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void hns_roce_v1_set_mtu(struct hns_roce_dev *hr_dev, u8 phy_port,
|
||||
enum ib_mtu mtu)
|
||||
static void hns_roce_v1_set_mtu(struct hns_roce_dev *hr_dev, u8 phy_port,
|
||||
enum ib_mtu mtu)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
@@ -1685,8 +1779,8 @@ void hns_roce_v1_set_mtu(struct hns_roce_dev *hr_dev, u8 phy_port,
|
||||
val);
|
||||
}
|
||||
|
||||
int hns_roce_v1_write_mtpt(void *mb_buf, struct hns_roce_mr *mr,
|
||||
unsigned long mtpt_idx)
|
||||
static int hns_roce_v1_write_mtpt(void *mb_buf, struct hns_roce_mr *mr,
|
||||
unsigned long mtpt_idx)
|
||||
{
|
||||
struct hns_roce_v1_mpt_entry *mpt_entry;
|
||||
struct scatterlist *sg;
|
||||
@@ -1858,7 +1952,7 @@ static struct hns_roce_cqe *next_cqe_sw(struct hns_roce_cq *hr_cq)
|
||||
return get_sw_cqe(hr_cq, hr_cq->cons_index);
|
||||
}
|
||||
|
||||
void hns_roce_v1_cq_set_ci(struct hns_roce_cq *hr_cq, u32 cons_index)
|
||||
static void hns_roce_v1_cq_set_ci(struct hns_roce_cq *hr_cq, u32 cons_index)
|
||||
{
|
||||
u32 doorbell[2];
|
||||
|
||||
@@ -1931,9 +2025,10 @@ static void hns_roce_v1_cq_clean(struct hns_roce_cq *hr_cq, u32 qpn,
|
||||
spin_unlock_irq(&hr_cq->lock);
|
||||
}
|
||||
|
||||
void hns_roce_v1_write_cqc(struct hns_roce_dev *hr_dev,
|
||||
struct hns_roce_cq *hr_cq, void *mb_buf, u64 *mtts,
|
||||
dma_addr_t dma_handle, int nent, u32 vector)
|
||||
static void hns_roce_v1_write_cqc(struct hns_roce_dev *hr_dev,
|
||||
struct hns_roce_cq *hr_cq, void *mb_buf,
|
||||
u64 *mtts, dma_addr_t dma_handle, int nent,
|
||||
u32 vector)
|
||||
{
|
||||
struct hns_roce_cq_context *cq_context = NULL;
|
||||
struct hns_roce_buf_list *tptr_buf;
|
||||
@@ -1941,7 +2036,7 @@ void hns_roce_v1_write_cqc(struct hns_roce_dev *hr_dev,
|
||||
dma_addr_t tptr_dma_addr;
|
||||
int offset;
|
||||
|
||||
priv = (struct hns_roce_v1_priv *)hr_dev->hw->priv;
|
||||
priv = (struct hns_roce_v1_priv *)hr_dev->priv;
|
||||
tptr_buf = &priv->tptr_table.tptr_buf;
|
||||
|
||||
cq_context = mb_buf;
|
||||
@@ -2018,7 +2113,8 @@ void hns_roce_v1_write_cqc(struct hns_roce_dev *hr_dev,
|
||||
cq_context->cqc_byte_32 = cpu_to_le32(cq_context->cqc_byte_32);
|
||||
}
|
||||
|
||||
int hns_roce_v1_req_notify_cq(struct ib_cq *ibcq, enum ib_cq_notify_flags flags)
|
||||
static int hns_roce_v1_req_notify_cq(struct ib_cq *ibcq,
|
||||
enum ib_cq_notify_flags flags)
|
||||
{
|
||||
struct hns_roce_cq *hr_cq = to_hr_cq(ibcq);
|
||||
u32 notification_flag;
|
||||
@@ -2279,8 +2375,9 @@ int hns_roce_v1_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *wc)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int hns_roce_v1_clear_hem(struct hns_roce_dev *hr_dev,
|
||||
struct hns_roce_hem_table *table, int obj)
|
||||
static int hns_roce_v1_clear_hem(struct hns_roce_dev *hr_dev,
|
||||
struct hns_roce_hem_table *table, int obj,
|
||||
int step_idx)
|
||||
{
|
||||
struct device *dev = &hr_dev->pdev->dev;
|
||||
struct hns_roce_v1_priv *priv;
|
||||
@@ -2289,7 +2386,7 @@ int hns_roce_v1_clear_hem(struct hns_roce_dev *hr_dev,
|
||||
void __iomem *bt_cmd;
|
||||
u64 bt_ba = 0;
|
||||
|
||||
priv = (struct hns_roce_v1_priv *)hr_dev->hw->priv;
|
||||
priv = (struct hns_roce_v1_priv *)hr_dev->priv;
|
||||
|
||||
switch (table->type) {
|
||||
case HEM_TYPE_QPC:
|
||||
@@ -2441,14 +2538,14 @@ static int hns_roce_v1_m_sqp(struct ib_qp *ibqp, const struct ib_qp_attr *attr,
|
||||
int rq_pa_start;
|
||||
u32 reg_val;
|
||||
u64 *mtts;
|
||||
u32 *addr;
|
||||
u32 __iomem *addr;
|
||||
|
||||
context = kzalloc(sizeof(*context), GFP_KERNEL);
|
||||
if (!context)
|
||||
return -ENOMEM;
|
||||
|
||||
/* Search QP buf's MTTs */
|
||||
mtts = hns_roce_table_find(&hr_dev->mr_table.mtt_table,
|
||||
mtts = hns_roce_table_find(hr_dev, &hr_dev->mr_table.mtt_table,
|
||||
hr_qp->mtt.first_seg, &dma_handle);
|
||||
if (!mtts) {
|
||||
dev_err(dev, "qp buf pa find failed\n");
|
||||
@@ -2523,8 +2620,9 @@ static int hns_roce_v1_m_sqp(struct ib_qp *ibqp, const struct ib_qp_attr *attr,
|
||||
QP1C_BYTES_40_SQ_CUR_IDX_S, 0);
|
||||
|
||||
/* Copy context to QP1C register */
|
||||
addr = (u32 *)(hr_dev->reg_base + ROCEE_QP1C_CFG0_0_REG +
|
||||
hr_qp->phy_port * sizeof(*context));
|
||||
addr = (u32 __iomem *)(hr_dev->reg_base +
|
||||
ROCEE_QP1C_CFG0_0_REG +
|
||||
hr_qp->phy_port * sizeof(*context));
|
||||
|
||||
writel(context->qp1c_bytes_4, addr);
|
||||
writel(context->sq_rq_bt_l, addr + 1);
|
||||
@@ -2595,7 +2693,7 @@ static int hns_roce_v1_m_qp(struct ib_qp *ibqp, const struct ib_qp_attr *attr,
|
||||
return -ENOMEM;
|
||||
|
||||
/* Search qp buf's mtts */
|
||||
mtts = hns_roce_table_find(&hr_dev->mr_table.mtt_table,
|
||||
mtts = hns_roce_table_find(hr_dev, &hr_dev->mr_table.mtt_table,
|
||||
hr_qp->mtt.first_seg, &dma_handle);
|
||||
if (mtts == NULL) {
|
||||
dev_err(dev, "qp buf pa find failed\n");
|
||||
@@ -2603,8 +2701,8 @@ static int hns_roce_v1_m_qp(struct ib_qp *ibqp, const struct ib_qp_attr *attr,
|
||||
}
|
||||
|
||||
/* Search IRRL's mtts */
|
||||
mtts_2 = hns_roce_table_find(&hr_dev->qp_table.irrl_table, hr_qp->qpn,
|
||||
&dma_handle_2);
|
||||
mtts_2 = hns_roce_table_find(hr_dev, &hr_dev->qp_table.irrl_table,
|
||||
hr_qp->qpn, &dma_handle_2);
|
||||
if (mtts_2 == NULL) {
|
||||
dev_err(dev, "qp irrl_table find failed\n");
|
||||
goto out;
|
||||
@@ -2800,10 +2898,11 @@ static int hns_roce_v1_m_qp(struct ib_qp *ibqp, const struct ib_qp_attr *attr,
|
||||
QP_CONTEXT_QPC_BYTES_32_RESPONDER_RESOURCES_S,
|
||||
ilog2((unsigned int)attr->max_dest_rd_atomic));
|
||||
|
||||
roce_set_field(context->qpc_bytes_36,
|
||||
QP_CONTEXT_QPC_BYTES_36_DEST_QP_M,
|
||||
QP_CONTEXT_QPC_BYTES_36_DEST_QP_S,
|
||||
attr->dest_qp_num);
|
||||
if (attr_mask & IB_QP_DEST_QPN)
|
||||
roce_set_field(context->qpc_bytes_36,
|
||||
QP_CONTEXT_QPC_BYTES_36_DEST_QP_M,
|
||||
QP_CONTEXT_QPC_BYTES_36_DEST_QP_S,
|
||||
attr->dest_qp_num);
|
||||
|
||||
/* Configure GID index */
|
||||
port_num = rdma_ah_get_port_num(&attr->ah_attr);
|
||||
@@ -3143,7 +3242,7 @@ static int hns_roce_v1_m_qp(struct ib_qp *ibqp, const struct ib_qp_attr *attr,
|
||||
|
||||
if (ibqp->uobject) {
|
||||
hr_qp->rq.db_reg_l = hr_dev->reg_base +
|
||||
ROCEE_DB_OTHERS_L_0_REG +
|
||||
hr_dev->odb_offset +
|
||||
DB_REG_OFFSET * hr_dev->priv_uar.index;
|
||||
}
|
||||
|
||||
@@ -3177,9 +3276,10 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int hns_roce_v1_modify_qp(struct ib_qp *ibqp, const struct ib_qp_attr *attr,
|
||||
int attr_mask, enum ib_qp_state cur_state,
|
||||
enum ib_qp_state new_state)
|
||||
static int hns_roce_v1_modify_qp(struct ib_qp *ibqp,
|
||||
const struct ib_qp_attr *attr, int attr_mask,
|
||||
enum ib_qp_state cur_state,
|
||||
enum ib_qp_state new_state)
|
||||
{
|
||||
|
||||
if (ibqp->qp_type == IB_QPT_GSI || ibqp->qp_type == IB_QPT_SMI)
|
||||
@@ -3270,6 +3370,7 @@ static int hns_roce_v1_q_sqp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr,
|
||||
qp_attr->path_mtu = IB_MTU_256;
|
||||
qp_attr->path_mig_state = IB_MIG_ARMED;
|
||||
qp_attr->qkey = QKEY_VAL;
|
||||
qp_attr->ah_attr.type = RDMA_AH_ATTR_TYPE_ROCE;
|
||||
qp_attr->rq_psn = 0;
|
||||
qp_attr->sq_psn = 0;
|
||||
qp_attr->dest_qp_num = 1;
|
||||
@@ -3351,6 +3452,7 @@ static int hns_roce_v1_q_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr,
|
||||
QP_CONTEXT_QPC_BYTES_48_MTU_M,
|
||||
QP_CONTEXT_QPC_BYTES_48_MTU_S);
|
||||
qp_attr->path_mig_state = IB_MIG_ARMED;
|
||||
qp_attr->ah_attr.type = RDMA_AH_ATTR_TYPE_ROCE;
|
||||
if (hr_qp->ibqp.qp_type == IB_QPT_UD)
|
||||
qp_attr->qkey = QKEY_VAL;
|
||||
|
||||
@@ -3406,10 +3508,10 @@ static int hns_roce_v1_q_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr,
|
||||
QP_CONTEXT_QPC_BYTES_12_P_KEY_INDEX_S);
|
||||
qp_attr->port_num = hr_qp->port + 1;
|
||||
qp_attr->sq_draining = 0;
|
||||
qp_attr->max_rd_atomic = roce_get_field(context->qpc_bytes_156,
|
||||
qp_attr->max_rd_atomic = 1 << roce_get_field(context->qpc_bytes_156,
|
||||
QP_CONTEXT_QPC_BYTES_156_INITIATOR_DEPTH_M,
|
||||
QP_CONTEXT_QPC_BYTES_156_INITIATOR_DEPTH_S);
|
||||
qp_attr->max_dest_rd_atomic = roce_get_field(context->qpc_bytes_32,
|
||||
qp_attr->max_dest_rd_atomic = 1 << roce_get_field(context->qpc_bytes_32,
|
||||
QP_CONTEXT_QPC_BYTES_32_RESPONDER_RESOURCES_M,
|
||||
QP_CONTEXT_QPC_BYTES_32_RESPONDER_RESOURCES_S);
|
||||
qp_attr->min_rnr_timer = (u8)(roce_get_field(context->qpc_bytes_24,
|
||||
@@ -3444,8 +3546,9 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int hns_roce_v1_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr,
|
||||
int qp_attr_mask, struct ib_qp_init_attr *qp_init_attr)
|
||||
static int hns_roce_v1_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr,
|
||||
int qp_attr_mask,
|
||||
struct ib_qp_init_attr *qp_init_attr)
|
||||
{
|
||||
struct hns_roce_qp *hr_qp = to_hr_qp(ibqp);
|
||||
|
||||
@@ -3454,6 +3557,53 @@ int hns_roce_v1_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr,
|
||||
hns_roce_v1_q_qp(ibqp, qp_attr, qp_attr_mask, qp_init_attr);
|
||||
}
|
||||
|
||||
static void hns_roce_check_sdb_status(struct hns_roce_dev *hr_dev,
|
||||
u32 *old_send, u32 *old_retry,
|
||||
u32 *tsp_st, u32 *success_flags)
|
||||
{
|
||||
u32 sdb_retry_cnt;
|
||||
u32 sdb_send_ptr;
|
||||
u32 cur_cnt, old_cnt;
|
||||
u32 send_ptr;
|
||||
|
||||
sdb_send_ptr = roce_read(hr_dev, ROCEE_SDB_SEND_PTR_REG);
|
||||
sdb_retry_cnt = roce_read(hr_dev, ROCEE_SDB_RETRY_CNT_REG);
|
||||
cur_cnt = roce_get_field(sdb_send_ptr,
|
||||
ROCEE_SDB_SEND_PTR_SDB_SEND_PTR_M,
|
||||
ROCEE_SDB_SEND_PTR_SDB_SEND_PTR_S) +
|
||||
roce_get_field(sdb_retry_cnt,
|
||||
ROCEE_SDB_RETRY_CNT_SDB_RETRY_CT_M,
|
||||
ROCEE_SDB_RETRY_CNT_SDB_RETRY_CT_S);
|
||||
if (!roce_get_bit(*tsp_st, ROCEE_CNT_CLR_CE_CNT_CLR_CE_S)) {
|
||||
old_cnt = roce_get_field(*old_send,
|
||||
ROCEE_SDB_SEND_PTR_SDB_SEND_PTR_M,
|
||||
ROCEE_SDB_SEND_PTR_SDB_SEND_PTR_S) +
|
||||
roce_get_field(*old_retry,
|
||||
ROCEE_SDB_RETRY_CNT_SDB_RETRY_CT_M,
|
||||
ROCEE_SDB_RETRY_CNT_SDB_RETRY_CT_S);
|
||||
if (cur_cnt - old_cnt > SDB_ST_CMP_VAL)
|
||||
*success_flags = 1;
|
||||
} else {
|
||||
old_cnt = roce_get_field(*old_send,
|
||||
ROCEE_SDB_SEND_PTR_SDB_SEND_PTR_M,
|
||||
ROCEE_SDB_SEND_PTR_SDB_SEND_PTR_S);
|
||||
if (cur_cnt - old_cnt > SDB_ST_CMP_VAL) {
|
||||
*success_flags = 1;
|
||||
} else {
|
||||
send_ptr = roce_get_field(*old_send,
|
||||
ROCEE_SDB_SEND_PTR_SDB_SEND_PTR_M,
|
||||
ROCEE_SDB_SEND_PTR_SDB_SEND_PTR_S) +
|
||||
roce_get_field(sdb_retry_cnt,
|
||||
ROCEE_SDB_RETRY_CNT_SDB_RETRY_CT_M,
|
||||
ROCEE_SDB_RETRY_CNT_SDB_RETRY_CT_S);
|
||||
roce_set_field(*old_send,
|
||||
ROCEE_SDB_SEND_PTR_SDB_SEND_PTR_M,
|
||||
ROCEE_SDB_SEND_PTR_SDB_SEND_PTR_S,
|
||||
send_ptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int check_qp_db_process_status(struct hns_roce_dev *hr_dev,
|
||||
struct hns_roce_qp *hr_qp,
|
||||
u32 sdb_issue_ptr,
|
||||
@@ -3461,12 +3611,10 @@ static int check_qp_db_process_status(struct hns_roce_dev *hr_dev,
|
||||
u32 *wait_stage)
|
||||
{
|
||||
struct device *dev = &hr_dev->pdev->dev;
|
||||
u32 sdb_retry_cnt, old_retry;
|
||||
u32 sdb_send_ptr, old_send;
|
||||
u32 success_flags = 0;
|
||||
u32 cur_cnt, old_cnt;
|
||||
unsigned long end;
|
||||
u32 send_ptr;
|
||||
u32 old_retry;
|
||||
u32 inv_cnt;
|
||||
u32 tsp_st;
|
||||
|
||||
@@ -3524,47 +3672,9 @@ static int check_qp_db_process_status(struct hns_roce_dev *hr_dev,
|
||||
|
||||
msleep(HNS_ROCE_V1_CHECK_DB_SLEEP_MSECS);
|
||||
|
||||
sdb_send_ptr = roce_read(hr_dev,
|
||||
ROCEE_SDB_SEND_PTR_REG);
|
||||
sdb_retry_cnt = roce_read(hr_dev,
|
||||
ROCEE_SDB_RETRY_CNT_REG);
|
||||
cur_cnt = roce_get_field(sdb_send_ptr,
|
||||
ROCEE_SDB_SEND_PTR_SDB_SEND_PTR_M,
|
||||
ROCEE_SDB_SEND_PTR_SDB_SEND_PTR_S) +
|
||||
roce_get_field(sdb_retry_cnt,
|
||||
ROCEE_SDB_RETRY_CNT_SDB_RETRY_CT_M,
|
||||
ROCEE_SDB_RETRY_CNT_SDB_RETRY_CT_S);
|
||||
if (!roce_get_bit(tsp_st,
|
||||
ROCEE_CNT_CLR_CE_CNT_CLR_CE_S)) {
|
||||
old_cnt = roce_get_field(old_send,
|
||||
ROCEE_SDB_SEND_PTR_SDB_SEND_PTR_M,
|
||||
ROCEE_SDB_SEND_PTR_SDB_SEND_PTR_S) +
|
||||
roce_get_field(old_retry,
|
||||
ROCEE_SDB_RETRY_CNT_SDB_RETRY_CT_M,
|
||||
ROCEE_SDB_RETRY_CNT_SDB_RETRY_CT_S);
|
||||
if (cur_cnt - old_cnt > SDB_ST_CMP_VAL)
|
||||
success_flags = 1;
|
||||
} else {
|
||||
old_cnt = roce_get_field(old_send,
|
||||
ROCEE_SDB_SEND_PTR_SDB_SEND_PTR_M,
|
||||
ROCEE_SDB_SEND_PTR_SDB_SEND_PTR_S);
|
||||
if (cur_cnt - old_cnt >
|
||||
SDB_ST_CMP_VAL) {
|
||||
success_flags = 1;
|
||||
} else {
|
||||
send_ptr =
|
||||
roce_get_field(old_send,
|
||||
ROCEE_SDB_SEND_PTR_SDB_SEND_PTR_M,
|
||||
ROCEE_SDB_SEND_PTR_SDB_SEND_PTR_S) +
|
||||
roce_get_field(sdb_retry_cnt,
|
||||
ROCEE_SDB_RETRY_CNT_SDB_RETRY_CT_M,
|
||||
ROCEE_SDB_RETRY_CNT_SDB_RETRY_CT_S);
|
||||
roce_set_field(old_send,
|
||||
ROCEE_SDB_SEND_PTR_SDB_SEND_PTR_M,
|
||||
ROCEE_SDB_SEND_PTR_SDB_SEND_PTR_S,
|
||||
send_ptr);
|
||||
}
|
||||
}
|
||||
hns_roce_check_sdb_status(hr_dev, &old_send,
|
||||
&old_retry, &tsp_st,
|
||||
&success_flags);
|
||||
} while (!success_flags);
|
||||
}
|
||||
|
||||
@@ -3664,7 +3774,7 @@ static void hns_roce_v1_destroy_qp_work_fn(struct work_struct *work)
|
||||
qp_work_entry = container_of(work, struct hns_roce_qp_work, work);
|
||||
hr_dev = to_hr_dev(qp_work_entry->ib_dev);
|
||||
dev = &hr_dev->pdev->dev;
|
||||
priv = (struct hns_roce_v1_priv *)hr_dev->hw->priv;
|
||||
priv = (struct hns_roce_v1_priv *)hr_dev->priv;
|
||||
hr_qp = qp_work_entry->qp;
|
||||
qpn = hr_qp->qpn;
|
||||
|
||||
@@ -3781,7 +3891,7 @@ int hns_roce_v1_destroy_qp(struct ib_qp *ibqp)
|
||||
qp_work->sdb_inv_cnt = qp_work_entry.sdb_inv_cnt;
|
||||
qp_work->sche_cnt = qp_work_entry.sche_cnt;
|
||||
|
||||
priv = (struct hns_roce_v1_priv *)hr_dev->hw->priv;
|
||||
priv = (struct hns_roce_v1_priv *)hr_dev->priv;
|
||||
queue_work(priv->des_qp.qp_wq, &qp_work->work);
|
||||
dev_dbg(dev, "Begin destroy QP(0x%lx) work.\n", hr_qp->qpn);
|
||||
}
|
||||
@@ -3789,7 +3899,7 @@ int hns_roce_v1_destroy_qp(struct ib_qp *ibqp)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hns_roce_v1_destroy_cq(struct ib_cq *ibcq)
|
||||
static int hns_roce_v1_destroy_cq(struct ib_cq *ibcq)
|
||||
{
|
||||
struct hns_roce_dev *hr_dev = to_hr_dev(ibcq->device);
|
||||
struct hns_roce_cq *hr_cq = to_hr_cq(ibcq);
|
||||
@@ -3841,13 +3951,13 @@ int hns_roce_v1_destroy_cq(struct ib_cq *ibcq)
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct hns_roce_v1_priv hr_v1_priv;
|
||||
|
||||
struct hns_roce_hw hns_roce_hw_v1 = {
|
||||
static const struct hns_roce_hw hns_roce_hw_v1 = {
|
||||
.reset = hns_roce_v1_reset,
|
||||
.hw_profile = hns_roce_v1_profile,
|
||||
.hw_init = hns_roce_v1_init,
|
||||
.hw_exit = hns_roce_v1_exit,
|
||||
.post_mbox = hns_roce_v1_post_mbox,
|
||||
.chk_mbox = hns_roce_v1_chk_mbox,
|
||||
.set_gid = hns_roce_v1_set_gid,
|
||||
.set_mac = hns_roce_v1_set_mac,
|
||||
.set_mtu = hns_roce_v1_set_mtu,
|
||||
@@ -3863,5 +3973,258 @@ struct hns_roce_hw hns_roce_hw_v1 = {
|
||||
.poll_cq = hns_roce_v1_poll_cq,
|
||||
.dereg_mr = hns_roce_v1_dereg_mr,
|
||||
.destroy_cq = hns_roce_v1_destroy_cq,
|
||||
.priv = &hr_v1_priv,
|
||||
};
|
||||
|
||||
static const struct of_device_id hns_roce_of_match[] = {
|
||||
{ .compatible = "hisilicon,hns-roce-v1", .data = &hns_roce_hw_v1, },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, hns_roce_of_match);
|
||||
|
||||
static const struct acpi_device_id hns_roce_acpi_match[] = {
|
||||
{ "HISI00D1", (kernel_ulong_t)&hns_roce_hw_v1 },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(acpi, hns_roce_acpi_match);
|
||||
|
||||
static int hns_roce_node_match(struct device *dev, void *fwnode)
|
||||
{
|
||||
return dev->fwnode == fwnode;
|
||||
}
|
||||
|
||||
static struct
|
||||
platform_device *hns_roce_find_pdev(struct fwnode_handle *fwnode)
|
||||
{
|
||||
struct device *dev;
|
||||
|
||||
/* get the 'device' corresponding to the matching 'fwnode' */
|
||||
dev = bus_find_device(&platform_bus_type, NULL,
|
||||
fwnode, hns_roce_node_match);
|
||||
/* get the platform device */
|
||||
return dev ? to_platform_device(dev) : NULL;
|
||||
}
|
||||
|
||||
static int hns_roce_get_cfg(struct hns_roce_dev *hr_dev)
|
||||
{
|
||||
struct device *dev = &hr_dev->pdev->dev;
|
||||
struct platform_device *pdev = NULL;
|
||||
struct net_device *netdev = NULL;
|
||||
struct device_node *net_node;
|
||||
struct resource *res;
|
||||
int port_cnt = 0;
|
||||
u8 phy_port;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
/* check if we are compatible with the underlying SoC */
|
||||
if (dev_of_node(dev)) {
|
||||
const struct of_device_id *of_id;
|
||||
|
||||
of_id = of_match_node(hns_roce_of_match, dev->of_node);
|
||||
if (!of_id) {
|
||||
dev_err(dev, "device is not compatible!\n");
|
||||
return -ENXIO;
|
||||
}
|
||||
hr_dev->hw = (const struct hns_roce_hw *)of_id->data;
|
||||
if (!hr_dev->hw) {
|
||||
dev_err(dev, "couldn't get H/W specific DT data!\n");
|
||||
return -ENXIO;
|
||||
}
|
||||
} else if (is_acpi_device_node(dev->fwnode)) {
|
||||
const struct acpi_device_id *acpi_id;
|
||||
|
||||
acpi_id = acpi_match_device(hns_roce_acpi_match, dev);
|
||||
if (!acpi_id) {
|
||||
dev_err(dev, "device is not compatible!\n");
|
||||
return -ENXIO;
|
||||
}
|
||||
hr_dev->hw = (const struct hns_roce_hw *) acpi_id->driver_data;
|
||||
if (!hr_dev->hw) {
|
||||
dev_err(dev, "couldn't get H/W specific ACPI data!\n");
|
||||
return -ENXIO;
|
||||
}
|
||||
} else {
|
||||
dev_err(dev, "can't read compatibility data from DT or ACPI\n");
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
/* get the mapped register base address */
|
||||
res = platform_get_resource(hr_dev->pdev, IORESOURCE_MEM, 0);
|
||||
if (!res) {
|
||||
dev_err(dev, "memory resource not found!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
hr_dev->reg_base = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(hr_dev->reg_base))
|
||||
return PTR_ERR(hr_dev->reg_base);
|
||||
|
||||
/* read the node_guid of IB device from the DT or ACPI */
|
||||
ret = device_property_read_u8_array(dev, "node-guid",
|
||||
(u8 *)&hr_dev->ib_dev.node_guid,
|
||||
GUID_LEN);
|
||||
if (ret) {
|
||||
dev_err(dev, "couldn't get node_guid from DT or ACPI!\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* get the RoCE associated ethernet ports or netdevices */
|
||||
for (i = 0; i < HNS_ROCE_MAX_PORTS; i++) {
|
||||
if (dev_of_node(dev)) {
|
||||
net_node = of_parse_phandle(dev->of_node, "eth-handle",
|
||||
i);
|
||||
if (!net_node)
|
||||
continue;
|
||||
pdev = of_find_device_by_node(net_node);
|
||||
} else if (is_acpi_device_node(dev->fwnode)) {
|
||||
struct acpi_reference_args args;
|
||||
struct fwnode_handle *fwnode;
|
||||
|
||||
ret = acpi_node_get_property_reference(dev->fwnode,
|
||||
"eth-handle",
|
||||
i, &args);
|
||||
if (ret)
|
||||
continue;
|
||||
fwnode = acpi_fwnode_handle(args.adev);
|
||||
pdev = hns_roce_find_pdev(fwnode);
|
||||
} else {
|
||||
dev_err(dev, "cannot read data from DT or ACPI\n");
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
if (pdev) {
|
||||
netdev = platform_get_drvdata(pdev);
|
||||
phy_port = (u8)i;
|
||||
if (netdev) {
|
||||
hr_dev->iboe.netdevs[port_cnt] = netdev;
|
||||
hr_dev->iboe.phy_port[port_cnt] = phy_port;
|
||||
} else {
|
||||
dev_err(dev, "no netdev found with pdev %s\n",
|
||||
pdev->name);
|
||||
return -ENODEV;
|
||||
}
|
||||
port_cnt++;
|
||||
}
|
||||
}
|
||||
|
||||
if (port_cnt == 0) {
|
||||
dev_err(dev, "unable to get eth-handle for available ports!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
hr_dev->caps.num_ports = port_cnt;
|
||||
|
||||
/* cmd issue mode: 0 is poll, 1 is event */
|
||||
hr_dev->cmd_mod = 1;
|
||||
hr_dev->loop_idc = 0;
|
||||
hr_dev->sdb_offset = ROCEE_DB_SQ_L_0_REG;
|
||||
hr_dev->odb_offset = ROCEE_DB_OTHERS_L_0_REG;
|
||||
|
||||
/* read the interrupt names from the DT or ACPI */
|
||||
ret = device_property_read_string_array(dev, "interrupt-names",
|
||||
hr_dev->irq_names,
|
||||
HNS_ROCE_MAX_IRQ_NUM);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "couldn't get interrupt names from DT or ACPI!\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* fetch the interrupt numbers */
|
||||
for (i = 0; i < HNS_ROCE_MAX_IRQ_NUM; i++) {
|
||||
hr_dev->irq[i] = platform_get_irq(hr_dev->pdev, i);
|
||||
if (hr_dev->irq[i] <= 0) {
|
||||
dev_err(dev, "platform get of irq[=%d] failed!\n", i);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* hns_roce_probe - RoCE driver entrance
|
||||
* @pdev: pointer to platform device
|
||||
* Return : int
|
||||
*
|
||||
*/
|
||||
static int hns_roce_probe(struct platform_device *pdev)
|
||||
{
|
||||
int ret;
|
||||
struct hns_roce_dev *hr_dev;
|
||||
struct device *dev = &pdev->dev;
|
||||
|
||||
hr_dev = (struct hns_roce_dev *)ib_alloc_device(sizeof(*hr_dev));
|
||||
if (!hr_dev)
|
||||
return -ENOMEM;
|
||||
|
||||
hr_dev->priv = kzalloc(sizeof(struct hns_roce_v1_priv), GFP_KERNEL);
|
||||
if (!hr_dev->priv) {
|
||||
ret = -ENOMEM;
|
||||
goto error_failed_kzalloc;
|
||||
}
|
||||
|
||||
hr_dev->pdev = pdev;
|
||||
hr_dev->dev = dev;
|
||||
platform_set_drvdata(pdev, hr_dev);
|
||||
|
||||
if (dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64ULL)) &&
|
||||
dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32ULL))) {
|
||||
dev_err(dev, "Not usable DMA addressing mode\n");
|
||||
ret = -EIO;
|
||||
goto error_failed_get_cfg;
|
||||
}
|
||||
|
||||
ret = hns_roce_get_cfg(hr_dev);
|
||||
if (ret) {
|
||||
dev_err(dev, "Get Configuration failed!\n");
|
||||
goto error_failed_get_cfg;
|
||||
}
|
||||
|
||||
ret = hns_roce_init(hr_dev);
|
||||
if (ret) {
|
||||
dev_err(dev, "RoCE engine init failed!\n");
|
||||
goto error_failed_get_cfg;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
error_failed_get_cfg:
|
||||
kfree(hr_dev->priv);
|
||||
|
||||
error_failed_kzalloc:
|
||||
ib_dealloc_device(&hr_dev->ib_dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* hns_roce_remove - remove RoCE device
|
||||
* @pdev: pointer to platform device
|
||||
*/
|
||||
static int hns_roce_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct hns_roce_dev *hr_dev = platform_get_drvdata(pdev);
|
||||
|
||||
hns_roce_exit(hr_dev);
|
||||
kfree(hr_dev->priv);
|
||||
ib_dealloc_device(&hr_dev->ib_dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver hns_roce_driver = {
|
||||
.probe = hns_roce_probe,
|
||||
.remove = hns_roce_remove,
|
||||
.driver = {
|
||||
.name = DRV_NAME,
|
||||
.of_match_table = hns_roce_of_match,
|
||||
.acpi_match_table = ACPI_PTR(hns_roce_acpi_match),
|
||||
},
|
||||
};
|
||||
|
||||
module_platform_driver(hns_roce_driver);
|
||||
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
||||
MODULE_AUTHOR("Wei Hu <xavier.huwei@huawei.com>");
|
||||
MODULE_AUTHOR("Nenglong Zhao <zhaonenglong@hisilicon.com>");
|
||||
MODULE_AUTHOR("Lijun Ou <oulijun@huawei.com>");
|
||||
MODULE_DESCRIPTION("Hisilicon Hip06 Family RoCE Driver");
|
||||
|
@@ -948,6 +948,11 @@ struct hns_roce_qp_context {
|
||||
#define QP_CONTEXT_QPC_BYTES_188_TX_RETRY_CUR_INDEX_M \
|
||||
(((1UL << 15) - 1) << QP_CONTEXT_QPC_BYTES_188_TX_RETRY_CUR_INDEX_S)
|
||||
|
||||
#define STATUS_MASK 0xff
|
||||
#define GO_BIT_TIMEOUT_MSECS 10000
|
||||
#define HCR_STATUS_OFFSET 0x18
|
||||
#define HCR_GO_BIT 15
|
||||
|
||||
struct hns_roce_rq_db {
|
||||
u32 u32_4;
|
||||
u32 u32_8;
|
||||
|
3133
drivers/infiniband/hw/hns/hns_roce_hw_v2.c
Normal file
3133
drivers/infiniband/hw/hns/hns_roce_hw_v2.c
Normal file
Filskillnaden har hållits tillbaka eftersom den är för stor
Load Diff
1165
drivers/infiniband/hw/hns/hns_roce_hw_v2.h
Normal file
1165
drivers/infiniband/hw/hns/hns_roce_hw_v2.h
Normal file
Filskillnaden har hållits tillbaka eftersom den är för stor
Load Diff
@@ -57,20 +57,21 @@ int hns_get_gid_index(struct hns_roce_dev *hr_dev, u8 port, int gid_index)
|
||||
{
|
||||
return gid_index * hr_dev->caps.num_ports + port;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(hns_get_gid_index);
|
||||
|
||||
static void hns_roce_set_mac(struct hns_roce_dev *hr_dev, u8 port, u8 *addr)
|
||||
static int hns_roce_set_mac(struct hns_roce_dev *hr_dev, u8 port, u8 *addr)
|
||||
{
|
||||
u8 phy_port;
|
||||
u32 i = 0;
|
||||
|
||||
if (!memcmp(hr_dev->dev_addr[port], addr, MAC_ADDR_OCTET_NUM))
|
||||
return;
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < MAC_ADDR_OCTET_NUM; i++)
|
||||
hr_dev->dev_addr[port][i] = addr[i];
|
||||
|
||||
phy_port = hr_dev->iboe.phy_port[port];
|
||||
hr_dev->hw->set_mac(hr_dev, phy_port, addr);
|
||||
return hr_dev->hw->set_mac(hr_dev, phy_port, addr);
|
||||
}
|
||||
|
||||
static int hns_roce_add_gid(struct ib_device *device, u8 port_num,
|
||||
@@ -116,8 +117,9 @@ static int hns_roce_del_gid(struct ib_device *device, u8 port_num,
|
||||
static int handle_en_event(struct hns_roce_dev *hr_dev, u8 port,
|
||||
unsigned long event)
|
||||
{
|
||||
struct device *dev = &hr_dev->pdev->dev;
|
||||
struct device *dev = hr_dev->dev;
|
||||
struct net_device *netdev;
|
||||
int ret = 0;
|
||||
|
||||
netdev = hr_dev->iboe.netdevs[port];
|
||||
if (!netdev) {
|
||||
@@ -130,7 +132,7 @@ static int handle_en_event(struct hns_roce_dev *hr_dev, u8 port,
|
||||
case NETDEV_CHANGE:
|
||||
case NETDEV_REGISTER:
|
||||
case NETDEV_CHANGEADDR:
|
||||
hns_roce_set_mac(hr_dev, port, netdev->dev_addr);
|
||||
ret = hns_roce_set_mac(hr_dev, port, netdev->dev_addr);
|
||||
break;
|
||||
case NETDEV_DOWN:
|
||||
/*
|
||||
@@ -142,7 +144,7 @@ static int handle_en_event(struct hns_roce_dev *hr_dev, u8 port,
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int hns_roce_netdev_event(struct notifier_block *self,
|
||||
@@ -171,12 +173,17 @@ static int hns_roce_netdev_event(struct notifier_block *self,
|
||||
|
||||
static int hns_roce_setup_mtu_mac(struct hns_roce_dev *hr_dev)
|
||||
{
|
||||
int ret;
|
||||
u8 i;
|
||||
|
||||
for (i = 0; i < hr_dev->caps.num_ports; i++) {
|
||||
hr_dev->hw->set_mtu(hr_dev, hr_dev->iboe.phy_port[i],
|
||||
hr_dev->caps.max_mtu);
|
||||
hns_roce_set_mac(hr_dev, i, hr_dev->iboe.netdevs[i]->dev_addr);
|
||||
if (hr_dev->hw->set_mtu)
|
||||
hr_dev->hw->set_mtu(hr_dev, hr_dev->iboe.phy_port[i],
|
||||
hr_dev->caps.max_mtu);
|
||||
ret = hns_roce_set_mac(hr_dev, i,
|
||||
hr_dev->iboe.netdevs[i]->dev_addr);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -200,7 +207,7 @@ static int hns_roce_query_device(struct ib_device *ib_dev,
|
||||
props->max_qp_wr = hr_dev->caps.max_wqes;
|
||||
props->device_cap_flags = IB_DEVICE_PORT_ACTIVE_EVENT |
|
||||
IB_DEVICE_RC_RNR_NAK_GEN;
|
||||
props->max_sge = hr_dev->caps.max_sq_sg;
|
||||
props->max_sge = max(hr_dev->caps.max_sq_sg, hr_dev->caps.max_rq_sg);
|
||||
props->max_sge_rd = 1;
|
||||
props->max_cq = hr_dev->caps.num_cqs;
|
||||
props->max_cqe = hr_dev->caps.max_cqes;
|
||||
@@ -238,7 +245,7 @@ static int hns_roce_query_port(struct ib_device *ib_dev, u8 port_num,
|
||||
struct ib_port_attr *props)
|
||||
{
|
||||
struct hns_roce_dev *hr_dev = to_hr_dev(ib_dev);
|
||||
struct device *dev = &hr_dev->pdev->dev;
|
||||
struct device *dev = hr_dev->dev;
|
||||
struct net_device *net_dev;
|
||||
unsigned long flags;
|
||||
enum ib_mtu mtu;
|
||||
@@ -379,7 +386,8 @@ static int hns_roce_mmap(struct ib_ucontext *context,
|
||||
to_hr_ucontext(context)->uar.pfn,
|
||||
PAGE_SIZE, vma->vm_page_prot))
|
||||
return -EAGAIN;
|
||||
} else if (vma->vm_pgoff == 1 && hr_dev->hw_rev == HNS_ROCE_HW_VER1) {
|
||||
} else if (vma->vm_pgoff == 1 && hr_dev->tptr_dma_addr &&
|
||||
hr_dev->tptr_size) {
|
||||
/* vm_pgoff: 1 -- TPTR */
|
||||
if (io_remap_pfn_range(vma, vma->vm_start,
|
||||
hr_dev->tptr_dma_addr >> PAGE_SHIFT,
|
||||
@@ -416,7 +424,6 @@ static void hns_roce_unregister_device(struct hns_roce_dev *hr_dev)
|
||||
{
|
||||
struct hns_roce_ib_iboe *iboe = &hr_dev->iboe;
|
||||
|
||||
unregister_inetaddr_notifier(&iboe->nb_inet);
|
||||
unregister_netdevice_notifier(&iboe->nb);
|
||||
ib_unregister_device(&hr_dev->ib_dev);
|
||||
}
|
||||
@@ -426,7 +433,7 @@ static int hns_roce_register_device(struct hns_roce_dev *hr_dev)
|
||||
int ret;
|
||||
struct hns_roce_ib_iboe *iboe = NULL;
|
||||
struct ib_device *ib_dev = NULL;
|
||||
struct device *dev = &hr_dev->pdev->dev;
|
||||
struct device *dev = hr_dev->dev;
|
||||
|
||||
iboe = &hr_dev->iboe;
|
||||
spin_lock_init(&iboe->lock);
|
||||
@@ -531,173 +538,10 @@ error_failed_setup_mtu_mac:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct of_device_id hns_roce_of_match[] = {
|
||||
{ .compatible = "hisilicon,hns-roce-v1", .data = &hns_roce_hw_v1, },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, hns_roce_of_match);
|
||||
|
||||
static const struct acpi_device_id hns_roce_acpi_match[] = {
|
||||
{ "HISI00D1", (kernel_ulong_t)&hns_roce_hw_v1 },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(acpi, hns_roce_acpi_match);
|
||||
|
||||
static int hns_roce_node_match(struct device *dev, void *fwnode)
|
||||
{
|
||||
return dev->fwnode == fwnode;
|
||||
}
|
||||
|
||||
static struct
|
||||
platform_device *hns_roce_find_pdev(struct fwnode_handle *fwnode)
|
||||
{
|
||||
struct device *dev;
|
||||
|
||||
/* get the 'device'corresponding to matching 'fwnode' */
|
||||
dev = bus_find_device(&platform_bus_type, NULL,
|
||||
fwnode, hns_roce_node_match);
|
||||
/* get the platform device */
|
||||
return dev ? to_platform_device(dev) : NULL;
|
||||
}
|
||||
|
||||
static int hns_roce_get_cfg(struct hns_roce_dev *hr_dev)
|
||||
{
|
||||
int i;
|
||||
int ret;
|
||||
u8 phy_port;
|
||||
int port_cnt = 0;
|
||||
struct device *dev = &hr_dev->pdev->dev;
|
||||
struct device_node *net_node;
|
||||
struct net_device *netdev = NULL;
|
||||
struct platform_device *pdev = NULL;
|
||||
struct resource *res;
|
||||
|
||||
/* check if we are compatible with the underlying SoC */
|
||||
if (dev_of_node(dev)) {
|
||||
const struct of_device_id *of_id;
|
||||
|
||||
of_id = of_match_node(hns_roce_of_match, dev->of_node);
|
||||
if (!of_id) {
|
||||
dev_err(dev, "device is not compatible!\n");
|
||||
return -ENXIO;
|
||||
}
|
||||
hr_dev->hw = (struct hns_roce_hw *)of_id->data;
|
||||
if (!hr_dev->hw) {
|
||||
dev_err(dev, "couldn't get H/W specific DT data!\n");
|
||||
return -ENXIO;
|
||||
}
|
||||
} else if (is_acpi_device_node(dev->fwnode)) {
|
||||
const struct acpi_device_id *acpi_id;
|
||||
|
||||
acpi_id = acpi_match_device(hns_roce_acpi_match, dev);
|
||||
if (!acpi_id) {
|
||||
dev_err(dev, "device is not compatible!\n");
|
||||
return -ENXIO;
|
||||
}
|
||||
hr_dev->hw = (struct hns_roce_hw *) acpi_id->driver_data;
|
||||
if (!hr_dev->hw) {
|
||||
dev_err(dev, "couldn't get H/W specific ACPI data!\n");
|
||||
return -ENXIO;
|
||||
}
|
||||
} else {
|
||||
dev_err(dev, "can't read compatibility data from DT or ACPI\n");
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
/* get the mapped register base address */
|
||||
res = platform_get_resource(hr_dev->pdev, IORESOURCE_MEM, 0);
|
||||
if (!res) {
|
||||
dev_err(dev, "memory resource not found!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
hr_dev->reg_base = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(hr_dev->reg_base))
|
||||
return PTR_ERR(hr_dev->reg_base);
|
||||
|
||||
/* read the node_guid of IB device from the DT or ACPI */
|
||||
ret = device_property_read_u8_array(dev, "node-guid",
|
||||
(u8 *)&hr_dev->ib_dev.node_guid,
|
||||
GUID_LEN);
|
||||
if (ret) {
|
||||
dev_err(dev, "couldn't get node_guid from DT or ACPI!\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* get the RoCE associated ethernet ports or netdevices */
|
||||
for (i = 0; i < HNS_ROCE_MAX_PORTS; i++) {
|
||||
if (dev_of_node(dev)) {
|
||||
net_node = of_parse_phandle(dev->of_node, "eth-handle",
|
||||
i);
|
||||
if (!net_node)
|
||||
continue;
|
||||
pdev = of_find_device_by_node(net_node);
|
||||
} else if (is_acpi_device_node(dev->fwnode)) {
|
||||
struct acpi_reference_args args;
|
||||
struct fwnode_handle *fwnode;
|
||||
|
||||
ret = acpi_node_get_property_reference(dev->fwnode,
|
||||
"eth-handle",
|
||||
i, &args);
|
||||
if (ret)
|
||||
continue;
|
||||
fwnode = acpi_fwnode_handle(args.adev);
|
||||
pdev = hns_roce_find_pdev(fwnode);
|
||||
} else {
|
||||
dev_err(dev, "cannot read data from DT or ACPI\n");
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
if (pdev) {
|
||||
netdev = platform_get_drvdata(pdev);
|
||||
phy_port = (u8)i;
|
||||
if (netdev) {
|
||||
hr_dev->iboe.netdevs[port_cnt] = netdev;
|
||||
hr_dev->iboe.phy_port[port_cnt] = phy_port;
|
||||
} else {
|
||||
dev_err(dev, "no netdev found with pdev %s\n",
|
||||
pdev->name);
|
||||
return -ENODEV;
|
||||
}
|
||||
port_cnt++;
|
||||
}
|
||||
}
|
||||
|
||||
if (port_cnt == 0) {
|
||||
dev_err(dev, "unable to get eth-handle for available ports!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
hr_dev->caps.num_ports = port_cnt;
|
||||
|
||||
/* cmd issue mode: 0 is poll, 1 is event */
|
||||
hr_dev->cmd_mod = 1;
|
||||
hr_dev->loop_idc = 0;
|
||||
|
||||
/* read the interrupt names from the DT or ACPI */
|
||||
ret = device_property_read_string_array(dev, "interrupt-names",
|
||||
hr_dev->irq_names,
|
||||
HNS_ROCE_MAX_IRQ_NUM);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "couldn't get interrupt names from DT or ACPI!\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* fetch the interrupt numbers */
|
||||
for (i = 0; i < HNS_ROCE_MAX_IRQ_NUM; i++) {
|
||||
hr_dev->irq[i] = platform_get_irq(hr_dev->pdev, i);
|
||||
if (hr_dev->irq[i] <= 0) {
|
||||
dev_err(dev, "platform get of irq[=%d] failed!\n", i);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hns_roce_init_hem(struct hns_roce_dev *hr_dev)
|
||||
{
|
||||
int ret;
|
||||
struct device *dev = &hr_dev->pdev->dev;
|
||||
struct device *dev = hr_dev->dev;
|
||||
|
||||
ret = hns_roce_init_hem_table(hr_dev, &hr_dev->mr_table.mtt_table,
|
||||
HEM_TYPE_MTT, hr_dev->caps.mtt_entry_sz,
|
||||
@@ -707,6 +551,17 @@ static int hns_roce_init_hem(struct hns_roce_dev *hr_dev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (hns_roce_check_whether_mhop(hr_dev, HEM_TYPE_CQE)) {
|
||||
ret = hns_roce_init_hem_table(hr_dev,
|
||||
&hr_dev->mr_table.mtt_cqe_table,
|
||||
HEM_TYPE_CQE, hr_dev->caps.mtt_entry_sz,
|
||||
hr_dev->caps.num_cqe_segs, 1);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to init MTT CQE context memory, aborting.\n");
|
||||
goto err_unmap_cqe;
|
||||
}
|
||||
}
|
||||
|
||||
ret = hns_roce_init_hem_table(hr_dev, &hr_dev->mr_table.mtpt_table,
|
||||
HEM_TYPE_MTPT, hr_dev->caps.mtpt_entry_sz,
|
||||
hr_dev->caps.num_mtpts, 1);
|
||||
@@ -754,6 +609,12 @@ err_unmap_dmpt:
|
||||
|
||||
err_unmap_mtt:
|
||||
hns_roce_cleanup_hem_table(hr_dev, &hr_dev->mr_table.mtt_table);
|
||||
if (hns_roce_check_whether_mhop(hr_dev, HEM_TYPE_CQE))
|
||||
hns_roce_cleanup_hem_table(hr_dev,
|
||||
&hr_dev->mr_table.mtt_cqe_table);
|
||||
|
||||
err_unmap_cqe:
|
||||
hns_roce_cleanup_hem_table(hr_dev, &hr_dev->mr_table.mtt_table);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -766,7 +627,7 @@ err_unmap_mtt:
|
||||
static int hns_roce_setup_hca(struct hns_roce_dev *hr_dev)
|
||||
{
|
||||
int ret;
|
||||
struct device *dev = &hr_dev->pdev->dev;
|
||||
struct device *dev = hr_dev->dev;
|
||||
|
||||
spin_lock_init(&hr_dev->sm_lock);
|
||||
spin_lock_init(&hr_dev->bt_cmd_lock);
|
||||
@@ -826,56 +687,45 @@ err_uar_table_free:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* hns_roce_probe - RoCE driver entrance
|
||||
* @pdev: pointer to platform device
|
||||
* Return : int
|
||||
*
|
||||
*/
|
||||
static int hns_roce_probe(struct platform_device *pdev)
|
||||
int hns_roce_init(struct hns_roce_dev *hr_dev)
|
||||
{
|
||||
int ret;
|
||||
struct hns_roce_dev *hr_dev;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct device *dev = hr_dev->dev;
|
||||
|
||||
hr_dev = (struct hns_roce_dev *)ib_alloc_device(sizeof(*hr_dev));
|
||||
if (!hr_dev)
|
||||
return -ENOMEM;
|
||||
|
||||
hr_dev->pdev = pdev;
|
||||
platform_set_drvdata(pdev, hr_dev);
|
||||
|
||||
if (dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64ULL)) &&
|
||||
dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32ULL))) {
|
||||
dev_err(dev, "Not usable DMA addressing mode\n");
|
||||
ret = -EIO;
|
||||
goto error_failed_get_cfg;
|
||||
if (hr_dev->hw->reset) {
|
||||
ret = hr_dev->hw->reset(hr_dev, true);
|
||||
if (ret) {
|
||||
dev_err(dev, "Reset RoCE engine failed!\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
ret = hns_roce_get_cfg(hr_dev);
|
||||
if (hr_dev->hw->cmq_init) {
|
||||
ret = hr_dev->hw->cmq_init(hr_dev);
|
||||
if (ret) {
|
||||
dev_err(dev, "Init RoCE Command Queue failed!\n");
|
||||
goto error_failed_cmq_init;
|
||||
}
|
||||
}
|
||||
|
||||
ret = hr_dev->hw->hw_profile(hr_dev);
|
||||
if (ret) {
|
||||
dev_err(dev, "Get Configuration failed!\n");
|
||||
goto error_failed_get_cfg;
|
||||
dev_err(dev, "Get RoCE engine profile failed!\n");
|
||||
goto error_failed_cmd_init;
|
||||
}
|
||||
|
||||
ret = hr_dev->hw->reset(hr_dev, true);
|
||||
if (ret) {
|
||||
dev_err(dev, "Reset RoCE engine failed!\n");
|
||||
goto error_failed_get_cfg;
|
||||
}
|
||||
|
||||
hr_dev->hw->hw_profile(hr_dev);
|
||||
|
||||
ret = hns_roce_cmd_init(hr_dev);
|
||||
if (ret) {
|
||||
dev_err(dev, "cmd init failed!\n");
|
||||
goto error_failed_cmd_init;
|
||||
}
|
||||
|
||||
ret = hns_roce_init_eq_table(hr_dev);
|
||||
if (ret) {
|
||||
dev_err(dev, "eq init failed!\n");
|
||||
goto error_failed_eq_table;
|
||||
if (hr_dev->cmd_mod) {
|
||||
ret = hns_roce_init_eq_table(hr_dev);
|
||||
if (ret) {
|
||||
dev_err(dev, "eq init failed!\n");
|
||||
goto error_failed_eq_table;
|
||||
}
|
||||
}
|
||||
|
||||
if (hr_dev->cmd_mod) {
|
||||
@@ -898,10 +748,12 @@ static int hns_roce_probe(struct platform_device *pdev)
|
||||
goto error_failed_setup_hca;
|
||||
}
|
||||
|
||||
ret = hr_dev->hw->hw_init(hr_dev);
|
||||
if (ret) {
|
||||
dev_err(dev, "hw_init failed!\n");
|
||||
goto error_failed_engine_init;
|
||||
if (hr_dev->hw->hw_init) {
|
||||
ret = hr_dev->hw->hw_init(hr_dev);
|
||||
if (ret) {
|
||||
dev_err(dev, "hw_init failed!\n");
|
||||
goto error_failed_engine_init;
|
||||
}
|
||||
}
|
||||
|
||||
ret = hns_roce_register_device(hr_dev);
|
||||
@@ -911,7 +763,8 @@ static int hns_roce_probe(struct platform_device *pdev)
|
||||
return 0;
|
||||
|
||||
error_failed_register_device:
|
||||
hr_dev->hw->hw_exit(hr_dev);
|
||||
if (hr_dev->hw->hw_exit)
|
||||
hr_dev->hw->hw_exit(hr_dev);
|
||||
|
||||
error_failed_engine_init:
|
||||
hns_roce_cleanup_bitmap(hr_dev);
|
||||
@@ -924,58 +777,47 @@ error_failed_init_hem:
|
||||
hns_roce_cmd_use_polling(hr_dev);
|
||||
|
||||
error_failed_use_event:
|
||||
hns_roce_cleanup_eq_table(hr_dev);
|
||||
if (hr_dev->cmd_mod)
|
||||
hns_roce_cleanup_eq_table(hr_dev);
|
||||
|
||||
error_failed_eq_table:
|
||||
hns_roce_cmd_cleanup(hr_dev);
|
||||
|
||||
error_failed_cmd_init:
|
||||
ret = hr_dev->hw->reset(hr_dev, false);
|
||||
if (ret)
|
||||
dev_err(&hr_dev->pdev->dev, "roce_engine reset fail\n");
|
||||
if (hr_dev->hw->cmq_exit)
|
||||
hr_dev->hw->cmq_exit(hr_dev);
|
||||
|
||||
error_failed_get_cfg:
|
||||
ib_dealloc_device(&hr_dev->ib_dev);
|
||||
error_failed_cmq_init:
|
||||
if (hr_dev->hw->reset) {
|
||||
ret = hr_dev->hw->reset(hr_dev, false);
|
||||
if (ret)
|
||||
dev_err(dev, "Dereset RoCE engine failed!\n");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(hns_roce_init);
|
||||
|
||||
/**
|
||||
* hns_roce_remove - remove RoCE device
|
||||
* @pdev: pointer to platform device
|
||||
*/
|
||||
static int hns_roce_remove(struct platform_device *pdev)
|
||||
void hns_roce_exit(struct hns_roce_dev *hr_dev)
|
||||
{
|
||||
struct hns_roce_dev *hr_dev = platform_get_drvdata(pdev);
|
||||
|
||||
hns_roce_unregister_device(hr_dev);
|
||||
hr_dev->hw->hw_exit(hr_dev);
|
||||
if (hr_dev->hw->hw_exit)
|
||||
hr_dev->hw->hw_exit(hr_dev);
|
||||
hns_roce_cleanup_bitmap(hr_dev);
|
||||
hns_roce_cleanup_hem(hr_dev);
|
||||
|
||||
if (hr_dev->cmd_mod)
|
||||
hns_roce_cmd_use_polling(hr_dev);
|
||||
|
||||
hns_roce_cleanup_eq_table(hr_dev);
|
||||
if (hr_dev->cmd_mod)
|
||||
hns_roce_cleanup_eq_table(hr_dev);
|
||||
hns_roce_cmd_cleanup(hr_dev);
|
||||
hr_dev->hw->reset(hr_dev, false);
|
||||
|
||||
ib_dealloc_device(&hr_dev->ib_dev);
|
||||
|
||||
return 0;
|
||||
if (hr_dev->hw->cmq_exit)
|
||||
hr_dev->hw->cmq_exit(hr_dev);
|
||||
if (hr_dev->hw->reset)
|
||||
hr_dev->hw->reset(hr_dev, false);
|
||||
}
|
||||
|
||||
static struct platform_driver hns_roce_driver = {
|
||||
.probe = hns_roce_probe,
|
||||
.remove = hns_roce_remove,
|
||||
.driver = {
|
||||
.name = DRV_NAME,
|
||||
.of_match_table = hns_roce_of_match,
|
||||
.acpi_match_table = ACPI_PTR(hns_roce_acpi_match),
|
||||
},
|
||||
};
|
||||
|
||||
module_platform_driver(hns_roce_driver);
|
||||
EXPORT_SYMBOL_GPL(hns_roce_exit);
|
||||
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
||||
MODULE_AUTHOR("Wei Hu <xavier.huwei@huawei.com>");
|
||||
|
@@ -47,6 +47,7 @@ unsigned long key_to_hw_index(u32 key)
|
||||
{
|
||||
return (key << 24) | (key >> 8);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(key_to_hw_index);
|
||||
|
||||
static int hns_roce_sw2hw_mpt(struct hns_roce_dev *hr_dev,
|
||||
struct hns_roce_cmd_mailbox *mailbox,
|
||||
@@ -65,6 +66,7 @@ int hns_roce_hw2sw_mpt(struct hns_roce_dev *hr_dev,
|
||||
mpt_index, !mailbox, HNS_ROCE_CMD_HW2SW_MPT,
|
||||
HNS_ROCE_CMD_TIMEOUT_MSECS);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(hns_roce_hw2sw_mpt);
|
||||
|
||||
static int hns_roce_buddy_alloc(struct hns_roce_buddy *buddy, int order,
|
||||
unsigned long *seg)
|
||||
@@ -175,18 +177,28 @@ static void hns_roce_buddy_cleanup(struct hns_roce_buddy *buddy)
|
||||
}
|
||||
|
||||
static int hns_roce_alloc_mtt_range(struct hns_roce_dev *hr_dev, int order,
|
||||
unsigned long *seg)
|
||||
unsigned long *seg, u32 mtt_type)
|
||||
{
|
||||
struct hns_roce_mr_table *mr_table = &hr_dev->mr_table;
|
||||
int ret = 0;
|
||||
struct hns_roce_hem_table *table;
|
||||
struct hns_roce_buddy *buddy;
|
||||
int ret;
|
||||
|
||||
ret = hns_roce_buddy_alloc(&mr_table->mtt_buddy, order, seg);
|
||||
if (mtt_type == MTT_TYPE_WQE) {
|
||||
buddy = &mr_table->mtt_buddy;
|
||||
table = &mr_table->mtt_table;
|
||||
} else {
|
||||
buddy = &mr_table->mtt_cqe_buddy;
|
||||
table = &mr_table->mtt_cqe_table;
|
||||
}
|
||||
|
||||
ret = hns_roce_buddy_alloc(buddy, order, seg);
|
||||
if (ret == -1)
|
||||
return -1;
|
||||
|
||||
if (hns_roce_table_get_range(hr_dev, &mr_table->mtt_table, *seg,
|
||||
if (hns_roce_table_get_range(hr_dev, table, *seg,
|
||||
*seg + (1 << order) - 1)) {
|
||||
hns_roce_buddy_free(&mr_table->mtt_buddy, *seg, order);
|
||||
hns_roce_buddy_free(buddy, *seg, order);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -196,7 +208,7 @@ static int hns_roce_alloc_mtt_range(struct hns_roce_dev *hr_dev, int order,
|
||||
int hns_roce_mtt_init(struct hns_roce_dev *hr_dev, int npages, int page_shift,
|
||||
struct hns_roce_mtt *mtt)
|
||||
{
|
||||
int ret = 0;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
/* Page num is zero, correspond to DMA memory register */
|
||||
@@ -215,7 +227,8 @@ int hns_roce_mtt_init(struct hns_roce_dev *hr_dev, int npages, int page_shift,
|
||||
++mtt->order;
|
||||
|
||||
/* Allocate MTT entry */
|
||||
ret = hns_roce_alloc_mtt_range(hr_dev, mtt->order, &mtt->first_seg);
|
||||
ret = hns_roce_alloc_mtt_range(hr_dev, mtt->order, &mtt->first_seg,
|
||||
mtt->mtt_type);
|
||||
if (ret == -1)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -229,18 +242,261 @@ void hns_roce_mtt_cleanup(struct hns_roce_dev *hr_dev, struct hns_roce_mtt *mtt)
|
||||
if (mtt->order < 0)
|
||||
return;
|
||||
|
||||
hns_roce_buddy_free(&mr_table->mtt_buddy, mtt->first_seg, mtt->order);
|
||||
hns_roce_table_put_range(hr_dev, &mr_table->mtt_table, mtt->first_seg,
|
||||
mtt->first_seg + (1 << mtt->order) - 1);
|
||||
if (mtt->mtt_type == MTT_TYPE_WQE) {
|
||||
hns_roce_buddy_free(&mr_table->mtt_buddy, mtt->first_seg,
|
||||
mtt->order);
|
||||
hns_roce_table_put_range(hr_dev, &mr_table->mtt_table,
|
||||
mtt->first_seg,
|
||||
mtt->first_seg + (1 << mtt->order) - 1);
|
||||
} else {
|
||||
hns_roce_buddy_free(&mr_table->mtt_cqe_buddy, mtt->first_seg,
|
||||
mtt->order);
|
||||
hns_roce_table_put_range(hr_dev, &mr_table->mtt_cqe_table,
|
||||
mtt->first_seg,
|
||||
mtt->first_seg + (1 << mtt->order) - 1);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(hns_roce_mtt_cleanup);
|
||||
|
||||
static void hns_roce_loop_free(struct hns_roce_dev *hr_dev,
|
||||
struct hns_roce_mr *mr, int err_loop_index,
|
||||
int loop_i, int loop_j)
|
||||
{
|
||||
struct device *dev = hr_dev->dev;
|
||||
u32 mhop_num;
|
||||
u32 pbl_bt_sz;
|
||||
u64 bt_idx;
|
||||
int i, j;
|
||||
|
||||
pbl_bt_sz = 1 << (hr_dev->caps.pbl_ba_pg_sz + PAGE_SHIFT);
|
||||
mhop_num = hr_dev->caps.pbl_hop_num;
|
||||
|
||||
i = loop_i;
|
||||
if (mhop_num == 3 && err_loop_index == 2) {
|
||||
for (; i >= 0; i--) {
|
||||
dma_free_coherent(dev, pbl_bt_sz, mr->pbl_bt_l1[i],
|
||||
mr->pbl_l1_dma_addr[i]);
|
||||
|
||||
for (j = 0; j < pbl_bt_sz / 8; j++) {
|
||||
if (i == loop_i && j >= loop_j)
|
||||
break;
|
||||
|
||||
bt_idx = i * pbl_bt_sz / 8 + j;
|
||||
dma_free_coherent(dev, pbl_bt_sz,
|
||||
mr->pbl_bt_l2[bt_idx],
|
||||
mr->pbl_l2_dma_addr[bt_idx]);
|
||||
}
|
||||
}
|
||||
} else if (mhop_num == 3 && err_loop_index == 1) {
|
||||
for (i -= 1; i >= 0; i--) {
|
||||
dma_free_coherent(dev, pbl_bt_sz, mr->pbl_bt_l1[i],
|
||||
mr->pbl_l1_dma_addr[i]);
|
||||
|
||||
for (j = 0; j < pbl_bt_sz / 8; j++) {
|
||||
bt_idx = i * pbl_bt_sz / 8 + j;
|
||||
dma_free_coherent(dev, pbl_bt_sz,
|
||||
mr->pbl_bt_l2[bt_idx],
|
||||
mr->pbl_l2_dma_addr[bt_idx]);
|
||||
}
|
||||
}
|
||||
} else if (mhop_num == 2 && err_loop_index == 1) {
|
||||
for (i -= 1; i >= 0; i--)
|
||||
dma_free_coherent(dev, pbl_bt_sz, mr->pbl_bt_l1[i],
|
||||
mr->pbl_l1_dma_addr[i]);
|
||||
} else {
|
||||
dev_warn(dev, "not support: mhop_num=%d, err_loop_index=%d.",
|
||||
mhop_num, err_loop_index);
|
||||
return;
|
||||
}
|
||||
|
||||
dma_free_coherent(dev, pbl_bt_sz, mr->pbl_bt_l0, mr->pbl_l0_dma_addr);
|
||||
mr->pbl_bt_l0 = NULL;
|
||||
mr->pbl_l0_dma_addr = 0;
|
||||
}
|
||||
|
||||
/* PBL multi hop addressing */
|
||||
static int hns_roce_mhop_alloc(struct hns_roce_dev *hr_dev, int npages,
|
||||
struct hns_roce_mr *mr)
|
||||
{
|
||||
struct device *dev = hr_dev->dev;
|
||||
int mr_alloc_done = 0;
|
||||
int npages_allocated;
|
||||
int i = 0, j = 0;
|
||||
u32 pbl_bt_sz;
|
||||
u32 mhop_num;
|
||||
u64 pbl_last_bt_num;
|
||||
u64 pbl_bt_cnt = 0;
|
||||
u64 bt_idx;
|
||||
u64 size;
|
||||
|
||||
mhop_num = hr_dev->caps.pbl_hop_num;
|
||||
pbl_bt_sz = 1 << (hr_dev->caps.pbl_ba_pg_sz + PAGE_SHIFT);
|
||||
pbl_last_bt_num = (npages + pbl_bt_sz / 8 - 1) / (pbl_bt_sz / 8);
|
||||
|
||||
if (mhop_num == HNS_ROCE_HOP_NUM_0)
|
||||
return 0;
|
||||
|
||||
/* hop_num = 1 */
|
||||
if (mhop_num == 1) {
|
||||
if (npages > pbl_bt_sz / 8) {
|
||||
dev_err(dev, "npages %d is larger than buf_pg_sz!",
|
||||
npages);
|
||||
return -EINVAL;
|
||||
}
|
||||
mr->pbl_buf = dma_alloc_coherent(dev, npages * 8,
|
||||
&(mr->pbl_dma_addr),
|
||||
GFP_KERNEL);
|
||||
if (!mr->pbl_buf)
|
||||
return -ENOMEM;
|
||||
|
||||
mr->pbl_size = npages;
|
||||
mr->pbl_ba = mr->pbl_dma_addr;
|
||||
mr->pbl_hop_num = hr_dev->caps.pbl_hop_num;
|
||||
mr->pbl_ba_pg_sz = hr_dev->caps.pbl_ba_pg_sz;
|
||||
mr->pbl_buf_pg_sz = hr_dev->caps.pbl_buf_pg_sz;
|
||||
return 0;
|
||||
}
|
||||
|
||||
mr->pbl_l1_dma_addr = kcalloc(pbl_bt_sz / 8,
|
||||
sizeof(*mr->pbl_l1_dma_addr),
|
||||
GFP_KERNEL);
|
||||
if (!mr->pbl_l1_dma_addr)
|
||||
return -ENOMEM;
|
||||
|
||||
mr->pbl_bt_l1 = kcalloc(pbl_bt_sz / 8, sizeof(*mr->pbl_bt_l1),
|
||||
GFP_KERNEL);
|
||||
if (!mr->pbl_bt_l1)
|
||||
goto err_kcalloc_bt_l1;
|
||||
|
||||
if (mhop_num == 3) {
|
||||
mr->pbl_l2_dma_addr = kcalloc(pbl_last_bt_num,
|
||||
sizeof(*mr->pbl_l2_dma_addr),
|
||||
GFP_KERNEL);
|
||||
if (!mr->pbl_l2_dma_addr)
|
||||
goto err_kcalloc_l2_dma;
|
||||
|
||||
mr->pbl_bt_l2 = kcalloc(pbl_last_bt_num,
|
||||
sizeof(*mr->pbl_bt_l2),
|
||||
GFP_KERNEL);
|
||||
if (!mr->pbl_bt_l2)
|
||||
goto err_kcalloc_bt_l2;
|
||||
}
|
||||
|
||||
/* alloc L0 BT */
|
||||
mr->pbl_bt_l0 = dma_alloc_coherent(dev, pbl_bt_sz,
|
||||
&(mr->pbl_l0_dma_addr),
|
||||
GFP_KERNEL);
|
||||
if (!mr->pbl_bt_l0)
|
||||
goto err_dma_alloc_l0;
|
||||
|
||||
if (mhop_num == 2) {
|
||||
/* alloc L1 BT */
|
||||
for (i = 0; i < pbl_bt_sz / 8; i++) {
|
||||
if (pbl_bt_cnt + 1 < pbl_last_bt_num) {
|
||||
size = pbl_bt_sz;
|
||||
} else {
|
||||
npages_allocated = i * (pbl_bt_sz / 8);
|
||||
size = (npages - npages_allocated) * 8;
|
||||
}
|
||||
mr->pbl_bt_l1[i] = dma_alloc_coherent(dev, size,
|
||||
&(mr->pbl_l1_dma_addr[i]),
|
||||
GFP_KERNEL);
|
||||
if (!mr->pbl_bt_l1[i]) {
|
||||
hns_roce_loop_free(hr_dev, mr, 1, i, 0);
|
||||
goto err_dma_alloc_l0;
|
||||
}
|
||||
|
||||
*(mr->pbl_bt_l0 + i) = mr->pbl_l1_dma_addr[i];
|
||||
|
||||
pbl_bt_cnt++;
|
||||
if (pbl_bt_cnt >= pbl_last_bt_num)
|
||||
break;
|
||||
}
|
||||
} else if (mhop_num == 3) {
|
||||
/* alloc L1, L2 BT */
|
||||
for (i = 0; i < pbl_bt_sz / 8; i++) {
|
||||
mr->pbl_bt_l1[i] = dma_alloc_coherent(dev, pbl_bt_sz,
|
||||
&(mr->pbl_l1_dma_addr[i]),
|
||||
GFP_KERNEL);
|
||||
if (!mr->pbl_bt_l1[i]) {
|
||||
hns_roce_loop_free(hr_dev, mr, 1, i, 0);
|
||||
goto err_dma_alloc_l0;
|
||||
}
|
||||
|
||||
*(mr->pbl_bt_l0 + i) = mr->pbl_l1_dma_addr[i];
|
||||
|
||||
for (j = 0; j < pbl_bt_sz / 8; j++) {
|
||||
bt_idx = i * pbl_bt_sz / 8 + j;
|
||||
|
||||
if (pbl_bt_cnt + 1 < pbl_last_bt_num) {
|
||||
size = pbl_bt_sz;
|
||||
} else {
|
||||
npages_allocated = bt_idx *
|
||||
(pbl_bt_sz / 8);
|
||||
size = (npages - npages_allocated) * 8;
|
||||
}
|
||||
mr->pbl_bt_l2[bt_idx] = dma_alloc_coherent(
|
||||
dev, size,
|
||||
&(mr->pbl_l2_dma_addr[bt_idx]),
|
||||
GFP_KERNEL);
|
||||
if (!mr->pbl_bt_l2[bt_idx]) {
|
||||
hns_roce_loop_free(hr_dev, mr, 2, i, j);
|
||||
goto err_dma_alloc_l0;
|
||||
}
|
||||
|
||||
*(mr->pbl_bt_l1[i] + j) =
|
||||
mr->pbl_l2_dma_addr[bt_idx];
|
||||
|
||||
pbl_bt_cnt++;
|
||||
if (pbl_bt_cnt >= pbl_last_bt_num) {
|
||||
mr_alloc_done = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (mr_alloc_done)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
mr->l0_chunk_last_num = i + 1;
|
||||
if (mhop_num == 3)
|
||||
mr->l1_chunk_last_num = j + 1;
|
||||
|
||||
mr->pbl_size = npages;
|
||||
mr->pbl_ba = mr->pbl_l0_dma_addr;
|
||||
mr->pbl_hop_num = hr_dev->caps.pbl_hop_num;
|
||||
mr->pbl_ba_pg_sz = hr_dev->caps.pbl_ba_pg_sz;
|
||||
mr->pbl_buf_pg_sz = hr_dev->caps.pbl_buf_pg_sz;
|
||||
|
||||
return 0;
|
||||
|
||||
err_dma_alloc_l0:
|
||||
kfree(mr->pbl_bt_l2);
|
||||
mr->pbl_bt_l2 = NULL;
|
||||
|
||||
err_kcalloc_bt_l2:
|
||||
kfree(mr->pbl_l2_dma_addr);
|
||||
mr->pbl_l2_dma_addr = NULL;
|
||||
|
||||
err_kcalloc_l2_dma:
|
||||
kfree(mr->pbl_bt_l1);
|
||||
mr->pbl_bt_l1 = NULL;
|
||||
|
||||
err_kcalloc_bt_l1:
|
||||
kfree(mr->pbl_l1_dma_addr);
|
||||
mr->pbl_l1_dma_addr = NULL;
|
||||
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
static int hns_roce_mr_alloc(struct hns_roce_dev *hr_dev, u32 pd, u64 iova,
|
||||
u64 size, u32 access, int npages,
|
||||
struct hns_roce_mr *mr)
|
||||
{
|
||||
struct device *dev = hr_dev->dev;
|
||||
unsigned long index = 0;
|
||||
int ret = 0;
|
||||
struct device *dev = &hr_dev->pdev->dev;
|
||||
|
||||
/* Allocate a key for mr from mr_table */
|
||||
ret = hns_roce_bitmap_alloc(&hr_dev->mr_table.mtpt_bitmap, &index);
|
||||
@@ -258,22 +514,117 @@ static int hns_roce_mr_alloc(struct hns_roce_dev *hr_dev, u32 pd, u64 iova,
|
||||
mr->type = MR_TYPE_DMA;
|
||||
mr->pbl_buf = NULL;
|
||||
mr->pbl_dma_addr = 0;
|
||||
/* PBL multi-hop addressing parameters */
|
||||
mr->pbl_bt_l2 = NULL;
|
||||
mr->pbl_bt_l1 = NULL;
|
||||
mr->pbl_bt_l0 = NULL;
|
||||
mr->pbl_l2_dma_addr = NULL;
|
||||
mr->pbl_l1_dma_addr = NULL;
|
||||
mr->pbl_l0_dma_addr = 0;
|
||||
} else {
|
||||
mr->type = MR_TYPE_MR;
|
||||
mr->pbl_buf = dma_alloc_coherent(dev, npages * 8,
|
||||
&(mr->pbl_dma_addr),
|
||||
GFP_KERNEL);
|
||||
if (!mr->pbl_buf)
|
||||
return -ENOMEM;
|
||||
if (!hr_dev->caps.pbl_hop_num) {
|
||||
mr->pbl_buf = dma_alloc_coherent(dev, npages * 8,
|
||||
&(mr->pbl_dma_addr),
|
||||
GFP_KERNEL);
|
||||
if (!mr->pbl_buf)
|
||||
return -ENOMEM;
|
||||
} else {
|
||||
ret = hns_roce_mhop_alloc(hr_dev, npages, mr);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void hns_roce_mhop_free(struct hns_roce_dev *hr_dev,
|
||||
struct hns_roce_mr *mr)
|
||||
{
|
||||
struct device *dev = hr_dev->dev;
|
||||
int npages_allocated;
|
||||
int npages;
|
||||
int i, j;
|
||||
u32 pbl_bt_sz;
|
||||
u32 mhop_num;
|
||||
u64 bt_idx;
|
||||
|
||||
npages = ib_umem_page_count(mr->umem);
|
||||
pbl_bt_sz = 1 << (hr_dev->caps.pbl_ba_pg_sz + PAGE_SHIFT);
|
||||
mhop_num = hr_dev->caps.pbl_hop_num;
|
||||
|
||||
if (mhop_num == HNS_ROCE_HOP_NUM_0)
|
||||
return;
|
||||
|
||||
/* hop_num = 1 */
|
||||
if (mhop_num == 1) {
|
||||
dma_free_coherent(dev, (unsigned int)(npages * 8),
|
||||
mr->pbl_buf, mr->pbl_dma_addr);
|
||||
return;
|
||||
}
|
||||
|
||||
dma_free_coherent(dev, pbl_bt_sz, mr->pbl_bt_l0,
|
||||
mr->pbl_l0_dma_addr);
|
||||
|
||||
if (mhop_num == 2) {
|
||||
for (i = 0; i < mr->l0_chunk_last_num; i++) {
|
||||
if (i == mr->l0_chunk_last_num - 1) {
|
||||
npages_allocated = i * (pbl_bt_sz / 8);
|
||||
|
||||
dma_free_coherent(dev,
|
||||
(npages - npages_allocated) * 8,
|
||||
mr->pbl_bt_l1[i],
|
||||
mr->pbl_l1_dma_addr[i]);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
dma_free_coherent(dev, pbl_bt_sz, mr->pbl_bt_l1[i],
|
||||
mr->pbl_l1_dma_addr[i]);
|
||||
}
|
||||
} else if (mhop_num == 3) {
|
||||
for (i = 0; i < mr->l0_chunk_last_num; i++) {
|
||||
dma_free_coherent(dev, pbl_bt_sz, mr->pbl_bt_l1[i],
|
||||
mr->pbl_l1_dma_addr[i]);
|
||||
|
||||
for (j = 0; j < pbl_bt_sz / 8; j++) {
|
||||
bt_idx = i * (pbl_bt_sz / 8) + j;
|
||||
|
||||
if ((i == mr->l0_chunk_last_num - 1)
|
||||
&& j == mr->l1_chunk_last_num - 1) {
|
||||
npages_allocated = bt_idx *
|
||||
(pbl_bt_sz / 8);
|
||||
|
||||
dma_free_coherent(dev,
|
||||
(npages - npages_allocated) * 8,
|
||||
mr->pbl_bt_l2[bt_idx],
|
||||
mr->pbl_l2_dma_addr[bt_idx]);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
dma_free_coherent(dev, pbl_bt_sz,
|
||||
mr->pbl_bt_l2[bt_idx],
|
||||
mr->pbl_l2_dma_addr[bt_idx]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
kfree(mr->pbl_bt_l1);
|
||||
kfree(mr->pbl_l1_dma_addr);
|
||||
mr->pbl_bt_l1 = NULL;
|
||||
mr->pbl_l1_dma_addr = NULL;
|
||||
if (mhop_num == 3) {
|
||||
kfree(mr->pbl_bt_l2);
|
||||
kfree(mr->pbl_l2_dma_addr);
|
||||
mr->pbl_bt_l2 = NULL;
|
||||
mr->pbl_l2_dma_addr = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void hns_roce_mr_free(struct hns_roce_dev *hr_dev,
|
||||
struct hns_roce_mr *mr)
|
||||
{
|
||||
struct device *dev = &hr_dev->pdev->dev;
|
||||
struct device *dev = hr_dev->dev;
|
||||
int npages = 0;
|
||||
int ret;
|
||||
|
||||
@@ -286,10 +637,18 @@ static void hns_roce_mr_free(struct hns_roce_dev *hr_dev,
|
||||
|
||||
if (mr->size != ~0ULL) {
|
||||
npages = ib_umem_page_count(mr->umem);
|
||||
dma_free_coherent(dev, (unsigned int)(npages * 8), mr->pbl_buf,
|
||||
mr->pbl_dma_addr);
|
||||
|
||||
if (!hr_dev->caps.pbl_hop_num)
|
||||
dma_free_coherent(dev, (unsigned int)(npages * 8),
|
||||
mr->pbl_buf, mr->pbl_dma_addr);
|
||||
else
|
||||
hns_roce_mhop_free(hr_dev, mr);
|
||||
}
|
||||
|
||||
if (mr->enabled)
|
||||
hns_roce_table_put(hr_dev, &hr_dev->mr_table.mtpt_table,
|
||||
key_to_hw_index(mr->key));
|
||||
|
||||
hns_roce_bitmap_free(&hr_dev->mr_table.mtpt_bitmap,
|
||||
key_to_hw_index(mr->key), BITMAP_NO_RR);
|
||||
}
|
||||
@@ -299,7 +658,7 @@ static int hns_roce_mr_enable(struct hns_roce_dev *hr_dev,
|
||||
{
|
||||
int ret;
|
||||
unsigned long mtpt_idx = key_to_hw_index(mr->key);
|
||||
struct device *dev = &hr_dev->pdev->dev;
|
||||
struct device *dev = hr_dev->dev;
|
||||
struct hns_roce_cmd_mailbox *mailbox;
|
||||
struct hns_roce_mr_table *mr_table = &hr_dev->mr_table;
|
||||
|
||||
@@ -345,10 +704,11 @@ static int hns_roce_write_mtt_chunk(struct hns_roce_dev *hr_dev,
|
||||
struct hns_roce_mtt *mtt, u32 start_index,
|
||||
u32 npages, u64 *page_list)
|
||||
{
|
||||
u32 i = 0;
|
||||
__le64 *mtts = NULL;
|
||||
struct hns_roce_hem_table *table;
|
||||
dma_addr_t dma_handle;
|
||||
__le64 *mtts;
|
||||
u32 s = start_index * sizeof(u64);
|
||||
u32 i;
|
||||
|
||||
/* All MTTs must fit in the same page */
|
||||
if (start_index / (PAGE_SIZE / sizeof(u64)) !=
|
||||
@@ -358,15 +718,24 @@ static int hns_roce_write_mtt_chunk(struct hns_roce_dev *hr_dev,
|
||||
if (start_index & (HNS_ROCE_MTT_ENTRY_PER_SEG - 1))
|
||||
return -EINVAL;
|
||||
|
||||
mtts = hns_roce_table_find(&hr_dev->mr_table.mtt_table,
|
||||
if (mtt->mtt_type == MTT_TYPE_WQE)
|
||||
table = &hr_dev->mr_table.mtt_table;
|
||||
else
|
||||
table = &hr_dev->mr_table.mtt_cqe_table;
|
||||
|
||||
mtts = hns_roce_table_find(hr_dev, table,
|
||||
mtt->first_seg + s / hr_dev->caps.mtt_entry_sz,
|
||||
&dma_handle);
|
||||
if (!mtts)
|
||||
return -ENOMEM;
|
||||
|
||||
/* Save page addr, low 12 bits : 0 */
|
||||
for (i = 0; i < npages; ++i)
|
||||
mtts[i] = (cpu_to_le64(page_list[i])) >> PAGE_ADDR_SHIFT;
|
||||
for (i = 0; i < npages; ++i) {
|
||||
if (!hr_dev->caps.mtt_hop_num)
|
||||
mtts[i] = cpu_to_le64(page_list[i] >> PAGE_ADDR_SHIFT);
|
||||
else
|
||||
mtts[i] = cpu_to_le64(page_list[i]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -400,9 +769,9 @@ static int hns_roce_write_mtt(struct hns_roce_dev *hr_dev,
|
||||
int hns_roce_buf_write_mtt(struct hns_roce_dev *hr_dev,
|
||||
struct hns_roce_mtt *mtt, struct hns_roce_buf *buf)
|
||||
{
|
||||
u32 i = 0;
|
||||
int ret = 0;
|
||||
u64 *page_list = NULL;
|
||||
u64 *page_list;
|
||||
int ret;
|
||||
u32 i;
|
||||
|
||||
page_list = kmalloc_array(buf->npages, sizeof(*page_list), GFP_KERNEL);
|
||||
if (!page_list)
|
||||
@@ -425,7 +794,7 @@ int hns_roce_buf_write_mtt(struct hns_roce_dev *hr_dev,
|
||||
int hns_roce_init_mr_table(struct hns_roce_dev *hr_dev)
|
||||
{
|
||||
struct hns_roce_mr_table *mr_table = &hr_dev->mr_table;
|
||||
int ret = 0;
|
||||
int ret;
|
||||
|
||||
ret = hns_roce_bitmap_init(&mr_table->mtpt_bitmap,
|
||||
hr_dev->caps.num_mtpts,
|
||||
@@ -439,8 +808,17 @@ int hns_roce_init_mr_table(struct hns_roce_dev *hr_dev)
|
||||
if (ret)
|
||||
goto err_buddy;
|
||||
|
||||
if (hns_roce_check_whether_mhop(hr_dev, HEM_TYPE_CQE)) {
|
||||
ret = hns_roce_buddy_init(&mr_table->mtt_cqe_buddy,
|
||||
ilog2(hr_dev->caps.num_cqe_segs));
|
||||
if (ret)
|
||||
goto err_buddy_cqe;
|
||||
}
|
||||
return 0;
|
||||
|
||||
err_buddy_cqe:
|
||||
hns_roce_buddy_cleanup(&mr_table->mtt_buddy);
|
||||
|
||||
err_buddy:
|
||||
hns_roce_bitmap_cleanup(&mr_table->mtpt_bitmap);
|
||||
return ret;
|
||||
@@ -451,13 +829,15 @@ void hns_roce_cleanup_mr_table(struct hns_roce_dev *hr_dev)
|
||||
struct hns_roce_mr_table *mr_table = &hr_dev->mr_table;
|
||||
|
||||
hns_roce_buddy_cleanup(&mr_table->mtt_buddy);
|
||||
if (hns_roce_check_whether_mhop(hr_dev, HEM_TYPE_CQE))
|
||||
hns_roce_buddy_cleanup(&mr_table->mtt_cqe_buddy);
|
||||
hns_roce_bitmap_cleanup(&mr_table->mtpt_bitmap);
|
||||
}
|
||||
|
||||
struct ib_mr *hns_roce_get_dma_mr(struct ib_pd *pd, int acc)
|
||||
{
|
||||
int ret = 0;
|
||||
struct hns_roce_mr *mr = NULL;
|
||||
struct hns_roce_mr *mr;
|
||||
int ret;
|
||||
|
||||
mr = kmalloc(sizeof(*mr), GFP_KERNEL);
|
||||
if (mr == NULL)
|
||||
@@ -526,16 +906,36 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int hns_roce_ib_umem_write_mr(struct hns_roce_mr *mr,
|
||||
static int hns_roce_ib_umem_write_mr(struct hns_roce_dev *hr_dev,
|
||||
struct hns_roce_mr *mr,
|
||||
struct ib_umem *umem)
|
||||
{
|
||||
int i = 0;
|
||||
int entry;
|
||||
struct scatterlist *sg;
|
||||
int i = 0, j = 0;
|
||||
int entry;
|
||||
|
||||
if (hr_dev->caps.pbl_hop_num == HNS_ROCE_HOP_NUM_0)
|
||||
return 0;
|
||||
|
||||
for_each_sg(umem->sg_head.sgl, sg, umem->nmap, entry) {
|
||||
mr->pbl_buf[i] = ((u64)sg_dma_address(sg)) >> 12;
|
||||
i++;
|
||||
if (!hr_dev->caps.pbl_hop_num) {
|
||||
mr->pbl_buf[i] = ((u64)sg_dma_address(sg)) >> 12;
|
||||
i++;
|
||||
} else if (hr_dev->caps.pbl_hop_num == 1) {
|
||||
mr->pbl_buf[i] = sg_dma_address(sg);
|
||||
i++;
|
||||
} else {
|
||||
if (hr_dev->caps.pbl_hop_num == 2)
|
||||
mr->pbl_bt_l1[i][j] = sg_dma_address(sg);
|
||||
else if (hr_dev->caps.pbl_hop_num == 3)
|
||||
mr->pbl_bt_l2[i][j] = sg_dma_address(sg);
|
||||
|
||||
j++;
|
||||
if (j >= (PAGE_SIZE / 8)) {
|
||||
i++;
|
||||
j = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Memory barrier */
|
||||
@@ -549,10 +949,12 @@ struct ib_mr *hns_roce_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
|
||||
struct ib_udata *udata)
|
||||
{
|
||||
struct hns_roce_dev *hr_dev = to_hr_dev(pd->device);
|
||||
struct device *dev = &hr_dev->pdev->dev;
|
||||
struct hns_roce_mr *mr = NULL;
|
||||
int ret = 0;
|
||||
int n = 0;
|
||||
struct device *dev = hr_dev->dev;
|
||||
struct hns_roce_mr *mr;
|
||||
int bt_size;
|
||||
int ret;
|
||||
int n;
|
||||
int i;
|
||||
|
||||
mr = kmalloc(sizeof(*mr), GFP_KERNEL);
|
||||
if (!mr)
|
||||
@@ -573,11 +975,27 @@ struct ib_mr *hns_roce_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
|
||||
goto err_umem;
|
||||
}
|
||||
|
||||
if (n > HNS_ROCE_MAX_MTPT_PBL_NUM) {
|
||||
dev_err(dev, " MR len %lld err. MR is limited to 4G at most!\n",
|
||||
length);
|
||||
ret = -EINVAL;
|
||||
goto err_umem;
|
||||
if (!hr_dev->caps.pbl_hop_num) {
|
||||
if (n > HNS_ROCE_MAX_MTPT_PBL_NUM) {
|
||||
dev_err(dev,
|
||||
" MR len %lld err. MR is limited to 4G at most!\n",
|
||||
length);
|
||||
ret = -EINVAL;
|
||||
goto err_umem;
|
||||
}
|
||||
} else {
|
||||
int pbl_size = 1;
|
||||
|
||||
bt_size = (1 << PAGE_SHIFT) / 8;
|
||||
for (i = 0; i < hr_dev->caps.pbl_hop_num; i++)
|
||||
pbl_size *= bt_size;
|
||||
if (n > pbl_size) {
|
||||
dev_err(dev,
|
||||
" MR len %lld err. MR page num is limited to %d!\n",
|
||||
length, pbl_size);
|
||||
ret = -EINVAL;
|
||||
goto err_umem;
|
||||
}
|
||||
}
|
||||
|
||||
ret = hns_roce_mr_alloc(hr_dev, to_hr_pd(pd)->pdn, virt_addr, length,
|
||||
@@ -585,7 +1003,7 @@ struct ib_mr *hns_roce_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
|
||||
if (ret)
|
||||
goto err_umem;
|
||||
|
||||
ret = hns_roce_ib_umem_write_mr(mr, mr->umem);
|
||||
ret = hns_roce_ib_umem_write_mr(hr_dev, mr, mr->umem);
|
||||
if (ret)
|
||||
goto err_mr;
|
||||
|
||||
|
@@ -31,6 +31,7 @@
|
||||
*/
|
||||
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pci.h>
|
||||
#include "hns_roce_device.h"
|
||||
|
||||
static int hns_roce_pd_alloc(struct hns_roce_dev *hr_dev, unsigned long *pdn)
|
||||
@@ -60,7 +61,7 @@ struct ib_pd *hns_roce_alloc_pd(struct ib_device *ib_dev,
|
||||
struct ib_udata *udata)
|
||||
{
|
||||
struct hns_roce_dev *hr_dev = to_hr_dev(ib_dev);
|
||||
struct device *dev = &hr_dev->pdev->dev;
|
||||
struct device *dev = hr_dev->dev;
|
||||
struct hns_roce_pd *pd;
|
||||
int ret;
|
||||
|
||||
@@ -86,6 +87,7 @@ struct ib_pd *hns_roce_alloc_pd(struct ib_device *ib_dev,
|
||||
|
||||
return &pd->ibpd;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(hns_roce_alloc_pd);
|
||||
|
||||
int hns_roce_dealloc_pd(struct ib_pd *pd)
|
||||
{
|
||||
@@ -94,6 +96,7 @@ int hns_roce_dealloc_pd(struct ib_pd *pd)
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(hns_roce_dealloc_pd);
|
||||
|
||||
int hns_roce_uar_alloc(struct hns_roce_dev *hr_dev, struct hns_roce_uar *uar)
|
||||
{
|
||||
@@ -109,12 +112,17 @@ int hns_roce_uar_alloc(struct hns_roce_dev *hr_dev, struct hns_roce_uar *uar)
|
||||
uar->index = (uar->index - 1) %
|
||||
(hr_dev->caps.phy_num_uars - 1) + 1;
|
||||
|
||||
res = platform_get_resource(hr_dev->pdev, IORESOURCE_MEM, 0);
|
||||
if (!res) {
|
||||
dev_err(&hr_dev->pdev->dev, "memory resource not found!\n");
|
||||
return -EINVAL;
|
||||
if (!dev_is_pci(hr_dev->dev)) {
|
||||
res = platform_get_resource(hr_dev->pdev, IORESOURCE_MEM, 0);
|
||||
if (!res) {
|
||||
dev_err(&hr_dev->pdev->dev, "memory resource not found!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
uar->pfn = ((res->start) >> PAGE_SHIFT) + uar->index;
|
||||
} else {
|
||||
uar->pfn = ((pci_resource_start(hr_dev->pci_dev, 2))
|
||||
>> PAGE_SHIFT);
|
||||
}
|
||||
uar->pfn = ((res->start) >> PAGE_SHIFT) + uar->index;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@@ -44,7 +44,7 @@
|
||||
void hns_roce_qp_event(struct hns_roce_dev *hr_dev, u32 qpn, int event_type)
|
||||
{
|
||||
struct hns_roce_qp_table *qp_table = &hr_dev->qp_table;
|
||||
struct device *dev = &hr_dev->pdev->dev;
|
||||
struct device *dev = hr_dev->dev;
|
||||
struct hns_roce_qp *qp;
|
||||
|
||||
spin_lock(&qp_table->lock);
|
||||
@@ -136,6 +136,7 @@ enum hns_roce_qp_state to_hns_roce_state(enum ib_qp_state state)
|
||||
return HNS_ROCE_QP_NUM_STATE;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(to_hns_roce_state);
|
||||
|
||||
static int hns_roce_gsi_qp_alloc(struct hns_roce_dev *hr_dev, unsigned long qpn,
|
||||
struct hns_roce_qp *hr_qp)
|
||||
@@ -153,7 +154,7 @@ static int hns_roce_gsi_qp_alloc(struct hns_roce_dev *hr_dev, unsigned long qpn,
|
||||
hr_qp->qpn & (hr_dev->caps.num_qps - 1), hr_qp);
|
||||
spin_unlock_irq(&qp_table->lock);
|
||||
if (ret) {
|
||||
dev_err(&hr_dev->pdev->dev, "QPC radix_tree_insert failed\n");
|
||||
dev_err(hr_dev->dev, "QPC radix_tree_insert failed\n");
|
||||
goto err_put_irrl;
|
||||
}
|
||||
|
||||
@@ -171,7 +172,7 @@ static int hns_roce_qp_alloc(struct hns_roce_dev *hr_dev, unsigned long qpn,
|
||||
struct hns_roce_qp *hr_qp)
|
||||
{
|
||||
struct hns_roce_qp_table *qp_table = &hr_dev->qp_table;
|
||||
struct device *dev = &hr_dev->pdev->dev;
|
||||
struct device *dev = hr_dev->dev;
|
||||
int ret;
|
||||
|
||||
if (!qpn)
|
||||
@@ -227,6 +228,7 @@ void hns_roce_qp_remove(struct hns_roce_dev *hr_dev, struct hns_roce_qp *hr_qp)
|
||||
hr_qp->qpn & (hr_dev->caps.num_qps - 1));
|
||||
spin_unlock_irqrestore(&qp_table->lock, flags);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(hns_roce_qp_remove);
|
||||
|
||||
void hns_roce_qp_free(struct hns_roce_dev *hr_dev, struct hns_roce_qp *hr_qp)
|
||||
{
|
||||
@@ -241,6 +243,7 @@ void hns_roce_qp_free(struct hns_roce_dev *hr_dev, struct hns_roce_qp *hr_qp)
|
||||
hns_roce_table_put(hr_dev, &qp_table->qp_table, hr_qp->qpn);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(hns_roce_qp_free);
|
||||
|
||||
void hns_roce_release_range_qp(struct hns_roce_dev *hr_dev, int base_qpn,
|
||||
int cnt)
|
||||
@@ -252,13 +255,14 @@ void hns_roce_release_range_qp(struct hns_roce_dev *hr_dev, int base_qpn,
|
||||
|
||||
hns_roce_bitmap_free_range(&qp_table->bitmap, base_qpn, cnt, BITMAP_RR);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(hns_roce_release_range_qp);
|
||||
|
||||
static int hns_roce_set_rq_size(struct hns_roce_dev *hr_dev,
|
||||
struct ib_qp_cap *cap, int is_user, int has_srq,
|
||||
struct hns_roce_qp *hr_qp)
|
||||
{
|
||||
struct device *dev = hr_dev->dev;
|
||||
u32 max_cnt;
|
||||
struct device *dev = &hr_dev->pdev->dev;
|
||||
|
||||
/* Check the validity of QP support capacity */
|
||||
if (cap->max_recv_wr > hr_dev->caps.max_wqes ||
|
||||
@@ -282,20 +286,27 @@ static int hns_roce_set_rq_size(struct hns_roce_dev *hr_dev,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* In v1 engine, parameter verification procession */
|
||||
max_cnt = cap->max_recv_wr > HNS_ROCE_MIN_WQE_NUM ?
|
||||
cap->max_recv_wr : HNS_ROCE_MIN_WQE_NUM;
|
||||
if (hr_dev->caps.min_wqes)
|
||||
max_cnt = max(cap->max_recv_wr, hr_dev->caps.min_wqes);
|
||||
else
|
||||
max_cnt = cap->max_recv_wr;
|
||||
|
||||
hr_qp->rq.wqe_cnt = roundup_pow_of_two(max_cnt);
|
||||
|
||||
if ((u32)hr_qp->rq.wqe_cnt > hr_dev->caps.max_wqes) {
|
||||
dev_err(dev, "hns_roce_set_rq_size rq.wqe_cnt too large\n");
|
||||
dev_err(dev, "while setting rq size, rq.wqe_cnt too large\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
max_cnt = max(1U, cap->max_recv_sge);
|
||||
hr_qp->rq.max_gs = roundup_pow_of_two(max_cnt);
|
||||
/* WQE is fixed for 64B */
|
||||
hr_qp->rq.wqe_shift = ilog2(hr_dev->caps.max_rq_desc_sz);
|
||||
if (hr_dev->caps.max_rq_sg <= 2)
|
||||
hr_qp->rq.wqe_shift =
|
||||
ilog2(hr_dev->caps.max_rq_desc_sz);
|
||||
else
|
||||
hr_qp->rq.wqe_shift =
|
||||
ilog2(hr_dev->caps.max_rq_desc_sz
|
||||
* hr_qp->rq.max_gs);
|
||||
}
|
||||
|
||||
cap->max_recv_wr = hr_qp->rq.max_post = hr_qp->rq.wqe_cnt;
|
||||
@@ -305,32 +316,77 @@ static int hns_roce_set_rq_size(struct hns_roce_dev *hr_dev,
|
||||
}
|
||||
|
||||
static int hns_roce_set_user_sq_size(struct hns_roce_dev *hr_dev,
|
||||
struct ib_qp_cap *cap,
|
||||
struct hns_roce_qp *hr_qp,
|
||||
struct hns_roce_ib_create_qp *ucmd)
|
||||
{
|
||||
u32 roundup_sq_stride = roundup_pow_of_two(hr_dev->caps.max_sq_desc_sz);
|
||||
u8 max_sq_stride = ilog2(roundup_sq_stride);
|
||||
u32 max_cnt;
|
||||
|
||||
/* Sanity check SQ size before proceeding */
|
||||
if ((u32)(1 << ucmd->log_sq_bb_count) > hr_dev->caps.max_wqes ||
|
||||
ucmd->log_sq_stride > max_sq_stride ||
|
||||
ucmd->log_sq_stride < HNS_ROCE_IB_MIN_SQ_STRIDE) {
|
||||
dev_err(&hr_dev->pdev->dev, "check SQ size error!\n");
|
||||
dev_err(hr_dev->dev, "check SQ size error!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (cap->max_send_sge > hr_dev->caps.max_sq_sg) {
|
||||
dev_err(hr_dev->dev, "SQ sge error! max_send_sge=%d\n",
|
||||
cap->max_send_sge);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
hr_qp->sq.wqe_cnt = 1 << ucmd->log_sq_bb_count;
|
||||
hr_qp->sq.wqe_shift = ucmd->log_sq_stride;
|
||||
|
||||
max_cnt = max(1U, cap->max_send_sge);
|
||||
if (hr_dev->caps.max_sq_sg <= 2)
|
||||
hr_qp->sq.max_gs = roundup_pow_of_two(max_cnt);
|
||||
else
|
||||
hr_qp->sq.max_gs = max_cnt;
|
||||
|
||||
if (hr_qp->sq.max_gs > 2)
|
||||
hr_qp->sge.sge_cnt = roundup_pow_of_two(hr_qp->sq.wqe_cnt *
|
||||
(hr_qp->sq.max_gs - 2));
|
||||
hr_qp->sge.sge_shift = 4;
|
||||
|
||||
/* Get buf size, SQ and RQ are aligned to page_szie */
|
||||
hr_qp->buff_size = HNS_ROCE_ALOGN_UP((hr_qp->rq.wqe_cnt <<
|
||||
if (hr_dev->caps.max_sq_sg <= 2) {
|
||||
hr_qp->buff_size = HNS_ROCE_ALOGN_UP((hr_qp->rq.wqe_cnt <<
|
||||
hr_qp->rq.wqe_shift), PAGE_SIZE) +
|
||||
HNS_ROCE_ALOGN_UP((hr_qp->sq.wqe_cnt <<
|
||||
HNS_ROCE_ALOGN_UP((hr_qp->sq.wqe_cnt <<
|
||||
hr_qp->sq.wqe_shift), PAGE_SIZE);
|
||||
|
||||
hr_qp->sq.offset = 0;
|
||||
hr_qp->rq.offset = HNS_ROCE_ALOGN_UP((hr_qp->sq.wqe_cnt <<
|
||||
hr_qp->sq.offset = 0;
|
||||
hr_qp->rq.offset = HNS_ROCE_ALOGN_UP((hr_qp->sq.wqe_cnt <<
|
||||
hr_qp->sq.wqe_shift), PAGE_SIZE);
|
||||
} else {
|
||||
hr_qp->buff_size = HNS_ROCE_ALOGN_UP((hr_qp->rq.wqe_cnt <<
|
||||
hr_qp->rq.wqe_shift), PAGE_SIZE) +
|
||||
HNS_ROCE_ALOGN_UP((hr_qp->sge.sge_cnt <<
|
||||
hr_qp->sge.sge_shift), PAGE_SIZE) +
|
||||
HNS_ROCE_ALOGN_UP((hr_qp->sq.wqe_cnt <<
|
||||
hr_qp->sq.wqe_shift), PAGE_SIZE);
|
||||
|
||||
hr_qp->sq.offset = 0;
|
||||
if (hr_qp->sge.sge_cnt) {
|
||||
hr_qp->sge.offset = HNS_ROCE_ALOGN_UP(
|
||||
(hr_qp->sq.wqe_cnt <<
|
||||
hr_qp->sq.wqe_shift),
|
||||
PAGE_SIZE);
|
||||
hr_qp->rq.offset = hr_qp->sge.offset +
|
||||
HNS_ROCE_ALOGN_UP((hr_qp->sge.sge_cnt <<
|
||||
hr_qp->sge.sge_shift),
|
||||
PAGE_SIZE);
|
||||
} else {
|
||||
hr_qp->rq.offset = HNS_ROCE_ALOGN_UP(
|
||||
(hr_qp->sq.wqe_cnt <<
|
||||
hr_qp->sq.wqe_shift),
|
||||
PAGE_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -339,13 +395,14 @@ static int hns_roce_set_kernel_sq_size(struct hns_roce_dev *hr_dev,
|
||||
struct ib_qp_cap *cap,
|
||||
struct hns_roce_qp *hr_qp)
|
||||
{
|
||||
struct device *dev = &hr_dev->pdev->dev;
|
||||
struct device *dev = hr_dev->dev;
|
||||
u32 max_cnt;
|
||||
int size;
|
||||
|
||||
if (cap->max_send_wr > hr_dev->caps.max_wqes ||
|
||||
cap->max_send_sge > hr_dev->caps.max_sq_sg ||
|
||||
cap->max_inline_data > hr_dev->caps.max_sq_inline) {
|
||||
dev_err(dev, "hns_roce_set_kernel_sq_size error1\n");
|
||||
dev_err(dev, "SQ WR or sge or inline data error!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -353,27 +410,45 @@ static int hns_roce_set_kernel_sq_size(struct hns_roce_dev *hr_dev,
|
||||
hr_qp->sq_max_wqes_per_wr = 1;
|
||||
hr_qp->sq_spare_wqes = 0;
|
||||
|
||||
/* In v1 engine, parameter verification procession */
|
||||
max_cnt = cap->max_send_wr > HNS_ROCE_MIN_WQE_NUM ?
|
||||
cap->max_send_wr : HNS_ROCE_MIN_WQE_NUM;
|
||||
if (hr_dev->caps.min_wqes)
|
||||
max_cnt = max(cap->max_send_wr, hr_dev->caps.min_wqes);
|
||||
else
|
||||
max_cnt = cap->max_send_wr;
|
||||
|
||||
hr_qp->sq.wqe_cnt = roundup_pow_of_two(max_cnt);
|
||||
if ((u32)hr_qp->sq.wqe_cnt > hr_dev->caps.max_wqes) {
|
||||
dev_err(dev, "hns_roce_set_kernel_sq_size sq.wqe_cnt too large\n");
|
||||
dev_err(dev, "while setting kernel sq size, sq.wqe_cnt too large\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Get data_seg numbers */
|
||||
max_cnt = max(1U, cap->max_send_sge);
|
||||
hr_qp->sq.max_gs = roundup_pow_of_two(max_cnt);
|
||||
if (hr_dev->caps.max_sq_sg <= 2)
|
||||
hr_qp->sq.max_gs = roundup_pow_of_two(max_cnt);
|
||||
else
|
||||
hr_qp->sq.max_gs = max_cnt;
|
||||
|
||||
/* Get buf size, SQ and RQ are aligned to page_szie */
|
||||
hr_qp->buff_size = HNS_ROCE_ALOGN_UP((hr_qp->rq.wqe_cnt <<
|
||||
hr_qp->rq.wqe_shift), PAGE_SIZE) +
|
||||
HNS_ROCE_ALOGN_UP((hr_qp->sq.wqe_cnt <<
|
||||
hr_qp->sq.wqe_shift), PAGE_SIZE);
|
||||
if (hr_qp->sq.max_gs > 2) {
|
||||
hr_qp->sge.sge_cnt = roundup_pow_of_two(hr_qp->sq.wqe_cnt *
|
||||
(hr_qp->sq.max_gs - 2));
|
||||
hr_qp->sge.sge_shift = 4;
|
||||
}
|
||||
|
||||
/* Get buf size, SQ and RQ are aligned to PAGE_SIZE */
|
||||
hr_qp->sq.offset = 0;
|
||||
hr_qp->rq.offset = HNS_ROCE_ALOGN_UP((hr_qp->sq.wqe_cnt <<
|
||||
hr_qp->sq.wqe_shift), PAGE_SIZE);
|
||||
size = HNS_ROCE_ALOGN_UP(hr_qp->sq.wqe_cnt << hr_qp->sq.wqe_shift,
|
||||
PAGE_SIZE);
|
||||
|
||||
if (hr_dev->caps.max_sq_sg > 2 && hr_qp->sge.sge_cnt) {
|
||||
hr_qp->sge.offset = size;
|
||||
size += HNS_ROCE_ALOGN_UP(hr_qp->sge.sge_cnt <<
|
||||
hr_qp->sge.sge_shift, PAGE_SIZE);
|
||||
}
|
||||
|
||||
hr_qp->rq.offset = size;
|
||||
size += HNS_ROCE_ALOGN_UP((hr_qp->rq.wqe_cnt << hr_qp->rq.wqe_shift),
|
||||
PAGE_SIZE);
|
||||
hr_qp->buff_size = size;
|
||||
|
||||
/* Get wr and sge number which send */
|
||||
cap->max_send_wr = hr_qp->sq.max_post = hr_qp->sq.wqe_cnt;
|
||||
@@ -391,7 +466,7 @@ static int hns_roce_create_qp_common(struct hns_roce_dev *hr_dev,
|
||||
struct ib_udata *udata, unsigned long sqpn,
|
||||
struct hns_roce_qp *hr_qp)
|
||||
{
|
||||
struct device *dev = &hr_dev->pdev->dev;
|
||||
struct device *dev = hr_dev->dev;
|
||||
struct hns_roce_ib_create_qp ucmd;
|
||||
unsigned long qpn = 0;
|
||||
int ret = 0;
|
||||
@@ -421,7 +496,8 @@ static int hns_roce_create_qp_common(struct hns_roce_dev *hr_dev,
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
ret = hns_roce_set_user_sq_size(hr_dev, hr_qp, &ucmd);
|
||||
ret = hns_roce_set_user_sq_size(hr_dev, &init_attr->cap, hr_qp,
|
||||
&ucmd);
|
||||
if (ret) {
|
||||
dev_err(dev, "hns_roce_set_user_sq_size error for create qp\n");
|
||||
goto err_out;
|
||||
@@ -436,6 +512,7 @@ static int hns_roce_create_qp_common(struct hns_roce_dev *hr_dev,
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
hr_qp->mtt.mtt_type = MTT_TYPE_WQE;
|
||||
ret = hns_roce_mtt_init(hr_dev, ib_umem_page_count(hr_qp->umem),
|
||||
hr_qp->umem->page_shift, &hr_qp->mtt);
|
||||
if (ret) {
|
||||
@@ -472,10 +549,9 @@ static int hns_roce_create_qp_common(struct hns_roce_dev *hr_dev,
|
||||
}
|
||||
|
||||
/* QP doorbell register address */
|
||||
hr_qp->sq.db_reg_l = hr_dev->reg_base + ROCEE_DB_SQ_L_0_REG +
|
||||
hr_qp->sq.db_reg_l = hr_dev->reg_base + hr_dev->sdb_offset +
|
||||
DB_REG_OFFSET * hr_dev->priv_uar.index;
|
||||
hr_qp->rq.db_reg_l = hr_dev->reg_base +
|
||||
ROCEE_DB_OTHERS_L_0_REG +
|
||||
hr_qp->rq.db_reg_l = hr_dev->reg_base + hr_dev->odb_offset +
|
||||
DB_REG_OFFSET * hr_dev->priv_uar.index;
|
||||
|
||||
/* Allocate QP buf */
|
||||
@@ -486,6 +562,7 @@ static int hns_roce_create_qp_common(struct hns_roce_dev *hr_dev,
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
hr_qp->mtt.mtt_type = MTT_TYPE_WQE;
|
||||
/* Write MTT */
|
||||
ret = hns_roce_mtt_init(hr_dev, hr_qp->hr_buf.npages,
|
||||
hr_qp->hr_buf.page_shift, &hr_qp->mtt);
|
||||
@@ -522,7 +599,9 @@ static int hns_roce_create_qp_common(struct hns_roce_dev *hr_dev,
|
||||
}
|
||||
}
|
||||
|
||||
if ((init_attr->qp_type) == IB_QPT_GSI) {
|
||||
if (init_attr->qp_type == IB_QPT_GSI &&
|
||||
hr_dev->hw_rev == HNS_ROCE_HW_VER1) {
|
||||
/* In v1 engine, GSI QP context in RoCE engine's register */
|
||||
ret = hns_roce_gsi_qp_alloc(hr_dev, qpn, hr_qp);
|
||||
if (ret) {
|
||||
dev_err(dev, "hns_roce_qp_alloc failed!\n");
|
||||
@@ -571,7 +650,7 @@ struct ib_qp *hns_roce_create_qp(struct ib_pd *pd,
|
||||
struct ib_udata *udata)
|
||||
{
|
||||
struct hns_roce_dev *hr_dev = to_hr_dev(pd->device);
|
||||
struct device *dev = &hr_dev->pdev->dev;
|
||||
struct device *dev = hr_dev->dev;
|
||||
struct hns_roce_sqp *hr_sqp;
|
||||
struct hns_roce_qp *hr_qp;
|
||||
int ret;
|
||||
@@ -629,6 +708,7 @@ struct ib_qp *hns_roce_create_qp(struct ib_pd *pd,
|
||||
|
||||
return &hr_qp->ibqp;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(hns_roce_create_qp);
|
||||
|
||||
int to_hr_qp_type(int qp_type)
|
||||
{
|
||||
@@ -647,6 +727,7 @@ int to_hr_qp_type(int qp_type)
|
||||
|
||||
return transport_type;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(to_hr_qp_type);
|
||||
|
||||
int hns_roce_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
|
||||
int attr_mask, struct ib_udata *udata)
|
||||
@@ -654,7 +735,7 @@ int hns_roce_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
|
||||
struct hns_roce_dev *hr_dev = to_hr_dev(ibqp->device);
|
||||
struct hns_roce_qp *hr_qp = to_hr_qp(ibqp);
|
||||
enum ib_qp_state cur_state, new_state;
|
||||
struct device *dev = &hr_dev->pdev->dev;
|
||||
struct device *dev = hr_dev->dev;
|
||||
int ret = -EINVAL;
|
||||
int p;
|
||||
enum ib_mtu active_mtu;
|
||||
@@ -692,7 +773,10 @@ int hns_roce_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
|
||||
p = attr_mask & IB_QP_PORT ? (attr->port_num - 1) : hr_qp->port;
|
||||
active_mtu = iboe_get_mtu(hr_dev->iboe.netdevs[p]->mtu);
|
||||
|
||||
if (attr->path_mtu > IB_MTU_2048 ||
|
||||
if ((hr_dev->caps.max_mtu == IB_MTU_4096 &&
|
||||
attr->path_mtu > IB_MTU_4096) ||
|
||||
(hr_dev->caps.max_mtu == IB_MTU_2048 &&
|
||||
attr->path_mtu > IB_MTU_2048) ||
|
||||
attr->path_mtu < IB_MTU_256 ||
|
||||
attr->path_mtu > active_mtu) {
|
||||
dev_err(dev, "attr path_mtu(%d)invalid while modify qp",
|
||||
@@ -716,9 +800,7 @@ int hns_roce_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
|
||||
}
|
||||
|
||||
if (cur_state == new_state && cur_state == IB_QPS_RESET) {
|
||||
ret = -EPERM;
|
||||
dev_err(dev, "cur_state=%d new_state=%d\n", cur_state,
|
||||
new_state);
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -745,6 +827,7 @@ void hns_roce_lock_cqs(struct hns_roce_cq *send_cq, struct hns_roce_cq *recv_cq)
|
||||
spin_lock_nested(&send_cq->lock, SINGLE_DEPTH_NESTING);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(hns_roce_lock_cqs);
|
||||
|
||||
void hns_roce_unlock_cqs(struct hns_roce_cq *send_cq,
|
||||
struct hns_roce_cq *recv_cq) __releases(&send_cq->lock)
|
||||
@@ -761,6 +844,7 @@ void hns_roce_unlock_cqs(struct hns_roce_cq *send_cq,
|
||||
spin_unlock_irq(&recv_cq->lock);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(hns_roce_unlock_cqs);
|
||||
|
||||
__be32 send_ieth(struct ib_send_wr *wr)
|
||||
{
|
||||
@@ -774,6 +858,7 @@ __be32 send_ieth(struct ib_send_wr *wr)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(send_ieth);
|
||||
|
||||
static void *get_wqe(struct hns_roce_qp *hr_qp, int offset)
|
||||
{
|
||||
@@ -785,11 +870,20 @@ void *get_recv_wqe(struct hns_roce_qp *hr_qp, int n)
|
||||
{
|
||||
return get_wqe(hr_qp, hr_qp->rq.offset + (n << hr_qp->rq.wqe_shift));
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(get_recv_wqe);
|
||||
|
||||
void *get_send_wqe(struct hns_roce_qp *hr_qp, int n)
|
||||
{
|
||||
return get_wqe(hr_qp, hr_qp->sq.offset + (n << hr_qp->sq.wqe_shift));
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(get_send_wqe);
|
||||
|
||||
void *get_send_extend_sge(struct hns_roce_qp *hr_qp, int n)
|
||||
{
|
||||
return hns_roce_buf_offset(&hr_qp->hr_buf, hr_qp->sge.offset +
|
||||
(n << hr_qp->sge.sge_shift));
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(get_send_extend_sge);
|
||||
|
||||
bool hns_roce_wq_overflow(struct hns_roce_wq *hr_wq, int nreq,
|
||||
struct ib_cq *ib_cq)
|
||||
@@ -808,6 +902,7 @@ bool hns_roce_wq_overflow(struct hns_roce_wq *hr_wq, int nreq,
|
||||
|
||||
return cur + nreq >= hr_wq->max_post;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(hns_roce_wq_overflow);
|
||||
|
||||
int hns_roce_init_qp_table(struct hns_roce_dev *hr_dev)
|
||||
{
|
||||
@@ -823,7 +918,7 @@ int hns_roce_init_qp_table(struct hns_roce_dev *hr_dev)
|
||||
hr_dev->caps.num_qps - 1, SQP_NUM,
|
||||
reserved_from_top);
|
||||
if (ret) {
|
||||
dev_err(&hr_dev->pdev->dev, "qp bitmap init failed!error=%d\n",
|
||||
dev_err(hr_dev->dev, "qp bitmap init failed!error=%d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
Referens i nytt ärende
Block a user