blob: 12998bf04e55a80cd1a5a77a3315b7462e3e2a6d [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,
Vivien Didelot8ae5bcd2017-05-19 17:00:54 -040023 DSA_NOTIFIER_MDB_ADD,
24 DSA_NOTIFIER_MDB_DEL,
Vivien Didelotd0c627b2017-05-19 17:00:55 -040025 DSA_NOTIFIER_VLAN_ADD,
26 DSA_NOTIFIER_VLAN_DEL,
Vladimir Olteanbfcb8132020-03-27 21:55:42 +020027 DSA_NOTIFIER_MTU,
Vivien Didelot52c96f92017-05-19 17:00:51 -040028};
29
Vivien Didelot1faabf72017-05-19 17:00:52 -040030/* DSA_NOTIFIER_AGEING_TIME */
31struct dsa_notifier_ageing_time_info {
32 struct switchdev_trans *trans;
33 unsigned int ageing_time;
Vivien Didelot1faabf72017-05-19 17:00:52 -040034};
35
Vivien Didelot52c96f92017-05-19 17:00:51 -040036/* DSA_NOTIFIER_BRIDGE_* */
37struct dsa_notifier_bridge_info {
38 struct net_device *br;
Vladimir Olteanf66a6a62020-05-10 19:37:41 +030039 int tree_index;
Vivien Didelot52c96f92017-05-19 17:00:51 -040040 int sw_index;
41 int port;
42};
43
Vivien Didelot685fb6a2017-05-19 17:00:53 -040044/* DSA_NOTIFIER_FDB_* */
45struct dsa_notifier_fdb_info {
Vivien Didelot685fb6a2017-05-19 17:00:53 -040046 int sw_index;
47 int port;
Arkadi Sharshevsky2acf4e62017-08-06 16:15:41 +030048 const unsigned char *addr;
49 u16 vid;
Vivien Didelot685fb6a2017-05-19 17:00:53 -040050};
51
Vivien Didelot8ae5bcd2017-05-19 17:00:54 -040052/* DSA_NOTIFIER_MDB_* */
53struct dsa_notifier_mdb_info {
54 const struct switchdev_obj_port_mdb *mdb;
55 struct switchdev_trans *trans;
56 int sw_index;
57 int port;
58};
59
Vivien Didelotd0c627b2017-05-19 17:00:55 -040060/* DSA_NOTIFIER_VLAN_* */
61struct dsa_notifier_vlan_info {
62 const struct switchdev_obj_port_vlan *vlan;
63 struct switchdev_trans *trans;
64 int sw_index;
65 int port;
66};
67
Vladimir Olteanbfcb8132020-03-27 21:55:42 +020068/* DSA_NOTIFIER_MTU */
69struct dsa_notifier_mtu_info {
70 bool propagate_upstream;
71 int sw_index;
72 int port;
73 int mtu;
74};
75
Lennert Buytenhek91da11f2008-10-07 13:44:02 +000076struct dsa_slave_priv {
Vivien Didelot15240242017-09-29 17:19:18 -040077 /* Copy of CPU port xmit for faster access in slave transmit hot path */
Florian Fainelli4ed70ce2015-07-31 11:42:56 -070078 struct sk_buff * (*xmit)(struct sk_buff *skb,
Alexander Duyck50753142014-09-15 13:00:19 -040079 struct net_device *dev);
Lennert Buytenheke84665c2009-03-20 09:52:09 +000080
Andrew Lunna61bf202020-07-05 21:30:04 +020081 struct pcpu_sw_netstats __percpu *stats64;
Florian Fainellif613ed62017-08-01 15:00:36 -070082
Alexander Lobakine131a562020-04-21 16:41:08 +030083 struct gro_cells gcells;
84
Vivien Didelotafdcf152017-01-27 15:29:39 -050085 /* DSA port data, such as switch, port index, etc. */
86 struct dsa_port *dp;
Lennert Buytenheke84665c2009-03-20 09:52:09 +000087
Florian Fainelli04ff53f2015-07-31 11:42:57 -070088#ifdef CONFIG_NET_POLL_CONTROLLER
89 struct netpoll *netpoll;
90#endif
Florian Fainellif50f2122017-01-30 12:41:40 -080091
92 /* TC context */
93 struct list_head mall_tc_list;
Lennert Buytenhek91da11f2008-10-07 13:44:02 +000094};
95
Lennert Buytenhek91da11f2008-10-07 13:44:02 +000096/* dsa.c */
Andrew Lunnc39e2a12019-04-28 19:37:18 +020097const struct dsa_device_ops *dsa_tag_driver_get(int tag_protocol);
Andrew Lunn4dad81e2019-04-28 19:37:19 +020098void dsa_tag_driver_put(const struct dsa_device_ops *ops);
Andrew Lunnc39e2a12019-04-28 19:37:18 +020099
Arkadi Sharshevskyc9eb3e02017-08-06 16:15:42 +0300100bool dsa_schedule_work(struct work_struct *work);
Florian Fainelli98cdb482018-09-07 11:09:02 -0700101const char *dsa_tag_protocol_to_str(const struct dsa_device_ops *ops);
Lennert Buytenhek91da11f2008-10-07 13:44:02 +0000102
Arkadi Sharshevsky37b8da12017-08-06 16:15:43 +0300103int dsa_legacy_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
104 struct net_device *dev,
105 const unsigned char *addr, u16 vid,
Petr Machata87b09842019-01-16 23:06:50 +0000106 u16 flags,
107 struct netlink_ext_ack *extack);
Arkadi Sharshevsky37b8da12017-08-06 16:15:43 +0300108int dsa_legacy_fdb_del(struct ndmsg *ndm, struct nlattr *tb[],
109 struct net_device *dev,
110 const unsigned char *addr, u16 vid);
Vivien Didelota6a71f12017-04-12 12:45:03 -0400111
Vivien Didelotf2f23562017-09-19 11:57:00 -0400112/* master.c */
Vivien Didelot17a22fc2017-11-06 16:11:45 -0500113int dsa_master_setup(struct net_device *dev, struct dsa_port *cpu_dp);
114void dsa_master_teardown(struct net_device *dev);
Vivien Didelotf2f23562017-09-19 11:57:00 -0400115
Vivien Didelot2231c432017-10-16 11:12:17 -0400116static inline struct net_device *dsa_master_find_slave(struct net_device *dev,
117 int device, int port)
Vivien Didelot3775b1b2017-09-29 17:19:15 -0400118{
Vivien Didelot2f657a62017-09-29 17:19:20 -0400119 struct dsa_port *cpu_dp = dev->dsa_ptr;
120 struct dsa_switch_tree *dst = cpu_dp->dst;
Vivien Didelot7b9a2f42019-10-21 16:51:18 -0400121 struct dsa_port *dp;
Vivien Didelot3775b1b2017-09-29 17:19:15 -0400122
Vivien Didelot7b9a2f42019-10-21 16:51:18 -0400123 list_for_each_entry(dp, &dst->ports, list)
124 if (dp->ds->index == device && dp->index == port &&
125 dp->type == DSA_PORT_TYPE_USER)
126 return dp->slave;
Vivien Didelot3775b1b2017-09-29 17:19:15 -0400127
Vivien Didelot7b9a2f42019-10-21 16:51:18 -0400128 return NULL;
Vivien Didelot3775b1b2017-09-29 17:19:15 -0400129}
130
Vivien Didelota40c1752017-05-19 17:00:44 -0400131/* port.c */
132int dsa_port_set_state(struct dsa_port *dp, u8 state,
133 struct switchdev_trans *trans);
Russell King8640f8d2020-03-03 15:01:46 +0000134int dsa_port_enable_rt(struct dsa_port *dp, struct phy_device *phy);
Vivien Didelotfb8a6a22017-09-22 19:01:56 -0400135int dsa_port_enable(struct dsa_port *dp, struct phy_device *phy);
Russell King8640f8d2020-03-03 15:01:46 +0000136void dsa_port_disable_rt(struct dsa_port *dp);
Andrew Lunn75104db2019-02-24 20:44:43 +0100137void dsa_port_disable(struct dsa_port *dp);
Vivien Didelotcfbed322017-05-19 17:00:45 -0400138int dsa_port_bridge_join(struct dsa_port *dp, struct net_device *br);
139void dsa_port_bridge_leave(struct dsa_port *dp, struct net_device *br);
Vivien Didelot4d61d302017-05-19 17:00:46 -0400140int dsa_port_vlan_filtering(struct dsa_port *dp, bool vlan_filtering,
141 struct switchdev_trans *trans);
Russell King54a0ed02020-05-12 20:20:25 +0300142bool dsa_port_skip_vlan_configuration(struct dsa_port *dp);
Vivien Didelotd87bd942017-05-19 17:00:47 -0400143int dsa_port_ageing_time(struct dsa_port *dp, clock_t ageing_clock,
144 struct switchdev_trans *trans);
Vladimir Olteanbfcb8132020-03-27 21:55:42 +0200145int dsa_port_mtu_change(struct dsa_port *dp, int new_mtu,
146 bool propagate_upstream);
Arkadi Sharshevsky2acf4e62017-08-06 16:15:41 +0300147int dsa_port_fdb_add(struct dsa_port *dp, const unsigned char *addr,
148 u16 vid);
149int dsa_port_fdb_del(struct dsa_port *dp, const unsigned char *addr,
150 u16 vid);
Vivien Didelotde40fc52017-09-20 19:32:14 -0400151int dsa_port_fdb_dump(struct dsa_port *dp, dsa_fdb_dump_cb_t *cb, void *data);
Andrew Lunnbb9f603172017-11-09 23:11:01 +0100152int dsa_port_mdb_add(const struct dsa_port *dp,
Vivien Didelot3a9afea2017-05-19 17:00:49 -0400153 const struct switchdev_obj_port_mdb *mdb,
154 struct switchdev_trans *trans);
Andrew Lunnbb9f603172017-11-09 23:11:01 +0100155int dsa_port_mdb_del(const struct dsa_port *dp,
Vivien Didelot3a9afea2017-05-19 17:00:49 -0400156 const struct switchdev_obj_port_mdb *mdb);
Florian Fainelliea870052019-02-20 16:58:22 -0800157int dsa_port_pre_bridge_flags(const struct dsa_port *dp, unsigned long flags,
158 struct switchdev_trans *trans);
Russell King57652792019-02-20 15:35:04 -0800159int dsa_port_bridge_flags(const struct dsa_port *dp, unsigned long flags,
160 struct switchdev_trans *trans);
Vivien Didelot08cc83c2019-07-08 23:31:13 -0400161int dsa_port_mrouter(struct dsa_port *dp, bool mrouter,
162 struct switchdev_trans *trans);
Vivien Didelot076e7132017-05-19 17:00:50 -0400163int dsa_port_vlan_add(struct dsa_port *dp,
164 const struct switchdev_obj_port_vlan *vlan,
165 struct switchdev_trans *trans);
166int dsa_port_vlan_del(struct dsa_port *dp,
167 const struct switchdev_obj_port_vlan *vlan);
Sebastian Reichel33615362018-01-23 16:03:46 +0100168int dsa_port_link_register_of(struct dsa_port *dp);
169void dsa_port_link_unregister_of(struct dsa_port *dp);
Ioana Ciornei77373d42019-05-28 20:38:15 +0300170extern const struct phylink_mac_ops dsa_port_phylink_mac_ops;
Vivien Didelot57ab1ca2017-10-26 10:50:07 -0400171
Lennert Buytenhek91da11f2008-10-07 13:44:02 +0000172/* slave.c */
Alexander Duyck50753142014-09-15 13:00:19 -0400173extern const struct dsa_device_ops notag_netdev_ops;
Lennert Buytenhek91da11f2008-10-07 13:44:02 +0000174void dsa_slave_mii_bus_init(struct dsa_switch *ds);
Vivien Didelot951259aa2017-10-27 15:55:19 -0400175int dsa_slave_create(struct dsa_port *dp);
Neil Armstrongcda5c152015-12-07 13:57:35 +0100176void dsa_slave_destroy(struct net_device *slave_dev);
Florian Fainelli4d776482020-01-07 21:06:05 -0800177bool dsa_slave_dev_check(const struct net_device *dev);
Florian Fainelli24462542014-09-18 17:31:22 -0700178int dsa_slave_suspend(struct net_device *slave_dev);
179int dsa_slave_resume(struct net_device *slave_dev);
Vivien Didelot88e4f0c2017-02-03 13:20:16 -0500180int dsa_slave_register_notifier(void);
181void dsa_slave_unregister_notifier(void);
Lennert Buytenhek91da11f2008-10-07 13:44:02 +0000182
Vivien Didelotd9450972017-10-16 11:12:15 -0400183static inline struct dsa_port *dsa_slave_to_port(const struct net_device *dev)
184{
185 struct dsa_slave_priv *p = netdev_priv(dev);
186
187 return p->dp;
188}
189
Vivien Didelotd0006b02017-10-16 11:12:16 -0400190static inline struct net_device *
191dsa_slave_to_master(const struct net_device *dev)
192{
193 struct dsa_port *dp = dsa_slave_to_port(dev);
194
Vivien Didelotf8b8b1c2017-10-16 11:12:18 -0400195 return dp->cpu_dp->master;
Vivien Didelotd0006b02017-10-16 11:12:16 -0400196}
197
Vladimir Oltean412a1522020-09-23 14:40:37 -0700198/* If under a bridge with vlan_filtering=0, make sure to send pvid-tagged
199 * frames as untagged, since the bridge will not untag them.
200 */
201static inline struct sk_buff *dsa_untag_bridge_pvid(struct sk_buff *skb)
202{
203 struct dsa_port *dp = dsa_slave_to_port(skb->dev);
Vladimir Oltean412a1522020-09-23 14:40:37 -0700204 struct net_device *br = dp->bridge_dev;
205 struct net_device *dev = skb->dev;
206 struct net_device *upper_dev;
Vladimir Oltean412a1522020-09-23 14:40:37 -0700207 u16 vid, pvid, proto;
208 int err;
209
210 if (!br || br_vlan_enabled(br))
211 return skb;
212
213 err = br_vlan_get_proto(br, &proto);
214 if (err)
215 return skb;
216
217 /* Move VLAN tag from data to hwaccel */
Florian Fainellia3482922020-10-01 19:42:14 -0700218 if (!skb_vlan_tag_present(skb) && skb->protocol == htons(proto)) {
Vladimir Oltean412a1522020-09-23 14:40:37 -0700219 skb = skb_vlan_untag(skb);
220 if (!skb)
221 return NULL;
222 }
223
224 if (!skb_vlan_tag_present(skb))
225 return skb;
226
227 vid = skb_vlan_tag_get_id(skb);
228
229 /* We already run under an RCU read-side critical section since
230 * we are called from netif_receive_skb_list_internal().
231 */
232 err = br_vlan_get_pvid_rcu(dev, &pvid);
233 if (err)
234 return skb;
235
236 if (vid != pvid)
237 return skb;
238
239 /* The sad part about attempting to untag from DSA is that we
240 * don't know, unless we check, if the skb will end up in
241 * the bridge's data path - br_allowed_ingress() - or not.
242 * For example, there might be an 8021q upper for the
243 * default_pvid of the bridge, which will steal VLAN-tagged traffic
244 * from the bridge's data path. This is a configuration that DSA
245 * supports because vlan_filtering is 0. In that case, we should
246 * definitely keep the tag, to make sure it keeps working.
247 */
Florian Fainelli3a688442020-10-01 19:42:15 -0700248 upper_dev = __vlan_find_dev_deep_rcu(br, htons(proto), vid);
249 if (upper_dev)
250 return skb;
Vladimir Oltean412a1522020-09-23 14:40:37 -0700251
252 __vlan_hwaccel_clear_tag(skb);
253
254 return skb;
255}
256
Vivien Didelotf515f192017-02-03 13:20:20 -0500257/* switch.c */
258int dsa_switch_register_notifier(struct dsa_switch *ds);
259void dsa_switch_unregister_notifier(struct dsa_switch *ds);
Vladimir Olteanbff33f72020-03-27 21:55:43 +0200260
261/* dsa2.c */
262extern struct list_head dsa_tree_list;
263
Lennert Buytenhek91da11f2008-10-07 13:44:02 +0000264#endif