net/cxgbe: query firmware for HASH filter resources
authorShagun Agrawal <shaguna@chelsio.com>
Fri, 29 Jun 2018 18:12:16 +0000 (23:42 +0530)
committerFerruh Yigit <ferruh.yigit@intel.com>
Wed, 4 Jul 2018 20:07:53 +0000 (22:07 +0200)
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 <shaguna@chelsio.com>
Signed-off-by: Rahul Lakkireddy <rahul.lakkireddy@chelsio.com>
drivers/net/cxgbe/base/common.h
drivers/net/cxgbe/base/t4_regs.h
drivers/net/cxgbe/cxgbe_compat.h
drivers/net/cxgbe/cxgbe_filter.c
drivers/net/cxgbe/cxgbe_filter.h
drivers/net/cxgbe/cxgbe_main.c
drivers/net/cxgbe/cxgbe_ofld.h

index e524f79..a276a1e 100644 (file)
@@ -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);
index fd8f9cf..a1f6208 100644 (file)
 #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
index 779bcf1..6091564 100644 (file)
@@ -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_ */
index d098b93..a5d20d1 100644 (file)
@@ -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
index 4df37b9..6758a18 100644 (file)
@@ -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);
index 21ad380..c692939 100644 (file)
@@ -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 @@ allocate_mac:
                         "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;
index 9f382f6..e97c424 100644 (file)
 
 #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_ */