X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fcxgbe%2Fcxgbe_filter.c;h=5a7efe7a733e880a12533af647eaa2d3369f87d3;hb=aa55a55b207fdb932e1a883b83d8aee6c3044063;hp=c5f5e41e366bd336afab608aa3e48ea133e9951e;hpb=993541b2fa4ffe4b532e22fae58fd9aa6638e441;p=dpdk.git diff --git a/drivers/net/cxgbe/cxgbe_filter.c b/drivers/net/cxgbe/cxgbe_filter.c index c5f5e41e36..5a7efe7a73 100644 --- a/drivers/net/cxgbe/cxgbe_filter.c +++ b/drivers/net/cxgbe/cxgbe_filter.c @@ -8,36 +8,41 @@ #include "base/t4_tcb.h" #include "base/t4_regs.h" #include "cxgbe_filter.h" +#include "mps_tcam.h" #include "clip_tbl.h" #include "l2t.h" #include "smt.h" +#include "cxgbe_pfvf.h" /** * Initialize Hash Filters */ int cxgbe_init_hash_filter(struct adapter *adap) { - unsigned int n_user_filters; - unsigned int user_filter_perc; + unsigned int user_filter_perc, n_user_filters; + u32 param, val; int ret; - u32 params[7], val[7]; -#define FW_PARAM_DEV(param) \ - (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_DEV) | \ - V_FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DEV_##param)) + if (CHELSIO_CHIP_VERSION(adap->params.chip) > CHELSIO_T5) { + val = t4_read_reg(adap, A_LE_DB_RSP_CODE_0); + if (G_TCAM_ACTV_HIT(val) != 4) { + adap->params.hash_filter = 0; + return 0; + } -#define FW_PARAM_PFVF(param) \ - (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_PFVF) | \ - V_FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_PFVF_##param) | \ - V_FW_PARAMS_PARAM_Y(0) | \ - V_FW_PARAMS_PARAM_Z(0)) + val = t4_read_reg(adap, A_LE_DB_RSP_CODE_1); + if (G_HASH_ACTV_HIT(val) != 4) { + adap->params.hash_filter = 0; + return 0; + } + } - params[0] = FW_PARAM_DEV(NTID); + param = CXGBE_FW_PARAM_DEV(NTID); ret = t4_query_params(adap, adap->mbox, adap->pf, 0, 1, - params, val); + ¶m, &val); if (ret < 0) return ret; - adap->tids.ntids = val[0]; + adap->tids.ntids = val; adap->tids.natids = min(adap->tids.ntids / 2, MAX_ATIDS); user_filter_perc = 100; @@ -62,7 +67,8 @@ int cxgbe_validate_filter(struct adapter *adapter, /* * Check for unconfigured fields being used. */ - fconf = adapter->params.tp.vlan_pri_map; + fconf = fs->cap ? adapter->params.tp.filter_mask : + adapter->params.tp.vlan_pri_map; iconf = adapter->params.tp.ingress_config; @@ -139,7 +145,7 @@ static unsigned int get_filter_steerq(struct rte_eth_dev *dev, * then assume it is an absolute qid. */ if (fs->iq < pi->n_rx_qsets) - iq = adapter->sge.ethrxq[pi->first_qset + + iq = adapter->sge.ethrxq[pi->first_rxqset + fs->iq].rspq.abs_id; else iq = fs->iq; @@ -283,6 +289,33 @@ int cxgbe_alloc_ftid(struct adapter *adap, u8 nentries) return pos < size ? pos : -1; } +/** + * Clear a filter and release any of its resources that we own. This also + * clears the filter's "pending" status. + */ +static void clear_filter(struct filter_entry *f) +{ + struct port_info *pi = ethdev2pinfo(f->dev); + + if (f->clipt) + cxgbe_clip_release(f->dev, f->clipt); + + if (f->l2t) + cxgbe_l2t_release(f->l2t); + + if (f->fs.mask.macidx) + cxgbe_mpstcam_remove(pi, f->fs.val.macidx); + + if (f->smt) + cxgbe_smt_release(f->smt); + + /* The zeroing of the filter rule below clears the filter valid, + * pending, locked flags etc. so it's all we need for + * this operation. + */ + memset(f, 0, sizeof(*f)); +} + /** * Construct hash filter ntuple. */ @@ -582,13 +615,26 @@ static int cxgbe_set_hash_filter(struct rte_eth_dev *dev, f = t4_os_alloc(sizeof(*f)); if (!f) - goto out_err; + return -ENOMEM; f->fs = *fs; f->ctx = ctx; f->dev = dev; f->fs.iq = iq; + /* Allocate MPS TCAM entry to match Destination MAC. */ + if (f->fs.mask.macidx) { + int idx; + + idx = cxgbe_mpstcam_alloc(pi, f->fs.val.dmac, f->fs.mask.dmac); + if (idx <= 0) { + ret = -ENOMEM; + goto out_err; + } + + f->fs.val.macidx = idx; + } + /* * If the new filter requires loopback Destination MAC and/or VLAN * rewriting then we need to allocate a Layer 2 Table (L2T) entry for @@ -630,7 +676,7 @@ static int cxgbe_set_hash_filter(struct rte_eth_dev *dev, mbuf = rte_pktmbuf_alloc(ctrlq->mb_pool); if (!mbuf) { ret = -ENOMEM; - goto free_clip; + goto free_atid; } mbuf->data_len = size; @@ -660,33 +706,15 @@ static int cxgbe_set_hash_filter(struct rte_eth_dev *dev, t4_mgmt_tx(ctrlq, mbuf); return 0; -free_clip: - cxgbe_clip_release(f->dev, f->clipt); free_atid: cxgbe_free_atid(t, atid); out_err: + clear_filter(f); t4_os_free(f); return ret; } -/** - * Clear a filter and release any of its resources that we own. This also - * clears the filter's "pending" status. - */ -static void clear_filter(struct filter_entry *f) -{ - if (f->clipt) - cxgbe_clip_release(f->dev, f->clipt); - - /* - * The zeroing of the filter rule below clears the filter valid, - * pending, locked flags etc. so it's all we need for - * this operation. - */ - memset(f, 0, sizeof(*f)); -} - /** * t4_mk_filtdelwr - create a delete filter WR * @adap: adapter context @@ -756,34 +784,6 @@ static int set_filter_wr(struct rte_eth_dev *dev, unsigned int fidx) unsigned int port_id = ethdev2pinfo(dev)->port_id; int ret; - /* - * If the new filter requires loopback Destination MAC and/or VLAN - * rewriting then we need to allocate a Layer 2 Table (L2T) entry for - * the filter. - */ - if (f->fs.newvlan || f->fs.newdmac) { - /* allocate L2T entry for new filter */ - f->l2t = cxgbe_l2t_alloc_switching(f->dev, f->fs.vlan, - f->fs.eport, f->fs.dmac); - - if (!f->l2t) - return -ENOMEM; - } - - /* If the new filter requires Source MAC rewriting then we need to - * allocate a SMT entry for the filter - */ - if (f->fs.newsmac) { - f->smt = cxgbe_smt_alloc_switching(f->dev, f->fs.smac); - if (!f->smt) { - if (f->l2t) { - cxgbe_l2t_release(f->l2t); - f->l2t = NULL; - } - return -ENOMEM; - } - } - ctrlq = &adapter->sge.ctrlq[port_id]; mbuf = rte_pktmbuf_alloc(ctrlq->mb_pool); if (!mbuf) { @@ -1069,16 +1069,6 @@ int cxgbe_set_filter(struct rte_eth_dev *dev, unsigned int filter_id, return ret; } - /* - * Allocate a clip table entry only if we have non-zero IPv6 address - */ - if (chip_ver > CHELSIO_T5 && fs->type && - memcmp(fs->val.lip, bitoff, sizeof(bitoff))) { - f->clipt = cxgbe_clip_alloc(dev, (u32 *)&fs->val.lip); - if (!f->clipt) - goto free_tid; - } - /* * Convert the filter specification into our internal format. * We copy the PF/VF specification into the Outer VLAN field @@ -1089,6 +1079,53 @@ int cxgbe_set_filter(struct rte_eth_dev *dev, unsigned int filter_id, f->fs.iq = iq; f->dev = dev; + /* Allocate MPS TCAM entry to match Destination MAC. */ + if (f->fs.mask.macidx) { + int idx; + + idx = cxgbe_mpstcam_alloc(pi, f->fs.val.dmac, f->fs.mask.dmac); + if (idx <= 0) { + ret = -ENOMEM; + goto free_tid; + } + + f->fs.val.macidx = idx; + } + + /* Allocate a clip table entry only if we have non-zero IPv6 address. */ + if (chip_ver > CHELSIO_T5 && f->fs.type && + memcmp(f->fs.val.lip, bitoff, sizeof(bitoff))) { + f->clipt = cxgbe_clip_alloc(dev, (u32 *)&f->fs.val.lip); + if (!f->clipt) { + ret = -ENOMEM; + goto free_tid; + } + } + + /* If the new filter requires loopback Destination MAC and/or VLAN + * rewriting then we need to allocate a Layer 2 Table (L2T) entry for + * the filter. + */ + if (f->fs.newvlan || f->fs.newdmac) { + f->l2t = cxgbe_l2t_alloc_switching(f->dev, f->fs.vlan, + f->fs.eport, f->fs.dmac); + if (!f->l2t) { + ret = -ENOMEM; + goto free_tid; + } + } + + /* If the new filter requires Source MAC rewriting then we need to + * allocate a SMT entry for the filter + */ + if (f->fs.newsmac) { + f->smt = cxgbe_smt_alloc_switching(f->dev, f->fs.smac); + if (!f->smt) { + ret = -ENOMEM; + goto free_tid; + } + } + iconf = adapter->params.tp.ingress_config; /* Either PFVF or OVLAN can be active, but not both @@ -1191,6 +1228,7 @@ void cxgbe_hash_filter_rpl(struct adapter *adap, } cxgbe_free_atid(t, ftid); + clear_filter(f); t4_os_free(f); } @@ -1415,13 +1453,8 @@ void cxgbe_hash_del_filter_rpl(struct adapter *adap, } ctx = f->ctx; - f->ctx = NULL; - - f->valid = 0; - - if (f->clipt) - cxgbe_clip_release(f->dev, f->clipt); + clear_filter(f); cxgbe_remove_tid(t, 0, tid, 0); t4_os_free(f);