Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 31 May 2015 23:11:25 +0000 (UTC)
From:      Navdeep Parhar <np@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org
Subject:   svn commit: r283854 - in stable/10/sys/dev/cxgbe: common tom
Message-ID:  <201505312311.t4VNBPrx047719@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: np
Date: Sun May 31 23:11:25 2015
New Revision: 283854
URL: https://svnweb.freebsd.org/changeset/base/283854

Log:
  MFC r272719:
  
  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.

Modified:
  stable/10/sys/dev/cxgbe/common/t4_msg.h
  stable/10/sys/dev/cxgbe/tom/t4_connect.c
  stable/10/sys/dev/cxgbe/tom/t4_tom.c
  stable/10/sys/dev/cxgbe/tom/t4_tom.h
  stable/10/sys/dev/cxgbe/tom/t4_tom_l2t.c
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sys/dev/cxgbe/common/t4_msg.h
==============================================================================
--- stable/10/sys/dev/cxgbe/common/t4_msg.h	Sun May 31 23:00:35 2015	(r283853)
+++ stable/10/sys/dev/cxgbe/common/t4_msg.h	Sun May 31 23:11:25 2015	(r283854)
@@ -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: stable/10/sys/dev/cxgbe/tom/t4_connect.c
==============================================================================
--- stable/10/sys/dev/cxgbe/tom/t4_connect.c	Sun May 31 23:00:35 2015	(r283853)
+++ stable/10/sys/dev/cxgbe/tom/t4_connect.c	Sun May 31 23:11:25 2015	(r283854)
@@ -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: stable/10/sys/dev/cxgbe/tom/t4_tom.c
==============================================================================
--- stable/10/sys/dev/cxgbe/tom/t4_tom.c	Sun May 31 23:00:35 2015	(r283853)
+++ stable/10/sys/dev/cxgbe/tom/t4_tom.c	Sun May 31 23:11:25 2015	(r283854)
@@ -97,6 +97,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;
@@ -902,6 +903,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))
@@ -911,6 +914,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
@@ -938,6 +979,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)
@@ -1011,6 +1057,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: stable/10/sys/dev/cxgbe/tom/t4_tom.h
==============================================================================
--- stable/10/sys/dev/cxgbe/tom/t4_tom.h	Sun May 31 23:00:35 2015	(r283853)
+++ stable/10/sys/dev/cxgbe/tom/t4_tom.h	Sun May 31 23:11:25 2015	(r283854)
@@ -199,6 +199,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 *
@@ -241,6 +246,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: stable/10/sys/dev/cxgbe/tom/t4_tom_l2t.c
==============================================================================
--- stable/10/sys/dev/cxgbe/tom/t4_tom_l2t.c	Sun May 31 23:00:35 2015	(r283853)
+++ stable/10/sys/dev/cxgbe/tom/t4_tom_l2t.c	Sun May 31 23:11:25 2015	(r283854)
@@ -41,6 +41,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/rwlock.h>
 #include <sys/socket.h>
 #include <sys/sbuf.h>
+#include <sys/taskqueue.h>
 #include <net/if.h>
 #include <net/if_types.h>
 #include <net/ethernet.h>
@@ -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);
 	}
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201505312311.t4VNBPrx047719>