Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 15 Aug 2018 03:03:01 +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: r337830 - head/sys/dev/cxgbe
Message-ID:  <201808150303.w7F331Wu016170@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: np
Date: Wed Aug 15 03:03:01 2018
New Revision: 337830
URL: https://svnweb.freebsd.org/changeset/base/337830

Log:
  cxgbe(4): Use two hashes instead of a table to keep track of
  hashfilters.  Two because the driver needs to look up a hashfilter by
  its 4-tuple or tid.
  
  A couple of fixes while here:
  - Reject attempts to add duplicate hashfilters.
  - Do not assume that any part of the 4-tuple that isn't specified is 0.
    This makes it consistent with all other mandatory parameters that
    already require explicit user input.
  
  MFC after:	2 weeks
  Sponsored by:	Chelsio Communications

Modified:
  head/sys/dev/cxgbe/adapter.h
  head/sys/dev/cxgbe/offload.h
  head/sys/dev/cxgbe/t4_filter.c
  head/sys/dev/cxgbe/t4_main.c

Modified: head/sys/dev/cxgbe/adapter.h
==============================================================================
--- head/sys/dev/cxgbe/adapter.h	Wed Aug 15 02:31:10 2018	(r337829)
+++ head/sys/dev/cxgbe/adapter.h	Wed Aug 15 03:03:01 2018	(r337830)
@@ -1270,7 +1270,7 @@ int t4_filter_rpl(struct sge_iq *, const struct rss_he
 int t4_hashfilter_ao_rpl(struct sge_iq *, const struct rss_header *, struct mbuf *);
 int t4_hashfilter_tcb_rpl(struct sge_iq *, const struct rss_header *, struct mbuf *);
 int t4_del_hashfilter_rpl(struct sge_iq *, const struct rss_header *, struct mbuf *);
-void free_hftid_tab(struct tid_info *);
+void free_hftid_hash(struct tid_info *);
 
 static inline struct wrqe *
 alloc_wrqe(int wr_len, struct sge_wrq *wrq)

Modified: head/sys/dev/cxgbe/offload.h
==============================================================================
--- head/sys/dev/cxgbe/offload.h	Wed Aug 15 02:31:10 2018	(r337829)
+++ head/sys/dev/cxgbe/offload.h	Wed Aug 15 03:03:01 2018	(r337830)
@@ -169,11 +169,13 @@ struct tid_info {
 	 */
 	struct mtx hftid_lock __aligned(CACHE_LINE_SIZE);
 	struct cv hftid_cv;
-	union {
-		void **hftid_tab;
-		void **tid_tab;
-	};
+	void **tid_tab;
 	u_int tids_in_use;
+
+	void *hftid_hash_4t;	/* LIST_HEAD(, filter_entry) *hftid_hash_4t; */
+	u_long hftid_4t_mask;
+	void *hftid_hash_tid;	/* LIST_HEAD(, filter_entry) *hftid_hash_tid; */
+	u_long hftid_tid_mask;
 
 	struct mtx etid_lock __aligned(CACHE_LINE_SIZE);
 	union etid_entry *etid_tab;

Modified: head/sys/dev/cxgbe/t4_filter.c
==============================================================================
--- head/sys/dev/cxgbe/t4_filter.c	Wed Aug 15 02:31:10 2018	(r337829)
+++ head/sys/dev/cxgbe/t4_filter.c	Wed Aug 15 03:03:01 2018	(r337830)
@@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$");
 
 #include <sys/param.h>
 #include <sys/eventhandler.h>
+#include <sys/fnv_hash.h>
 #include <sys/systm.h>
 #include <sys/kernel.h>
 #include <sys/module.h>
@@ -53,6 +54,9 @@ __FBSDID("$FreeBSD$");
 #include "t4_smt.h"
 
 struct filter_entry {
+	LIST_ENTRY(filter_entry) link_4t;
+	LIST_ENTRY(filter_entry) link_tid;
+
 	uint32_t valid:1;	/* filter allocated and valid */
 	uint32_t locked:1;	/* filter is administratively locked or busy */
 	uint32_t pending:1;	/* filter action is pending firmware reply */
@@ -78,17 +82,54 @@ separate_hpfilter_region(struct adapter *sc)
 	return (chip_id(sc) >= CHELSIO_T6);
 }
 
+static inline uint32_t
+hf_hashfn_4t(struct t4_filter_specification *fs)
+{
+	struct t4_filter_tuple *ft = &fs->val;
+	uint32_t hash;
+
+	if (fs->type) {
+		/* IPv6 */
+		hash = fnv_32_buf(&ft->sip[0], 16, FNV1_32_INIT);
+		hash = fnv_32_buf(&ft->dip[0], 16, hash);
+	} else {
+		hash = fnv_32_buf(&ft->sip[0], 4, FNV1_32_INIT);
+		hash = fnv_32_buf(&ft->dip[0], 4, hash);
+	}
+	hash = fnv_32_buf(&ft->sport, sizeof(ft->sport), hash);
+	hash = fnv_32_buf(&ft->dport, sizeof(ft->dport), hash);
+
+	return (hash);
+}
+
+static inline uint32_t
+hf_hashfn_tid(int tid)
+{
+
+	return (fnv_32_buf(&tid, sizeof(tid), FNV1_32_INIT));
+}
+
 static int
-alloc_hftid_tab(struct tid_info *t, int flags)
+alloc_hftid_hash(struct tid_info *t, int flags)
 {
+	int n;
 
 	MPASS(t->ntids > 0);
-	MPASS(t->hftid_tab == NULL);
+	MPASS(t->hftid_hash_4t == NULL);
+	MPASS(t->hftid_hash_tid == NULL);
 
-	t->hftid_tab = malloc(sizeof(*t->hftid_tab) * t->ntids, M_CXGBE,
-	    M_ZERO | flags);
-	if (t->hftid_tab == NULL)
+	n = max(t->ntids / 1024, 16);
+	t->hftid_hash_4t = hashinit_flags(n, M_CXGBE, &t->hftid_4t_mask, flags);
+	if (t->hftid_hash_4t == NULL)
 		return (ENOMEM);
+	t->hftid_hash_tid = hashinit_flags(n, M_CXGBE, &t->hftid_tid_mask,
+	    flags);
+	if (t->hftid_hash_tid == NULL) {
+		hashdestroy(t->hftid_hash_4t, M_CXGBE, t->hftid_4t_mask);
+		t->hftid_hash_4t = NULL;
+		return (ENOMEM);
+	}
+
 	mtx_init(&t->hftid_lock, "T4 hashfilters", 0, MTX_DEF);
 	cv_init(&t->hftid_cv, "t4hfcv");
 
@@ -96,22 +137,47 @@ alloc_hftid_tab(struct tid_info *t, int flags)
 }
 
 void
-free_hftid_tab(struct tid_info *t)
+free_hftid_hash(struct tid_info *t)
 {
+	struct filter_entry *f, *ftmp;
+	LIST_HEAD(, filter_entry) *head;
 	int i;
+#ifdef INVARIANTS
+	int n = 0;
+#endif
 
-	if (t->hftid_tab != NULL) {
-		MPASS(t->ntids > 0);
-		for (i = 0; t->tids_in_use > 0 && i < t->ntids; i++) {
-			if (t->hftid_tab[i] == NULL)
-				continue;
-			free(t->hftid_tab[i], M_CXGBE);
-			t->tids_in_use--;
+	if (t->tids_in_use > 0) {
+		/* Remove everything from the tid hash. */
+		head = t->hftid_hash_tid;
+		for (i = 0; i <= t->hftid_tid_mask; i++) {
+			LIST_FOREACH_SAFE(f, &head[i], link_tid, ftmp) {
+				LIST_REMOVE(f, link_tid);
+			}
 		}
-		free(t->hftid_tab, M_CXGBE);
-		t->hftid_tab = NULL;
+
+		/* Remove and then free each filter in the 4t hash. */
+		head = t->hftid_hash_4t;
+		for (i = 0; i <= t->hftid_4t_mask; i++) {
+			LIST_FOREACH_SAFE(f, &head[i], link_4t, ftmp) {
+#ifdef INVARIANTS
+				n += f->fs.type ? 2 : 1;
+#endif
+				LIST_REMOVE(f, link_4t);
+				free(f, M_CXGBE);
+			}
+		}
+		MPASS(t->tids_in_use == n);
+		t->tids_in_use = 0;
 	}
 
+	if (t->hftid_hash_4t) {
+		hashdestroy(t->hftid_hash_4t, M_CXGBE, t->hftid_4t_mask);
+		t->hftid_hash_4t = NULL;
+	}
+	if (t->hftid_hash_tid) {
+		hashdestroy(t->hftid_hash_tid, M_CXGBE, t->hftid_tid_mask);
+		t->hftid_hash_tid = NULL;
+	}
 	if (mtx_initialized(&t->hftid_lock)) {
 		mtx_destroy(&t->hftid_lock);
 		cv_destroy(&t->hftid_cv);
@@ -119,31 +185,146 @@ free_hftid_tab(struct tid_info *t)
 }
 
 static void
-insert_hftid(struct adapter *sc, int tid, void *ctx, int ntids)
+insert_hf(struct adapter *sc, struct filter_entry *f, uint32_t hash)
 {
 	struct tid_info *t = &sc->tids;
+	LIST_HEAD(, filter_entry) *head = t->hftid_hash_4t;
 
-	t->hftid_tab[tid] = ctx;
-	atomic_add_int(&t->tids_in_use, ntids);
+	MPASS(head != NULL);
+	if (hash == 0)
+		hash = hf_hashfn_4t(&f->fs);
+	LIST_INSERT_HEAD(&head[hash & t->hftid_4t_mask], f, link_4t);
+	atomic_add_int(&t->tids_in_use, f->fs.type ? 2 : 1);
 }
 
-static void *
+static void
+insert_hftid(struct adapter *sc, struct filter_entry *f)
+{
+	struct tid_info *t = &sc->tids;
+	LIST_HEAD(, filter_entry) *head = t->hftid_hash_tid;
+	uint32_t hash;
+
+	MPASS(f->tid >= t->tid_base);
+	MPASS(f->tid - t->tid_base < t->ntids);
+	mtx_assert(&t->hftid_lock, MA_OWNED);
+
+	hash = hf_hashfn_tid(f->tid);
+	LIST_INSERT_HEAD(&head[hash & t->hftid_tid_mask], f, link_tid);
+}
+
+static bool
+filter_eq(struct t4_filter_specification *fs1,
+    struct t4_filter_specification *fs2)
+{
+	int n;
+
+	MPASS(fs1->hash && fs2->hash);
+
+	if (fs1->type != fs2->type)
+		return (false);
+
+	n = fs1->type ? 16 : 4;
+	if (bcmp(&fs1->val.sip[0], &fs2->val.sip[0], n) ||
+	    bcmp(&fs1->val.dip[0], &fs2->val.dip[0], n) ||
+	    fs1->val.sport != fs2->val.sport ||
+	    fs1->val.dport != fs2->val.dport)
+		return (false);
+
+	/*
+	 * We know the masks are the same because all hashfilter masks have to
+	 * conform to the global tp->hash_filter_mask and the driver has
+	 * verified that already.
+	 */
+
+	if ((fs1->mask.pfvf_vld || fs1->mask.ovlan_vld) &&
+	    fs1->val.vnic != fs2->val.vnic)
+		return (false);
+	if (fs1->mask.vlan_vld && fs1->val.vlan != fs2->val.vlan)
+		return (false);
+	if (fs1->mask.macidx && fs1->val.macidx != fs2->val.macidx)
+		return (false);
+	if (fs1->mask.frag && fs1->val.frag != fs2->val.frag)
+		return (false);
+	if (fs1->mask.matchtype && fs1->val.matchtype != fs2->val.matchtype)
+		return (false);
+	if (fs1->mask.iport && fs1->val.iport != fs2->val.iport)
+		return (false);
+	if (fs1->mask.fcoe && fs1->val.fcoe != fs2->val.fcoe)
+		return (false);
+	if (fs1->mask.proto && fs1->val.proto != fs2->val.proto)
+		return (false);
+	if (fs1->mask.tos && fs1->val.tos != fs2->val.tos)
+		return (false);
+	if (fs1->mask.ethtype && fs1->val.ethtype != fs2->val.ethtype)
+		return (false);
+
+	return (true);
+}
+
+static struct filter_entry *
+lookup_hf(struct adapter *sc, struct t4_filter_specification *fs, uint32_t hash)
+{
+	struct tid_info *t = &sc->tids;
+	LIST_HEAD(, filter_entry) *head = t->hftid_hash_4t;
+	struct filter_entry *f;
+
+	mtx_assert(&t->hftid_lock, MA_OWNED);
+	MPASS(head != NULL);
+
+	if (hash == 0)
+		hash = hf_hashfn_4t(fs);
+
+	LIST_FOREACH(f, &head[hash & t->hftid_4t_mask], link_4t) {
+		if (filter_eq(&f->fs, fs))
+			return (f);
+	}
+
+	return (NULL);
+}
+
+static struct filter_entry *
 lookup_hftid(struct adapter *sc, int tid)
 {
 	struct tid_info *t = &sc->tids;
+	LIST_HEAD(, filter_entry) *head = t->hftid_hash_tid;
+	struct filter_entry *f;
+	uint32_t hash;
 
-	return (t->hftid_tab[tid]);
+	mtx_assert(&t->hftid_lock, MA_OWNED);
+	MPASS(head != NULL);
+
+	hash = hf_hashfn_tid(tid);
+	LIST_FOREACH(f, &head[hash & t->hftid_tid_mask], link_tid) {
+		if (f->tid == tid)
+			return (f);
+	}
+
+	return (NULL);
 }
 
 static void
-remove_hftid(struct adapter *sc, int tid, int ntids)
+remove_hf(struct adapter *sc, struct filter_entry *f)
 {
 	struct tid_info *t = &sc->tids;
 
-	t->hftid_tab[tid] = NULL;
-	atomic_subtract_int(&t->tids_in_use, ntids);
+	mtx_assert(&t->hftid_lock, MA_OWNED);
+
+	LIST_REMOVE(f, link_4t);
+	atomic_subtract_int(&t->tids_in_use, f->fs.type ? 2 : 1);
 }
 
+static void
+remove_hftid(struct adapter *sc, struct filter_entry *f)
+{
+#ifdef INVARIANTS
+	struct tid_info *t = &sc->tids;
+
+	mtx_assert(&t->hftid_lock, MA_OWNED);
+#endif
+
+	LIST_REMOVE(f, link_tid);
+}
+
 static uint32_t
 mode_to_fconf(uint32_t mode)
 {
@@ -613,6 +794,25 @@ hashfilter_ntuple(struct adapter *sc, const struct t4_
 	return (0);
 }
 
+static bool
+is_4tuple_specified(struct t4_filter_specification *fs)
+{
+	int i;
+	const int n = fs->type ? 16 : 4;
+
+	if (fs->mask.sport != 0xffff || fs->mask.dport != 0xffff)
+		return (false);
+
+	for (i = 0; i < n; i++) {
+		if (fs->mask.sip[i] != 0xff)
+			return (false);
+		if (fs->mask.dip[i] != 0xff)
+			return (false);
+	}
+
+	return (true);
+}
+
 int
 set_filter(struct adapter *sc, struct t4_filter *t)
 {
@@ -635,6 +835,8 @@ set_filter(struct adapter *sc, struct t4_filter *t)
 		/* T5 can't count hashfilter hits. */
 		if (is_t5(sc) && t->fs.hitcnts)
 			return (EINVAL);
+		if (!is_4tuple_specified(&t->fs))
+			return (EINVAL);
 		rc = hashfilter_ntuple(sc, &t->fs, &ftuple);
 		if (rc != 0)
 			return (rc);
@@ -689,8 +891,8 @@ set_filter(struct adapter *sc, struct t4_filter *t)
 		return (rc);
 	}
 	if (t->fs.hash) {
-		if (__predict_false(ti->hftid_tab == NULL)) {
-			rc = alloc_hftid_tab(&sc->tids, M_NOWAIT);
+		if (__predict_false(ti->hftid_hash_4t == NULL)) {
+			rc = alloc_hftid_hash(&sc->tids, HASH_NOWAIT);
 			if (rc != 0)
 				goto done;
 		}
@@ -864,7 +1066,7 @@ del_filter(struct adapter *sc, struct t4_filter *t)
 	 * for are initialized.
 	 */
 	if (t->fs.hash) {
-		if (sc->tids.hftid_tab != NULL)
+		if (sc->tids.hftid_hash_4t != NULL)
 			return (del_hashfilter(sc, t));
 	} else if (separate_hpfilter_region(sc) && t->fs.prio) {
 		if (sc->tids.hpftid_tab != NULL)
@@ -1018,18 +1220,9 @@ t4_hashfilter_ao_rpl(struct sge_iq *iq, const struct r
 	KASSERT(f->tid == -1, ("%s: hashfilter[%p] has tid %d already.",
 	    __func__, f, f->tid));
 	if (status == CPL_ERR_NONE) {
-		struct filter_entry *f2;
-
 		f->tid = GET_TID(cpl);
-		MPASS(f->tid < sc->tids.ntids);
-		if (__predict_false((f2 = lookup_hftid(sc, f->tid)) != NULL)) {
-			/* XXX: avoid hash collisions in the first place. */
-			MPASS(f2->tid == f->tid);
-			remove_hftid(sc, f2->tid, f2->fs.type ? 2 : 1);
-			free_filter_resources(f2);
-			free(f2, M_CXGBE);
-		}
-		insert_hftid(sc, f->tid, f, f->fs.type ? 2 : 1);
+		MPASS(lookup_hftid(sc, f->tid) == NULL);
+		insert_hftid(sc, f);
 		/*
 		 * Leave the filter pending until it is fully set up, which will
 		 * be indicated by the reply to the last TCB update.  No need to
@@ -1046,6 +1239,7 @@ t4_hashfilter_ao_rpl(struct sge_iq *iq, const struct r
 		if (act_open_has_tid(status))
 			release_tid(sc, GET_TID(cpl), &sc->sge.ctrlq[0]);
 		free_filter_resources(f);
+		remove_hf(sc, f);
 		if (f->locked == 0)
 			free(f, M_CXGBE);
 	}
@@ -1080,7 +1274,8 @@ t4_hashfilter_tcb_rpl(struct sge_iq *iq, const struct 
 		f->tid = EIO;
 		f->valid = 0;
 		free_filter_resources(f);
-		remove_hftid(sc, tid, f->fs.type ? 2 : 1);
+		remove_hftid(sc, f);
+		remove_hf(sc, f);
 		release_tid(sc, tid, &sc->sge.ctrlq[0]);
 		if (f->locked == 0)
 			free(f, M_CXGBE);
@@ -1111,7 +1306,8 @@ t4_del_hashfilter_rpl(struct sge_iq *iq, const struct 
 	if (cpl->status == 0) {
 		f->valid = 0;
 		free_filter_resources(f);
-		remove_hftid(sc, tid, f->fs.type ? 2 : 1);
+		remove_hftid(sc, f);
+		remove_hf(sc, f);
 		release_tid(sc, tid, &sc->sge.ctrlq[0]);
 		if (f->locked == 0)
 			free(f, M_CXGBE);
@@ -1181,26 +1377,30 @@ done:
 static int
 get_hashfilter(struct adapter *sc, struct t4_filter *t)
 {
-	int i, nfilters = sc->tids.ntids;
+	struct tid_info *ti = &sc->tids;
+	int tid;
 	struct filter_entry *f;
+	const int inv_tid = ti->ntids + ti->tid_base;
 
 	MPASS(t->fs.hash);
 
-	if (sc->tids.tids_in_use == 0 || sc->tids.hftid_tab == NULL ||
-	    t->idx >= nfilters) {
+	if (ti->tids_in_use == 0 || ti->hftid_hash_tid == NULL ||
+	    t->idx >= inv_tid) {
 		t->idx = 0xffffffff;
 		return (0);
 	}
+	if (t->idx < ti->tid_base)
+		t->idx = ti->tid_base;
 
-	mtx_lock(&sc->tids.hftid_lock);
-	for (i = t->idx; i < nfilters; i++) {
-		f = lookup_hftid(sc, i);
+	mtx_lock(&ti->hftid_lock);
+	for (tid = t->idx; tid < inv_tid; tid++) {
+		f = lookup_hftid(sc, tid);
 		if (f != NULL && f->valid) {
-			t->idx = i;
+			t->idx = tid;
 			t->l2tidx = f->l2te ? f->l2te->idx : 0;
 			t->smtidx = f->smt ? f->smt->idx : 0;
 			if (f->fs.hitcnts)
-				t->hits = get_filter_hits(sc, t->idx);
+				t->hits = get_filter_hits(sc, tid);
 			else
 				t->hits = UINT64_MAX;
 			t->fs = f->fs;
@@ -1210,7 +1410,7 @@ get_hashfilter(struct adapter *sc, struct t4_filter *t
 	}
 	t->idx = 0xffffffff;
 done:
-	mtx_unlock(&sc->tids.hftid_lock);
+	mtx_unlock(&ti->hftid_lock);
 	return (0);
 }
 
@@ -1335,20 +1535,21 @@ set_hashfilter(struct adapter *sc, struct t4_filter *t
 	struct wrq_cookie cookie;
 	struct filter_entry *f;
 	int rc, atid = -1;
+	uint32_t hash;
 
 	MPASS(t->fs.hash);
 	/* Already validated against fconf, iconf */
 	MPASS((t->fs.val.pfvf_vld & t->fs.val.ovlan_vld) == 0);
 	MPASS((t->fs.mask.pfvf_vld & t->fs.mask.ovlan_vld) == 0);
 
+	hash = hf_hashfn_4t(&t->fs);
+
 	mtx_lock(&sc->tids.hftid_lock);
+	if (lookup_hf(sc, &t->fs, hash) != NULL) {
+		rc = EEXIST;
+		goto done;
+	}
 
-	/*
-	 * XXX: Check for hash collisions and insert in the hash based lookup
-	 * table so that in-flight hashfilters are also considered when checking
-	 * for collisions.
-	 */
-
 	f = malloc(sizeof(*f), M_CXGBE, M_ZERO | M_NOWAIT);
 	if (__predict_false(f == NULL)) {
 		if (l2te)
@@ -1394,6 +1595,7 @@ set_hashfilter(struct adapter *sc, struct t4_filter *t
 	f->locked = 1; /* ithread mustn't free f if ioctl is still around. */
 	f->pending = 1;
 	f->tid = -1;
+	insert_hf(sc, f, hash);
 	commit_wrq_wr(&sc->sge.ctrlq[0], wr, &cookie);
 
 	for (;;) {
@@ -1404,6 +1606,7 @@ set_hashfilter(struct adapter *sc, struct t4_filter *t
 				f->locked = 0;
 				t->idx = f->tid;
 			} else {
+				remove_hf(sc, f);
 				rc = f->tid;
 				free(f, M_CXGBE);
 			}
@@ -1544,19 +1747,21 @@ mk_del_hashfilter_wr(int tid, struct work_request_hdr 
 static int
 del_hashfilter(struct adapter *sc, struct t4_filter *t)
 {
+	struct tid_info *ti = &sc->tids;
 	void *wr;
 	struct filter_entry *f;
 	struct wrq_cookie cookie;
 	int rc;
 	const int wrlen = del_hashfilter_wrlen();
+	const int inv_tid = ti->ntids + ti->tid_base;
 
-	MPASS(sc->tids.hftid_tab != NULL);
+	MPASS(sc->tids.hftid_hash_4t != NULL);
 	MPASS(sc->tids.ntids > 0);
 
-	if (t->idx >= sc->tids.ntids)
+	if (t->idx < sc->tids.tid_base || t->idx >= inv_tid)
 		return (EINVAL);
 
-	mtx_lock(&sc->tids.hftid_lock);
+	mtx_lock(&ti->hftid_lock);
 	f = lookup_hftid(sc, t->idx);
 	if (f == NULL || f->valid == 0) {
 		rc = EINVAL;
@@ -1595,14 +1800,14 @@ del_hashfilter(struct adapter *sc, struct t4_filter *t
 			}
 			break;
 		}
-		if (cv_wait_sig(&sc->tids.hftid_cv, &sc->tids.hftid_lock) != 0) {
+		if (cv_wait_sig(&ti->hftid_cv, &ti->hftid_lock) != 0) {
 			f->locked = 0;
 			rc = EINPROGRESS;
 			break;
 		}
 	}
 done:
-	mtx_unlock(&sc->tids.hftid_lock);
+	mtx_unlock(&ti->hftid_lock);
 	return (rc);
 }
 

Modified: head/sys/dev/cxgbe/t4_main.c
==============================================================================
--- head/sys/dev/cxgbe/t4_main.c	Wed Aug 15 02:31:10 2018	(r337829)
+++ head/sys/dev/cxgbe/t4_main.c	Wed Aug 15 03:03:01 2018	(r337830)
@@ -1405,8 +1405,7 @@ t4_detach_common(device_t dev)
 	free(sc->sge.eqmap, M_CXGBE);
 	free(sc->tids.ftid_tab, M_CXGBE);
 	free(sc->tids.hpftid_tab, M_CXGBE);
-	if (sc->tids.hftid_tab)
-		free_hftid_tab(&sc->tids);
+	free_hftid_hash(&sc->tids);
 	free(sc->tids.atid_tab, M_CXGBE);
 	free(sc->tids.tid_tab, M_CXGBE);
 	free(sc->tt.tls_rx_ports, M_CXGBE);



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