xref: /openbmc/linux/net/dsa/port.c (revision 68198dca)
1 /*
2  * Handling of a single switch port
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/if_bridge.h>
14 #include <linux/notifier.h>
15 #include <linux/of_mdio.h>
16 #include <linux/of_net.h>
17 
18 #include "dsa_priv.h"
19 
20 static int dsa_port_notify(const struct dsa_port *dp, unsigned long e, void *v)
21 {
22 	struct raw_notifier_head *nh = &dp->ds->dst->nh;
23 	int err;
24 
25 	err = raw_notifier_call_chain(nh, e, v);
26 
27 	return notifier_to_errno(err);
28 }
29 
30 int dsa_port_set_state(struct dsa_port *dp, u8 state,
31 		       struct switchdev_trans *trans)
32 {
33 	struct dsa_switch *ds = dp->ds;
34 	int port = dp->index;
35 
36 	if (switchdev_trans_ph_prepare(trans))
37 		return ds->ops->port_stp_state_set ? 0 : -EOPNOTSUPP;
38 
39 	if (ds->ops->port_stp_state_set)
40 		ds->ops->port_stp_state_set(ds, port, state);
41 
42 	if (ds->ops->port_fast_age) {
43 		/* Fast age FDB entries or flush appropriate forwarding database
44 		 * for the given port, if we are moving it from Learning or
45 		 * Forwarding state, to Disabled or Blocking or Listening state.
46 		 */
47 
48 		if ((dp->stp_state == BR_STATE_LEARNING ||
49 		     dp->stp_state == BR_STATE_FORWARDING) &&
50 		    (state == BR_STATE_DISABLED ||
51 		     state == BR_STATE_BLOCKING ||
52 		     state == BR_STATE_LISTENING))
53 			ds->ops->port_fast_age(ds, port);
54 	}
55 
56 	dp->stp_state = state;
57 
58 	return 0;
59 }
60 
61 static void dsa_port_set_state_now(struct dsa_port *dp, u8 state)
62 {
63 	int err;
64 
65 	err = dsa_port_set_state(dp, state, NULL);
66 	if (err)
67 		pr_err("DSA: failed to set STP state %u (%d)\n", state, err);
68 }
69 
70 int dsa_port_enable(struct dsa_port *dp, struct phy_device *phy)
71 {
72 	u8 stp_state = dp->bridge_dev ? BR_STATE_BLOCKING : BR_STATE_FORWARDING;
73 	struct dsa_switch *ds = dp->ds;
74 	int port = dp->index;
75 	int err;
76 
77 	if (ds->ops->port_enable) {
78 		err = ds->ops->port_enable(ds, port, phy);
79 		if (err)
80 			return err;
81 	}
82 
83 	dsa_port_set_state_now(dp, stp_state);
84 
85 	return 0;
86 }
87 
88 void dsa_port_disable(struct dsa_port *dp, struct phy_device *phy)
89 {
90 	struct dsa_switch *ds = dp->ds;
91 	int port = dp->index;
92 
93 	dsa_port_set_state_now(dp, BR_STATE_DISABLED);
94 
95 	if (ds->ops->port_disable)
96 		ds->ops->port_disable(ds, port, phy);
97 }
98 
99 int dsa_port_bridge_join(struct dsa_port *dp, struct net_device *br)
100 {
101 	struct dsa_notifier_bridge_info info = {
102 		.sw_index = dp->ds->index,
103 		.port = dp->index,
104 		.br = br,
105 	};
106 	int err;
107 
108 	/* Here the port is already bridged. Reflect the current configuration
109 	 * so that drivers can program their chips accordingly.
110 	 */
111 	dp->bridge_dev = br;
112 
113 	err = dsa_port_notify(dp, DSA_NOTIFIER_BRIDGE_JOIN, &info);
114 
115 	/* The bridging is rolled back on error */
116 	if (err)
117 		dp->bridge_dev = NULL;
118 
119 	return err;
120 }
121 
122 void dsa_port_bridge_leave(struct dsa_port *dp, struct net_device *br)
123 {
124 	struct dsa_notifier_bridge_info info = {
125 		.sw_index = dp->ds->index,
126 		.port = dp->index,
127 		.br = br,
128 	};
129 	int err;
130 
131 	/* Here the port is already unbridged. Reflect the current configuration
132 	 * so that drivers can program their chips accordingly.
133 	 */
134 	dp->bridge_dev = NULL;
135 
136 	err = dsa_port_notify(dp, DSA_NOTIFIER_BRIDGE_LEAVE, &info);
137 	if (err)
138 		pr_err("DSA: failed to notify DSA_NOTIFIER_BRIDGE_LEAVE\n");
139 
140 	/* Port left the bridge, put in BR_STATE_DISABLED by the bridge layer,
141 	 * so allow it to be in BR_STATE_FORWARDING to be kept functional
142 	 */
143 	dsa_port_set_state_now(dp, BR_STATE_FORWARDING);
144 }
145 
146 int dsa_port_vlan_filtering(struct dsa_port *dp, bool vlan_filtering,
147 			    struct switchdev_trans *trans)
148 {
149 	struct dsa_switch *ds = dp->ds;
150 
151 	/* bridge skips -EOPNOTSUPP, so skip the prepare phase */
152 	if (switchdev_trans_ph_prepare(trans))
153 		return 0;
154 
155 	if (ds->ops->port_vlan_filtering)
156 		return ds->ops->port_vlan_filtering(ds, dp->index,
157 						    vlan_filtering);
158 
159 	return 0;
160 }
161 
162 int dsa_port_ageing_time(struct dsa_port *dp, clock_t ageing_clock,
163 			 struct switchdev_trans *trans)
164 {
165 	unsigned long ageing_jiffies = clock_t_to_jiffies(ageing_clock);
166 	unsigned int ageing_time = jiffies_to_msecs(ageing_jiffies);
167 	struct dsa_notifier_ageing_time_info info = {
168 		.ageing_time = ageing_time,
169 		.trans = trans,
170 	};
171 
172 	if (switchdev_trans_ph_prepare(trans))
173 		return dsa_port_notify(dp, DSA_NOTIFIER_AGEING_TIME, &info);
174 
175 	dp->ageing_time = ageing_time;
176 
177 	return dsa_port_notify(dp, DSA_NOTIFIER_AGEING_TIME, &info);
178 }
179 
180 int dsa_port_fdb_add(struct dsa_port *dp, const unsigned char *addr,
181 		     u16 vid)
182 {
183 	struct dsa_notifier_fdb_info info = {
184 		.sw_index = dp->ds->index,
185 		.port = dp->index,
186 		.addr = addr,
187 		.vid = vid,
188 	};
189 
190 	return dsa_port_notify(dp, DSA_NOTIFIER_FDB_ADD, &info);
191 }
192 
193 int dsa_port_fdb_del(struct dsa_port *dp, const unsigned char *addr,
194 		     u16 vid)
195 {
196 	struct dsa_notifier_fdb_info info = {
197 		.sw_index = dp->ds->index,
198 		.port = dp->index,
199 		.addr = addr,
200 		.vid = vid,
201 
202 	};
203 
204 	return dsa_port_notify(dp, DSA_NOTIFIER_FDB_DEL, &info);
205 }
206 
207 int dsa_port_fdb_dump(struct dsa_port *dp, dsa_fdb_dump_cb_t *cb, void *data)
208 {
209 	struct dsa_switch *ds = dp->ds;
210 	int port = dp->index;
211 
212 	if (!ds->ops->port_fdb_dump)
213 		return -EOPNOTSUPP;
214 
215 	return ds->ops->port_fdb_dump(ds, port, cb, data);
216 }
217 
218 int dsa_port_mdb_add(const struct dsa_port *dp,
219 		     const struct switchdev_obj_port_mdb *mdb,
220 		     struct switchdev_trans *trans)
221 {
222 	struct dsa_notifier_mdb_info info = {
223 		.sw_index = dp->ds->index,
224 		.port = dp->index,
225 		.trans = trans,
226 		.mdb = mdb,
227 	};
228 
229 	return dsa_port_notify(dp, DSA_NOTIFIER_MDB_ADD, &info);
230 }
231 
232 int dsa_port_mdb_del(const struct dsa_port *dp,
233 		     const struct switchdev_obj_port_mdb *mdb)
234 {
235 	struct dsa_notifier_mdb_info info = {
236 		.sw_index = dp->ds->index,
237 		.port = dp->index,
238 		.mdb = mdb,
239 	};
240 
241 	return dsa_port_notify(dp, DSA_NOTIFIER_MDB_DEL, &info);
242 }
243 
244 int dsa_port_vlan_add(struct dsa_port *dp,
245 		      const struct switchdev_obj_port_vlan *vlan,
246 		      struct switchdev_trans *trans)
247 {
248 	struct dsa_notifier_vlan_info info = {
249 		.sw_index = dp->ds->index,
250 		.port = dp->index,
251 		.trans = trans,
252 		.vlan = vlan,
253 	};
254 
255 	if (br_vlan_enabled(dp->bridge_dev))
256 		return dsa_port_notify(dp, DSA_NOTIFIER_VLAN_ADD, &info);
257 
258 	return 0;
259 }
260 
261 int dsa_port_vlan_del(struct dsa_port *dp,
262 		      const struct switchdev_obj_port_vlan *vlan)
263 {
264 	struct dsa_notifier_vlan_info info = {
265 		.sw_index = dp->ds->index,
266 		.port = dp->index,
267 		.vlan = vlan,
268 	};
269 
270 	if (br_vlan_enabled(dp->bridge_dev))
271 		return dsa_port_notify(dp, DSA_NOTIFIER_VLAN_DEL, &info);
272 
273 	return 0;
274 }
275 
276 int dsa_port_fixed_link_register_of(struct dsa_port *dp)
277 {
278 	struct device_node *dn = dp->dn;
279 	struct dsa_switch *ds = dp->ds;
280 	struct phy_device *phydev;
281 	int port = dp->index;
282 	int mode;
283 	int err;
284 
285 	if (of_phy_is_fixed_link(dn)) {
286 		err = of_phy_register_fixed_link(dn);
287 		if (err) {
288 			dev_err(ds->dev,
289 				"failed to register the fixed PHY of port %d\n",
290 				port);
291 			return err;
292 		}
293 
294 		phydev = of_phy_find_device(dn);
295 
296 		mode = of_get_phy_mode(dn);
297 		if (mode < 0)
298 			mode = PHY_INTERFACE_MODE_NA;
299 		phydev->interface = mode;
300 
301 		genphy_config_init(phydev);
302 		genphy_read_status(phydev);
303 
304 		if (ds->ops->adjust_link)
305 			ds->ops->adjust_link(ds, port, phydev);
306 
307 		put_device(&phydev->mdio.dev);
308 	}
309 
310 	return 0;
311 }
312 
313 void dsa_port_fixed_link_unregister_of(struct dsa_port *dp)
314 {
315 	struct device_node *dn = dp->dn;
316 
317 	if (of_phy_is_fixed_link(dn))
318 		of_phy_deregister_fixed_link(dn);
319 }
320