xref: /OK3568_Linux_fs/kernel/drivers/net/ethernet/marvell/prestera/prestera_main.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2*4882a593Smuzhiyun /* Copyright (c) 2019-2020 Marvell International Ltd. All rights reserved */
3*4882a593Smuzhiyun 
4*4882a593Smuzhiyun #include <linux/etherdevice.h>
5*4882a593Smuzhiyun #include <linux/jiffies.h>
6*4882a593Smuzhiyun #include <linux/list.h>
7*4882a593Smuzhiyun #include <linux/module.h>
8*4882a593Smuzhiyun #include <linux/netdev_features.h>
9*4882a593Smuzhiyun #include <linux/of.h>
10*4882a593Smuzhiyun #include <linux/of_net.h>
11*4882a593Smuzhiyun 
12*4882a593Smuzhiyun #include "prestera.h"
13*4882a593Smuzhiyun #include "prestera_hw.h"
14*4882a593Smuzhiyun #include "prestera_rxtx.h"
15*4882a593Smuzhiyun #include "prestera_devlink.h"
16*4882a593Smuzhiyun #include "prestera_ethtool.h"
17*4882a593Smuzhiyun #include "prestera_switchdev.h"
18*4882a593Smuzhiyun 
19*4882a593Smuzhiyun #define PRESTERA_MTU_DEFAULT	1536
20*4882a593Smuzhiyun 
21*4882a593Smuzhiyun #define PRESTERA_STATS_DELAY_MS	1000
22*4882a593Smuzhiyun 
23*4882a593Smuzhiyun #define PRESTERA_MAC_ADDR_NUM_MAX	255
24*4882a593Smuzhiyun 
25*4882a593Smuzhiyun static struct workqueue_struct *prestera_wq;
26*4882a593Smuzhiyun 
prestera_port_pvid_set(struct prestera_port * port,u16 vid)27*4882a593Smuzhiyun int prestera_port_pvid_set(struct prestera_port *port, u16 vid)
28*4882a593Smuzhiyun {
29*4882a593Smuzhiyun 	enum prestera_accept_frm_type frm_type;
30*4882a593Smuzhiyun 	int err;
31*4882a593Smuzhiyun 
32*4882a593Smuzhiyun 	frm_type = PRESTERA_ACCEPT_FRAME_TYPE_TAGGED;
33*4882a593Smuzhiyun 
34*4882a593Smuzhiyun 	if (vid) {
35*4882a593Smuzhiyun 		err = prestera_hw_vlan_port_vid_set(port, vid);
36*4882a593Smuzhiyun 		if (err)
37*4882a593Smuzhiyun 			return err;
38*4882a593Smuzhiyun 
39*4882a593Smuzhiyun 		frm_type = PRESTERA_ACCEPT_FRAME_TYPE_ALL;
40*4882a593Smuzhiyun 	}
41*4882a593Smuzhiyun 
42*4882a593Smuzhiyun 	err = prestera_hw_port_accept_frm_type(port, frm_type);
43*4882a593Smuzhiyun 	if (err && frm_type == PRESTERA_ACCEPT_FRAME_TYPE_ALL)
44*4882a593Smuzhiyun 		prestera_hw_vlan_port_vid_set(port, port->pvid);
45*4882a593Smuzhiyun 
46*4882a593Smuzhiyun 	port->pvid = vid;
47*4882a593Smuzhiyun 	return 0;
48*4882a593Smuzhiyun }
49*4882a593Smuzhiyun 
prestera_port_find_by_hwid(struct prestera_switch * sw,u32 dev_id,u32 hw_id)50*4882a593Smuzhiyun struct prestera_port *prestera_port_find_by_hwid(struct prestera_switch *sw,
51*4882a593Smuzhiyun 						 u32 dev_id, u32 hw_id)
52*4882a593Smuzhiyun {
53*4882a593Smuzhiyun 	struct prestera_port *port = NULL, *tmp;
54*4882a593Smuzhiyun 
55*4882a593Smuzhiyun 	read_lock(&sw->port_list_lock);
56*4882a593Smuzhiyun 	list_for_each_entry(tmp, &sw->port_list, list) {
57*4882a593Smuzhiyun 		if (tmp->dev_id == dev_id && tmp->hw_id == hw_id) {
58*4882a593Smuzhiyun 			port = tmp;
59*4882a593Smuzhiyun 			break;
60*4882a593Smuzhiyun 		}
61*4882a593Smuzhiyun 	}
62*4882a593Smuzhiyun 	read_unlock(&sw->port_list_lock);
63*4882a593Smuzhiyun 
64*4882a593Smuzhiyun 	return port;
65*4882a593Smuzhiyun }
66*4882a593Smuzhiyun 
prestera_find_port(struct prestera_switch * sw,u32 id)67*4882a593Smuzhiyun struct prestera_port *prestera_find_port(struct prestera_switch *sw, u32 id)
68*4882a593Smuzhiyun {
69*4882a593Smuzhiyun 	struct prestera_port *port = NULL, *tmp;
70*4882a593Smuzhiyun 
71*4882a593Smuzhiyun 	read_lock(&sw->port_list_lock);
72*4882a593Smuzhiyun 	list_for_each_entry(tmp, &sw->port_list, list) {
73*4882a593Smuzhiyun 		if (tmp->id == id) {
74*4882a593Smuzhiyun 			port = tmp;
75*4882a593Smuzhiyun 			break;
76*4882a593Smuzhiyun 		}
77*4882a593Smuzhiyun 	}
78*4882a593Smuzhiyun 	read_unlock(&sw->port_list_lock);
79*4882a593Smuzhiyun 
80*4882a593Smuzhiyun 	return port;
81*4882a593Smuzhiyun }
82*4882a593Smuzhiyun 
prestera_port_open(struct net_device * dev)83*4882a593Smuzhiyun static int prestera_port_open(struct net_device *dev)
84*4882a593Smuzhiyun {
85*4882a593Smuzhiyun 	struct prestera_port *port = netdev_priv(dev);
86*4882a593Smuzhiyun 	int err;
87*4882a593Smuzhiyun 
88*4882a593Smuzhiyun 	err = prestera_hw_port_state_set(port, true);
89*4882a593Smuzhiyun 	if (err)
90*4882a593Smuzhiyun 		return err;
91*4882a593Smuzhiyun 
92*4882a593Smuzhiyun 	netif_start_queue(dev);
93*4882a593Smuzhiyun 
94*4882a593Smuzhiyun 	return 0;
95*4882a593Smuzhiyun }
96*4882a593Smuzhiyun 
prestera_port_close(struct net_device * dev)97*4882a593Smuzhiyun static int prestera_port_close(struct net_device *dev)
98*4882a593Smuzhiyun {
99*4882a593Smuzhiyun 	struct prestera_port *port = netdev_priv(dev);
100*4882a593Smuzhiyun 	int err;
101*4882a593Smuzhiyun 
102*4882a593Smuzhiyun 	netif_stop_queue(dev);
103*4882a593Smuzhiyun 
104*4882a593Smuzhiyun 	err = prestera_hw_port_state_set(port, false);
105*4882a593Smuzhiyun 	if (err)
106*4882a593Smuzhiyun 		return err;
107*4882a593Smuzhiyun 
108*4882a593Smuzhiyun 	return 0;
109*4882a593Smuzhiyun }
110*4882a593Smuzhiyun 
prestera_port_xmit(struct sk_buff * skb,struct net_device * dev)111*4882a593Smuzhiyun static netdev_tx_t prestera_port_xmit(struct sk_buff *skb,
112*4882a593Smuzhiyun 				      struct net_device *dev)
113*4882a593Smuzhiyun {
114*4882a593Smuzhiyun 	return prestera_rxtx_xmit(netdev_priv(dev), skb);
115*4882a593Smuzhiyun }
116*4882a593Smuzhiyun 
prestera_is_valid_mac_addr(struct prestera_port * port,u8 * addr)117*4882a593Smuzhiyun static int prestera_is_valid_mac_addr(struct prestera_port *port, u8 *addr)
118*4882a593Smuzhiyun {
119*4882a593Smuzhiyun 	if (!is_valid_ether_addr(addr))
120*4882a593Smuzhiyun 		return -EADDRNOTAVAIL;
121*4882a593Smuzhiyun 
122*4882a593Smuzhiyun 	/* firmware requires that port's MAC address contains first 5 bytes
123*4882a593Smuzhiyun 	 * of the base MAC address
124*4882a593Smuzhiyun 	 */
125*4882a593Smuzhiyun 	if (memcmp(port->sw->base_mac, addr, ETH_ALEN - 1))
126*4882a593Smuzhiyun 		return -EINVAL;
127*4882a593Smuzhiyun 
128*4882a593Smuzhiyun 	return 0;
129*4882a593Smuzhiyun }
130*4882a593Smuzhiyun 
prestera_port_set_mac_address(struct net_device * dev,void * p)131*4882a593Smuzhiyun static int prestera_port_set_mac_address(struct net_device *dev, void *p)
132*4882a593Smuzhiyun {
133*4882a593Smuzhiyun 	struct prestera_port *port = netdev_priv(dev);
134*4882a593Smuzhiyun 	struct sockaddr *addr = p;
135*4882a593Smuzhiyun 	int err;
136*4882a593Smuzhiyun 
137*4882a593Smuzhiyun 	err = prestera_is_valid_mac_addr(port, addr->sa_data);
138*4882a593Smuzhiyun 	if (err)
139*4882a593Smuzhiyun 		return err;
140*4882a593Smuzhiyun 
141*4882a593Smuzhiyun 	err = prestera_hw_port_mac_set(port, addr->sa_data);
142*4882a593Smuzhiyun 	if (err)
143*4882a593Smuzhiyun 		return err;
144*4882a593Smuzhiyun 
145*4882a593Smuzhiyun 	ether_addr_copy(dev->dev_addr, addr->sa_data);
146*4882a593Smuzhiyun 
147*4882a593Smuzhiyun 	return 0;
148*4882a593Smuzhiyun }
149*4882a593Smuzhiyun 
prestera_port_change_mtu(struct net_device * dev,int mtu)150*4882a593Smuzhiyun static int prestera_port_change_mtu(struct net_device *dev, int mtu)
151*4882a593Smuzhiyun {
152*4882a593Smuzhiyun 	struct prestera_port *port = netdev_priv(dev);
153*4882a593Smuzhiyun 	int err;
154*4882a593Smuzhiyun 
155*4882a593Smuzhiyun 	err = prestera_hw_port_mtu_set(port, mtu);
156*4882a593Smuzhiyun 	if (err)
157*4882a593Smuzhiyun 		return err;
158*4882a593Smuzhiyun 
159*4882a593Smuzhiyun 	dev->mtu = mtu;
160*4882a593Smuzhiyun 
161*4882a593Smuzhiyun 	return 0;
162*4882a593Smuzhiyun }
163*4882a593Smuzhiyun 
prestera_port_get_stats64(struct net_device * dev,struct rtnl_link_stats64 * stats)164*4882a593Smuzhiyun static void prestera_port_get_stats64(struct net_device *dev,
165*4882a593Smuzhiyun 				      struct rtnl_link_stats64 *stats)
166*4882a593Smuzhiyun {
167*4882a593Smuzhiyun 	struct prestera_port *port = netdev_priv(dev);
168*4882a593Smuzhiyun 	struct prestera_port_stats *port_stats = &port->cached_hw_stats.stats;
169*4882a593Smuzhiyun 
170*4882a593Smuzhiyun 	stats->rx_packets = port_stats->broadcast_frames_received +
171*4882a593Smuzhiyun 				port_stats->multicast_frames_received +
172*4882a593Smuzhiyun 				port_stats->unicast_frames_received;
173*4882a593Smuzhiyun 
174*4882a593Smuzhiyun 	stats->tx_packets = port_stats->broadcast_frames_sent +
175*4882a593Smuzhiyun 				port_stats->multicast_frames_sent +
176*4882a593Smuzhiyun 				port_stats->unicast_frames_sent;
177*4882a593Smuzhiyun 
178*4882a593Smuzhiyun 	stats->rx_bytes = port_stats->good_octets_received;
179*4882a593Smuzhiyun 
180*4882a593Smuzhiyun 	stats->tx_bytes = port_stats->good_octets_sent;
181*4882a593Smuzhiyun 
182*4882a593Smuzhiyun 	stats->rx_errors = port_stats->rx_error_frame_received;
183*4882a593Smuzhiyun 	stats->tx_errors = port_stats->mac_trans_error;
184*4882a593Smuzhiyun 
185*4882a593Smuzhiyun 	stats->rx_dropped = port_stats->buffer_overrun;
186*4882a593Smuzhiyun 	stats->tx_dropped = 0;
187*4882a593Smuzhiyun 
188*4882a593Smuzhiyun 	stats->multicast = port_stats->multicast_frames_received;
189*4882a593Smuzhiyun 	stats->collisions = port_stats->excessive_collision;
190*4882a593Smuzhiyun 
191*4882a593Smuzhiyun 	stats->rx_crc_errors = port_stats->bad_crc;
192*4882a593Smuzhiyun }
193*4882a593Smuzhiyun 
prestera_port_get_hw_stats(struct prestera_port * port)194*4882a593Smuzhiyun static void prestera_port_get_hw_stats(struct prestera_port *port)
195*4882a593Smuzhiyun {
196*4882a593Smuzhiyun 	prestera_hw_port_stats_get(port, &port->cached_hw_stats.stats);
197*4882a593Smuzhiyun }
198*4882a593Smuzhiyun 
prestera_port_stats_update(struct work_struct * work)199*4882a593Smuzhiyun static void prestera_port_stats_update(struct work_struct *work)
200*4882a593Smuzhiyun {
201*4882a593Smuzhiyun 	struct prestera_port *port =
202*4882a593Smuzhiyun 		container_of(work, struct prestera_port,
203*4882a593Smuzhiyun 			     cached_hw_stats.caching_dw.work);
204*4882a593Smuzhiyun 
205*4882a593Smuzhiyun 	prestera_port_get_hw_stats(port);
206*4882a593Smuzhiyun 
207*4882a593Smuzhiyun 	queue_delayed_work(prestera_wq, &port->cached_hw_stats.caching_dw,
208*4882a593Smuzhiyun 			   msecs_to_jiffies(PRESTERA_STATS_DELAY_MS));
209*4882a593Smuzhiyun }
210*4882a593Smuzhiyun 
211*4882a593Smuzhiyun static const struct net_device_ops prestera_netdev_ops = {
212*4882a593Smuzhiyun 	.ndo_open = prestera_port_open,
213*4882a593Smuzhiyun 	.ndo_stop = prestera_port_close,
214*4882a593Smuzhiyun 	.ndo_start_xmit = prestera_port_xmit,
215*4882a593Smuzhiyun 	.ndo_change_mtu = prestera_port_change_mtu,
216*4882a593Smuzhiyun 	.ndo_get_stats64 = prestera_port_get_stats64,
217*4882a593Smuzhiyun 	.ndo_set_mac_address = prestera_port_set_mac_address,
218*4882a593Smuzhiyun 	.ndo_get_devlink_port = prestera_devlink_get_port,
219*4882a593Smuzhiyun };
220*4882a593Smuzhiyun 
prestera_port_autoneg_set(struct prestera_port * port,bool enable,u64 adver_link_modes,u8 adver_fec)221*4882a593Smuzhiyun int prestera_port_autoneg_set(struct prestera_port *port, bool enable,
222*4882a593Smuzhiyun 			      u64 adver_link_modes, u8 adver_fec)
223*4882a593Smuzhiyun {
224*4882a593Smuzhiyun 	bool refresh = false;
225*4882a593Smuzhiyun 	u64 link_modes;
226*4882a593Smuzhiyun 	int err;
227*4882a593Smuzhiyun 	u8 fec;
228*4882a593Smuzhiyun 
229*4882a593Smuzhiyun 	if (port->caps.type != PRESTERA_PORT_TYPE_TP)
230*4882a593Smuzhiyun 		return enable ? -EINVAL : 0;
231*4882a593Smuzhiyun 
232*4882a593Smuzhiyun 	if (!enable)
233*4882a593Smuzhiyun 		goto set_autoneg;
234*4882a593Smuzhiyun 
235*4882a593Smuzhiyun 	link_modes = port->caps.supp_link_modes & adver_link_modes;
236*4882a593Smuzhiyun 	fec = port->caps.supp_fec & adver_fec;
237*4882a593Smuzhiyun 
238*4882a593Smuzhiyun 	if (!link_modes && !fec)
239*4882a593Smuzhiyun 		return -EOPNOTSUPP;
240*4882a593Smuzhiyun 
241*4882a593Smuzhiyun 	if (link_modes && port->adver_link_modes != link_modes) {
242*4882a593Smuzhiyun 		port->adver_link_modes = link_modes;
243*4882a593Smuzhiyun 		refresh = true;
244*4882a593Smuzhiyun 	}
245*4882a593Smuzhiyun 
246*4882a593Smuzhiyun 	if (fec && port->adver_fec != fec) {
247*4882a593Smuzhiyun 		port->adver_fec = fec;
248*4882a593Smuzhiyun 		refresh = true;
249*4882a593Smuzhiyun 	}
250*4882a593Smuzhiyun 
251*4882a593Smuzhiyun set_autoneg:
252*4882a593Smuzhiyun 	if (port->autoneg == enable && !refresh)
253*4882a593Smuzhiyun 		return 0;
254*4882a593Smuzhiyun 
255*4882a593Smuzhiyun 	err = prestera_hw_port_autoneg_set(port, enable, port->adver_link_modes,
256*4882a593Smuzhiyun 					   port->adver_fec);
257*4882a593Smuzhiyun 	if (err)
258*4882a593Smuzhiyun 		return err;
259*4882a593Smuzhiyun 
260*4882a593Smuzhiyun 	port->autoneg = enable;
261*4882a593Smuzhiyun 
262*4882a593Smuzhiyun 	return 0;
263*4882a593Smuzhiyun }
264*4882a593Smuzhiyun 
prestera_port_list_add(struct prestera_port * port)265*4882a593Smuzhiyun static void prestera_port_list_add(struct prestera_port *port)
266*4882a593Smuzhiyun {
267*4882a593Smuzhiyun 	write_lock(&port->sw->port_list_lock);
268*4882a593Smuzhiyun 	list_add(&port->list, &port->sw->port_list);
269*4882a593Smuzhiyun 	write_unlock(&port->sw->port_list_lock);
270*4882a593Smuzhiyun }
271*4882a593Smuzhiyun 
prestera_port_list_del(struct prestera_port * port)272*4882a593Smuzhiyun static void prestera_port_list_del(struct prestera_port *port)
273*4882a593Smuzhiyun {
274*4882a593Smuzhiyun 	write_lock(&port->sw->port_list_lock);
275*4882a593Smuzhiyun 	list_del(&port->list);
276*4882a593Smuzhiyun 	write_unlock(&port->sw->port_list_lock);
277*4882a593Smuzhiyun }
278*4882a593Smuzhiyun 
prestera_port_create(struct prestera_switch * sw,u32 id)279*4882a593Smuzhiyun static int prestera_port_create(struct prestera_switch *sw, u32 id)
280*4882a593Smuzhiyun {
281*4882a593Smuzhiyun 	struct prestera_port *port;
282*4882a593Smuzhiyun 	struct net_device *dev;
283*4882a593Smuzhiyun 	int err;
284*4882a593Smuzhiyun 
285*4882a593Smuzhiyun 	dev = alloc_etherdev(sizeof(*port));
286*4882a593Smuzhiyun 	if (!dev)
287*4882a593Smuzhiyun 		return -ENOMEM;
288*4882a593Smuzhiyun 
289*4882a593Smuzhiyun 	port = netdev_priv(dev);
290*4882a593Smuzhiyun 
291*4882a593Smuzhiyun 	INIT_LIST_HEAD(&port->vlans_list);
292*4882a593Smuzhiyun 	port->pvid = PRESTERA_DEFAULT_VID;
293*4882a593Smuzhiyun 	port->dev = dev;
294*4882a593Smuzhiyun 	port->id = id;
295*4882a593Smuzhiyun 	port->sw = sw;
296*4882a593Smuzhiyun 
297*4882a593Smuzhiyun 	err = prestera_hw_port_info_get(port, &port->dev_id, &port->hw_id,
298*4882a593Smuzhiyun 					&port->fp_id);
299*4882a593Smuzhiyun 	if (err) {
300*4882a593Smuzhiyun 		dev_err(prestera_dev(sw), "Failed to get port(%u) info\n", id);
301*4882a593Smuzhiyun 		goto err_port_info_get;
302*4882a593Smuzhiyun 	}
303*4882a593Smuzhiyun 
304*4882a593Smuzhiyun 	err = prestera_devlink_port_register(port);
305*4882a593Smuzhiyun 	if (err)
306*4882a593Smuzhiyun 		goto err_dl_port_register;
307*4882a593Smuzhiyun 
308*4882a593Smuzhiyun 	dev->features |= NETIF_F_NETNS_LOCAL;
309*4882a593Smuzhiyun 	dev->netdev_ops = &prestera_netdev_ops;
310*4882a593Smuzhiyun 	dev->ethtool_ops = &prestera_ethtool_ops;
311*4882a593Smuzhiyun 
312*4882a593Smuzhiyun 	netif_carrier_off(dev);
313*4882a593Smuzhiyun 
314*4882a593Smuzhiyun 	dev->mtu = min_t(unsigned int, sw->mtu_max, PRESTERA_MTU_DEFAULT);
315*4882a593Smuzhiyun 	dev->min_mtu = sw->mtu_min;
316*4882a593Smuzhiyun 	dev->max_mtu = sw->mtu_max;
317*4882a593Smuzhiyun 
318*4882a593Smuzhiyun 	err = prestera_hw_port_mtu_set(port, dev->mtu);
319*4882a593Smuzhiyun 	if (err) {
320*4882a593Smuzhiyun 		dev_err(prestera_dev(sw), "Failed to set port(%u) mtu(%d)\n",
321*4882a593Smuzhiyun 			id, dev->mtu);
322*4882a593Smuzhiyun 		goto err_port_init;
323*4882a593Smuzhiyun 	}
324*4882a593Smuzhiyun 
325*4882a593Smuzhiyun 	if (port->fp_id >= PRESTERA_MAC_ADDR_NUM_MAX) {
326*4882a593Smuzhiyun 		err = -EINVAL;
327*4882a593Smuzhiyun 		goto err_port_init;
328*4882a593Smuzhiyun 	}
329*4882a593Smuzhiyun 
330*4882a593Smuzhiyun 	/* firmware requires that port's MAC address consist of the first
331*4882a593Smuzhiyun 	 * 5 bytes of the base MAC address
332*4882a593Smuzhiyun 	 */
333*4882a593Smuzhiyun 	memcpy(dev->dev_addr, sw->base_mac, dev->addr_len - 1);
334*4882a593Smuzhiyun 	dev->dev_addr[dev->addr_len - 1] = port->fp_id;
335*4882a593Smuzhiyun 
336*4882a593Smuzhiyun 	err = prestera_hw_port_mac_set(port, dev->dev_addr);
337*4882a593Smuzhiyun 	if (err) {
338*4882a593Smuzhiyun 		dev_err(prestera_dev(sw), "Failed to set port(%u) mac addr\n", id);
339*4882a593Smuzhiyun 		goto err_port_init;
340*4882a593Smuzhiyun 	}
341*4882a593Smuzhiyun 
342*4882a593Smuzhiyun 	err = prestera_hw_port_cap_get(port, &port->caps);
343*4882a593Smuzhiyun 	if (err) {
344*4882a593Smuzhiyun 		dev_err(prestera_dev(sw), "Failed to get port(%u) caps\n", id);
345*4882a593Smuzhiyun 		goto err_port_init;
346*4882a593Smuzhiyun 	}
347*4882a593Smuzhiyun 
348*4882a593Smuzhiyun 	port->adver_fec = BIT(PRESTERA_PORT_FEC_OFF);
349*4882a593Smuzhiyun 	prestera_port_autoneg_set(port, true, port->caps.supp_link_modes,
350*4882a593Smuzhiyun 				  port->caps.supp_fec);
351*4882a593Smuzhiyun 
352*4882a593Smuzhiyun 	err = prestera_hw_port_state_set(port, false);
353*4882a593Smuzhiyun 	if (err) {
354*4882a593Smuzhiyun 		dev_err(prestera_dev(sw), "Failed to set port(%u) down\n", id);
355*4882a593Smuzhiyun 		goto err_port_init;
356*4882a593Smuzhiyun 	}
357*4882a593Smuzhiyun 
358*4882a593Smuzhiyun 	err = prestera_rxtx_port_init(port);
359*4882a593Smuzhiyun 	if (err)
360*4882a593Smuzhiyun 		goto err_port_init;
361*4882a593Smuzhiyun 
362*4882a593Smuzhiyun 	INIT_DELAYED_WORK(&port->cached_hw_stats.caching_dw,
363*4882a593Smuzhiyun 			  &prestera_port_stats_update);
364*4882a593Smuzhiyun 
365*4882a593Smuzhiyun 	prestera_port_list_add(port);
366*4882a593Smuzhiyun 
367*4882a593Smuzhiyun 	err = register_netdev(dev);
368*4882a593Smuzhiyun 	if (err)
369*4882a593Smuzhiyun 		goto err_register_netdev;
370*4882a593Smuzhiyun 
371*4882a593Smuzhiyun 	prestera_devlink_port_set(port);
372*4882a593Smuzhiyun 
373*4882a593Smuzhiyun 	return 0;
374*4882a593Smuzhiyun 
375*4882a593Smuzhiyun err_register_netdev:
376*4882a593Smuzhiyun 	prestera_port_list_del(port);
377*4882a593Smuzhiyun err_port_init:
378*4882a593Smuzhiyun 	prestera_devlink_port_unregister(port);
379*4882a593Smuzhiyun err_dl_port_register:
380*4882a593Smuzhiyun err_port_info_get:
381*4882a593Smuzhiyun 	free_netdev(dev);
382*4882a593Smuzhiyun 	return err;
383*4882a593Smuzhiyun }
384*4882a593Smuzhiyun 
prestera_port_destroy(struct prestera_port * port)385*4882a593Smuzhiyun static void prestera_port_destroy(struct prestera_port *port)
386*4882a593Smuzhiyun {
387*4882a593Smuzhiyun 	struct net_device *dev = port->dev;
388*4882a593Smuzhiyun 
389*4882a593Smuzhiyun 	cancel_delayed_work_sync(&port->cached_hw_stats.caching_dw);
390*4882a593Smuzhiyun 	prestera_devlink_port_clear(port);
391*4882a593Smuzhiyun 	unregister_netdev(dev);
392*4882a593Smuzhiyun 	prestera_port_list_del(port);
393*4882a593Smuzhiyun 	prestera_devlink_port_unregister(port);
394*4882a593Smuzhiyun 	free_netdev(dev);
395*4882a593Smuzhiyun }
396*4882a593Smuzhiyun 
prestera_destroy_ports(struct prestera_switch * sw)397*4882a593Smuzhiyun static void prestera_destroy_ports(struct prestera_switch *sw)
398*4882a593Smuzhiyun {
399*4882a593Smuzhiyun 	struct prestera_port *port, *tmp;
400*4882a593Smuzhiyun 
401*4882a593Smuzhiyun 	list_for_each_entry_safe(port, tmp, &sw->port_list, list)
402*4882a593Smuzhiyun 		prestera_port_destroy(port);
403*4882a593Smuzhiyun }
404*4882a593Smuzhiyun 
prestera_create_ports(struct prestera_switch * sw)405*4882a593Smuzhiyun static int prestera_create_ports(struct prestera_switch *sw)
406*4882a593Smuzhiyun {
407*4882a593Smuzhiyun 	struct prestera_port *port, *tmp;
408*4882a593Smuzhiyun 	u32 port_idx;
409*4882a593Smuzhiyun 	int err;
410*4882a593Smuzhiyun 
411*4882a593Smuzhiyun 	for (port_idx = 0; port_idx < sw->port_count; port_idx++) {
412*4882a593Smuzhiyun 		err = prestera_port_create(sw, port_idx);
413*4882a593Smuzhiyun 		if (err)
414*4882a593Smuzhiyun 			goto err_port_create;
415*4882a593Smuzhiyun 	}
416*4882a593Smuzhiyun 
417*4882a593Smuzhiyun 	return 0;
418*4882a593Smuzhiyun 
419*4882a593Smuzhiyun err_port_create:
420*4882a593Smuzhiyun 	list_for_each_entry_safe(port, tmp, &sw->port_list, list)
421*4882a593Smuzhiyun 		prestera_port_destroy(port);
422*4882a593Smuzhiyun 
423*4882a593Smuzhiyun 	return err;
424*4882a593Smuzhiyun }
425*4882a593Smuzhiyun 
prestera_port_handle_event(struct prestera_switch * sw,struct prestera_event * evt,void * arg)426*4882a593Smuzhiyun static void prestera_port_handle_event(struct prestera_switch *sw,
427*4882a593Smuzhiyun 				       struct prestera_event *evt, void *arg)
428*4882a593Smuzhiyun {
429*4882a593Smuzhiyun 	struct delayed_work *caching_dw;
430*4882a593Smuzhiyun 	struct prestera_port *port;
431*4882a593Smuzhiyun 
432*4882a593Smuzhiyun 	port = prestera_find_port(sw, evt->port_evt.port_id);
433*4882a593Smuzhiyun 	if (!port || !port->dev)
434*4882a593Smuzhiyun 		return;
435*4882a593Smuzhiyun 
436*4882a593Smuzhiyun 	caching_dw = &port->cached_hw_stats.caching_dw;
437*4882a593Smuzhiyun 
438*4882a593Smuzhiyun 	if (evt->id == PRESTERA_PORT_EVENT_STATE_CHANGED) {
439*4882a593Smuzhiyun 		if (evt->port_evt.data.oper_state) {
440*4882a593Smuzhiyun 			netif_carrier_on(port->dev);
441*4882a593Smuzhiyun 			if (!delayed_work_pending(caching_dw))
442*4882a593Smuzhiyun 				queue_delayed_work(prestera_wq, caching_dw, 0);
443*4882a593Smuzhiyun 		} else if (netif_running(port->dev) &&
444*4882a593Smuzhiyun 			   netif_carrier_ok(port->dev)) {
445*4882a593Smuzhiyun 			netif_carrier_off(port->dev);
446*4882a593Smuzhiyun 			if (delayed_work_pending(caching_dw))
447*4882a593Smuzhiyun 				cancel_delayed_work(caching_dw);
448*4882a593Smuzhiyun 		}
449*4882a593Smuzhiyun 	}
450*4882a593Smuzhiyun }
451*4882a593Smuzhiyun 
prestera_event_handlers_register(struct prestera_switch * sw)452*4882a593Smuzhiyun static int prestera_event_handlers_register(struct prestera_switch *sw)
453*4882a593Smuzhiyun {
454*4882a593Smuzhiyun 	return prestera_hw_event_handler_register(sw, PRESTERA_EVENT_TYPE_PORT,
455*4882a593Smuzhiyun 						  prestera_port_handle_event,
456*4882a593Smuzhiyun 						  NULL);
457*4882a593Smuzhiyun }
458*4882a593Smuzhiyun 
prestera_event_handlers_unregister(struct prestera_switch * sw)459*4882a593Smuzhiyun static void prestera_event_handlers_unregister(struct prestera_switch *sw)
460*4882a593Smuzhiyun {
461*4882a593Smuzhiyun 	prestera_hw_event_handler_unregister(sw, PRESTERA_EVENT_TYPE_PORT,
462*4882a593Smuzhiyun 					     prestera_port_handle_event);
463*4882a593Smuzhiyun }
464*4882a593Smuzhiyun 
prestera_switch_set_base_mac_addr(struct prestera_switch * sw)465*4882a593Smuzhiyun static int prestera_switch_set_base_mac_addr(struct prestera_switch *sw)
466*4882a593Smuzhiyun {
467*4882a593Smuzhiyun 	struct device_node *base_mac_np;
468*4882a593Smuzhiyun 	struct device_node *np;
469*4882a593Smuzhiyun 	const char *base_mac;
470*4882a593Smuzhiyun 
471*4882a593Smuzhiyun 	np = of_find_compatible_node(NULL, NULL, "marvell,prestera");
472*4882a593Smuzhiyun 	base_mac_np = of_parse_phandle(np, "base-mac-provider", 0);
473*4882a593Smuzhiyun 
474*4882a593Smuzhiyun 	base_mac = of_get_mac_address(base_mac_np);
475*4882a593Smuzhiyun 	of_node_put(base_mac_np);
476*4882a593Smuzhiyun 	if (!IS_ERR(base_mac))
477*4882a593Smuzhiyun 		ether_addr_copy(sw->base_mac, base_mac);
478*4882a593Smuzhiyun 
479*4882a593Smuzhiyun 	if (!is_valid_ether_addr(sw->base_mac)) {
480*4882a593Smuzhiyun 		eth_random_addr(sw->base_mac);
481*4882a593Smuzhiyun 		dev_info(prestera_dev(sw), "using random base mac address\n");
482*4882a593Smuzhiyun 	}
483*4882a593Smuzhiyun 
484*4882a593Smuzhiyun 	return prestera_hw_switch_mac_set(sw, sw->base_mac);
485*4882a593Smuzhiyun }
486*4882a593Smuzhiyun 
prestera_netdev_check(const struct net_device * dev)487*4882a593Smuzhiyun bool prestera_netdev_check(const struct net_device *dev)
488*4882a593Smuzhiyun {
489*4882a593Smuzhiyun 	return dev->netdev_ops == &prestera_netdev_ops;
490*4882a593Smuzhiyun }
491*4882a593Smuzhiyun 
prestera_lower_dev_walk(struct net_device * dev,struct netdev_nested_priv * priv)492*4882a593Smuzhiyun static int prestera_lower_dev_walk(struct net_device *dev,
493*4882a593Smuzhiyun 				   struct netdev_nested_priv *priv)
494*4882a593Smuzhiyun {
495*4882a593Smuzhiyun 	struct prestera_port **pport = (struct prestera_port **)priv->data;
496*4882a593Smuzhiyun 
497*4882a593Smuzhiyun 	if (prestera_netdev_check(dev)) {
498*4882a593Smuzhiyun 		*pport = netdev_priv(dev);
499*4882a593Smuzhiyun 		return 1;
500*4882a593Smuzhiyun 	}
501*4882a593Smuzhiyun 
502*4882a593Smuzhiyun 	return 0;
503*4882a593Smuzhiyun }
504*4882a593Smuzhiyun 
prestera_port_dev_lower_find(struct net_device * dev)505*4882a593Smuzhiyun struct prestera_port *prestera_port_dev_lower_find(struct net_device *dev)
506*4882a593Smuzhiyun {
507*4882a593Smuzhiyun 	struct prestera_port *port = NULL;
508*4882a593Smuzhiyun 	struct netdev_nested_priv priv = {
509*4882a593Smuzhiyun 		.data = (void *)&port,
510*4882a593Smuzhiyun 	};
511*4882a593Smuzhiyun 
512*4882a593Smuzhiyun 	if (prestera_netdev_check(dev))
513*4882a593Smuzhiyun 		return netdev_priv(dev);
514*4882a593Smuzhiyun 
515*4882a593Smuzhiyun 	netdev_walk_all_lower_dev(dev, prestera_lower_dev_walk, &priv);
516*4882a593Smuzhiyun 
517*4882a593Smuzhiyun 	return port;
518*4882a593Smuzhiyun }
519*4882a593Smuzhiyun 
prestera_netdev_port_event(struct net_device * dev,unsigned long event,void * ptr)520*4882a593Smuzhiyun static int prestera_netdev_port_event(struct net_device *dev,
521*4882a593Smuzhiyun 				      unsigned long event, void *ptr)
522*4882a593Smuzhiyun {
523*4882a593Smuzhiyun 	switch (event) {
524*4882a593Smuzhiyun 	case NETDEV_PRECHANGEUPPER:
525*4882a593Smuzhiyun 	case NETDEV_CHANGEUPPER:
526*4882a593Smuzhiyun 		return prestera_bridge_port_event(dev, event, ptr);
527*4882a593Smuzhiyun 	default:
528*4882a593Smuzhiyun 		return 0;
529*4882a593Smuzhiyun 	}
530*4882a593Smuzhiyun }
531*4882a593Smuzhiyun 
prestera_netdev_event_handler(struct notifier_block * nb,unsigned long event,void * ptr)532*4882a593Smuzhiyun static int prestera_netdev_event_handler(struct notifier_block *nb,
533*4882a593Smuzhiyun 					 unsigned long event, void *ptr)
534*4882a593Smuzhiyun {
535*4882a593Smuzhiyun 	struct net_device *dev = netdev_notifier_info_to_dev(ptr);
536*4882a593Smuzhiyun 	int err = 0;
537*4882a593Smuzhiyun 
538*4882a593Smuzhiyun 	if (prestera_netdev_check(dev))
539*4882a593Smuzhiyun 		err = prestera_netdev_port_event(dev, event, ptr);
540*4882a593Smuzhiyun 
541*4882a593Smuzhiyun 	return notifier_from_errno(err);
542*4882a593Smuzhiyun }
543*4882a593Smuzhiyun 
prestera_netdev_event_handler_register(struct prestera_switch * sw)544*4882a593Smuzhiyun static int prestera_netdev_event_handler_register(struct prestera_switch *sw)
545*4882a593Smuzhiyun {
546*4882a593Smuzhiyun 	sw->netdev_nb.notifier_call = prestera_netdev_event_handler;
547*4882a593Smuzhiyun 
548*4882a593Smuzhiyun 	return register_netdevice_notifier(&sw->netdev_nb);
549*4882a593Smuzhiyun }
550*4882a593Smuzhiyun 
prestera_netdev_event_handler_unregister(struct prestera_switch * sw)551*4882a593Smuzhiyun static void prestera_netdev_event_handler_unregister(struct prestera_switch *sw)
552*4882a593Smuzhiyun {
553*4882a593Smuzhiyun 	unregister_netdevice_notifier(&sw->netdev_nb);
554*4882a593Smuzhiyun }
555*4882a593Smuzhiyun 
prestera_switch_init(struct prestera_switch * sw)556*4882a593Smuzhiyun static int prestera_switch_init(struct prestera_switch *sw)
557*4882a593Smuzhiyun {
558*4882a593Smuzhiyun 	int err;
559*4882a593Smuzhiyun 
560*4882a593Smuzhiyun 	err = prestera_hw_switch_init(sw);
561*4882a593Smuzhiyun 	if (err) {
562*4882a593Smuzhiyun 		dev_err(prestera_dev(sw), "Failed to init Switch device\n");
563*4882a593Smuzhiyun 		return err;
564*4882a593Smuzhiyun 	}
565*4882a593Smuzhiyun 
566*4882a593Smuzhiyun 	rwlock_init(&sw->port_list_lock);
567*4882a593Smuzhiyun 	INIT_LIST_HEAD(&sw->port_list);
568*4882a593Smuzhiyun 
569*4882a593Smuzhiyun 	err = prestera_switch_set_base_mac_addr(sw);
570*4882a593Smuzhiyun 	if (err)
571*4882a593Smuzhiyun 		return err;
572*4882a593Smuzhiyun 
573*4882a593Smuzhiyun 	err = prestera_netdev_event_handler_register(sw);
574*4882a593Smuzhiyun 	if (err)
575*4882a593Smuzhiyun 		return err;
576*4882a593Smuzhiyun 
577*4882a593Smuzhiyun 	err = prestera_switchdev_init(sw);
578*4882a593Smuzhiyun 	if (err)
579*4882a593Smuzhiyun 		goto err_swdev_register;
580*4882a593Smuzhiyun 
581*4882a593Smuzhiyun 	err = prestera_rxtx_switch_init(sw);
582*4882a593Smuzhiyun 	if (err)
583*4882a593Smuzhiyun 		goto err_rxtx_register;
584*4882a593Smuzhiyun 
585*4882a593Smuzhiyun 	err = prestera_event_handlers_register(sw);
586*4882a593Smuzhiyun 	if (err)
587*4882a593Smuzhiyun 		goto err_handlers_register;
588*4882a593Smuzhiyun 
589*4882a593Smuzhiyun 	err = prestera_devlink_register(sw);
590*4882a593Smuzhiyun 	if (err)
591*4882a593Smuzhiyun 		goto err_dl_register;
592*4882a593Smuzhiyun 
593*4882a593Smuzhiyun 	err = prestera_create_ports(sw);
594*4882a593Smuzhiyun 	if (err)
595*4882a593Smuzhiyun 		goto err_ports_create;
596*4882a593Smuzhiyun 
597*4882a593Smuzhiyun 	return 0;
598*4882a593Smuzhiyun 
599*4882a593Smuzhiyun err_ports_create:
600*4882a593Smuzhiyun 	prestera_devlink_unregister(sw);
601*4882a593Smuzhiyun err_dl_register:
602*4882a593Smuzhiyun 	prestera_event_handlers_unregister(sw);
603*4882a593Smuzhiyun err_handlers_register:
604*4882a593Smuzhiyun 	prestera_rxtx_switch_fini(sw);
605*4882a593Smuzhiyun err_rxtx_register:
606*4882a593Smuzhiyun 	prestera_switchdev_fini(sw);
607*4882a593Smuzhiyun err_swdev_register:
608*4882a593Smuzhiyun 	prestera_netdev_event_handler_unregister(sw);
609*4882a593Smuzhiyun 	prestera_hw_switch_fini(sw);
610*4882a593Smuzhiyun 
611*4882a593Smuzhiyun 	return err;
612*4882a593Smuzhiyun }
613*4882a593Smuzhiyun 
prestera_switch_fini(struct prestera_switch * sw)614*4882a593Smuzhiyun static void prestera_switch_fini(struct prestera_switch *sw)
615*4882a593Smuzhiyun {
616*4882a593Smuzhiyun 	prestera_destroy_ports(sw);
617*4882a593Smuzhiyun 	prestera_devlink_unregister(sw);
618*4882a593Smuzhiyun 	prestera_event_handlers_unregister(sw);
619*4882a593Smuzhiyun 	prestera_rxtx_switch_fini(sw);
620*4882a593Smuzhiyun 	prestera_switchdev_fini(sw);
621*4882a593Smuzhiyun 	prestera_netdev_event_handler_unregister(sw);
622*4882a593Smuzhiyun 	prestera_hw_switch_fini(sw);
623*4882a593Smuzhiyun }
624*4882a593Smuzhiyun 
prestera_device_register(struct prestera_device * dev)625*4882a593Smuzhiyun int prestera_device_register(struct prestera_device *dev)
626*4882a593Smuzhiyun {
627*4882a593Smuzhiyun 	struct prestera_switch *sw;
628*4882a593Smuzhiyun 	int err;
629*4882a593Smuzhiyun 
630*4882a593Smuzhiyun 	sw = prestera_devlink_alloc();
631*4882a593Smuzhiyun 	if (!sw)
632*4882a593Smuzhiyun 		return -ENOMEM;
633*4882a593Smuzhiyun 
634*4882a593Smuzhiyun 	dev->priv = sw;
635*4882a593Smuzhiyun 	sw->dev = dev;
636*4882a593Smuzhiyun 
637*4882a593Smuzhiyun 	err = prestera_switch_init(sw);
638*4882a593Smuzhiyun 	if (err) {
639*4882a593Smuzhiyun 		prestera_devlink_free(sw);
640*4882a593Smuzhiyun 		return err;
641*4882a593Smuzhiyun 	}
642*4882a593Smuzhiyun 
643*4882a593Smuzhiyun 	return 0;
644*4882a593Smuzhiyun }
645*4882a593Smuzhiyun EXPORT_SYMBOL(prestera_device_register);
646*4882a593Smuzhiyun 
prestera_device_unregister(struct prestera_device * dev)647*4882a593Smuzhiyun void prestera_device_unregister(struct prestera_device *dev)
648*4882a593Smuzhiyun {
649*4882a593Smuzhiyun 	struct prestera_switch *sw = dev->priv;
650*4882a593Smuzhiyun 
651*4882a593Smuzhiyun 	prestera_switch_fini(sw);
652*4882a593Smuzhiyun 	prestera_devlink_free(sw);
653*4882a593Smuzhiyun }
654*4882a593Smuzhiyun EXPORT_SYMBOL(prestera_device_unregister);
655*4882a593Smuzhiyun 
prestera_module_init(void)656*4882a593Smuzhiyun static int __init prestera_module_init(void)
657*4882a593Smuzhiyun {
658*4882a593Smuzhiyun 	prestera_wq = alloc_workqueue("prestera", 0, 0);
659*4882a593Smuzhiyun 	if (!prestera_wq)
660*4882a593Smuzhiyun 		return -ENOMEM;
661*4882a593Smuzhiyun 
662*4882a593Smuzhiyun 	return 0;
663*4882a593Smuzhiyun }
664*4882a593Smuzhiyun 
prestera_module_exit(void)665*4882a593Smuzhiyun static void __exit prestera_module_exit(void)
666*4882a593Smuzhiyun {
667*4882a593Smuzhiyun 	destroy_workqueue(prestera_wq);
668*4882a593Smuzhiyun }
669*4882a593Smuzhiyun 
670*4882a593Smuzhiyun module_init(prestera_module_init);
671*4882a593Smuzhiyun module_exit(prestera_module_exit);
672*4882a593Smuzhiyun 
673*4882a593Smuzhiyun MODULE_LICENSE("Dual BSD/GPL");
674*4882a593Smuzhiyun MODULE_DESCRIPTION("Marvell Prestera switch driver");
675