Commit d915c299 authored by Vishal Kulkarni's avatar Vishal Kulkarni Committed by David S. Miller
Browse files

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: default avatarRahul Lakkireddy <rahul.lakkireddy@chelsio.com>
Signed-off-by: default avatarVishal Kulkarni <vishal@chelsio.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 4b61d3e8
Loading
Loading
Loading
Loading
+14 −0
Original line number Diff line number Diff line
@@ -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
+82 −0
Original line number Diff line number Diff line
@@ -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;
+2 −0
Original line number Diff line number Diff line
@@ -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 */
+22 −16
Original line number Diff line number Diff line
@@ -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 */
+2 −0
Original line number Diff line number Diff line
@@ -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;
Loading