aboutsummaryrefslogtreecommitdiff
path: root/include/net/dsa.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/net/dsa.h')
-rw-r--r--include/net/dsa.h98
1 files changed, 68 insertions, 30 deletions
diff --git a/include/net/dsa.h b/include/net/dsa.h
index 6463bb2863ac..2217a3f817f8 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -16,7 +16,6 @@
#include <linux/timer.h>
#include <linux/workqueue.h>
#include <linux/of.h>
-#include <linux/of_gpio.h>
#include <linux/phy.h>
#include <linux/phy_fixed.h>
#include <linux/ethtool.h>
@@ -27,11 +26,14 @@ enum dsa_tag_protocol {
DSA_TAG_PROTO_TRAILER,
DSA_TAG_PROTO_EDSA,
DSA_TAG_PROTO_BRCM,
+ DSA_TAG_LAST, /* MUST BE LAST */
};
#define DSA_MAX_SWITCHES 4
#define DSA_MAX_PORTS 12
+#define DSA_RTABLE_NONE -1
+
struct dsa_chip_data {
/*
* How to access the switch configuration registers.
@@ -59,19 +61,11 @@ struct dsa_chip_data {
struct device_node *port_dn[DSA_MAX_PORTS];
/*
- * An array (with nr_chips elements) of which element [a]
- * indicates which port on this switch should be used to
- * send packets to that are destined for switch a. Can be
- * NULL if there is only one switch chip.
- */
- s8 *rtable;
-
- /*
- * A switch may have a GPIO line tied to its reset pin. Parse
- * this from the device tree, and use it before performing
- * switch soft reset.
+ * An array of which element [a] indicates which port on this
+ * switch should be used to send packets to that are destined
+ * for switch a. Can be NULL if there is only one switch chip.
*/
- struct gpio_desc *reset;
+ s8 rtable[DSA_MAX_SWITCHES];
};
struct dsa_platform_data {
@@ -93,6 +87,17 @@ struct dsa_platform_data {
struct packet_type;
struct dsa_switch_tree {
+ struct list_head list;
+
+ /* Tree identifier */
+ u32 tree;
+
+ /* Number of switches attached to this tree */
+ struct kref refcount;
+
+ /* Has this tree been applied to the hardware? */
+ bool applied;
+
/*
* Configuration data for the platform device that owns
* this dsa switch tree instance.
@@ -108,7 +113,12 @@ struct dsa_switch_tree {
struct net_device *dev,
struct packet_type *pt,
struct net_device *orig_dev);
- enum dsa_tag_protocol tag_protocol;
+
+ /*
+ * Original copy of the master netdev ethtool_ops
+ */
+ struct ethtool_ops master_ethtool_ops;
+ const struct ethtool_ops *master_orig_ethtool_ops;
/*
* The switch and port to which the CPU is attached.
@@ -120,9 +130,23 @@ 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;
+};
+
+struct dsa_port {
+ struct net_device *netdev;
+ struct device_node *dn;
+ unsigned int ageing_time;
};
struct dsa_switch {
+ struct device *dev;
+
/*
* Parent switch tree, and switch index.
*/
@@ -130,14 +154,15 @@ struct dsa_switch {
int index;
/*
- * Tagging protocol understood by this switch
+ * Give the switch driver somewhere to hang its private data
+ * structure.
*/
- enum dsa_tag_protocol tag_protocol;
+ void *priv;
/*
* Configuration data for this switch.
*/
- struct dsa_chip_data *pd;
+ struct dsa_chip_data *cd;
/*
* The used switch driver.
@@ -145,9 +170,11 @@ struct dsa_switch {
struct dsa_switch_driver *drv;
/*
- * Reference to host device to use.
+ * An array of which element [a] indicates which port on this
+ * switch should be used to send packets to that are destined
+ * for switch a. Can be NULL if there is only one switch chip.
*/
- struct device *master_dev;
+ s8 rtable[DSA_MAX_SWITCHES];
#ifdef CONFIG_NET_DSA_HWMON
/*
@@ -158,13 +185,19 @@ struct dsa_switch {
#endif
/*
+ * The lower device this switch uses to talk to the host
+ */
+ struct net_device *master_netdev;
+
+ /*
* Slave mii_bus and devices for the individual ports.
*/
u32 dsa_port_mask;
- u32 phys_port_mask;
+ u32 cpu_port_mask;
+ u32 enabled_port_mask;
u32 phys_mii_mask;
+ struct dsa_port ports[DSA_MAX_PORTS];
struct mii_bus *slave_mii_bus;
- struct net_device *ports[DSA_MAX_PORTS];
};
static inline bool dsa_is_cpu_port(struct dsa_switch *ds, int p)
@@ -179,7 +212,7 @@ static inline bool dsa_is_dsa_port(struct dsa_switch *ds, int p)
static inline bool dsa_is_port_initialized(struct dsa_switch *ds, int p)
{
- return ds->phys_port_mask & (1 << p) && ds->ports[p];
+ return ds->enabled_port_mask & (1 << p) && ds->ports[p].netdev;
}
static inline u8 dsa_upstream_port(struct dsa_switch *ds)
@@ -195,7 +228,7 @@ static inline u8 dsa_upstream_port(struct dsa_switch *ds)
if (dst->cpu_switch == ds->index)
return dst->cpu_port;
else
- return ds->pd->rtable[dst->cpu_switch];
+ return ds->rtable[dst->cpu_switch];
}
struct switchdev_trans;
@@ -207,12 +240,13 @@ struct dsa_switch_driver {
struct list_head list;
enum dsa_tag_protocol tag_protocol;
- int priv_size;
/*
* Probing and setup.
*/
- char *(*probe)(struct device *host_dev, int sw_addr);
+ const char *(*probe)(struct device *dsa_dev,
+ struct device *host_dev, int sw_addr,
+ void **priv);
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);
@@ -296,11 +330,12 @@ struct dsa_switch_driver {
/*
* Bridge integration
*/
+ int (*set_ageing_time)(struct dsa_switch *ds, unsigned int msecs);
int (*port_bridge_join)(struct dsa_switch *ds, int port,
struct net_device *bridge);
void (*port_bridge_leave)(struct dsa_switch *ds, int port);
- int (*port_stp_update)(struct dsa_switch *ds, int port,
- u8 state);
+ void (*port_stp_state_set)(struct dsa_switch *ds, int port,
+ u8 state);
/*
* VLAN support
@@ -310,7 +345,7 @@ struct dsa_switch_driver {
int (*port_vlan_prepare)(struct dsa_switch *ds, int port,
const struct switchdev_obj_port_vlan *vlan,
struct switchdev_trans *trans);
- int (*port_vlan_add)(struct dsa_switch *ds, int port,
+ void (*port_vlan_add)(struct dsa_switch *ds, int port,
const struct switchdev_obj_port_vlan *vlan,
struct switchdev_trans *trans);
int (*port_vlan_del)(struct dsa_switch *ds, int port,
@@ -325,7 +360,7 @@ struct dsa_switch_driver {
int (*port_fdb_prepare)(struct dsa_switch *ds, int port,
const struct switchdev_obj_port_fdb *fdb,
struct switchdev_trans *trans);
- int (*port_fdb_add)(struct dsa_switch *ds, int port,
+ void (*port_fdb_add)(struct dsa_switch *ds, int port,
const struct switchdev_obj_port_fdb *fdb,
struct switchdev_trans *trans);
int (*port_fdb_del)(struct dsa_switch *ds, int port,
@@ -341,11 +376,14 @@ struct mii_bus *dsa_host_dev_to_mii_bus(struct device *dev);
static inline void *ds_to_priv(struct dsa_switch *ds)
{
- return (void *)(ds + 1);
+ return ds->priv;
}
static inline bool dsa_uses_tagged_protocol(struct dsa_switch_tree *dst)
{
return dst->rcv != NULL;
}
+
+void dsa_unregister_switch(struct dsa_switch *ds);
+int dsa_register_switch(struct dsa_switch *ds, struct device_node *np);
#endif