]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - include/net/dsa.h
net: dsa: Pass a port to get_tag_protocol()
[mirror_ubuntu-bionic-kernel.git] / include / net / dsa.h
index dd44d6ce10976fa4d14a9b6086104c782cf5f40b..68e232fd4b0f0476e3cd4f658e05bdaf94932454 100644 (file)
@@ -116,13 +116,13 @@ struct dsa_switch_tree {
        struct raw_notifier_head        nh;
 
        /* Tree identifier */
-       u32 tree;
+       unsigned int index;
 
        /* Number of switches attached to this tree */
        struct kref refcount;
 
        /* Has this tree been applied to the hardware? */
-       bool applied;
+       bool setup;
 
        /*
         * Configuration data for the platform device that owns
@@ -130,11 +130,6 @@ struct dsa_switch_tree {
         */
        struct dsa_platform_data        *pd;
 
-       /* Copy of tag_ops->rcv for faster access in hot path */
-       struct sk_buff *        (*rcv)(struct sk_buff *skb,
-                                      struct net_device *dev,
-                                      struct packet_type *pt);
-
        /*
         * The switch port to which the CPU is attached.
         */
@@ -144,12 +139,6 @@ struct dsa_switch_tree {
         * Data for the individual switch chips.
         */
        struct dsa_switch       *ds[DSA_MAX_SWITCHES];
-
-       /*
-        * Tagging protocol operations for adding and removing an
-        * encapsulation tag.
-        */
-       const struct dsa_device_ops *tag_ops;
 };
 
 /* TC matchall action types, only mirroring for now */
@@ -175,11 +164,33 @@ struct dsa_mall_tc_entry {
 
 
 struct dsa_port {
+       /* A CPU port is physically connected to a master device.
+        * A user port exposed to userspace has a slave device.
+        */
+       union {
+               struct net_device *master;
+               struct net_device *slave;
+       };
+
+       /* CPU port tagging operations used by master or slave devices */
+       const struct dsa_device_ops *tag_ops;
+
+       /* Copies for faster access in master receive hot path */
+       struct dsa_switch_tree *dst;
+       struct sk_buff *(*rcv)(struct sk_buff *skb, struct net_device *dev,
+                              struct packet_type *pt);
+
+       enum {
+               DSA_PORT_TYPE_UNUSED = 0,
+               DSA_PORT_TYPE_CPU,
+               DSA_PORT_TYPE_DSA,
+               DSA_PORT_TYPE_USER,
+       } type;
+
        struct dsa_switch       *ds;
        unsigned int            index;
        const char              *name;
-       struct dsa_port         *cpu_dp;
-       struct net_device       *netdev;
+       const struct dsa_port   *cpu_dp;
        struct device_node      *dn;
        unsigned int            ageing_time;
        u8                      stp_state;
@@ -188,7 +199,6 @@ struct dsa_port {
        /*
         * Original copy of the master netdev ethtool_ops
         */
-       struct ethtool_ops      ethtool_ops;
        const struct ethtool_ops *orig_ethtool_ops;
 };
 
@@ -199,7 +209,7 @@ struct dsa_switch {
         * Parent switch tree, and switch index.
         */
        struct dsa_switch_tree  *dst;
-       int                     index;
+       unsigned int            index;
 
        /* Listener for switch fabric events */
        struct notifier_block   nb;
@@ -230,9 +240,6 @@ struct dsa_switch {
        /*
         * Slave mii_bus and devices for the individual ports.
         */
-       u32                     dsa_port_mask;
-       u32                     cpu_port_mask;
-       u32                     enabled_port_mask;
        u32                     phys_mii_mask;
        struct mii_bus          *slave_mii_bus;
 
@@ -251,19 +258,41 @@ struct dsa_switch {
        struct dsa_port ports[];
 };
 
+static inline const struct dsa_port *dsa_to_port(struct dsa_switch *ds, int p)
+{
+       return &ds->ports[p];
+}
+
+static inline bool dsa_is_unused_port(struct dsa_switch *ds, int p)
+{
+       return dsa_to_port(ds, p)->type == DSA_PORT_TYPE_UNUSED;
+}
+
 static inline bool dsa_is_cpu_port(struct dsa_switch *ds, int p)
 {
-       return !!(ds->cpu_port_mask & (1 << p));
+       return dsa_to_port(ds, p)->type == DSA_PORT_TYPE_CPU;
 }
 
 static inline bool dsa_is_dsa_port(struct dsa_switch *ds, int p)
 {
-       return !!((ds->dsa_port_mask) & (1 << p));
+       return dsa_to_port(ds, p)->type == DSA_PORT_TYPE_DSA;
+}
+
+static inline bool dsa_is_user_port(struct dsa_switch *ds, int p)
+{
+       return dsa_to_port(ds, p)->type == DSA_PORT_TYPE_USER;
 }
 
-static inline bool dsa_is_normal_port(struct dsa_switch *ds, int p)
+static inline u32 dsa_user_ports(struct dsa_switch *ds)
 {
-       return !dsa_is_cpu_port(ds, p) && !dsa_is_dsa_port(ds, p);
+       u32 mask = 0;
+       int p;
+
+       for (p = 0; p < ds->num_ports; p++)
+               if (dsa_is_user_port(ds, p))
+                       mask |= BIT(p);
+
+       return mask;
 }
 
 static inline u8 dsa_upstream_port(struct dsa_switch *ds)
@@ -292,10 +321,10 @@ struct dsa_switch_ops {
                                  struct device *host_dev, int sw_addr,
                                  void **priv);
 
-       enum dsa_tag_protocol (*get_tag_protocol)(struct dsa_switch *ds);
+       enum dsa_tag_protocol (*get_tag_protocol)(struct dsa_switch *ds,
+                                                 int port);
 
        int     (*setup)(struct dsa_switch *ds);
-       int     (*set_addr)(struct dsa_switch *ds, u8 *addr);
        u32     (*get_phy_flags)(struct dsa_switch *ds, int port);
 
        /*
@@ -475,4 +504,54 @@ static inline int dsa_switch_resume(struct dsa_switch *ds)
 }
 #endif /* CONFIG_PM_SLEEP */
 
+enum dsa_notifier_type {
+       DSA_PORT_REGISTER,
+       DSA_PORT_UNREGISTER,
+};
+
+struct dsa_notifier_info {
+       struct net_device *dev;
+};
+
+struct dsa_notifier_register_info {
+       struct dsa_notifier_info info;  /* must be first */
+       struct net_device *master;
+       unsigned int port_number;
+       unsigned int switch_number;
+};
+
+static inline struct net_device *
+dsa_notifier_info_to_dev(const struct dsa_notifier_info *info)
+{
+       return info->dev;
+}
+
+#if IS_ENABLED(CONFIG_NET_DSA)
+int register_dsa_notifier(struct notifier_block *nb);
+int unregister_dsa_notifier(struct notifier_block *nb);
+int call_dsa_notifiers(unsigned long val, struct net_device *dev,
+                      struct dsa_notifier_info *info);
+#else
+static inline int register_dsa_notifier(struct notifier_block *nb)
+{
+       return 0;
+}
+
+static inline int unregister_dsa_notifier(struct notifier_block *nb)
+{
+       return 0;
+}
+
+static inline int call_dsa_notifiers(unsigned long val, struct net_device *dev,
+                                    struct dsa_notifier_info *info)
+{
+       return NOTIFY_DONE;
+}
+#endif
+
+/* Broadcom tag specific helpers to insert and extract queue/port number */
+#define BRCM_TAG_SET_PORT_QUEUE(p, q)  ((p) << 8 | q)
+#define BRCM_TAG_GET_PORT(v)           ((v) >> 8)
+#define BRCM_TAG_GET_QUEUE(v)          ((v) & 0xff)
+
 #endif