aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/hw/cxgb3
diff options
context:
space:
mode:
authorSteve Wise <swise@opengridcomputing.com>2009-03-30 11:37:59 -0400
committerRoland Dreier <rolandd@cisco.com>2009-03-30 11:37:59 -0400
commit874d8df5ed6e36fed07b524c266f6a96dd6d10d9 (patch)
tree22fe735a0a00fda013e8514bdc00a5a31e612b77 /drivers/infiniband/hw/cxgb3
parent04b5d028f50ff05a8f9ae049ee71f8fdfcf1f5de (diff)
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: Steve Wise <swise@opengridcomputing.com> Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers/infiniband/hw/cxgb3')
-rw-r--r--drivers/infiniband/hw/cxgb3/iwch_cm.c26
-rw-r--r--drivers/infiniband/hw/cxgb3/iwch_cm.h3
2 files changed, 17 insertions, 12 deletions
diff --git a/drivers/infiniband/hw/cxgb3/iwch_cm.c b/drivers/infiniband/hw/cxgb3/iwch_cm.c
index 59e1c5f00785..fef3f1ae7225 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_cm.c
+++ b/drivers/infiniband/hw/cxgb3/iwch_cm.c
@@ -282,18 +282,22 @@ static void *alloc_ep(int size, gfp_t gfp)
282 282
283void __free_ep(struct kref *kref) 283void __free_ep(struct kref *kref)
284{ 284{
285 struct iwch_ep_common *epc; 285 struct iwch_ep *ep;
286 epc = container_of(kref, struct iwch_ep_common, kref); 286 ep = container_of(container_of(kref, struct iwch_ep_common, kref),
287 PDBG("%s ep %p state %s\n", __func__, epc, states[state_read(epc)]); 287 struct iwch_ep, com);
288 kfree(epc); 288 PDBG("%s ep %p state %s\n", __func__, ep, states[state_read(&ep->com)]);
289 if (ep->com.flags & RELEASE_RESOURCES) {
290 cxgb3_remove_tid(ep->com.tdev, (void *)ep, ep->hwtid);
291 dst_release(ep->dst);
292 l2t_release(L2DATA(ep->com.tdev), ep->l2t);
293 }
294 kfree(ep);
289} 295}
290 296
291static void release_ep_resources(struct iwch_ep *ep) 297static void release_ep_resources(struct iwch_ep *ep)
292{ 298{
293 PDBG("%s ep %p tid %d\n", __func__, ep, ep->hwtid); 299 PDBG("%s ep %p tid %d\n", __func__, ep, ep->hwtid);
294 cxgb3_remove_tid(ep->com.tdev, (void *)ep, ep->hwtid); 300 ep->com.flags |= RELEASE_RESOURCES;
295 dst_release(ep->dst);
296 l2t_release(L2DATA(ep->com.tdev), ep->l2t);
297 put_ep(&ep->com); 301 put_ep(&ep->com);
298} 302}
299 303
@@ -1152,8 +1156,8 @@ static int abort_rpl(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
1152 * We get 2 abort replies from the HW. The first one must 1156 * We get 2 abort replies from the HW. The first one must
1153 * be ignored except for scribbling that we need one more. 1157 * be ignored except for scribbling that we need one more.
1154 */ 1158 */
1155 if (!(ep->flags & ABORT_REQ_IN_PROGRESS)) { 1159 if (!(ep->com.flags & ABORT_REQ_IN_PROGRESS)) {
1156 ep->flags |= ABORT_REQ_IN_PROGRESS; 1160 ep->com.flags |= ABORT_REQ_IN_PROGRESS;
1157 return CPL_RET_BUF_DONE; 1161 return CPL_RET_BUF_DONE;
1158 } 1162 }
1159 1163
@@ -1557,8 +1561,8 @@ static int peer_abort(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
1557 * We get 2 peer aborts from the HW. The first one must 1561 * We get 2 peer aborts from the HW. The first one must
1558 * be ignored except for scribbling that we need one more. 1562 * be ignored except for scribbling that we need one more.
1559 */ 1563 */
1560 if (!(ep->flags & PEER_ABORT_IN_PROGRESS)) { 1564 if (!(ep->com.flags & PEER_ABORT_IN_PROGRESS)) {
1561 ep->flags |= PEER_ABORT_IN_PROGRESS; 1565 ep->com.flags |= PEER_ABORT_IN_PROGRESS;
1562 return CPL_RET_BUF_DONE; 1566 return CPL_RET_BUF_DONE;
1563 } 1567 }
1564 1568
diff --git a/drivers/infiniband/hw/cxgb3/iwch_cm.h b/drivers/infiniband/hw/cxgb3/iwch_cm.h
index d7c7e09f0996..43c0aea7eadc 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_cm.h
+++ b/drivers/infiniband/hw/cxgb3/iwch_cm.h
@@ -147,6 +147,7 @@ enum iwch_ep_state {
147enum iwch_ep_flags { 147enum iwch_ep_flags {
148 PEER_ABORT_IN_PROGRESS = (1 << 0), 148 PEER_ABORT_IN_PROGRESS = (1 << 0),
149 ABORT_REQ_IN_PROGRESS = (1 << 1), 149 ABORT_REQ_IN_PROGRESS = (1 << 1),
150 RELEASE_RESOURCES = (1 << 2),
150}; 151};
151 152
152struct iwch_ep_common { 153struct iwch_ep_common {
@@ -161,6 +162,7 @@ struct iwch_ep_common {
161 wait_queue_head_t waitq; 162 wait_queue_head_t waitq;
162 int rpl_done; 163 int rpl_done;
163 int rpl_err; 164 int rpl_err;
165 u32 flags;
164}; 166};
165 167
166struct iwch_listen_ep { 168struct iwch_listen_ep {
@@ -188,7 +190,6 @@ struct iwch_ep {
188 u16 plen; 190 u16 plen;
189 u32 ird; 191 u32 ird;
190 u32 ord; 192 u32 ord;
191 u32 flags;
192}; 193};
193 194
194static inline struct iwch_ep *to_ep(struct iw_cm_id *cm_id) 195static inline struct iwch_ep *to_ep(struct iw_cm_id *cm_id)