From owner-svn-src-all@FreeBSD.ORG Tue Oct 7 21:26:24 2014 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id AA8C78A7; Tue, 7 Oct 2014 21:26:24 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 9671B17D; Tue, 7 Oct 2014 21:26:24 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.9/8.14.9) with ESMTP id s97LQOEs025769; Tue, 7 Oct 2014 21:26:24 GMT (envelope-from np@FreeBSD.org) Received: (from np@localhost) by svn.freebsd.org (8.14.9/8.14.9/Submit) id s97LQNrX025760; Tue, 7 Oct 2014 21:26:23 GMT (envelope-from np@FreeBSD.org) Message-Id: <201410072126.s97LQNrX025760@svn.freebsd.org> X-Authentication-Warning: svn.freebsd.org: np set sender to np@FreeBSD.org using -f From: Navdeep Parhar Date: Tue, 7 Oct 2014 21:26:23 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r272719 - in head/sys/dev/cxgbe: common tom X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 07 Oct 2014 21:26:24 -0000 Author: np Date: Tue Oct 7 21:26:22 2014 New Revision: 272719 URL: https://svnweb.freebsd.org/changeset/base/272719 Log: cxgbe/tom: don't leak resources tied to an active open request that cannot be sent to the chip because a prerequisite L2 resolution failed. Submitted by: Hariprasad at chelsio dot com (original version) MFC after: 2 weeks. Modified: head/sys/dev/cxgbe/common/t4_msg.h head/sys/dev/cxgbe/tom/t4_connect.c head/sys/dev/cxgbe/tom/t4_tom.c head/sys/dev/cxgbe/tom/t4_tom.h head/sys/dev/cxgbe/tom/t4_tom_l2t.c Modified: head/sys/dev/cxgbe/common/t4_msg.h ============================================================================== --- head/sys/dev/cxgbe/common/t4_msg.h Tue Oct 7 20:13:47 2014 (r272718) +++ head/sys/dev/cxgbe/common/t4_msg.h Tue Oct 7 21:26:22 2014 (r272719) @@ -273,6 +273,7 @@ union opcode_tid { /* extract the TID from a CPL command */ #define GET_TID(cmd) (G_TID(ntohl(OPCODE_TID(cmd)))) +#define GET_OPCODE(cmd) ((cmd)->ot.opcode) /* partitioning of TID fields that also carry a queue id */ #define S_TID_TID 0 Modified: head/sys/dev/cxgbe/tom/t4_connect.c ============================================================================== --- head/sys/dev/cxgbe/tom/t4_connect.c Tue Oct 7 20:13:47 2014 (r272718) +++ head/sys/dev/cxgbe/tom/t4_connect.c Tue Oct 7 21:26:22 2014 (r272719) @@ -115,8 +115,8 @@ do_act_establish(struct sge_iq *iq, cons { struct adapter *sc = iq->adapter; const struct cpl_act_establish *cpl = (const void *)(rss + 1); - unsigned int tid = GET_TID(cpl); - unsigned int atid = G_TID_TID(ntohl(cpl->tos_atid)); + u_int tid = GET_TID(cpl); + u_int atid = G_TID_TID(ntohl(cpl->tos_atid)); struct toepcb *toep = lookup_atid(sc, atid); struct inpcb *inp = toep->inp; @@ -178,17 +178,34 @@ act_open_rpl_status_to_errno(int status) } } +void +act_open_failure_cleanup(struct adapter *sc, u_int atid, u_int status) +{ + struct toepcb *toep = lookup_atid(sc, atid); + struct inpcb *inp = toep->inp; + struct toedev *tod = &toep->td->tod; + + free_atid(sc, atid); + toep->tid = -1; + + if (status != EAGAIN) + INP_INFO_WLOCK(&V_tcbinfo); + INP_WLOCK(inp); + toe_connect_failed(tod, inp, status); + final_cpl_received(toep); /* unlocks inp */ + if (status != EAGAIN) + INP_INFO_WUNLOCK(&V_tcbinfo); +} + static int do_act_open_rpl(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m) { struct adapter *sc = iq->adapter; const struct cpl_act_open_rpl *cpl = (const void *)(rss + 1); - unsigned int atid = G_TID_TID(G_AOPEN_ATID(be32toh(cpl->atid_status))); - unsigned int status = G_AOPEN_STATUS(be32toh(cpl->atid_status)); + u_int atid = G_TID_TID(G_AOPEN_ATID(be32toh(cpl->atid_status))); + u_int status = G_AOPEN_STATUS(be32toh(cpl->atid_status)); struct toepcb *toep = lookup_atid(sc, atid); - struct inpcb *inp = toep->inp; - struct toedev *tod = &toep->td->tod; int rc; KASSERT(m == NULL, ("%s: wasn't expecting payload", __func__)); @@ -200,20 +217,11 @@ do_act_open_rpl(struct sge_iq *iq, const if (negative_advice(status)) return (0); - free_atid(sc, atid); - toep->tid = -1; - if (status && act_open_has_tid(status)) release_tid(sc, GET_TID(cpl), toep->ctrlq); rc = act_open_rpl_status_to_errno(status); - if (rc != EAGAIN) - INP_INFO_WLOCK(&V_tcbinfo); - INP_WLOCK(inp); - toe_connect_failed(tod, inp, rc); - final_cpl_received(toep); /* unlocks inp */ - if (rc != EAGAIN) - INP_INFO_WUNLOCK(&V_tcbinfo); + act_open_failure_cleanup(sc, atid, rc); return (0); } Modified: head/sys/dev/cxgbe/tom/t4_tom.c ============================================================================== --- head/sys/dev/cxgbe/tom/t4_tom.c Tue Oct 7 20:13:47 2014 (r272718) +++ head/sys/dev/cxgbe/tom/t4_tom.c Tue Oct 7 21:26:22 2014 (r272719) @@ -98,6 +98,7 @@ static void t4_clip_task(void *, int); static void update_clip_table(struct adapter *, struct tom_data *); static void destroy_clip_table(struct adapter *, struct tom_data *); static void free_tom_data(struct adapter *, struct tom_data *); +static void reclaim_wr_resources(void *, int); static int in6_ifaddr_gen; static eventhandler_tag ifaddr_evhandler; @@ -903,6 +904,8 @@ free_tom_data(struct adapter *sc, struct if (td->listen_mask != 0) hashdestroy(td->listen_hash, M_CXGBE, td->listen_mask); + if (mtx_initialized(&td->unsent_wr_lock)) + mtx_destroy(&td->unsent_wr_lock); if (mtx_initialized(&td->lctx_hash_lock)) mtx_destroy(&td->lctx_hash_lock); if (mtx_initialized(&td->toep_list_lock)) @@ -912,6 +915,44 @@ free_tom_data(struct adapter *sc, struct free(td, M_CXGBE); } +static void +reclaim_wr_resources(void *arg, int count) +{ + struct tom_data *td = arg; + STAILQ_HEAD(, wrqe) twr_list = STAILQ_HEAD_INITIALIZER(twr_list); + struct cpl_act_open_req *cpl; + u_int opcode, atid; + struct wrqe *wr; + struct adapter *sc; + + mtx_lock(&td->unsent_wr_lock); + STAILQ_SWAP(&td->unsent_wr_list, &twr_list, wrqe); + mtx_unlock(&td->unsent_wr_lock); + + while ((wr = STAILQ_FIRST(&twr_list)) != NULL) { + STAILQ_REMOVE_HEAD(&twr_list, link); + + cpl = wrtod(wr); + opcode = GET_OPCODE(cpl); + + switch (opcode) { + case CPL_ACT_OPEN_REQ: + case CPL_ACT_OPEN_REQ6: + atid = G_TID_TID(be32toh(OPCODE_TID(cpl))); + sc = td_adapter(td); + + CTR2(KTR_CXGBE, "%s: atid %u ", __func__, atid); + act_open_failure_cleanup(sc, atid, EHOSTUNREACH); + free(wr, M_CXGBE); + break; + default: + log(LOG_ERR, "%s: leaked work request %p, wr_len %d, " + "opcode %x\n", __func__, wr, wr->wr_len, opcode); + /* WR not freed here; go look at it with a debugger. */ + } + } +} + /* * Ground control to Major TOM * Commencing countdown, engines on @@ -939,6 +980,11 @@ t4_tom_activate(struct adapter *sc) td->listen_hash = hashinit_flags(LISTEN_HASH_SIZE, M_CXGBE, &td->listen_mask, HASH_NOWAIT); + /* List of WRs for which L2 resolution failed */ + mtx_init(&td->unsent_wr_lock, "Unsent WR list lock", NULL, MTX_DEF); + STAILQ_INIT(&td->unsent_wr_list); + TASK_INIT(&td->reclaim_wr_resources, 0, reclaim_wr_resources, td); + /* TID tables */ rc = alloc_tid_tabs(&sc->tids); if (rc != 0) @@ -1012,6 +1058,12 @@ t4_tom_deactivate(struct adapter *sc) rc = EBUSY; mtx_unlock(&td->lctx_hash_lock); + taskqueue_drain(taskqueue_thread, &td->reclaim_wr_resources); + mtx_lock(&td->unsent_wr_lock); + if (!STAILQ_EMPTY(&td->unsent_wr_list)) + rc = EBUSY; + mtx_unlock(&td->unsent_wr_lock); + if (rc == 0) { unregister_toedev(sc->tom_softc); free_tom_data(sc, td); Modified: head/sys/dev/cxgbe/tom/t4_tom.h ============================================================================== --- head/sys/dev/cxgbe/tom/t4_tom.h Tue Oct 7 20:13:47 2014 (r272718) +++ head/sys/dev/cxgbe/tom/t4_tom.h Tue Oct 7 21:26:22 2014 (r272719) @@ -210,6 +210,11 @@ struct tom_data { struct mtx clip_table_lock; struct clip_head clip_table; int clip_gen; + + /* WRs that will not be sent to the chip because L2 resolution failed */ + struct mtx unsent_wr_lock; + STAILQ_HEAD(, wrqe) unsent_wr_list; + struct task reclaim_wr_resources; }; static inline struct tom_data * @@ -252,6 +257,7 @@ void release_lip(struct tom_data *, stru void t4_init_connect_cpl_handlers(struct adapter *); int t4_connect(struct toedev *, struct socket *, struct rtentry *, struct sockaddr *); +void act_open_failure_cleanup(struct adapter *, u_int, u_int); /* t4_listen.c */ void t4_init_listen_cpl_handlers(struct adapter *); Modified: head/sys/dev/cxgbe/tom/t4_tom_l2t.c ============================================================================== --- head/sys/dev/cxgbe/tom/t4_tom_l2t.c Tue Oct 7 20:13:47 2014 (r272718) +++ head/sys/dev/cxgbe/tom/t4_tom_l2t.c Tue Oct 7 21:26:22 2014 (r272719) @@ -41,6 +41,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -161,25 +162,17 @@ send_pending(struct adapter *sc, struct } static void -resolution_failed_for_wr(struct wrqe *wr) +resolution_failed(struct adapter *sc, struct l2t_entry *e) { - log(LOG_ERR, "%s: leaked work request %p, wr_len %d\n", __func__, wr, - wr->wr_len); - - /* free(wr, M_CXGBE); */ -} - -static void -resolution_failed(struct l2t_entry *e) -{ - struct wrqe *wr; + struct tom_data *td = sc->tom_softc; mtx_assert(&e->lock, MA_OWNED); - while ((wr = STAILQ_FIRST(&e->wr_list)) != NULL) { - STAILQ_REMOVE_HEAD(&e->wr_list, link); - resolution_failed_for_wr(wr); - } + mtx_lock(&td->unsent_wr_lock); + STAILQ_CONCAT(&td->unsent_wr_list, &e->wr_list); + mtx_unlock(&td->unsent_wr_lock); + + taskqueue_enqueue(taskqueue_thread, &td->reclaim_wr_resources); } static void @@ -203,7 +196,7 @@ update_entry(struct adapter *sc, struct * need to wlock the table). */ e->state = L2T_STATE_FAILED; - resolution_failed(e); + resolution_failed(sc, e); return; } else if (lladdr == NULL) { @@ -305,12 +298,11 @@ again: if (e->state == L2T_STATE_VALID && !STAILQ_EMPTY(&e->wr_list)) send_pending(sc, e); if (e->state == L2T_STATE_FAILED) - resolution_failed(e); + resolution_failed(sc, e); mtx_unlock(&e->lock); break; case L2T_STATE_FAILED: - resolution_failed_for_wr(wr); return (EHOSTUNREACH); }