]> www.infradead.org Git - linux.git/commitdiff
RDMA/erdma: Support non-sleeping erdma_post_cmd_wait()
authorBoshi Yu <boshiyu@linux.alibaba.com>
Thu, 26 Dec 2024 08:41:10 +0000 (16:41 +0800)
committerLeon Romanovsky <leon@kernel.org>
Mon, 30 Dec 2024 18:42:52 +0000 (13:42 -0500)
Several scenarios require posting commands to the cmdq in a non-sleepable
context. For example, the cm_alloc_msg() might call erdma_create_ah()
while still holding a spinlock. So we add support for non-sleeping
erdma_post_cmd_wait().

Reviewed-by: Cheng Xu <chengyou@linux.alibaba.com>
Signed-off-by: Boshi Yu <boshiyu@linux.alibaba.com>
Link: https://patch.msgid.link/20241226084141.74823-4-boshiyu@linux.alibaba.com
Signed-off-by: Leon Romanovsky <leon@kernel.org>
drivers/infiniband/hw/erdma/erdma.h
drivers/infiniband/hw/erdma/erdma_cmdq.c
drivers/infiniband/hw/erdma/erdma_eq.c
drivers/infiniband/hw/erdma/erdma_main.c
drivers/infiniband/hw/erdma/erdma_qp.c
drivers/infiniband/hw/erdma/erdma_verbs.c

index 2418ac68740473f9cd010e1ec7e9b09653a3b4a8..2a023b99f9926584e228f25e5fa6a506176a129d 100644 (file)
@@ -101,8 +101,6 @@ struct erdma_cmdq {
        struct erdma_comp_wait *wait_pool;
        spinlock_t lock;
 
-       bool use_event;
-
        struct erdma_cmdq_sq sq;
        struct erdma_cmdq_cq cq;
        struct erdma_eq eq;
@@ -267,7 +265,7 @@ void erdma_cmdq_destroy(struct erdma_dev *dev);
 
 void erdma_cmdq_build_reqhdr(u64 *hdr, u32 mod, u32 op);
 int erdma_post_cmd_wait(struct erdma_cmdq *cmdq, void *req, u32 req_size,
-                       u64 *resp0, u64 *resp1);
+                       u64 *resp0, u64 *resp1, bool sleepable);
 void erdma_cmdq_completion_handler(struct erdma_cmdq *cmdq);
 
 int erdma_ceqs_init(struct erdma_dev *dev);
index a3d8922d1ad1048ee98c9f6f21b1af0aa2c53c55..b867aefe83b2f2ea2d655f07791cecb3d42317c3 100644 (file)
@@ -182,7 +182,6 @@ int erdma_cmdq_init(struct erdma_dev *dev)
        int err;
 
        cmdq->max_outstandings = ERDMA_CMDQ_MAX_OUTSTANDING;
-       cmdq->use_event = false;
 
        sema_init(&cmdq->credits, cmdq->max_outstandings);
 
@@ -223,8 +222,6 @@ err_destroy_sq:
 
 void erdma_finish_cmdq_init(struct erdma_dev *dev)
 {
-       /* after device init successfully, change cmdq to event mode. */
-       dev->cmdq.use_event = true;
        arm_cmdq_cq(&dev->cmdq);
 }
 
@@ -312,8 +309,7 @@ static int erdma_poll_single_cmd_completion(struct erdma_cmdq *cmdq)
        /* Copy 16B comp data after cqe hdr to outer */
        be32_to_cpu_array(comp_wait->comp_data, cqe + 2, 4);
 
-       if (cmdq->use_event)
-               complete(&comp_wait->wait_event);
+       complete(&comp_wait->wait_event);
 
        return 0;
 }
@@ -332,9 +328,6 @@ static void erdma_polling_cmd_completions(struct erdma_cmdq *cmdq)
                if (erdma_poll_single_cmd_completion(cmdq))
                        break;
 
-       if (comp_num && cmdq->use_event)
-               arm_cmdq_cq(cmdq);
-
        spin_unlock_irqrestore(&cmdq->cq.lock, flags);
 }
 
@@ -342,8 +335,7 @@ void erdma_cmdq_completion_handler(struct erdma_cmdq *cmdq)
 {
        int got_event = 0;
 
-       if (!test_bit(ERDMA_CMDQ_STATE_OK_BIT, &cmdq->state) ||
-           !cmdq->use_event)
+       if (!test_bit(ERDMA_CMDQ_STATE_OK_BIT, &cmdq->state))
                return;
 
        while (get_next_valid_eqe(&cmdq->eq)) {
@@ -354,6 +346,7 @@ void erdma_cmdq_completion_handler(struct erdma_cmdq *cmdq)
        if (got_event) {
                cmdq->cq.cmdsn++;
                erdma_polling_cmd_completions(cmdq);
+               arm_cmdq_cq(cmdq);
        }
 
        notify_eq(&cmdq->eq);
@@ -372,7 +365,7 @@ static int erdma_poll_cmd_completion(struct erdma_comp_wait *comp_ctx,
                if (time_is_before_jiffies(comp_timeout))
                        return -ETIME;
 
-               msleep(20);
+               udelay(20);
        }
 
        return 0;
@@ -403,7 +396,7 @@ void erdma_cmdq_build_reqhdr(u64 *hdr, u32 mod, u32 op)
 }
 
 int erdma_post_cmd_wait(struct erdma_cmdq *cmdq, void *req, u32 req_size,
-                       u64 *resp0, u64 *resp1)
+                       u64 *resp0, u64 *resp1, bool sleepable)
 {
        struct erdma_comp_wait *comp_wait;
        int ret;
@@ -411,7 +404,12 @@ int erdma_post_cmd_wait(struct erdma_cmdq *cmdq, void *req, u32 req_size,
        if (!test_bit(ERDMA_CMDQ_STATE_OK_BIT, &cmdq->state))
                return -ENODEV;
 
-       down(&cmdq->credits);
+       if (!sleepable) {
+               while (down_trylock(&cmdq->credits))
+                       ;
+       } else {
+               down(&cmdq->credits);
+       }
 
        comp_wait = get_comp_wait(cmdq);
        if (IS_ERR(comp_wait)) {
@@ -425,7 +423,7 @@ int erdma_post_cmd_wait(struct erdma_cmdq *cmdq, void *req, u32 req_size,
        push_cmdq_sqe(cmdq, req, req_size, comp_wait);
        spin_unlock(&cmdq->sq.lock);
 
-       if (cmdq->use_event)
+       if (sleepable)
                ret = erdma_wait_cmd_completion(comp_wait, cmdq,
                                                ERDMA_CMDQ_TIMEOUT_MS);
        else
index 9a72fec6d5ccff642d6022fca03fa906bb7321dc..6486234a2360061b2d3ebd694686d84f6d3ecc44 100644 (file)
@@ -236,7 +236,8 @@ static int create_eq_cmd(struct erdma_dev *dev, u32 eqn, struct erdma_eq *eq)
        req.db_dma_addr_l = lower_32_bits(eq->dbrec_dma);
        req.db_dma_addr_h = upper_32_bits(eq->dbrec_dma);
 
-       return erdma_post_cmd_wait(&dev->cmdq, &req, sizeof(req), NULL, NULL);
+       return erdma_post_cmd_wait(&dev->cmdq, &req, sizeof(req), NULL, NULL,
+                                  false);
 }
 
 static int erdma_ceq_init_one(struct erdma_dev *dev, u16 ceqn)
@@ -278,7 +279,8 @@ static void erdma_ceq_uninit_one(struct erdma_dev *dev, u16 ceqn)
        req.qtype = ERDMA_EQ_TYPE_CEQ;
        req.vector_idx = ceqn + 1;
 
-       err = erdma_post_cmd_wait(&dev->cmdq, &req, sizeof(req), NULL, NULL);
+       err = erdma_post_cmd_wait(&dev->cmdq, &req, sizeof(req), NULL, NULL,
+                                 false);
        if (err)
                return;
 
index 9f512b642884477ccdf8107e764fcac66ac93734..f35b30235018baa56818e7387f9f442c0c6dda6c 100644 (file)
@@ -384,7 +384,7 @@ static int erdma_dev_attrs_init(struct erdma_dev *dev)
                                CMDQ_OPCODE_QUERY_DEVICE);
 
        err = erdma_post_cmd_wait(&dev->cmdq, &req_hdr, sizeof(req_hdr), &cap0,
-                                 &cap1);
+                                 &cap1, true);
        if (err)
                return err;
 
@@ -417,7 +417,7 @@ static int erdma_dev_attrs_init(struct erdma_dev *dev)
                                CMDQ_OPCODE_QUERY_FW_INFO);
 
        err = erdma_post_cmd_wait(&dev->cmdq, &req_hdr, sizeof(req_hdr), &cap0,
-                                 &cap1);
+                                 &cap1, true);
        if (!err)
                dev->attrs.fw_version =
                        FIELD_GET(ERDMA_CMD_INFO0_FW_VER_MASK, cap0);
@@ -438,7 +438,8 @@ static int erdma_device_config(struct erdma_dev *dev)
        req.cfg = FIELD_PREP(ERDMA_CMD_CONFIG_DEVICE_PGSHIFT_MASK, PAGE_SHIFT) |
                  FIELD_PREP(ERDMA_CMD_CONFIG_DEVICE_PS_EN_MASK, 1);
 
-       return erdma_post_cmd_wait(&dev->cmdq, &req, sizeof(req), NULL, NULL);
+       return erdma_post_cmd_wait(&dev->cmdq, &req, sizeof(req), NULL, NULL,
+                                  true);
 }
 
 static int erdma_res_cb_init(struct erdma_dev *dev)
index 5c266918fb36dea8a52f2bebea35b4d7f4d72dd2..25f6c49aec77989c3eddbc82e291796a9425393c 100644 (file)
@@ -98,7 +98,8 @@ erdma_modify_qp_state_to_rts(struct erdma_qp *qp,
                req.send_nxt += MPA_DEFAULT_HDR_LEN + params->pd_len;
        req.recv_nxt = tp->rcv_nxt;
 
-       ret = erdma_post_cmd_wait(&dev->cmdq, &req, sizeof(req), NULL, NULL);
+       ret = erdma_post_cmd_wait(&dev->cmdq, &req, sizeof(req), NULL, NULL,
+                                 true);
        if (ret)
                return ret;
 
@@ -131,7 +132,8 @@ erdma_modify_qp_state_to_stop(struct erdma_qp *qp,
        req.cfg = FIELD_PREP(ERDMA_CMD_MODIFY_QP_STATE_MASK, params->state) |
                  FIELD_PREP(ERDMA_CMD_MODIFY_QP_QPN_MASK, QP_ID(qp));
 
-       ret = erdma_post_cmd_wait(&dev->cmdq, &req, sizeof(req), NULL, NULL);
+       ret = erdma_post_cmd_wait(&dev->cmdq, &req, sizeof(req), NULL, NULL,
+                                 true);
        if (ret)
                return ret;
 
@@ -246,7 +248,7 @@ static int modify_qp_cmd_rocev2(struct erdma_qp *qp,
        req.attr_mask = attr_mask;
 
        return erdma_post_cmd_wait(&qp->dev->cmdq, &req, sizeof(req), NULL,
-                                  NULL);
+                                  NULL, true);
 }
 
 static void erdma_reset_qp(struct erdma_qp *qp)
index 199c7a26cd9d5876a965caeac7b4f0a2e80541fa..0e8a13577fdcebc42bcc40806009616eb0a2a388 100644 (file)
@@ -126,8 +126,8 @@ static int create_qp_cmd(struct erdma_ucontext *uctx, struct erdma_qp *qp)
                }
        }
 
-       err = erdma_post_cmd_wait(&dev->cmdq, &req, sizeof(req), &resp0,
-                                 &resp1);
+       err = erdma_post_cmd_wait(&dev->cmdq, &req, sizeof(req), &resp0, &resp1,
+                                 true);
        if (!err && erdma_device_iwarp(dev))
                qp->attrs.iwarp.cookie =
                        FIELD_GET(ERDMA_CMDQ_CREATE_QP_RESP_COOKIE_MASK, resp0);
@@ -185,7 +185,8 @@ static int regmr_cmd(struct erdma_dev *dev, struct erdma_mr *mr)
        }
 
 post_cmd:
-       return erdma_post_cmd_wait(&dev->cmdq, &req, sizeof(req), NULL, NULL);
+       return erdma_post_cmd_wait(&dev->cmdq, &req, sizeof(req), NULL, NULL,
+                                  true);
 }
 
 static int create_cq_cmd(struct erdma_ucontext *uctx, struct erdma_cq *cq)
@@ -247,7 +248,8 @@ static int create_cq_cmd(struct erdma_ucontext *uctx, struct erdma_cq *cq)
                }
        }
 
-       return erdma_post_cmd_wait(&dev->cmdq, &req, sizeof(req), NULL, NULL);
+       return erdma_post_cmd_wait(&dev->cmdq, &req, sizeof(req), NULL, NULL,
+                                  true);
 }
 
 static int erdma_alloc_idx(struct erdma_resource_cb *res_cb)
@@ -463,7 +465,8 @@ static void erdma_flush_worker(struct work_struct *work)
        req.qpn = QP_ID(qp);
        req.sq_pi = qp->kern_qp.sq_pi;
        req.rq_pi = qp->kern_qp.rq_pi;
-       erdma_post_cmd_wait(&qp->dev->cmdq, &req, sizeof(req), NULL, NULL);
+       erdma_post_cmd_wait(&qp->dev->cmdq, &req, sizeof(req), NULL, NULL,
+                           true);
 }
 
 static int erdma_qp_validate_cap(struct erdma_dev *dev,
@@ -1261,7 +1264,8 @@ int erdma_dereg_mr(struct ib_mr *ibmr, struct ib_udata *udata)
        req.cfg = FIELD_PREP(ERDMA_CMD_MR_MPT_IDX_MASK, ibmr->lkey >> 8) |
                  FIELD_PREP(ERDMA_CMD_MR_KEY_MASK, ibmr->lkey & 0xFF);
 
-       ret = erdma_post_cmd_wait(&dev->cmdq, &req, sizeof(req), NULL, NULL);
+       ret = erdma_post_cmd_wait(&dev->cmdq, &req, sizeof(req), NULL, NULL,
+                                 true);
        if (ret)
                return ret;
 
@@ -1286,7 +1290,8 @@ int erdma_destroy_cq(struct ib_cq *ibcq, struct ib_udata *udata)
                                CMDQ_OPCODE_DESTROY_CQ);
        req.cqn = cq->cqn;
 
-       err = erdma_post_cmd_wait(&dev->cmdq, &req, sizeof(req), NULL, NULL);
+       err = erdma_post_cmd_wait(&dev->cmdq, &req, sizeof(req), NULL, NULL,
+                                 true);
        if (err)
                return err;
 
@@ -1333,7 +1338,8 @@ int erdma_destroy_qp(struct ib_qp *ibqp, struct ib_udata *udata)
                                CMDQ_OPCODE_DESTROY_QP);
        req.qpn = QP_ID(qp);
 
-       err = erdma_post_cmd_wait(&dev->cmdq, &req, sizeof(req), NULL, NULL);
+       err = erdma_post_cmd_wait(&dev->cmdq, &req, sizeof(req), NULL, NULL,
+                                 true);
        if (err)
                return err;
 
@@ -1431,7 +1437,8 @@ static int alloc_db_resources(struct erdma_dev *dev, struct erdma_ucontext *ctx,
                  FIELD_PREP(ERDMA_CMD_EXT_DB_RQ_EN_MASK, 1) |
                  FIELD_PREP(ERDMA_CMD_EXT_DB_SQ_EN_MASK, 1);
 
-       ret = erdma_post_cmd_wait(&dev->cmdq, &req, sizeof(req), &val0, &val1);
+       ret = erdma_post_cmd_wait(&dev->cmdq, &req, sizeof(req), &val0, &val1,
+                                 true);
        if (ret)
                return ret;
 
@@ -1466,7 +1473,8 @@ static void free_db_resources(struct erdma_dev *dev, struct erdma_ucontext *ctx)
        req.rdb_off = ctx->ext_db.rdb_off;
        req.cdb_off = ctx->ext_db.cdb_off;
 
-       ret = erdma_post_cmd_wait(&dev->cmdq, &req, sizeof(req), NULL, NULL);
+       ret = erdma_post_cmd_wait(&dev->cmdq, &req, sizeof(req), NULL, NULL,
+                                 true);
        if (ret)
                ibdev_err_ratelimited(&dev->ibdev,
                                      "free db resources failed %d", ret);
@@ -1830,7 +1838,7 @@ int erdma_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr,
                req.qpn = QP_ID(qp);
 
                ret = erdma_post_cmd_wait(&dev->cmdq, &req, sizeof(req), &resp0,
-                                         &resp1);
+                                         &resp1, true);
                if (ret)
                        return ret;
 
@@ -1993,7 +2001,7 @@ void erdma_set_mtu(struct erdma_dev *dev, u32 mtu)
                                CMDQ_OPCODE_CONF_MTU);
        req.mtu = mtu;
 
-       erdma_post_cmd_wait(&dev->cmdq, &req, sizeof(req), NULL, NULL);
+       erdma_post_cmd_wait(&dev->cmdq, &req, sizeof(req), NULL, NULL, true);
 }
 
 void erdma_port_event(struct erdma_dev *dev, enum ib_event_type reason)
@@ -2063,7 +2071,8 @@ static int erdma_query_hw_stats(struct erdma_dev *dev,
        req.target_addr = dma_addr;
        req.target_length = ERDMA_HW_RESP_SIZE;
 
-       err = erdma_post_cmd_wait(&dev->cmdq, &req, sizeof(req), NULL, NULL);
+       err = erdma_post_cmd_wait(&dev->cmdq, &req, sizeof(req), NULL, NULL,
+                                 true);
        if (err)
                goto out;
 
@@ -2124,7 +2133,8 @@ static int erdma_set_gid(struct erdma_dev *dev, u8 op, u32 idx,
 
        erdma_cmdq_build_reqhdr(&req.hdr, CMDQ_SUBMOD_RDMA,
                                CMDQ_OPCODE_SET_GID);
-       return erdma_post_cmd_wait(&dev->cmdq, &req, sizeof(req), NULL, NULL);
+       return erdma_post_cmd_wait(&dev->cmdq, &req, sizeof(req), NULL, NULL,
+                                  true);
 }
 
 int erdma_add_gid(const struct ib_gid_attr *attr, void **context)
@@ -2208,7 +2218,8 @@ int erdma_create_ah(struct ib_ah *ibah, struct rdma_ah_init_attr *init_attr,
        req.ahn = ah->ahn;
        erdma_set_av_cfg(&req.av_cfg, &ah->av);
 
-       ret = erdma_post_cmd_wait(&dev->cmdq, &req, sizeof(req), NULL, NULL);
+       ret = erdma_post_cmd_wait(&dev->cmdq, &req, sizeof(req), NULL, NULL,
+                                 true);
        if (ret) {
                erdma_free_idx(&dev->res_cb[ERDMA_RES_TYPE_AH], ah->ahn);
                return ret;
@@ -2231,7 +2242,8 @@ int erdma_destroy_ah(struct ib_ah *ibah, u32 flags)
        req.pdn = pd->pdn;
        req.ahn = ah->ahn;
 
-       ret = erdma_post_cmd_wait(&dev->cmdq, &req, sizeof(req), NULL, NULL);
+       ret = erdma_post_cmd_wait(&dev->cmdq, &req, sizeof(req), NULL, NULL,
+                                 true);
        if (ret)
                return ret;