Commit fb9bb704 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'bnxt_en-ntuple-fuilter-support'



Michael Chan says:

====================
bnxt_en: Add basic ntuple filter support

The current driver only supports ntuple filters added by aRFS.  This
patch series adds basic support for user defined TCP/UDP ntuple filters
added by the user using ethtool.  Many of the patches are refactoring
patches to make the existing code more general to support both aRFS
and user defined filters.  aRFS filters always have the Toeplitz hash
value from the NIC.  A Toepliz hash function is added in patch 5 to
get the same hash value for user defined filters.  The hash is used
to store all ntuple filters in the table and all filters must be
hashed identically using the same function and key.

v2: Fix compile error in patch #4 when CONFIG_BNXT_SRIOV is disabled.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 8a48a2dc 8d7ba028
Loading
Loading
Loading
Loading
+539 −180

File changed.

Preview size limit exceeded, changes collapsed.

+84 −8
Original line number Diff line number Diff line
@@ -1219,7 +1219,7 @@ struct bnxt_vnic_info {
	u16		fw_rss_cos_lb_ctx[BNXT_MAX_CTX_PER_VNIC];
	u16		fw_l2_ctx_id;
#define BNXT_MAX_UC_ADDRS	4
	__le64		fw_l2_filter_id[BNXT_MAX_UC_ADDRS];
	struct bnxt_l2_filter *l2_filters[BNXT_MAX_UC_ADDRS];
				/* index 0 always dev_addr */
	u16		uc_filter_count;
	u8		*uc_list;
@@ -1332,19 +1332,71 @@ struct bnxt_pf_info {
	struct bnxt_vf_info	*vf;
};

struct bnxt_ntuple_filter {
struct bnxt_filter_base {
	struct hlist_node	hash;
	u8			dst_mac_addr[ETH_ALEN];
	u8			src_mac_addr[ETH_ALEN];
	struct flow_keys	fkeys;
	__le64			filter_id;
	u8			type;
#define BNXT_FLTR_TYPE_NTUPLE	1
#define BNXT_FLTR_TYPE_L2	2
	u8			flags;
#define BNXT_ACT_DROP		1
#define BNXT_ACT_RING_DST	2
#define BNXT_ACT_FUNC_DST	4
#define BNXT_ACT_NO_AGING	8
	u16			sw_id;
	u8			l2_fltr_idx;
	u16			rxq;
	u32			flow_id;
	u16			fw_vnic_id;
	u16			vf_idx;
	unsigned long		state;
#define BNXT_FLTR_VALID		0
#define BNXT_FLTR_UPDATE	1
#define BNXT_FLTR_INSERTED	1
#define BNXT_FLTR_FW_DELETED	2

	struct rcu_head         rcu;
};

struct bnxt_ntuple_filter {
	struct bnxt_filter_base	base;
	struct flow_keys	fkeys;
	struct bnxt_l2_filter	*l2_fltr;
	u32			ntuple_flags;
#define BNXT_NTUPLE_MATCH_SRC_IP	1
#define BNXT_NTUPLE_MATCH_DST_IP	2
#define BNXT_NTUPLE_MATCH_SRC_PORT	4
#define BNXT_NTUPLE_MATCH_DST_PORT	8
#define BNXT_NTUPLE_MATCH_ALL		(BNXT_NTUPLE_MATCH_SRC_IP |	\
					 BNXT_NTUPLE_MATCH_DST_IP |	\
					 BNXT_NTUPLE_MATCH_SRC_PORT |	\
					 BNXT_NTUPLE_MATCH_DST_PORT)
	u32			flow_id;
};

struct bnxt_l2_key {
	union {
		struct {
			u8	dst_mac_addr[ETH_ALEN];
			u16	vlan;
		};
		u32	filter_key;
	};
};

struct bnxt_ipv4_tuple {
	struct flow_dissector_key_ipv4_addrs v4addrs;
	struct flow_dissector_key_ports ports;
};

struct bnxt_ipv6_tuple {
	struct flow_dissector_key_ipv6_addrs v6addrs;
	struct flow_dissector_key_ports ports;
};

#define BNXT_L2_KEY_SIZE	(sizeof(struct bnxt_l2_key) / 4)

struct bnxt_l2_filter {
	struct bnxt_filter_base	base;
	struct bnxt_l2_key	l2_key;
	atomic_t		refcnt;
};

struct bnxt_link_info {
@@ -2367,6 +2419,7 @@ struct bnxt {
	int			db_size;

#define BNXT_NTP_FLTR_MAX_FLTR	4096
#define BNXT_MAX_FLTR		(BNXT_NTP_FLTR_MAX_FLTR + BNXT_L2_FLTR_MAX_FLTR)
#define BNXT_NTP_FLTR_HASH_SIZE	512
#define BNXT_NTP_FLTR_HASH_MASK	(BNXT_NTP_FLTR_HASH_SIZE - 1)
	struct hlist_head	ntp_fltr_hash_tbl[BNXT_NTP_FLTR_HASH_SIZE];
@@ -2375,6 +2428,14 @@ struct bnxt {
	unsigned long		*ntp_fltr_bmap;
	int			ntp_fltr_count;

#define BNXT_L2_FLTR_MAX_FLTR	1024
#define BNXT_L2_FLTR_HASH_SIZE	32
#define BNXT_L2_FLTR_HASH_MASK	(BNXT_L2_FLTR_HASH_SIZE - 1)
	struct hlist_head	l2_fltr_hash_tbl[BNXT_L2_FLTR_HASH_SIZE];

	u32			hash_seed;
	u64			toeplitz_prefix;

	/* To protect link related settings during link changes and
	 * ethtool settings changes.
	 */
@@ -2582,6 +2643,14 @@ int bnxt_set_rx_skb_mode(struct bnxt *bp, bool page_mode);
int bnxt_hwrm_func_drv_rgtr(struct bnxt *bp, unsigned long *bmap,
			    int bmap_size, bool async_only);
int bnxt_hwrm_func_drv_unrgtr(struct bnxt *bp);
void bnxt_del_l2_filter(struct bnxt *bp, struct bnxt_l2_filter *fltr);
int bnxt_hwrm_l2_filter_free(struct bnxt *bp, struct bnxt_l2_filter *fltr);
int bnxt_hwrm_l2_filter_alloc(struct bnxt *bp, struct bnxt_l2_filter *fltr);
int bnxt_hwrm_cfa_ntuple_filter_free(struct bnxt *bp,
				     struct bnxt_ntuple_filter *fltr);
int bnxt_hwrm_cfa_ntuple_filter_alloc(struct bnxt *bp,
				      struct bnxt_ntuple_filter *fltr);
void bnxt_fill_ipv6_mask(__be32 mask[4]);
int bnxt_get_nr_rss_ctxs(struct bnxt *bp, int rx_rings);
int bnxt_hwrm_vnic_cfg(struct bnxt *bp, u16 vnic_id);
int __bnxt_hwrm_get_tx_rings(struct bnxt *bp, u16 fid, int *tx_rings);
@@ -2625,6 +2694,13 @@ int bnxt_check_rings(struct bnxt *bp, int tx, int rx, bool sh, int tcs,
int bnxt_fw_init_one(struct bnxt *bp);
bool bnxt_hwrm_reset_permitted(struct bnxt *bp);
int bnxt_setup_mq_tc(struct net_device *dev, u8 tc);
struct bnxt_ntuple_filter *bnxt_lookup_ntp_filter_from_idx(struct bnxt *bp,
				struct bnxt_ntuple_filter *fltr, u32 idx);
u32 bnxt_get_ntp_filter_idx(struct bnxt *bp, struct flow_keys *fkeys,
			    const struct sk_buff *skb);
int bnxt_insert_ntp_filter(struct bnxt *bp, struct bnxt_ntuple_filter *fltr,
			   u32 idx);
void bnxt_del_ntp_filter(struct bnxt *bp, struct bnxt_ntuple_filter *fltr);
int bnxt_get_max_rings(struct bnxt *, int *, int *, bool);
int bnxt_restore_pf_fw_resources(struct bnxt *bp);
int bnxt_get_port_parent_id(struct net_device *dev,
+313 −58
Original line number Diff line number Diff line
@@ -1011,29 +1011,60 @@ static int bnxt_set_channels(struct net_device *dev,
	return rc;
}

#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();
		head = &tbl[i];
		hlist_for_each_entry_rcu(fltr, head, hash) {
			if (j == cmd->rule_cnt)
				break;
			rule_locs[j++] = fltr->sw_id;
			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 +1072,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, hash) {
			if (fltr->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)
@@ -1071,20 +1099,23 @@ static int bnxt_grxclsrule(struct bnxt *bp, struct ethtool_rxnfc *cmd)
		else
			goto fltr_err;

		if (fltr->ntuple_flags & BNXT_NTUPLE_MATCH_SRC_IP) {
			fs->h_u.tcp_ip4_spec.ip4src = fkeys->addrs.v4addrs.src;
			fs->m_u.tcp_ip4_spec.ip4src = cpu_to_be32(~0);

		}
		if (fltr->ntuple_flags & BNXT_NTUPLE_MATCH_DST_IP) {
			fs->h_u.tcp_ip4_spec.ip4dst = fkeys->addrs.v4addrs.dst;
			fs->m_u.tcp_ip4_spec.ip4dst = cpu_to_be32(~0);

		}
		if (fltr->ntuple_flags & BNXT_NTUPLE_MATCH_SRC_PORT) {
			fs->h_u.tcp_ip4_spec.psrc = fkeys->ports.src;
			fs->m_u.tcp_ip4_spec.psrc = cpu_to_be16(~0);

		}
		if (fltr->ntuple_flags & BNXT_NTUPLE_MATCH_DST_PORT) {
			fs->h_u.tcp_ip4_spec.pdst = fkeys->ports.dst;
			fs->m_u.tcp_ip4_spec.pdst = cpu_to_be16(~0);
		}
	} else {
		int i;

		if (fkeys->basic.ip_proto == IPPROTO_TCP)
			fs->flow_type = TCP_V6_FLOW;
		else if (fkeys->basic.ip_proto == IPPROTO_UDP)
@@ -1092,22 +1123,27 @@ static int bnxt_grxclsrule(struct bnxt *bp, struct ethtool_rxnfc *cmd)
		else
			goto fltr_err;

		if (fltr->ntuple_flags & BNXT_NTUPLE_MATCH_SRC_IP) {
			*(struct in6_addr *)&fs->h_u.tcp_ip6_spec.ip6src[0] =
				fkeys->addrs.v6addrs.src;
			bnxt_fill_ipv6_mask(fs->m_u.tcp_ip6_spec.ip6src);
		}
		if (fltr->ntuple_flags & BNXT_NTUPLE_MATCH_DST_IP) {
			*(struct in6_addr *)&fs->h_u.tcp_ip6_spec.ip6dst[0] =
				fkeys->addrs.v6addrs.dst;
		for (i = 0; i < 4; i++) {
			fs->m_u.tcp_ip6_spec.ip6src[i] = cpu_to_be32(~0);
			fs->m_u.tcp_ip6_spec.ip6dst[i] = cpu_to_be32(~0);
			bnxt_fill_ipv6_mask(fs->m_u.tcp_ip6_spec.ip6dst);
		}
		if (fltr->ntuple_flags & BNXT_NTUPLE_MATCH_SRC_PORT) {
			fs->h_u.tcp_ip6_spec.psrc = fkeys->ports.src;
			fs->m_u.tcp_ip6_spec.psrc = cpu_to_be16(~0);

		}
		if (fltr->ntuple_flags & BNXT_NTUPLE_MATCH_DST_PORT) {
			fs->h_u.tcp_ip6_spec.pdst = fkeys->ports.dst;
			fs->m_u.tcp_ip6_spec.pdst = cpu_to_be16(~0);
		}
	}

	fs->ring_cookie = fltr->rxq;
	fs->ring_cookie = fltr->base.rxq;
	rc = 0;

fltr_err:
@@ -1115,7 +1151,220 @@ static int bnxt_grxclsrule(struct bnxt *bp, struct ethtool_rxnfc *cmd)

	return rc;
}
#endif

#define IPV4_ALL_MASK		((__force __be32)~0)
#define L4_PORT_ALL_MASK	((__force __be16)~0)

static bool ipv6_mask_is_full(__be32 mask[4])
{
	return (mask[0] & mask[1] & mask[2] & mask[3]) == IPV4_ALL_MASK;
}

static bool ipv6_mask_is_zero(__be32 mask[4])
{
	return !(mask[0] | mask[1] | mask[2] | mask[3]);
}

static int bnxt_add_ntuple_cls_rule(struct bnxt *bp,
				    struct ethtool_rx_flow_spec *fs)
{
	u8 vf = ethtool_get_flow_spec_ring_vf(fs->ring_cookie);
	u32 ring = ethtool_get_flow_spec_ring(fs->ring_cookie);
	struct bnxt_ntuple_filter *new_fltr, *fltr;
	struct bnxt_l2_filter *l2_fltr;
	u32 flow_type = fs->flow_type;
	struct flow_keys *fkeys;
	u32 idx;
	int rc;

	if (!bp->vnic_info)
		return -EAGAIN;

	if ((flow_type & (FLOW_MAC_EXT | FLOW_EXT)) || vf)
		return -EOPNOTSUPP;

	new_fltr = kzalloc(sizeof(*new_fltr), GFP_KERNEL);
	if (!new_fltr)
		return -ENOMEM;

	l2_fltr = bp->vnic_info[0].l2_filters[0];
	atomic_inc(&l2_fltr->refcnt);
	new_fltr->l2_fltr = l2_fltr;
	fkeys = &new_fltr->fkeys;

	rc = -EOPNOTSUPP;
	switch (flow_type) {
	case TCP_V4_FLOW:
	case UDP_V4_FLOW: {
		struct ethtool_tcpip4_spec *ip_spec = &fs->h_u.tcp_ip4_spec;
		struct ethtool_tcpip4_spec *ip_mask = &fs->m_u.tcp_ip4_spec;

		fkeys->basic.ip_proto = IPPROTO_TCP;
		if (flow_type == UDP_V4_FLOW)
			fkeys->basic.ip_proto = IPPROTO_UDP;
		fkeys->basic.n_proto = htons(ETH_P_IP);

		if (ip_mask->ip4src == IPV4_ALL_MASK) {
			fkeys->addrs.v4addrs.src = ip_spec->ip4src;
			new_fltr->ntuple_flags |= BNXT_NTUPLE_MATCH_SRC_IP;
		} else if (ip_mask->ip4src) {
			goto ntuple_err;
		}
		if (ip_mask->ip4dst == IPV4_ALL_MASK) {
			fkeys->addrs.v4addrs.dst = ip_spec->ip4dst;
			new_fltr->ntuple_flags |= BNXT_NTUPLE_MATCH_DST_IP;
		} else if (ip_mask->ip4dst) {
			goto ntuple_err;
		}

		if (ip_mask->psrc == L4_PORT_ALL_MASK) {
			fkeys->ports.src = ip_spec->psrc;
			new_fltr->ntuple_flags |= BNXT_NTUPLE_MATCH_SRC_PORT;
		} else if (ip_mask->psrc) {
			goto ntuple_err;
		}
		if (ip_mask->pdst == L4_PORT_ALL_MASK) {
			fkeys->ports.dst = ip_spec->pdst;
			new_fltr->ntuple_flags |= BNXT_NTUPLE_MATCH_DST_PORT;
		} else if (ip_mask->pdst) {
			goto ntuple_err;
		}
		break;
	}
	case TCP_V6_FLOW:
	case UDP_V6_FLOW: {
		struct ethtool_tcpip6_spec *ip_spec = &fs->h_u.tcp_ip6_spec;
		struct ethtool_tcpip6_spec *ip_mask = &fs->m_u.tcp_ip6_spec;

		fkeys->basic.ip_proto = IPPROTO_TCP;
		if (flow_type == UDP_V6_FLOW)
			fkeys->basic.ip_proto = IPPROTO_UDP;
		fkeys->basic.n_proto = htons(ETH_P_IPV6);

		if (ipv6_mask_is_full(ip_mask->ip6src)) {
			fkeys->addrs.v6addrs.src =
				*(struct in6_addr *)&ip_spec->ip6src;
			new_fltr->ntuple_flags |= BNXT_NTUPLE_MATCH_SRC_IP;
		} else if (!ipv6_mask_is_zero(ip_mask->ip6src)) {
			goto ntuple_err;
		}
		if (ipv6_mask_is_full(ip_mask->ip6dst)) {
			fkeys->addrs.v6addrs.dst =
				*(struct in6_addr *)&ip_spec->ip6dst;
			new_fltr->ntuple_flags |= BNXT_NTUPLE_MATCH_DST_IP;
		} else if (!ipv6_mask_is_zero(ip_mask->ip6dst)) {
			goto ntuple_err;
		}

		if (ip_mask->psrc == L4_PORT_ALL_MASK) {
			fkeys->ports.src = ip_spec->psrc;
			new_fltr->ntuple_flags |= BNXT_NTUPLE_MATCH_SRC_PORT;
		} else if (ip_mask->psrc) {
			goto ntuple_err;
		}
		if (ip_mask->pdst == L4_PORT_ALL_MASK) {
			fkeys->ports.dst = ip_spec->pdst;
			new_fltr->ntuple_flags |= BNXT_NTUPLE_MATCH_DST_PORT;
		} else if (ip_mask->pdst) {
			goto ntuple_err;
		}
		break;
	}
	default:
		rc = -EOPNOTSUPP;
		goto ntuple_err;
	}
	if (!new_fltr->ntuple_flags)
		goto ntuple_err;

	idx = bnxt_get_ntp_filter_idx(bp, fkeys, NULL);
	rcu_read_lock();
	fltr = bnxt_lookup_ntp_filter_from_idx(bp, new_fltr, idx);
	if (fltr) {
		rcu_read_unlock();
		rc = -EEXIST;
		goto ntuple_err;
	}
	rcu_read_unlock();

	new_fltr->base.rxq = ring;
	new_fltr->base.flags = BNXT_ACT_NO_AGING;
	__set_bit(BNXT_FLTR_VALID, &new_fltr->base.state);
	rc = bnxt_insert_ntp_filter(bp, new_fltr, idx);
	if (!rc) {
		rc = bnxt_hwrm_cfa_ntuple_filter_alloc(bp, new_fltr);
		if (rc) {
			bnxt_del_ntp_filter(bp, new_fltr);
			return rc;
		}
		fs->location = new_fltr->base.sw_id;
		return 0;
	}

ntuple_err:
	atomic_dec(&l2_fltr->refcnt);
	kfree(new_fltr);
	return rc;
}

static int bnxt_srxclsrlins(struct bnxt *bp, struct ethtool_rxnfc *cmd)
{
	struct ethtool_rx_flow_spec *fs = &cmd->fs;
	u32 ring, flow_type;
	int rc;
	u8 vf;

	if (!netif_running(bp->dev))
		return -EAGAIN;
	if (!(bp->flags & BNXT_FLAG_RFS))
		return -EPERM;
	if (fs->location != RX_CLS_LOC_ANY)
		return -EINVAL;

	ring = ethtool_get_flow_spec_ring(fs->ring_cookie);
	vf = ethtool_get_flow_spec_ring_vf(fs->ring_cookie);
	if (BNXT_VF(bp) && vf)
		return -EINVAL;
	if (BNXT_PF(bp) && vf > bp->pf.active_vfs)
		return -EINVAL;
	if (!vf && ring >= bp->rx_nr_rings)
		return -EINVAL;

	flow_type = fs->flow_type;
	if (flow_type & (FLOW_MAC_EXT | FLOW_RSS))
		return -EINVAL;
	flow_type &= ~FLOW_EXT;
	if (flow_type == ETHER_FLOW)
		rc = -EOPNOTSUPP;
	else
		rc = bnxt_add_ntuple_cls_rule(bp, fs);
	return rc;
}

static int bnxt_srxclsrldel(struct bnxt *bp, struct ethtool_rxnfc *cmd)
{
	struct ethtool_rx_flow_spec *fs = &cmd->fs;
	struct bnxt_filter_base *fltr_base;

	rcu_read_lock();
	fltr_base = bnxt_get_one_fltr_rcu(bp, bp->ntp_fltr_hash_tbl,
					  BNXT_NTP_FLTR_HASH_SIZE,
					  fs->location);
	if (fltr_base) {
		struct bnxt_ntuple_filter *fltr;

		fltr = container_of(fltr_base, struct bnxt_ntuple_filter, base);
		rcu_read_unlock();
		if (!(fltr->base.flags & BNXT_ACT_NO_AGING))
			return -EINVAL;
		bnxt_hwrm_cfa_ntuple_filter_free(bp, fltr);
		bnxt_del_ntp_filter(bp, fltr);
		return 0;
	}

	rcu_read_unlock();
	return -ENOENT;
}

static u64 get_ethtool_ipv4_rss(struct bnxt *bp)
{
@@ -1265,14 +1514,13 @@ static int bnxt_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd,
	int rc = 0;

	switch (cmd->cmd) {
#ifdef CONFIG_RFS_ACCEL
	case ETHTOOL_GRXRINGS:
		cmd->data = bp->rx_nr_rings;
		break;

	case ETHTOOL_GRXCLSRLCNT:
		cmd->rule_cnt = bp->ntp_fltr_count;
		cmd->data = BNXT_NTP_FLTR_MAX_FLTR;
		cmd->data = BNXT_NTP_FLTR_MAX_FLTR | RX_CLS_LOC_SPECIAL;
		break;

	case ETHTOOL_GRXCLSRLALL:
@@ -1282,7 +1530,6 @@ static int bnxt_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd,
	case ETHTOOL_GRXCLSRULE:
		rc = bnxt_grxclsrule(bp, cmd);
		break;
#endif

	case ETHTOOL_GRXFH:
		rc = bnxt_grxfh(bp, cmd);
@@ -1306,6 +1553,14 @@ static int bnxt_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd)
		rc = bnxt_srxfh(bp, cmd);
		break;

	case ETHTOOL_SRXCLSRLINS:
		rc = bnxt_srxclsrlins(bp, cmd);
		break;

	case ETHTOOL_SRXCLSRLDEL:
		rc = bnxt_srxclsrldel(bp, cmd);
		break;

	default:
		rc = -EOPNOTSUPP;
		break;