From owner-svn-src-all@FreeBSD.ORG Wed Jul 23 22:29:23 2014 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 0A1AE42D; Wed, 23 Jul 2014 22:29:23 +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 EB39721B1; Wed, 23 Jul 2014 22:29:22 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.8/8.14.8) with ESMTP id s6NMTMbd024929; Wed, 23 Jul 2014 22:29:22 GMT (envelope-from np@svn.freebsd.org) Received: (from np@localhost) by svn.freebsd.org (8.14.8/8.14.8/Submit) id s6NMTMIN024923; Wed, 23 Jul 2014 22:29:22 GMT (envelope-from np@svn.freebsd.org) Message-Id: <201407232229.s6NMTMIN024923@svn.freebsd.org> From: Navdeep Parhar Date: Wed, 23 Jul 2014 22:29:22 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r269032 - head/sys/dev/cxgbe 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 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: Wed, 23 Jul 2014 22:29:23 -0000 Author: np Date: Wed Jul 23 22:29:22 2014 New Revision: 269032 URL: http://svnweb.freebsd.org/changeset/base/269032 Log: cxgbe(4): Keep track of the clusters that have to be freed by the custom free routine (rxb_free) in the driver. Fail MOD_UNLOAD with EBUSY if any such cluster has been handed up to the kernel but hasn't been freed yet. This prevents a panic later when the cluster finally needs to be freed but rxb_free is gone from the kernel. MFC after: 1 week Modified: head/sys/dev/cxgbe/adapter.h head/sys/dev/cxgbe/t4_main.c head/sys/dev/cxgbe/t4_sge.c Modified: head/sys/dev/cxgbe/adapter.h ============================================================================== --- head/sys/dev/cxgbe/adapter.h Wed Jul 23 22:18:43 2014 (r269031) +++ head/sys/dev/cxgbe/adapter.h Wed Jul 23 22:29:22 2014 (r269032) @@ -985,6 +985,8 @@ void t4_nm_intr(void *); /* t4_sge.c */ void t4_sge_modload(void); +void t4_sge_modunload(void); +uint64_t t4_sge_extfree_refs(void); void t4_init_sge_cpl_handlers(struct adapter *); void t4_tweak_chip_settings(struct adapter *); int t4_read_chip_settings(struct adapter *); Modified: head/sys/dev/cxgbe/t4_main.c ============================================================================== --- head/sys/dev/cxgbe/t4_main.c Wed Jul 23 22:18:43 2014 (r269031) +++ head/sys/dev/cxgbe/t4_main.c Wed Jul 23 22:29:22 2014 (r269032) @@ -8259,6 +8259,9 @@ tweak_tunables(void) t4_intr_types &= INTR_MSIX | INTR_MSI | INTR_INTX; } +static struct sx mlu; /* mod load unload */ +SX_SYSINIT(cxgbe_mlu, &mlu, "cxgbe mod load/unload"); + static int mod_event(module_t mod, int cmd, void *arg) { @@ -8267,41 +8270,67 @@ mod_event(module_t mod, int cmd, void *a switch (cmd) { case MOD_LOAD: - if (atomic_fetchadd_int(&loaded, 1)) - break; - t4_sge_modload(); - sx_init(&t4_list_lock, "T4/T5 adapters"); - SLIST_INIT(&t4_list); + sx_xlock(&mlu); + if (loaded++ == 0) { + t4_sge_modload(); + sx_init(&t4_list_lock, "T4/T5 adapters"); + SLIST_INIT(&t4_list); #ifdef TCP_OFFLOAD - sx_init(&t4_uld_list_lock, "T4/T5 ULDs"); - SLIST_INIT(&t4_uld_list); + sx_init(&t4_uld_list_lock, "T4/T5 ULDs"); + SLIST_INIT(&t4_uld_list); #endif - t4_tracer_modload(); - tweak_tunables(); + t4_tracer_modload(); + tweak_tunables(); + } + sx_xunlock(&mlu); break; case MOD_UNLOAD: - if (atomic_fetchadd_int(&loaded, -1) > 1) - break; - t4_tracer_modunload(); + sx_xlock(&mlu); + if (--loaded == 0) { + int tries; + + sx_slock(&t4_list_lock); + if (!SLIST_EMPTY(&t4_list)) { + rc = EBUSY; + sx_sunlock(&t4_list_lock); + goto done_unload; + } +#ifdef TCP_OFFLOAD + sx_slock(&t4_uld_list_lock); + if (!SLIST_EMPTY(&t4_uld_list)) { + rc = EBUSY; + sx_sunlock(&t4_uld_list_lock); + sx_sunlock(&t4_list_lock); + goto done_unload; + } +#endif + tries = 0; + while (tries++ < 5 && t4_sge_extfree_refs() != 0) { + uprintf("%ju clusters with custom free routine " + "still is use.\n", t4_sge_extfree_refs()); + pause("t4unload", 2 * hz); + } #ifdef TCP_OFFLOAD - sx_slock(&t4_uld_list_lock); - if (!SLIST_EMPTY(&t4_uld_list)) { - rc = EBUSY; sx_sunlock(&t4_uld_list_lock); - break; - } - sx_sunlock(&t4_uld_list_lock); - sx_destroy(&t4_uld_list_lock); #endif - sx_slock(&t4_list_lock); - if (!SLIST_EMPTY(&t4_list)) { - rc = EBUSY; sx_sunlock(&t4_list_lock); - break; + + if (t4_sge_extfree_refs() == 0) { + t4_tracer_modunload(); +#ifdef TCP_OFFLOAD + sx_destroy(&t4_uld_list_lock); +#endif + sx_destroy(&t4_list_lock); + t4_sge_modunload(); + loaded = 0; + } else { + rc = EBUSY; + loaded++; /* undo earlier decrement */ + } } - sx_sunlock(&t4_list_lock); - sx_destroy(&t4_list_lock); +done_unload: + sx_xunlock(&mlu); break; } Modified: head/sys/dev/cxgbe/t4_sge.c ============================================================================== --- head/sys/dev/cxgbe/t4_sge.c Wed Jul 23 22:18:43 2014 (r269031) +++ head/sys/dev/cxgbe/t4_sge.c Wed Jul 23 22:29:22 2014 (r269032) @@ -44,6 +44,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -258,6 +259,9 @@ static int handle_fw_msg(struct sge_iq * static int sysctl_uint16(SYSCTL_HANDLER_ARGS); static int sysctl_bufsizes(SYSCTL_HANDLER_ARGS); +static counter_u64_t extfree_refs; +static counter_u64_t extfree_rels; + /* * Called on MOD_LOAD. Validates and calculates the SGE tunables. */ @@ -329,6 +333,30 @@ t4_sge_modload(void) " using 0 instead.\n", cong_drop); cong_drop = 0; } + + extfree_refs = counter_u64_alloc(M_WAITOK); + extfree_rels = counter_u64_alloc(M_WAITOK); + counter_u64_zero(extfree_refs); + counter_u64_zero(extfree_rels); +} + +void +t4_sge_modunload(void) +{ + + counter_u64_free(extfree_refs); + counter_u64_free(extfree_rels); +} + +uint64_t +t4_sge_extfree_refs(void) +{ + uint64_t refs, rels; + + rels = counter_u64_fetch(extfree_rels); + refs = counter_u64_fetch(extfree_refs); + + return (refs - rels); } void @@ -1513,6 +1541,7 @@ rxb_free(struct mbuf *m, void *arg1, voi caddr_t cl = arg2; uma_zfree(zone, cl); + counter_u64_add(extfree_rels, 1); } /* @@ -1574,7 +1603,8 @@ get_scatter_segment(struct adapter *sc, fl->mbuf_inlined++; m_extaddref(m, payload, padded_len, &clm->refcount, rxb_free, swz->zone, sd->cl); - sd->nmbuf++; + if (sd->nmbuf++ == 0) + counter_u64_add(extfree_refs, 1); } else { @@ -1591,7 +1621,8 @@ get_scatter_segment(struct adapter *sc, if (clm != NULL) { m_extaddref(m, payload, padded_len, &clm->refcount, rxb_free, swz->zone, sd->cl); - sd->nmbuf++; + if (sd->nmbuf++ == 0) + counter_u64_add(extfree_refs, 1); } else { m_cljset(m, sd->cl, swz->type); sd->cl = NULL; /* consumed, not a recycle candidate */ @@ -3280,6 +3311,7 @@ refill_fl(struct adapter *sc, struct sge if (atomic_fetchadd_int(&clm->refcount, -1) == 1) { fl->cl_recycled++; + counter_u64_add(extfree_rels, 1); goto recycled; } sd->cl = NULL; /* gave up my reference */ @@ -3381,9 +3413,11 @@ free_fl_sdesc(struct adapter *sc, struct cll = &sd->cll; clm = cl_metadata(sc, fl, cll, sd->cl); - if (sd->nmbuf == 0 || - (clm && atomic_fetchadd_int(&clm->refcount, -1) == 1)) { + if (sd->nmbuf == 0) + uma_zfree(sc->sge.sw_zone_info[cll->zidx].zone, sd->cl); + else if (clm && atomic_fetchadd_int(&clm->refcount, -1) == 1) { uma_zfree(sc->sge.sw_zone_info[cll->zidx].zone, sd->cl); + counter_u64_add(extfree_rels, 1); } sd->cl = NULL; }