brintos

brintos / linux-shallow public Read only

0
0
Text · 45.6 KiB · e548cd3 Raw
1919 lines · c
1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.02/* Copyright (c) 2019-2020 Marvell International Ltd. All rights reserved */3 4#include <linux/if_bridge.h>5#include <linux/if_vlan.h>6#include <linux/kernel.h>7#include <linux/module.h>8#include <linux/notifier.h>9#include <net/netevent.h>10#include <net/switchdev.h>11 12#include "prestera.h"13#include "prestera_hw.h"14#include "prestera_switchdev.h"15 16#define PRESTERA_VID_ALL (0xffff)17 18#define PRESTERA_DEFAULT_AGEING_TIME_MS 30000019#define PRESTERA_MAX_AGEING_TIME_MS 100000000020#define PRESTERA_MIN_AGEING_TIME_MS 3200021 22struct prestera_fdb_event_work {23	struct work_struct work;24	struct switchdev_notifier_fdb_info fdb_info;25	struct net_device *dev;26	unsigned long event;27};28 29struct prestera_switchdev {30	struct prestera_switch *sw;31	struct list_head bridge_list;32	bool bridge_8021q_exists;33	struct notifier_block swdev_nb_blk;34	struct notifier_block swdev_nb;35};36 37struct prestera_bridge {38	struct list_head head;39	struct net_device *dev;40	struct prestera_switchdev *swdev;41	struct list_head port_list;42	struct list_head br_mdb_entry_list;43	bool mrouter_exist;44	bool vlan_enabled;45	bool multicast_enabled;46	u16 bridge_id;47};48 49struct prestera_bridge_port {50	struct list_head head;51	struct net_device *dev;52	struct prestera_bridge *bridge;53	struct list_head vlan_list;54	struct list_head br_mdb_port_list;55	refcount_t ref_count;56	unsigned long flags;57	bool mrouter;58	u8 stp_state;59};60 61struct prestera_bridge_vlan {62	struct list_head head;63	struct list_head port_vlan_list;64	u16 vid;65};66 67struct prestera_port_vlan {68	struct list_head br_vlan_head;69	struct list_head port_head;70	struct prestera_port *port;71	struct prestera_bridge_port *br_port;72	u16 vid;73};74 75struct prestera_br_mdb_port {76	struct prestera_bridge_port *br_port;77	struct list_head br_mdb_port_node;78};79 80/* Software representation of MDB table. */81struct prestera_br_mdb_entry {82	struct prestera_bridge *bridge;83	struct prestera_mdb_entry *mdb;84	struct list_head br_mdb_port_list;85	struct list_head br_mdb_entry_node;86	bool enabled;87};88 89static struct workqueue_struct *swdev_wq;90 91static void prestera_bridge_port_put(struct prestera_bridge_port *br_port);92 93static int prestera_port_vid_stp_set(struct prestera_port *port, u16 vid,94				     u8 state);95 96static struct prestera_bridge *97prestera_bridge_find(const struct prestera_switch *sw,98		     const struct net_device *br_dev)99{100	struct prestera_bridge *bridge;101 102	list_for_each_entry(bridge, &sw->swdev->bridge_list, head)103		if (bridge->dev == br_dev)104			return bridge;105 106	return NULL;107}108 109static struct prestera_bridge_port *110__prestera_bridge_port_find(const struct prestera_bridge *bridge,111			    const struct net_device *brport_dev)112{113	struct prestera_bridge_port *br_port;114 115	list_for_each_entry(br_port, &bridge->port_list, head)116		if (br_port->dev == brport_dev)117			return br_port;118 119	return NULL;120}121 122static struct prestera_bridge_port *123prestera_bridge_port_find(struct prestera_switch *sw,124			  struct net_device *brport_dev)125{126	struct net_device *br_dev = netdev_master_upper_dev_get(brport_dev);127	struct prestera_bridge *bridge;128 129	if (!br_dev)130		return NULL;131 132	bridge = prestera_bridge_find(sw, br_dev);133	if (!bridge)134		return NULL;135 136	return __prestera_bridge_port_find(bridge, brport_dev);137}138 139static void140prestera_br_port_flags_reset(struct prestera_bridge_port *br_port,141			     struct prestera_port *port)142{143	prestera_port_uc_flood_set(port, false);144	prestera_port_mc_flood_set(port, false);145	prestera_port_learning_set(port, false);146	prestera_port_br_locked_set(port, false);147}148 149static int prestera_br_port_flags_set(struct prestera_bridge_port *br_port,150				      struct prestera_port *port)151{152	int err;153 154	err = prestera_port_uc_flood_set(port, br_port->flags & BR_FLOOD);155	if (err)156		goto err_out;157 158	err = prestera_port_mc_flood_set(port, br_port->flags & BR_MCAST_FLOOD);159	if (err)160		goto err_out;161 162	err = prestera_port_learning_set(port, br_port->flags & BR_LEARNING);163	if (err)164		goto err_out;165 166	err = prestera_port_br_locked_set(port,167					  br_port->flags & BR_PORT_LOCKED);168	if (err)169		goto err_out;170 171	return 0;172 173err_out:174	prestera_br_port_flags_reset(br_port, port);175	return err;176}177 178static struct prestera_bridge_vlan *179prestera_bridge_vlan_create(struct prestera_bridge_port *br_port, u16 vid)180{181	struct prestera_bridge_vlan *br_vlan;182 183	br_vlan = kzalloc(sizeof(*br_vlan), GFP_KERNEL);184	if (!br_vlan)185		return NULL;186 187	INIT_LIST_HEAD(&br_vlan->port_vlan_list);188	br_vlan->vid = vid;189	list_add(&br_vlan->head, &br_port->vlan_list);190 191	return br_vlan;192}193 194static void prestera_bridge_vlan_destroy(struct prestera_bridge_vlan *br_vlan)195{196	list_del(&br_vlan->head);197	WARN_ON(!list_empty(&br_vlan->port_vlan_list));198	kfree(br_vlan);199}200 201static struct prestera_bridge_vlan *202prestera_bridge_vlan_by_vid(struct prestera_bridge_port *br_port, u16 vid)203{204	struct prestera_bridge_vlan *br_vlan;205 206	list_for_each_entry(br_vlan, &br_port->vlan_list, head) {207		if (br_vlan->vid == vid)208			return br_vlan;209	}210 211	return NULL;212}213 214static int prestera_bridge_vlan_port_count(struct prestera_bridge *bridge,215					   u16 vid)216{217	struct prestera_bridge_port *br_port;218	struct prestera_bridge_vlan *br_vlan;219	int count = 0;220 221	list_for_each_entry(br_port, &bridge->port_list, head) {222		list_for_each_entry(br_vlan, &br_port->vlan_list, head) {223			if (br_vlan->vid == vid) {224				count += 1;225				break;226			}227		}228	}229 230	return count;231}232 233static void prestera_bridge_vlan_put(struct prestera_bridge_vlan *br_vlan)234{235	if (list_empty(&br_vlan->port_vlan_list))236		prestera_bridge_vlan_destroy(br_vlan);237}238 239static struct prestera_port_vlan *240prestera_port_vlan_by_vid(struct prestera_port *port, u16 vid)241{242	struct prestera_port_vlan *port_vlan;243 244	list_for_each_entry(port_vlan, &port->vlans_list, port_head) {245		if (port_vlan->vid == vid)246			return port_vlan;247	}248 249	return NULL;250}251 252static struct prestera_port_vlan *253prestera_port_vlan_create(struct prestera_port *port, u16 vid, bool untagged)254{255	struct prestera_port_vlan *port_vlan;256	int err;257 258	port_vlan = prestera_port_vlan_by_vid(port, vid);259	if (port_vlan)260		return ERR_PTR(-EEXIST);261 262	err = prestera_hw_vlan_port_set(port, vid, true, untagged);263	if (err)264		return ERR_PTR(err);265 266	port_vlan = kzalloc(sizeof(*port_vlan), GFP_KERNEL);267	if (!port_vlan) {268		err = -ENOMEM;269		goto err_port_vlan_alloc;270	}271 272	port_vlan->port = port;273	port_vlan->vid = vid;274 275	list_add(&port_vlan->port_head, &port->vlans_list);276 277	return port_vlan;278 279err_port_vlan_alloc:280	prestera_hw_vlan_port_set(port, vid, false, false);281	return ERR_PTR(err);282}283 284static int prestera_fdb_add(struct prestera_port *port,285			    const unsigned char *mac, u16 vid, bool dynamic)286{287	if (prestera_port_is_lag_member(port))288		return prestera_hw_lag_fdb_add(port->sw, prestera_port_lag_id(port),289					      mac, vid, dynamic);290 291	return prestera_hw_fdb_add(port, mac, vid, dynamic);292}293 294static int prestera_fdb_del(struct prestera_port *port,295			    const unsigned char *mac, u16 vid)296{297	if (prestera_port_is_lag_member(port))298		return prestera_hw_lag_fdb_del(port->sw, prestera_port_lag_id(port),299					      mac, vid);300	else301		return prestera_hw_fdb_del(port, mac, vid);302}303 304static int prestera_fdb_flush_port_vlan(struct prestera_port *port, u16 vid,305					u32 mode)306{307	if (prestera_port_is_lag_member(port))308		return prestera_hw_fdb_flush_lag_vlan(port->sw, prestera_port_lag_id(port),309						      vid, mode);310	else311		return prestera_hw_fdb_flush_port_vlan(port, vid, mode);312}313 314static int prestera_fdb_flush_port(struct prestera_port *port, u32 mode)315{316	if (prestera_port_is_lag_member(port))317		return prestera_hw_fdb_flush_lag(port->sw, prestera_port_lag_id(port),318						 mode);319	else320		return prestera_hw_fdb_flush_port(port, mode);321}322 323static void324prestera_mdb_port_del(struct prestera_mdb_entry *mdb,325		      struct net_device *orig_dev)326{327	struct prestera_flood_domain *fl_domain = mdb->flood_domain;328	struct prestera_flood_domain_port *flood_domain_port;329 330	flood_domain_port = prestera_flood_domain_port_find(fl_domain,331							    orig_dev,332							    mdb->vid);333	if (flood_domain_port)334		prestera_flood_domain_port_destroy(flood_domain_port);335}336 337static void338prestera_br_mdb_entry_put(struct prestera_br_mdb_entry *br_mdb)339{340	struct prestera_bridge_port *br_port;341 342	if (list_empty(&br_mdb->br_mdb_port_list)) {343		list_for_each_entry(br_port, &br_mdb->bridge->port_list, head)344			prestera_mdb_port_del(br_mdb->mdb, br_port->dev);345 346		prestera_mdb_entry_destroy(br_mdb->mdb);347		list_del(&br_mdb->br_mdb_entry_node);348		kfree(br_mdb);349	}350}351 352static void353prestera_br_mdb_port_del(struct prestera_br_mdb_entry *br_mdb,354			 struct prestera_bridge_port *br_port)355{356	struct prestera_br_mdb_port *br_mdb_port, *tmp;357 358	list_for_each_entry_safe(br_mdb_port, tmp, &br_mdb->br_mdb_port_list,359				 br_mdb_port_node) {360		if (br_mdb_port->br_port == br_port) {361			list_del(&br_mdb_port->br_mdb_port_node);362			kfree(br_mdb_port);363		}364	}365}366 367static void368prestera_mdb_flush_bridge_port(struct prestera_bridge_port *br_port)369{370	struct prestera_br_mdb_port *br_mdb_port, *tmp_port;371	struct prestera_br_mdb_entry *br_mdb, *br_mdb_tmp;372	struct prestera_bridge *br_dev = br_port->bridge;373 374	list_for_each_entry_safe(br_mdb, br_mdb_tmp, &br_dev->br_mdb_entry_list,375				 br_mdb_entry_node) {376		list_for_each_entry_safe(br_mdb_port, tmp_port,377					 &br_mdb->br_mdb_port_list,378					 br_mdb_port_node) {379			prestera_mdb_port_del(br_mdb->mdb,380					      br_mdb_port->br_port->dev);381			prestera_br_mdb_port_del(br_mdb,  br_mdb_port->br_port);382		}383		prestera_br_mdb_entry_put(br_mdb);384	}385}386 387static void388prestera_port_vlan_bridge_leave(struct prestera_port_vlan *port_vlan)389{390	u32 fdb_flush_mode = PRESTERA_FDB_FLUSH_MODE_DYNAMIC;391	struct prestera_port *port = port_vlan->port;392	struct prestera_bridge_vlan *br_vlan;393	struct prestera_bridge_port *br_port;394	bool last_port, last_vlan;395	u16 vid = port_vlan->vid;396	int port_count;397 398	br_port = port_vlan->br_port;399	port_count = prestera_bridge_vlan_port_count(br_port->bridge, vid);400	br_vlan = prestera_bridge_vlan_by_vid(br_port, vid);401 402	last_vlan = list_is_singular(&br_port->vlan_list);403	last_port = port_count == 1;404 405	if (last_vlan)406		prestera_fdb_flush_port(port, fdb_flush_mode);407	else if (last_port)408		prestera_hw_fdb_flush_vlan(port->sw, vid, fdb_flush_mode);409	else410		prestera_fdb_flush_port_vlan(port, vid, fdb_flush_mode);411 412	prestera_mdb_flush_bridge_port(br_port);413 414	list_del(&port_vlan->br_vlan_head);415	prestera_bridge_vlan_put(br_vlan);416	prestera_bridge_port_put(br_port);417	port_vlan->br_port = NULL;418}419 420static void prestera_port_vlan_destroy(struct prestera_port_vlan *port_vlan)421{422	struct prestera_port *port = port_vlan->port;423	u16 vid = port_vlan->vid;424 425	if (port_vlan->br_port)426		prestera_port_vlan_bridge_leave(port_vlan);427 428	prestera_hw_vlan_port_set(port, vid, false, false);429	list_del(&port_vlan->port_head);430	kfree(port_vlan);431}432 433static struct prestera_bridge *434prestera_bridge_create(struct prestera_switchdev *swdev, struct net_device *dev)435{436	bool vlan_enabled = br_vlan_enabled(dev);437	struct prestera_bridge *bridge;438	u16 bridge_id;439	int err;440 441	if (vlan_enabled && swdev->bridge_8021q_exists) {442		netdev_err(dev, "Only one VLAN-aware bridge is supported\n");443		return ERR_PTR(-EINVAL);444	}445 446	bridge = kzalloc(sizeof(*bridge), GFP_KERNEL);447	if (!bridge)448		return ERR_PTR(-ENOMEM);449 450	if (vlan_enabled) {451		swdev->bridge_8021q_exists = true;452	} else {453		err = prestera_hw_bridge_create(swdev->sw, &bridge_id);454		if (err) {455			kfree(bridge);456			return ERR_PTR(err);457		}458 459		bridge->bridge_id = bridge_id;460	}461 462	bridge->vlan_enabled = vlan_enabled;463	bridge->swdev = swdev;464	bridge->dev = dev;465	bridge->multicast_enabled = br_multicast_enabled(dev);466 467	INIT_LIST_HEAD(&bridge->port_list);468	INIT_LIST_HEAD(&bridge->br_mdb_entry_list);469 470	list_add(&bridge->head, &swdev->bridge_list);471 472	return bridge;473}474 475static void prestera_bridge_destroy(struct prestera_bridge *bridge)476{477	struct prestera_switchdev *swdev = bridge->swdev;478 479	list_del(&bridge->head);480 481	if (bridge->vlan_enabled)482		swdev->bridge_8021q_exists = false;483	else484		prestera_hw_bridge_delete(swdev->sw, bridge->bridge_id);485 486	WARN_ON(!list_empty(&bridge->br_mdb_entry_list));487	WARN_ON(!list_empty(&bridge->port_list));488	kfree(bridge);489}490 491static void prestera_bridge_put(struct prestera_bridge *bridge)492{493	if (list_empty(&bridge->port_list))494		prestera_bridge_destroy(bridge);495}496 497static498struct prestera_bridge *prestera_bridge_by_dev(struct prestera_switchdev *swdev,499					       const struct net_device *dev)500{501	struct prestera_bridge *bridge;502 503	list_for_each_entry(bridge, &swdev->bridge_list, head)504		if (bridge->dev == dev)505			return bridge;506 507	return NULL;508}509 510static struct prestera_bridge_port *511__prestera_bridge_port_by_dev(struct prestera_bridge *bridge,512			      struct net_device *dev)513{514	struct prestera_bridge_port *br_port;515 516	list_for_each_entry(br_port, &bridge->port_list, head) {517		if (br_port->dev == dev)518			return br_port;519	}520 521	return NULL;522}523 524static int prestera_match_upper_bridge_dev(struct net_device *dev,525					   struct netdev_nested_priv *priv)526{527	if (netif_is_bridge_master(dev))528		priv->data = dev;529 530	return 0;531}532 533static struct net_device *prestera_get_upper_bridge_dev(struct net_device *dev)534{535	struct netdev_nested_priv priv = { };536 537	netdev_walk_all_upper_dev_rcu(dev, prestera_match_upper_bridge_dev,538				      &priv);539	return priv.data;540}541 542static struct prestera_bridge_port *543prestera_bridge_port_by_dev(struct prestera_switchdev *swdev,544			    struct net_device *dev)545{546	struct net_device *br_dev = prestera_get_upper_bridge_dev(dev);547	struct prestera_bridge *bridge;548 549	if (!br_dev)550		return NULL;551 552	bridge = prestera_bridge_by_dev(swdev, br_dev);553	if (!bridge)554		return NULL;555 556	return __prestera_bridge_port_by_dev(bridge, dev);557}558 559static struct prestera_bridge_port *560prestera_bridge_port_create(struct prestera_bridge *bridge,561			    struct net_device *dev)562{563	struct prestera_bridge_port *br_port;564 565	br_port = kzalloc(sizeof(*br_port), GFP_KERNEL);566	if (!br_port)567		return NULL;568 569	br_port->flags = BR_LEARNING | BR_FLOOD | BR_LEARNING_SYNC |570				BR_MCAST_FLOOD;571	br_port->stp_state = BR_STATE_DISABLED;572	refcount_set(&br_port->ref_count, 1);573	br_port->bridge = bridge;574	br_port->dev = dev;575 576	INIT_LIST_HEAD(&br_port->vlan_list);577	list_add(&br_port->head, &bridge->port_list);578	INIT_LIST_HEAD(&br_port->br_mdb_port_list);579 580	return br_port;581}582 583static void584prestera_bridge_port_destroy(struct prestera_bridge_port *br_port)585{586	list_del(&br_port->head);587	WARN_ON(!list_empty(&br_port->vlan_list));588	WARN_ON(!list_empty(&br_port->br_mdb_port_list));589	kfree(br_port);590}591 592static void prestera_bridge_port_get(struct prestera_bridge_port *br_port)593{594	refcount_inc(&br_port->ref_count);595}596 597static void prestera_bridge_port_put(struct prestera_bridge_port *br_port)598{599	struct prestera_bridge *bridge = br_port->bridge;600 601	if (refcount_dec_and_test(&br_port->ref_count)) {602		prestera_bridge_port_destroy(br_port);603		prestera_bridge_put(bridge);604	}605}606 607static struct prestera_bridge_port *608prestera_bridge_port_add(struct prestera_bridge *bridge, struct net_device *dev)609{610	struct prestera_bridge_port *br_port;611 612	br_port = __prestera_bridge_port_by_dev(bridge, dev);613	if (br_port) {614		prestera_bridge_port_get(br_port);615		return br_port;616	}617 618	br_port = prestera_bridge_port_create(bridge, dev);619	if (!br_port)620		return ERR_PTR(-ENOMEM);621 622	return br_port;623}624 625static int626prestera_bridge_1d_port_join(struct prestera_bridge_port *br_port)627{628	struct prestera_port *port = netdev_priv(br_port->dev);629	struct prestera_bridge *bridge = br_port->bridge;630	int err;631 632	err = prestera_hw_bridge_port_add(port, bridge->bridge_id);633	if (err)634		return err;635 636	err = prestera_br_port_flags_set(br_port, port);637	if (err)638		goto err_flags2port_set;639 640	return 0;641 642err_flags2port_set:643	prestera_hw_bridge_port_delete(port, bridge->bridge_id);644 645	return err;646}647 648int prestera_bridge_port_join(struct net_device *br_dev,649			      struct prestera_port *port,650			      struct netlink_ext_ack *extack)651{652	struct prestera_switchdev *swdev = port->sw->swdev;653	struct prestera_bridge_port *br_port;654	struct prestera_bridge *bridge;655	int err;656 657	bridge = prestera_bridge_by_dev(swdev, br_dev);658	if (!bridge) {659		bridge = prestera_bridge_create(swdev, br_dev);660		if (IS_ERR(bridge))661			return PTR_ERR(bridge);662	}663 664	br_port = prestera_bridge_port_add(bridge, port->dev);665	if (IS_ERR(br_port)) {666		prestera_bridge_put(bridge);667		return PTR_ERR(br_port);668	}669 670	err = switchdev_bridge_port_offload(br_port->dev, port->dev, NULL,671					    NULL, NULL, false, extack);672	if (err)673		goto err_switchdev_offload;674 675	if (bridge->vlan_enabled)676		return 0;677 678	err = prestera_bridge_1d_port_join(br_port);679	if (err)680		goto err_port_join;681 682	return 0;683 684err_port_join:685	switchdev_bridge_port_unoffload(br_port->dev, NULL, NULL, NULL);686err_switchdev_offload:687	prestera_bridge_port_put(br_port);688	return err;689}690 691static void prestera_bridge_1q_port_leave(struct prestera_bridge_port *br_port)692{693	struct prestera_port *port = netdev_priv(br_port->dev);694 695	prestera_hw_fdb_flush_port(port, PRESTERA_FDB_FLUSH_MODE_ALL);696	prestera_port_pvid_set(port, PRESTERA_DEFAULT_VID);697}698 699static void prestera_bridge_1d_port_leave(struct prestera_bridge_port *br_port)700{701	struct prestera_port *port = netdev_priv(br_port->dev);702 703	prestera_hw_fdb_flush_port(port, PRESTERA_FDB_FLUSH_MODE_ALL);704	prestera_hw_bridge_port_delete(port, br_port->bridge->bridge_id);705}706 707static int prestera_port_vid_stp_set(struct prestera_port *port, u16 vid,708				     u8 state)709{710	u8 hw_state = state;711 712	switch (state) {713	case BR_STATE_DISABLED:714		hw_state = PRESTERA_STP_DISABLED;715		break;716 717	case BR_STATE_BLOCKING:718	case BR_STATE_LISTENING:719		hw_state = PRESTERA_STP_BLOCK_LISTEN;720		break;721 722	case BR_STATE_LEARNING:723		hw_state = PRESTERA_STP_LEARN;724		break;725 726	case BR_STATE_FORWARDING:727		hw_state = PRESTERA_STP_FORWARD;728		break;729 730	default:731		return -EINVAL;732	}733 734	return prestera_hw_vlan_port_stp_set(port, vid, hw_state);735}736 737void prestera_bridge_port_leave(struct net_device *br_dev,738				struct prestera_port *port)739{740	struct prestera_switchdev *swdev = port->sw->swdev;741	struct prestera_bridge_port *br_port;742	struct prestera_bridge *bridge;743 744	bridge = prestera_bridge_by_dev(swdev, br_dev);745	if (!bridge)746		return;747 748	br_port = __prestera_bridge_port_by_dev(bridge, port->dev);749	if (!br_port)750		return;751 752	bridge = br_port->bridge;753 754	if (bridge->vlan_enabled)755		prestera_bridge_1q_port_leave(br_port);756	else757		prestera_bridge_1d_port_leave(br_port);758 759	switchdev_bridge_port_unoffload(br_port->dev, NULL, NULL, NULL);760 761	prestera_mdb_flush_bridge_port(br_port);762 763	prestera_br_port_flags_reset(br_port, port);764	prestera_port_vid_stp_set(port, PRESTERA_VID_ALL, BR_STATE_FORWARDING);765	prestera_bridge_port_put(br_port);766}767 768static int prestera_port_attr_br_flags_set(struct prestera_port *port,769					   struct net_device *dev,770					   struct switchdev_brport_flags flags)771{772	struct prestera_bridge_port *br_port;773 774	br_port = prestera_bridge_port_by_dev(port->sw->swdev, dev);775	if (!br_port)776		return 0;777 778	br_port->flags &= ~flags.mask;779	br_port->flags |= flags.val & flags.mask;780	return prestera_br_port_flags_set(br_port, port);781}782 783static int prestera_port_attr_br_ageing_set(struct prestera_port *port,784					    unsigned long ageing_clock_t)785{786	unsigned long ageing_jiffies = clock_t_to_jiffies(ageing_clock_t);787	u32 ageing_time_ms = jiffies_to_msecs(ageing_jiffies);788	struct prestera_switch *sw = port->sw;789 790	if (ageing_time_ms < PRESTERA_MIN_AGEING_TIME_MS ||791	    ageing_time_ms > PRESTERA_MAX_AGEING_TIME_MS)792		return -ERANGE;793 794	return prestera_hw_switch_ageing_set(sw, ageing_time_ms);795}796 797static int prestera_port_attr_br_vlan_set(struct prestera_port *port,798					  struct net_device *dev,799					  bool vlan_enabled)800{801	struct prestera_switch *sw = port->sw;802	struct prestera_bridge *bridge;803 804	bridge = prestera_bridge_by_dev(sw->swdev, dev);805	if (WARN_ON(!bridge))806		return -EINVAL;807 808	if (bridge->vlan_enabled == vlan_enabled)809		return 0;810 811	netdev_err(bridge->dev, "VLAN filtering can't be changed for existing bridge\n");812 813	return -EINVAL;814}815 816static int prestera_port_bridge_vlan_stp_set(struct prestera_port *port,817					     struct prestera_bridge_vlan *br_vlan,818					     u8 state)819{820	struct prestera_port_vlan *port_vlan;821 822	list_for_each_entry(port_vlan, &br_vlan->port_vlan_list, br_vlan_head) {823		if (port_vlan->port != port)824			continue;825 826		return prestera_port_vid_stp_set(port, br_vlan->vid, state);827	}828 829	return 0;830}831 832static int prestera_port_attr_stp_state_set(struct prestera_port *port,833					    struct net_device *dev,834					    u8 state)835{836	struct prestera_bridge_port *br_port;837	struct prestera_bridge_vlan *br_vlan;838	int err;839	u16 vid;840 841	br_port = prestera_bridge_port_by_dev(port->sw->swdev, dev);842	if (!br_port)843		return 0;844 845	if (!br_port->bridge->vlan_enabled) {846		vid = br_port->bridge->bridge_id;847		err = prestera_port_vid_stp_set(port, vid, state);848		if (err)849			goto err_port_stp_set;850	} else {851		list_for_each_entry(br_vlan, &br_port->vlan_list, head) {852			err = prestera_port_bridge_vlan_stp_set(port, br_vlan,853								state);854			if (err)855				goto err_port_vlan_stp_set;856		}857	}858 859	br_port->stp_state = state;860 861	return 0;862 863err_port_vlan_stp_set:864	list_for_each_entry_continue_reverse(br_vlan, &br_port->vlan_list, head)865		prestera_port_bridge_vlan_stp_set(port, br_vlan, br_port->stp_state);866	return err;867 868err_port_stp_set:869	prestera_port_vid_stp_set(port, vid, br_port->stp_state);870 871	return err;872}873 874static int875prestera_br_port_lag_mdb_mc_enable_sync(struct prestera_bridge_port *br_port,876					bool enabled)877{878	struct prestera_port *pr_port;879	struct prestera_switch *sw;880	u16 lag_id;881	int err;882 883	pr_port = prestera_port_dev_lower_find(br_port->dev);884	if (!pr_port)885		return 0;886 887	sw = pr_port->sw;888	err = prestera_lag_id(sw, br_port->dev, &lag_id);889	if (err)890		return err;891 892	list_for_each_entry(pr_port, &sw->port_list, list) {893		if (pr_port->lag->lag_id == lag_id) {894			err = prestera_port_mc_flood_set(pr_port, enabled);895			if (err)896				return err;897		}898	}899 900	return 0;901}902 903static int prestera_br_mdb_mc_enable_sync(struct prestera_bridge *br_dev)904{905	struct prestera_bridge_port *br_port;906	struct prestera_port *port;907	bool enabled;908	int err;909 910	/* if mrouter exists:911	 *  - make sure every mrouter receives unreg mcast traffic;912	 * if mrouter doesn't exists:913	 *  - make sure every port receives unreg mcast traffic;914	 */915	list_for_each_entry(br_port, &br_dev->port_list, head) {916		if (br_dev->multicast_enabled && br_dev->mrouter_exist)917			enabled = br_port->mrouter;918		else919			enabled = br_port->flags & BR_MCAST_FLOOD;920 921		if (netif_is_lag_master(br_port->dev)) {922			err = prestera_br_port_lag_mdb_mc_enable_sync(br_port,923								      enabled);924			if (err)925				return err;926			continue;927		}928 929		port = prestera_port_dev_lower_find(br_port->dev);930		if (!port)931			continue;932 933		err = prestera_port_mc_flood_set(port, enabled);934		if (err)935			return err;936	}937 938	return 0;939}940 941static bool942prestera_br_mdb_port_is_member(struct prestera_br_mdb_entry *br_mdb,943			       struct net_device *orig_dev)944{945	struct prestera_br_mdb_port *tmp_port;946 947	list_for_each_entry(tmp_port, &br_mdb->br_mdb_port_list,948			    br_mdb_port_node)949		if (tmp_port->br_port->dev == orig_dev)950			return true;951 952	return false;953}954 955static int956prestera_mdb_port_add(struct prestera_mdb_entry *mdb,957		      struct net_device *orig_dev,958		      const unsigned char addr[ETH_ALEN], u16 vid)959{960	struct prestera_flood_domain *flood_domain = mdb->flood_domain;961	int err;962 963	if (!prestera_flood_domain_port_find(flood_domain,964					     orig_dev, vid)) {965		err = prestera_flood_domain_port_create(flood_domain, orig_dev,966							vid);967		if (err)968			return err;969	}970 971	return 0;972}973 974/* Sync bridge mdb (software table) with HW table (if MC is enabled). */975static int prestera_br_mdb_sync(struct prestera_bridge *br_dev)976{977	struct prestera_br_mdb_port *br_mdb_port;978	struct prestera_bridge_port *br_port;979	struct prestera_br_mdb_entry *br_mdb;980	struct prestera_mdb_entry *mdb;981	struct prestera_port *pr_port;982	int err = 0;983 984	if (!br_dev->multicast_enabled)985		return 0;986 987	list_for_each_entry(br_mdb, &br_dev->br_mdb_entry_list,988			    br_mdb_entry_node) {989		mdb = br_mdb->mdb;990		/* Make sure every port that explicitly been added to the mdb991		 * joins the specified group.992		 */993		list_for_each_entry(br_mdb_port, &br_mdb->br_mdb_port_list,994				    br_mdb_port_node) {995			br_port = br_mdb_port->br_port;996			pr_port = prestera_port_dev_lower_find(br_port->dev);997 998			/* Match only mdb and br_mdb ports that belong to the999			 * same broadcast domain.1000			 */1001			if (br_dev->vlan_enabled &&1002			    !prestera_port_vlan_by_vid(pr_port,1003						       mdb->vid))1004				continue;1005 1006			/* If port is not in MDB or there's no Mrouter1007			 * clear HW mdb.1008			 */1009			if (prestera_br_mdb_port_is_member(br_mdb,1010							   br_mdb_port->br_port->dev) &&1011							   br_dev->mrouter_exist)1012				err = prestera_mdb_port_add(mdb, br_port->dev,1013							    mdb->addr,1014							    mdb->vid);1015			else1016				prestera_mdb_port_del(mdb, br_port->dev);1017 1018			if (err)1019				return err;1020		}1021 1022		/* Make sure that every mrouter port joins every MC group int1023		 * broadcast domain. If it's not an mrouter - it should leave1024		 */1025		list_for_each_entry(br_port, &br_dev->port_list, head) {1026			pr_port = prestera_port_dev_lower_find(br_port->dev);1027 1028			/* Make sure mrouter woudln't receive traffci from1029			 * another broadcast domain (e.g. from a vlan, which1030			 * mrouter port is not a member of).1031			 */1032			if (br_dev->vlan_enabled &&1033			    !prestera_port_vlan_by_vid(pr_port,1034						       mdb->vid))1035				continue;1036 1037			if (br_port->mrouter) {1038				err = prestera_mdb_port_add(mdb, br_port->dev,1039							    mdb->addr,1040							    mdb->vid);1041				if (err)1042					return err;1043			} else if (!br_port->mrouter &&1044				   !prestera_br_mdb_port_is_member1045				   (br_mdb, br_port->dev)) {1046				prestera_mdb_port_del(mdb, br_port->dev);1047			}1048		}1049	}1050 1051	return 0;1052}1053 1054static int1055prestera_mdb_enable_set(struct prestera_br_mdb_entry *br_mdb, bool enable)1056{1057	int err;1058 1059	if (enable != br_mdb->enabled) {1060		if (enable)1061			err = prestera_hw_mdb_create(br_mdb->mdb);1062		else1063			err = prestera_hw_mdb_destroy(br_mdb->mdb);1064 1065		if (err)1066			return err;1067 1068		br_mdb->enabled = enable;1069	}1070 1071	return 0;1072}1073 1074static int1075prestera_br_mdb_enable_set(struct prestera_bridge *br_dev, bool enable)1076{1077	struct prestera_br_mdb_entry *br_mdb;1078	int err;1079 1080	list_for_each_entry(br_mdb, &br_dev->br_mdb_entry_list,1081			    br_mdb_entry_node) {1082		err = prestera_mdb_enable_set(br_mdb, enable);1083		if (err)1084			return err;1085	}1086 1087	return 0;1088}1089 1090static int prestera_port_attr_br_mc_disabled_set(struct prestera_port *port,1091						 struct net_device *orig_dev,1092						 bool mc_disabled)1093{1094	struct prestera_switch *sw = port->sw;1095	struct prestera_bridge *br_dev;1096 1097	br_dev = prestera_bridge_find(sw, orig_dev);1098	if (!br_dev)1099		return 0;1100 1101	br_dev->multicast_enabled = !mc_disabled;1102 1103	/* There's no point in enabling mdb back if router is missing. */1104	WARN_ON(prestera_br_mdb_enable_set(br_dev, br_dev->multicast_enabled &&1105					   br_dev->mrouter_exist));1106 1107	WARN_ON(prestera_br_mdb_sync(br_dev));1108 1109	WARN_ON(prestera_br_mdb_mc_enable_sync(br_dev));1110 1111	return 0;1112}1113 1114static bool1115prestera_bridge_mdb_mc_mrouter_exists(struct prestera_bridge *br_dev)1116{1117	struct prestera_bridge_port *br_port;1118 1119	list_for_each_entry(br_port, &br_dev->port_list, head)1120		if (br_port->mrouter)1121			return true;1122 1123	return false;1124}1125 1126static int1127prestera_port_attr_mrouter_set(struct prestera_port *port,1128			       struct net_device *orig_dev,1129			       bool is_port_mrouter)1130{1131	struct prestera_bridge_port *br_port;1132	struct prestera_bridge *br_dev;1133 1134	br_port = prestera_bridge_port_find(port->sw, orig_dev);1135	if (!br_port)1136		return 0;1137 1138	br_dev = br_port->bridge;1139	br_port->mrouter = is_port_mrouter;1140 1141	br_dev->mrouter_exist = prestera_bridge_mdb_mc_mrouter_exists(br_dev);1142 1143	/* Enable MDB processing if both mrouter exists and mc is enabled.1144	 * In case if MC enabled, but there is no mrouter, device would flood1145	 * all multicast traffic (even if MDB table is not empty) with the use1146	 * of bridge's flood capabilities (without the use of flood_domain).1147	 */1148	WARN_ON(prestera_br_mdb_enable_set(br_dev, br_dev->multicast_enabled &&1149					   br_dev->mrouter_exist));1150 1151	WARN_ON(prestera_br_mdb_sync(br_dev));1152 1153	WARN_ON(prestera_br_mdb_mc_enable_sync(br_dev));1154 1155	return 0;1156}1157 1158static int prestera_port_obj_attr_set(struct net_device *dev, const void *ctx,1159				      const struct switchdev_attr *attr,1160				      struct netlink_ext_ack *extack)1161{1162	struct prestera_port *port = netdev_priv(dev);1163	int err = 0;1164 1165	switch (attr->id) {1166	case SWITCHDEV_ATTR_ID_PORT_STP_STATE:1167		err = prestera_port_attr_stp_state_set(port, attr->orig_dev,1168						       attr->u.stp_state);1169		break;1170	case SWITCHDEV_ATTR_ID_PORT_PRE_BRIDGE_FLAGS:1171		if (attr->u.brport_flags.mask &1172		    ~(BR_LEARNING | BR_FLOOD | BR_MCAST_FLOOD | BR_PORT_LOCKED))1173			err = -EINVAL;1174		break;1175	case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS:1176		err = prestera_port_attr_br_flags_set(port, attr->orig_dev,1177						      attr->u.brport_flags);1178		break;1179	case SWITCHDEV_ATTR_ID_BRIDGE_AGEING_TIME:1180		err = prestera_port_attr_br_ageing_set(port,1181						       attr->u.ageing_time);1182		break;1183	case SWITCHDEV_ATTR_ID_BRIDGE_VLAN_FILTERING:1184		err = prestera_port_attr_br_vlan_set(port, attr->orig_dev,1185						     attr->u.vlan_filtering);1186		break;1187	case SWITCHDEV_ATTR_ID_PORT_MROUTER:1188		err = prestera_port_attr_mrouter_set(port, attr->orig_dev,1189						     attr->u.mrouter);1190		break;1191	case SWITCHDEV_ATTR_ID_BRIDGE_MC_DISABLED:1192		err = prestera_port_attr_br_mc_disabled_set(port, attr->orig_dev,1193							    attr->u.mc_disabled);1194		break;1195	default:1196		err = -EOPNOTSUPP;1197	}1198 1199	return err;1200}1201 1202static void1203prestera_fdb_offload_notify(struct prestera_port *port,1204			    struct switchdev_notifier_fdb_info *info)1205{1206	struct switchdev_notifier_fdb_info send_info = {};1207 1208	send_info.addr = info->addr;1209	send_info.vid = info->vid;1210	send_info.offloaded = true;1211 1212	call_switchdev_notifiers(SWITCHDEV_FDB_OFFLOADED, port->dev,1213				 &send_info.info, NULL);1214}1215 1216static int prestera_port_fdb_set(struct prestera_port *port,1217				 struct switchdev_notifier_fdb_info *fdb_info,1218				 bool adding)1219{1220	struct prestera_switch *sw = port->sw;1221	struct prestera_bridge_port *br_port;1222	struct prestera_bridge *bridge;1223	int err;1224	u16 vid;1225 1226	br_port = prestera_bridge_port_by_dev(sw->swdev, port->dev);1227	if (!br_port)1228		return -EINVAL;1229 1230	bridge = br_port->bridge;1231 1232	if (bridge->vlan_enabled)1233		vid = fdb_info->vid;1234	else1235		vid = bridge->bridge_id;1236 1237	if (adding)1238		err = prestera_fdb_add(port, fdb_info->addr, vid, false);1239	else1240		err = prestera_fdb_del(port, fdb_info->addr, vid);1241 1242	return err;1243}1244 1245static void prestera_fdb_event_work(struct work_struct *work)1246{1247	struct switchdev_notifier_fdb_info *fdb_info;1248	struct prestera_fdb_event_work *swdev_work;1249	struct prestera_port *port;1250	struct net_device *dev;1251	int err;1252 1253	swdev_work = container_of(work, struct prestera_fdb_event_work, work);1254	dev = swdev_work->dev;1255 1256	rtnl_lock();1257 1258	port = prestera_port_dev_lower_find(dev);1259	if (!port)1260		goto out_unlock;1261 1262	switch (swdev_work->event) {1263	case SWITCHDEV_FDB_ADD_TO_DEVICE:1264		fdb_info = &swdev_work->fdb_info;1265		if (!fdb_info->added_by_user || fdb_info->is_local)1266			break;1267 1268		err = prestera_port_fdb_set(port, fdb_info, true);1269		if (err)1270			break;1271 1272		prestera_fdb_offload_notify(port, fdb_info);1273		break;1274 1275	case SWITCHDEV_FDB_DEL_TO_DEVICE:1276		fdb_info = &swdev_work->fdb_info;1277		prestera_port_fdb_set(port, fdb_info, false);1278		break;1279	}1280 1281out_unlock:1282	rtnl_unlock();1283 1284	kfree(swdev_work->fdb_info.addr);1285	kfree(swdev_work);1286	dev_put(dev);1287}1288 1289static int prestera_switchdev_event(struct notifier_block *unused,1290				    unsigned long event, void *ptr)1291{1292	struct net_device *dev = switchdev_notifier_info_to_dev(ptr);1293	struct switchdev_notifier_fdb_info *fdb_info;1294	struct switchdev_notifier_info *info = ptr;1295	struct prestera_fdb_event_work *swdev_work;1296	struct net_device *upper;1297	int err;1298 1299	if (event == SWITCHDEV_PORT_ATTR_SET) {1300		err = switchdev_handle_port_attr_set(dev, ptr,1301						     prestera_netdev_check,1302						     prestera_port_obj_attr_set);1303		return notifier_from_errno(err);1304	}1305 1306	if (!prestera_netdev_check(dev))1307		return NOTIFY_DONE;1308 1309	upper = netdev_master_upper_dev_get_rcu(dev);1310	if (!upper)1311		return NOTIFY_DONE;1312 1313	if (!netif_is_bridge_master(upper))1314		return NOTIFY_DONE;1315 1316	swdev_work = kzalloc(sizeof(*swdev_work), GFP_ATOMIC);1317	if (!swdev_work)1318		return NOTIFY_BAD;1319 1320	swdev_work->event = event;1321	swdev_work->dev = dev;1322 1323	switch (event) {1324	case SWITCHDEV_FDB_ADD_TO_DEVICE:1325	case SWITCHDEV_FDB_DEL_TO_DEVICE:1326		fdb_info = container_of(info,1327					struct switchdev_notifier_fdb_info,1328					info);1329 1330		INIT_WORK(&swdev_work->work, prestera_fdb_event_work);1331		memcpy(&swdev_work->fdb_info, ptr,1332		       sizeof(swdev_work->fdb_info));1333 1334		swdev_work->fdb_info.addr = kzalloc(ETH_ALEN, GFP_ATOMIC);1335		if (!swdev_work->fdb_info.addr)1336			goto out_bad;1337 1338		ether_addr_copy((u8 *)swdev_work->fdb_info.addr,1339				fdb_info->addr);1340		dev_hold(dev);1341		break;1342 1343	default:1344		kfree(swdev_work);1345		return NOTIFY_DONE;1346	}1347 1348	queue_work(swdev_wq, &swdev_work->work);1349	return NOTIFY_DONE;1350 1351out_bad:1352	kfree(swdev_work);1353	return NOTIFY_BAD;1354}1355 1356static int1357prestera_port_vlan_bridge_join(struct prestera_port_vlan *port_vlan,1358			       struct prestera_bridge_port *br_port)1359{1360	struct prestera_port *port = port_vlan->port;1361	struct prestera_bridge_vlan *br_vlan;1362	u16 vid = port_vlan->vid;1363	int err;1364 1365	if (port_vlan->br_port)1366		return 0;1367 1368	err = prestera_br_port_flags_set(br_port, port);1369	if (err)1370		goto err_flags2port_set;1371 1372	err = prestera_port_vid_stp_set(port, vid, br_port->stp_state);1373	if (err)1374		goto err_port_vid_stp_set;1375 1376	br_vlan = prestera_bridge_vlan_by_vid(br_port, vid);1377	if (!br_vlan) {1378		br_vlan = prestera_bridge_vlan_create(br_port, vid);1379		if (!br_vlan) {1380			err = -ENOMEM;1381			goto err_bridge_vlan_get;1382		}1383	}1384 1385	list_add(&port_vlan->br_vlan_head, &br_vlan->port_vlan_list);1386 1387	prestera_bridge_port_get(br_port);1388	port_vlan->br_port = br_port;1389 1390	return 0;1391 1392err_bridge_vlan_get:1393	prestera_port_vid_stp_set(port, vid, BR_STATE_FORWARDING);1394err_port_vid_stp_set:1395	prestera_br_port_flags_reset(br_port, port);1396err_flags2port_set:1397	return err;1398}1399 1400static int1401prestera_bridge_port_vlan_add(struct prestera_port *port,1402			      struct prestera_bridge_port *br_port,1403			      u16 vid, bool is_untagged, bool is_pvid,1404			      struct netlink_ext_ack *extack)1405{1406	struct prestera_port_vlan *port_vlan;1407	u16 old_pvid = port->pvid;1408	u16 pvid;1409	int err;1410 1411	if (is_pvid)1412		pvid = vid;1413	else1414		pvid = port->pvid == vid ? 0 : port->pvid;1415 1416	port_vlan = prestera_port_vlan_by_vid(port, vid);1417	if (port_vlan && port_vlan->br_port != br_port)1418		return -EEXIST;1419 1420	if (!port_vlan) {1421		port_vlan = prestera_port_vlan_create(port, vid, is_untagged);1422		if (IS_ERR(port_vlan))1423			return PTR_ERR(port_vlan);1424	} else {1425		err = prestera_hw_vlan_port_set(port, vid, true, is_untagged);1426		if (err)1427			goto err_port_vlan_set;1428	}1429 1430	err = prestera_port_pvid_set(port, pvid);1431	if (err)1432		goto err_port_pvid_set;1433 1434	err = prestera_port_vlan_bridge_join(port_vlan, br_port);1435	if (err)1436		goto err_port_vlan_bridge_join;1437 1438	return 0;1439 1440err_port_vlan_bridge_join:1441	prestera_port_pvid_set(port, old_pvid);1442err_port_pvid_set:1443	prestera_hw_vlan_port_set(port, vid, false, false);1444err_port_vlan_set:1445	prestera_port_vlan_destroy(port_vlan);1446 1447	return err;1448}1449 1450static void1451prestera_bridge_port_vlan_del(struct prestera_port *port,1452			      struct prestera_bridge_port *br_port, u16 vid)1453{1454	u16 pvid = port->pvid == vid ? 0 : port->pvid;1455	struct prestera_port_vlan *port_vlan;1456 1457	port_vlan = prestera_port_vlan_by_vid(port, vid);1458	if (WARN_ON(!port_vlan))1459		return;1460 1461	prestera_port_vlan_bridge_leave(port_vlan);1462	prestera_port_pvid_set(port, pvid);1463	prestera_port_vlan_destroy(port_vlan);1464}1465 1466static int prestera_port_vlans_add(struct prestera_port *port,1467				   const struct switchdev_obj_port_vlan *vlan,1468				   struct netlink_ext_ack *extack)1469{1470	bool flag_untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;1471	bool flag_pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID;1472	struct net_device *orig_dev = vlan->obj.orig_dev;1473	struct prestera_bridge_port *br_port;1474	struct prestera_switch *sw = port->sw;1475	struct prestera_bridge *bridge;1476 1477	if (netif_is_bridge_master(orig_dev))1478		return 0;1479 1480	br_port = prestera_bridge_port_by_dev(sw->swdev, port->dev);1481	if (WARN_ON(!br_port))1482		return -EINVAL;1483 1484	bridge = br_port->bridge;1485	if (!bridge->vlan_enabled)1486		return 0;1487 1488	return prestera_bridge_port_vlan_add(port, br_port,1489					     vlan->vid, flag_untagged,1490					     flag_pvid, extack);1491}1492 1493static struct prestera_br_mdb_entry *1494prestera_br_mdb_entry_create(struct prestera_switch *sw,1495			     struct prestera_bridge *br_dev,1496			     const unsigned char *addr, u16 vid)1497{1498	struct prestera_br_mdb_entry *br_mdb_entry;1499	struct prestera_mdb_entry *mdb_entry;1500 1501	br_mdb_entry = kzalloc(sizeof(*br_mdb_entry), GFP_KERNEL);1502	if (!br_mdb_entry)1503		return NULL;1504 1505	mdb_entry = prestera_mdb_entry_create(sw, addr, vid);1506	if (!mdb_entry)1507		goto err_mdb_alloc;1508 1509	br_mdb_entry->mdb = mdb_entry;1510	br_mdb_entry->bridge = br_dev;1511	br_mdb_entry->enabled = true;1512	INIT_LIST_HEAD(&br_mdb_entry->br_mdb_port_list);1513 1514	list_add(&br_mdb_entry->br_mdb_entry_node, &br_dev->br_mdb_entry_list);1515 1516	return br_mdb_entry;1517 1518err_mdb_alloc:1519	kfree(br_mdb_entry);1520	return NULL;1521}1522 1523static int prestera_br_mdb_port_add(struct prestera_br_mdb_entry *br_mdb,1524				    struct prestera_bridge_port *br_port)1525{1526	struct prestera_br_mdb_port *br_mdb_port;1527 1528	list_for_each_entry(br_mdb_port, &br_mdb->br_mdb_port_list,1529			    br_mdb_port_node)1530		if (br_mdb_port->br_port == br_port)1531			return 0;1532 1533	br_mdb_port = kzalloc(sizeof(*br_mdb_port), GFP_KERNEL);1534	if (!br_mdb_port)1535		return -ENOMEM;1536 1537	br_mdb_port->br_port = br_port;1538	list_add(&br_mdb_port->br_mdb_port_node,1539		 &br_mdb->br_mdb_port_list);1540 1541	return 0;1542}1543 1544static struct prestera_br_mdb_entry *1545prestera_br_mdb_entry_find(struct prestera_bridge *br_dev,1546			   const unsigned char *addr, u16 vid)1547{1548	struct prestera_br_mdb_entry *br_mdb;1549 1550	list_for_each_entry(br_mdb, &br_dev->br_mdb_entry_list,1551			    br_mdb_entry_node)1552		if (ether_addr_equal(&br_mdb->mdb->addr[0], addr) &&1553		    vid == br_mdb->mdb->vid)1554			return br_mdb;1555 1556	return NULL;1557}1558 1559static struct prestera_br_mdb_entry *1560prestera_br_mdb_entry_get(struct prestera_switch *sw,1561			  struct prestera_bridge *br_dev,1562			  const unsigned char *addr, u16 vid)1563{1564	struct prestera_br_mdb_entry *br_mdb;1565 1566	br_mdb = prestera_br_mdb_entry_find(br_dev, addr, vid);1567	if (br_mdb)1568		return br_mdb;1569 1570	return prestera_br_mdb_entry_create(sw, br_dev, addr, vid);1571}1572 1573static int1574prestera_mdb_port_addr_obj_add(const struct switchdev_obj_port_mdb *mdb)1575{1576	struct prestera_br_mdb_entry *br_mdb;1577	struct prestera_bridge_port *br_port;1578	struct prestera_bridge *br_dev;1579	struct prestera_switch *sw;1580	struct prestera_port *port;1581	int err;1582 1583	sw = prestera_switch_get(mdb->obj.orig_dev);1584	port = prestera_port_dev_lower_find(mdb->obj.orig_dev);1585 1586	br_port = prestera_bridge_port_find(sw, mdb->obj.orig_dev);1587	if (!br_port)1588		return 0;1589 1590	br_dev = br_port->bridge;1591 1592	if (mdb->vid && !prestera_port_vlan_by_vid(port, mdb->vid))1593		return 0;1594 1595	if (mdb->vid)1596		br_mdb = prestera_br_mdb_entry_get(sw, br_dev, &mdb->addr[0],1597						   mdb->vid);1598	else1599		br_mdb = prestera_br_mdb_entry_get(sw, br_dev, &mdb->addr[0],1600						   br_dev->bridge_id);1601 1602	if (!br_mdb)1603		return -ENOMEM;1604 1605	/* Make sure newly allocated MDB entry gets disabled if either MC is1606	 * disabled, or the mrouter does not exist.1607	 */1608	WARN_ON(prestera_mdb_enable_set(br_mdb, br_dev->multicast_enabled &&1609					br_dev->mrouter_exist));1610 1611	err = prestera_br_mdb_port_add(br_mdb, br_port);1612	if (err) {1613		prestera_br_mdb_entry_put(br_mdb);1614		return err;1615	}1616 1617	err = prestera_br_mdb_sync(br_dev);1618	if (err)1619		return err;1620 1621	return 0;1622}1623 1624static int prestera_port_obj_add(struct net_device *dev, const void *ctx,1625				 const struct switchdev_obj *obj,1626				 struct netlink_ext_ack *extack)1627{1628	struct prestera_port *port = netdev_priv(dev);1629	const struct switchdev_obj_port_vlan *vlan;1630	const struct switchdev_obj_port_mdb *mdb;1631	int err = 0;1632 1633	switch (obj->id) {1634	case SWITCHDEV_OBJ_ID_PORT_VLAN:1635		vlan = SWITCHDEV_OBJ_PORT_VLAN(obj);1636		return prestera_port_vlans_add(port, vlan, extack);1637	case SWITCHDEV_OBJ_ID_PORT_MDB:1638		mdb = SWITCHDEV_OBJ_PORT_MDB(obj);1639		err = prestera_mdb_port_addr_obj_add(mdb);1640		break;1641	case SWITCHDEV_OBJ_ID_HOST_MDB:1642		fallthrough;1643	default:1644		err = -EOPNOTSUPP;1645		break;1646	}1647 1648	return err;1649}1650 1651static int prestera_port_vlans_del(struct prestera_port *port,1652				   const struct switchdev_obj_port_vlan *vlan)1653{1654	struct net_device *orig_dev = vlan->obj.orig_dev;1655	struct prestera_bridge_port *br_port;1656	struct prestera_switch *sw = port->sw;1657 1658	if (netif_is_bridge_master(orig_dev))1659		return -EOPNOTSUPP;1660 1661	br_port = prestera_bridge_port_by_dev(sw->swdev, port->dev);1662	if (WARN_ON(!br_port))1663		return -EINVAL;1664 1665	if (!br_port->bridge->vlan_enabled)1666		return 0;1667 1668	prestera_bridge_port_vlan_del(port, br_port, vlan->vid);1669 1670	return 0;1671}1672 1673static int1674prestera_mdb_port_addr_obj_del(struct prestera_port *port,1675			       const struct switchdev_obj_port_mdb *mdb)1676{1677	struct prestera_br_mdb_entry *br_mdb;1678	struct prestera_bridge_port *br_port;1679	struct prestera_bridge *br_dev;1680	int err;1681 1682	/* Bridge port no longer exists - and so does this MDB entry */1683	br_port = prestera_bridge_port_find(port->sw, mdb->obj.orig_dev);1684	if (!br_port)1685		return 0;1686 1687	/* Removing MDB with non-existing VLAN - not supported; */1688	if (mdb->vid && !prestera_port_vlan_by_vid(port, mdb->vid))1689		return 0;1690 1691	br_dev = br_port->bridge;1692 1693	if (br_port->bridge->vlan_enabled)1694		br_mdb = prestera_br_mdb_entry_find(br_dev, &mdb->addr[0],1695						    mdb->vid);1696	else1697		br_mdb = prestera_br_mdb_entry_find(br_dev, &mdb->addr[0],1698						    br_port->bridge->bridge_id);1699 1700	if (!br_mdb)1701		return 0;1702 1703	/* Since there might be a situation that this port was the last in the1704	 * MDB group, we have to both remove this port from software and HW MDB,1705	 * sync MDB table, and then destroy software MDB (if needed).1706	 */1707	prestera_br_mdb_port_del(br_mdb, br_port);1708 1709	prestera_br_mdb_entry_put(br_mdb);1710 1711	err = prestera_br_mdb_sync(br_dev);1712	if (err)1713		return err;1714 1715	return 0;1716}1717 1718static int prestera_port_obj_del(struct net_device *dev, const void *ctx,1719				 const struct switchdev_obj *obj)1720{1721	struct prestera_port *port = netdev_priv(dev);1722	const struct switchdev_obj_port_mdb *mdb;1723	int err = 0;1724 1725	switch (obj->id) {1726	case SWITCHDEV_OBJ_ID_PORT_VLAN:1727		return prestera_port_vlans_del(port, SWITCHDEV_OBJ_PORT_VLAN(obj));1728	case SWITCHDEV_OBJ_ID_PORT_MDB:1729		mdb = SWITCHDEV_OBJ_PORT_MDB(obj);1730		err = prestera_mdb_port_addr_obj_del(port, mdb);1731		break;1732	default:1733		err = -EOPNOTSUPP;1734		break;1735	}1736 1737	return err;1738}1739 1740static int prestera_switchdev_blk_event(struct notifier_block *unused,1741					unsigned long event, void *ptr)1742{1743	struct net_device *dev = switchdev_notifier_info_to_dev(ptr);1744	int err;1745 1746	switch (event) {1747	case SWITCHDEV_PORT_OBJ_ADD:1748		err = switchdev_handle_port_obj_add(dev, ptr,1749						    prestera_netdev_check,1750						    prestera_port_obj_add);1751		break;1752	case SWITCHDEV_PORT_OBJ_DEL:1753		err = switchdev_handle_port_obj_del(dev, ptr,1754						    prestera_netdev_check,1755						    prestera_port_obj_del);1756		break;1757	case SWITCHDEV_PORT_ATTR_SET:1758		err = switchdev_handle_port_attr_set(dev, ptr,1759						     prestera_netdev_check,1760						     prestera_port_obj_attr_set);1761		break;1762	default:1763		return NOTIFY_DONE;1764	}1765 1766	return notifier_from_errno(err);1767}1768 1769static void prestera_fdb_event(struct prestera_switch *sw,1770			       struct prestera_event *evt, void *arg)1771{1772	struct switchdev_notifier_fdb_info info = {};1773	struct net_device *dev = NULL;1774	struct prestera_port *port;1775	struct prestera_lag *lag;1776 1777	switch (evt->fdb_evt.type) {1778	case PRESTERA_FDB_ENTRY_TYPE_REG_PORT:1779		port = prestera_find_port(sw, evt->fdb_evt.dest.port_id);1780		if (port)1781			dev = port->dev;1782		break;1783	case PRESTERA_FDB_ENTRY_TYPE_LAG:1784		lag = prestera_lag_by_id(sw, evt->fdb_evt.dest.lag_id);1785		if (lag)1786			dev = lag->dev;1787		break;1788	default:1789		return;1790	}1791 1792	if (!dev)1793		return;1794 1795	info.addr = evt->fdb_evt.data.mac;1796	info.vid = evt->fdb_evt.vid;1797	info.offloaded = true;1798 1799	rtnl_lock();1800 1801	switch (evt->id) {1802	case PRESTERA_FDB_EVENT_LEARNED:1803		call_switchdev_notifiers(SWITCHDEV_FDB_ADD_TO_BRIDGE,1804					 dev, &info.info, NULL);1805		break;1806	case PRESTERA_FDB_EVENT_AGED:1807		call_switchdev_notifiers(SWITCHDEV_FDB_DEL_TO_BRIDGE,1808					 dev, &info.info, NULL);1809		break;1810	}1811 1812	rtnl_unlock();1813}1814 1815static int prestera_fdb_init(struct prestera_switch *sw)1816{1817	int err;1818 1819	err = prestera_hw_event_handler_register(sw, PRESTERA_EVENT_TYPE_FDB,1820						 prestera_fdb_event, NULL);1821	if (err)1822		return err;1823 1824	err = prestera_hw_switch_ageing_set(sw, PRESTERA_DEFAULT_AGEING_TIME_MS);1825	if (err)1826		goto err_ageing_set;1827 1828	return 0;1829 1830err_ageing_set:1831	prestera_hw_event_handler_unregister(sw, PRESTERA_EVENT_TYPE_FDB,1832					     prestera_fdb_event);1833	return err;1834}1835 1836static void prestera_fdb_fini(struct prestera_switch *sw)1837{1838	prestera_hw_event_handler_unregister(sw, PRESTERA_EVENT_TYPE_FDB,1839					     prestera_fdb_event);1840}1841 1842static int prestera_switchdev_handler_init(struct prestera_switchdev *swdev)1843{1844	int err;1845 1846	swdev->swdev_nb.notifier_call = prestera_switchdev_event;1847	err = register_switchdev_notifier(&swdev->swdev_nb);1848	if (err)1849		goto err_register_swdev_notifier;1850 1851	swdev->swdev_nb_blk.notifier_call = prestera_switchdev_blk_event;1852	err = register_switchdev_blocking_notifier(&swdev->swdev_nb_blk);1853	if (err)1854		goto err_register_blk_swdev_notifier;1855 1856	return 0;1857 1858err_register_blk_swdev_notifier:1859	unregister_switchdev_notifier(&swdev->swdev_nb);1860err_register_swdev_notifier:1861	destroy_workqueue(swdev_wq);1862	return err;1863}1864 1865static void prestera_switchdev_handler_fini(struct prestera_switchdev *swdev)1866{1867	unregister_switchdev_blocking_notifier(&swdev->swdev_nb_blk);1868	unregister_switchdev_notifier(&swdev->swdev_nb);1869}1870 1871int prestera_switchdev_init(struct prestera_switch *sw)1872{1873	struct prestera_switchdev *swdev;1874	int err;1875 1876	swdev = kzalloc(sizeof(*swdev), GFP_KERNEL);1877	if (!swdev)1878		return -ENOMEM;1879 1880	sw->swdev = swdev;1881	swdev->sw = sw;1882 1883	INIT_LIST_HEAD(&swdev->bridge_list);1884 1885	swdev_wq = alloc_ordered_workqueue("%s_ordered", 0, "prestera_br");1886	if (!swdev_wq) {1887		err = -ENOMEM;1888		goto err_alloc_wq;1889	}1890 1891	err = prestera_switchdev_handler_init(swdev);1892	if (err)1893		goto err_swdev_init;1894 1895	err = prestera_fdb_init(sw);1896	if (err)1897		goto err_fdb_init;1898 1899	return 0;1900 1901err_fdb_init:1902err_swdev_init:1903	destroy_workqueue(swdev_wq);1904err_alloc_wq:1905	kfree(swdev);1906 1907	return err;1908}1909 1910void prestera_switchdev_fini(struct prestera_switch *sw)1911{1912	struct prestera_switchdev *swdev = sw->swdev;1913 1914	prestera_fdb_fini(sw);1915	prestera_switchdev_handler_fini(swdev);1916	destroy_workqueue(swdev_wq);1917	kfree(swdev);1918}1919