mirror of
https://github.com/torvalds/linux.git
synced 2026-08-01 03:59:40 +02:00
RDMA/erdma: Support non-sleeping erdma_post_cmd_wait()
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>
This commit is contained in:
parent
3761e0ad79
commit
26981e688c
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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 @@ int erdma_cmdq_init(struct erdma_dev *dev)
|
|||
|
||||
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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user