470 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			470 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
// SPDX-License-Identifier: GPL-2.0
 | 
						|
/* Texas Instruments ICSSG Ethernet Driver
 | 
						|
 *
 | 
						|
 * Copyright (C) 2018-2022 Texas Instruments Incorporated - https://www.ti.com/
 | 
						|
 *
 | 
						|
 */
 | 
						|
 | 
						|
#include <linux/etherdevice.h>
 | 
						|
#include <linux/types.h>
 | 
						|
#include <linux/regmap.h>
 | 
						|
 | 
						|
#include "icssg_prueth.h"
 | 
						|
 | 
						|
#define ICSSG_NUM_CLASSIFIERS	16
 | 
						|
#define ICSSG_NUM_FT1_SLOTS	8
 | 
						|
#define ICSSG_NUM_FT3_SLOTS	16
 | 
						|
 | 
						|
#define ICSSG_NUM_CLASSIFIERS_IN_USE	5
 | 
						|
 | 
						|
/* Filter 1 - FT1 */
 | 
						|
#define FT1_NUM_SLOTS	8
 | 
						|
#define FT1_SLOT_SIZE	0x10	/* bytes */
 | 
						|
 | 
						|
/* offsets from FT1 slot base i.e. slot 1 start */
 | 
						|
#define FT1_DA0		0x0
 | 
						|
#define FT1_DA1		0x4
 | 
						|
#define FT1_DA0_MASK	0x8
 | 
						|
#define FT1_DA1_MASK	0xc
 | 
						|
 | 
						|
#define FT1_N_REG(slize, n, reg)	\
 | 
						|
	(offs[slice].ft1_slot_base + FT1_SLOT_SIZE * (n) + (reg))
 | 
						|
 | 
						|
#define FT1_LEN_MASK		GENMASK(19, 16)
 | 
						|
#define FT1_LEN_SHIFT		16
 | 
						|
#define FT1_LEN(len)		(((len) << FT1_LEN_SHIFT) & FT1_LEN_MASK)
 | 
						|
#define FT1_START_MASK		GENMASK(14, 0)
 | 
						|
#define FT1_START(start)	((start) & FT1_START_MASK)
 | 
						|
#define FT1_MATCH_SLOT(n)	(GENMASK(23, 16) & (BIT(n) << 16))
 | 
						|
 | 
						|
/* FT1 config type */
 | 
						|
enum ft1_cfg_type {
 | 
						|
	FT1_CFG_TYPE_DISABLED = 0,
 | 
						|
	FT1_CFG_TYPE_EQ,
 | 
						|
	FT1_CFG_TYPE_GT,
 | 
						|
	FT1_CFG_TYPE_LT,
 | 
						|
};
 | 
						|
 | 
						|
#define FT1_CFG_SHIFT(n)	(2 * (n))
 | 
						|
#define FT1_CFG_MASK(n)		(0x3 << FT1_CFG_SHIFT((n)))
 | 
						|
 | 
						|
/* Filter 3 -  FT3 */
 | 
						|
#define FT3_NUM_SLOTS	16
 | 
						|
#define FT3_SLOT_SIZE	0x20	/* bytes */
 | 
						|
 | 
						|
/* offsets from FT3 slot n's base */
 | 
						|
#define FT3_START		0
 | 
						|
#define FT3_START_AUTO		0x4
 | 
						|
#define FT3_START_OFFSET	0x8
 | 
						|
#define FT3_JUMP_OFFSET		0xc
 | 
						|
#define FT3_LEN			0x10
 | 
						|
#define FT3_CFG			0x14
 | 
						|
#define FT3_T			0x18
 | 
						|
#define FT3_T_MASK		0x1c
 | 
						|
 | 
						|
#define FT3_N_REG(slize, n, reg)	\
 | 
						|
	(offs[slice].ft3_slot_base + FT3_SLOT_SIZE * (n) + (reg))
 | 
						|
 | 
						|
/* offsets from rx_class n's base */
 | 
						|
#define RX_CLASS_AND_EN		0
 | 
						|
#define RX_CLASS_OR_EN		0x4
 | 
						|
#define RX_CLASS_NUM_SLOTS	16
 | 
						|
#define RX_CLASS_EN_SIZE	0x8	/* bytes */
 | 
						|
 | 
						|
#define RX_CLASS_N_REG(slice, n, reg)	\
 | 
						|
	(offs[slice].rx_class_base + RX_CLASS_EN_SIZE * (n) + (reg))
 | 
						|
 | 
						|
/* RX Class Gates */
 | 
						|
#define RX_CLASS_GATES_SIZE	0x4	/* bytes */
 | 
						|
 | 
						|
#define RX_CLASS_GATES_N_REG(slice, n)	\
 | 
						|
	(offs[slice].rx_class_gates_base + RX_CLASS_GATES_SIZE * (n))
 | 
						|
 | 
						|
#define RX_CLASS_GATES_ALLOW_MASK	BIT(6)
 | 
						|
#define RX_CLASS_GATES_RAW_MASK		BIT(5)
 | 
						|
#define RX_CLASS_GATES_PHASE_MASK	BIT(4)
 | 
						|
 | 
						|
/* RX Class traffic data matching bits */
 | 
						|
#define RX_CLASS_FT_UC				BIT(31)
 | 
						|
#define RX_CLASS_FT_MC			BIT(30)
 | 
						|
#define RX_CLASS_FT_BC			BIT(29)
 | 
						|
#define RX_CLASS_FT_FW			BIT(28)
 | 
						|
#define RX_CLASS_FT_RCV			BIT(27)
 | 
						|
#define RX_CLASS_FT_VLAN		BIT(26)
 | 
						|
#define RX_CLASS_FT_DA_P		BIT(25)
 | 
						|
#define RX_CLASS_FT_DA_I		BIT(24)
 | 
						|
#define RX_CLASS_FT_FT1_MATCH_MASK	GENMASK(23, 16)
 | 
						|
#define RX_CLASS_FT_FT1_MATCH_SHIFT	16
 | 
						|
#define RX_CLASS_FT_FT3_MATCH_MASK	GENMASK(15, 0)
 | 
						|
#define RX_CLASS_FT_FT3_MATCH_SHIFT	0
 | 
						|
 | 
						|
#define RX_CLASS_FT_FT1_MATCH(slot)	\
 | 
						|
	((BIT(slot) << RX_CLASS_FT_FT1_MATCH_SHIFT) & \
 | 
						|
	RX_CLASS_FT_FT1_MATCH_MASK)
 | 
						|
 | 
						|
/* RX class type */
 | 
						|
enum rx_class_sel_type {
 | 
						|
	RX_CLASS_SEL_TYPE_OR = 0,
 | 
						|
	RX_CLASS_SEL_TYPE_AND = 1,
 | 
						|
	RX_CLASS_SEL_TYPE_OR_AND_AND = 2,
 | 
						|
	RX_CLASS_SEL_TYPE_OR_OR_AND = 3,
 | 
						|
};
 | 
						|
 | 
						|
#define FT1_CFG_SHIFT(n)	(2 * (n))
 | 
						|
#define FT1_CFG_MASK(n)		(0x3 << FT1_CFG_SHIFT((n)))
 | 
						|
 | 
						|
#define RX_CLASS_SEL_SHIFT(n)	(2 * (n))
 | 
						|
#define RX_CLASS_SEL_MASK(n)	(0x3 << RX_CLASS_SEL_SHIFT((n)))
 | 
						|
 | 
						|
#define ICSSG_CFG_OFFSET	0
 | 
						|
#define MAC_INTERFACE_0		0x18
 | 
						|
#define MAC_INTERFACE_1		0x1c
 | 
						|
 | 
						|
#define ICSSG_CFG_RX_L2_G_EN	BIT(2)
 | 
						|
 | 
						|
/* These are register offsets per PRU */
 | 
						|
struct miig_rt_offsets {
 | 
						|
	u32 mac0;
 | 
						|
	u32 mac1;
 | 
						|
	u32 ft1_start_len;
 | 
						|
	u32 ft1_cfg;
 | 
						|
	u32 ft1_slot_base;
 | 
						|
	u32 ft3_slot_base;
 | 
						|
	u32 ft3_p_base;
 | 
						|
	u32 ft_rx_ptr;
 | 
						|
	u32 rx_class_base;
 | 
						|
	u32 rx_class_cfg1;
 | 
						|
	u32 rx_class_cfg2;
 | 
						|
	u32 rx_class_gates_base;
 | 
						|
	u32 rx_green;
 | 
						|
	u32 rx_rate_cfg_base;
 | 
						|
	u32 rx_rate_src_sel0;
 | 
						|
	u32 rx_rate_src_sel1;
 | 
						|
	u32 tx_rate_cfg_base;
 | 
						|
	u32 stat_base;
 | 
						|
	u32 tx_hsr_tag;
 | 
						|
	u32 tx_hsr_seq;
 | 
						|
	u32 tx_vlan_type;
 | 
						|
	u32 tx_vlan_ins;
 | 
						|
};
 | 
						|
 | 
						|
/* These are the offset values for miig_rt_offsets registers */
 | 
						|
static const struct miig_rt_offsets offs[] = {
 | 
						|
	/* PRU0 */
 | 
						|
	{
 | 
						|
		0x8,
 | 
						|
		0xc,
 | 
						|
		0x80,
 | 
						|
		0x84,
 | 
						|
		0x88,
 | 
						|
		0x108,
 | 
						|
		0x308,
 | 
						|
		0x408,
 | 
						|
		0x40c,
 | 
						|
		0x48c,
 | 
						|
		0x490,
 | 
						|
		0x494,
 | 
						|
		0x4d4,
 | 
						|
		0x4e4,
 | 
						|
		0x504,
 | 
						|
		0x508,
 | 
						|
		0x50c,
 | 
						|
		0x54c,
 | 
						|
		0x63c,
 | 
						|
		0x640,
 | 
						|
		0x644,
 | 
						|
		0x648,
 | 
						|
	},
 | 
						|
	/* PRU1 */
 | 
						|
	{
 | 
						|
		0x10,
 | 
						|
		0x14,
 | 
						|
		0x64c,
 | 
						|
		0x650,
 | 
						|
		0x654,
 | 
						|
		0x6d4,
 | 
						|
		0x8d4,
 | 
						|
		0x9d4,
 | 
						|
		0x9d8,
 | 
						|
		0xa58,
 | 
						|
		0xa5c,
 | 
						|
		0xa60,
 | 
						|
		0xaa0,
 | 
						|
		0xab0,
 | 
						|
		0xad0,
 | 
						|
		0xad4,
 | 
						|
		0xad8,
 | 
						|
		0xb18,
 | 
						|
		0xc08,
 | 
						|
		0xc0c,
 | 
						|
		0xc10,
 | 
						|
		0xc14,
 | 
						|
	},
 | 
						|
};
 | 
						|
 | 
						|
static void rx_class_ft1_set_start_len(struct regmap *miig_rt, int slice,
 | 
						|
				       u16 start, u8 len)
 | 
						|
{
 | 
						|
	u32 offset, val;
 | 
						|
 | 
						|
	offset = offs[slice].ft1_start_len;
 | 
						|
	val = FT1_LEN(len) | FT1_START(start);
 | 
						|
	regmap_write(miig_rt, offset, val);
 | 
						|
}
 | 
						|
 | 
						|
static void rx_class_ft1_set_da(struct regmap *miig_rt, int slice,
 | 
						|
				int n, const u8 *addr)
 | 
						|
{
 | 
						|
	u32 offset;
 | 
						|
 | 
						|
	offset = FT1_N_REG(slice, n, FT1_DA0);
 | 
						|
	regmap_write(miig_rt, offset, (u32)(addr[0] | addr[1] << 8 |
 | 
						|
		     addr[2] << 16 | addr[3] << 24));
 | 
						|
	offset = FT1_N_REG(slice, n, FT1_DA1);
 | 
						|
	regmap_write(miig_rt, offset, (u32)(addr[4] | addr[5] << 8));
 | 
						|
}
 | 
						|
 | 
						|
static void rx_class_ft1_set_da_mask(struct regmap *miig_rt, int slice,
 | 
						|
				     int n, const u8 *addr)
 | 
						|
{
 | 
						|
	u32 offset;
 | 
						|
 | 
						|
	offset = FT1_N_REG(slice, n, FT1_DA0_MASK);
 | 
						|
	regmap_write(miig_rt, offset, (u32)(addr[0] | addr[1] << 8 |
 | 
						|
		     addr[2] << 16 | addr[3] << 24));
 | 
						|
	offset = FT1_N_REG(slice, n, FT1_DA1_MASK);
 | 
						|
	regmap_write(miig_rt, offset, (u32)(addr[4] | addr[5] << 8));
 | 
						|
}
 | 
						|
 | 
						|
static void rx_class_ft1_cfg_set_type(struct regmap *miig_rt, int slice, int n,
 | 
						|
				      enum ft1_cfg_type type)
 | 
						|
{
 | 
						|
	u32 offset;
 | 
						|
 | 
						|
	offset = offs[slice].ft1_cfg;
 | 
						|
	regmap_update_bits(miig_rt, offset, FT1_CFG_MASK(n),
 | 
						|
			   type << FT1_CFG_SHIFT(n));
 | 
						|
}
 | 
						|
 | 
						|
static void rx_class_sel_set_type(struct regmap *miig_rt, int slice, int n,
 | 
						|
				  enum rx_class_sel_type type)
 | 
						|
{
 | 
						|
	u32 offset;
 | 
						|
 | 
						|
	offset = offs[slice].rx_class_cfg1;
 | 
						|
	regmap_update_bits(miig_rt, offset, RX_CLASS_SEL_MASK(n),
 | 
						|
			   type << RX_CLASS_SEL_SHIFT(n));
 | 
						|
}
 | 
						|
 | 
						|
static void rx_class_set_and(struct regmap *miig_rt, int slice, int n,
 | 
						|
			     u32 data)
 | 
						|
{
 | 
						|
	u32 offset;
 | 
						|
 | 
						|
	offset = RX_CLASS_N_REG(slice, n, RX_CLASS_AND_EN);
 | 
						|
	regmap_write(miig_rt, offset, data);
 | 
						|
}
 | 
						|
 | 
						|
static void rx_class_set_or(struct regmap *miig_rt, int slice, int n,
 | 
						|
			    u32 data)
 | 
						|
{
 | 
						|
	u32 offset;
 | 
						|
 | 
						|
	offset = RX_CLASS_N_REG(slice, n, RX_CLASS_OR_EN);
 | 
						|
	regmap_write(miig_rt, offset, data);
 | 
						|
}
 | 
						|
 | 
						|
static u32 rx_class_get_or(struct regmap *miig_rt, int slice, int n)
 | 
						|
{
 | 
						|
	u32 offset, val;
 | 
						|
 | 
						|
	offset = RX_CLASS_N_REG(slice, n, RX_CLASS_OR_EN);
 | 
						|
	regmap_read(miig_rt, offset, &val);
 | 
						|
 | 
						|
	return val;
 | 
						|
}
 | 
						|
 | 
						|
void icssg_class_set_host_mac_addr(struct regmap *miig_rt, const u8 *mac)
 | 
						|
{
 | 
						|
	regmap_write(miig_rt, MAC_INTERFACE_0, (u32)(mac[0] | mac[1] << 8 |
 | 
						|
		     mac[2] << 16 | mac[3] << 24));
 | 
						|
	regmap_write(miig_rt, MAC_INTERFACE_1, (u32)(mac[4] | mac[5] << 8));
 | 
						|
}
 | 
						|
EXPORT_SYMBOL_GPL(icssg_class_set_host_mac_addr);
 | 
						|
 | 
						|
void icssg_class_set_mac_addr(struct regmap *miig_rt, int slice, u8 *mac)
 | 
						|
{
 | 
						|
	regmap_write(miig_rt, offs[slice].mac0, (u32)(mac[0] | mac[1] << 8 |
 | 
						|
		     mac[2] << 16 | mac[3] << 24));
 | 
						|
	regmap_write(miig_rt, offs[slice].mac1, (u32)(mac[4] | mac[5] << 8));
 | 
						|
}
 | 
						|
EXPORT_SYMBOL_GPL(icssg_class_set_mac_addr);
 | 
						|
 | 
						|
static void icssg_class_ft1_add_mcast(struct regmap *miig_rt, int slice,
 | 
						|
				      int slot, const u8 *addr, const u8 *mask)
 | 
						|
{
 | 
						|
	u32 val;
 | 
						|
	int i;
 | 
						|
 | 
						|
	WARN(slot >= FT1_NUM_SLOTS, "invalid slot: %d\n", slot);
 | 
						|
 | 
						|
	rx_class_ft1_set_da(miig_rt, slice, slot, addr);
 | 
						|
	rx_class_ft1_set_da_mask(miig_rt, slice, slot, mask);
 | 
						|
	rx_class_ft1_cfg_set_type(miig_rt, slice, slot, FT1_CFG_TYPE_EQ);
 | 
						|
 | 
						|
	/* Enable the FT1 slot in OR enable for all classifiers */
 | 
						|
	for (i = 0; i < ICSSG_NUM_CLASSIFIERS_IN_USE; i++) {
 | 
						|
		val = rx_class_get_or(miig_rt, slice, i);
 | 
						|
		val |= RX_CLASS_FT_FT1_MATCH(slot);
 | 
						|
		rx_class_set_or(miig_rt, slice, i, val);
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
/* disable all RX traffic */
 | 
						|
void icssg_class_disable(struct regmap *miig_rt, int slice)
 | 
						|
{
 | 
						|
	u32 data, offset;
 | 
						|
	int n;
 | 
						|
 | 
						|
	/* Enable RX_L2_G */
 | 
						|
	regmap_update_bits(miig_rt, ICSSG_CFG_OFFSET, ICSSG_CFG_RX_L2_G_EN,
 | 
						|
			   ICSSG_CFG_RX_L2_G_EN);
 | 
						|
 | 
						|
	for (n = 0; n < ICSSG_NUM_CLASSIFIERS; n++) {
 | 
						|
		/* AND_EN = 0 */
 | 
						|
		rx_class_set_and(miig_rt, slice, n, 0);
 | 
						|
		/* OR_EN = 0 */
 | 
						|
		rx_class_set_or(miig_rt, slice, n, 0);
 | 
						|
 | 
						|
		/* set CFG1 to OR */
 | 
						|
		rx_class_sel_set_type(miig_rt, slice, n, RX_CLASS_SEL_TYPE_OR);
 | 
						|
 | 
						|
		/* configure gate */
 | 
						|
		offset = RX_CLASS_GATES_N_REG(slice, n);
 | 
						|
		regmap_read(miig_rt, offset, &data);
 | 
						|
		/* clear class_raw so we go through filters */
 | 
						|
		data &= ~RX_CLASS_GATES_RAW_MASK;
 | 
						|
		/* set allow and phase mask */
 | 
						|
		data |= RX_CLASS_GATES_ALLOW_MASK | RX_CLASS_GATES_PHASE_MASK;
 | 
						|
		regmap_write(miig_rt, offset, data);
 | 
						|
	}
 | 
						|
 | 
						|
	/* FT1 Disabled */
 | 
						|
	for (n = 0; n < ICSSG_NUM_FT1_SLOTS; n++) {
 | 
						|
		const u8 addr[] = { 0, 0, 0, 0, 0, 0, };
 | 
						|
 | 
						|
		rx_class_ft1_cfg_set_type(miig_rt, slice, n,
 | 
						|
					  FT1_CFG_TYPE_DISABLED);
 | 
						|
		rx_class_ft1_set_da(miig_rt, slice, n, addr);
 | 
						|
		rx_class_ft1_set_da_mask(miig_rt, slice, n, addr);
 | 
						|
	}
 | 
						|
 | 
						|
	/* clear CFG2 */
 | 
						|
	regmap_write(miig_rt, offs[slice].rx_class_cfg2, 0);
 | 
						|
}
 | 
						|
EXPORT_SYMBOL_GPL(icssg_class_disable);
 | 
						|
 | 
						|
void icssg_class_default(struct regmap *miig_rt, int slice, bool allmulti,
 | 
						|
			 bool is_sr1)
 | 
						|
{
 | 
						|
	int num_classifiers = is_sr1 ? ICSSG_NUM_CLASSIFIERS_IN_USE : 1;
 | 
						|
	u32 data;
 | 
						|
	int n;
 | 
						|
 | 
						|
	/* defaults */
 | 
						|
	icssg_class_disable(miig_rt, slice);
 | 
						|
 | 
						|
	/* Setup Classifier */
 | 
						|
	for (n = 0; n < num_classifiers; n++) {
 | 
						|
		/* match on Broadcast or MAC_PRU address */
 | 
						|
		data = RX_CLASS_FT_BC | RX_CLASS_FT_DA_P;
 | 
						|
 | 
						|
		/* multicast */
 | 
						|
		if (allmulti)
 | 
						|
			data |= RX_CLASS_FT_MC;
 | 
						|
 | 
						|
		rx_class_set_or(miig_rt, slice, n, data);
 | 
						|
 | 
						|
		/* set CFG1 for OR_OR_AND for classifier */
 | 
						|
		rx_class_sel_set_type(miig_rt, slice, n,
 | 
						|
				      RX_CLASS_SEL_TYPE_OR_OR_AND);
 | 
						|
	}
 | 
						|
 | 
						|
	/* clear CFG2 */
 | 
						|
	regmap_write(miig_rt, offs[slice].rx_class_cfg2, 0);
 | 
						|
}
 | 
						|
EXPORT_SYMBOL_GPL(icssg_class_default);
 | 
						|
 | 
						|
void icssg_class_promiscuous_sr1(struct regmap *miig_rt, int slice)
 | 
						|
{
 | 
						|
	u32 data, offset;
 | 
						|
	int n;
 | 
						|
 | 
						|
	/* defaults */
 | 
						|
	icssg_class_disable(miig_rt, slice);
 | 
						|
 | 
						|
	/* Setup Classifier */
 | 
						|
	for (n = 0; n < ICSSG_NUM_CLASSIFIERS_IN_USE; n++) {
 | 
						|
		/* set RAW_MASK to bypass filters */
 | 
						|
		offset = RX_CLASS_GATES_N_REG(slice, n);
 | 
						|
		regmap_read(miig_rt, offset, &data);
 | 
						|
		data |= RX_CLASS_GATES_RAW_MASK;
 | 
						|
		regmap_write(miig_rt, offset, data);
 | 
						|
	}
 | 
						|
}
 | 
						|
EXPORT_SYMBOL_GPL(icssg_class_promiscuous_sr1);
 | 
						|
 | 
						|
void icssg_class_add_mcast_sr1(struct regmap *miig_rt, int slice,
 | 
						|
			       struct net_device *ndev)
 | 
						|
{
 | 
						|
	u8 mask_addr[6] = { 0, 0, 0, 0, 0, 0xff };
 | 
						|
	struct netdev_hw_addr *ha;
 | 
						|
	int slot = 2;
 | 
						|
 | 
						|
	rx_class_ft1_set_start_len(miig_rt, slice, 0, 6);
 | 
						|
	/* reserve first 2 slots for
 | 
						|
	 *	1) 01-80-C2-00-00-XX Known Service Ethernet Multicast addresses
 | 
						|
	 *	2) 01-00-5e-00-00-XX Local Network Control Block
 | 
						|
	 *			      (224.0.0.0 - 224.0.0.255  (224.0.0/24))
 | 
						|
	 */
 | 
						|
	icssg_class_ft1_add_mcast(miig_rt, slice, 0,
 | 
						|
				  eth_reserved_addr_base, mask_addr);
 | 
						|
	icssg_class_ft1_add_mcast(miig_rt, slice, 1,
 | 
						|
				  eth_ipv4_mcast_addr_base, mask_addr);
 | 
						|
	mask_addr[5] = 0;
 | 
						|
	netdev_for_each_mc_addr(ha, ndev) {
 | 
						|
		/* skip addresses matching reserved slots */
 | 
						|
		if (!memcmp(eth_reserved_addr_base, ha->addr, 5) ||
 | 
						|
		    !memcmp(eth_ipv4_mcast_addr_base, ha->addr, 5)) {
 | 
						|
			netdev_dbg(ndev, "mcast skip %pM\n", ha->addr);
 | 
						|
			continue;
 | 
						|
		}
 | 
						|
 | 
						|
		if (slot >= FT1_NUM_SLOTS) {
 | 
						|
			netdev_dbg(ndev,
 | 
						|
				   "can't add more than %d MC addresses, enabling allmulti\n",
 | 
						|
				   FT1_NUM_SLOTS);
 | 
						|
			icssg_class_default(miig_rt, slice, 1, true);
 | 
						|
			break;
 | 
						|
		}
 | 
						|
 | 
						|
		netdev_dbg(ndev, "mcast add %pM\n", ha->addr);
 | 
						|
		icssg_class_ft1_add_mcast(miig_rt, slice, slot,
 | 
						|
					  ha->addr, mask_addr);
 | 
						|
		slot++;
 | 
						|
	}
 | 
						|
}
 | 
						|
EXPORT_SYMBOL_GPL(icssg_class_add_mcast_sr1);
 | 
						|
 | 
						|
/* required for SAV check */
 | 
						|
void icssg_ft1_set_mac_addr(struct regmap *miig_rt, int slice, u8 *mac_addr)
 | 
						|
{
 | 
						|
	const u8 mask_addr[] = { 0, 0, 0, 0, 0, 0, };
 | 
						|
 | 
						|
	rx_class_ft1_set_start_len(miig_rt, slice, ETH_ALEN, ETH_ALEN);
 | 
						|
	rx_class_ft1_set_da(miig_rt, slice, 0, mac_addr);
 | 
						|
	rx_class_ft1_set_da_mask(miig_rt, slice, 0, mask_addr);
 | 
						|
	rx_class_ft1_cfg_set_type(miig_rt, slice, 0, FT1_CFG_TYPE_EQ);
 | 
						|
}
 | 
						|
EXPORT_SYMBOL_GPL(icssg_ft1_set_mac_addr);
 |