X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fcxgbe%2Fcxgbe_filter.c;h=384dde3f9f9810cfc38580f6ebfbae09687c270a;hb=25ae7f1a5d9d127a46f8d62d1d689f77a78138fd;hp=b009217f8eb5783e52237f30b001e6a85e9cd3e5;hpb=7d71ba5d15ce4db117a02f4a79de7c9d22a5fdba;p=dpdk.git diff --git a/drivers/net/cxgbe/cxgbe_filter.c b/drivers/net/cxgbe/cxgbe_filter.c index b009217f8e..384dde3f9f 100644 --- a/drivers/net/cxgbe/cxgbe_filter.c +++ b/drivers/net/cxgbe/cxgbe_filter.c @@ -8,35 +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; @@ -61,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; @@ -282,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. */ @@ -581,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 @@ -604,6 +651,17 @@ static int cxgbe_set_hash_filter(struct rte_eth_dev *dev, } } + /* 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 = -EAGAIN; + goto out_err; + } + } + atid = cxgbe_alloc_atid(t, f); if (atid < 0) goto out_err; @@ -618,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; @@ -648,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 @@ -744,20 +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; - } - ctrlq = &adapter->sge.ctrlq[port_id]; mbuf = rte_pktmbuf_alloc(ctrlq->mb_pool); if (!mbuf) { @@ -788,6 +814,7 @@ static int set_filter_wr(struct rte_eth_dev *dev, unsigned int fidx) cpu_to_be32(V_FW_FILTER_WR_DROP(f->fs.action == FILTER_DROP) | V_FW_FILTER_WR_DIRSTEER(f->fs.dirsteer) | V_FW_FILTER_WR_LPBK(f->fs.action == FILTER_SWITCH) | + V_FW_FILTER_WR_SMAC(f->fs.newsmac) | V_FW_FILTER_WR_DMAC(f->fs.newdmac) | V_FW_FILTER_WR_INSVLAN (f->fs.newvlan == VLAN_INSERT || @@ -806,7 +833,7 @@ static int set_filter_wr(struct rte_eth_dev *dev, unsigned int fidx) V_FW_FILTER_WR_IVLAN_VLDM(f->fs.mask.ivlan_vld) | V_FW_FILTER_WR_OVLAN_VLD(f->fs.val.ovlan_vld) | V_FW_FILTER_WR_OVLAN_VLDM(f->fs.mask.ovlan_vld)); - fwr->smac_sel = 0; + fwr->smac_sel = f->smt ? f->smt->hw_idx : 0; fwr->rx_chan_rx_rpl_iq = cpu_to_be16(V_FW_FILTER_WR_RX_CHAN(0) | V_FW_FILTER_WR_RX_RPL_IQ(adapter->sge.fw_evtq.abs_id @@ -1042,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 @@ -1062,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 @@ -1144,6 +1208,12 @@ void cxgbe_hash_filter_rpl(struct adapter *adap, if (f->fs.newvlan == VLAN_INSERT || f->fs.newvlan == VLAN_REWRITE) set_tcb_tflag(adap, tid, S_TF_CCTRL_RFR, 1, 1); + if (f->fs.newsmac) { + set_tcb_tflag(adap, tid, S_TF_CCTRL_CWR, 1, 1); + set_tcb_field(adap, tid, W_TCB_SMAC_SEL, + V_TCB_SMAC_SEL(M_TCB_SMAC_SEL), + V_TCB_SMAC_SEL(f->smt->hw_idx), 1); + } break; } default: @@ -1158,6 +1228,7 @@ void cxgbe_hash_filter_rpl(struct adapter *adap, } cxgbe_free_atid(t, ftid); + clear_filter(f); t4_os_free(f); } @@ -1382,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);