svn commit: r334452 - head/sys/dev/cxgbe

Navdeep Parhar np at FreeBSD.org
Thu May 31 21:56:58 UTC 2018


Author: np
Date: Thu May 31 21:56:57 2018
New Revision: 334452
URL: https://svnweb.freebsd.org/changeset/base/334452

Log:
  cxgbe(4): Add support for SMAC-rewriting filters.
  
  Submitted by:	Krishnamraju Eraparaju @ Chelsio
  Sponsored by:	Chelsio Communications

Modified:
  head/sys/dev/cxgbe/t4_filter.c

Modified: head/sys/dev/cxgbe/t4_filter.c
==============================================================================
--- head/sys/dev/cxgbe/t4_filter.c	Thu May 31 21:54:55 2018	(r334451)
+++ head/sys/dev/cxgbe/t4_filter.c	Thu May 31 21:56:57 2018	(r334452)
@@ -50,14 +50,15 @@ __FBSDID("$FreeBSD$");
 #include "common/t4_regs_values.h"
 #include "common/t4_tcb.h"
 #include "t4_l2t.h"
+#include "t4_smt.h"
 
 struct filter_entry {
 	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 */
-	uint32_t smtidx:8;	/* Source MAC Table index for smac */
 	int tid;		/* tid of the filter TCB */
 	struct l2t_entry *l2te;	/* L2 table entry for DMAC rewrite */
+	struct smt_entry *smt;	/* SMT entry for SMAC rewrite */
 
 	struct t4_filter_specification fs;
 };
@@ -65,7 +66,7 @@ struct filter_entry {
 static void free_filter_resources(struct filter_entry *);
 static int get_hashfilter(struct adapter *, struct t4_filter *);
 static int set_hashfilter(struct adapter *, struct t4_filter *, uint64_t,
-    struct l2t_entry *);
+    struct l2t_entry *, struct smt_entry *);
 static int del_hashfilter(struct adapter *, struct t4_filter *);
 static int configure_hashfilter_tcb(struct adapter *, struct filter_entry *);
 
@@ -321,7 +322,7 @@ get_filter(struct adapter *sc, struct t4_filter *t)
 			MPASS(f->tid == sc->tids.ftid_base + i);
 			t->idx = i;
 			t->l2tidx = f->l2te ? f->l2te->idx : 0;
-			t->smtidx = f->smtidx;
+			t->smtidx = f->smt ? f->smt->idx : 0;
 			if (f->fs.hitcnts)
 				t->hits = get_filter_hits(sc, f->tid);
 			else
@@ -338,7 +339,8 @@ done:
 }
 
 static int
-set_tcamfilter(struct adapter *sc, struct t4_filter *t, struct l2t_entry *l2te)
+set_tcamfilter(struct adapter *sc, struct t4_filter *t, struct l2t_entry *l2te,
+    struct smt_entry *smt)
 {
 	struct filter_entry *f;
 	struct fw_filter2_wr *fwr;
@@ -383,6 +385,8 @@ set_tcamfilter(struct adapter *sc, struct t4_filter *t
 	if (rc != 0) {
 		if (l2te)
 			t4_l2t_release(l2te);
+		if (smt)
+			t4_smt_release(smt);
 		return (rc);
 	}
 
@@ -393,6 +397,7 @@ set_tcamfilter(struct adapter *sc, struct t4_filter *t
 	f->tid = sc->tids.ftid_base + t->idx;
 	f->fs = t->fs;
 	f->l2te = l2te;
+	f->smt = smt;
 
 	if (t->fs.val.pfvf_vld || t->fs.val.ovlan_vld)
 		vnic_vld = 1;
@@ -468,10 +473,8 @@ set_tcamfilter(struct adapter *sc, struct t4_filter *t
 	fwr->lpm = htobe16(f->fs.mask.dport);
 	fwr->fp = htobe16(f->fs.val.sport);
 	fwr->fpm = htobe16(f->fs.mask.sport);
-	if (f->fs.newsmac) {
-		/* XXX: need to use SMT idx instead */
-		bcopy(f->fs.smac, fwr->sma, sizeof (fwr->sma));
-	}
+	/* sma = 0 tells the fw to use SMAC_SEL for source MAC address */
+	bzero(fwr->sma, sizeof (fwr->sma));
 	if (sc->params.filter2_wr_support) {
 		fwr->filter_type_swapmac =
 		    V_FW_FILTER2_WR_SWAPMAC(f->fs.swapmac);
@@ -585,6 +588,7 @@ set_filter(struct adapter *sc, struct t4_filter *t)
 {
 	struct tid_info *ti = &sc->tids;
 	struct l2t_entry *l2te;
+	struct smt_entry *smt;
 	uint64_t ftuple;
 	int rc;
 
@@ -690,22 +694,36 @@ done:
 		l2te = t4_l2t_alloc_switching(sc->l2t);
 		if (__predict_false(l2te == NULL))
 			return (EAGAIN);
-		if (t4_l2t_set_switching(sc, l2te, t->fs.vlan, t->fs.eport,
-		    t->fs.dmac)) {
+		rc = t4_l2t_set_switching(sc, l2te, t->fs.vlan, t->fs.eport,
+		    t->fs.dmac);
+		if (rc) {
 			t4_l2t_release(l2te);
 			return (ENOMEM);
 		}
 	}
 
+	smt = NULL;
 	if (t->fs.newsmac) {
-		/* XXX: alloc SMT */
-		return (ENOTSUP);
+		/* This filter needs an SMT entry; allocate one. */
+		smt = t4_smt_alloc_switching(sc->smt, t->fs.smac);
+		if (__predict_false(smt == NULL)) {
+			if (l2te != NULL)
+				t4_l2t_release(l2te);
+			return (EAGAIN);
+		}
+		rc = t4_smt_set_switching(sc, smt, 0x0, t->fs.smac);
+		if (rc) {
+			t4_smt_release(smt);
+			if (l2te != NULL)
+				t4_l2t_release(l2te);
+			return (rc);
+		}
 	}
 
 	if (t->fs.hash)
-		return (set_hashfilter(sc, t, ftuple, l2te));
+		return (set_hashfilter(sc, t, ftuple, l2te, smt));
 	else
-		return (set_tcamfilter(sc, t, l2te));
+		return (set_tcamfilter(sc, t, l2te, smt));
 
 }
 
@@ -799,8 +817,47 @@ free_filter_resources(struct filter_entry *f)
 		t4_l2t_release(f->l2te);
 		f->l2te = NULL;
 	}
+	if (f->smt) {
+		t4_smt_release(f->smt);
+		f->smt = NULL;
+	}
 }
 
+static int
+set_tcb_field(struct adapter *sc, u_int tid, uint16_t word, uint64_t mask,
+    uint64_t val, int no_reply)
+{
+	struct wrq_cookie cookie;
+	struct cpl_set_tcb_field *req;
+
+	req = start_wrq_wr(&sc->sge.mgmtq, howmany(sizeof(*req), 16), &cookie);
+	if (req == NULL)
+		return (ENOMEM);
+	bzero(req, sizeof(*req));
+	INIT_TP_WR_MIT_CPL(req, CPL_SET_TCB_FIELD, tid);
+	if (no_reply == 0) {
+		req->reply_ctrl = htobe16(V_QUEUENO(sc->sge.fwq.abs_id) |
+		    V_NO_REPLY(0));
+	} else
+		req->reply_ctrl = htobe16(V_NO_REPLY(1));
+	req->word_cookie = htobe16(V_WORD(word) | V_COOKIE(CPL_COOKIE_HASHFILTER));
+	req->mask = htobe64(mask);
+	req->val = htobe64(val);
+	commit_wrq_wr(&sc->sge.mgmtq, req, &cookie);
+
+	return (0);
+}
+
+/* Set one of the t_flags bits in the TCB. */
+static inline int
+set_tcb_tflag(struct adapter *sc, int tid, u_int bit_pos, u_int val,
+    u_int no_reply)
+{
+
+	return (set_tcb_field(sc, tid,  W_TCB_T_FLAGS, 1ULL << bit_pos,
+	    (uint64_t)val << bit_pos, no_reply));
+}
+
 int
 t4_filter_rpl(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m)
 {
@@ -826,7 +883,14 @@ t4_filter_rpl(struct sge_iq *iq, const struct rss_head
 	case FW_FILTER_WR_FLT_ADDED:
 		/* set-filter succeeded */
 		f->valid = 1;
-		f->smtidx = (be64toh(rpl->oldval) >> 24) & 0xff;
+		if (f->fs.newsmac) {
+			MPASS(f->smt != NULL);
+			set_tcb_tflag(sc, f->tid, S_TF_CCTRL_CWR, 1, 1);
+			set_tcb_field(sc, f->tid, W_TCB_SMAC_SEL,
+			    V_TCB_SMAC_SEL(M_TCB_SMAC_SEL),
+			    V_TCB_SMAC_SEL(f->smt->idx), 1);
+			/* XXX: wait for reply to TCB update before !pending */
+		}
 		break;
 	case FW_FILTER_WR_FLT_DELETED:
 		/* del-filter succeeded */
@@ -995,7 +1059,7 @@ get_hashfilter(struct adapter *sc, struct t4_filter *t
 		if (f != NULL && f->valid) {
 			t->idx = i;
 			t->l2tidx = f->l2te ? f->l2te->idx : 0;
-			t->smtidx = f->smtidx;
+			t->smtidx = f->smt ? f->smt->idx : 0;
 			if (f->fs.hitcnts)
 				t->hits = get_filter_hits(sc, t->idx);
 			else
@@ -1126,7 +1190,7 @@ act_open_cpl_len16(struct adapter *sc, int isipv6)
 
 static int
 set_hashfilter(struct adapter *sc, struct t4_filter *t, uint64_t ftuple,
-    struct l2t_entry *l2te)
+    struct l2t_entry *l2te, struct smt_entry *smt)
 {
 	void *wr;
 	struct wrq_cookie cookie;
@@ -1150,16 +1214,21 @@ set_hashfilter(struct adapter *sc, struct t4_filter *t
 	if (__predict_false(f == NULL)) {
 		if (l2te)
 			t4_l2t_release(l2te);
+		if (smt)
+			t4_smt_release(smt);
 		rc = ENOMEM;
 		goto done;
 	}
 	f->fs = t->fs;
 	f->l2te = l2te;
+	f->smt = smt;
 
 	atid = alloc_atid(sc, f);
 	if (__predict_false(atid) == -1) {
 		if (l2te)
 			t4_l2t_release(l2te);
+		if (smt)
+			t4_smt_release(smt);
 		free(f, M_CXGBE);
 		rc = EAGAIN;
 		goto done;
@@ -1172,6 +1241,8 @@ set_hashfilter(struct adapter *sc, struct t4_filter *t
 		free_atid(sc, atid);
 		if (l2te)
 			t4_l2t_release(l2te);
+		if (smt)
+			t4_smt_release(smt);
 		free(f, M_CXGBE);
 		rc = ENOMEM;
 		goto done;
@@ -1396,41 +1467,6 @@ done:
 	return (rc);
 }
 
-static int
-set_tcb_field(struct adapter *sc, u_int tid, uint16_t word, uint64_t mask,
-    uint64_t val, int no_reply)
-{
-	struct wrq_cookie cookie;
-	struct cpl_set_tcb_field *req;
-
-	req = start_wrq_wr(&sc->sge.mgmtq, howmany(sizeof(*req), 16), &cookie);
-	if (req == NULL)
-		return (ENOMEM);
-	bzero(req, sizeof(*req));
-	INIT_TP_WR_MIT_CPL(req, CPL_SET_TCB_FIELD, tid);
-	if (no_reply == 0) {
-		req->reply_ctrl = htobe16(V_QUEUENO(sc->sge.fwq.abs_id) |
-		    V_NO_REPLY(0));
-	} else
-		req->reply_ctrl = htobe16(V_NO_REPLY(1));
-	req->word_cookie = htobe16(V_WORD(word) | V_COOKIE(CPL_COOKIE_HASHFILTER));
-	req->mask = htobe64(mask);
-	req->val = htobe64(val);
-	commit_wrq_wr(&sc->sge.mgmtq, req, &cookie);
-
-	return (0);
-}
-
-/* Set one of the t_flags bits in the TCB. */
-static inline int
-set_tcb_tflag(struct adapter *sc, int tid, u_int bit_pos, u_int val,
-    u_int no_reply)
-{
-
-	return (set_tcb_field(sc, tid,  W_TCB_T_FLAGS, 1ULL << bit_pos,
-	    (uint64_t)val << bit_pos, no_reply));
-}
-
 #define WORD_MASK       0xffffffff
 static void
 set_nat_params(struct adapter *sc, struct filter_entry *f, const bool dip,
@@ -1525,9 +1561,10 @@ configure_hashfilter_tcb(struct adapter *sc, struct fi
 	}
 
 	if (f->fs.newsmac) {
+		MPASS(f->smt != NULL);
 		set_tcb_tflag(sc, f->tid, S_TF_CCTRL_CWR, 1, 1);
 		set_tcb_field(sc, f->tid, W_TCB_SMAC_SEL,
-		    V_TCB_SMAC_SEL(M_TCB_SMAC_SEL), V_TCB_SMAC_SEL(f->smtidx),
+		    V_TCB_SMAC_SEL(M_TCB_SMAC_SEL), V_TCB_SMAC_SEL(f->smt->idx),
 		    1);
 		updated++;
 	}


More information about the svn-src-all mailing list