12874c5fdSThomas Gleixner /* SPDX-License-Identifier: GPL-2.0-or-later */ 291da11f8SLennert Buytenhek /* 391da11f8SLennert Buytenhek * include/net/dsa.h - Driver for Distributed Switch Architecture switch chips 4e84665c9SLennert Buytenhek * Copyright (c) 2008-2009 Marvell Semiconductor 591da11f8SLennert Buytenhek */ 691da11f8SLennert Buytenhek 791da11f8SLennert Buytenhek #ifndef __LINUX_NET_DSA_H 891da11f8SLennert Buytenhek #define __LINUX_NET_DSA_H 991da11f8SLennert Buytenhek 104d56a29fSRussell King #include <linux/if.h> 11ea1f51beSAxel Lin #include <linux/if_ether.h> 12c8f0b869SBen Hutchings #include <linux/list.h> 13f515f192SVivien Didelot #include <linux/notifier.h> 14cf50dcc2SBen Hutchings #include <linux/timer.h> 15cf50dcc2SBen Hutchings #include <linux/workqueue.h> 16fa981d9aSFlorian Fainelli #include <linux/of.h> 17a2820543SFlorian Fainelli #include <linux/ethtool.h> 180336369dSBrandon Streiff #include <linux/net_tstamp.h> 1911d8f3ddSFlorian Fainelli #include <linux/phy.h> 20ecfc9372SFlorian Fainelli #include <linux/platform_data/dsa.h> 2144cc27e4SIoana Ciornei #include <linux/phylink.h> 2296567d5dSAndrew Lunn #include <net/devlink.h> 23f0c24ccfSVivien Didelot #include <net/switchdev.h> 24cf50dcc2SBen Hutchings 25f50f2127SFlorian Fainelli struct tc_action; 264d56a29fSRussell King struct phy_device; 274d56a29fSRussell King struct fixed_phy_status; 2811d8f3ddSFlorian Fainelli struct phylink_link_state; 29f50f2127SFlorian Fainelli 300b42f033SAndrew Lunn #define DSA_TAG_PROTO_NONE_VALUE 0 310b42f033SAndrew Lunn #define DSA_TAG_PROTO_BRCM_VALUE 1 320b42f033SAndrew Lunn #define DSA_TAG_PROTO_BRCM_PREPEND_VALUE 2 330b42f033SAndrew Lunn #define DSA_TAG_PROTO_DSA_VALUE 3 340b42f033SAndrew Lunn #define DSA_TAG_PROTO_EDSA_VALUE 4 350b42f033SAndrew Lunn #define DSA_TAG_PROTO_GSWIP_VALUE 5 360b42f033SAndrew Lunn #define DSA_TAG_PROTO_KSZ9477_VALUE 6 370b42f033SAndrew Lunn #define DSA_TAG_PROTO_KSZ9893_VALUE 7 380b42f033SAndrew Lunn #define DSA_TAG_PROTO_LAN9303_VALUE 8 390b42f033SAndrew Lunn #define DSA_TAG_PROTO_MTK_VALUE 9 400b42f033SAndrew Lunn #define DSA_TAG_PROTO_QCA_VALUE 10 410b42f033SAndrew Lunn #define DSA_TAG_PROTO_TRAILER_VALUE 11 42f9bbe447SVladimir Oltean #define DSA_TAG_PROTO_8021Q_VALUE 12 43227d07a0SVladimir Oltean #define DSA_TAG_PROTO_SJA1105_VALUE 13 44016e43a2STristram Ha #define DSA_TAG_PROTO_KSZ8795_VALUE 14 458dce89aaSVladimir Oltean #define DSA_TAG_PROTO_OCELOT_VALUE 15 4648fda74fSOleksij Rempel #define DSA_TAG_PROTO_AR9331_VALUE 16 47efd7fe68SLinus Walleij #define DSA_TAG_PROTO_RTL4_A_VALUE 17 4801ef09caSKurt Kanzenbach #define DSA_TAG_PROTO_HELLCREEK_VALUE 18 490b42f033SAndrew Lunn 50ac7a04c3SFlorian Fainelli enum dsa_tag_protocol { 510b42f033SAndrew Lunn DSA_TAG_PROTO_NONE = DSA_TAG_PROTO_NONE_VALUE, 520b42f033SAndrew Lunn DSA_TAG_PROTO_BRCM = DSA_TAG_PROTO_BRCM_VALUE, 530b42f033SAndrew Lunn DSA_TAG_PROTO_BRCM_PREPEND = DSA_TAG_PROTO_BRCM_PREPEND_VALUE, 540b42f033SAndrew Lunn DSA_TAG_PROTO_DSA = DSA_TAG_PROTO_DSA_VALUE, 550b42f033SAndrew Lunn DSA_TAG_PROTO_EDSA = DSA_TAG_PROTO_EDSA_VALUE, 560b42f033SAndrew Lunn DSA_TAG_PROTO_GSWIP = DSA_TAG_PROTO_GSWIP_VALUE, 570b42f033SAndrew Lunn DSA_TAG_PROTO_KSZ9477 = DSA_TAG_PROTO_KSZ9477_VALUE, 580b42f033SAndrew Lunn DSA_TAG_PROTO_KSZ9893 = DSA_TAG_PROTO_KSZ9893_VALUE, 590b42f033SAndrew Lunn DSA_TAG_PROTO_LAN9303 = DSA_TAG_PROTO_LAN9303_VALUE, 600b42f033SAndrew Lunn DSA_TAG_PROTO_MTK = DSA_TAG_PROTO_MTK_VALUE, 610b42f033SAndrew Lunn DSA_TAG_PROTO_QCA = DSA_TAG_PROTO_QCA_VALUE, 620b42f033SAndrew Lunn DSA_TAG_PROTO_TRAILER = DSA_TAG_PROTO_TRAILER_VALUE, 63f9bbe447SVladimir Oltean DSA_TAG_PROTO_8021Q = DSA_TAG_PROTO_8021Q_VALUE, 64227d07a0SVladimir Oltean DSA_TAG_PROTO_SJA1105 = DSA_TAG_PROTO_SJA1105_VALUE, 65016e43a2STristram Ha DSA_TAG_PROTO_KSZ8795 = DSA_TAG_PROTO_KSZ8795_VALUE, 668dce89aaSVladimir Oltean DSA_TAG_PROTO_OCELOT = DSA_TAG_PROTO_OCELOT_VALUE, 6748fda74fSOleksij Rempel DSA_TAG_PROTO_AR9331 = DSA_TAG_PROTO_AR9331_VALUE, 68efd7fe68SLinus Walleij DSA_TAG_PROTO_RTL4_A = DSA_TAG_PROTO_RTL4_A_VALUE, 6901ef09caSKurt Kanzenbach DSA_TAG_PROTO_HELLCREEK = DSA_TAG_PROTO_HELLCREEK_VALUE, 70ac7a04c3SFlorian Fainelli }; 715037d532SFlorian Fainelli 725075314eSAlexander Duyck struct packet_type; 7390af1059SBrandon Streiff struct dsa_switch; 743e8a72d1SFlorian Fainelli 7568277a2cSJohn Crispin struct dsa_device_ops { 7668277a2cSJohn Crispin struct sk_buff *(*xmit)(struct sk_buff *skb, struct net_device *dev); 7768277a2cSJohn Crispin struct sk_buff *(*rcv)(struct sk_buff *skb, struct net_device *dev, 7889e49506SFlorian Westphal struct packet_type *pt); 792e8cb1b3SVladimir Oltean void (*flow_dissect)(const struct sk_buff *skb, __be16 *proto, 80598a9680SJohn Crispin int *offset); 81cc1939e4SVladimir Oltean /* Used to determine which traffic should match the DSA filter in 82cc1939e4SVladimir Oltean * eth_type_trans, and which, if any, should bypass it and be processed 83cc1939e4SVladimir Oltean * as regular on the master net device. 84cc1939e4SVladimir Oltean */ 85cc1939e4SVladimir Oltean bool (*filter)(const struct sk_buff *skb, struct net_device *dev); 86a5dd3087SAndrew Lunn unsigned int overhead; 87875138f8SAndrew Lunn const char *name; 88056eed2fSAndrew Lunn enum dsa_tag_protocol proto; 89c3975400SVladimir Oltean /* Some tagging protocols either mangle or shift the destination MAC 90c3975400SVladimir Oltean * address, in which case the DSA master would drop packets on ingress 91c3975400SVladimir Oltean * if what it understands out of the destination MAC address is not in 92c3975400SVladimir Oltean * its RX filter. 93c3975400SVladimir Oltean */ 94c3975400SVladimir Oltean bool promisc_on_master; 957a6ffe76SVladimir Oltean bool tail_tag; 9668277a2cSJohn Crispin }; 9768277a2cSJohn Crispin 984cfab356SFlorian Fainelli /* This structure defines the control interfaces that are overlayed by the 994cfab356SFlorian Fainelli * DSA layer on top of the DSA CPU/management net_device instance. This is 1004cfab356SFlorian Fainelli * used by the core net_device layer while calling various net_device_ops 1014cfab356SFlorian Fainelli * function pointers. 1024cfab356SFlorian Fainelli */ 1034cfab356SFlorian Fainelli struct dsa_netdevice_ops { 1044cfab356SFlorian Fainelli int (*ndo_do_ioctl)(struct net_device *dev, struct ifreq *ifr, 1054cfab356SFlorian Fainelli int cmd); 1064cfab356SFlorian Fainelli }; 1074cfab356SFlorian Fainelli 1080b42f033SAndrew Lunn #define DSA_TAG_DRIVER_ALIAS "dsa_tag-" 1090b42f033SAndrew Lunn #define MODULE_ALIAS_DSA_TAG_DRIVER(__proto) \ 1100b42f033SAndrew Lunn MODULE_ALIAS(DSA_TAG_DRIVER_ALIAS __stringify(__proto##_VALUE)) 1110b42f033SAndrew Lunn 112b68b0dd0SVladimir Oltean struct dsa_skb_cb { 113b68b0dd0SVladimir Oltean struct sk_buff *clone; 114b68b0dd0SVladimir Oltean }; 115b68b0dd0SVladimir Oltean 116b68b0dd0SVladimir Oltean struct __dsa_skb_cb { 117b68b0dd0SVladimir Oltean struct dsa_skb_cb cb; 118b68b0dd0SVladimir Oltean u8 priv[48 - sizeof(struct dsa_skb_cb)]; 119b68b0dd0SVladimir Oltean }; 120b68b0dd0SVladimir Oltean 121b68b0dd0SVladimir Oltean #define DSA_SKB_CB(skb) ((struct dsa_skb_cb *)((skb)->cb)) 122b68b0dd0SVladimir Oltean 123b68b0dd0SVladimir Oltean #define DSA_SKB_CB_PRIV(skb) \ 124b68b0dd0SVladimir Oltean ((void *)(skb)->cb + offsetof(struct __dsa_skb_cb, priv)) 125b68b0dd0SVladimir Oltean 126cf50dcc2SBen Hutchings struct dsa_switch_tree { 12783c0afaeSAndrew Lunn struct list_head list; 12883c0afaeSAndrew Lunn 129f515f192SVivien Didelot /* Notifier chain for switch-wide events */ 130f515f192SVivien Didelot struct raw_notifier_head nh; 131f515f192SVivien Didelot 13283c0afaeSAndrew Lunn /* Tree identifier */ 13349463b7fSVivien Didelot unsigned int index; 13483c0afaeSAndrew Lunn 13583c0afaeSAndrew Lunn /* Number of switches attached to this tree */ 13683c0afaeSAndrew Lunn struct kref refcount; 13783c0afaeSAndrew Lunn 13883c0afaeSAndrew Lunn /* Has this tree been applied to the hardware? */ 139ec15dd42SVivien Didelot bool setup; 14083c0afaeSAndrew Lunn 141cf50dcc2SBen Hutchings /* 142cf50dcc2SBen Hutchings * Configuration data for the platform device that owns 143cf50dcc2SBen Hutchings * this dsa switch tree instance. 144cf50dcc2SBen Hutchings */ 145cf50dcc2SBen Hutchings struct dsa_platform_data *pd; 146cf85d08fSLennert Buytenhek 147ab8ccae1SVivien Didelot /* List of switch ports */ 148ab8ccae1SVivien Didelot struct list_head ports; 149ab8ccae1SVivien Didelot 150c5f51765SVivien Didelot /* List of DSA links composing the routing table */ 151c5f51765SVivien Didelot struct list_head rtable; 152*058102a6STobias Waldekranz 153*058102a6STobias Waldekranz /* Maps offloaded LAG netdevs to a zero-based linear ID for 154*058102a6STobias Waldekranz * drivers that need it. 155*058102a6STobias Waldekranz */ 156*058102a6STobias Waldekranz struct net_device **lags; 157*058102a6STobias Waldekranz unsigned int lags_len; 158cf50dcc2SBen Hutchings }; 159cf50dcc2SBen Hutchings 160*058102a6STobias Waldekranz #define dsa_lags_foreach_id(_id, _dst) \ 161*058102a6STobias Waldekranz for ((_id) = 0; (_id) < (_dst)->lags_len; (_id)++) \ 162*058102a6STobias Waldekranz if ((_dst)->lags[(_id)]) 163*058102a6STobias Waldekranz 164*058102a6STobias Waldekranz #define dsa_lag_foreach_port(_dp, _dst, _lag) \ 165*058102a6STobias Waldekranz list_for_each_entry((_dp), &(_dst)->ports, list) \ 166*058102a6STobias Waldekranz if ((_dp)->lag_dev == (_lag)) 167*058102a6STobias Waldekranz 168*058102a6STobias Waldekranz static inline struct net_device *dsa_lag_dev(struct dsa_switch_tree *dst, 169*058102a6STobias Waldekranz unsigned int id) 170*058102a6STobias Waldekranz { 171*058102a6STobias Waldekranz return dst->lags[id]; 172*058102a6STobias Waldekranz } 173*058102a6STobias Waldekranz 174*058102a6STobias Waldekranz static inline int dsa_lag_id(struct dsa_switch_tree *dst, 175*058102a6STobias Waldekranz struct net_device *lag) 176*058102a6STobias Waldekranz { 177*058102a6STobias Waldekranz unsigned int id; 178*058102a6STobias Waldekranz 179*058102a6STobias Waldekranz dsa_lags_foreach_id(id, dst) { 180*058102a6STobias Waldekranz if (dsa_lag_dev(dst, id) == lag) 181*058102a6STobias Waldekranz return id; 182*058102a6STobias Waldekranz } 183*058102a6STobias Waldekranz 184*058102a6STobias Waldekranz return -ENODEV; 185*058102a6STobias Waldekranz } 186*058102a6STobias Waldekranz 18734297176SVladimir Oltean /* TC matchall action types */ 188f50f2127SFlorian Fainelli enum dsa_port_mall_action_type { 189f50f2127SFlorian Fainelli DSA_PORT_MALL_MIRROR, 19034297176SVladimir Oltean DSA_PORT_MALL_POLICER, 191f50f2127SFlorian Fainelli }; 192f50f2127SFlorian Fainelli 193f50f2127SFlorian Fainelli /* TC mirroring entry */ 194f50f2127SFlorian Fainelli struct dsa_mall_mirror_tc_entry { 195f50f2127SFlorian Fainelli u8 to_local_port; 196f50f2127SFlorian Fainelli bool ingress; 197f50f2127SFlorian Fainelli }; 198f50f2127SFlorian Fainelli 19934297176SVladimir Oltean /* TC port policer entry */ 20034297176SVladimir Oltean struct dsa_mall_policer_tc_entry { 2015f035af7SPo Liu u32 burst; 20234297176SVladimir Oltean u64 rate_bytes_per_sec; 20334297176SVladimir Oltean }; 20434297176SVladimir Oltean 205f50f2127SFlorian Fainelli /* TC matchall entry */ 206f50f2127SFlorian Fainelli struct dsa_mall_tc_entry { 207f50f2127SFlorian Fainelli struct list_head list; 208f50f2127SFlorian Fainelli unsigned long cookie; 209f50f2127SFlorian Fainelli enum dsa_port_mall_action_type type; 210f50f2127SFlorian Fainelli union { 211f50f2127SFlorian Fainelli struct dsa_mall_mirror_tc_entry mirror; 21234297176SVladimir Oltean struct dsa_mall_policer_tc_entry policer; 213f50f2127SFlorian Fainelli }; 214f50f2127SFlorian Fainelli }; 215f50f2127SFlorian Fainelli 216f50f2127SFlorian Fainelli 217c8b09808SAndrew Lunn struct dsa_port { 218f8b8b1cdSVivien Didelot /* A CPU port is physically connected to a master device. 219f8b8b1cdSVivien Didelot * A user port exposed to userspace has a slave device. 220f8b8b1cdSVivien Didelot */ 221f8b8b1cdSVivien Didelot union { 222f8b8b1cdSVivien Didelot struct net_device *master; 223f8b8b1cdSVivien Didelot struct net_device *slave; 224f8b8b1cdSVivien Didelot }; 225f8b8b1cdSVivien Didelot 22615240248SVivien Didelot /* CPU port tagging operations used by master or slave devices */ 22715240248SVivien Didelot const struct dsa_device_ops *tag_ops; 22815240248SVivien Didelot 2293e41f93bSVivien Didelot /* Copies for faster access in master receive hot path */ 2303e41f93bSVivien Didelot struct dsa_switch_tree *dst; 2313e41f93bSVivien Didelot struct sk_buff *(*rcv)(struct sk_buff *skb, struct net_device *dev, 2323e41f93bSVivien Didelot struct packet_type *pt); 233cc1939e4SVladimir Oltean bool (*filter)(const struct sk_buff *skb, struct net_device *dev); 2343e41f93bSVivien Didelot 235057cad2cSVivien Didelot enum { 236057cad2cSVivien Didelot DSA_PORT_TYPE_UNUSED = 0, 237057cad2cSVivien Didelot DSA_PORT_TYPE_CPU, 238057cad2cSVivien Didelot DSA_PORT_TYPE_DSA, 239057cad2cSVivien Didelot DSA_PORT_TYPE_USER, 240057cad2cSVivien Didelot } type; 241057cad2cSVivien Didelot 242818be848SVivien Didelot struct dsa_switch *ds; 243818be848SVivien Didelot unsigned int index; 24471e0bbdeSFlorian Fainelli const char *name; 24568b2d4a8SVivien Didelot struct dsa_port *cpu_dp; 246a2c7023fSXiaofei Shen const char *mac; 247189b0d93SAndrew Lunn struct device_node *dn; 24834a79f63SVivien Didelot unsigned int ageing_time; 24933162e9aSVladimir Oltean bool vlan_filtering; 250732f794cSVivien Didelot u8 stp_state; 251a5e9a02eSVivien Didelot struct net_device *bridge_dev; 25296567d5dSAndrew Lunn struct devlink_port devlink_port; 2533122433eSAndrew Lunn bool devlink_port_setup; 254aab9c406SFlorian Fainelli struct phylink *pl; 25544cc27e4SIoana Ciornei struct phylink_config pl_config; 256*058102a6STobias Waldekranz struct net_device *lag_dev; 257*058102a6STobias Waldekranz bool lag_tx_enabled; 25897a69a0dSVladimir Oltean 259ab8ccae1SVivien Didelot struct list_head list; 260ab8ccae1SVivien Didelot 26167dbb9d4SFlorian Fainelli /* 262c362beb0SVladimir Oltean * Give the switch driver somewhere to hang its per-port private data 263c362beb0SVladimir Oltean * structures (accessible from the tagger). 264c362beb0SVladimir Oltean */ 265c362beb0SVladimir Oltean void *priv; 266c362beb0SVladimir Oltean 267c362beb0SVladimir Oltean /* 26867dbb9d4SFlorian Fainelli * Original copy of the master netdev ethtool_ops 26967dbb9d4SFlorian Fainelli */ 27067dbb9d4SFlorian Fainelli const struct ethtool_ops *orig_ethtool_ops; 271da7b9e9bSFlorian Fainelli 272da7b9e9bSFlorian Fainelli /* 273da7b9e9bSFlorian Fainelli * Original copy of the master netdev net_device_ops 274da7b9e9bSFlorian Fainelli */ 2754cfab356SFlorian Fainelli const struct dsa_netdevice_ops *netdev_ops; 276fb35c60cSVivien Didelot 277fb35c60cSVivien Didelot bool setup; 278c8b09808SAndrew Lunn }; 279c8b09808SAndrew Lunn 280c5f51765SVivien Didelot /* TODO: ideally DSA ports would have a single dp->link_dp member, 281c5f51765SVivien Didelot * and no dst->rtable nor this struct dsa_link would be needed, 282c5f51765SVivien Didelot * but this would require some more complex tree walking, 283c5f51765SVivien Didelot * so keep it stupid at the moment and list them all. 284c5f51765SVivien Didelot */ 285c5f51765SVivien Didelot struct dsa_link { 286c5f51765SVivien Didelot struct dsa_port *dp; 287c5f51765SVivien Didelot struct dsa_port *link_dp; 288c5f51765SVivien Didelot struct list_head list; 289c5f51765SVivien Didelot }; 290c5f51765SVivien Didelot 291c8f0b869SBen Hutchings struct dsa_switch { 292fb35c60cSVivien Didelot bool setup; 293fb35c60cSVivien Didelot 294c33063d6SAndrew Lunn struct device *dev; 295c33063d6SAndrew Lunn 296c8f0b869SBen Hutchings /* 297c8f0b869SBen Hutchings * Parent switch tree, and switch index. 298c8f0b869SBen Hutchings */ 299c8f0b869SBen Hutchings struct dsa_switch_tree *dst; 30099feaafcSVivien Didelot unsigned int index; 301c8f0b869SBen Hutchings 302f515f192SVivien Didelot /* Listener for switch fabric events */ 303f515f192SVivien Didelot struct notifier_block nb; 304f515f192SVivien Didelot 305c8f0b869SBen Hutchings /* 3067543a6d5SAndrew Lunn * Give the switch driver somewhere to hang its private data 3077543a6d5SAndrew Lunn * structure. 3087543a6d5SAndrew Lunn */ 3097543a6d5SAndrew Lunn void *priv; 3107543a6d5SAndrew Lunn 3117543a6d5SAndrew Lunn /* 312c8f0b869SBen Hutchings * Configuration data for this switch. 313c8f0b869SBen Hutchings */ 314ff04955cSAndrew Lunn struct dsa_chip_data *cd; 315c8f0b869SBen Hutchings 316c8f0b869SBen Hutchings /* 3179d490b4eSVivien Didelot * The switch operations. 318c8f0b869SBen Hutchings */ 319a82f67afSFlorian Fainelli const struct dsa_switch_ops *ops; 320c8f0b869SBen Hutchings 32166472fc0SAndrew Lunn /* 322c8f0b869SBen Hutchings * Slave mii_bus and devices for the individual ports. 323c8f0b869SBen Hutchings */ 3240d8bcdd3SFlorian Fainelli u32 phys_mii_mask; 325c8f0b869SBen Hutchings struct mii_bus *slave_mii_bus; 326a0c02161SVivien Didelot 3270f3da6afSVivien Didelot /* Ageing Time limits in msecs */ 3280f3da6afSVivien Didelot unsigned int ageing_time_min; 3290f3da6afSVivien Didelot unsigned int ageing_time_max; 3300f3da6afSVivien Didelot 33196567d5dSAndrew Lunn /* devlink used to represent this switch device */ 33296567d5dSAndrew Lunn struct devlink *devlink; 33396567d5dSAndrew Lunn 33455199df6SFlorian Fainelli /* Number of switch port queues */ 33555199df6SFlorian Fainelli unsigned int num_tx_queues; 33655199df6SFlorian Fainelli 3378f5d16f6SVladimir Oltean /* Disallow bridge core from requesting different VLAN awareness 3388f5d16f6SVladimir Oltean * settings on ports if not hardware-supported 3398f5d16f6SVladimir Oltean */ 3408f5d16f6SVladimir Oltean bool vlan_filtering_is_global; 3418f5d16f6SVladimir Oltean 34254a0ed0dSRussell King /* Pass .port_vlan_add and .port_vlan_del to drivers even for bridges 34354a0ed0dSRussell King * that have vlan_filtering=0. All drivers should ideally set this (and 34454a0ed0dSRussell King * then the option would get removed), but it is unknown whether this 34554a0ed0dSRussell King * would break things or not. 34654a0ed0dSRussell King */ 34754a0ed0dSRussell King bool configure_vlan_while_not_filtering; 34854a0ed0dSRussell King 3491dc0408cSFlorian Fainelli /* If the switch driver always programs the CPU port as egress tagged 3501dc0408cSFlorian Fainelli * despite the VLAN configuration indicating otherwise, then setting 3511dc0408cSFlorian Fainelli * @untag_bridge_pvid will force the DSA receive path to pop the bridge's 3521dc0408cSFlorian Fainelli * default_pvid VLAN tagged frames to offer a consistent behavior 3531dc0408cSFlorian Fainelli * between a vlan_filtering=0 and vlan_filtering=1 bridge device. 3541dc0408cSFlorian Fainelli */ 3551dc0408cSFlorian Fainelli bool untag_bridge_pvid; 3561dc0408cSFlorian Fainelli 357d5f19486SVladimir Oltean /* Let DSA manage the FDB entries towards the CPU, based on the 358d5f19486SVladimir Oltean * software bridge database. 359d5f19486SVladimir Oltean */ 360d5f19486SVladimir Oltean bool assisted_learning_on_cpu_port; 361d5f19486SVladimir Oltean 36214574676SVladimir Oltean /* In case vlan_filtering_is_global is set, the VLAN awareness state 36314574676SVladimir Oltean * should be retrieved from here and not from the per-port settings. 36414574676SVladimir Oltean */ 36514574676SVladimir Oltean bool vlan_filtering; 36614574676SVladimir Oltean 367787cac3fSVladimir Oltean /* MAC PCS does not provide link state change interrupt, and requires 368787cac3fSVladimir Oltean * polling. Flag passed on to PHYLINK. 369787cac3fSVladimir Oltean */ 370787cac3fSVladimir Oltean bool pcs_poll; 371787cac3fSVladimir Oltean 372bff33f7eSVladimir Oltean /* For switches that only have the MRU configurable. To ensure the 373bff33f7eSVladimir Oltean * configured MTU is not exceeded, normalization of MRU on all bridged 374bff33f7eSVladimir Oltean * interfaces is needed. 375bff33f7eSVladimir Oltean */ 376bff33f7eSVladimir Oltean bool mtu_enforcement_ingress; 377bff33f7eSVladimir Oltean 378*058102a6STobias Waldekranz /* Drivers that benefit from having an ID associated with each 379*058102a6STobias Waldekranz * offloaded LAG should set this to the maximum number of 380*058102a6STobias Waldekranz * supported IDs. DSA will then maintain a mapping of _at 381*058102a6STobias Waldekranz * least_ these many IDs, accessible to drivers via 382*058102a6STobias Waldekranz * dsa_lag_id(). 383*058102a6STobias Waldekranz */ 384*058102a6STobias Waldekranz unsigned int num_lag_ids; 385*058102a6STobias Waldekranz 386a0c02161SVivien Didelot size_t num_ports; 387c8f0b869SBen Hutchings }; 388c8f0b869SBen Hutchings 38968bb8ea8SVivien Didelot static inline struct dsa_port *dsa_to_port(struct dsa_switch *ds, int p) 390c38c5a66SVivien Didelot { 391b96ddf25SVivien Didelot struct dsa_switch_tree *dst = ds->dst; 392d607525bSVivien Didelot struct dsa_port *dp; 393b96ddf25SVivien Didelot 394b96ddf25SVivien Didelot list_for_each_entry(dp, &dst->ports, list) 395b96ddf25SVivien Didelot if (dp->ds == ds && dp->index == p) 396b96ddf25SVivien Didelot return dp; 397d607525bSVivien Didelot 398d607525bSVivien Didelot return NULL; 399c38c5a66SVivien Didelot } 400c38c5a66SVivien Didelot 401bff7b688SVivien Didelot static inline bool dsa_is_unused_port(struct dsa_switch *ds, int p) 402bff7b688SVivien Didelot { 403c38c5a66SVivien Didelot return dsa_to_port(ds, p)->type == DSA_PORT_TYPE_UNUSED; 404bff7b688SVivien Didelot } 405bff7b688SVivien Didelot 406c8f0b869SBen Hutchings static inline bool dsa_is_cpu_port(struct dsa_switch *ds, int p) 407c8f0b869SBen Hutchings { 408c38c5a66SVivien Didelot return dsa_to_port(ds, p)->type == DSA_PORT_TYPE_CPU; 409c8f0b869SBen Hutchings } 410c8f0b869SBen Hutchings 41160045cbfSAndrew Lunn static inline bool dsa_is_dsa_port(struct dsa_switch *ds, int p) 41260045cbfSAndrew Lunn { 413c38c5a66SVivien Didelot return dsa_to_port(ds, p)->type == DSA_PORT_TYPE_DSA; 41460045cbfSAndrew Lunn } 41560045cbfSAndrew Lunn 4162b3e9891SVivien Didelot static inline bool dsa_is_user_port(struct dsa_switch *ds, int p) 4176cd456f3SVivien Didelot { 418c38c5a66SVivien Didelot return dsa_to_port(ds, p)->type == DSA_PORT_TYPE_USER; 4196cd456f3SVivien Didelot } 4206cd456f3SVivien Didelot 42102bc6e54SVivien Didelot static inline u32 dsa_user_ports(struct dsa_switch *ds) 42202bc6e54SVivien Didelot { 423c38c5a66SVivien Didelot u32 mask = 0; 424c38c5a66SVivien Didelot int p; 42502bc6e54SVivien Didelot 426c38c5a66SVivien Didelot for (p = 0; p < ds->num_ports; p++) 427c38c5a66SVivien Didelot if (dsa_is_user_port(ds, p)) 428c38c5a66SVivien Didelot mask |= BIT(p); 429c38c5a66SVivien Didelot 430c38c5a66SVivien Didelot return mask; 431c8652c83SVivien Didelot } 432c8652c83SVivien Didelot 433c5f51765SVivien Didelot /* Return the local port used to reach an arbitrary switch device */ 434c5f51765SVivien Didelot static inline unsigned int dsa_routing_port(struct dsa_switch *ds, int device) 435c5f51765SVivien Didelot { 436c5f51765SVivien Didelot struct dsa_switch_tree *dst = ds->dst; 437c5f51765SVivien Didelot struct dsa_link *dl; 438c5f51765SVivien Didelot 439c5f51765SVivien Didelot list_for_each_entry(dl, &dst->rtable, list) 440c5f51765SVivien Didelot if (dl->dp->ds == ds && dl->link_dp->ds->index == device) 441c5f51765SVivien Didelot return dl->dp->index; 442c5f51765SVivien Didelot 443c5f51765SVivien Didelot return ds->num_ports; 444c5f51765SVivien Didelot } 445c5f51765SVivien Didelot 4463b8fac5dSVivien Didelot /* Return the local port used to reach an arbitrary switch port */ 4473b8fac5dSVivien Didelot static inline unsigned int dsa_towards_port(struct dsa_switch *ds, int device, 4483b8fac5dSVivien Didelot int port) 4493b8fac5dSVivien Didelot { 4503b8fac5dSVivien Didelot if (device == ds->index) 4513b8fac5dSVivien Didelot return port; 4523b8fac5dSVivien Didelot else 453c5f51765SVivien Didelot return dsa_routing_port(ds, device); 4543b8fac5dSVivien Didelot } 4553b8fac5dSVivien Didelot 4563b8fac5dSVivien Didelot /* Return the local port used to reach the dedicated CPU port */ 45707073c79SVivien Didelot static inline unsigned int dsa_upstream_port(struct dsa_switch *ds, int port) 458c8f0b869SBen Hutchings { 45907073c79SVivien Didelot const struct dsa_port *dp = dsa_to_port(ds, port); 46007073c79SVivien Didelot const struct dsa_port *cpu_dp = dp->cpu_dp; 46107073c79SVivien Didelot 46207073c79SVivien Didelot if (!cpu_dp) 46307073c79SVivien Didelot return port; 464c8f0b869SBen Hutchings 4653b8fac5dSVivien Didelot return dsa_towards_port(ds, cpu_dp->ds->index, cpu_dp->index); 466c8f0b869SBen Hutchings } 467c8f0b869SBen Hutchings 468cf2d45f5SVladimir Oltean static inline bool dsa_port_is_vlan_filtering(const struct dsa_port *dp) 469cf2d45f5SVladimir Oltean { 470cf2d45f5SVladimir Oltean const struct dsa_switch *ds = dp->ds; 471cf2d45f5SVladimir Oltean 472cf2d45f5SVladimir Oltean if (ds->vlan_filtering_is_global) 473cf2d45f5SVladimir Oltean return ds->vlan_filtering; 474cf2d45f5SVladimir Oltean else 475cf2d45f5SVladimir Oltean return dp->vlan_filtering; 476cf2d45f5SVladimir Oltean } 477cf2d45f5SVladimir Oltean 4782bedde1aSArkadi Sharshevsky typedef int dsa_fdb_dump_cb_t(const unsigned char *addr, u16 vid, 4792bedde1aSArkadi Sharshevsky bool is_static, void *data); 4809d490b4eSVivien Didelot struct dsa_switch_ops { 4815ed4e3ebSFlorian Fainelli enum dsa_tag_protocol (*get_tag_protocol)(struct dsa_switch *ds, 4824d776482SFlorian Fainelli int port, 4834d776482SFlorian Fainelli enum dsa_tag_protocol mprot); 4847b314362SAndrew Lunn 485c8f0b869SBen Hutchings int (*setup)(struct dsa_switch *ds); 4865e3f847aSVladimir Oltean void (*teardown)(struct dsa_switch *ds); 4876819563eSFlorian Fainelli u32 (*get_phy_flags)(struct dsa_switch *ds, int port); 488c8f0b869SBen Hutchings 489c8f0b869SBen Hutchings /* 490c8f0b869SBen Hutchings * Access to the switch's PHY registers. 491c8f0b869SBen Hutchings */ 492c8f0b869SBen Hutchings int (*phy_read)(struct dsa_switch *ds, int port, int regnum); 493c8f0b869SBen Hutchings int (*phy_write)(struct dsa_switch *ds, int port, 494c8f0b869SBen Hutchings int regnum, u16 val); 495c8f0b869SBen Hutchings 496c8f0b869SBen Hutchings /* 497ec9436baSFlorian Fainelli * Link state adjustment (called from libphy) 498ec9436baSFlorian Fainelli */ 499ec9436baSFlorian Fainelli void (*adjust_link)(struct dsa_switch *ds, int port, 500ec9436baSFlorian Fainelli struct phy_device *phydev); 501ce31b31cSFlorian Fainelli void (*fixed_link_update)(struct dsa_switch *ds, int port, 502ce31b31cSFlorian Fainelli struct fixed_phy_status *st); 503ec9436baSFlorian Fainelli 504ec9436baSFlorian Fainelli /* 50511d8f3ddSFlorian Fainelli * PHYLINK integration 50611d8f3ddSFlorian Fainelli */ 50711d8f3ddSFlorian Fainelli void (*phylink_validate)(struct dsa_switch *ds, int port, 50811d8f3ddSFlorian Fainelli unsigned long *supported, 50911d8f3ddSFlorian Fainelli struct phylink_link_state *state); 51011d8f3ddSFlorian Fainelli int (*phylink_mac_link_state)(struct dsa_switch *ds, int port, 51111d8f3ddSFlorian Fainelli struct phylink_link_state *state); 51211d8f3ddSFlorian Fainelli void (*phylink_mac_config)(struct dsa_switch *ds, int port, 51311d8f3ddSFlorian Fainelli unsigned int mode, 51411d8f3ddSFlorian Fainelli const struct phylink_link_state *state); 51511d8f3ddSFlorian Fainelli void (*phylink_mac_an_restart)(struct dsa_switch *ds, int port); 51611d8f3ddSFlorian Fainelli void (*phylink_mac_link_down)(struct dsa_switch *ds, int port, 51711d8f3ddSFlorian Fainelli unsigned int mode, 51811d8f3ddSFlorian Fainelli phy_interface_t interface); 51911d8f3ddSFlorian Fainelli void (*phylink_mac_link_up)(struct dsa_switch *ds, int port, 52011d8f3ddSFlorian Fainelli unsigned int mode, 52111d8f3ddSFlorian Fainelli phy_interface_t interface, 5225b502a7bSRussell King struct phy_device *phydev, 5235b502a7bSRussell King int speed, int duplex, 5245b502a7bSRussell King bool tx_pause, bool rx_pause); 52511d8f3ddSFlorian Fainelli void (*phylink_fixed_state)(struct dsa_switch *ds, int port, 52611d8f3ddSFlorian Fainelli struct phylink_link_state *state); 52711d8f3ddSFlorian Fainelli /* 528c2ec5f2eSOleksij Rempel * Port statistics counters. 529c8f0b869SBen Hutchings */ 53089f09048SFlorian Fainelli void (*get_strings)(struct dsa_switch *ds, int port, 53189f09048SFlorian Fainelli u32 stringset, uint8_t *data); 532c8f0b869SBen Hutchings void (*get_ethtool_stats)(struct dsa_switch *ds, 533c8f0b869SBen Hutchings int port, uint64_t *data); 53489f09048SFlorian Fainelli int (*get_sset_count)(struct dsa_switch *ds, int port, int sset); 535cf963573SFlorian Fainelli void (*get_ethtool_phy_stats)(struct dsa_switch *ds, 536cf963573SFlorian Fainelli int port, uint64_t *data); 537c2ec5f2eSOleksij Rempel void (*get_stats64)(struct dsa_switch *ds, int port, 538c2ec5f2eSOleksij Rempel struct rtnl_link_stats64 *s); 53924462549SFlorian Fainelli 54024462549SFlorian Fainelli /* 54119e57c4eSFlorian Fainelli * ethtool Wake-on-LAN 54219e57c4eSFlorian Fainelli */ 54319e57c4eSFlorian Fainelli void (*get_wol)(struct dsa_switch *ds, int port, 54419e57c4eSFlorian Fainelli struct ethtool_wolinfo *w); 54519e57c4eSFlorian Fainelli int (*set_wol)(struct dsa_switch *ds, int port, 54619e57c4eSFlorian Fainelli struct ethtool_wolinfo *w); 54719e57c4eSFlorian Fainelli 54819e57c4eSFlorian Fainelli /* 5490336369dSBrandon Streiff * ethtool timestamp info 5500336369dSBrandon Streiff */ 5510336369dSBrandon Streiff int (*get_ts_info)(struct dsa_switch *ds, int port, 5520336369dSBrandon Streiff struct ethtool_ts_info *ts); 5530336369dSBrandon Streiff 5540336369dSBrandon Streiff /* 55524462549SFlorian Fainelli * Suspend and resume 55624462549SFlorian Fainelli */ 55724462549SFlorian Fainelli int (*suspend)(struct dsa_switch *ds); 55824462549SFlorian Fainelli int (*resume)(struct dsa_switch *ds); 559b2f2af21SFlorian Fainelli 560b2f2af21SFlorian Fainelli /* 561b2f2af21SFlorian Fainelli * Port enable/disable 562b2f2af21SFlorian Fainelli */ 563b2f2af21SFlorian Fainelli int (*port_enable)(struct dsa_switch *ds, int port, 564b2f2af21SFlorian Fainelli struct phy_device *phy); 56575104db0SAndrew Lunn void (*port_disable)(struct dsa_switch *ds, int port); 5667905288fSFlorian Fainelli 5677905288fSFlorian Fainelli /* 56808f50061SVivien Didelot * Port's MAC EEE settings 5697905288fSFlorian Fainelli */ 57008f50061SVivien Didelot int (*set_mac_eee)(struct dsa_switch *ds, int port, 5717905288fSFlorian Fainelli struct ethtool_eee *e); 57208f50061SVivien Didelot int (*get_mac_eee)(struct dsa_switch *ds, int port, 5737905288fSFlorian Fainelli struct ethtool_eee *e); 57451579c3fSGuenter Roeck 5756793abb4SGuenter Roeck /* EEPROM access */ 5766793abb4SGuenter Roeck int (*get_eeprom_len)(struct dsa_switch *ds); 5776793abb4SGuenter Roeck int (*get_eeprom)(struct dsa_switch *ds, 5786793abb4SGuenter Roeck struct ethtool_eeprom *eeprom, u8 *data); 5796793abb4SGuenter Roeck int (*set_eeprom)(struct dsa_switch *ds, 5806793abb4SGuenter Roeck struct ethtool_eeprom *eeprom, u8 *data); 5813d762a0fSGuenter Roeck 5823d762a0fSGuenter Roeck /* 5833d762a0fSGuenter Roeck * Register access. 5843d762a0fSGuenter Roeck */ 5853d762a0fSGuenter Roeck int (*get_regs_len)(struct dsa_switch *ds, int port); 5863d762a0fSGuenter Roeck void (*get_regs)(struct dsa_switch *ds, int port, 5873d762a0fSGuenter Roeck struct ethtool_regs *regs, void *p); 588b73adef6SFlorian Fainelli 589b73adef6SFlorian Fainelli /* 590e358bef7SVladimir Oltean * Upper device tracking. 591e358bef7SVladimir Oltean */ 592e358bef7SVladimir Oltean int (*port_prechangeupper)(struct dsa_switch *ds, int port, 593e358bef7SVladimir Oltean struct netdev_notifier_changeupper_info *info); 594e358bef7SVladimir Oltean 595e358bef7SVladimir Oltean /* 596b73adef6SFlorian Fainelli * Bridge integration 597b73adef6SFlorian Fainelli */ 59834a79f63SVivien Didelot int (*set_ageing_time)(struct dsa_switch *ds, unsigned int msecs); 59971327a4eSVivien Didelot int (*port_bridge_join)(struct dsa_switch *ds, int port, 600a6692754SVivien Didelot struct net_device *bridge); 601f123f2fbSVivien Didelot void (*port_bridge_leave)(struct dsa_switch *ds, int port, 602f123f2fbSVivien Didelot struct net_device *bridge); 60343c44a9fSVivien Didelot void (*port_stp_state_set)(struct dsa_switch *ds, int port, 604b73adef6SFlorian Fainelli u8 state); 605732f794cSVivien Didelot void (*port_fast_age)(struct dsa_switch *ds, int port); 60657652796SRussell King int (*port_egress_floods)(struct dsa_switch *ds, int port, 60757652796SRussell King bool unicast, bool multicast); 6082a778e1bSVivien Didelot 6092a778e1bSVivien Didelot /* 61011149536SVivien Didelot * VLAN support 61111149536SVivien Didelot */ 612fb2dabadSVivien Didelot int (*port_vlan_filtering)(struct dsa_switch *ds, int port, 613bae33f2bSVladimir Oltean bool vlan_filtering); 6141958d581SVladimir Oltean int (*port_vlan_add)(struct dsa_switch *ds, int port, 61580e02360SVivien Didelot const struct switchdev_obj_port_vlan *vlan); 61676e398a6SVivien Didelot int (*port_vlan_del)(struct dsa_switch *ds, int port, 61776e398a6SVivien Didelot const struct switchdev_obj_port_vlan *vlan); 61811149536SVivien Didelot /* 6192a778e1bSVivien Didelot * Forwarding database 6202a778e1bSVivien Didelot */ 6211b6dd556SArkadi Sharshevsky int (*port_fdb_add)(struct dsa_switch *ds, int port, 6226c2c1dcbSArkadi Sharshevsky const unsigned char *addr, u16 vid); 6232a778e1bSVivien Didelot int (*port_fdb_del)(struct dsa_switch *ds, int port, 6246c2c1dcbSArkadi Sharshevsky const unsigned char *addr, u16 vid); 625ea70ba98SVivien Didelot int (*port_fdb_dump)(struct dsa_switch *ds, int port, 6262bedde1aSArkadi Sharshevsky dsa_fdb_dump_cb_t *cb, void *data); 6278df30255SVivien Didelot 6288df30255SVivien Didelot /* 6298df30255SVivien Didelot * Multicast database 6308df30255SVivien Didelot */ 631a52b2da7SVladimir Oltean int (*port_mdb_add)(struct dsa_switch *ds, int port, 6323709aadcSVivien Didelot const struct switchdev_obj_port_mdb *mdb); 6338df30255SVivien Didelot int (*port_mdb_del)(struct dsa_switch *ds, int port, 6348df30255SVivien Didelot const struct switchdev_obj_port_mdb *mdb); 635bf9f2648SFlorian Fainelli /* 636bf9f2648SFlorian Fainelli * RXNFC 637bf9f2648SFlorian Fainelli */ 638bf9f2648SFlorian Fainelli int (*get_rxnfc)(struct dsa_switch *ds, int port, 639bf9f2648SFlorian Fainelli struct ethtool_rxnfc *nfc, u32 *rule_locs); 640bf9f2648SFlorian Fainelli int (*set_rxnfc)(struct dsa_switch *ds, int port, 641bf9f2648SFlorian Fainelli struct ethtool_rxnfc *nfc); 642f50f2127SFlorian Fainelli 643f50f2127SFlorian Fainelli /* 644f50f2127SFlorian Fainelli * TC integration 645f50f2127SFlorian Fainelli */ 646ed11bb1fSVladimir Oltean int (*cls_flower_add)(struct dsa_switch *ds, int port, 647ed11bb1fSVladimir Oltean struct flow_cls_offload *cls, bool ingress); 648ed11bb1fSVladimir Oltean int (*cls_flower_del)(struct dsa_switch *ds, int port, 649ed11bb1fSVladimir Oltean struct flow_cls_offload *cls, bool ingress); 650ed11bb1fSVladimir Oltean int (*cls_flower_stats)(struct dsa_switch *ds, int port, 651ed11bb1fSVladimir Oltean struct flow_cls_offload *cls, bool ingress); 652f50f2127SFlorian Fainelli int (*port_mirror_add)(struct dsa_switch *ds, int port, 653f50f2127SFlorian Fainelli struct dsa_mall_mirror_tc_entry *mirror, 654f50f2127SFlorian Fainelli bool ingress); 655f50f2127SFlorian Fainelli void (*port_mirror_del)(struct dsa_switch *ds, int port, 656f50f2127SFlorian Fainelli struct dsa_mall_mirror_tc_entry *mirror); 65734297176SVladimir Oltean int (*port_policer_add)(struct dsa_switch *ds, int port, 65834297176SVladimir Oltean struct dsa_mall_policer_tc_entry *policer); 65934297176SVladimir Oltean void (*port_policer_del)(struct dsa_switch *ds, int port); 66047d23af2SVladimir Oltean int (*port_setup_tc)(struct dsa_switch *ds, int port, 66147d23af2SVladimir Oltean enum tc_setup_type type, void *type_data); 66240ef2c93SVivien Didelot 66340ef2c93SVivien Didelot /* 66440ef2c93SVivien Didelot * Cross-chip operations 66540ef2c93SVivien Didelot */ 666f66a6a69SVladimir Oltean int (*crosschip_bridge_join)(struct dsa_switch *ds, int tree_index, 667f66a6a69SVladimir Oltean int sw_index, int port, 668f66a6a69SVladimir Oltean struct net_device *br); 669f66a6a69SVladimir Oltean void (*crosschip_bridge_leave)(struct dsa_switch *ds, int tree_index, 670f66a6a69SVladimir Oltean int sw_index, int port, 671f66a6a69SVladimir Oltean struct net_device *br); 672*058102a6STobias Waldekranz int (*crosschip_lag_change)(struct dsa_switch *ds, int sw_index, 673*058102a6STobias Waldekranz int port); 674*058102a6STobias Waldekranz int (*crosschip_lag_join)(struct dsa_switch *ds, int sw_index, 675*058102a6STobias Waldekranz int port, struct net_device *lag, 676*058102a6STobias Waldekranz struct netdev_lag_upper_info *info); 677*058102a6STobias Waldekranz int (*crosschip_lag_leave)(struct dsa_switch *ds, int sw_index, 678*058102a6STobias Waldekranz int port, struct net_device *lag); 6790336369dSBrandon Streiff 6800336369dSBrandon Streiff /* 6810336369dSBrandon Streiff * PTP functionality 6820336369dSBrandon Streiff */ 6830336369dSBrandon Streiff int (*port_hwtstamp_get)(struct dsa_switch *ds, int port, 6840336369dSBrandon Streiff struct ifreq *ifr); 6850336369dSBrandon Streiff int (*port_hwtstamp_set)(struct dsa_switch *ds, int port, 6860336369dSBrandon Streiff struct ifreq *ifr); 68790af1059SBrandon Streiff bool (*port_txtstamp)(struct dsa_switch *ds, int port, 68890af1059SBrandon Streiff struct sk_buff *clone, unsigned int type); 68990af1059SBrandon Streiff bool (*port_rxtstamp)(struct dsa_switch *ds, int port, 69090af1059SBrandon Streiff struct sk_buff *skb, unsigned int type); 69197a69a0dSVladimir Oltean 6920f06b855SAndrew Lunn /* Devlink parameters, etc */ 6936b297524SAndrew Lunn int (*devlink_param_get)(struct dsa_switch *ds, u32 id, 6946b297524SAndrew Lunn struct devlink_param_gset_ctx *ctx); 6956b297524SAndrew Lunn int (*devlink_param_set)(struct dsa_switch *ds, u32 id, 6966b297524SAndrew Lunn struct devlink_param_gset_ctx *ctx); 6970f06b855SAndrew Lunn int (*devlink_info_get)(struct dsa_switch *ds, 6980f06b855SAndrew Lunn struct devlink_info_req *req, 6990f06b855SAndrew Lunn struct netlink_ext_ack *extack); 700bfcb8132SVladimir Oltean 701bfcb8132SVladimir Oltean /* 702bfcb8132SVladimir Oltean * MTU change functionality. Switches can also adjust their MRU through 703bfcb8132SVladimir Oltean * this method. By MTU, one understands the SDU (L2 payload) length. 704bfcb8132SVladimir Oltean * If the switch needs to account for the DSA tag on the CPU port, this 705ab88d64aSRandy Dunlap * method needs to do so privately. 706bfcb8132SVladimir Oltean */ 707bfcb8132SVladimir Oltean int (*port_change_mtu)(struct dsa_switch *ds, int port, 708bfcb8132SVladimir Oltean int new_mtu); 709bfcb8132SVladimir Oltean int (*port_max_mtu)(struct dsa_switch *ds, int port); 710*058102a6STobias Waldekranz 711*058102a6STobias Waldekranz /* 712*058102a6STobias Waldekranz * LAG integration 713*058102a6STobias Waldekranz */ 714*058102a6STobias Waldekranz int (*port_lag_change)(struct dsa_switch *ds, int port); 715*058102a6STobias Waldekranz int (*port_lag_join)(struct dsa_switch *ds, int port, 716*058102a6STobias Waldekranz struct net_device *lag, 717*058102a6STobias Waldekranz struct netdev_lag_upper_info *info); 718*058102a6STobias Waldekranz int (*port_lag_leave)(struct dsa_switch *ds, int port, 719*058102a6STobias Waldekranz struct net_device *lag); 7206b297524SAndrew Lunn }; 7216b297524SAndrew Lunn 7226b297524SAndrew Lunn #define DSA_DEVLINK_PARAM_DRIVER(_id, _name, _type, _cmodes) \ 7236b297524SAndrew Lunn DEVLINK_PARAM_DRIVER(_id, _name, _type, _cmodes, \ 7246b297524SAndrew Lunn dsa_devlink_param_get, dsa_devlink_param_set, NULL) 7256b297524SAndrew Lunn 7266b297524SAndrew Lunn int dsa_devlink_param_get(struct devlink *dl, u32 id, 7276b297524SAndrew Lunn struct devlink_param_gset_ctx *ctx); 7286b297524SAndrew Lunn int dsa_devlink_param_set(struct devlink *dl, u32 id, 7296b297524SAndrew Lunn struct devlink_param_gset_ctx *ctx); 7306b297524SAndrew Lunn int dsa_devlink_params_register(struct dsa_switch *ds, 7316b297524SAndrew Lunn const struct devlink_param *params, 7326b297524SAndrew Lunn size_t params_count); 7336b297524SAndrew Lunn void dsa_devlink_params_unregister(struct dsa_switch *ds, 7346b297524SAndrew Lunn const struct devlink_param *params, 7356b297524SAndrew Lunn size_t params_count); 7365cd73fbdSAndrew Lunn int dsa_devlink_resource_register(struct dsa_switch *ds, 7375cd73fbdSAndrew Lunn const char *resource_name, 7385cd73fbdSAndrew Lunn u64 resource_size, 7395cd73fbdSAndrew Lunn u64 resource_id, 7405cd73fbdSAndrew Lunn u64 parent_resource_id, 7415cd73fbdSAndrew Lunn const struct devlink_resource_size_params *size_params); 7425cd73fbdSAndrew Lunn 7435cd73fbdSAndrew Lunn void dsa_devlink_resources_unregister(struct dsa_switch *ds); 7445cd73fbdSAndrew Lunn 7455cd73fbdSAndrew Lunn void dsa_devlink_resource_occ_get_register(struct dsa_switch *ds, 7465cd73fbdSAndrew Lunn u64 resource_id, 7475cd73fbdSAndrew Lunn devlink_resource_occ_get_t *occ_get, 7485cd73fbdSAndrew Lunn void *occ_get_priv); 7495cd73fbdSAndrew Lunn void dsa_devlink_resource_occ_get_unregister(struct dsa_switch *ds, 7505cd73fbdSAndrew Lunn u64 resource_id); 75197c82c23SAndrew Lunn struct devlink_region * 75297c82c23SAndrew Lunn dsa_devlink_region_create(struct dsa_switch *ds, 75397c82c23SAndrew Lunn const struct devlink_region_ops *ops, 75497c82c23SAndrew Lunn u32 region_max_snapshots, u64 region_size); 75508156ba4SAndrew Lunn struct devlink_region * 75608156ba4SAndrew Lunn dsa_devlink_port_region_create(struct dsa_switch *ds, 75708156ba4SAndrew Lunn int port, 75808156ba4SAndrew Lunn const struct devlink_port_region_ops *ops, 75908156ba4SAndrew Lunn u32 region_max_snapshots, u64 region_size); 76097c82c23SAndrew Lunn void dsa_devlink_region_destroy(struct devlink_region *region); 76197c82c23SAndrew Lunn 762e1eea811SVladimir Oltean struct dsa_port *dsa_port_from_netdev(struct net_device *netdev); 7635cd73fbdSAndrew Lunn 7646b297524SAndrew Lunn struct dsa_devlink_priv { 7656b297524SAndrew Lunn struct dsa_switch *ds; 766c8f0b869SBen Hutchings }; 767c8f0b869SBen Hutchings 768ccc3e6b0SAndrew Lunn static inline struct dsa_switch *dsa_devlink_to_ds(struct devlink *dl) 769ccc3e6b0SAndrew Lunn { 770ccc3e6b0SAndrew Lunn struct dsa_devlink_priv *dl_priv = devlink_priv(dl); 771ccc3e6b0SAndrew Lunn 772ccc3e6b0SAndrew Lunn return dl_priv->ds; 773ccc3e6b0SAndrew Lunn } 774ccc3e6b0SAndrew Lunn 7757d1e2a10SAndrew Lunn static inline 7767d1e2a10SAndrew Lunn struct dsa_switch *dsa_devlink_port_to_ds(struct devlink_port *port) 7777d1e2a10SAndrew Lunn { 7787d1e2a10SAndrew Lunn struct devlink *dl = port->devlink; 7797d1e2a10SAndrew Lunn struct dsa_devlink_priv *dl_priv = devlink_priv(dl); 7807d1e2a10SAndrew Lunn 7817d1e2a10SAndrew Lunn return dl_priv->ds; 7827d1e2a10SAndrew Lunn } 7837d1e2a10SAndrew Lunn 7847d1e2a10SAndrew Lunn static inline int dsa_devlink_port_to_port(struct devlink_port *port) 7857d1e2a10SAndrew Lunn { 7867d1e2a10SAndrew Lunn return port->index; 7877d1e2a10SAndrew Lunn } 7887d1e2a10SAndrew Lunn 789ab3d408dSFlorian Fainelli struct dsa_switch_driver { 790ab3d408dSFlorian Fainelli struct list_head list; 791a82f67afSFlorian Fainelli const struct dsa_switch_ops *ops; 792ab3d408dSFlorian Fainelli }; 793ab3d408dSFlorian Fainelli 79414b89f36SFlorian Fainelli struct net_device *dsa_dev_to_net_device(struct device *dev); 795c8f0b869SBen Hutchings 79673a7ece8SVivien Didelot /* Keep inline for faster access in hot path */ 7979eb8eff0SVladimir Oltean static inline bool netdev_uses_dsa(const struct net_device *dev) 798c6e970a0SAndrew Lunn { 799c6e970a0SAndrew Lunn #if IS_ENABLED(CONFIG_NET_DSA) 800717ffbfbSVivien Didelot return dev->dsa_ptr && dev->dsa_ptr->rcv; 801c6e970a0SAndrew Lunn #endif 802c6e970a0SAndrew Lunn return false; 803c6e970a0SAndrew Lunn } 804c6e970a0SAndrew Lunn 805cc1939e4SVladimir Oltean static inline bool dsa_can_decode(const struct sk_buff *skb, 806cc1939e4SVladimir Oltean struct net_device *dev) 807cc1939e4SVladimir Oltean { 808cc1939e4SVladimir Oltean #if IS_ENABLED(CONFIG_NET_DSA) 809cc1939e4SVladimir Oltean return !dev->dsa_ptr->filter || dev->dsa_ptr->filter(skb, dev); 810cc1939e4SVladimir Oltean #endif 811cc1939e4SVladimir Oltean return false; 812cc1939e4SVladimir Oltean } 813cc1939e4SVladimir Oltean 8149790cf20SVladimir Oltean /* All DSA tags that push the EtherType to the right (basically all except tail 8159790cf20SVladimir Oltean * tags, which don't break dissection) can be treated the same from the 8169790cf20SVladimir Oltean * perspective of the flow dissector. 8179790cf20SVladimir Oltean * 8189790cf20SVladimir Oltean * We need to return: 8199790cf20SVladimir Oltean * - offset: the (B - A) difference between: 8209790cf20SVladimir Oltean * A. the position of the real EtherType and 8219790cf20SVladimir Oltean * B. the current skb->data (aka ETH_HLEN bytes into the frame, aka 2 bytes 8229790cf20SVladimir Oltean * after the normal EtherType was supposed to be) 8239790cf20SVladimir Oltean * The offset in bytes is exactly equal to the tagger overhead (and half of 8249790cf20SVladimir Oltean * that, in __be16 shorts). 8259790cf20SVladimir Oltean * 8269790cf20SVladimir Oltean * - proto: the value of the real EtherType. 8279790cf20SVladimir Oltean */ 8289790cf20SVladimir Oltean static inline void dsa_tag_generic_flow_dissect(const struct sk_buff *skb, 8299790cf20SVladimir Oltean __be16 *proto, int *offset) 8309790cf20SVladimir Oltean { 8319790cf20SVladimir Oltean #if IS_ENABLED(CONFIG_NET_DSA) 8329790cf20SVladimir Oltean const struct dsa_device_ops *ops = skb->dev->dsa_ptr->tag_ops; 8339790cf20SVladimir Oltean int tag_len = ops->overhead; 8349790cf20SVladimir Oltean 8359790cf20SVladimir Oltean *offset = tag_len; 8369790cf20SVladimir Oltean *proto = ((__be16 *)skb->data)[(tag_len / 2) - 1]; 8379790cf20SVladimir Oltean #endif 8389790cf20SVladimir Oltean } 8399790cf20SVladimir Oltean 8404cfab356SFlorian Fainelli #if IS_ENABLED(CONFIG_NET_DSA) 8414cfab356SFlorian Fainelli static inline int __dsa_netdevice_ops_check(struct net_device *dev) 8424cfab356SFlorian Fainelli { 8434cfab356SFlorian Fainelli int err = -EOPNOTSUPP; 8444cfab356SFlorian Fainelli 8454cfab356SFlorian Fainelli if (!dev->dsa_ptr) 8464cfab356SFlorian Fainelli return err; 8474cfab356SFlorian Fainelli 8484cfab356SFlorian Fainelli if (!dev->dsa_ptr->netdev_ops) 8494cfab356SFlorian Fainelli return err; 8504cfab356SFlorian Fainelli 8514cfab356SFlorian Fainelli return 0; 8524cfab356SFlorian Fainelli } 8534cfab356SFlorian Fainelli 8544cfab356SFlorian Fainelli static inline int dsa_ndo_do_ioctl(struct net_device *dev, struct ifreq *ifr, 8554cfab356SFlorian Fainelli int cmd) 8564cfab356SFlorian Fainelli { 8574cfab356SFlorian Fainelli const struct dsa_netdevice_ops *ops; 8584cfab356SFlorian Fainelli int err; 8594cfab356SFlorian Fainelli 8604cfab356SFlorian Fainelli err = __dsa_netdevice_ops_check(dev); 8614cfab356SFlorian Fainelli if (err) 8624cfab356SFlorian Fainelli return err; 8634cfab356SFlorian Fainelli 8644cfab356SFlorian Fainelli ops = dev->dsa_ptr->netdev_ops; 8654cfab356SFlorian Fainelli 8664cfab356SFlorian Fainelli return ops->ndo_do_ioctl(dev, ifr, cmd); 8674cfab356SFlorian Fainelli } 8684cfab356SFlorian Fainelli #else 8694cfab356SFlorian Fainelli static inline int dsa_ndo_do_ioctl(struct net_device *dev, struct ifreq *ifr, 8704cfab356SFlorian Fainelli int cmd) 8714cfab356SFlorian Fainelli { 8724cfab356SFlorian Fainelli return -EOPNOTSUPP; 8734cfab356SFlorian Fainelli } 8744cfab356SFlorian Fainelli #endif 8754cfab356SFlorian Fainelli 87683c0afaeSAndrew Lunn void dsa_unregister_switch(struct dsa_switch *ds); 87723c9ee49SVivien Didelot int dsa_register_switch(struct dsa_switch *ds); 8783b7bc1f0SVladimir Oltean struct dsa_switch *dsa_switch_find(int tree_index, int sw_index); 879ea825e70SFlorian Fainelli #ifdef CONFIG_PM_SLEEP 880ea825e70SFlorian Fainelli int dsa_switch_suspend(struct dsa_switch *ds); 881ea825e70SFlorian Fainelli int dsa_switch_resume(struct dsa_switch *ds); 882ea825e70SFlorian Fainelli #else 883ea825e70SFlorian Fainelli static inline int dsa_switch_suspend(struct dsa_switch *ds) 884ea825e70SFlorian Fainelli { 885ea825e70SFlorian Fainelli return 0; 886ea825e70SFlorian Fainelli } 887ea825e70SFlorian Fainelli static inline int dsa_switch_resume(struct dsa_switch *ds) 888ea825e70SFlorian Fainelli { 889ea825e70SFlorian Fainelli return 0; 890ea825e70SFlorian Fainelli } 891ea825e70SFlorian Fainelli #endif /* CONFIG_PM_SLEEP */ 892ea825e70SFlorian Fainelli 89360724d4bSFlorian Fainelli #if IS_ENABLED(CONFIG_NET_DSA) 894a5e3c9baSVladimir Oltean bool dsa_slave_dev_check(const struct net_device *dev); 89560724d4bSFlorian Fainelli #else 896a5e3c9baSVladimir Oltean static inline bool dsa_slave_dev_check(const struct net_device *dev) 897a5e3c9baSVladimir Oltean { 898a5e3c9baSVladimir Oltean return false; 899a5e3c9baSVladimir Oltean } 90060724d4bSFlorian Fainelli #endif 90160724d4bSFlorian Fainelli 90297a69a0dSVladimir Oltean netdev_tx_t dsa_enqueue_skb(struct sk_buff *skb, struct net_device *dev); 903cf963573SFlorian Fainelli int dsa_port_get_phy_strings(struct dsa_port *dp, uint8_t *data); 904cf963573SFlorian Fainelli int dsa_port_get_ethtool_phy_stats(struct dsa_port *dp, uint64_t *data); 905cf963573SFlorian Fainelli int dsa_port_get_phy_sset_count(struct dsa_port *dp); 90611d8f3ddSFlorian Fainelli void dsa_port_phylink_mac_change(struct dsa_switch *ds, int port, bool up); 907cf963573SFlorian Fainelli 908d3b8c049SAndrew Lunn struct dsa_tag_driver { 909d3b8c049SAndrew Lunn const struct dsa_device_ops *ops; 910d3b8c049SAndrew Lunn struct list_head list; 911d3b8c049SAndrew Lunn struct module *owner; 912d3b8c049SAndrew Lunn }; 913d3b8c049SAndrew Lunn 914d3b8c049SAndrew Lunn void dsa_tag_drivers_register(struct dsa_tag_driver *dsa_tag_driver_array[], 915d3b8c049SAndrew Lunn unsigned int count, 916d3b8c049SAndrew Lunn struct module *owner); 917d3b8c049SAndrew Lunn void dsa_tag_drivers_unregister(struct dsa_tag_driver *dsa_tag_driver_array[], 918d3b8c049SAndrew Lunn unsigned int count); 919d3b8c049SAndrew Lunn 920d3b8c049SAndrew Lunn #define dsa_tag_driver_module_drivers(__dsa_tag_drivers_array, __count) \ 921d3b8c049SAndrew Lunn static int __init dsa_tag_driver_module_init(void) \ 922d3b8c049SAndrew Lunn { \ 923d3b8c049SAndrew Lunn dsa_tag_drivers_register(__dsa_tag_drivers_array, __count, \ 924d3b8c049SAndrew Lunn THIS_MODULE); \ 925d3b8c049SAndrew Lunn return 0; \ 926d3b8c049SAndrew Lunn } \ 927d3b8c049SAndrew Lunn module_init(dsa_tag_driver_module_init); \ 928d3b8c049SAndrew Lunn \ 929d3b8c049SAndrew Lunn static void __exit dsa_tag_driver_module_exit(void) \ 930d3b8c049SAndrew Lunn { \ 931d3b8c049SAndrew Lunn dsa_tag_drivers_unregister(__dsa_tag_drivers_array, __count); \ 932d3b8c049SAndrew Lunn } \ 933d3b8c049SAndrew Lunn module_exit(dsa_tag_driver_module_exit) 934d3b8c049SAndrew Lunn 935d3b8c049SAndrew Lunn /** 936d3b8c049SAndrew Lunn * module_dsa_tag_drivers() - Helper macro for registering DSA tag 937d3b8c049SAndrew Lunn * drivers 938d3b8c049SAndrew Lunn * @__ops_array: Array of tag driver strucutres 939d3b8c049SAndrew Lunn * 940d3b8c049SAndrew Lunn * Helper macro for DSA tag drivers which do not do anything special 941d3b8c049SAndrew Lunn * in module init/exit. Each module may only use this macro once, and 942d3b8c049SAndrew Lunn * calling it replaces module_init() and module_exit(). 943d3b8c049SAndrew Lunn */ 944d3b8c049SAndrew Lunn #define module_dsa_tag_drivers(__ops_array) \ 945d3b8c049SAndrew Lunn dsa_tag_driver_module_drivers(__ops_array, ARRAY_SIZE(__ops_array)) 946d3b8c049SAndrew Lunn 947d3b8c049SAndrew Lunn #define DSA_TAG_DRIVER_NAME(__ops) dsa_tag_driver ## _ ## __ops 948d3b8c049SAndrew Lunn 949d3b8c049SAndrew Lunn /* Create a static structure we can build a linked list of dsa_tag 950d3b8c049SAndrew Lunn * drivers 951d3b8c049SAndrew Lunn */ 952d3b8c049SAndrew Lunn #define DSA_TAG_DRIVER(__ops) \ 953d3b8c049SAndrew Lunn static struct dsa_tag_driver DSA_TAG_DRIVER_NAME(__ops) = { \ 954d3b8c049SAndrew Lunn .ops = &__ops, \ 955d3b8c049SAndrew Lunn } 956d3b8c049SAndrew Lunn 957d3b8c049SAndrew Lunn /** 958d3b8c049SAndrew Lunn * module_dsa_tag_driver() - Helper macro for registering a single DSA tag 959d3b8c049SAndrew Lunn * driver 960d3b8c049SAndrew Lunn * @__ops: Single tag driver structures 961d3b8c049SAndrew Lunn * 962d3b8c049SAndrew Lunn * Helper macro for DSA tag drivers which do not do anything special 963d3b8c049SAndrew Lunn * in module init/exit. Each module may only use this macro once, and 964d3b8c049SAndrew Lunn * calling it replaces module_init() and module_exit(). 965d3b8c049SAndrew Lunn */ 966d3b8c049SAndrew Lunn #define module_dsa_tag_driver(__ops) \ 967d3b8c049SAndrew Lunn DSA_TAG_DRIVER(__ops); \ 968d3b8c049SAndrew Lunn \ 969d3b8c049SAndrew Lunn static struct dsa_tag_driver *dsa_tag_driver_array[] = { \ 970d3b8c049SAndrew Lunn &DSA_TAG_DRIVER_NAME(__ops) \ 971d3b8c049SAndrew Lunn }; \ 972d3b8c049SAndrew Lunn module_dsa_tag_drivers(dsa_tag_driver_array) 97391da11f8SLennert Buytenhek #endif 974d3b8c049SAndrew Lunn 975