diff options
author | Raju Rangoju <rajur@chelsio.com> | 2019-02-06 12:24:44 -0500 |
---|---|---|
committer | Jason Gunthorpe <jgg@mellanox.com> | 2019-02-08 19:02:05 -0500 |
commit | f368ff188ae4b3ef6f740a15999ea0373261b619 (patch) | |
tree | 6f9c412a4066bb10bdc362c4ca8b144947ab55eb /drivers/infiniband | |
parent | 11a27e2121a544cae2dde62df9218b3d5d888a02 (diff) |
iw_cxgb4: fix srqidx leak during connection abort
When an application aborts the connection by moving QP from RTS to ERROR,
then iw_cxgb4's modify_rc_qp() RTS->ERROR logic sets the
*srqidxp to 0 via t4_set_wq_in_error(&qhp->wq, 0), and aborts the
connection by calling c4iw_ep_disconnect().
c4iw_ep_disconnect() does the following:
1. sends up a close_complete_upcall(ep, -ECONNRESET) to libcxgb4.
2. sends abort request CPL to hw.
But, since the close_complete_upcall() is sent before sending the
ABORT_REQ to hw, libcxgb4 would fail to release the srqidx if the
connection holds one. Because, the srqidx is passed up to libcxgb4 only
after corresponding ABORT_RPL is processed by kernel in abort_rpl().
This patch handle the corner-case by moving the call to
close_complete_upcall() from c4iw_ep_disconnect() to abort_rpl(). So that
libcxgb4 is notified about the -ECONNRESET only after abort_rpl(), and
libcxgb4 can relinquish the srqidx properly.
Signed-off-by: Raju Rangoju <rajur@chelsio.com>
Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
Diffstat (limited to 'drivers/infiniband')
-rw-r--r-- | drivers/infiniband/hw/cxgb4/cm.c | 5 |
1 files changed, 3 insertions, 2 deletions
diff --git a/drivers/infiniband/hw/cxgb4/cm.c b/drivers/infiniband/hw/cxgb4/cm.c index b188d89674f1..ae90b2932bd2 100644 --- a/drivers/infiniband/hw/cxgb4/cm.c +++ b/drivers/infiniband/hw/cxgb4/cm.c | |||
@@ -1941,8 +1941,10 @@ static int abort_rpl(struct c4iw_dev *dev, struct sk_buff *skb) | |||
1941 | } | 1941 | } |
1942 | mutex_unlock(&ep->com.mutex); | 1942 | mutex_unlock(&ep->com.mutex); |
1943 | 1943 | ||
1944 | if (release) | 1944 | if (release) { |
1945 | close_complete_upcall(ep, -ECONNRESET); | ||
1945 | release_ep_resources(ep); | 1946 | release_ep_resources(ep); |
1947 | } | ||
1946 | c4iw_put_ep(&ep->com); | 1948 | c4iw_put_ep(&ep->com); |
1947 | return 0; | 1949 | return 0; |
1948 | } | 1950 | } |
@@ -3684,7 +3686,6 @@ int c4iw_ep_disconnect(struct c4iw_ep *ep, int abrupt, gfp_t gfp) | |||
3684 | if (close) { | 3686 | if (close) { |
3685 | if (abrupt) { | 3687 | if (abrupt) { |
3686 | set_bit(EP_DISC_ABORT, &ep->com.history); | 3688 | set_bit(EP_DISC_ABORT, &ep->com.history); |
3687 | close_complete_upcall(ep, -ECONNRESET); | ||
3688 | ret = send_abort(ep); | 3689 | ret = send_abort(ep); |
3689 | } else { | 3690 | } else { |
3690 | set_bit(EP_DISC_CLOSE, &ep->com.history); | 3691 | set_bit(EP_DISC_CLOSE, &ep->com.history); |