Commit a89df867 authored by Dmitry Bogdanov's avatar Dmitry Bogdanov Committed by David S. Miller
Browse files

net: atlantic: A0 ntuple filters



This patch adds support for ntuple filters on A0.

Signed-off-by: default avatarDmitry Bogdanov <dbogdanov@marvell.com>
Signed-off-by: default avatarMark Starovoytov <mstarovoitov@marvell.com>
Signed-off-by: default avatarIgor Russkikh <irusskikh@marvell.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent b98ffe6f
Loading
Loading
Loading
Loading
+88 −28
Original line number Diff line number Diff line
@@ -38,7 +38,9 @@
			NETIF_F_RXHASH |	     \
			NETIF_F_RXCSUM |	     \
			NETIF_F_SG |		     \
			NETIF_F_TSO,	  \
			NETIF_F_TSO |		     \
			NETIF_F_NTUPLE |	     \
			NETIF_F_HW_VLAN_CTAG_FILTER, \
	.hw_priv_flags = IFF_UNICAST_FLT,	     \
	.flow_control = true,			     \
	.mtu = HW_ATL_A0_MTU_JUMBO,		     \
@@ -330,6 +332,7 @@ static int hw_atl_a0_hw_mac_addr_set(struct aq_hw_s *self, u8 *mac_addr)
		err = -EINVAL;
		goto err_exit;
	}

	h = (mac_addr[0] << 8) | (mac_addr[1]);
	l = (mac_addr[2] << 24) | (mac_addr[3] << 16) |
	    (mac_addr[4] << 8) | mac_addr[5];
@@ -356,7 +359,6 @@ static int hw_atl_a0_hw_init(struct aq_hw_s *self, u8 *mac_addr)
	struct aq_nic_cfg_s *aq_nic_cfg = self->aq_nic_cfg;
	int err = 0;


	hw_atl_a0_hw_init_tx_path(self);
	hw_atl_a0_hw_init_rx_path(self);

@@ -885,6 +887,63 @@ static int hw_atl_a0_hw_ring_rx_stop(struct aq_hw_s *self,
	return aq_hw_err_from_flags(self);
}

static int hw_atl_a0_hw_fl3l4_clear(struct aq_hw_s *self,
				    struct aq_rx_filter_l3l4 *data)
{
	u8 location = data->location;

	if (!data->is_ipv6) {
		hw_atl_rpfl3l4_cmd_clear(self, location);
		hw_atl_rpf_l4_spd_set(self, 0U, location);
		hw_atl_rpf_l4_dpd_set(self, 0U, location);
		hw_atl_rpfl3l4_ipv4_src_addr_clear(self, location);
		hw_atl_rpfl3l4_ipv4_dest_addr_clear(self, location);
	} else {
		int i;

		for (i = 0; i < HW_ATL_RX_CNT_REG_ADDR_IPV6; ++i) {
			hw_atl_rpfl3l4_cmd_clear(self, location + i);
			hw_atl_rpf_l4_spd_set(self, 0U, location + i);
			hw_atl_rpf_l4_dpd_set(self, 0U, location + i);
		}
		hw_atl_rpfl3l4_ipv6_src_addr_clear(self, location);
		hw_atl_rpfl3l4_ipv6_dest_addr_clear(self, location);
	}

	return aq_hw_err_from_flags(self);
}

static int hw_atl_a0_hw_fl3l4_set(struct aq_hw_s *self,
				  struct aq_rx_filter_l3l4 *data)
{
	u8 location = data->location;

	hw_atl_a0_hw_fl3l4_clear(self, data);

	if (data->cmd) {
		if (!data->is_ipv6) {
			hw_atl_rpfl3l4_ipv4_dest_addr_set(self,
							  location,
							  data->ip_dst[0]);
			hw_atl_rpfl3l4_ipv4_src_addr_set(self,
							 location,
							 data->ip_src[0]);
		} else {
			hw_atl_rpfl3l4_ipv6_dest_addr_set(self,
							  location,
							  data->ip_dst);
			hw_atl_rpfl3l4_ipv6_src_addr_set(self,
							 location,
							 data->ip_src);
		}
	}
	hw_atl_rpf_l4_dpd_set(self, data->p_dst, location);
	hw_atl_rpf_l4_spd_set(self, data->p_src, location);
	hw_atl_rpfl3l4_cmd_set(self, location, data->cmd);

	return aq_hw_err_from_flags(self);
}

const struct aq_hw_ops hw_atl_ops_a0 = {
	.hw_soft_reset        = hw_atl_utils_soft_reset,
	.hw_prepare           = hw_atl_utils_initfw,
@@ -911,6 +970,7 @@ const struct aq_hw_ops hw_atl_ops_a0 = {
	.hw_ring_rx_init             = hw_atl_a0_hw_ring_rx_init,
	.hw_ring_tx_init             = hw_atl_a0_hw_ring_tx_init,
	.hw_packet_filter_set        = hw_atl_a0_hw_packet_filter_set,
	.hw_filter_l3l4_set          = hw_atl_a0_hw_fl3l4_set,
	.hw_multicast_list_set       = hw_atl_a0_hw_multicast_list_set,
	.hw_interrupt_moderation_set = hw_atl_a0_hw_interrupt_moderation_set,
	.hw_rss_set                  = hw_atl_a0_hw_rss_set,