mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-16 00:34:20 +08:00
RDMA/rxe: Remove tasklet call from rxe_cq.c
Remove the tasklet call in rxe_cq.c and also the is_dying in the
cq struct. There is no reason for the rxe driver to defer the call
to the cq completion handler by scheduling a tasklet. rxe_cq_post()
is not called in a hard irq context.
The rxe driver currently is incorrect because the tasklet call is
made without protecting the cq pointer with a reference from having
the underlying memory freed before the deferred routine is called.
Executing the comp_handler inline fixes this problem.
Fixes: 8700e3e7c4
("Soft RoCE driver")
Signed-off-by: Bob Pearson <rpearsonhpe@gmail.com>
Link: https://lore.kernel.org/r/20230327215643.10410-1-rpearsonhpe@gmail.com
Acked-by: Zhu Yanjun <zyjzyj2000@gmail.com>
Signed-off-by: Leon Romanovsky <leon@kernel.org>
This commit is contained in:
parent
cba968e33e
commit
78b26a3353
@ -39,21 +39,6 @@ err1:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static void rxe_send_complete(struct tasklet_struct *t)
|
||||
{
|
||||
struct rxe_cq *cq = from_tasklet(cq, t, comp_task);
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&cq->cq_lock, flags);
|
||||
if (cq->is_dying) {
|
||||
spin_unlock_irqrestore(&cq->cq_lock, flags);
|
||||
return;
|
||||
}
|
||||
spin_unlock_irqrestore(&cq->cq_lock, flags);
|
||||
|
||||
cq->ibcq.comp_handler(&cq->ibcq, cq->ibcq.cq_context);
|
||||
}
|
||||
|
||||
int rxe_cq_from_init(struct rxe_dev *rxe, struct rxe_cq *cq, int cqe,
|
||||
int comp_vector, struct ib_udata *udata,
|
||||
struct rxe_create_cq_resp __user *uresp)
|
||||
@ -79,10 +64,6 @@ int rxe_cq_from_init(struct rxe_dev *rxe, struct rxe_cq *cq, int cqe,
|
||||
|
||||
cq->is_user = uresp;
|
||||
|
||||
cq->is_dying = false;
|
||||
|
||||
tasklet_setup(&cq->comp_task, rxe_send_complete);
|
||||
|
||||
spin_lock_init(&cq->cq_lock);
|
||||
cq->ibcq.cqe = cqe;
|
||||
return 0;
|
||||
@ -103,6 +84,7 @@ int rxe_cq_resize_queue(struct rxe_cq *cq, int cqe,
|
||||
return err;
|
||||
}
|
||||
|
||||
/* caller holds reference to cq */
|
||||
int rxe_cq_post(struct rxe_cq *cq, struct rxe_cqe *cqe, int solicited)
|
||||
{
|
||||
struct ib_event ev;
|
||||
@ -136,21 +118,13 @@ int rxe_cq_post(struct rxe_cq *cq, struct rxe_cqe *cqe, int solicited)
|
||||
if ((cq->notify == IB_CQ_NEXT_COMP) ||
|
||||
(cq->notify == IB_CQ_SOLICITED && solicited)) {
|
||||
cq->notify = 0;
|
||||
tasklet_schedule(&cq->comp_task);
|
||||
|
||||
cq->ibcq.comp_handler(&cq->ibcq, cq->ibcq.cq_context);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void rxe_cq_disable(struct rxe_cq *cq)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&cq->cq_lock, flags);
|
||||
cq->is_dying = true;
|
||||
spin_unlock_irqrestore(&cq->cq_lock, flags);
|
||||
}
|
||||
|
||||
void rxe_cq_cleanup(struct rxe_pool_elem *elem)
|
||||
{
|
||||
struct rxe_cq *cq = container_of(elem, typeof(*cq), elem);
|
||||
|
@ -1178,8 +1178,6 @@ static int rxe_destroy_cq(struct ib_cq *ibcq, struct ib_udata *udata)
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
rxe_cq_disable(cq);
|
||||
|
||||
err = rxe_cleanup(cq);
|
||||
if (err)
|
||||
rxe_err_cq(cq, "cleanup failed, err = %d", err);
|
||||
|
@ -63,9 +63,7 @@ struct rxe_cq {
|
||||
struct rxe_queue *queue;
|
||||
spinlock_t cq_lock;
|
||||
u8 notify;
|
||||
bool is_dying;
|
||||
bool is_user;
|
||||
struct tasklet_struct comp_task;
|
||||
atomic_t num_wq;
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user