Date: Thu, 31 May 2018 21:56:57 +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: r334452 - head/sys/dev/cxgbe Message-ID: <201805312156.w4VLuvBF050594@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
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++; }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201805312156.w4VLuvBF050594>