Date: Wed, 23 Jul 2014 22:29:22 +0000 (UTC) From: Navdeep Parhar <np@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r269032 - head/sys/dev/cxgbe Message-ID: <201407232229.s6NMTMIN024923@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
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 <sys/time.h> #include <sys/sysctl.h> #include <sys/smp.h> +#include <sys/counter.h> #include <net/bpf.h> #include <net/ethernet.h> #include <net/if.h> @@ -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; }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201407232229.s6NMTMIN024923>