xref: /openbmc/linux/net/dsa/switch.c (revision 3213486f)
1 /*
2  * Handling of a single switch chip, part of a switch fabric
3  *
4  * Copyright (c) 2017 Savoir-faire Linux Inc.
5  *	Vivien Didelot <vivien.didelot@savoirfairelinux.com>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  */
12 
13 #include <linux/netdevice.h>
14 #include <linux/notifier.h>
15 #include <linux/if_vlan.h>
16 #include <net/switchdev.h>
17 
18 #include "dsa_priv.h"
19 
20 static unsigned int dsa_switch_fastest_ageing_time(struct dsa_switch *ds,
21 						   unsigned int ageing_time)
22 {
23 	int i;
24 
25 	for (i = 0; i < ds->num_ports; ++i) {
26 		struct dsa_port *dp = &ds->ports[i];
27 
28 		if (dp->ageing_time && dp->ageing_time < ageing_time)
29 			ageing_time = dp->ageing_time;
30 	}
31 
32 	return ageing_time;
33 }
34 
35 static int dsa_switch_ageing_time(struct dsa_switch *ds,
36 				  struct dsa_notifier_ageing_time_info *info)
37 {
38 	unsigned int ageing_time = info->ageing_time;
39 	struct switchdev_trans *trans = info->trans;
40 
41 	if (switchdev_trans_ph_prepare(trans)) {
42 		if (ds->ageing_time_min && ageing_time < ds->ageing_time_min)
43 			return -ERANGE;
44 		if (ds->ageing_time_max && ageing_time > ds->ageing_time_max)
45 			return -ERANGE;
46 		return 0;
47 	}
48 
49 	/* Program the fastest ageing time in case of multiple bridges */
50 	ageing_time = dsa_switch_fastest_ageing_time(ds, ageing_time);
51 
52 	if (ds->ops->set_ageing_time)
53 		return ds->ops->set_ageing_time(ds, ageing_time);
54 
55 	return 0;
56 }
57 
58 static int dsa_switch_bridge_join(struct dsa_switch *ds,
59 				  struct dsa_notifier_bridge_info *info)
60 {
61 	if (ds->index == info->sw_index && ds->ops->port_bridge_join)
62 		return ds->ops->port_bridge_join(ds, info->port, info->br);
63 
64 	if (ds->index != info->sw_index && ds->ops->crosschip_bridge_join)
65 		return ds->ops->crosschip_bridge_join(ds, info->sw_index,
66 						      info->port, info->br);
67 
68 	return 0;
69 }
70 
71 static int dsa_switch_bridge_leave(struct dsa_switch *ds,
72 				   struct dsa_notifier_bridge_info *info)
73 {
74 	if (ds->index == info->sw_index && ds->ops->port_bridge_leave)
75 		ds->ops->port_bridge_leave(ds, info->port, info->br);
76 
77 	if (ds->index != info->sw_index && ds->ops->crosschip_bridge_leave)
78 		ds->ops->crosschip_bridge_leave(ds, info->sw_index, info->port,
79 						info->br);
80 
81 	return 0;
82 }
83 
84 static int dsa_switch_fdb_add(struct dsa_switch *ds,
85 			      struct dsa_notifier_fdb_info *info)
86 {
87 	int port = dsa_towards_port(ds, info->sw_index, info->port);
88 
89 	if (!ds->ops->port_fdb_add)
90 		return -EOPNOTSUPP;
91 
92 	return ds->ops->port_fdb_add(ds, port, info->addr, info->vid);
93 }
94 
95 static int dsa_switch_fdb_del(struct dsa_switch *ds,
96 			      struct dsa_notifier_fdb_info *info)
97 {
98 	int port = dsa_towards_port(ds, info->sw_index, info->port);
99 
100 	if (!ds->ops->port_fdb_del)
101 		return -EOPNOTSUPP;
102 
103 	return ds->ops->port_fdb_del(ds, port, info->addr, info->vid);
104 }
105 
106 static int
107 dsa_switch_mdb_prepare_bitmap(struct dsa_switch *ds,
108 			      const struct switchdev_obj_port_mdb *mdb,
109 			      const unsigned long *bitmap)
110 {
111 	int port, err;
112 
113 	if (!ds->ops->port_mdb_prepare || !ds->ops->port_mdb_add)
114 		return -EOPNOTSUPP;
115 
116 	for_each_set_bit(port, bitmap, ds->num_ports) {
117 		err = ds->ops->port_mdb_prepare(ds, port, mdb);
118 		if (err)
119 			return err;
120 	}
121 
122 	return 0;
123 }
124 
125 static void dsa_switch_mdb_add_bitmap(struct dsa_switch *ds,
126 				      const struct switchdev_obj_port_mdb *mdb,
127 				      const unsigned long *bitmap)
128 {
129 	int port;
130 
131 	for_each_set_bit(port, bitmap, ds->num_ports)
132 		ds->ops->port_mdb_add(ds, port, mdb);
133 }
134 
135 static int dsa_switch_mdb_add(struct dsa_switch *ds,
136 			      struct dsa_notifier_mdb_info *info)
137 {
138 	const struct switchdev_obj_port_mdb *mdb = info->mdb;
139 	struct switchdev_trans *trans = info->trans;
140 	int port;
141 
142 	/* Build a mask of Multicast group members */
143 	bitmap_zero(ds->bitmap, ds->num_ports);
144 	if (ds->index == info->sw_index)
145 		set_bit(info->port, ds->bitmap);
146 	for (port = 0; port < ds->num_ports; port++)
147 		if (dsa_is_dsa_port(ds, port))
148 			set_bit(port, ds->bitmap);
149 
150 	if (switchdev_trans_ph_prepare(trans))
151 		return dsa_switch_mdb_prepare_bitmap(ds, mdb, ds->bitmap);
152 
153 	dsa_switch_mdb_add_bitmap(ds, mdb, ds->bitmap);
154 
155 	return 0;
156 }
157 
158 static int dsa_switch_mdb_del(struct dsa_switch *ds,
159 			      struct dsa_notifier_mdb_info *info)
160 {
161 	const struct switchdev_obj_port_mdb *mdb = info->mdb;
162 
163 	if (!ds->ops->port_mdb_del)
164 		return -EOPNOTSUPP;
165 
166 	if (ds->index == info->sw_index)
167 		return ds->ops->port_mdb_del(ds, info->port, mdb);
168 
169 	return 0;
170 }
171 
172 static int dsa_port_vlan_device_check(struct net_device *vlan_dev,
173 				      int vlan_dev_vid,
174 				      void *arg)
175 {
176 	struct switchdev_obj_port_vlan *vlan = arg;
177 	u16 vid;
178 
179 	for (vid = vlan->vid_begin; vid <= vlan->vid_end; ++vid) {
180 		if (vid == vlan_dev_vid)
181 			return -EBUSY;
182 	}
183 
184 	return 0;
185 }
186 
187 static int dsa_port_vlan_check(struct dsa_switch *ds, int port,
188 			       const struct switchdev_obj_port_vlan *vlan)
189 {
190 	const struct dsa_port *dp = dsa_to_port(ds, port);
191 	int err = 0;
192 
193 	/* Device is not bridged, let it proceed with the VLAN device
194 	 * creation.
195 	 */
196 	if (!dp->bridge_dev)
197 		return err;
198 
199 	/* dsa_slave_vlan_rx_{add,kill}_vid() cannot use the prepare pharse and
200 	 * already checks whether there is an overlapping bridge VLAN entry
201 	 * with the same VID, so here we only need to check that if we are
202 	 * adding a bridge VLAN entry there is not an overlapping VLAN device
203 	 * claiming that VID.
204 	 */
205 	return vlan_for_each(dp->slave, dsa_port_vlan_device_check,
206 			     (void *)vlan);
207 }
208 
209 static int
210 dsa_switch_vlan_prepare_bitmap(struct dsa_switch *ds,
211 			       const struct switchdev_obj_port_vlan *vlan,
212 			       const unsigned long *bitmap)
213 {
214 	int port, err;
215 
216 	if (!ds->ops->port_vlan_prepare || !ds->ops->port_vlan_add)
217 		return -EOPNOTSUPP;
218 
219 	for_each_set_bit(port, bitmap, ds->num_ports) {
220 		err = dsa_port_vlan_check(ds, port, vlan);
221 		if (err)
222 			return err;
223 
224 		err = ds->ops->port_vlan_prepare(ds, port, vlan);
225 		if (err)
226 			return err;
227 	}
228 
229 	return 0;
230 }
231 
232 static void
233 dsa_switch_vlan_add_bitmap(struct dsa_switch *ds,
234 			   const struct switchdev_obj_port_vlan *vlan,
235 			   const unsigned long *bitmap)
236 {
237 	int port;
238 
239 	for_each_set_bit(port, bitmap, ds->num_ports)
240 		ds->ops->port_vlan_add(ds, port, vlan);
241 }
242 
243 static int dsa_switch_vlan_add(struct dsa_switch *ds,
244 			       struct dsa_notifier_vlan_info *info)
245 {
246 	const struct switchdev_obj_port_vlan *vlan = info->vlan;
247 	struct switchdev_trans *trans = info->trans;
248 	int port;
249 
250 	/* Build a mask of VLAN members */
251 	bitmap_zero(ds->bitmap, ds->num_ports);
252 	if (ds->index == info->sw_index)
253 		set_bit(info->port, ds->bitmap);
254 	for (port = 0; port < ds->num_ports; port++)
255 		if (dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port))
256 			set_bit(port, ds->bitmap);
257 
258 	if (switchdev_trans_ph_prepare(trans))
259 		return dsa_switch_vlan_prepare_bitmap(ds, vlan, ds->bitmap);
260 
261 	dsa_switch_vlan_add_bitmap(ds, vlan, ds->bitmap);
262 
263 	return 0;
264 }
265 
266 static int dsa_switch_vlan_del(struct dsa_switch *ds,
267 			       struct dsa_notifier_vlan_info *info)
268 {
269 	const struct switchdev_obj_port_vlan *vlan = info->vlan;
270 
271 	if (!ds->ops->port_vlan_del)
272 		return -EOPNOTSUPP;
273 
274 	if (ds->index == info->sw_index)
275 		return ds->ops->port_vlan_del(ds, info->port, vlan);
276 
277 	return 0;
278 }
279 
280 static int dsa_switch_event(struct notifier_block *nb,
281 			    unsigned long event, void *info)
282 {
283 	struct dsa_switch *ds = container_of(nb, struct dsa_switch, nb);
284 	int err;
285 
286 	switch (event) {
287 	case DSA_NOTIFIER_AGEING_TIME:
288 		err = dsa_switch_ageing_time(ds, info);
289 		break;
290 	case DSA_NOTIFIER_BRIDGE_JOIN:
291 		err = dsa_switch_bridge_join(ds, info);
292 		break;
293 	case DSA_NOTIFIER_BRIDGE_LEAVE:
294 		err = dsa_switch_bridge_leave(ds, info);
295 		break;
296 	case DSA_NOTIFIER_FDB_ADD:
297 		err = dsa_switch_fdb_add(ds, info);
298 		break;
299 	case DSA_NOTIFIER_FDB_DEL:
300 		err = dsa_switch_fdb_del(ds, info);
301 		break;
302 	case DSA_NOTIFIER_MDB_ADD:
303 		err = dsa_switch_mdb_add(ds, info);
304 		break;
305 	case DSA_NOTIFIER_MDB_DEL:
306 		err = dsa_switch_mdb_del(ds, info);
307 		break;
308 	case DSA_NOTIFIER_VLAN_ADD:
309 		err = dsa_switch_vlan_add(ds, info);
310 		break;
311 	case DSA_NOTIFIER_VLAN_DEL:
312 		err = dsa_switch_vlan_del(ds, info);
313 		break;
314 	default:
315 		err = -EOPNOTSUPP;
316 		break;
317 	}
318 
319 	/* Non-switchdev operations cannot be rolled back. If a DSA driver
320 	 * returns an error during the chained call, switch chips may be in an
321 	 * inconsistent state.
322 	 */
323 	if (err)
324 		dev_dbg(ds->dev, "breaking chain for DSA event %lu (%d)\n",
325 			event, err);
326 
327 	return notifier_from_errno(err);
328 }
329 
330 int dsa_switch_register_notifier(struct dsa_switch *ds)
331 {
332 	ds->nb.notifier_call = dsa_switch_event;
333 
334 	return raw_notifier_chain_register(&ds->dst->nh, &ds->nb);
335 }
336 
337 void dsa_switch_unregister_notifier(struct dsa_switch *ds)
338 {
339 	int err;
340 
341 	err = raw_notifier_chain_unregister(&ds->dst->nh, &ds->nb);
342 	if (err)
343 		dev_err(ds->dev, "failed to unregister notifier (%d)\n", err);
344 }
345