Commit 80cfde29 authored by Michael Chan's avatar Michael Chan Committed by David S. Miller
Browse files

bnxt_en: Refactor the hash table logic for ntuple filters.



Generalize the ethtool logic that walks the ntuple hash table now that
we have the common bnxt_filter_base structure.  This will allow the code
to easily extend to cover user defined ntuple or ether filters.

Reviewed-by: default avatarVasundhara Volam <vasundhara-v.volam@broadcom.com>
Reviewed-by: default avatarAndy Gospodarek <andrew.gospodarek@broadcom.com>
Reviewed-by: default avatarPavan Chebbi <pavan.chebbi@broadcom.com>
Signed-off-by: default avatarMichael Chan <michael.chan@broadcom.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 59cde76f
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -5615,6 +5615,7 @@ static int bnxt_hwrm_cfa_ntuple_filter_free(struct bnxt *bp,
	struct hwrm_cfa_ntuple_filter_free_input *req;
	int rc;

	set_bit(BNXT_FLTR_FW_DELETED, &fltr->base.state);
	rc = hwrm_req_init(bp, req, HWRM_CFA_NTUPLE_FILTER_FREE);
	if (rc)
		return rc;
+1 −0
Original line number Diff line number Diff line
@@ -1349,6 +1349,7 @@ struct bnxt_filter_base {
	unsigned long		state;
#define BNXT_FLTR_VALID		0
#define BNXT_FLTR_INSERTED	1
#define BNXT_FLTR_FW_DELETED	2

	struct rcu_head         rcu;
};
+57 −28
Original line number Diff line number Diff line
@@ -1012,28 +1012,60 @@ static int bnxt_set_channels(struct net_device *dev,
}

#ifdef CONFIG_RFS_ACCEL
static int bnxt_grxclsrlall(struct bnxt *bp, struct ethtool_rxnfc *cmd,
			    u32 *rule_locs)
static u32 bnxt_get_all_fltr_ids_rcu(struct bnxt *bp, struct hlist_head tbl[],
				     int tbl_size, u32 *ids, u32 start,
				     u32 id_cnt)
{
	int i, j = 0;
	int i, j = start;

	cmd->data = bp->ntp_fltr_count;
	for (i = 0; i < BNXT_NTP_FLTR_HASH_SIZE; i++) {
	if (j >= id_cnt)
		return j;
	for (i = 0; i < tbl_size; i++) {
		struct hlist_head *head;
		struct bnxt_ntuple_filter *fltr;
		struct bnxt_filter_base *fltr;

		head = &bp->ntp_fltr_hash_tbl[i];
		rcu_read_lock();
		hlist_for_each_entry_rcu(fltr, head, base.hash) {
			if (j == cmd->rule_cnt)
				break;
			rule_locs[j++] = fltr->base.sw_id;
		head = &tbl[i];
		hlist_for_each_entry_rcu(fltr, head, hash) {
			if (!fltr->flags ||
			    test_bit(BNXT_FLTR_FW_DELETED, &fltr->state))
				continue;
			ids[j++] = fltr->sw_id;
			if (j == id_cnt)
				return j;
		}
		rcu_read_unlock();
		if (j == cmd->rule_cnt)
			break;
	}
	cmd->rule_cnt = j;
	return j;
}

static struct bnxt_filter_base *bnxt_get_one_fltr_rcu(struct bnxt *bp,
						      struct hlist_head tbl[],
						      int tbl_size, u32 id)
{
	int i;

	for (i = 0; i < tbl_size; i++) {
		struct hlist_head *head;
		struct bnxt_filter_base *fltr;

		head = &tbl[i];
		hlist_for_each_entry_rcu(fltr, head, hash) {
			if (fltr->flags && fltr->sw_id == id)
				return fltr;
		}
	}
	return NULL;
}

static int bnxt_grxclsrlall(struct bnxt *bp, struct ethtool_rxnfc *cmd,
			    u32 *rule_locs)
{
	cmd->data = bp->ntp_fltr_count;
	rcu_read_lock();
	cmd->rule_cnt = bnxt_get_all_fltr_ids_rcu(bp, bp->ntp_fltr_hash_tbl,
						  BNXT_NTP_FLTR_HASH_SIZE,
						  rule_locs, 0, cmd->rule_cnt);
	rcu_read_unlock();

	return 0;
}

@@ -1041,27 +1073,24 @@ static int bnxt_grxclsrule(struct bnxt *bp, struct ethtool_rxnfc *cmd)
{
	struct ethtool_rx_flow_spec *fs =
		(struct ethtool_rx_flow_spec *)&cmd->fs;
	struct bnxt_filter_base *fltr_base;
	struct bnxt_ntuple_filter *fltr;
	struct flow_keys *fkeys;
	int i, rc = -EINVAL;
	int rc = -EINVAL;

	if (fs->location >= BNXT_NTP_FLTR_MAX_FLTR)
		return rc;

	for (i = 0; i < BNXT_NTP_FLTR_HASH_SIZE; i++) {
		struct hlist_head *head;

		head = &bp->ntp_fltr_hash_tbl[i];
	rcu_read_lock();
		hlist_for_each_entry_rcu(fltr, head, base.hash) {
			if (fltr->base.sw_id == fs->location)
				goto fltr_found;
		}
	fltr_base = bnxt_get_one_fltr_rcu(bp, bp->ntp_fltr_hash_tbl,
					  BNXT_NTP_FLTR_HASH_SIZE,
					  fs->location);
	if (!fltr_base) {
		rcu_read_unlock();
	}
		return rc;
	}
	fltr = container_of(fltr_base, struct bnxt_ntuple_filter, base);

fltr_found:
	fkeys = &fltr->fkeys;
	if (fkeys->basic.n_proto == htons(ETH_P_IP)) {
		if (fkeys->basic.ip_proto == IPPROTO_TCP)