blob: 263593ce94a8199ce5880fe03d0a589b291632c6 [file] [log] [blame]
Thomas Gleixner2874c5f2019-05-27 08:55:01 +02001/* SPDX-License-Identifier: GPL-2.0-or-later */
Lennert Buytenhek91da11f2008-10-07 13:44:02 +00002/*
3 * net/dsa/dsa_priv.h - Hardware switch handling
Lennert Buytenheke84665c2009-03-20 09:52:09 +00004 * Copyright (c) 2008-2009 Marvell Semiconductor
Lennert Buytenhek91da11f2008-10-07 13:44:02 +00005 */
6
7#ifndef __DSA_PRIV_H
8#define __DSA_PRIV_H
9
Vladimir Oltean412a1522020-09-23 14:40:37 -070010#include <linux/if_bridge.h>
Lennert Buytenhek91da11f2008-10-07 13:44:02 +000011#include <linux/phy.h>
Alexander Duyck50753142014-09-15 13:00:19 -040012#include <linux/netdevice.h>
Florian Fainelli04ff53f2015-07-31 11:42:57 -070013#include <linux/netpoll.h>
Vivien Didelotea5dd342017-05-17 15:46:03 -040014#include <net/dsa.h>
Alexander Lobakine131a562020-04-21 16:41:08 +030015#include <net/gro_cells.h>
Alexander Duyck50753142014-09-15 13:00:19 -040016
Vivien Didelot52c96f92017-05-19 17:00:51 -040017enum {
Vivien Didelot1faabf72017-05-19 17:00:52 -040018 DSA_NOTIFIER_AGEING_TIME,
Vivien Didelot52c96f92017-05-19 17:00:51 -040019 DSA_NOTIFIER_BRIDGE_JOIN,
20 DSA_NOTIFIER_BRIDGE_LEAVE,
Vivien Didelot685fb6a2017-05-19 17:00:53 -040021 DSA_NOTIFIER_FDB_ADD,
22 DSA_NOTIFIER_FDB_DEL,
Tobias Waldekranz058102a2021-01-13 09:42:53 +010023 DSA_NOTIFIER_LAG_CHANGE,
24 DSA_NOTIFIER_LAG_JOIN,
25 DSA_NOTIFIER_LAG_LEAVE,
Vivien Didelot8ae5bcd2017-05-19 17:00:54 -040026 DSA_NOTIFIER_MDB_ADD,
27 DSA_NOTIFIER_MDB_DEL,
Vivien Didelotd0c627b2017-05-19 17:00:55 -040028 DSA_NOTIFIER_VLAN_ADD,
29 DSA_NOTIFIER_VLAN_DEL,
Vladimir Olteanbfcb8132020-03-27 21:55:42 +020030 DSA_NOTIFIER_MTU,
Vladimir Oltean53da0eb2021-01-29 03:00:06 +020031 DSA_NOTIFIER_TAG_PROTO,
Vivien Didelot52c96f92017-05-19 17:00:51 -040032};
33
Vivien Didelot1faabf72017-05-19 17:00:52 -040034/* DSA_NOTIFIER_AGEING_TIME */
35struct dsa_notifier_ageing_time_info {
Vivien Didelot1faabf72017-05-19 17:00:52 -040036 unsigned int ageing_time;
Vivien Didelot1faabf72017-05-19 17:00:52 -040037};
38
Vivien Didelot52c96f92017-05-19 17:00:51 -040039/* DSA_NOTIFIER_BRIDGE_* */
40struct dsa_notifier_bridge_info {
41 struct net_device *br;
Vladimir Olteanf66a6a62020-05-10 19:37:41 +030042 int tree_index;
Vivien Didelot52c96f92017-05-19 17:00:51 -040043 int sw_index;
44 int port;
45};
46
Vivien Didelot685fb6a2017-05-19 17:00:53 -040047/* DSA_NOTIFIER_FDB_* */
48struct dsa_notifier_fdb_info {
Vivien Didelot685fb6a2017-05-19 17:00:53 -040049 int sw_index;
50 int port;
Arkadi Sharshevsky2acf4e62017-08-06 16:15:41 +030051 const unsigned char *addr;
52 u16 vid;
Vivien Didelot685fb6a2017-05-19 17:00:53 -040053};
54
Vivien Didelot8ae5bcd2017-05-19 17:00:54 -040055/* DSA_NOTIFIER_MDB_* */
56struct dsa_notifier_mdb_info {
57 const struct switchdev_obj_port_mdb *mdb;
Vivien Didelot8ae5bcd2017-05-19 17:00:54 -040058 int sw_index;
59 int port;
60};
61
Tobias Waldekranz058102a2021-01-13 09:42:53 +010062/* DSA_NOTIFIER_LAG_* */
63struct dsa_notifier_lag_info {
64 struct net_device *lag;
65 int sw_index;
66 int port;
67
68 struct netdev_lag_upper_info *info;
69};
70
Vivien Didelotd0c627b2017-05-19 17:00:55 -040071/* DSA_NOTIFIER_VLAN_* */
72struct dsa_notifier_vlan_info {
73 const struct switchdev_obj_port_vlan *vlan;
Vivien Didelotd0c627b2017-05-19 17:00:55 -040074 int sw_index;
75 int port;
76};
77
Vladimir Olteanbfcb8132020-03-27 21:55:42 +020078/* DSA_NOTIFIER_MTU */
79struct dsa_notifier_mtu_info {
80 bool propagate_upstream;
81 int sw_index;
82 int port;
83 int mtu;
84};
85
Vladimir Oltean53da0eb2021-01-29 03:00:06 +020086/* DSA_NOTIFIER_TAG_PROTO_* */
87struct dsa_notifier_tag_proto_info {
88 const struct dsa_device_ops *tag_ops;
89};
90
Vladimir Olteanc4bb76a2021-01-06 11:51:32 +020091struct dsa_switchdev_event_work {
92 struct dsa_switch *ds;
93 int port;
94 struct work_struct work;
95 unsigned long event;
96 /* Specific for SWITCHDEV_FDB_ADD_TO_DEVICE and
97 * SWITCHDEV_FDB_DEL_TO_DEVICE
98 */
99 unsigned char addr[ETH_ALEN];
100 u16 vid;
101};
102
Lennert Buytenhek91da11f2008-10-07 13:44:02 +0000103struct dsa_slave_priv {
Vivien Didelot15240242017-09-29 17:19:18 -0400104 /* Copy of CPU port xmit for faster access in slave transmit hot path */
Florian Fainelli4ed70ce2015-07-31 11:42:56 -0700105 struct sk_buff * (*xmit)(struct sk_buff *skb,
Alexander Duyck50753142014-09-15 13:00:19 -0400106 struct net_device *dev);
Lennert Buytenheke84665c2009-03-20 09:52:09 +0000107
Alexander Lobakine131a562020-04-21 16:41:08 +0300108 struct gro_cells gcells;
109
Vivien Didelotafdcf152017-01-27 15:29:39 -0500110 /* DSA port data, such as switch, port index, etc. */
111 struct dsa_port *dp;
Lennert Buytenheke84665c2009-03-20 09:52:09 +0000112
Florian Fainelli04ff53f2015-07-31 11:42:57 -0700113#ifdef CONFIG_NET_POLL_CONTROLLER
114 struct netpoll *netpoll;
115#endif
Florian Fainellif50f2122017-01-30 12:41:40 -0800116
117 /* TC context */
118 struct list_head mall_tc_list;
Lennert Buytenhek91da11f2008-10-07 13:44:02 +0000119};
120
Lennert Buytenhek91da11f2008-10-07 13:44:02 +0000121/* dsa.c */
Andrew Lunnc39e2a12019-04-28 19:37:18 +0200122const struct dsa_device_ops *dsa_tag_driver_get(int tag_protocol);
Andrew Lunn4dad81e2019-04-28 19:37:19 +0200123void dsa_tag_driver_put(const struct dsa_device_ops *ops);
Vladimir Oltean53da0eb2021-01-29 03:00:06 +0200124const struct dsa_device_ops *dsa_find_tagger_by_name(const char *buf);
Andrew Lunnc39e2a12019-04-28 19:37:18 +0200125
Arkadi Sharshevskyc9eb3e02017-08-06 16:15:42 +0300126bool dsa_schedule_work(struct work_struct *work);
Florian Fainelli98cdb482018-09-07 11:09:02 -0700127const char *dsa_tag_protocol_to_str(const struct dsa_device_ops *ops);
Lennert Buytenhek91da11f2008-10-07 13:44:02 +0000128
Vivien Didelotf2f23562017-09-19 11:57:00 -0400129/* master.c */
Vivien Didelot17a22fc2017-11-06 16:11:45 -0500130int dsa_master_setup(struct net_device *dev, struct dsa_port *cpu_dp);
131void dsa_master_teardown(struct net_device *dev);
Vivien Didelotf2f23562017-09-19 11:57:00 -0400132
Vivien Didelot2231c432017-10-16 11:12:17 -0400133static inline struct net_device *dsa_master_find_slave(struct net_device *dev,
134 int device, int port)
Vivien Didelot3775b1b2017-09-29 17:19:15 -0400135{
Vivien Didelot2f657a62017-09-29 17:19:20 -0400136 struct dsa_port *cpu_dp = dev->dsa_ptr;
137 struct dsa_switch_tree *dst = cpu_dp->dst;
Vivien Didelot7b9a2f42019-10-21 16:51:18 -0400138 struct dsa_port *dp;
Vivien Didelot3775b1b2017-09-29 17:19:15 -0400139
Vivien Didelot7b9a2f42019-10-21 16:51:18 -0400140 list_for_each_entry(dp, &dst->ports, list)
141 if (dp->ds->index == device && dp->index == port &&
142 dp->type == DSA_PORT_TYPE_USER)
143 return dp->slave;
Vivien Didelot3775b1b2017-09-29 17:19:15 -0400144
Vivien Didelot7b9a2f42019-10-21 16:51:18 -0400145 return NULL;
Vivien Didelot3775b1b2017-09-29 17:19:15 -0400146}
147
Vivien Didelota40c1752017-05-19 17:00:44 -0400148/* port.c */
Vladimir Oltean53da0eb2021-01-29 03:00:06 +0200149void dsa_port_set_tag_protocol(struct dsa_port *cpu_dp,
150 const struct dsa_device_ops *tag_ops);
Vladimir Olteanbae33f22021-01-09 02:01:50 +0200151int dsa_port_set_state(struct dsa_port *dp, u8 state);
Russell King8640f8d2020-03-03 15:01:46 +0000152int dsa_port_enable_rt(struct dsa_port *dp, struct phy_device *phy);
Vivien Didelotfb8a6a22017-09-22 19:01:56 -0400153int dsa_port_enable(struct dsa_port *dp, struct phy_device *phy);
Russell King8640f8d2020-03-03 15:01:46 +0000154void dsa_port_disable_rt(struct dsa_port *dp);
Andrew Lunn75104db2019-02-24 20:44:43 +0100155void dsa_port_disable(struct dsa_port *dp);
Vivien Didelotcfbed322017-05-19 17:00:45 -0400156int dsa_port_bridge_join(struct dsa_port *dp, struct net_device *br);
157void dsa_port_bridge_leave(struct dsa_port *dp, struct net_device *br);
Tobias Waldekranz058102a2021-01-13 09:42:53 +0100158int dsa_port_lag_change(struct dsa_port *dp,
159 struct netdev_lag_lower_state_info *linfo);
160int dsa_port_lag_join(struct dsa_port *dp, struct net_device *lag_dev,
161 struct netdev_lag_upper_info *uinfo);
162void dsa_port_lag_leave(struct dsa_port *dp, struct net_device *lag_dev);
Vladimir Olteanbae33f22021-01-09 02:01:50 +0200163int dsa_port_vlan_filtering(struct dsa_port *dp, bool vlan_filtering);
Russell King54a0ed02020-05-12 20:20:25 +0300164bool dsa_port_skip_vlan_configuration(struct dsa_port *dp);
Vladimir Olteanbae33f22021-01-09 02:01:50 +0200165int dsa_port_ageing_time(struct dsa_port *dp, clock_t ageing_clock);
Vladimir Olteanbfcb8132020-03-27 21:55:42 +0200166int dsa_port_mtu_change(struct dsa_port *dp, int new_mtu,
167 bool propagate_upstream);
Arkadi Sharshevsky2acf4e62017-08-06 16:15:41 +0300168int dsa_port_fdb_add(struct dsa_port *dp, const unsigned char *addr,
169 u16 vid);
170int dsa_port_fdb_del(struct dsa_port *dp, const unsigned char *addr,
171 u16 vid);
Vivien Didelotde40fc52017-09-20 19:32:14 -0400172int dsa_port_fdb_dump(struct dsa_port *dp, dsa_fdb_dump_cb_t *cb, void *data);
Andrew Lunnbb9f603172017-11-09 23:11:01 +0100173int dsa_port_mdb_add(const struct dsa_port *dp,
Vladimir Olteanffb68fc2021-01-09 02:01:48 +0200174 const struct switchdev_obj_port_mdb *mdb);
Andrew Lunnbb9f603172017-11-09 23:11:01 +0100175int dsa_port_mdb_del(const struct dsa_port *dp,
Vivien Didelot3a9afea2017-05-19 17:00:49 -0400176 const struct switchdev_obj_port_mdb *mdb);
Vladimir Olteanbae33f22021-01-09 02:01:50 +0200177int dsa_port_pre_bridge_flags(const struct dsa_port *dp, unsigned long flags);
178int dsa_port_bridge_flags(const struct dsa_port *dp, unsigned long flags);
179int dsa_port_mrouter(struct dsa_port *dp, bool mrouter);
Vivien Didelot076e7132017-05-19 17:00:50 -0400180int dsa_port_vlan_add(struct dsa_port *dp,
Vladimir Olteanffb68fc2021-01-09 02:01:48 +0200181 const struct switchdev_obj_port_vlan *vlan);
Vivien Didelot076e7132017-05-19 17:00:50 -0400182int dsa_port_vlan_del(struct dsa_port *dp,
183 const struct switchdev_obj_port_vlan *vlan);
Sebastian Reichel33615362018-01-23 16:03:46 +0100184int dsa_port_link_register_of(struct dsa_port *dp);
185void dsa_port_link_unregister_of(struct dsa_port *dp);
Ioana Ciornei77373d42019-05-28 20:38:15 +0300186extern const struct phylink_mac_ops dsa_port_phylink_mac_ops;
Vivien Didelot57ab1ca2017-10-26 10:50:07 -0400187
Tobias Waldekranz058102a2021-01-13 09:42:53 +0100188static inline bool dsa_port_offloads_netdev(struct dsa_port *dp,
189 struct net_device *dev)
190{
191 /* Switchdev offloading can be configured on: */
192
193 if (dev == dp->slave)
Vladimir Oltean99b82022021-02-03 01:31:09 +0200194 /* DSA ports directly connected to a bridge, and event
195 * was emitted for the ports themselves.
196 */
197 return true;
198
199 if (dp->bridge_dev == dev)
200 /* DSA ports connected to a bridge, and event was emitted
201 * for the bridge.
202 */
Tobias Waldekranz058102a2021-01-13 09:42:53 +0100203 return true;
204
205 if (dp->lag_dev == dev)
206 /* DSA ports connected to a bridge via a LAG */
207 return true;
208
209 return false;
210}
211
Lennert Buytenhek91da11f2008-10-07 13:44:02 +0000212/* slave.c */
Alexander Duyck50753142014-09-15 13:00:19 -0400213extern const struct dsa_device_ops notag_netdev_ops;
Lennert Buytenhek91da11f2008-10-07 13:44:02 +0000214void dsa_slave_mii_bus_init(struct dsa_switch *ds);
Vivien Didelot951259aa2017-10-27 15:55:19 -0400215int dsa_slave_create(struct dsa_port *dp);
Neil Armstrongcda5c152015-12-07 13:57:35 +0100216void dsa_slave_destroy(struct net_device *slave_dev);
Florian Fainelli24462542014-09-18 17:31:22 -0700217int dsa_slave_suspend(struct net_device *slave_dev);
218int dsa_slave_resume(struct net_device *slave_dev);
Vivien Didelot88e4f0c2017-02-03 13:20:16 -0500219int dsa_slave_register_notifier(void);
220void dsa_slave_unregister_notifier(void);
Vladimir Oltean53da0eb2021-01-29 03:00:06 +0200221void dsa_slave_setup_tagger(struct net_device *slave);
222int dsa_slave_change_mtu(struct net_device *dev, int new_mtu);
Lennert Buytenhek91da11f2008-10-07 13:44:02 +0000223
Vivien Didelotd9450972017-10-16 11:12:15 -0400224static inline struct dsa_port *dsa_slave_to_port(const struct net_device *dev)
225{
226 struct dsa_slave_priv *p = netdev_priv(dev);
227
228 return p->dp;
229}
230
Vivien Didelotd0006b02017-10-16 11:12:16 -0400231static inline struct net_device *
232dsa_slave_to_master(const struct net_device *dev)
233{
234 struct dsa_port *dp = dsa_slave_to_port(dev);
235
Vivien Didelotf8b8b1c2017-10-16 11:12:18 -0400236 return dp->cpu_dp->master;
Vivien Didelotd0006b02017-10-16 11:12:16 -0400237}
238
Vladimir Oltean412a1522020-09-23 14:40:37 -0700239/* If under a bridge with vlan_filtering=0, make sure to send pvid-tagged
240 * frames as untagged, since the bridge will not untag them.
241 */
242static inline struct sk_buff *dsa_untag_bridge_pvid(struct sk_buff *skb)
243{
244 struct dsa_port *dp = dsa_slave_to_port(skb->dev);
Vladimir Oltean412a1522020-09-23 14:40:37 -0700245 struct net_device *br = dp->bridge_dev;
246 struct net_device *dev = skb->dev;
247 struct net_device *upper_dev;
Vladimir Oltean412a1522020-09-23 14:40:37 -0700248 u16 vid, pvid, proto;
249 int err;
250
251 if (!br || br_vlan_enabled(br))
252 return skb;
253
254 err = br_vlan_get_proto(br, &proto);
255 if (err)
256 return skb;
257
258 /* Move VLAN tag from data to hwaccel */
Florian Fainellia3482922020-10-01 19:42:14 -0700259 if (!skb_vlan_tag_present(skb) && skb->protocol == htons(proto)) {
Vladimir Oltean412a1522020-09-23 14:40:37 -0700260 skb = skb_vlan_untag(skb);
261 if (!skb)
262 return NULL;
263 }
264
265 if (!skb_vlan_tag_present(skb))
266 return skb;
267
268 vid = skb_vlan_tag_get_id(skb);
269
270 /* We already run under an RCU read-side critical section since
271 * we are called from netif_receive_skb_list_internal().
272 */
273 err = br_vlan_get_pvid_rcu(dev, &pvid);
274 if (err)
275 return skb;
276
277 if (vid != pvid)
278 return skb;
279
280 /* The sad part about attempting to untag from DSA is that we
281 * don't know, unless we check, if the skb will end up in
282 * the bridge's data path - br_allowed_ingress() - or not.
283 * For example, there might be an 8021q upper for the
284 * default_pvid of the bridge, which will steal VLAN-tagged traffic
285 * from the bridge's data path. This is a configuration that DSA
286 * supports because vlan_filtering is 0. In that case, we should
287 * definitely keep the tag, to make sure it keeps working.
288 */
Florian Fainelli3a688442020-10-01 19:42:15 -0700289 upper_dev = __vlan_find_dev_deep_rcu(br, htons(proto), vid);
290 if (upper_dev)
291 return skb;
Vladimir Oltean412a1522020-09-23 14:40:37 -0700292
293 __vlan_hwaccel_clear_tag(skb);
294
295 return skb;
296}
297
Vivien Didelotf515f192017-02-03 13:20:20 -0500298/* switch.c */
299int dsa_switch_register_notifier(struct dsa_switch *ds);
300void dsa_switch_unregister_notifier(struct dsa_switch *ds);
Vladimir Olteanbff33f72020-03-27 21:55:43 +0200301
302/* dsa2.c */
Tobias Waldekranz058102a2021-01-13 09:42:53 +0100303void dsa_lag_map(struct dsa_switch_tree *dst, struct net_device *lag);
304void dsa_lag_unmap(struct dsa_switch_tree *dst, struct net_device *lag);
Vladimir Oltean886f8e22021-01-29 03:00:04 +0200305int dsa_tree_notify(struct dsa_switch_tree *dst, unsigned long e, void *v);
306int dsa_broadcast(unsigned long e, void *v);
Vladimir Oltean53da0eb2021-01-29 03:00:06 +0200307int dsa_tree_change_tag_proto(struct dsa_switch_tree *dst,
308 struct net_device *master,
309 const struct dsa_device_ops *tag_ops,
310 const struct dsa_device_ops *old_tag_ops);
Tobias Waldekranz058102a2021-01-13 09:42:53 +0100311
Vladimir Olteanbff33f72020-03-27 21:55:43 +0200312extern struct list_head dsa_tree_list;
313
Lennert Buytenhek91da11f2008-10-07 13:44:02 +0000314#endif