brintos

brintos / linux-shallow public Read only

0
0
Text · 35.3 KiB · 22ca6ee Raw
1527 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/etherdevice.h>5#include <linux/jiffies.h>6#include <linux/list.h>7#include <linux/module.h>8#include <linux/netdev_features.h>9#include <linux/of.h>10#include <linux/of_net.h>11#include <linux/if_vlan.h>12#include <linux/phylink.h>13 14#include "prestera.h"15#include "prestera_hw.h"16#include "prestera_acl.h"17#include "prestera_flow.h"18#include "prestera_span.h"19#include "prestera_rxtx.h"20#include "prestera_devlink.h"21#include "prestera_ethtool.h"22#include "prestera_counter.h"23#include "prestera_switchdev.h"24 25#define PRESTERA_MTU_DEFAULT	153626 27#define PRESTERA_STATS_DELAY_MS	100028 29#define PRESTERA_MAC_ADDR_NUM_MAX	25530 31static struct workqueue_struct *prestera_wq;32static struct workqueue_struct *prestera_owq;33 34void prestera_queue_work(struct work_struct *work)35{36	queue_work(prestera_owq, work);37}38 39void prestera_queue_delayed_work(struct delayed_work *work, unsigned long delay)40{41	queue_delayed_work(prestera_wq, work, delay);42}43 44void prestera_queue_drain(void)45{46	drain_workqueue(prestera_wq);47	drain_workqueue(prestera_owq);48}49 50int prestera_port_learning_set(struct prestera_port *port, bool learn)51{52	return prestera_hw_port_learning_set(port, learn);53}54 55int prestera_port_uc_flood_set(struct prestera_port *port, bool flood)56{57	return prestera_hw_port_uc_flood_set(port, flood);58}59 60int prestera_port_mc_flood_set(struct prestera_port *port, bool flood)61{62	return prestera_hw_port_mc_flood_set(port, flood);63}64 65int prestera_port_br_locked_set(struct prestera_port *port, bool br_locked)66{67	return prestera_hw_port_br_locked_set(port, br_locked);68}69 70int prestera_port_pvid_set(struct prestera_port *port, u16 vid)71{72	enum prestera_accept_frm_type frm_type;73	int err;74 75	frm_type = PRESTERA_ACCEPT_FRAME_TYPE_TAGGED;76 77	if (vid) {78		err = prestera_hw_vlan_port_vid_set(port, vid);79		if (err)80			return err;81 82		frm_type = PRESTERA_ACCEPT_FRAME_TYPE_ALL;83	}84 85	err = prestera_hw_port_accept_frm_type(port, frm_type);86	if (err && frm_type == PRESTERA_ACCEPT_FRAME_TYPE_ALL)87		prestera_hw_vlan_port_vid_set(port, port->pvid);88 89	port->pvid = vid;90	return 0;91}92 93struct prestera_port *prestera_port_find_by_hwid(struct prestera_switch *sw,94						 u32 dev_id, u32 hw_id)95{96	struct prestera_port *port = NULL, *tmp;97 98	read_lock(&sw->port_list_lock);99	list_for_each_entry(tmp, &sw->port_list, list) {100		if (tmp->dev_id == dev_id && tmp->hw_id == hw_id) {101			port = tmp;102			break;103		}104	}105	read_unlock(&sw->port_list_lock);106 107	return port;108}109 110struct prestera_port *prestera_find_port(struct prestera_switch *sw, u32 id)111{112	struct prestera_port *port = NULL, *tmp;113 114	read_lock(&sw->port_list_lock);115	list_for_each_entry(tmp, &sw->port_list, list) {116		if (tmp->id == id) {117			port = tmp;118			break;119		}120	}121	read_unlock(&sw->port_list_lock);122 123	return port;124}125 126struct prestera_switch *prestera_switch_get(struct net_device *dev)127{128	struct prestera_port *port;129 130	port = prestera_port_dev_lower_find(dev);131	return port ? port->sw : NULL;132}133 134int prestera_port_cfg_mac_read(struct prestera_port *port,135			       struct prestera_port_mac_config *cfg)136{137	*cfg = port->cfg_mac;138	return 0;139}140 141int prestera_port_cfg_mac_write(struct prestera_port *port,142				struct prestera_port_mac_config *cfg)143{144	int err;145 146	err = prestera_hw_port_mac_mode_set(port, cfg->admin,147					    cfg->mode, cfg->inband, cfg->speed,148					    cfg->duplex, cfg->fec);149	if (err)150		return err;151 152	port->cfg_mac = *cfg;153	return 0;154}155 156static int prestera_port_open(struct net_device *dev)157{158	struct prestera_port *port = netdev_priv(dev);159	struct prestera_port_mac_config cfg_mac;160	int err = 0;161 162	if (port->phy_link) {163		phylink_start(port->phy_link);164	} else {165		if (port->caps.transceiver == PRESTERA_PORT_TCVR_SFP) {166			err = prestera_port_cfg_mac_read(port, &cfg_mac);167			if (!err) {168				cfg_mac.admin = true;169				err = prestera_port_cfg_mac_write(port,170								  &cfg_mac);171			}172		} else {173			port->cfg_phy.admin = true;174			err = prestera_hw_port_phy_mode_set(port, true,175							    port->autoneg,176							    port->cfg_phy.mode,177							    port->adver_link_modes,178							    port->cfg_phy.mdix);179		}180	}181 182	netif_start_queue(dev);183 184	return err;185}186 187static int prestera_port_close(struct net_device *dev)188{189	struct prestera_port *port = netdev_priv(dev);190	struct prestera_port_mac_config cfg_mac;191	int err = 0;192 193	netif_stop_queue(dev);194 195	if (port->phy_link) {196		phylink_stop(port->phy_link);197		phylink_disconnect_phy(port->phy_link);198		err = prestera_port_cfg_mac_read(port, &cfg_mac);199		if (!err) {200			cfg_mac.admin = false;201			prestera_port_cfg_mac_write(port, &cfg_mac);202		}203	} else {204		if (port->caps.transceiver == PRESTERA_PORT_TCVR_SFP) {205			err = prestera_port_cfg_mac_read(port, &cfg_mac);206			if (!err) {207				cfg_mac.admin = false;208				prestera_port_cfg_mac_write(port, &cfg_mac);209			}210		} else {211			port->cfg_phy.admin = false;212			err = prestera_hw_port_phy_mode_set(port, false, port->autoneg,213							    port->cfg_phy.mode,214							    port->adver_link_modes,215							    port->cfg_phy.mdix);216		}217	}218 219	return err;220}221 222static void223prestera_port_mac_state_cache_read(struct prestera_port *port,224				   struct prestera_port_mac_state *state)225{226	spin_lock(&port->state_mac_lock);227	*state = port->state_mac;228	spin_unlock(&port->state_mac_lock);229}230 231static void232prestera_port_mac_state_cache_write(struct prestera_port *port,233				    struct prestera_port_mac_state *state)234{235	spin_lock(&port->state_mac_lock);236	port->state_mac = *state;237	spin_unlock(&port->state_mac_lock);238}239 240static struct prestera_port *prestera_pcs_to_port(struct phylink_pcs *pcs)241{242	return container_of(pcs, struct prestera_port, phylink_pcs);243}244 245static void prestera_mac_config(struct phylink_config *config,246				unsigned int an_mode,247				const struct phylink_link_state *state)248{249}250 251static void prestera_mac_link_down(struct phylink_config *config,252				   unsigned int mode, phy_interface_t interface)253{254	struct net_device *ndev = to_net_dev(config->dev);255	struct prestera_port *port = netdev_priv(ndev);256	struct prestera_port_mac_state state_mac;257 258	/* Invalidate. Parameters will update on next link event. */259	memset(&state_mac, 0, sizeof(state_mac));260	state_mac.valid = false;261	prestera_port_mac_state_cache_write(port, &state_mac);262}263 264static void prestera_mac_link_up(struct phylink_config *config,265				 struct phy_device *phy,266				 unsigned int mode, phy_interface_t interface,267				 int speed, int duplex,268				 bool tx_pause, bool rx_pause)269{270}271 272static struct phylink_pcs *273prestera_mac_select_pcs(struct phylink_config *config,274			phy_interface_t interface)275{276	struct net_device *dev = to_net_dev(config->dev);277	struct prestera_port *port = netdev_priv(dev);278 279	return &port->phylink_pcs;280}281 282static void prestera_pcs_get_state(struct phylink_pcs *pcs,283				   struct phylink_link_state *state)284{285	struct prestera_port *port = container_of(pcs, struct prestera_port,286						  phylink_pcs);287	struct prestera_port_mac_state smac;288 289	prestera_port_mac_state_cache_read(port, &smac);290 291	if (smac.valid) {292		state->link = smac.oper ? 1 : 0;293		/* AN is completed, when port is up */294		state->an_complete = (smac.oper && port->autoneg) ? 1 : 0;295		state->speed = smac.speed;296		state->duplex = smac.duplex;297	} else {298		state->link = 0;299		state->an_complete = 0;300	}301}302 303static int prestera_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode,304			       phy_interface_t interface,305			       const unsigned long *advertising,306			       bool permit_pause_to_mac)307{308	struct prestera_port *port = prestera_pcs_to_port(pcs);309	struct prestera_port_mac_config cfg_mac;310	int err;311 312	err = prestera_port_cfg_mac_read(port, &cfg_mac);313	if (err)314		return err;315 316	cfg_mac.admin = true;317	cfg_mac.fec = PRESTERA_PORT_FEC_OFF;318	cfg_mac.inband = neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED;319 320	switch (interface) {321	case PHY_INTERFACE_MODE_10GBASER:322		cfg_mac.speed = SPEED_10000;323		cfg_mac.mode = PRESTERA_MAC_MODE_SR_LR;324		break;325	case PHY_INTERFACE_MODE_2500BASEX:326		cfg_mac.speed = SPEED_2500;327		cfg_mac.duplex = DUPLEX_FULL;328		cfg_mac.mode = PRESTERA_MAC_MODE_SGMII;329		break;330	case PHY_INTERFACE_MODE_SGMII:331		cfg_mac.mode = PRESTERA_MAC_MODE_SGMII;332		break;333	case PHY_INTERFACE_MODE_1000BASEX:334	default:335		cfg_mac.speed = SPEED_1000;336		cfg_mac.duplex = DUPLEX_FULL;337		cfg_mac.mode = PRESTERA_MAC_MODE_1000BASE_X;338		break;339	}340 341	err = prestera_port_cfg_mac_write(port, &cfg_mac);342	if (err)343		return err;344 345	return 0;346}347 348static void prestera_pcs_an_restart(struct phylink_pcs *pcs)349{350	/* TODO: add 1000basex AN restart support351	 * (Currently FW has no support for 1000baseX AN restart, but it will in the future,352	 * so as for now the function would stay empty.)353	 */354}355 356static const struct phylink_mac_ops prestera_mac_ops = {357	.mac_select_pcs = prestera_mac_select_pcs,358	.mac_config = prestera_mac_config,359	.mac_link_down = prestera_mac_link_down,360	.mac_link_up = prestera_mac_link_up,361};362 363static const struct phylink_pcs_ops prestera_pcs_ops = {364	.pcs_get_state = prestera_pcs_get_state,365	.pcs_config = prestera_pcs_config,366	.pcs_an_restart = prestera_pcs_an_restart,367};368 369static int prestera_port_sfp_bind(struct prestera_port *port)370{371	struct prestera_switch *sw = port->sw;372	struct device_node *ports, *node;373	struct fwnode_handle *fwnode;374	struct phylink *phy_link;375	int err;376 377	if (!sw->np)378		return 0;379 380	of_node_get(sw->np);381	ports = of_find_node_by_name(sw->np, "ports");382 383	for_each_child_of_node(ports, node) {384		int num;385 386		err = of_property_read_u32(node, "prestera,port-num", &num);387		if (err) {388			dev_err(sw->dev->dev,389				"device node %pOF has no valid reg property: %d\n",390				node, err);391			goto out;392		}393 394		if (port->fp_id != num)395			continue;396 397		port->phylink_pcs.ops = &prestera_pcs_ops;398		port->phylink_pcs.neg_mode = true;399 400		port->phy_config.dev = &port->dev->dev;401		port->phy_config.type = PHYLINK_NETDEV;402 403		fwnode = of_fwnode_handle(node);404 405		__set_bit(PHY_INTERFACE_MODE_10GBASER,406			  port->phy_config.supported_interfaces);407		__set_bit(PHY_INTERFACE_MODE_2500BASEX,408			  port->phy_config.supported_interfaces);409		__set_bit(PHY_INTERFACE_MODE_SGMII,410			  port->phy_config.supported_interfaces);411		__set_bit(PHY_INTERFACE_MODE_1000BASEX,412			  port->phy_config.supported_interfaces);413 414		port->phy_config.mac_capabilities =415			MAC_1000 | MAC_2500FD | MAC_10000FD;416 417		phy_link = phylink_create(&port->phy_config, fwnode,418					  PHY_INTERFACE_MODE_INTERNAL,419					  &prestera_mac_ops);420		if (IS_ERR(phy_link)) {421			netdev_err(port->dev, "failed to create phylink\n");422			err = PTR_ERR(phy_link);423			goto out;424		}425 426		port->phy_link = phy_link;427		break;428	}429 430out:431	of_node_put(node);432	of_node_put(ports);433	return err;434}435 436static int prestera_port_sfp_unbind(struct prestera_port *port)437{438	if (port->phy_link)439		phylink_destroy(port->phy_link);440 441	return 0;442}443 444static netdev_tx_t prestera_port_xmit(struct sk_buff *skb,445				      struct net_device *dev)446{447	return prestera_rxtx_xmit(netdev_priv(dev), skb);448}449 450int prestera_is_valid_mac_addr(struct prestera_port *port, const u8 *addr)451{452	if (!is_valid_ether_addr(addr))453		return -EADDRNOTAVAIL;454 455	/* firmware requires that port's MAC address contains first 5 bytes456	 * of the base MAC address457	 */458	if (memcmp(port->sw->base_mac, addr, ETH_ALEN - 1))459		return -EINVAL;460 461	return 0;462}463 464static int prestera_port_set_mac_address(struct net_device *dev, void *p)465{466	struct prestera_port *port = netdev_priv(dev);467	struct sockaddr *addr = p;468	int err;469 470	err = prestera_is_valid_mac_addr(port, addr->sa_data);471	if (err)472		return err;473 474	err = prestera_hw_port_mac_set(port, addr->sa_data);475	if (err)476		return err;477 478	eth_hw_addr_set(dev, addr->sa_data);479 480	return 0;481}482 483static int prestera_port_change_mtu(struct net_device *dev, int mtu)484{485	struct prestera_port *port = netdev_priv(dev);486	int err;487 488	err = prestera_hw_port_mtu_set(port, mtu);489	if (err)490		return err;491 492	WRITE_ONCE(dev->mtu, mtu);493 494	return 0;495}496 497static void prestera_port_get_stats64(struct net_device *dev,498				      struct rtnl_link_stats64 *stats)499{500	struct prestera_port *port = netdev_priv(dev);501	struct prestera_port_stats *port_stats = &port->cached_hw_stats.stats;502 503	stats->rx_packets = port_stats->broadcast_frames_received +504				port_stats->multicast_frames_received +505				port_stats->unicast_frames_received;506 507	stats->tx_packets = port_stats->broadcast_frames_sent +508				port_stats->multicast_frames_sent +509				port_stats->unicast_frames_sent;510 511	stats->rx_bytes = port_stats->good_octets_received;512 513	stats->tx_bytes = port_stats->good_octets_sent;514 515	stats->rx_errors = port_stats->rx_error_frame_received;516	stats->tx_errors = port_stats->mac_trans_error;517 518	stats->rx_dropped = port_stats->buffer_overrun;519	stats->tx_dropped = 0;520 521	stats->multicast = port_stats->multicast_frames_received;522	stats->collisions = port_stats->excessive_collision;523 524	stats->rx_crc_errors = port_stats->bad_crc;525}526 527static void prestera_port_get_hw_stats(struct prestera_port *port)528{529	prestera_hw_port_stats_get(port, &port->cached_hw_stats.stats);530}531 532static void prestera_port_stats_update(struct work_struct *work)533{534	struct prestera_port *port =535		container_of(work, struct prestera_port,536			     cached_hw_stats.caching_dw.work);537 538	prestera_port_get_hw_stats(port);539 540	queue_delayed_work(prestera_wq, &port->cached_hw_stats.caching_dw,541			   msecs_to_jiffies(PRESTERA_STATS_DELAY_MS));542}543 544static int prestera_port_setup_tc(struct net_device *dev,545				  enum tc_setup_type type,546				  void *type_data)547{548	struct prestera_port *port = netdev_priv(dev);549 550	switch (type) {551	case TC_SETUP_BLOCK:552		return prestera_flow_block_setup(port, type_data);553	default:554		return -EOPNOTSUPP;555	}556}557 558static const struct net_device_ops prestera_netdev_ops = {559	.ndo_open = prestera_port_open,560	.ndo_stop = prestera_port_close,561	.ndo_start_xmit = prestera_port_xmit,562	.ndo_setup_tc = prestera_port_setup_tc,563	.ndo_change_mtu = prestera_port_change_mtu,564	.ndo_get_stats64 = prestera_port_get_stats64,565	.ndo_set_mac_address = prestera_port_set_mac_address,566};567 568int prestera_port_autoneg_set(struct prestera_port *port, u64 link_modes)569{570	int err;571 572	if (port->autoneg && port->adver_link_modes == link_modes)573		return 0;574 575	err = prestera_hw_port_phy_mode_set(port, port->cfg_phy.admin,576					    true, 0, link_modes,577					    port->cfg_phy.mdix);578	if (err)579		return err;580 581	port->adver_fec = BIT(PRESTERA_PORT_FEC_OFF);582	port->adver_link_modes = link_modes;583	port->cfg_phy.mode = 0;584	port->autoneg = true;585 586	return 0;587}588 589static void prestera_port_list_add(struct prestera_port *port)590{591	write_lock(&port->sw->port_list_lock);592	list_add(&port->list, &port->sw->port_list);593	write_unlock(&port->sw->port_list_lock);594}595 596static void prestera_port_list_del(struct prestera_port *port)597{598	write_lock(&port->sw->port_list_lock);599	list_del(&port->list);600	write_unlock(&port->sw->port_list_lock);601}602 603static int prestera_port_create(struct prestera_switch *sw, u32 id)604{605	struct prestera_port_mac_config cfg_mac;606	struct prestera_port *port;607	struct net_device *dev;608	int err;609 610	dev = alloc_etherdev(sizeof(*port));611	if (!dev)612		return -ENOMEM;613 614	port = netdev_priv(dev);615 616	INIT_LIST_HEAD(&port->vlans_list);617	port->pvid = PRESTERA_DEFAULT_VID;618	port->lag = NULL;619	port->dev = dev;620	port->id = id;621	port->sw = sw;622 623	spin_lock_init(&port->state_mac_lock);624 625	err = prestera_hw_port_info_get(port, &port->dev_id, &port->hw_id,626					&port->fp_id);627	if (err) {628		dev_err(prestera_dev(sw), "Failed to get port(%u) info\n", id);629		goto err_port_info_get;630	}631 632	err = prestera_devlink_port_register(port);633	if (err)634		goto err_dl_port_register;635 636	dev->features |= NETIF_F_HW_TC;637	dev->netns_local = true;638	dev->netdev_ops = &prestera_netdev_ops;639	dev->ethtool_ops = &prestera_ethtool_ops;640	SET_NETDEV_DEV(dev, sw->dev->dev);641	SET_NETDEV_DEVLINK_PORT(dev, &port->dl_port);642 643	if (port->caps.transceiver != PRESTERA_PORT_TCVR_SFP)644		netif_carrier_off(dev);645 646	dev->mtu = min_t(unsigned int, sw->mtu_max, PRESTERA_MTU_DEFAULT);647	dev->min_mtu = sw->mtu_min;648	dev->max_mtu = sw->mtu_max;649 650	err = prestera_hw_port_mtu_set(port, dev->mtu);651	if (err) {652		dev_err(prestera_dev(sw), "Failed to set port(%u) mtu(%d)\n",653			id, dev->mtu);654		goto err_port_init;655	}656 657	if (port->fp_id >= PRESTERA_MAC_ADDR_NUM_MAX) {658		err = -EINVAL;659		goto err_port_init;660	}661 662	eth_hw_addr_gen(dev, sw->base_mac, port->fp_id);663	/* firmware requires that port's MAC address consist of the first664	 * 5 bytes of the base MAC address665	 */666	if (memcmp(dev->dev_addr, sw->base_mac, ETH_ALEN - 1)) {667		dev_warn(prestera_dev(sw), "Port MAC address wraps for port(%u)\n", id);668		dev_addr_mod(dev, 0, sw->base_mac, ETH_ALEN - 1);669	}670 671	err = prestera_hw_port_mac_set(port, dev->dev_addr);672	if (err) {673		dev_err(prestera_dev(sw), "Failed to set port(%u) mac addr\n", id);674		goto err_port_init;675	}676 677	err = prestera_hw_port_cap_get(port, &port->caps);678	if (err) {679		dev_err(prestera_dev(sw), "Failed to get port(%u) caps\n", id);680		goto err_port_init;681	}682 683	port->adver_link_modes = port->caps.supp_link_modes;684	port->adver_fec = 0;685	port->autoneg = true;686 687	/* initialize config mac */688	if (port->caps.transceiver != PRESTERA_PORT_TCVR_SFP) {689		cfg_mac.admin = true;690		cfg_mac.mode = PRESTERA_MAC_MODE_INTERNAL;691	} else {692		cfg_mac.admin = false;693		cfg_mac.mode = PRESTERA_MAC_MODE_MAX;694	}695	cfg_mac.inband = 0;696	cfg_mac.speed = 0;697	cfg_mac.duplex = DUPLEX_UNKNOWN;698	cfg_mac.fec = PRESTERA_PORT_FEC_OFF;699 700	err = prestera_port_cfg_mac_write(port, &cfg_mac);701	if (err) {702		dev_err(prestera_dev(sw),703			"Failed to set port(%u) mac mode\n", id);704		goto err_port_init;705	}706 707	/* initialize config phy (if this is inegral) */708	if (port->caps.transceiver != PRESTERA_PORT_TCVR_SFP) {709		port->cfg_phy.mdix = ETH_TP_MDI_AUTO;710		port->cfg_phy.admin = false;711		err = prestera_hw_port_phy_mode_set(port,712						    port->cfg_phy.admin,713						    false, 0, 0,714						    port->cfg_phy.mdix);715		if (err) {716			dev_err(prestera_dev(sw),717				"Failed to set port(%u) phy mode\n", id);718			goto err_port_init;719		}720	}721 722	err = prestera_rxtx_port_init(port);723	if (err)724		goto err_port_init;725 726	INIT_DELAYED_WORK(&port->cached_hw_stats.caching_dw,727			  &prestera_port_stats_update);728 729	prestera_port_list_add(port);730 731	err = register_netdev(dev);732	if (err)733		goto err_register_netdev;734 735	err = prestera_port_sfp_bind(port);736	if (err)737		goto err_sfp_bind;738 739	return 0;740 741err_sfp_bind:742	unregister_netdev(dev);743err_register_netdev:744	prestera_port_list_del(port);745err_port_init:746	prestera_devlink_port_unregister(port);747err_dl_port_register:748err_port_info_get:749	free_netdev(dev);750	return err;751}752 753static void prestera_port_destroy(struct prestera_port *port)754{755	struct net_device *dev = port->dev;756 757	cancel_delayed_work_sync(&port->cached_hw_stats.caching_dw);758	unregister_netdev(dev);759	prestera_port_list_del(port);760	prestera_devlink_port_unregister(port);761	free_netdev(dev);762}763 764static void prestera_destroy_ports(struct prestera_switch *sw)765{766	struct prestera_port *port, *tmp;767 768	list_for_each_entry_safe(port, tmp, &sw->port_list, list)769		prestera_port_destroy(port);770}771 772static int prestera_create_ports(struct prestera_switch *sw)773{774	struct prestera_port *port, *tmp;775	u32 port_idx;776	int err;777 778	for (port_idx = 0; port_idx < sw->port_count; port_idx++) {779		err = prestera_port_create(sw, port_idx);780		if (err)781			goto err_port_create;782	}783 784	return 0;785 786err_port_create:787	list_for_each_entry_safe(port, tmp, &sw->port_list, list) {788		prestera_port_sfp_unbind(port);789		prestera_port_destroy(port);790	}791 792	return err;793}794 795static void prestera_port_handle_event(struct prestera_switch *sw,796				       struct prestera_event *evt, void *arg)797{798	struct prestera_port_mac_state smac;799	struct prestera_port_event *pevt;800	struct delayed_work *caching_dw;801	struct prestera_port *port;802 803	if (evt->id == PRESTERA_PORT_EVENT_MAC_STATE_CHANGED) {804		pevt = &evt->port_evt;805		port = prestera_find_port(sw, pevt->port_id);806		if (!port || !port->dev)807			return;808 809		caching_dw = &port->cached_hw_stats.caching_dw;810 811		memset(&smac, 0, sizeof(smac));812		smac.valid = true;813		smac.oper = pevt->data.mac.oper;814		if (smac.oper) {815			smac.mode = pevt->data.mac.mode;816			smac.speed = pevt->data.mac.speed;817			smac.duplex = pevt->data.mac.duplex;818			smac.fc = pevt->data.mac.fc;819			smac.fec = pevt->data.mac.fec;820		}821		prestera_port_mac_state_cache_write(port, &smac);822 823		if (port->state_mac.oper) {824			if (port->phy_link)825				phylink_pcs_change(&port->phylink_pcs, true);826			else827				netif_carrier_on(port->dev);828 829			if (!delayed_work_pending(caching_dw))830				queue_delayed_work(prestera_wq, caching_dw, 0);831		} else {832			if (port->phy_link)833				phylink_pcs_change(&port->phylink_pcs, false);834			else if (netif_running(port->dev) && netif_carrier_ok(port->dev))835				netif_carrier_off(port->dev);836 837			if (delayed_work_pending(caching_dw))838				cancel_delayed_work(caching_dw);839		}840	}841}842 843static int prestera_event_handlers_register(struct prestera_switch *sw)844{845	return prestera_hw_event_handler_register(sw, PRESTERA_EVENT_TYPE_PORT,846						  prestera_port_handle_event,847						  NULL);848}849 850static void prestera_event_handlers_unregister(struct prestera_switch *sw)851{852	prestera_hw_event_handler_unregister(sw, PRESTERA_EVENT_TYPE_PORT,853					     prestera_port_handle_event);854}855 856static int prestera_switch_set_base_mac_addr(struct prestera_switch *sw)857{858	int ret;859 860	if (sw->np)861		ret = of_get_mac_address(sw->np, sw->base_mac);862	if (!is_valid_ether_addr(sw->base_mac) || ret) {863		eth_random_addr(sw->base_mac);864		dev_info(prestera_dev(sw), "using random base mac address\n");865	}866 867	return prestera_hw_switch_mac_set(sw, sw->base_mac);868}869 870struct prestera_lag *prestera_lag_by_id(struct prestera_switch *sw, u16 id)871{872	return id < sw->lag_max ? &sw->lags[id] : NULL;873}874 875static struct prestera_lag *prestera_lag_by_dev(struct prestera_switch *sw,876						struct net_device *dev)877{878	struct prestera_lag *lag;879	u16 id;880 881	for (id = 0; id < sw->lag_max; id++) {882		lag = &sw->lags[id];883		if (lag->dev == dev)884			return lag;885	}886 887	return NULL;888}889 890int prestera_lag_id(struct prestera_switch *sw,891		    struct net_device *lag_dev, u16 *lag_id)892{893	struct prestera_lag *lag;894	int free_id = -1;895	int id;896 897	for (id = 0; id < sw->lag_max; id++) {898		lag = prestera_lag_by_id(sw, id);899		if (lag->member_count) {900			if (lag->dev == lag_dev) {901				*lag_id = id;902				return 0;903			}904		} else if (free_id < 0) {905			free_id = id;906		}907	}908	if (free_id < 0)909		return -ENOSPC;910	*lag_id = free_id;911	return 0;912}913 914static struct prestera_lag *prestera_lag_create(struct prestera_switch *sw,915						struct net_device *lag_dev)916{917	struct prestera_lag *lag = NULL;918	u16 id;919 920	for (id = 0; id < sw->lag_max; id++) {921		lag = &sw->lags[id];922		if (!lag->dev)923			break;924	}925	if (lag) {926		INIT_LIST_HEAD(&lag->members);927		lag->dev = lag_dev;928	}929 930	return lag;931}932 933static void prestera_lag_destroy(struct prestera_switch *sw,934				 struct prestera_lag *lag)935{936	WARN_ON(!list_empty(&lag->members));937	lag->member_count = 0;938	lag->dev = NULL;939}940 941static int prestera_lag_port_add(struct prestera_port *port,942				 struct net_device *lag_dev)943{944	struct prestera_switch *sw = port->sw;945	struct prestera_lag *lag;946	int err;947 948	lag = prestera_lag_by_dev(sw, lag_dev);949	if (!lag) {950		lag = prestera_lag_create(sw, lag_dev);951		if (!lag)952			return -ENOSPC;953	}954 955	if (lag->member_count >= sw->lag_member_max)956		return -ENOSPC;957 958	err = prestera_hw_lag_member_add(port, lag->lag_id);959	if (err) {960		if (!lag->member_count)961			prestera_lag_destroy(sw, lag);962		return err;963	}964 965	list_add(&port->lag_member, &lag->members);966	lag->member_count++;967	port->lag = lag;968 969	return 0;970}971 972static int prestera_lag_port_del(struct prestera_port *port)973{974	struct prestera_switch *sw = port->sw;975	struct prestera_lag *lag = port->lag;976	int err;977 978	if (!lag || !lag->member_count)979		return -EINVAL;980 981	err = prestera_hw_lag_member_del(port, lag->lag_id);982	if (err)983		return err;984 985	list_del(&port->lag_member);986	lag->member_count--;987	port->lag = NULL;988 989	if (netif_is_bridge_port(lag->dev)) {990		struct net_device *br_dev;991 992		br_dev = netdev_master_upper_dev_get(lag->dev);993 994		prestera_bridge_port_leave(br_dev, port);995	}996 997	if (!lag->member_count)998		prestera_lag_destroy(sw, lag);999 1000	return 0;1001}1002 1003bool prestera_port_is_lag_member(const struct prestera_port *port)1004{1005	return !!port->lag;1006}1007 1008u16 prestera_port_lag_id(const struct prestera_port *port)1009{1010	return port->lag->lag_id;1011}1012 1013static int prestera_lag_init(struct prestera_switch *sw)1014{1015	u16 id;1016 1017	sw->lags = kcalloc(sw->lag_max, sizeof(*sw->lags), GFP_KERNEL);1018	if (!sw->lags)1019		return -ENOMEM;1020 1021	for (id = 0; id < sw->lag_max; id++)1022		sw->lags[id].lag_id = id;1023 1024	return 0;1025}1026 1027static void prestera_lag_fini(struct prestera_switch *sw)1028{1029	u8 idx;1030 1031	for (idx = 0; idx < sw->lag_max; idx++)1032		WARN_ON(sw->lags[idx].member_count);1033 1034	kfree(sw->lags);1035}1036 1037bool prestera_netdev_check(const struct net_device *dev)1038{1039	return dev->netdev_ops == &prestera_netdev_ops;1040}1041 1042static int prestera_lower_dev_walk(struct net_device *dev,1043				   struct netdev_nested_priv *priv)1044{1045	struct prestera_port **pport = (struct prestera_port **)priv->data;1046 1047	if (prestera_netdev_check(dev)) {1048		*pport = netdev_priv(dev);1049		return 1;1050	}1051 1052	return 0;1053}1054 1055struct prestera_port *prestera_port_dev_lower_find(struct net_device *dev)1056{1057	struct prestera_port *port = NULL;1058	struct netdev_nested_priv priv = {1059		.data = (void *)&port,1060	};1061 1062	if (prestera_netdev_check(dev))1063		return netdev_priv(dev);1064 1065	netdev_walk_all_lower_dev(dev, prestera_lower_dev_walk, &priv);1066 1067	return port;1068}1069 1070static int prestera_netdev_port_lower_event(struct net_device *dev,1071					    unsigned long event, void *ptr)1072{1073	struct netdev_notifier_changelowerstate_info *info = ptr;1074	struct netdev_lag_lower_state_info *lower_state_info;1075	struct prestera_port *port = netdev_priv(dev);1076	bool enabled;1077 1078	if (!netif_is_lag_port(dev))1079		return 0;1080	if (!prestera_port_is_lag_member(port))1081		return 0;1082 1083	lower_state_info = info->lower_state_info;1084	enabled = lower_state_info->link_up && lower_state_info->tx_enabled;1085 1086	return prestera_hw_lag_member_enable(port, port->lag->lag_id, enabled);1087}1088 1089static bool prestera_lag_master_check(struct net_device *lag_dev,1090				      struct netdev_lag_upper_info *info,1091				      struct netlink_ext_ack *ext_ack)1092{1093	if (info->tx_type != NETDEV_LAG_TX_TYPE_HASH) {1094		NL_SET_ERR_MSG_MOD(ext_ack, "Unsupported LAG Tx type");1095		return false;1096	}1097 1098	return true;1099}1100 1101static int prestera_netdev_port_event(struct net_device *lower,1102				      struct net_device *dev,1103				      unsigned long event, void *ptr)1104{1105	struct netdev_notifier_info *info = ptr;1106	struct netdev_notifier_changeupper_info *cu_info;1107	struct prestera_port *port = netdev_priv(dev);1108	struct netlink_ext_ack *extack;1109	struct net_device *upper;1110 1111	extack = netdev_notifier_info_to_extack(info);1112	cu_info = container_of(info,1113			       struct netdev_notifier_changeupper_info,1114			       info);1115 1116	switch (event) {1117	case NETDEV_PRECHANGEUPPER:1118		upper = cu_info->upper_dev;1119		if (!netif_is_bridge_master(upper) &&1120		    !netif_is_lag_master(upper)) {1121			NL_SET_ERR_MSG_MOD(extack, "Unknown upper device type");1122			return -EINVAL;1123		}1124 1125		if (!cu_info->linking)1126			break;1127 1128		if (netdev_has_any_upper_dev(upper)) {1129			NL_SET_ERR_MSG_MOD(extack, "Upper device is already enslaved");1130			return -EINVAL;1131		}1132 1133		if (netif_is_lag_master(upper) &&1134		    !prestera_lag_master_check(upper, cu_info->upper_info, extack))1135			return -EOPNOTSUPP;1136		if (netif_is_lag_master(upper) && vlan_uses_dev(dev)) {1137			NL_SET_ERR_MSG_MOD(extack,1138					   "Master device is a LAG master and port has a VLAN");1139			return -EINVAL;1140		}1141		if (netif_is_lag_port(dev) && is_vlan_dev(upper) &&1142		    !netif_is_lag_master(vlan_dev_real_dev(upper))) {1143			NL_SET_ERR_MSG_MOD(extack,1144					   "Can not put a VLAN on a LAG port");1145			return -EINVAL;1146		}1147		break;1148 1149	case NETDEV_CHANGEUPPER:1150		upper = cu_info->upper_dev;1151		if (netif_is_bridge_master(upper)) {1152			if (cu_info->linking)1153				return prestera_bridge_port_join(upper, port,1154								 extack);1155			else1156				prestera_bridge_port_leave(upper, port);1157		} else if (netif_is_lag_master(upper)) {1158			if (cu_info->linking)1159				return prestera_lag_port_add(port, upper);1160			else1161				prestera_lag_port_del(port);1162		}1163		break;1164 1165	case NETDEV_CHANGELOWERSTATE:1166		return prestera_netdev_port_lower_event(dev, event, ptr);1167	}1168 1169	return 0;1170}1171 1172static int prestera_netdevice_lag_event(struct net_device *lag_dev,1173					unsigned long event, void *ptr)1174{1175	struct net_device *dev;1176	struct list_head *iter;1177	int err;1178 1179	netdev_for_each_lower_dev(lag_dev, dev, iter) {1180		if (prestera_netdev_check(dev)) {1181			err = prestera_netdev_port_event(lag_dev, dev, event,1182							 ptr);1183			if (err)1184				return err;1185		}1186	}1187 1188	return 0;1189}1190 1191static int prestera_netdev_event_handler(struct notifier_block *nb,1192					 unsigned long event, void *ptr)1193{1194	struct net_device *dev = netdev_notifier_info_to_dev(ptr);1195	int err = 0;1196 1197	if (prestera_netdev_check(dev))1198		err = prestera_netdev_port_event(dev, dev, event, ptr);1199	else if (netif_is_lag_master(dev))1200		err = prestera_netdevice_lag_event(dev, event, ptr);1201 1202	return notifier_from_errno(err);1203}1204 1205struct prestera_mdb_entry *1206prestera_mdb_entry_create(struct prestera_switch *sw,1207			  const unsigned char *addr, u16 vid)1208{1209	struct prestera_flood_domain *flood_domain;1210	struct prestera_mdb_entry *mdb_entry;1211 1212	mdb_entry = kzalloc(sizeof(*mdb_entry), GFP_KERNEL);1213	if (!mdb_entry)1214		goto err_mdb_alloc;1215 1216	flood_domain = prestera_flood_domain_create(sw);1217	if (!flood_domain)1218		goto err_flood_domain_create;1219 1220	mdb_entry->sw = sw;1221	mdb_entry->vid = vid;1222	mdb_entry->flood_domain = flood_domain;1223	ether_addr_copy(mdb_entry->addr, addr);1224 1225	if (prestera_hw_mdb_create(mdb_entry))1226		goto err_mdb_hw_create;1227 1228	return mdb_entry;1229 1230err_mdb_hw_create:1231	prestera_flood_domain_destroy(flood_domain);1232err_flood_domain_create:1233	kfree(mdb_entry);1234err_mdb_alloc:1235	return NULL;1236}1237 1238void prestera_mdb_entry_destroy(struct prestera_mdb_entry *mdb_entry)1239{1240	prestera_hw_mdb_destroy(mdb_entry);1241	prestera_flood_domain_destroy(mdb_entry->flood_domain);1242	kfree(mdb_entry);1243}1244 1245struct prestera_flood_domain *1246prestera_flood_domain_create(struct prestera_switch *sw)1247{1248	struct prestera_flood_domain *domain;1249 1250	domain = kzalloc(sizeof(*domain), GFP_KERNEL);1251	if (!domain)1252		return NULL;1253 1254	domain->sw = sw;1255 1256	if (prestera_hw_flood_domain_create(domain)) {1257		kfree(domain);1258		return NULL;1259	}1260 1261	INIT_LIST_HEAD(&domain->flood_domain_port_list);1262 1263	return domain;1264}1265 1266void prestera_flood_domain_destroy(struct prestera_flood_domain *flood_domain)1267{1268	WARN_ON(!list_empty(&flood_domain->flood_domain_port_list));1269	WARN_ON_ONCE(prestera_hw_flood_domain_destroy(flood_domain));1270	kfree(flood_domain);1271}1272 1273int1274prestera_flood_domain_port_create(struct prestera_flood_domain *flood_domain,1275				  struct net_device *dev,1276				  u16 vid)1277{1278	struct prestera_flood_domain_port *flood_domain_port;1279	bool is_first_port_in_list = false;1280	int err;1281 1282	flood_domain_port = kzalloc(sizeof(*flood_domain_port), GFP_KERNEL);1283	if (!flood_domain_port) {1284		err = -ENOMEM;1285		goto err_port_alloc;1286	}1287 1288	flood_domain_port->vid = vid;1289 1290	if (list_empty(&flood_domain->flood_domain_port_list))1291		is_first_port_in_list = true;1292 1293	list_add(&flood_domain_port->flood_domain_port_node,1294		 &flood_domain->flood_domain_port_list);1295 1296	flood_domain_port->flood_domain = flood_domain;1297	flood_domain_port->dev = dev;1298 1299	if (!is_first_port_in_list) {1300		err = prestera_hw_flood_domain_ports_reset(flood_domain);1301		if (err)1302			goto err_prestera_mdb_port_create_hw;1303	}1304 1305	err = prestera_hw_flood_domain_ports_set(flood_domain);1306	if (err)1307		goto err_prestera_mdb_port_create_hw;1308 1309	return 0;1310 1311err_prestera_mdb_port_create_hw:1312	list_del(&flood_domain_port->flood_domain_port_node);1313	kfree(flood_domain_port);1314err_port_alloc:1315	return err;1316}1317 1318void1319prestera_flood_domain_port_destroy(struct prestera_flood_domain_port *port)1320{1321	struct prestera_flood_domain *flood_domain = port->flood_domain;1322 1323	list_del(&port->flood_domain_port_node);1324 1325	WARN_ON_ONCE(prestera_hw_flood_domain_ports_reset(flood_domain));1326 1327	if (!list_empty(&flood_domain->flood_domain_port_list))1328		WARN_ON_ONCE(prestera_hw_flood_domain_ports_set(flood_domain));1329 1330	kfree(port);1331}1332 1333struct prestera_flood_domain_port *1334prestera_flood_domain_port_find(struct prestera_flood_domain *flood_domain,1335				struct net_device *dev, u16 vid)1336{1337	struct prestera_flood_domain_port *flood_domain_port;1338 1339	list_for_each_entry(flood_domain_port,1340			    &flood_domain->flood_domain_port_list,1341			    flood_domain_port_node)1342		if (flood_domain_port->dev == dev &&1343		    vid == flood_domain_port->vid)1344			return flood_domain_port;1345 1346	return NULL;1347}1348 1349static int prestera_netdev_event_handler_register(struct prestera_switch *sw)1350{1351	sw->netdev_nb.notifier_call = prestera_netdev_event_handler;1352 1353	return register_netdevice_notifier(&sw->netdev_nb);1354}1355 1356static void prestera_netdev_event_handler_unregister(struct prestera_switch *sw)1357{1358	unregister_netdevice_notifier(&sw->netdev_nb);1359}1360 1361static int prestera_switch_init(struct prestera_switch *sw)1362{1363	int err;1364 1365	sw->np = sw->dev->dev->of_node;1366 1367	err = prestera_hw_switch_init(sw);1368	if (err) {1369		dev_err(prestera_dev(sw), "Failed to init Switch device\n");1370		return err;1371	}1372 1373	rwlock_init(&sw->port_list_lock);1374	INIT_LIST_HEAD(&sw->port_list);1375 1376	err = prestera_switch_set_base_mac_addr(sw);1377	if (err)1378		return err;1379 1380	err = prestera_netdev_event_handler_register(sw);1381	if (err)1382		return err;1383 1384	err = prestera_router_init(sw);1385	if (err)1386		goto err_router_init;1387 1388	err = prestera_switchdev_init(sw);1389	if (err)1390		goto err_swdev_register;1391 1392	err = prestera_rxtx_switch_init(sw);1393	if (err)1394		goto err_rxtx_register;1395 1396	err = prestera_event_handlers_register(sw);1397	if (err)1398		goto err_handlers_register;1399 1400	err = prestera_counter_init(sw);1401	if (err)1402		goto err_counter_init;1403 1404	err = prestera_acl_init(sw);1405	if (err)1406		goto err_acl_init;1407 1408	err = prestera_span_init(sw);1409	if (err)1410		goto err_span_init;1411 1412	err = prestera_devlink_traps_register(sw);1413	if (err)1414		goto err_dl_register;1415 1416	err = prestera_lag_init(sw);1417	if (err)1418		goto err_lag_init;1419 1420	err = prestera_create_ports(sw);1421	if (err)1422		goto err_ports_create;1423 1424	prestera_devlink_register(sw);1425	return 0;1426 1427err_ports_create:1428	prestera_lag_fini(sw);1429err_lag_init:1430	prestera_devlink_traps_unregister(sw);1431err_dl_register:1432	prestera_span_fini(sw);1433err_span_init:1434	prestera_acl_fini(sw);1435err_acl_init:1436	prestera_counter_fini(sw);1437err_counter_init:1438	prestera_event_handlers_unregister(sw);1439err_handlers_register:1440	prestera_rxtx_switch_fini(sw);1441err_rxtx_register:1442	prestera_switchdev_fini(sw);1443err_swdev_register:1444	prestera_router_fini(sw);1445err_router_init:1446	prestera_netdev_event_handler_unregister(sw);1447	prestera_hw_switch_fini(sw);1448 1449	return err;1450}1451 1452static void prestera_switch_fini(struct prestera_switch *sw)1453{1454	prestera_devlink_unregister(sw);1455	prestera_destroy_ports(sw);1456	prestera_lag_fini(sw);1457	prestera_devlink_traps_unregister(sw);1458	prestera_span_fini(sw);1459	prestera_acl_fini(sw);1460	prestera_counter_fini(sw);1461	prestera_event_handlers_unregister(sw);1462	prestera_rxtx_switch_fini(sw);1463	prestera_switchdev_fini(sw);1464	prestera_router_fini(sw);1465	prestera_netdev_event_handler_unregister(sw);1466	prestera_hw_switch_fini(sw);1467	of_node_put(sw->np);1468}1469 1470int prestera_device_register(struct prestera_device *dev)1471{1472	struct prestera_switch *sw;1473	int err;1474 1475	sw = prestera_devlink_alloc(dev);1476	if (!sw)1477		return -ENOMEM;1478 1479	dev->priv = sw;1480	sw->dev = dev;1481 1482	err = prestera_switch_init(sw);1483	if (err) {1484		prestera_devlink_free(sw);1485		return err;1486	}1487 1488	return 0;1489}1490EXPORT_SYMBOL(prestera_device_register);1491 1492void prestera_device_unregister(struct prestera_device *dev)1493{1494	struct prestera_switch *sw = dev->priv;1495 1496	prestera_switch_fini(sw);1497	prestera_devlink_free(sw);1498}1499EXPORT_SYMBOL(prestera_device_unregister);1500 1501static int __init prestera_module_init(void)1502{1503	prestera_wq = alloc_workqueue("prestera", 0, 0);1504	if (!prestera_wq)1505		return -ENOMEM;1506 1507	prestera_owq = alloc_ordered_workqueue("prestera_ordered", 0);1508	if (!prestera_owq) {1509		destroy_workqueue(prestera_wq);1510		return -ENOMEM;1511	}1512 1513	return 0;1514}1515 1516static void __exit prestera_module_exit(void)1517{1518	destroy_workqueue(prestera_wq);1519	destroy_workqueue(prestera_owq);1520}1521 1522module_init(prestera_module_init);1523module_exit(prestera_module_exit);1524 1525MODULE_LICENSE("Dual BSD/GPL");1526MODULE_DESCRIPTION("Marvell Prestera switch driver");1527