summaryrefslogtreecommitdiff
path: root/drivers/infiniband/hw/hns
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/infiniband/hw/hns')
-rw-r--r--drivers/infiniband/hw/hns/hns_roce_ah.c23
-rw-r--r--drivers/infiniband/hw/hns/hns_roce_alloc.c4
-rw-r--r--drivers/infiniband/hw/hns/hns_roce_bond.c4
-rw-r--r--drivers/infiniband/hw/hns/hns_roce_cmd.c4
-rw-r--r--drivers/infiniband/hw/hns/hns_roce_cq.c12
-rw-r--r--drivers/infiniband/hw/hns/hns_roce_db.c4
-rw-r--r--drivers/infiniband/hw/hns/hns_roce_device.h6
-rw-r--r--drivers/infiniband/hw/hns/hns_roce_hem.c19
-rw-r--r--drivers/infiniband/hw/hns/hns_roce_hw_v2.c240
-rw-r--r--drivers/infiniband/hw/hns/hns_roce_main.c10
-rw-r--r--drivers/infiniband/hw/hns/hns_roce_mr.c12
-rw-r--r--drivers/infiniband/hw/hns/hns_roce_qp.c49
-rw-r--r--drivers/infiniband/hw/hns/hns_roce_restrack.c4
13 files changed, 313 insertions, 78 deletions
diff --git a/drivers/infiniband/hw/hns/hns_roce_ah.c b/drivers/infiniband/hw/hns/hns_roce_ah.c
index 0c1c32d23c88..8a605da8a93c 100644
--- a/drivers/infiniband/hw/hns/hns_roce_ah.c
+++ b/drivers/infiniband/hw/hns/hns_roce_ah.c
@@ -60,7 +60,7 @@ int hns_roce_create_ah(struct ib_ah *ibah, struct rdma_ah_init_attr *init_attr,
u8 tclass = get_tclass(grh);
u8 priority = 0;
u8 tc_mode = 0;
- int ret;
+ int ret = 0;
if (hr_dev->pci_dev->revision == PCI_REVISION_ID_HIP08 && udata) {
ret = -EOPNOTSUPP;
@@ -77,19 +77,18 @@ int hns_roce_create_ah(struct ib_ah *ibah, struct rdma_ah_init_attr *init_attr,
ah->av.flowlabel = grh->flow_label;
ah->av.udp_sport = get_ah_udp_sport(ah_attr);
ah->av.tclass = tclass;
+ ah->av.sl = rdma_ah_get_sl(ah_attr);
- ret = hr_dev->hw->get_dscp(hr_dev, tclass, &tc_mode, &priority);
- if (ret == -EOPNOTSUPP)
- ret = 0;
-
- if (ret && grh->sgid_attr->gid_type == IB_GID_TYPE_ROCE_UDP_ENCAP)
- goto err_out;
+ if (grh->sgid_attr->gid_type == IB_GID_TYPE_ROCE_UDP_ENCAP) {
+ ret = hr_dev->hw->get_dscp(hr_dev, tclass, &tc_mode, &priority);
+ if (ret == -EOPNOTSUPP)
+ ret = 0;
+ else if (ret)
+ goto err_out;
- if (tc_mode == HNAE3_TC_MAP_MODE_DSCP &&
- grh->sgid_attr->gid_type == IB_GID_TYPE_ROCE_UDP_ENCAP)
- ah->av.sl = priority;
- else
- ah->av.sl = rdma_ah_get_sl(ah_attr);
+ if (tc_mode == HNAE3_TC_MAP_MODE_DSCP)
+ ah->av.sl = priority;
+ }
if (!check_sl_valid(hr_dev, ah->av.sl)) {
ret = -EINVAL;
diff --git a/drivers/infiniband/hw/hns/hns_roce_alloc.c b/drivers/infiniband/hw/hns/hns_roce_alloc.c
index 6ee911f6885b..8e802f118bc9 100644
--- a/drivers/infiniband/hw/hns/hns_roce_alloc.c
+++ b/drivers/infiniband/hw/hns/hns_roce_alloc.c
@@ -77,7 +77,7 @@ struct hns_roce_buf *hns_roce_buf_alloc(struct hns_roce_dev *hr_dev, u32 size,
return ERR_PTR(-EINVAL);
gfp_flags = (flags & HNS_ROCE_BUF_NOSLEEP) ? GFP_ATOMIC : GFP_KERNEL;
- buf = kzalloc(sizeof(*buf), gfp_flags);
+ buf = kzalloc_obj(*buf, gfp_flags);
if (!buf)
return ERR_PTR(-ENOMEM);
@@ -93,7 +93,7 @@ struct hns_roce_buf *hns_roce_buf_alloc(struct hns_roce_dev *hr_dev, u32 size,
ntrunk = DIV_ROUND_UP(size, 1 << buf->trunk_shift);
}
- trunks = kcalloc(ntrunk, sizeof(*trunks), gfp_flags);
+ trunks = kzalloc_objs(*trunks, ntrunk, gfp_flags);
if (!trunks) {
kfree(buf);
return ERR_PTR(-ENOMEM);
diff --git a/drivers/infiniband/hw/hns/hns_roce_bond.c b/drivers/infiniband/hw/hns/hns_roce_bond.c
index cc85f3ce1f3e..f2b12ae13a58 100644
--- a/drivers/infiniband/hw/hns/hns_roce_bond.c
+++ b/drivers/infiniband/hw/hns/hns_roce_bond.c
@@ -253,7 +253,7 @@ static struct hns_roce_die_info *alloc_die_info(int bus_num)
struct hns_roce_die_info *die_info;
int ret;
- die_info = kzalloc(sizeof(*die_info), GFP_KERNEL);
+ die_info = kzalloc_obj(*die_info);
if (!die_info)
return NULL;
@@ -855,7 +855,7 @@ int hns_roce_alloc_bond_grp(struct hns_roce_dev *hr_dev)
return 0;
for (i = 0; i < ROCE_BOND_NUM_MAX; i++) {
- bond_grp = kvzalloc(sizeof(*bond_grp), GFP_KERNEL);
+ bond_grp = kvzalloc_obj(*bond_grp);
if (!bond_grp) {
ret = -ENOMEM;
goto mem_err;
diff --git a/drivers/infiniband/hw/hns/hns_roce_cmd.c b/drivers/infiniband/hw/hns/hns_roce_cmd.c
index 873e8a69a1b9..1943031b0dbe 100644
--- a/drivers/infiniband/hw/hns/hns_roce_cmd.c
+++ b/drivers/infiniband/hw/hns/hns_roce_cmd.c
@@ -219,7 +219,7 @@ int hns_roce_cmd_use_events(struct hns_roce_dev *hr_dev)
int i;
hr_cmd->context =
- kcalloc(hr_cmd->max_cmds, sizeof(*hr_cmd->context), GFP_KERNEL);
+ kzalloc_objs(*hr_cmd->context, hr_cmd->max_cmds);
if (!hr_cmd->context) {
hr_dev->cmd_mod = 0;
return -ENOMEM;
@@ -254,7 +254,7 @@ hns_roce_alloc_cmd_mailbox(struct hns_roce_dev *hr_dev)
{
struct hns_roce_cmd_mailbox *mailbox;
- mailbox = kmalloc(sizeof(*mailbox), GFP_KERNEL);
+ mailbox = kmalloc_obj(*mailbox);
if (!mailbox)
return ERR_PTR(-ENOMEM);
diff --git a/drivers/infiniband/hw/hns/hns_roce_cq.c b/drivers/infiniband/hw/hns/hns_roce_cq.c
index 6aa82fe9dd3d..857a913326cd 100644
--- a/drivers/infiniband/hw/hns/hns_roce_cq.c
+++ b/drivers/infiniband/hw/hns/hns_roce_cq.c
@@ -55,7 +55,7 @@ void hns_roce_get_cq_bankid_for_uctx(struct hns_roce_ucontext *uctx)
{
struct hns_roce_dev *hr_dev = to_hr_dev(uctx->ibucontext.device);
struct hns_roce_cq_table *cq_table = &hr_dev->cq_table;
- u32 least_load = cq_table->ctx_num[0];
+ u32 least_load = U32_MAX;
u8 bankid = 0;
u8 i;
@@ -63,7 +63,10 @@ void hns_roce_get_cq_bankid_for_uctx(struct hns_roce_ucontext *uctx)
return;
mutex_lock(&cq_table->bank_mutex);
- for (i = 1; i < HNS_ROCE_CQ_BANK_NUM; i++) {
+ for (i = 0; i < HNS_ROCE_CQ_BANK_NUM; i++) {
+ if (!(cq_table->valid_cq_bank_mask & BIT(i)))
+ continue;
+
if (cq_table->ctx_num[i] < least_load) {
least_load = cq_table->ctx_num[i];
bankid = i;
@@ -581,6 +584,11 @@ void hns_roce_init_cq_table(struct hns_roce_dev *hr_dev)
cq_table->bank[i].max = hr_dev->caps.num_cqs /
HNS_ROCE_CQ_BANK_NUM - 1;
}
+
+ if (hr_dev->caps.flags & HNS_ROCE_CAP_FLAG_LIMIT_BANK)
+ cq_table->valid_cq_bank_mask = VALID_CQ_BANK_MASK_LIMIT;
+ else
+ cq_table->valid_cq_bank_mask = VALID_CQ_BANK_MASK_DEFAULT;
}
void hns_roce_cleanup_cq_table(struct hns_roce_dev *hr_dev)
diff --git a/drivers/infiniband/hw/hns/hns_roce_db.c b/drivers/infiniband/hw/hns/hns_roce_db.c
index 5c4c0480832b..f64023f5cf0a 100644
--- a/drivers/infiniband/hw/hns/hns_roce_db.c
+++ b/drivers/infiniband/hw/hns/hns_roce_db.c
@@ -21,7 +21,7 @@ int hns_roce_db_map_user(struct hns_roce_ucontext *context, unsigned long virt,
if (page->user_virt == page_addr)
goto found;
- page = kmalloc(sizeof(*page), GFP_KERNEL);
+ page = kmalloc_obj(*page);
if (!page) {
ret = -ENOMEM;
goto out;
@@ -72,7 +72,7 @@ static struct hns_roce_db_pgdir *hns_roce_alloc_db_pgdir(
{
struct hns_roce_db_pgdir *pgdir;
- pgdir = kzalloc(sizeof(*pgdir), GFP_KERNEL);
+ pgdir = kzalloc_obj(*pgdir);
if (!pgdir)
return NULL;
diff --git a/drivers/infiniband/hw/hns/hns_roce_device.h b/drivers/infiniband/hw/hns/hns_roce_device.h
index 318f18cf37aa..3f032b8038af 100644
--- a/drivers/infiniband/hw/hns/hns_roce_device.h
+++ b/drivers/infiniband/hw/hns/hns_roce_device.h
@@ -103,6 +103,10 @@
#define CQ_BANKID_SHIFT 2
#define CQ_BANKID_MASK GENMASK(1, 0)
+#define VALID_CQ_BANK_MASK_DEFAULT 0xF
+#define VALID_CQ_BANK_MASK_LIMIT 0x9
+
+#define VALID_EXT_SGE_QP_BANK_MASK_LIMIT 0x42
#define HNS_ROCE_MAX_CQ_COUNT 0xFFFF
#define HNS_ROCE_MAX_CQ_PERIOD 0xFFFF
@@ -156,6 +160,7 @@ enum {
HNS_ROCE_CAP_FLAG_CQE_INLINE = BIT(19),
HNS_ROCE_CAP_FLAG_BOND = BIT(21),
HNS_ROCE_CAP_FLAG_SRQ_RECORD_DB = BIT(22),
+ HNS_ROCE_CAP_FLAG_LIMIT_BANK = BIT(23),
};
#define HNS_ROCE_DB_TYPE_COUNT 2
@@ -500,6 +505,7 @@ struct hns_roce_cq_table {
struct hns_roce_bank bank[HNS_ROCE_CQ_BANK_NUM];
struct mutex bank_mutex;
u32 ctx_num[HNS_ROCE_CQ_BANK_NUM];
+ u8 valid_cq_bank_mask;
};
struct hns_roce_srq_table {
diff --git a/drivers/infiniband/hw/hns/hns_roce_hem.c b/drivers/infiniband/hw/hns/hns_roce_hem.c
index 3d479c63b117..4eaaedcc7652 100644
--- a/drivers/infiniband/hw/hns/hns_roce_hem.c
+++ b/drivers/infiniband/hw/hns/hns_roce_hem.c
@@ -262,7 +262,7 @@ static struct hns_roce_hem *hns_roce_alloc_hem(struct hns_roce_dev *hr_dev,
return NULL;
}
- hem = kmalloc(sizeof(*hem), GFP_KERNEL);
+ hem = kmalloc_obj(*hem);
if (!hem)
return NULL;
@@ -737,7 +737,7 @@ int hns_roce_init_hem_table(struct hns_roce_dev *hr_dev,
obj_per_chunk = table->table_chunk_size / obj_size;
num_hem = DIV_ROUND_UP(nobj, obj_per_chunk);
- table->hem = kcalloc(num_hem, sizeof(*table->hem), GFP_KERNEL);
+ table->hem = kzalloc_objs(*table->hem, num_hem);
if (!table->hem)
return -ENOMEM;
} else {
@@ -763,8 +763,7 @@ int hns_roce_init_hem_table(struct hns_roce_dev *hr_dev,
if (type >= HEM_TYPE_MTT)
num_bt_l0 = bt_chunk_num;
- table->hem = kcalloc(num_hem, sizeof(*table->hem),
- GFP_KERNEL);
+ table->hem = kzalloc_objs(*table->hem, num_hem);
if (!table->hem)
goto err_kcalloc_hem_buf;
@@ -778,9 +777,8 @@ int hns_roce_init_hem_table(struct hns_roce_dev *hr_dev,
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);
+ table->bt_l1_dma_addr = kzalloc_objs(*table->bt_l1_dma_addr,
+ num_bt_l1);
if (!table->bt_l1_dma_addr)
goto err_kcalloc_l1_dma;
@@ -793,9 +791,8 @@ int hns_roce_init_hem_table(struct hns_roce_dev *hr_dev,
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);
+ table->bt_l0_dma_addr = kzalloc_objs(*table->bt_l0_dma_addr,
+ num_bt_l0);
if (!table->bt_l0_dma_addr)
goto err_kcalloc_l0_dma;
}
@@ -939,7 +936,7 @@ hem_list_alloc_item(struct hns_roce_dev *hr_dev, int start, int end, int count,
{
struct hns_roce_hem_item *hem;
- hem = kzalloc(sizeof(*hem), GFP_KERNEL);
+ hem = kzalloc_obj(*hem);
if (!hem)
return NULL;
diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c
index 2d6ae89e525b..fa36700d0db2 100644
--- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c
+++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c
@@ -876,6 +876,170 @@ out:
return ret;
}
+static int hns_roce_push_drain_wr(struct hns_roce_wq *wq, struct ib_cq *cq,
+ u64 wr_id)
+{
+ unsigned long flags;
+ int ret = 0;
+
+ spin_lock_irqsave(&wq->lock, flags);
+ if (hns_roce_wq_overflow(wq, 1, cq)) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ wq->wrid[wq->head & (wq->wqe_cnt - 1)] = wr_id;
+ wq->head++;
+
+out:
+ spin_unlock_irqrestore(&wq->lock, flags);
+ return ret;
+}
+
+struct hns_roce_drain_cqe {
+ struct ib_cqe cqe;
+ struct completion done;
+};
+
+static void hns_roce_drain_qp_done(struct ib_cq *cq, struct ib_wc *wc)
+{
+ struct hns_roce_drain_cqe *cqe = container_of(wc->wr_cqe,
+ struct hns_roce_drain_cqe,
+ cqe);
+ complete(&cqe->done);
+}
+
+static void handle_drain_completion(struct ib_cq *ibcq,
+ struct hns_roce_drain_cqe *drain,
+ struct hns_roce_dev *hr_dev)
+{
+#define TIMEOUT (HZ / 10)
+ struct hns_roce_cq *hr_cq = to_hr_cq(ibcq);
+ unsigned long flags;
+ bool triggered;
+
+ if (ibcq->poll_ctx == IB_POLL_DIRECT) {
+ while (wait_for_completion_timeout(&drain->done, TIMEOUT) <= 0)
+ ib_process_cq_direct(ibcq, -1);
+ return;
+ }
+
+ if (hr_dev->state < HNS_ROCE_DEVICE_STATE_RST_DOWN)
+ goto waiting_done;
+
+ spin_lock_irqsave(&hr_cq->lock, flags);
+ triggered = hr_cq->is_armed;
+ hr_cq->is_armed = 1;
+ spin_unlock_irqrestore(&hr_cq->lock, flags);
+
+ /* Triggered means this cq is processing or has been processed
+ * by hns_roce_handle_device_err() or this function. We need to
+ * cancel the already invoked comp_handler() to avoid concurrency.
+ * If it has not been triggered, we can directly invoke
+ * comp_handler().
+ */
+ if (triggered) {
+ switch (ibcq->poll_ctx) {
+ case IB_POLL_SOFTIRQ:
+ irq_poll_disable(&ibcq->iop);
+ irq_poll_enable(&ibcq->iop);
+ break;
+ case IB_POLL_WORKQUEUE:
+ case IB_POLL_UNBOUND_WORKQUEUE:
+ cancel_work_sync(&ibcq->work);
+ break;
+ default:
+ WARN_ON_ONCE(1);
+ }
+ }
+
+ if (ibcq->comp_handler)
+ ibcq->comp_handler(ibcq, ibcq->cq_context);
+
+waiting_done:
+ if (ibcq->comp_handler)
+ wait_for_completion(&drain->done);
+}
+
+static void hns_roce_v2_drain_rq(struct ib_qp *ibqp)
+{
+ struct hns_roce_dev *hr_dev = to_hr_dev(ibqp->device);
+ struct ib_qp_attr attr = { .qp_state = IB_QPS_ERR };
+ struct hns_roce_qp *hr_qp = to_hr_qp(ibqp);
+ struct hns_roce_drain_cqe rdrain = {};
+ const struct ib_recv_wr *bad_rwr;
+ struct ib_cq *cq = ibqp->recv_cq;
+ struct ib_recv_wr rwr = {};
+ int ret;
+
+ ret = ib_modify_qp(ibqp, &attr, IB_QP_STATE);
+ if (ret && hr_dev->state < HNS_ROCE_DEVICE_STATE_RST_DOWN) {
+ ibdev_err_ratelimited(&hr_dev->ib_dev,
+ "failed to modify qp during drain rq, ret = %d.\n",
+ ret);
+ return;
+ }
+
+ rwr.wr_cqe = &rdrain.cqe;
+ rdrain.cqe.done = hns_roce_drain_qp_done;
+ init_completion(&rdrain.done);
+
+ if (hr_dev->state >= HNS_ROCE_DEVICE_STATE_RST_DOWN)
+ ret = hns_roce_push_drain_wr(&hr_qp->rq, cq, rwr.wr_id);
+ else
+ ret = hns_roce_v2_post_recv(ibqp, &rwr, &bad_rwr);
+ if (ret) {
+ ibdev_err_ratelimited(&hr_dev->ib_dev,
+ "failed to post recv for drain rq, ret = %d.\n",
+ ret);
+ return;
+ }
+
+ handle_drain_completion(cq, &rdrain, hr_dev);
+}
+
+static void hns_roce_v2_drain_sq(struct ib_qp *ibqp)
+{
+ struct hns_roce_dev *hr_dev = to_hr_dev(ibqp->device);
+ struct ib_qp_attr attr = { .qp_state = IB_QPS_ERR };
+ struct hns_roce_qp *hr_qp = to_hr_qp(ibqp);
+ struct hns_roce_drain_cqe sdrain = {};
+ const struct ib_send_wr *bad_swr;
+ struct ib_cq *cq = ibqp->send_cq;
+ struct ib_rdma_wr swr = {
+ .wr = {
+ .next = NULL,
+ { .wr_cqe = &sdrain.cqe, },
+ .opcode = IB_WR_RDMA_WRITE,
+ },
+ };
+ int ret;
+
+ ret = ib_modify_qp(ibqp, &attr, IB_QP_STATE);
+ if (ret && hr_dev->state < HNS_ROCE_DEVICE_STATE_RST_DOWN) {
+ ibdev_err_ratelimited(&hr_dev->ib_dev,
+ "failed to modify qp during drain sq, ret = %d.\n",
+ ret);
+ return;
+ }
+
+ sdrain.cqe.done = hns_roce_drain_qp_done;
+ init_completion(&sdrain.done);
+
+ if (hr_dev->state >= HNS_ROCE_DEVICE_STATE_RST_DOWN)
+ ret = hns_roce_push_drain_wr(&hr_qp->sq, cq, swr.wr.wr_id);
+ else
+ ret = hns_roce_v2_post_send(ibqp, &swr.wr, &bad_swr);
+ if (ret) {
+ ibdev_err_ratelimited(&hr_dev->ib_dev,
+ "failed to post send for drain sq, ret = %d.\n",
+ ret);
+ return;
+ }
+
+ handle_drain_completion(cq, &sdrain, hr_dev);
+}
+
static void *get_srq_wqe_buf(struct hns_roce_srq *srq, u32 n)
{
return hns_roce_buf_offset(srq->buf_mtr.kmem, n << srq->wqe_shift);
@@ -1784,7 +1948,7 @@ static int hns_roce_hw_v2_query_counter(struct hns_roce_dev *hr_dev,
return -EINVAL;
desc_num = DIV_ROUND_UP(HNS_ROCE_HW_CNT_TOTAL, CNT_PER_DESC);
- desc = kcalloc(desc_num, sizeof(*desc), GFP_KERNEL);
+ desc = kzalloc_objs(*desc, desc_num);
if (!desc)
return -ENOMEM;
@@ -2717,7 +2881,7 @@ static struct ib_pd *free_mr_init_pd(struct hns_roce_dev *hr_dev)
struct hns_roce_pd *hr_pd;
struct ib_pd *pd;
- hr_pd = kzalloc(sizeof(*hr_pd), GFP_KERNEL);
+ hr_pd = kzalloc_obj(*hr_pd);
if (!hr_pd)
return NULL;
pd = &hr_pd->ibpd;
@@ -2748,7 +2912,7 @@ static struct ib_cq *free_mr_init_cq(struct hns_roce_dev *hr_dev)
cq_init_attr.cqe = HNS_ROCE_FREE_MR_USED_CQE_NUM;
- hr_cq = kzalloc(sizeof(*hr_cq), GFP_KERNEL);
+ hr_cq = kzalloc_obj(*hr_cq);
if (!hr_cq)
return NULL;
@@ -2781,7 +2945,7 @@ static int free_mr_init_qp(struct hns_roce_dev *hr_dev, struct ib_cq *cq,
struct ib_qp *qp;
int ret;
- hr_qp = kzalloc(sizeof(*hr_qp), GFP_KERNEL);
+ hr_qp = kzalloc_obj(*hr_qp);
if (!hr_qp)
return -ENOMEM;
@@ -3739,6 +3903,23 @@ static void hns_roce_v2_write_cqc(struct hns_roce_dev *hr_dev,
HNS_ROCE_V2_CQ_DEFAULT_INTERVAL);
}
+static bool left_sw_wc(struct hns_roce_dev *hr_dev, struct hns_roce_cq *hr_cq)
+{
+ struct hns_roce_qp *hr_qp;
+
+ list_for_each_entry(hr_qp, &hr_cq->sq_list, sq_node) {
+ if (hr_qp->sq.head != hr_qp->sq.tail)
+ return true;
+ }
+
+ list_for_each_entry(hr_qp, &hr_cq->rq_list, rq_node) {
+ if (hr_qp->rq.head != hr_qp->rq.tail)
+ return true;
+ }
+
+ return false;
+}
+
static int hns_roce_v2_req_notify_cq(struct ib_cq *ibcq,
enum ib_cq_notify_flags flags)
{
@@ -3747,6 +3928,12 @@ static int hns_roce_v2_req_notify_cq(struct ib_cq *ibcq,
struct hns_roce_v2_db cq_db = {};
u32 notify_flag;
+ if (hr_dev->state >= HNS_ROCE_DEVICE_STATE_RST_DOWN) {
+ if ((flags & IB_CQ_REPORT_MISSED_EVENTS) &&
+ left_sw_wc(hr_dev, hr_cq))
+ return 1;
+ return 0;
+ }
/*
* flags = 0, then notify_flag : next
* flags = 1, then notify flag : solocited
@@ -4834,7 +5021,7 @@ static int alloc_dip_entry(struct xarray *dip_xa, u32 qpn)
if (hr_dip)
return 0;
- hr_dip = kzalloc(sizeof(*hr_dip), GFP_KERNEL);
+ hr_dip = kzalloc_obj(*hr_dip);
if (!hr_dip)
return -ENOMEM;
@@ -5053,20 +5240,22 @@ static int hns_roce_set_sl(struct ib_qp *ibqp,
struct ib_device *ibdev = &hr_dev->ib_dev;
int ret;
- ret = hns_roce_hw_v2_get_dscp(hr_dev, get_tclass(&attr->ah_attr.grh),
- &hr_qp->tc_mode, &hr_qp->priority);
- if (ret && ret != -EOPNOTSUPP &&
- grh->sgid_attr->gid_type == IB_GID_TYPE_ROCE_UDP_ENCAP) {
- ibdev_err_ratelimited(ibdev,
- "failed to get dscp, ret = %d.\n", ret);
- return ret;
- }
+ hr_qp->sl = rdma_ah_get_sl(&attr->ah_attr);
- if (hr_qp->tc_mode == HNAE3_TC_MAP_MODE_DSCP &&
- grh->sgid_attr->gid_type == IB_GID_TYPE_ROCE_UDP_ENCAP)
- hr_qp->sl = hr_qp->priority;
- else
- hr_qp->sl = rdma_ah_get_sl(&attr->ah_attr);
+ if (grh->sgid_attr->gid_type == IB_GID_TYPE_ROCE_UDP_ENCAP) {
+ ret = hns_roce_hw_v2_get_dscp(hr_dev,
+ get_tclass(&attr->ah_attr.grh),
+ &hr_qp->tc_mode, &hr_qp->priority);
+ if (ret && ret != -EOPNOTSUPP) {
+ ibdev_err_ratelimited(ibdev,
+ "failed to get dscp, ret = %d.\n",
+ ret);
+ return ret;
+ }
+
+ if (hr_qp->tc_mode == HNAE3_TC_MAP_MODE_DSCP)
+ hr_qp->sl = hr_qp->priority;
+ }
if (!check_sl_valid(hr_dev, hr_qp->sl))
return -EINVAL;
@@ -5446,8 +5635,8 @@ static int hns_roce_v2_modify_qp(struct ib_qp *ibqp,
* we should set all bits of the relevant fields in context mask to
* 0 at the same time, else set them to 0x1.
*/
- context = kvzalloc(sizeof(*context), GFP_KERNEL);
- qpc_mask = kvzalloc(sizeof(*qpc_mask), GFP_KERNEL);
+ context = kvzalloc_obj(*context);
+ qpc_mask = kvzalloc_obj(*qpc_mask);
if (!context || !qpc_mask)
goto out;
@@ -6261,7 +6450,7 @@ static void hns_roce_v2_init_irq_work(struct hns_roce_dev *hr_dev,
{
struct hns_roce_work *irq_work;
- irq_work = kzalloc(sizeof(struct hns_roce_work), GFP_ATOMIC);
+ irq_work = kzalloc_obj(struct hns_roce_work, GFP_ATOMIC);
if (!irq_work)
return;
@@ -6918,7 +7107,7 @@ static int hns_roce_v2_init_eq_table(struct hns_roce_dev *hr_dev)
eq_num = comp_num + aeq_num;
irq_num = eq_num + other_num;
- eq_table->eq = kcalloc(eq_num, sizeof(*eq_table->eq), GFP_KERNEL);
+ eq_table->eq = kzalloc_objs(*eq_table->eq, eq_num);
if (!eq_table->eq)
return -ENOMEM;
@@ -6956,7 +7145,8 @@ static int hns_roce_v2_init_eq_table(struct hns_roce_dev *hr_dev)
INIT_WORK(&hr_dev->ecc_work, fmea_ram_ecc_work);
- hr_dev->irq_workq = alloc_ordered_workqueue("hns_roce_irq_workq", 0);
+ hr_dev->irq_workq = alloc_ordered_workqueue("hns_roce_irq_workq",
+ WQ_MEM_RECLAIM);
if (!hr_dev->irq_workq) {
dev_err(dev, "failed to create irq workqueue.\n");
ret = -ENOMEM;
@@ -7014,6 +7204,8 @@ static const struct ib_device_ops hns_roce_v2_dev_ops = {
.post_send = hns_roce_v2_post_send,
.query_qp = hns_roce_v2_query_qp,
.req_notify_cq = hns_roce_v2_req_notify_cq,
+ .drain_rq = hns_roce_v2_drain_rq,
+ .drain_sq = hns_roce_v2_drain_sq,
};
static const struct ib_device_ops hns_roce_v2_dev_srq_ops = {
@@ -7117,7 +7309,7 @@ static int __hns_roce_hw_v2_init_instance(struct hnae3_handle *handle)
if (!hr_dev)
return -ENOMEM;
- hr_dev->priv = kzalloc(sizeof(struct hns_roce_v2_priv), GFP_KERNEL);
+ hr_dev->priv = kzalloc_obj(struct hns_roce_v2_priv);
if (!hr_dev->priv) {
ret = -ENOMEM;
goto error_failed_kzalloc;
diff --git a/drivers/infiniband/hw/hns/hns_roce_main.c b/drivers/infiniband/hw/hns/hns_roce_main.c
index 2f4864ab7d4e..1148d732f94f 100644
--- a/drivers/infiniband/hw/hns/hns_roce_main.c
+++ b/drivers/infiniband/hw/hns/hns_roce_main.c
@@ -259,6 +259,11 @@ static int hns_roce_query_device(struct ib_device *ib_dev,
props->max_srq_sge = hr_dev->caps.max_srq_sges;
}
+ if (hr_dev->caps.flags & HNS_ROCE_CAP_FLAG_LIMIT_BANK) {
+ props->max_cq >>= 1;
+ props->max_qp >>= 1;
+ }
+
if (hr_dev->caps.flags & HNS_ROCE_CAP_FLAG_FRMR &&
hr_dev->pci_dev->revision >= PCI_REVISION_ID_HIP09) {
props->device_cap_flags |= IB_DEVICE_MEM_MGT_EXTENSIONS;
@@ -361,7 +366,7 @@ hns_roce_user_mmap_entry_insert(struct ib_ucontext *ucontext, u64 address,
struct hns_user_mmap_entry *entry;
int ret;
- entry = kzalloc(sizeof(*entry), GFP_KERNEL);
+ entry = kzalloc_obj(*entry);
if (!entry)
return NULL;
@@ -1148,8 +1153,7 @@ void hns_roce_handle_device_err(struct hns_roce_dev *hr_dev)
static int hns_roce_alloc_dfx_cnt(struct hns_roce_dev *hr_dev)
{
- hr_dev->dfx_cnt = kvcalloc(HNS_ROCE_DFX_CNT_TOTAL, sizeof(atomic64_t),
- GFP_KERNEL);
+ hr_dev->dfx_cnt = kvzalloc_objs(atomic64_t, HNS_ROCE_DFX_CNT_TOTAL);
if (!hr_dev->dfx_cnt)
return -ENOMEM;
diff --git a/drivers/infiniband/hw/hns/hns_roce_mr.c b/drivers/infiniband/hw/hns/hns_roce_mr.c
index 31cb8699e198..896af1828a38 100644
--- a/drivers/infiniband/hw/hns/hns_roce_mr.c
+++ b/drivers/infiniband/hw/hns/hns_roce_mr.c
@@ -200,7 +200,7 @@ struct ib_mr *hns_roce_get_dma_mr(struct ib_pd *pd, int acc)
struct hns_roce_mr *mr;
int ret;
- mr = kzalloc(sizeof(*mr), GFP_KERNEL);
+ mr = kzalloc_obj(*mr);
if (!mr)
return ERR_PTR(-ENOMEM);
@@ -243,7 +243,7 @@ struct ib_mr *hns_roce_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
goto err_out;
}
- mr = kzalloc(sizeof(*mr), GFP_KERNEL);
+ mr = kzalloc_obj(*mr);
if (!mr) {
ret = -ENOMEM;
goto err_out;
@@ -395,7 +395,7 @@ struct ib_mr *hns_roce_alloc_mr(struct ib_pd *pd, enum ib_mr_type mr_type,
return ERR_PTR(-EINVAL);
}
- mr = kzalloc(sizeof(*mr), GFP_KERNEL);
+ mr = kzalloc_obj(*mr);
if (!mr)
return ERR_PTR(-ENOMEM);
@@ -458,8 +458,8 @@ int hns_roce_map_mr_sg(struct ib_mr *ibmr, struct scatterlist *sg, int sg_nents,
return sg_num;
mr->npages = 0;
- mr->page_list = kvcalloc(mr->pbl_mtr.hem_cfg.buf_pg_count,
- sizeof(dma_addr_t), GFP_KERNEL);
+ mr->page_list = kvzalloc_objs(dma_addr_t,
+ mr->pbl_mtr.hem_cfg.buf_pg_count);
if (!mr->page_list)
return sg_num;
@@ -650,7 +650,7 @@ static int mtr_map_bufs(struct hns_roce_dev *hr_dev, struct hns_roce_mtr *mtr)
page_shift = need_split_huge_page(mtr) ? HNS_HW_PAGE_SHIFT :
mtr->hem_cfg.buf_pg_shift;
/* alloc a tmp array to store buffer's dma address */
- pages = kvcalloc(page_count, sizeof(dma_addr_t), GFP_KERNEL);
+ pages = kvzalloc_objs(dma_addr_t, page_count);
if (!pages)
return -ENOMEM;
diff --git a/drivers/infiniband/hw/hns/hns_roce_qp.c b/drivers/infiniband/hw/hns/hns_roce_qp.c
index d1640c5fbaab..5f7ea6c16644 100644
--- a/drivers/infiniband/hw/hns/hns_roce_qp.c
+++ b/drivers/infiniband/hw/hns/hns_roce_qp.c
@@ -197,22 +197,16 @@ static u8 get_affinity_cq_bank(u8 qp_bank)
return (qp_bank >> 1) & CQ_BANKID_MASK;
}
-static u8 get_least_load_bankid_for_qp(struct ib_qp_init_attr *init_attr,
- struct hns_roce_bank *bank)
+static u8 get_least_load_bankid_for_qp(struct hns_roce_bank *bank, u8 valid_qp_bank_mask)
{
#define INVALID_LOAD_QPNUM 0xFFFFFFFF
- struct ib_cq *scq = init_attr->send_cq;
u32 least_load = INVALID_LOAD_QPNUM;
- unsigned long cqn = 0;
u8 bankid = 0;
u32 bankcnt;
u8 i;
- if (scq)
- cqn = to_hr_cq(scq)->cqn;
-
for (i = 0; i < HNS_ROCE_QP_BANK_NUM; i++) {
- if (scq && (get_affinity_cq_bank(i) != (cqn & CQ_BANKID_MASK)))
+ if (!(valid_qp_bank_mask & BIT(i)))
continue;
bankcnt = bank[i].inuse;
@@ -246,6 +240,42 @@ static int alloc_qpn_with_bankid(struct hns_roce_bank *bank, u8 bankid,
return 0;
}
+
+static bool use_ext_sge(struct ib_qp_init_attr *init_attr)
+{
+ return init_attr->cap.max_send_sge > HNS_ROCE_SGE_IN_WQE ||
+ init_attr->qp_type == IB_QPT_UD ||
+ init_attr->qp_type == IB_QPT_GSI;
+}
+
+static u8 select_qp_bankid(struct hns_roce_dev *hr_dev,
+ struct ib_qp_init_attr *init_attr)
+{
+ struct hns_roce_qp_table *qp_table = &hr_dev->qp_table;
+ struct hns_roce_bank *bank = qp_table->bank;
+ struct ib_cq *scq = init_attr->send_cq;
+ u8 valid_qp_bank_mask = 0;
+ unsigned long cqn = 0;
+ u8 i;
+
+ if (scq)
+ cqn = to_hr_cq(scq)->cqn;
+
+ for (i = 0; i < HNS_ROCE_QP_BANK_NUM; i++) {
+ if (scq && (get_affinity_cq_bank(i) != (cqn & CQ_BANKID_MASK)))
+ continue;
+
+ if ((hr_dev->caps.flags & HNS_ROCE_CAP_FLAG_LIMIT_BANK) &&
+ use_ext_sge(init_attr) &&
+ !(VALID_EXT_SGE_QP_BANK_MASK_LIMIT & BIT(i)))
+ continue;
+
+ valid_qp_bank_mask |= BIT(i);
+ }
+
+ return get_least_load_bankid_for_qp(bank, valid_qp_bank_mask);
+}
+
static int alloc_qpn(struct hns_roce_dev *hr_dev, struct hns_roce_qp *hr_qp,
struct ib_qp_init_attr *init_attr)
{
@@ -258,8 +288,7 @@ static int alloc_qpn(struct hns_roce_dev *hr_dev, struct hns_roce_qp *hr_qp,
num = 1;
} else {
mutex_lock(&qp_table->bank_mutex);
- bankid = get_least_load_bankid_for_qp(init_attr, qp_table->bank);
-
+ bankid = select_qp_bankid(hr_dev, init_attr);
ret = alloc_qpn_with_bankid(&qp_table->bank[bankid], bankid,
&num);
if (ret) {
diff --git a/drivers/infiniband/hw/hns/hns_roce_restrack.c b/drivers/infiniband/hw/hns/hns_roce_restrack.c
index 230187dda6a0..085791cc617c 100644
--- a/drivers/infiniband/hw/hns/hns_roce_restrack.c
+++ b/drivers/infiniband/hw/hns/hns_roce_restrack.c
@@ -51,7 +51,7 @@ int hns_roce_fill_res_cq_entry_raw(struct sk_buff *msg, struct ib_cq *ib_cq)
ret = hr_dev->hw->query_cqc(hr_dev, hr_cq->cqn, &context);
if (ret)
- return -EINVAL;
+ return ret;
ret = nla_put(msg, RDMA_NLDEV_ATTR_RES_RAW, sizeof(context), &context);
@@ -177,7 +177,7 @@ int hns_roce_fill_res_mr_entry_raw(struct sk_buff *msg, struct ib_mr *ib_mr)
ret = hr_dev->hw->query_mpt(hr_dev, hr_mr->key, &context);
if (ret)
- return -EINVAL;
+ return ret;
ret = nla_put(msg, RDMA_NLDEV_ATTR_RES_RAW, sizeof(context), &context);