net: dsa: Optional VLAN-based port separation for switches without tagging
[linux-2.6-block.git] / include / net / dsa.h
index ae480bba11f58e28435bd45c18632d2d5614a661..69f3714f42bab2637d3396909d6eeb79f5981c2c 100644 (file)
@@ -30,20 +30,34 @@ 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
+
 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,
 };
 
 struct packet_type;
@@ -56,8 +70,14 @@ struct dsa_device_ops {
        int (*flow_dissect)(const struct sk_buff *skb, __be16 *proto,
                            int *offset);
        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_switch_tree {
        struct list_head        list;
 
@@ -140,8 +160,10 @@ 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;
@@ -208,6 +230,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 +307,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);
 
@@ -476,20 +509,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 */
@@ -574,4 +593,70 @@ 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
+