cxgb4: add skeleton for ethtool n-tuple filters
Allocate and manage resources required for ethtool n-tuple filters. Also fetch the HASH filter region size and calculate nhash entries. Signed-off-by: Rahul Lakkireddy <rahul.lakkireddy@chelsio.com> Signed-off-by: Vishal Kulkarni <vishal@chelsio.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
4b61d3e8d3
commit
d915c299f1
|
@ -1066,6 +1066,17 @@ struct mps_entries_ref {
|
|||
refcount_t refcnt;
|
||||
};
|
||||
|
||||
struct cxgb4_ethtool_filter_info {
|
||||
u32 *loc_array; /* Array holding the actual TIDs set to filters */
|
||||
unsigned long *bmap; /* Bitmap for managing filters in use */
|
||||
u32 in_use; /* # of filters in use */
|
||||
};
|
||||
|
||||
struct cxgb4_ethtool_filter {
|
||||
u32 nentries; /* Adapter wide number of supported filters */
|
||||
struct cxgb4_ethtool_filter_info *port; /* Per port entry */
|
||||
};
|
||||
|
||||
struct adapter {
|
||||
void __iomem *regs;
|
||||
void __iomem *bar2;
|
||||
|
@ -1191,6 +1202,9 @@ struct adapter {
|
|||
|
||||
/* TC MATCHALL classifier offload */
|
||||
struct cxgb4_tc_matchall *tc_matchall;
|
||||
|
||||
/* Ethtool n-tuple */
|
||||
struct cxgb4_ethtool_filter *ethtool_filters;
|
||||
};
|
||||
|
||||
/* Support for "sched-class" command to allow a TX Scheduling Class to be
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "t4_regs.h"
|
||||
#include "t4fw_api.h"
|
||||
#include "cxgb4_cudbg.h"
|
||||
#include "cxgb4_filter.h"
|
||||
|
||||
#define EEPROM_MAGIC 0x38E2F10C
|
||||
|
||||
|
@ -1853,6 +1854,87 @@ static const struct ethtool_ops cxgb_ethtool_ops = {
|
|||
.set_priv_flags = cxgb4_set_priv_flags,
|
||||
};
|
||||
|
||||
void cxgb4_cleanup_ethtool_filters(struct adapter *adap)
|
||||
{
|
||||
struct cxgb4_ethtool_filter_info *eth_filter_info;
|
||||
u8 i;
|
||||
|
||||
if (!adap->ethtool_filters)
|
||||
return;
|
||||
|
||||
eth_filter_info = adap->ethtool_filters->port;
|
||||
|
||||
if (eth_filter_info) {
|
||||
for (i = 0; i < adap->params.nports; i++) {
|
||||
kvfree(eth_filter_info[i].loc_array);
|
||||
kfree(eth_filter_info[i].bmap);
|
||||
}
|
||||
kfree(eth_filter_info);
|
||||
}
|
||||
|
||||
kfree(adap->ethtool_filters);
|
||||
}
|
||||
|
||||
int cxgb4_init_ethtool_filters(struct adapter *adap)
|
||||
{
|
||||
struct cxgb4_ethtool_filter_info *eth_filter_info;
|
||||
struct cxgb4_ethtool_filter *eth_filter;
|
||||
struct tid_info *tids = &adap->tids;
|
||||
u32 nentries, i;
|
||||
int ret;
|
||||
|
||||
eth_filter = kzalloc(sizeof(*eth_filter), GFP_KERNEL);
|
||||
if (!eth_filter)
|
||||
return -ENOMEM;
|
||||
|
||||
eth_filter_info = kcalloc(adap->params.nports,
|
||||
sizeof(*eth_filter_info),
|
||||
GFP_KERNEL);
|
||||
if (!eth_filter_info) {
|
||||
ret = -ENOMEM;
|
||||
goto free_eth_filter;
|
||||
}
|
||||
|
||||
eth_filter->port = eth_filter_info;
|
||||
|
||||
nentries = tids->nhpftids + tids->nftids;
|
||||
if (is_hashfilter(adap))
|
||||
nentries += tids->nhash +
|
||||
(adap->tids.stid_base - adap->tids.tid_base);
|
||||
eth_filter->nentries = nentries;
|
||||
|
||||
for (i = 0; i < adap->params.nports; i++) {
|
||||
eth_filter->port[i].loc_array = kvzalloc(nentries, GFP_KERNEL);
|
||||
if (!eth_filter->port[i].loc_array) {
|
||||
ret = -ENOMEM;
|
||||
goto free_eth_finfo;
|
||||
}
|
||||
|
||||
eth_filter->port[i].bmap = kcalloc(BITS_TO_LONGS(nentries),
|
||||
sizeof(unsigned long),
|
||||
GFP_KERNEL);
|
||||
if (!eth_filter->port[i].bmap) {
|
||||
ret = -ENOMEM;
|
||||
goto free_eth_finfo;
|
||||
}
|
||||
}
|
||||
|
||||
adap->ethtool_filters = eth_filter;
|
||||
return 0;
|
||||
|
||||
free_eth_finfo:
|
||||
while (i-- > 0) {
|
||||
kfree(eth_filter->port[i].bmap);
|
||||
kvfree(eth_filter->port[i].loc_array);
|
||||
}
|
||||
kfree(eth_filter_info);
|
||||
|
||||
free_eth_filter:
|
||||
kfree(eth_filter);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void cxgb4_set_ethtool_ops(struct net_device *netdev)
|
||||
{
|
||||
netdev->ethtool_ops = &cxgb_ethtool_ops;
|
||||
|
|
|
@ -53,4 +53,6 @@ void clear_all_filters(struct adapter *adapter);
|
|||
void init_hash_filter(struct adapter *adap);
|
||||
bool is_filter_exact_match(struct adapter *adap,
|
||||
struct ch_filter_specification *fs);
|
||||
void cxgb4_cleanup_ethtool_filters(struct adapter *adap);
|
||||
int cxgb4_init_ethtool_filters(struct adapter *adap);
|
||||
#endif /* __CXGB4_FILTER_H */
|
||||
|
|
|
@ -5860,6 +5860,7 @@ static void free_some_resources(struct adapter *adapter)
|
|||
cxgb4_cleanup_tc_mqprio(adapter);
|
||||
cxgb4_cleanup_tc_flower(adapter);
|
||||
cxgb4_cleanup_tc_u32(adapter);
|
||||
cxgb4_cleanup_ethtool_filters(adapter);
|
||||
kfree(adapter->sge.egr_map);
|
||||
kfree(adapter->sge.ingr_map);
|
||||
kfree(adapter->sge.starving_fl);
|
||||
|
@ -6493,6 +6494,24 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
i);
|
||||
}
|
||||
|
||||
if (is_offload(adapter) || is_hashfilter(adapter)) {
|
||||
if (t4_read_reg(adapter, LE_DB_CONFIG_A) & HASHEN_F) {
|
||||
u32 v;
|
||||
|
||||
v = t4_read_reg(adapter, LE_DB_HASH_CONFIG_A);
|
||||
if (chip_ver <= CHELSIO_T5) {
|
||||
adapter->tids.nhash = 1 << HASHTIDSIZE_G(v);
|
||||
v = t4_read_reg(adapter, LE_DB_TID_HASHBASE_A);
|
||||
adapter->tids.hash_base = v / 4;
|
||||
} else {
|
||||
adapter->tids.nhash = HASHTBLSIZE_G(v) << 3;
|
||||
v = t4_read_reg(adapter,
|
||||
T6_LE_DB_HASH_TID_BASE_A);
|
||||
adapter->tids.hash_base = v;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (tid_init(&adapter->tids) < 0) {
|
||||
dev_warn(&pdev->dev, "could not allocate TID table, "
|
||||
"continuing\n");
|
||||
|
@ -6514,22 +6533,9 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
if (cxgb4_init_tc_matchall(adapter))
|
||||
dev_warn(&pdev->dev,
|
||||
"could not offload tc matchall, continuing\n");
|
||||
}
|
||||
|
||||
if (is_offload(adapter) || is_hashfilter(adapter)) {
|
||||
if (t4_read_reg(adapter, LE_DB_CONFIG_A) & HASHEN_F) {
|
||||
u32 hash_base, hash_reg;
|
||||
|
||||
if (chip_ver <= CHELSIO_T5) {
|
||||
hash_reg = LE_DB_TID_HASHBASE_A;
|
||||
hash_base = t4_read_reg(adapter, hash_reg);
|
||||
adapter->tids.hash_base = hash_base / 4;
|
||||
} else {
|
||||
hash_reg = T6_LE_DB_HASH_TID_BASE_A;
|
||||
hash_base = t4_read_reg(adapter, hash_reg);
|
||||
adapter->tids.hash_base = hash_base;
|
||||
}
|
||||
}
|
||||
if (cxgb4_init_ethtool_filters(adapter))
|
||||
dev_warn(&pdev->dev,
|
||||
"could not initialize ethtool filters, continuing\n");
|
||||
}
|
||||
|
||||
/* See what interrupts we'll be using */
|
||||
|
|
|
@ -106,6 +106,8 @@ struct tid_info {
|
|||
unsigned long *stid_bmap;
|
||||
unsigned int nstids;
|
||||
unsigned int stid_base;
|
||||
|
||||
unsigned int nhash;
|
||||
unsigned int hash_base;
|
||||
|
||||
union aopen_entry *atid_tab;
|
||||
|
|
|
@ -3044,6 +3044,10 @@
|
|||
#define HASHTIDSIZE_M 0x3fU
|
||||
#define HASHTIDSIZE_G(x) (((x) >> HASHTIDSIZE_S) & HASHTIDSIZE_M)
|
||||
|
||||
#define HASHTBLSIZE_S 3
|
||||
#define HASHTBLSIZE_M 0x1ffffU
|
||||
#define HASHTBLSIZE_G(x) (((x) >> HASHTBLSIZE_S) & HASHTBLSIZE_M)
|
||||
|
||||
#define LE_DB_HASH_TID_BASE_A 0x19c30
|
||||
#define LE_DB_HASH_TBL_BASE_ADDR_A 0x19c30
|
||||
#define LE_DB_INT_CAUSE_A 0x19c3c
|
||||
|
|
Loading…
Reference in New Issue