提交 ca5a2202 编写于 作者: S Steve Wise 提交者: Roland Dreier

RDMA/cxgb4: Set/reset the EP timer inside EP lock

Endpoint timer manipulation needs to be done inside the lock.  Otherwise
we can get into a situation where a timer is stopped before it is started,
which hits the WARN_ON() in stop_ep_timer().
Signed-off-by: NSteve Wise <swise@opengridcomputing.com>
Signed-off-by: NRoland Dreier <rolandd@cisco.com>
上级 d4f1a5c6
...@@ -1484,8 +1484,6 @@ static int peer_close(struct c4iw_dev *dev, struct sk_buff *skb) ...@@ -1484,8 +1484,6 @@ static int peer_close(struct c4iw_dev *dev, struct sk_buff *skb)
int closing = 0; int closing = 0;
struct tid_info *t = dev->rdev.lldi.tids; struct tid_info *t = dev->rdev.lldi.tids;
unsigned int tid = GET_TID(hdr); unsigned int tid = GET_TID(hdr);
int start_timer = 0;
int stop_timer = 0;
ep = lookup_tid(t, tid); ep = lookup_tid(t, tid);
PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
...@@ -1522,7 +1520,7 @@ static int peer_close(struct c4iw_dev *dev, struct sk_buff *skb) ...@@ -1522,7 +1520,7 @@ static int peer_close(struct c4iw_dev *dev, struct sk_buff *skb)
wake_up(&ep->com.waitq); wake_up(&ep->com.waitq);
break; break;
case FPDU_MODE: case FPDU_MODE:
start_timer = 1; start_ep_timer(ep);
__state_set(&ep->com, CLOSING); __state_set(&ep->com, CLOSING);
closing = 1; closing = 1;
peer_close_upcall(ep); peer_close_upcall(ep);
...@@ -1535,7 +1533,7 @@ static int peer_close(struct c4iw_dev *dev, struct sk_buff *skb) ...@@ -1535,7 +1533,7 @@ static int peer_close(struct c4iw_dev *dev, struct sk_buff *skb)
disconnect = 0; disconnect = 0;
break; break;
case MORIBUND: case MORIBUND:
stop_timer = 1; stop_ep_timer(ep);
if (ep->com.cm_id && ep->com.qp) { if (ep->com.cm_id && ep->com.qp) {
attrs.next_state = C4IW_QP_STATE_IDLE; attrs.next_state = C4IW_QP_STATE_IDLE;
c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp, c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp,
...@@ -1558,10 +1556,6 @@ static int peer_close(struct c4iw_dev *dev, struct sk_buff *skb) ...@@ -1558,10 +1556,6 @@ static int peer_close(struct c4iw_dev *dev, struct sk_buff *skb)
c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp, c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp,
C4IW_QP_ATTR_NEXT_STATE, &attrs, 1); C4IW_QP_ATTR_NEXT_STATE, &attrs, 1);
} }
if (start_timer)
start_ep_timer(ep);
if (stop_timer)
stop_ep_timer(ep);
if (disconnect) if (disconnect)
c4iw_ep_disconnect(ep, 0, GFP_KERNEL); c4iw_ep_disconnect(ep, 0, GFP_KERNEL);
if (release) if (release)
...@@ -1590,7 +1584,6 @@ static int peer_abort(struct c4iw_dev *dev, struct sk_buff *skb) ...@@ -1590,7 +1584,6 @@ static int peer_abort(struct c4iw_dev *dev, struct sk_buff *skb)
unsigned long flags; unsigned long flags;
struct tid_info *t = dev->rdev.lldi.tids; struct tid_info *t = dev->rdev.lldi.tids;
unsigned int tid = GET_TID(req); unsigned int tid = GET_TID(req);
int stop_timer = 0;
ep = lookup_tid(t, tid); ep = lookup_tid(t, tid);
if (is_neg_adv_abort(req->status)) { if (is_neg_adv_abort(req->status)) {
...@@ -1605,10 +1598,10 @@ static int peer_abort(struct c4iw_dev *dev, struct sk_buff *skb) ...@@ -1605,10 +1598,10 @@ static int peer_abort(struct c4iw_dev *dev, struct sk_buff *skb)
case CONNECTING: case CONNECTING:
break; break;
case MPA_REQ_WAIT: case MPA_REQ_WAIT:
stop_timer = 1; stop_ep_timer(ep);
break; break;
case MPA_REQ_SENT: case MPA_REQ_SENT:
stop_timer = 1; stop_ep_timer(ep);
connect_reply_upcall(ep, -ECONNRESET); connect_reply_upcall(ep, -ECONNRESET);
break; break;
case MPA_REP_SENT: case MPA_REP_SENT:
...@@ -1632,7 +1625,7 @@ static int peer_abort(struct c4iw_dev *dev, struct sk_buff *skb) ...@@ -1632,7 +1625,7 @@ static int peer_abort(struct c4iw_dev *dev, struct sk_buff *skb)
break; break;
case MORIBUND: case MORIBUND:
case CLOSING: case CLOSING:
stop_timer = 1; stop_ep_timer(ep);
/*FALLTHROUGH*/ /*FALLTHROUGH*/
case FPDU_MODE: case FPDU_MODE:
if (ep->com.cm_id && ep->com.qp) { if (ep->com.cm_id && ep->com.qp) {
...@@ -1678,8 +1671,6 @@ static int peer_abort(struct c4iw_dev *dev, struct sk_buff *skb) ...@@ -1678,8 +1671,6 @@ static int peer_abort(struct c4iw_dev *dev, struct sk_buff *skb)
rpl->cmd = CPL_ABORT_NO_RST; rpl->cmd = CPL_ABORT_NO_RST;
c4iw_ofld_send(&ep->com.dev->rdev, rpl_skb); c4iw_ofld_send(&ep->com.dev->rdev, rpl_skb);
out: out:
if (stop_timer)
stop_ep_timer(ep);
if (release) if (release)
release_ep_resources(ep); release_ep_resources(ep);
return 0; return 0;
...@@ -1694,7 +1685,6 @@ static int close_con_rpl(struct c4iw_dev *dev, struct sk_buff *skb) ...@@ -1694,7 +1685,6 @@ static int close_con_rpl(struct c4iw_dev *dev, struct sk_buff *skb)
int release = 0; int release = 0;
struct tid_info *t = dev->rdev.lldi.tids; struct tid_info *t = dev->rdev.lldi.tids;
unsigned int tid = GET_TID(rpl); unsigned int tid = GET_TID(rpl);
int stop_timer = 0;
ep = lookup_tid(t, tid); ep = lookup_tid(t, tid);
...@@ -1708,7 +1698,7 @@ static int close_con_rpl(struct c4iw_dev *dev, struct sk_buff *skb) ...@@ -1708,7 +1698,7 @@ static int close_con_rpl(struct c4iw_dev *dev, struct sk_buff *skb)
__state_set(&ep->com, MORIBUND); __state_set(&ep->com, MORIBUND);
break; break;
case MORIBUND: case MORIBUND:
stop_timer = 1; stop_ep_timer(ep);
if ((ep->com.cm_id) && (ep->com.qp)) { if ((ep->com.cm_id) && (ep->com.qp)) {
attrs.next_state = C4IW_QP_STATE_IDLE; attrs.next_state = C4IW_QP_STATE_IDLE;
c4iw_modify_qp(ep->com.qp->rhp, c4iw_modify_qp(ep->com.qp->rhp,
...@@ -1728,8 +1718,6 @@ static int close_con_rpl(struct c4iw_dev *dev, struct sk_buff *skb) ...@@ -1728,8 +1718,6 @@ static int close_con_rpl(struct c4iw_dev *dev, struct sk_buff *skb)
break; break;
} }
spin_unlock_irqrestore(&ep->com.lock, flags); spin_unlock_irqrestore(&ep->com.lock, flags);
if (stop_timer)
stop_ep_timer(ep);
if (release) if (release)
release_ep_resources(ep); release_ep_resources(ep);
return 0; return 0;
...@@ -2108,8 +2096,6 @@ int c4iw_ep_disconnect(struct c4iw_ep *ep, int abrupt, gfp_t gfp) ...@@ -2108,8 +2096,6 @@ int c4iw_ep_disconnect(struct c4iw_ep *ep, int abrupt, gfp_t gfp)
int close = 0; int close = 0;
int fatal = 0; int fatal = 0;
struct c4iw_rdev *rdev; struct c4iw_rdev *rdev;
int start_timer = 0;
int stop_timer = 0;
spin_lock_irqsave(&ep->com.lock, flags); spin_lock_irqsave(&ep->com.lock, flags);
...@@ -2133,7 +2119,7 @@ int c4iw_ep_disconnect(struct c4iw_ep *ep, int abrupt, gfp_t gfp) ...@@ -2133,7 +2119,7 @@ int c4iw_ep_disconnect(struct c4iw_ep *ep, int abrupt, gfp_t gfp)
ep->com.state = ABORTING; ep->com.state = ABORTING;
else { else {
ep->com.state = CLOSING; ep->com.state = CLOSING;
start_timer = 1; start_ep_timer(ep);
} }
set_bit(CLOSE_SENT, &ep->com.flags); set_bit(CLOSE_SENT, &ep->com.flags);
break; break;
...@@ -2141,7 +2127,7 @@ int c4iw_ep_disconnect(struct c4iw_ep *ep, int abrupt, gfp_t gfp) ...@@ -2141,7 +2127,7 @@ int c4iw_ep_disconnect(struct c4iw_ep *ep, int abrupt, gfp_t gfp)
if (!test_and_set_bit(CLOSE_SENT, &ep->com.flags)) { if (!test_and_set_bit(CLOSE_SENT, &ep->com.flags)) {
close = 1; close = 1;
if (abrupt) { if (abrupt) {
stop_timer = 1; stop_ep_timer(ep);
ep->com.state = ABORTING; ep->com.state = ABORTING;
} else } else
ep->com.state = MORIBUND; ep->com.state = MORIBUND;
...@@ -2159,10 +2145,6 @@ int c4iw_ep_disconnect(struct c4iw_ep *ep, int abrupt, gfp_t gfp) ...@@ -2159,10 +2145,6 @@ int c4iw_ep_disconnect(struct c4iw_ep *ep, int abrupt, gfp_t gfp)
} }
spin_unlock_irqrestore(&ep->com.lock, flags); spin_unlock_irqrestore(&ep->com.lock, flags);
if (start_timer)
start_ep_timer(ep);
if (stop_timer)
stop_ep_timer(ep);
if (close) { if (close) {
if (abrupt) if (abrupt)
ret = abort_connection(ep, NULL, gfp); ret = abort_connection(ep, NULL, gfp);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册