Commit b37a1bae authored by Steen Hegelund's avatar Steen Hegelund Committed by David S. Miller

net: sparx5: add mactable support

This adds the Sparx5 MAC tables: listening for MAC table updates and
updating on request.
Signed-off-by: default avatarSteen Hegelund <steen.hegelund@microchip.com>
Signed-off-by: default avatarBjarni Jonasson <bjarni.jonasson@microchip.com>
Signed-off-by: default avatarLars Povlsen <lars.povlsen@microchip.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 946e7fd5
......@@ -6,4 +6,4 @@
obj-$(CONFIG_SPARX5_SWITCH) += sparx5-switch.o
sparx5-switch-objs := sparx5_main.o sparx5_packet.o \
sparx5_netdev.o sparx5_phylink.o sparx5_port.o
sparx5_netdev.o sparx5_phylink.o sparx5_port.o sparx5_mactable.o
This diff is collapsed.
......@@ -558,6 +558,8 @@ static void sparx5_board_init(struct sparx5 *sparx5)
static int sparx5_start(struct sparx5 *sparx5)
{
u8 broadcast[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
char queue_name[32];
u32 idx;
int err;
......@@ -589,12 +591,29 @@ static int sparx5_start(struct sparx5 *sparx5)
ANA_CL_FILTER_CTRL_FORCE_FCS_UPDATE_ENA,
sparx5, ANA_CL_FILTER_CTRL(idx));
/* MAC/VLAN support to be added in later patches */
/* Init MAC table, ageing */
sparx5_mact_init(sparx5);
/* VLAN support to be added in later patches */
/* Add host mode BC address (points only to CPU) */
sparx5_mact_learn(sparx5, PGID_CPU, broadcast, NULL_VID);
/* Enable queue limitation watermarks */
sparx5_qlim_set(sparx5);
/* Resource calendar support to be added in later patches */
/* Init mact_sw struct */
mutex_init(&sparx5->mact_lock);
INIT_LIST_HEAD(&sparx5->mact_entries);
snprintf(queue_name, sizeof(queue_name), "%s-mact",
dev_name(sparx5->dev));
sparx5->mact_queue = create_singlethread_workqueue(queue_name);
INIT_DELAYED_WORK(&sparx5->mact_work, sparx5_mact_pull_work);
queue_delayed_work(sparx5->mact_queue, &sparx5->mact_work,
SPX5_MACT_PULL_DELAY);
err = sparx5_register_netdevs(sparx5);
if (err)
return err;
......
......@@ -135,7 +135,14 @@ struct sparx5 {
/* port structures are in net device */
struct sparx5_port *ports[SPX5_PORTS];
enum sparx5_core_clockfreq coreclock;
/* Switch state */
u8 base_mac[ETH_ALEN];
/* SW MAC table */
struct list_head mact_entries;
/* mac table list (mact_entries) mutex */
struct mutex mact_lock;
struct delayed_work mact_work;
struct workqueue_struct *mact_queue;
/* Board specifics */
bool sd_sgpio_remapping;
/* Register based inj/xtr */
......@@ -148,6 +155,25 @@ int sparx5_port_xmit_impl(struct sk_buff *skb, struct net_device *dev);
int sparx5_manual_injection_mode(struct sparx5 *sparx5);
void sparx5_port_inj_timer_setup(struct sparx5_port *port);
/* sparx5_mactable.c */
void sparx5_mact_pull_work(struct work_struct *work);
int sparx5_mact_learn(struct sparx5 *sparx5, int port,
const unsigned char mac[ETH_ALEN], u16 vid);
bool sparx5_mact_getnext(struct sparx5 *sparx5,
unsigned char mac[ETH_ALEN], u16 *vid, u32 *pcfg2);
int sparx5_mact_forget(struct sparx5 *sparx5,
const unsigned char mac[ETH_ALEN], u16 vid);
int sparx5_add_mact_entry(struct sparx5 *sparx5,
struct sparx5_port *port,
const unsigned char *addr, u16 vid);
int sparx5_del_mact_entry(struct sparx5 *sparx5,
const unsigned char *addr,
u16 vid);
int sparx5_mc_sync(struct net_device *dev, const unsigned char *addr);
int sparx5_mc_unsync(struct net_device *dev, const unsigned char *addr);
void sparx5_set_ageing(struct sparx5 *sparx5, int msecs);
void sparx5_mact_init(struct sparx5 *sparx5);
/* sparx5_netdev.c */
bool sparx5_netdevice_check(const struct net_device *dev);
struct net_device *sparx5_create_netdev(struct sparx5 *sparx5, u32 portno);
......
......@@ -132,17 +132,37 @@ static int sparx5_port_get_phys_port_name(struct net_device *dev,
static int sparx5_set_mac_address(struct net_device *dev, void *p)
{
struct sparx5_port *port = netdev_priv(dev);
struct sparx5 *sparx5 = port->sparx5;
const struct sockaddr *addr = p;
if (!is_valid_ether_addr(addr->sa_data))
return -EADDRNOTAVAIL;
/* Remove current */
sparx5_mact_forget(sparx5, dev->dev_addr, port->pvid);
/* Add new */
sparx5_mact_learn(sparx5, PGID_CPU, addr->sa_data, port->pvid);
/* Record the address */
ether_addr_copy(dev->dev_addr, addr->sa_data);
return 0;
}
static int sparx5_get_port_parent_id(struct net_device *dev,
struct netdev_phys_item_id *ppid)
{
struct sparx5_port *sparx5_port = netdev_priv(dev);
struct sparx5 *sparx5 = sparx5_port->sparx5;
ppid->id_len = sizeof(sparx5->base_mac);
memcpy(&ppid->id, &sparx5->base_mac, ppid->id_len);
return 0;
}
static const struct net_device_ops sparx5_port_netdev_ops = {
.ndo_open = sparx5_port_open,
.ndo_stop = sparx5_port_stop,
......@@ -150,6 +170,7 @@ static const struct net_device_ops sparx5_port_netdev_ops = {
.ndo_get_phys_port_name = sparx5_port_get_phys_port_name,
.ndo_set_mac_address = sparx5_set_mac_address,
.ndo_validate_addr = eth_validate_addr,
.ndo_get_port_parent_id = sparx5_get_port_parent_id,
};
bool sparx5_netdevice_check(const struct net_device *dev)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment