From 3a381a4116ede3b92dca787c71d3288b260d1486 Mon Sep 17 00:00:00 2001 From: Shagun Agrawal Date: Fri, 29 Jun 2018 23:42:16 +0530 Subject: [PATCH] net/cxgbe: query firmware for HASH filter resources Fetch available HASH filter resources and allocate table for managing them. Currently only supported on Chelsio T6 family of NICs. Signed-off-by: Shagun Agrawal Signed-off-by: Rahul Lakkireddy --- drivers/net/cxgbe/base/common.h | 7 +++++ drivers/net/cxgbe/base/t4_regs.h | 9 ++++++ drivers/net/cxgbe/cxgbe_compat.h | 12 ++++++++ drivers/net/cxgbe/cxgbe_filter.c | 38 ++++++++++++++++++++++++++ drivers/net/cxgbe/cxgbe_filter.h | 1 + drivers/net/cxgbe/cxgbe_main.c | 47 +++++++++++++++++++++++++++++--- drivers/net/cxgbe/cxgbe_ofld.h | 26 ++++++++++++++++-- 7 files changed, 134 insertions(+), 6 deletions(-) diff --git a/drivers/net/cxgbe/base/common.h b/drivers/net/cxgbe/base/common.h index e524f79312..a276a1ef5f 100644 --- a/drivers/net/cxgbe/base/common.h +++ b/drivers/net/cxgbe/base/common.h @@ -251,6 +251,8 @@ struct adapter_params { unsigned char nports; /* # of ethernet ports */ unsigned char portvec; + unsigned char hash_filter; + enum chip_type chip; /* chip code */ struct arch_specific_params arch; /* chip specific params */ @@ -314,6 +316,11 @@ static inline int is_pf4(struct adapter *adap) #define for_each_port(adapter, iter) \ for (iter = 0; iter < (adapter)->params.nports; ++iter) +static inline int is_hashfilter(const struct adapter *adap) +{ + return adap->params.hash_filter; +} + void t4_read_mtu_tbl(struct adapter *adap, u16 *mtus, u8 *mtu_log); void t4_tp_wr_bits_indirect(struct adapter *adap, unsigned int addr, unsigned int mask, unsigned int val); diff --git a/drivers/net/cxgbe/base/t4_regs.h b/drivers/net/cxgbe/base/t4_regs.h index fd8f9cf27b..a1f6208ea3 100644 --- a/drivers/net/cxgbe/base/t4_regs.h +++ b/drivers/net/cxgbe/base/t4_regs.h @@ -937,3 +937,12 @@ #define M_REV 0xfU #define V_REV(x) ((x) << S_REV) #define G_REV(x) (((x) >> S_REV) & M_REV) + +/* registers for module LE */ +#define A_LE_DB_CONFIG 0x19c04 + +#define S_HASHEN 20 +#define V_HASHEN(x) ((x) << S_HASHEN) +#define F_HASHEN V_HASHEN(1U) + +#define A_LE_DB_TID_HASHBASE 0x19df8 diff --git a/drivers/net/cxgbe/cxgbe_compat.h b/drivers/net/cxgbe/cxgbe_compat.h index 779bcf165c..609156499f 100644 --- a/drivers/net/cxgbe/cxgbe_compat.h +++ b/drivers/net/cxgbe/cxgbe_compat.h @@ -250,4 +250,16 @@ static inline void writel_relaxed(unsigned int val, volatile void __iomem *addr) rte_write32_relaxed(val, addr); } +/* + * Multiplies an integer by a fraction, while avoiding unnecessary + * overflow or loss of precision. + */ +#define mult_frac(x, numer, denom)( \ +{ \ + typeof(x) quot = (x) / (denom); \ + typeof(x) rem = (x) % (denom); \ + (quot * (numer)) + ((rem * (numer)) / (denom)); \ +} \ +) + #endif /* _CXGBE_COMPAT_H_ */ diff --git a/drivers/net/cxgbe/cxgbe_filter.c b/drivers/net/cxgbe/cxgbe_filter.c index d098b93088..a5d20d164e 100644 --- a/drivers/net/cxgbe/cxgbe_filter.c +++ b/drivers/net/cxgbe/cxgbe_filter.c @@ -7,6 +7,44 @@ #include "t4_regs.h" #include "cxgbe_filter.h" +/** + * Initialize Hash Filters + */ +int init_hash_filter(struct adapter *adap) +{ + unsigned int n_user_filters; + unsigned int user_filter_perc; + 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)) + +#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)) + + params[0] = FW_PARAM_DEV(NTID); + ret = t4_query_params(adap, adap->mbox, adap->pf, 0, 1, + params, val); + if (ret < 0) + return ret; + adap->tids.ntids = val[0]; + adap->tids.natids = min(adap->tids.ntids / 2, MAX_ATIDS); + + user_filter_perc = 100; + n_user_filters = mult_frac(adap->tids.nftids, + user_filter_perc, + 100); + + adap->tids.nftids = n_user_filters; + adap->params.hash_filter = 1; + return 0; +} + /** * Validate if the requested filter specification can be set by checking * if the requested features have been enabled diff --git a/drivers/net/cxgbe/cxgbe_filter.h b/drivers/net/cxgbe/cxgbe_filter.h index 4df37b9cd2..6758a1879d 100644 --- a/drivers/net/cxgbe/cxgbe_filter.h +++ b/drivers/net/cxgbe/cxgbe_filter.h @@ -220,6 +220,7 @@ int cxgbe_del_filter(struct rte_eth_dev *dev, unsigned int filter_id, struct ch_filter_specification *fs, struct filter_ctx *ctx); int cxgbe_alloc_ftid(struct adapter *adap, unsigned int family); +int init_hash_filter(struct adapter *adap); int validate_filter(struct adapter *adap, struct ch_filter_specification *fs); int cxgbe_get_filter_count(struct adapter *adapter, unsigned int fidx, u64 *c, bool get_byte); diff --git a/drivers/net/cxgbe/cxgbe_main.c b/drivers/net/cxgbe/cxgbe_main.c index 21ad380ae8..c692939db0 100644 --- a/drivers/net/cxgbe/cxgbe_main.c +++ b/drivers/net/cxgbe/cxgbe_main.c @@ -287,24 +287,43 @@ static int tid_init(struct tid_info *t) { size_t size; unsigned int ftid_bmap_size; + unsigned int natids = t->natids; unsigned int max_ftids = t->nftids; ftid_bmap_size = rte_bitmap_get_memory_footprint(t->nftids); size = t->ntids * sizeof(*t->tid_tab) + - max_ftids * sizeof(*t->ftid_tab); + max_ftids * sizeof(*t->ftid_tab) + + natids * sizeof(*t->atid_tab); t->tid_tab = t4_os_alloc(size); if (!t->tid_tab) return -ENOMEM; - t->ftid_tab = (struct filter_entry *)&t->tid_tab[t->ntids]; + t->atid_tab = (union aopen_entry *)&t->tid_tab[t->ntids]; + t->ftid_tab = (struct filter_entry *)&t->tid_tab[t->natids]; t->ftid_bmap_array = t4_os_alloc(ftid_bmap_size); if (!t->ftid_bmap_array) { tid_free(t); return -ENOMEM; } + t4_os_lock_init(&t->atid_lock); t4_os_lock_init(&t->ftid_lock); + + t->afree = NULL; + t->atids_in_use = 0; + rte_atomic32_init(&t->tids_in_use); + rte_atomic32_set(&t->tids_in_use, 0); + rte_atomic32_init(&t->conns_in_use); + rte_atomic32_set(&t->conns_in_use, 0); + + /* Setup the free list for atid_tab and clear the stid bitmap. */ + if (natids) { + while (--natids) + t->atid_tab[natids - 1].next = &t->atid_tab[natids]; + t->afree = t->atid_tab; + } + t->ftid_bmap = rte_bitmap_init(t->nftids, t->ftid_bmap_array, ftid_bmap_size); if (!t->ftid_bmap) { @@ -784,8 +803,7 @@ static int adap_init0_config(struct adapter *adapter, int reset) * This will allow the firmware to optimize aspects of the hardware * configuration which will result in improved performance. */ - caps_cmd.niccaps &= cpu_to_be16(~(FW_CAPS_CONFIG_NIC_HASHFILTER | - FW_CAPS_CONFIG_NIC_ETHOFLD)); + caps_cmd.niccaps &= cpu_to_be16(~FW_CAPS_CONFIG_NIC_ETHOFLD); caps_cmd.toecaps = 0; caps_cmd.iscsicaps = 0; caps_cmd.rdmacaps = 0; @@ -990,6 +1008,12 @@ static int adap_init0(struct adapter *adap) if (ret < 0) goto bye; + if ((caps_cmd.niccaps & cpu_to_be16(FW_CAPS_CONFIG_NIC_HASHFILTER)) && + is_t6(adap->params.chip)) { + if (init_hash_filter(adap) < 0) + goto bye; + } + /* query tid-related parameters */ params[0] = FW_PARAM_DEV(NTID); ret = t4_query_params(adap, adap->mbox, adap->pf, 0, 1, @@ -997,6 +1021,7 @@ static int adap_init0(struct adapter *adap) if (ret < 0) goto bye; adap->tids.ntids = val[0]; + adap->tids.natids = min(adap->tids.ntids / 2, MAX_ATIDS); /* If we're running on newer firmware, let it know that we're * prepared to deal with encapsulated CPL messages. Older @@ -1653,6 +1678,20 @@ int cxgbe_probe(struct adapter *adapter) "filter support disabled. Continuing\n"); } + if (is_hashfilter(adapter)) { + if (t4_read_reg(adapter, A_LE_DB_CONFIG) & F_HASHEN) { + u32 hash_base, hash_reg; + + hash_reg = A_LE_DB_TID_HASHBASE; + hash_base = t4_read_reg(adapter, hash_reg); + adapter->tids.hash_base = hash_base / 4; + } + } else { + /* Disable hash filtering support */ + dev_warn(adapter, + "Maskless filter support disabled. Continuing\n"); + } + err = init_rss(adapter); if (err) goto out_free; diff --git a/drivers/net/cxgbe/cxgbe_ofld.h b/drivers/net/cxgbe/cxgbe_ofld.h index 9f382f6595..e97c424693 100644 --- a/drivers/net/cxgbe/cxgbe_ofld.h +++ b/drivers/net/cxgbe/cxgbe_ofld.h @@ -10,6 +10,16 @@ #include "cxgbe_filter.h" +/* + * Max # of ATIDs. The absolute HW max is 16K but we keep it lower. + */ +#define MAX_ATIDS 8192U + +union aopen_entry { + void *data; + union aopen_entry *next; +}; + /* * Holds the size, base address, free list start, etc of filter TID. * The tables themselves are allocated dynamically. @@ -18,10 +28,22 @@ struct tid_info { void **tid_tab; unsigned int ntids; struct filter_entry *ftid_tab; /* Normal filters */ + union aopen_entry *atid_tab; struct rte_bitmap *ftid_bmap; uint8_t *ftid_bmap_array; - unsigned int nftids; - unsigned int ftid_base; + unsigned int nftids, natids; + unsigned int ftid_base, hash_base; + + union aopen_entry *afree; + unsigned int atids_in_use; + + /* TIDs in the TCAM */ + rte_atomic32_t tids_in_use; + /* TIDs in the HASH */ + rte_atomic32_t hash_tids_in_use; + rte_atomic32_t conns_in_use; + + rte_spinlock_t atid_lock __rte_cache_aligned; rte_spinlock_t ftid_lock; }; #endif /* _CXGBE_OFLD_H_ */