IB/rxe: Hold refs when running tasklets
It might be possible for all of a QP's references to be dropped while one of that QP's tasklets is running. For example, the completer might run during QP destroy. If qp->valid is false, it will drop all of the packets on the resp_pkts list, potentially removing the last reference. Then it tries to advance the SQ consumer pointer. If the SQ's buffer has already been destroyed, the system will panic. To be safe, hold a reference on the QP for the duration of each tasklet. Signed-off-by: Andrew Boyer <andrew.boyer@dell.com> Signed-off-by: Doug Ledford <dledford@redhat.com>
This commit is contained in:
parent
07bf9627d5
commit
37f69f43fb
3 changed files with 11 additions and 1 deletions
|
@ -511,6 +511,8 @@ int rxe_completer(void *arg)
|
|||
struct rxe_pkt_info *pkt = NULL;
|
||||
enum comp_state state;
|
||||
|
||||
rxe_add_ref(qp);
|
||||
|
||||
if (!qp->valid) {
|
||||
while ((skb = skb_dequeue(&qp->resp_pkts))) {
|
||||
rxe_drop_ref(qp);
|
||||
|
@ -740,11 +742,13 @@ exit:
|
|||
/* we come here if we are done with processing and want the task to
|
||||
* exit from the loop calling us
|
||||
*/
|
||||
rxe_drop_ref(qp);
|
||||
return -EAGAIN;
|
||||
|
||||
done:
|
||||
/* we come here if we have processed a packet we want the task to call
|
||||
* us again to see if there is anything else to do
|
||||
*/
|
||||
rxe_drop_ref(qp);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -596,6 +596,8 @@ int rxe_requester(void *arg)
|
|||
struct rxe_send_wqe rollback_wqe;
|
||||
u32 rollback_psn;
|
||||
|
||||
rxe_add_ref(qp);
|
||||
|
||||
next_wqe:
|
||||
if (unlikely(!qp->valid || qp->req.state == QP_STATE_ERROR))
|
||||
goto exit;
|
||||
|
@ -750,9 +752,10 @@ complete:
|
|||
while (rxe_completer(qp) == 0)
|
||||
;
|
||||
}
|
||||
|
||||
rxe_drop_ref(qp);
|
||||
return 0;
|
||||
|
||||
exit:
|
||||
rxe_drop_ref(qp);
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
|
|
@ -1212,6 +1212,8 @@ int rxe_responder(void *arg)
|
|||
struct rxe_pkt_info *pkt = NULL;
|
||||
int ret = 0;
|
||||
|
||||
rxe_add_ref(qp);
|
||||
|
||||
qp->resp.aeth_syndrome = AETH_ACK_UNLIMITED;
|
||||
|
||||
if (!qp->valid) {
|
||||
|
@ -1400,5 +1402,6 @@ int rxe_responder(void *arg)
|
|||
exit:
|
||||
ret = -EAGAIN;
|
||||
done:
|
||||
rxe_drop_ref(qp);
|
||||
return ret;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue