Commit 874d8df5 authored by Steve Wise's avatar Steve Wise Committed by Roland Dreier

RDMA/cxgb3: Release dependent resources only when endpoint memory is freed.

The cxgb3 l2t entry, hwtid, and dst entry were being released before
all the iwch_ep references were released.  This can cause a crash in
t3_l2t_send_slow() and other places where the l2t entry is used.

The fix is to defer releasing these resources until all endpoint
references are gone.

Details:

- move flags field to the iwch_ep_common struct.
- add a flag indicating resources are to be released.
- release resources at endpoint free time instead of close/abort time.
Signed-off-by: default avatarSteve Wise <swise@opengridcomputing.com>
Signed-off-by: default avatarRoland Dreier <rolandd@cisco.com>
parent 04b5d028
...@@ -282,18 +282,22 @@ static void *alloc_ep(int size, gfp_t gfp) ...@@ -282,18 +282,22 @@ static void *alloc_ep(int size, gfp_t gfp)
void __free_ep(struct kref *kref) void __free_ep(struct kref *kref)
{ {
struct iwch_ep_common *epc; struct iwch_ep *ep;
epc = container_of(kref, struct iwch_ep_common, kref); ep = container_of(container_of(kref, struct iwch_ep_common, kref),
PDBG("%s ep %p state %s\n", __func__, epc, states[state_read(epc)]); struct iwch_ep, com);
kfree(epc); PDBG("%s ep %p state %s\n", __func__, ep, states[state_read(&ep->com)]);
if (ep->com.flags & RELEASE_RESOURCES) {
cxgb3_remove_tid(ep->com.tdev, (void *)ep, ep->hwtid);
dst_release(ep->dst);
l2t_release(L2DATA(ep->com.tdev), ep->l2t);
}
kfree(ep);
} }
static void release_ep_resources(struct iwch_ep *ep) static void release_ep_resources(struct iwch_ep *ep)
{ {
PDBG("%s ep %p tid %d\n", __func__, ep, ep->hwtid); PDBG("%s ep %p tid %d\n", __func__, ep, ep->hwtid);
cxgb3_remove_tid(ep->com.tdev, (void *)ep, ep->hwtid); ep->com.flags |= RELEASE_RESOURCES;
dst_release(ep->dst);
l2t_release(L2DATA(ep->com.tdev), ep->l2t);
put_ep(&ep->com); put_ep(&ep->com);
} }
...@@ -1152,8 +1156,8 @@ static int abort_rpl(struct t3cdev *tdev, struct sk_buff *skb, void *ctx) ...@@ -1152,8 +1156,8 @@ static int abort_rpl(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
* We get 2 abort replies from the HW. The first one must * We get 2 abort replies from the HW. The first one must
* be ignored except for scribbling that we need one more. * be ignored except for scribbling that we need one more.
*/ */
if (!(ep->flags & ABORT_REQ_IN_PROGRESS)) { if (!(ep->com.flags & ABORT_REQ_IN_PROGRESS)) {
ep->flags |= ABORT_REQ_IN_PROGRESS; ep->com.flags |= ABORT_REQ_IN_PROGRESS;
return CPL_RET_BUF_DONE; return CPL_RET_BUF_DONE;
} }
...@@ -1557,8 +1561,8 @@ static int peer_abort(struct t3cdev *tdev, struct sk_buff *skb, void *ctx) ...@@ -1557,8 +1561,8 @@ static int peer_abort(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
* We get 2 peer aborts from the HW. The first one must * We get 2 peer aborts from the HW. The first one must
* be ignored except for scribbling that we need one more. * be ignored except for scribbling that we need one more.
*/ */
if (!(ep->flags & PEER_ABORT_IN_PROGRESS)) { if (!(ep->com.flags & PEER_ABORT_IN_PROGRESS)) {
ep->flags |= PEER_ABORT_IN_PROGRESS; ep->com.flags |= PEER_ABORT_IN_PROGRESS;
return CPL_RET_BUF_DONE; return CPL_RET_BUF_DONE;
} }
......
...@@ -147,6 +147,7 @@ enum iwch_ep_state { ...@@ -147,6 +147,7 @@ enum iwch_ep_state {
enum iwch_ep_flags { enum iwch_ep_flags {
PEER_ABORT_IN_PROGRESS = (1 << 0), PEER_ABORT_IN_PROGRESS = (1 << 0),
ABORT_REQ_IN_PROGRESS = (1 << 1), ABORT_REQ_IN_PROGRESS = (1 << 1),
RELEASE_RESOURCES = (1 << 2),
}; };
struct iwch_ep_common { struct iwch_ep_common {
...@@ -161,6 +162,7 @@ struct iwch_ep_common { ...@@ -161,6 +162,7 @@ struct iwch_ep_common {
wait_queue_head_t waitq; wait_queue_head_t waitq;
int rpl_done; int rpl_done;
int rpl_err; int rpl_err;
u32 flags;
}; };
struct iwch_listen_ep { struct iwch_listen_ep {
...@@ -188,7 +190,6 @@ struct iwch_ep { ...@@ -188,7 +190,6 @@ struct iwch_ep {
u16 plen; u16 plen;
u32 ird; u32 ird;
u32 ord; u32 ord;
u32 flags;
}; };
static inline struct iwch_ep *to_ep(struct iw_cm_id *cm_id) static inline struct iwch_ep *to_ep(struct iw_cm_id *cm_id)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment