Merge tag 'gfs2-for-5.2' of git://git.kernel.org/pub/scm/linux/kernel/git/gfs2/linux...
[sfrench/cifs-2.6.git] / include / net / dsa.h
index ae480bba11f58e28435bd45c18632d2d5614a661..6aaaadd6a413c9bf1d8600325d171fb69006d3be 100644 (file)
@@ -30,20 +30,36 @@ struct phy_device;
 struct fixed_phy_status;
 struct phylink_link_state;
 
+#define DSA_TAG_PROTO_NONE_VALUE               0
+#define DSA_TAG_PROTO_BRCM_VALUE               1
+#define DSA_TAG_PROTO_BRCM_PREPEND_VALUE       2
+#define DSA_TAG_PROTO_DSA_VALUE                        3
+#define DSA_TAG_PROTO_EDSA_VALUE               4
+#define DSA_TAG_PROTO_GSWIP_VALUE              5
+#define DSA_TAG_PROTO_KSZ9477_VALUE            6
+#define DSA_TAG_PROTO_KSZ9893_VALUE            7
+#define DSA_TAG_PROTO_LAN9303_VALUE            8
+#define DSA_TAG_PROTO_MTK_VALUE                        9
+#define DSA_TAG_PROTO_QCA_VALUE                        10
+#define DSA_TAG_PROTO_TRAILER_VALUE            11
+#define DSA_TAG_PROTO_8021Q_VALUE              12
+#define DSA_TAG_PROTO_SJA1105_VALUE            13
+
 enum dsa_tag_protocol {
-       DSA_TAG_PROTO_NONE = 0,
-       DSA_TAG_PROTO_BRCM,
-       DSA_TAG_PROTO_BRCM_PREPEND,
-       DSA_TAG_PROTO_DSA,
-       DSA_TAG_PROTO_EDSA,
-       DSA_TAG_PROTO_GSWIP,
-       DSA_TAG_PROTO_KSZ9477,
-       DSA_TAG_PROTO_KSZ9893,
-       DSA_TAG_PROTO_LAN9303,
-       DSA_TAG_PROTO_MTK,
-       DSA_TAG_PROTO_QCA,
-       DSA_TAG_PROTO_TRAILER,
-       DSA_TAG_LAST,           /* MUST BE LAST */
+       DSA_TAG_PROTO_NONE              = DSA_TAG_PROTO_NONE_VALUE,
+       DSA_TAG_PROTO_BRCM              = DSA_TAG_PROTO_BRCM_VALUE,
+       DSA_TAG_PROTO_BRCM_PREPEND      = DSA_TAG_PROTO_BRCM_PREPEND_VALUE,
+       DSA_TAG_PROTO_DSA               = DSA_TAG_PROTO_DSA_VALUE,
+       DSA_TAG_PROTO_EDSA              = DSA_TAG_PROTO_EDSA_VALUE,
+       DSA_TAG_PROTO_GSWIP             = DSA_TAG_PROTO_GSWIP_VALUE,
+       DSA_TAG_PROTO_KSZ9477           = DSA_TAG_PROTO_KSZ9477_VALUE,
+       DSA_TAG_PROTO_KSZ9893           = DSA_TAG_PROTO_KSZ9893_VALUE,
+       DSA_TAG_PROTO_LAN9303           = DSA_TAG_PROTO_LAN9303_VALUE,
+       DSA_TAG_PROTO_MTK               = DSA_TAG_PROTO_MTK_VALUE,
+       DSA_TAG_PROTO_QCA               = DSA_TAG_PROTO_QCA_VALUE,
+       DSA_TAG_PROTO_TRAILER           = DSA_TAG_PROTO_TRAILER_VALUE,
+       DSA_TAG_PROTO_8021Q             = DSA_TAG_PROTO_8021Q_VALUE,
+       DSA_TAG_PROTO_SJA1105           = DSA_TAG_PROTO_SJA1105_VALUE,
 };
 
 struct packet_type;
@@ -55,9 +71,52 @@ struct dsa_device_ops {
                               struct packet_type *pt);
        int (*flow_dissect)(const struct sk_buff *skb, __be16 *proto,
                            int *offset);
+       /* Used to determine which traffic should match the DSA filter in
+        * eth_type_trans, and which, if any, should bypass it and be processed
+        * as regular on the master net device.
+        */
+       bool (*filter)(const struct sk_buff *skb, struct net_device *dev);
        unsigned int overhead;
+       const char *name;
+       enum dsa_tag_protocol proto;
+};
+
+#define DSA_TAG_DRIVER_ALIAS "dsa_tag-"
+#define MODULE_ALIAS_DSA_TAG_DRIVER(__proto)                           \
+       MODULE_ALIAS(DSA_TAG_DRIVER_ALIAS __stringify(__proto##_VALUE))
+
+struct dsa_skb_cb {
+       struct sk_buff *clone;
+       bool deferred_xmit;
+};
+
+struct __dsa_skb_cb {
+       struct dsa_skb_cb cb;
+       u8 priv[48 - sizeof(struct dsa_skb_cb)];
 };
 
+#define __DSA_SKB_CB(skb) ((struct __dsa_skb_cb *)((skb)->cb))
+
+#define DSA_SKB_CB(skb) ((struct dsa_skb_cb *)((skb)->cb))
+
+#define DSA_SKB_CB_COPY(nskb, skb)             \
+       { *__DSA_SKB_CB(nskb) = *__DSA_SKB_CB(skb); }
+
+#define DSA_SKB_CB_ZERO(skb)                   \
+       { *__DSA_SKB_CB(skb) = (struct __dsa_skb_cb) {0}; }
+
+#define DSA_SKB_CB_PRIV(skb)                   \
+       ((void *)(skb)->cb + offsetof(struct __dsa_skb_cb, priv))
+
+#define DSA_SKB_CB_CLONE(_clone, _skb)         \
+       {                                       \
+               struct sk_buff *clone = _clone; \
+               struct sk_buff *skb = _skb;     \
+                                               \
+               DSA_SKB_CB_COPY(clone, skb);    \
+               DSA_SKB_CB(skb)->clone = clone; \
+       }
+
 struct dsa_switch_tree {
        struct list_head        list;
 
@@ -128,6 +187,7 @@ struct dsa_port {
        struct dsa_switch_tree *dst;
        struct sk_buff *(*rcv)(struct sk_buff *skb, struct net_device *dev,
                               struct packet_type *pt);
+       bool (*filter)(const struct sk_buff *skb, struct net_device *dev);
 
        enum {
                DSA_PORT_TYPE_UNUSED = 0,
@@ -140,12 +200,24 @@ struct dsa_port {
        unsigned int            index;
        const char              *name;
        const struct dsa_port   *cpu_dp;
+       const char              *mac;
        struct device_node      *dn;
        unsigned int            ageing_time;
+       bool                    vlan_filtering;
        u8                      stp_state;
        struct net_device       *bridge_dev;
        struct devlink_port     devlink_port;
        struct phylink          *pl;
+
+       struct work_struct      xmit_work;
+       struct sk_buff_head     xmit_queue;
+
+       /*
+        * Give the switch driver somewhere to hang its per-port private data
+        * structures (accessible from the tagger).
+        */
+       void *priv;
+
        /*
         * Original copy of the master netdev ethtool_ops
         */
@@ -208,6 +280,16 @@ struct dsa_switch {
        /* Number of switch port queues */
        unsigned int            num_tx_queues;
 
+       /* Disallow bridge core from requesting different VLAN awareness
+        * settings on ports if not hardware-supported
+        */
+       bool                    vlan_filtering_is_global;
+
+       /* In case vlan_filtering_is_global is set, the VLAN awareness state
+        * should be retrieved from here and not from the per-port settings.
+        */
+       bool                    vlan_filtering;
+
        unsigned long           *bitmap;
        unsigned long           _bitmap;
 
@@ -275,18 +357,19 @@ static inline unsigned int dsa_upstream_port(struct dsa_switch *ds, int port)
        return dsa_towards_port(ds, cpu_dp->ds->index, cpu_dp->index);
 }
 
+static inline bool dsa_port_is_vlan_filtering(const struct dsa_port *dp)
+{
+       const struct dsa_switch *ds = dp->ds;
+
+       if (ds->vlan_filtering_is_global)
+               return ds->vlan_filtering;
+       else
+               return dp->vlan_filtering;
+}
+
 typedef int dsa_fdb_dump_cb_t(const unsigned char *addr, u16 vid,
                              bool is_static, void *data);
 struct dsa_switch_ops {
-#if IS_ENABLED(CONFIG_NET_DSA_LEGACY)
-       /*
-        * Legacy probing.
-        */
-       const char      *(*probe)(struct device *dsa_dev,
-                                 struct device *host_dev, int sw_addr,
-                                 void **priv);
-#endif
-
        enum dsa_tag_protocol (*get_tag_protocol)(struct dsa_switch *ds,
                                                  int port);
 
@@ -469,6 +552,12 @@ struct dsa_switch_ops {
                                 struct sk_buff *clone, unsigned int type);
        bool    (*port_rxtstamp)(struct dsa_switch *ds, int port,
                                 struct sk_buff *skb, unsigned int type);
+
+       /*
+        * Deferred frame Tx
+        */
+       netdev_tx_t (*port_deferred_xmit)(struct dsa_switch *ds, int port,
+                                         struct sk_buff *skb);
 };
 
 struct dsa_switch_driver {
@@ -476,20 +565,6 @@ struct dsa_switch_driver {
        const struct dsa_switch_ops *ops;
 };
 
-#if IS_ENABLED(CONFIG_NET_DSA_LEGACY)
-/* Legacy driver registration */
-void register_switch_driver(struct dsa_switch_driver *type);
-void unregister_switch_driver(struct dsa_switch_driver *type);
-struct mii_bus *dsa_host_dev_to_mii_bus(struct device *dev);
-
-#else
-static inline void register_switch_driver(struct dsa_switch_driver *type) { }
-static inline void unregister_switch_driver(struct dsa_switch_driver *type) { }
-static inline struct mii_bus *dsa_host_dev_to_mii_bus(struct device *dev)
-{
-       return NULL;
-}
-#endif
 struct net_device *dsa_dev_to_net_device(struct device *dev);
 
 /* Keep inline for faster access in hot path */
@@ -501,6 +576,15 @@ static inline bool netdev_uses_dsa(struct net_device *dev)
        return false;
 }
 
+static inline bool dsa_can_decode(const struct sk_buff *skb,
+                                 struct net_device *dev)
+{
+#if IS_ENABLED(CONFIG_NET_DSA)
+       return !dev->dsa_ptr->filter || dev->dsa_ptr->filter(skb, dev);
+#endif
+       return false;
+}
+
 struct dsa_switch *dsa_switch_alloc(struct device *dev, size_t n);
 void dsa_unregister_switch(struct dsa_switch *ds);
 int dsa_register_switch(struct dsa_switch *ds);
@@ -569,9 +653,76 @@ static inline int call_dsa_notifiers(unsigned long val, struct net_device *dev,
 #define BRCM_TAG_GET_QUEUE(v)          ((v) & 0xff)
 
 
+netdev_tx_t dsa_enqueue_skb(struct sk_buff *skb, struct net_device *dev);
 int dsa_port_get_phy_strings(struct dsa_port *dp, uint8_t *data);
 int dsa_port_get_ethtool_phy_stats(struct dsa_port *dp, uint64_t *data);
 int dsa_port_get_phy_sset_count(struct dsa_port *dp);
 void dsa_port_phylink_mac_change(struct dsa_switch *ds, int port, bool up);
 
+struct dsa_tag_driver {
+       const struct dsa_device_ops *ops;
+       struct list_head list;
+       struct module *owner;
+};
+
+void dsa_tag_drivers_register(struct dsa_tag_driver *dsa_tag_driver_array[],
+                             unsigned int count,
+                             struct module *owner);
+void dsa_tag_drivers_unregister(struct dsa_tag_driver *dsa_tag_driver_array[],
+                               unsigned int count);
+
+#define dsa_tag_driver_module_drivers(__dsa_tag_drivers_array, __count)        \
+static int __init dsa_tag_driver_module_init(void)                     \
+{                                                                      \
+       dsa_tag_drivers_register(__dsa_tag_drivers_array, __count,      \
+                                THIS_MODULE);                          \
+       return 0;                                                       \
+}                                                                      \
+module_init(dsa_tag_driver_module_init);                               \
+                                                                       \
+static void __exit dsa_tag_driver_module_exit(void)                    \
+{                                                                      \
+       dsa_tag_drivers_unregister(__dsa_tag_drivers_array, __count);   \
+}                                                                      \
+module_exit(dsa_tag_driver_module_exit)
+
+/**
+ * module_dsa_tag_drivers() - Helper macro for registering DSA tag
+ * drivers
+ * @__ops_array: Array of tag driver strucutres
+ *
+ * Helper macro for DSA tag drivers which do not do anything special
+ * in module init/exit. Each module may only use this macro once, and
+ * calling it replaces module_init() and module_exit().
+ */
+#define module_dsa_tag_drivers(__ops_array)                            \
+dsa_tag_driver_module_drivers(__ops_array, ARRAY_SIZE(__ops_array))
+
+#define DSA_TAG_DRIVER_NAME(__ops) dsa_tag_driver ## _ ## __ops
+
+/* Create a static structure we can build a linked list of dsa_tag
+ * drivers
+ */
+#define DSA_TAG_DRIVER(__ops)                                          \
+static struct dsa_tag_driver DSA_TAG_DRIVER_NAME(__ops) = {            \
+       .ops = &__ops,                                                  \
+}
+
+/**
+ * module_dsa_tag_driver() - Helper macro for registering a single DSA tag
+ * driver
+ * @__ops: Single tag driver structures
+ *
+ * Helper macro for DSA tag drivers which do not do anything special
+ * in module init/exit. Each module may only use this macro once, and
+ * calling it replaces module_init() and module_exit().
+ */
+#define module_dsa_tag_driver(__ops)                                   \
+DSA_TAG_DRIVER(__ops);                                                 \
+                                                                       \
+static struct dsa_tag_driver *dsa_tag_driver_array[] = {               \
+       &DSA_TAG_DRIVER_NAME(__ops)                                     \
+};                                                                     \
+module_dsa_tag_drivers(dsa_tag_driver_array)
 #endif
+