* [PATCH RFC v2 00/32] Make DSA switches linux devices.
@ 2016-02-28 16:41 Andrew Lunn
2016-02-28 16:41 ` [PATCH RFC v2 01/32] net: dsa: Move platform data allocation for OF Andrew Lunn
` (32 more replies)
0 siblings, 33 replies; 47+ messages in thread
From: Andrew Lunn @ 2016-02-28 16:41 UTC (permalink / raw)
To: Florian Fainelli, Vivien Didelot, netdev; +Cc: Andrew Lunn
This is the second RFC for rearchitecturing how DSA devices are
probed. This patchset allows switches to be linux devices, probed by
the ususal mechanism for whatever bus they hang off. They then
register with the DSA core.
DSA has been limited to devices which hang off an MDIO bus, or with a
bit of work, memory mapped devices. This refactoring generalizes DSA
so that switches on other sorts of busses, eg. SPI can be supported.
The code should remain backwards compatible. The old device tree
binding are still supported. It is extended with phandles to switch
devices.
The changes also make it eaiser for the drivers to be kernel modules,
and the patches contain cleanups and fixes so that the modules can be
unloaded and loaded.
Patches can be found in
https://github.com/lunn/linux.git v4.5-rc2-net-next-dsa-proposal-4
Andrew Lunn (30):
dsa: Rename mv88e6123_61_65 to mv88e6123 to be consistent
dsa: Make setup and finish more symmetrical
net: dsa: Pass the dsa device to the switch drivers
net: dsa: Have the switch driver allocate there own private memory
net: dsa: Remove allocation of driver private memory
net: dsa: Keep the mii bus and address in the private structure
net: dsa: dsa.c: Refactor to increase symmetry
driver: component: Add support for empty match table
net: dsa: Add basic support for component master support
net: dsa: Keep a reference to the switch device for component matching
net: dsa: Add slave component matches based on a phandle to the slave.
net: dsa: Make dsa,mii-bus optional
net: dsa: Add register/unregister functions for switch drivers
net: dsa: Rename DSA probe function.
dsa: mv88e6xxx: Use bus in mv88e6xxx_lookup_name()
dsa: mv88e6xxx: Add shared code for binding/unbinding a switch driver.
dsa: mv88e6xxx: Prepare for turning this into a library module
dsa: mv88e6xxx: Add macro for registering the drivers
dsa: Add mdio device support to Marvell switches
net: mdio: Add mdiodev_{read|write} helpers
net: dsa: Better integrate the drivers with mdio device
net: dsa: Add some debug prints for error cases
net: dsa: Setup the switches after all have been probed
net: dsa: Only setup platform switches, not device switches
net: dsa: If a switch fails to probe, defer probing
Documentation: DSA: Describe how probe of DSA and switches work.
dsa: slave: Don't reference NULL pointer during phy_disconnect
dsa: Destroy fixed link phys after the phy has been disconnected
dsa: dsa: Fix freeing of fixed-phys from user ports.
phy: fixed: Fix removal of phys.
Florian Fainelli (2):
net: dsa: Move platform data allocation for OF
net: dsa: bcm_sf2: make it a real platform driver
.../devicetree/bindings/net/dsa/broadcom.txt | 54 +++
Documentation/devicetree/bindings/net/dsa/dsa.txt | 5 +-
.../devicetree/bindings/net/dsa/marvell.txt | 29 ++
Documentation/networking/dsa/dsa.txt | 48 +++
drivers/base/component.c | 33 +-
drivers/net/dsa/Kconfig | 2 +-
drivers/net/dsa/Makefile | 19 +-
drivers/net/dsa/bcm_sf2.c | 292 +++++++++-------
drivers/net/dsa/mv88e6060.c | 138 +++++++-
drivers/net/dsa/mv88e6060.h | 10 +
drivers/net/dsa/mv88e6123.c | 173 ++++++++++
drivers/net/dsa/mv88e6123_61_65.c | 124 -------
drivers/net/dsa/mv88e6131.c | 70 +++-
drivers/net/dsa/mv88e6171.c | 70 +++-
drivers/net/dsa/mv88e6352.c | 72 +++-
drivers/net/dsa/mv88e6xxx.c | 200 +++++++----
drivers/net/dsa/mv88e6xxx.h | 40 ++-
drivers/net/phy/fixed_phy.c | 10 +-
drivers/net/phy/mdio_device.c | 68 ++++
include/linux/mdio.h | 5 +
include/linux/phy_fixed.h | 2 +-
include/net/dsa.h | 17 +-
net/dsa/dsa.c | 372 ++++++++++++++-------
net/dsa/slave.c | 12 +-
24 files changed, 1339 insertions(+), 526 deletions(-)
create mode 100644 Documentation/devicetree/bindings/net/dsa/broadcom.txt
create mode 100644 Documentation/devicetree/bindings/net/dsa/marvell.txt
create mode 100644 drivers/net/dsa/mv88e6123.c
delete mode 100644 drivers/net/dsa/mv88e6123_61_65.c
--
2.7.0
^ permalink raw reply [flat|nested] 47+ messages in thread
* [PATCH RFC v2 01/32] net: dsa: Move platform data allocation for OF
2016-02-28 16:41 [PATCH RFC v2 00/32] Make DSA switches linux devices Andrew Lunn
@ 2016-02-28 16:41 ` Andrew Lunn
2016-02-28 16:41 ` [PATCH RFC v2 02/32] dsa: Rename mv88e6123_61_65 to mv88e6123 to be consistent Andrew Lunn
` (31 subsequent siblings)
32 siblings, 0 replies; 47+ messages in thread
From: Andrew Lunn @ 2016-02-28 16:41 UTC (permalink / raw)
To: Florian Fainelli, Vivien Didelot, netdev
From: Florian Fainelli <f.fainelli@gmail.com>
Do not have dsa_of_probe() allocate and assign struct dsa_platform_data,
but instead do this outside of this function such that we can control
exactly the storage of that data structure.
This is a preliminary change to allow multiple callers of dsa_of_probe()
not to clobber an existing dsa_platform_data and later, control where
this data structure is coming from.
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
net/dsa/dsa.c | 48 +++++++++++++++++++-----------------------------
1 file changed, 19 insertions(+), 29 deletions(-)
diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c
index fa4daba8db55..be68c00b8cfd 100644
--- a/net/dsa/dsa.c
+++ b/net/dsa/dsa.c
@@ -651,13 +651,12 @@ static void dsa_of_free_platform_data(struct dsa_platform_data *pd)
kfree(pd->chip);
}
-static int dsa_of_probe(struct device *dev)
+static int dsa_of_probe(struct device *dev, struct dsa_platform_data *pd)
{
struct device_node *np = dev->of_node;
struct device_node *child, *mdio, *ethernet, *port;
struct mii_bus *mdio_bus, *mdio_bus_switch;
struct net_device *ethernet_dev;
- struct dsa_platform_data *pd;
struct dsa_chip_data *cd;
const char *port_name;
int chip_index, port_index;
@@ -666,7 +665,7 @@ static int dsa_of_probe(struct device *dev)
enum of_gpio_flags of_flags;
unsigned long flags;
u32 eeprom_len;
- int ret;
+ int ret = 0;
mdio = of_parse_phandle(np, "dsa,mii-bus", 0);
if (!mdio)
@@ -688,13 +687,6 @@ static int dsa_of_probe(struct device *dev)
goto out_put_mdio;
}
- pd = kzalloc(sizeof(*pd), GFP_KERNEL);
- if (!pd) {
- ret = -ENOMEM;
- goto out_put_ethernet;
- }
-
- dev->platform_data = pd;
pd->of_netdev = ethernet_dev;
pd->nr_chips = of_get_available_child_count(np);
if (pd->nr_chips > DSA_MAX_SWITCHES)
@@ -702,10 +694,8 @@ static int dsa_of_probe(struct device *dev)
pd->chip = kcalloc(pd->nr_chips, sizeof(struct dsa_chip_data),
GFP_KERNEL);
- if (!pd->chip) {
- ret = -ENOMEM;
- goto out_free;
- }
+ if (!pd->chip)
+ goto out_put_mdio;
chip_index = -1;
for_each_available_child_of_node(np, child) {
@@ -795,34 +785,29 @@ static int dsa_of_probe(struct device *dev)
out_free_chip:
dsa_of_free_platform_data(pd);
-out_free:
- kfree(pd);
- dev->platform_data = NULL;
-out_put_ethernet:
- put_device(ðernet_dev->dev);
+
out_put_mdio:
put_device(&mdio_bus->dev);
return ret;
}
-static void dsa_of_remove(struct device *dev)
+static void dsa_of_remove(struct device *dev, struct dsa_platform_data *pd)
{
- struct dsa_platform_data *pd = dev->platform_data;
-
if (!dev->of_node)
return;
dsa_of_free_platform_data(pd);
put_device(&pd->of_netdev->dev);
- kfree(pd);
}
#else
-static inline int dsa_of_probe(struct device *dev)
+static inline int dsa_of_probe(struct device *dev,
+ struct dsa_platform_data *pd)
{
return 0;
}
-static inline void dsa_of_remove(struct device *dev)
+static inline void dsa_of_remove(struct device *dev,
+ struct dsa_platform_data *pd)
{
}
#endif
@@ -881,11 +866,15 @@ static int dsa_probe(struct platform_device *pdev)
dsa_driver_version);
if (pdev->dev.of_node) {
- ret = dsa_of_probe(&pdev->dev);
+ pd = devm_kzalloc(&pdev->dev, sizeof(*pd), GFP_KERNEL);
+ if (!pd)
+ return -ENOMEM;
+
+ ret = dsa_of_probe(&pdev->dev, pd);
if (ret)
return ret;
- pd = pdev->dev.platform_data;
+ pdev->dev.platform_data = pd;
}
if (pd == NULL || (pd->netdev == NULL && pd->of_netdev == NULL))
@@ -926,7 +915,7 @@ static int dsa_probe(struct platform_device *pdev)
return 0;
out:
- dsa_of_remove(&pdev->dev);
+ dsa_of_remove(&pdev->dev, pd);
return ret;
}
@@ -948,9 +937,10 @@ static void dsa_remove_dst(struct dsa_switch_tree *dst)
static int dsa_remove(struct platform_device *pdev)
{
struct dsa_switch_tree *dst = platform_get_drvdata(pdev);
+ struct dsa_platform_data *pd = pdev->dev.platform_data;
dsa_remove_dst(dst);
- dsa_of_remove(&pdev->dev);
+ dsa_of_remove(&pdev->dev, pd);
return 0;
}
--
2.7.0
^ permalink raw reply related [flat|nested] 47+ messages in thread
* [PATCH RFC v2 02/32] dsa: Rename mv88e6123_61_65 to mv88e6123 to be consistent
2016-02-28 16:41 [PATCH RFC v2 00/32] Make DSA switches linux devices Andrew Lunn
2016-02-28 16:41 ` [PATCH RFC v2 01/32] net: dsa: Move platform data allocation for OF Andrew Lunn
@ 2016-02-28 16:41 ` Andrew Lunn
2016-02-28 16:41 ` [PATCH RFC v2 03/32] dsa: Make setup and finish more symmetrical Andrew Lunn
` (30 subsequent siblings)
32 siblings, 0 replies; 47+ messages in thread
From: Andrew Lunn @ 2016-02-28 16:41 UTC (permalink / raw)
To: Florian Fainelli, Vivien Didelot, netdev; +Cc: Andrew Lunn
All the drivers support multiple chips, but mv88e6123_61_65 is the
only one that reflects this in its naming. Change it to be consistent
with the other drivers.
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
---
drivers/net/dsa/Kconfig | 2 +-
drivers/net/dsa/Makefile | 4 +-
drivers/net/dsa/mv88e6123.c | 124 ++++++++++++++++++++++++++++++++++++++
drivers/net/dsa/mv88e6123_61_65.c | 124 --------------------------------------
drivers/net/dsa/mv88e6xxx.c | 4 +-
drivers/net/dsa/mv88e6xxx.h | 2 +-
6 files changed, 130 insertions(+), 130 deletions(-)
create mode 100644 drivers/net/dsa/mv88e6123.c
delete mode 100644 drivers/net/dsa/mv88e6123_61_65.c
diff --git a/drivers/net/dsa/Kconfig b/drivers/net/dsa/Kconfig
index 4c483d937481..90ba003d8fdf 100644
--- a/drivers/net/dsa/Kconfig
+++ b/drivers/net/dsa/Kconfig
@@ -27,7 +27,7 @@ config NET_DSA_MV88E6131
This enables support for the Marvell 88E6085/6095/6095F/6131
ethernet switch chips.
-config NET_DSA_MV88E6123_61_65
+config NET_DSA_MV88E6123
tristate "Marvell 88E6123/6161/6165 ethernet switch chip support"
depends on NET_DSA
select NET_DSA_MV88E6XXX
diff --git a/drivers/net/dsa/Makefile b/drivers/net/dsa/Makefile
index e2d51c4b9382..a6e09939be65 100644
--- a/drivers/net/dsa/Makefile
+++ b/drivers/net/dsa/Makefile
@@ -1,8 +1,8 @@
obj-$(CONFIG_NET_DSA_MV88E6060) += mv88e6060.o
obj-$(CONFIG_NET_DSA_MV88E6XXX) += mv88e6xxx_drv.o
mv88e6xxx_drv-y += mv88e6xxx.o
-ifdef CONFIG_NET_DSA_MV88E6123_61_65
-mv88e6xxx_drv-y += mv88e6123_61_65.o
+ifdef CONFIG_NET_DSA_MV88E6123
+mv88e6xxx_drv-y += mv88e6123.o
endif
ifdef CONFIG_NET_DSA_MV88E6131
mv88e6xxx_drv-y += mv88e6131.o
diff --git a/drivers/net/dsa/mv88e6123.c b/drivers/net/dsa/mv88e6123.c
new file mode 100644
index 000000000000..69a6f79dcb10
--- /dev/null
+++ b/drivers/net/dsa/mv88e6123.c
@@ -0,0 +1,124 @@
+/*
+ * net/dsa/mv88e6123_61_65.c - Marvell 88e6123/6161/6165 switch chip support
+ * Copyright (c) 2008-2009 Marvell Semiconductor
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/delay.h>
+#include <linux/jiffies.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/phy.h>
+#include <net/dsa.h>
+#include "mv88e6xxx.h"
+
+static const struct mv88e6xxx_switch_id mv88e6123_table[] = {
+ { PORT_SWITCH_ID_6123, "Marvell 88E6123" },
+ { PORT_SWITCH_ID_6123_A1, "Marvell 88E6123 (A1)" },
+ { PORT_SWITCH_ID_6123_A2, "Marvell 88E6123 (A2)" },
+ { PORT_SWITCH_ID_6161, "Marvell 88E6161" },
+ { PORT_SWITCH_ID_6161_A1, "Marvell 88E6161 (A1)" },
+ { PORT_SWITCH_ID_6161_A2, "Marvell 88E6161 (A2)" },
+ { PORT_SWITCH_ID_6165, "Marvell 88E6165" },
+ { PORT_SWITCH_ID_6165_A1, "Marvell 88E6165 (A1)" },
+ { PORT_SWITCH_ID_6165_A2, "Marvell 88e6165 (A2)" },
+};
+
+static char *mv88e6123_probe(struct device *host_dev, int sw_addr)
+{
+ return mv88e6xxx_lookup_name(host_dev, sw_addr, mv88e6123_table,
+ ARRAY_SIZE(mv88e6123_table));
+}
+
+static int mv88e6123_setup_global(struct dsa_switch *ds)
+{
+ u32 upstream_port = dsa_upstream_port(ds);
+ int ret;
+ u32 reg;
+
+ ret = mv88e6xxx_setup_global(ds);
+ if (ret)
+ return ret;
+
+ /* Disable the PHY polling unit (since there won't be any
+ * external PHYs to poll), don't discard packets with
+ * excessive collisions, and mask all interrupt sources.
+ */
+ REG_WRITE(REG_GLOBAL, GLOBAL_CONTROL, 0x0000);
+
+ /* Configure the upstream port, and configure the upstream
+ * port as the port to which ingress and egress monitor frames
+ * are to be sent.
+ */
+ reg = upstream_port << GLOBAL_MONITOR_CONTROL_INGRESS_SHIFT |
+ upstream_port << GLOBAL_MONITOR_CONTROL_EGRESS_SHIFT |
+ upstream_port << GLOBAL_MONITOR_CONTROL_ARP_SHIFT;
+ REG_WRITE(REG_GLOBAL, GLOBAL_MONITOR_CONTROL, reg);
+
+ /* Disable remote management for now, and set the switch's
+ * DSA device number.
+ */
+ REG_WRITE(REG_GLOBAL, GLOBAL_CONTROL_2, ds->index & 0x1f);
+
+ return 0;
+}
+
+static int mv88e6123_setup(struct dsa_switch *ds)
+{
+ struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+ int ret;
+
+ ret = mv88e6xxx_setup_common(ds);
+ if (ret < 0)
+ return ret;
+
+ switch (ps->id) {
+ case PORT_SWITCH_ID_6123:
+ ps->num_ports = 3;
+ break;
+ case PORT_SWITCH_ID_6161:
+ case PORT_SWITCH_ID_6165:
+ ps->num_ports = 6;
+ break;
+ default:
+ return -ENODEV;
+ }
+
+ ret = mv88e6xxx_switch_reset(ds, false);
+ if (ret < 0)
+ return ret;
+
+ ret = mv88e6123_setup_global(ds);
+ if (ret < 0)
+ return ret;
+
+ return mv88e6xxx_setup_ports(ds);
+}
+
+struct dsa_switch_driver mv88e6123_switch_driver = {
+ .tag_protocol = DSA_TAG_PROTO_EDSA,
+ .priv_size = sizeof(struct mv88e6xxx_priv_state),
+ .probe = mv88e6123_probe,
+ .setup = mv88e6123_setup,
+ .set_addr = mv88e6xxx_set_addr_indirect,
+ .phy_read = mv88e6xxx_phy_read,
+ .phy_write = mv88e6xxx_phy_write,
+ .get_strings = mv88e6xxx_get_strings,
+ .get_ethtool_stats = mv88e6xxx_get_ethtool_stats,
+ .get_sset_count = mv88e6xxx_get_sset_count,
+ .adjust_link = mv88e6xxx_adjust_link,
+#ifdef CONFIG_NET_DSA_HWMON
+ .get_temp = mv88e6xxx_get_temp,
+#endif
+ .get_regs_len = mv88e6xxx_get_regs_len,
+ .get_regs = mv88e6xxx_get_regs,
+};
+
+MODULE_ALIAS("platform:mv88e6123");
+MODULE_ALIAS("platform:mv88e6161");
+MODULE_ALIAS("platform:mv88e6165");
diff --git a/drivers/net/dsa/mv88e6123_61_65.c b/drivers/net/dsa/mv88e6123_61_65.c
deleted file mode 100644
index d4fcf4570d95..000000000000
--- a/drivers/net/dsa/mv88e6123_61_65.c
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * net/dsa/mv88e6123_61_65.c - Marvell 88e6123/6161/6165 switch chip support
- * Copyright (c) 2008-2009 Marvell Semiconductor
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include <linux/delay.h>
-#include <linux/jiffies.h>
-#include <linux/list.h>
-#include <linux/module.h>
-#include <linux/netdevice.h>
-#include <linux/phy.h>
-#include <net/dsa.h>
-#include "mv88e6xxx.h"
-
-static const struct mv88e6xxx_switch_id mv88e6123_61_65_table[] = {
- { PORT_SWITCH_ID_6123, "Marvell 88E6123" },
- { PORT_SWITCH_ID_6123_A1, "Marvell 88E6123 (A1)" },
- { PORT_SWITCH_ID_6123_A2, "Marvell 88E6123 (A2)" },
- { PORT_SWITCH_ID_6161, "Marvell 88E6161" },
- { PORT_SWITCH_ID_6161_A1, "Marvell 88E6161 (A1)" },
- { PORT_SWITCH_ID_6161_A2, "Marvell 88E6161 (A2)" },
- { PORT_SWITCH_ID_6165, "Marvell 88E6165" },
- { PORT_SWITCH_ID_6165_A1, "Marvell 88E6165 (A1)" },
- { PORT_SWITCH_ID_6165_A2, "Marvell 88e6165 (A2)" },
-};
-
-static char *mv88e6123_61_65_probe(struct device *host_dev, int sw_addr)
-{
- return mv88e6xxx_lookup_name(host_dev, sw_addr, mv88e6123_61_65_table,
- ARRAY_SIZE(mv88e6123_61_65_table));
-}
-
-static int mv88e6123_61_65_setup_global(struct dsa_switch *ds)
-{
- u32 upstream_port = dsa_upstream_port(ds);
- int ret;
- u32 reg;
-
- ret = mv88e6xxx_setup_global(ds);
- if (ret)
- return ret;
-
- /* Disable the PHY polling unit (since there won't be any
- * external PHYs to poll), don't discard packets with
- * excessive collisions, and mask all interrupt sources.
- */
- REG_WRITE(REG_GLOBAL, GLOBAL_CONTROL, 0x0000);
-
- /* Configure the upstream port, and configure the upstream
- * port as the port to which ingress and egress monitor frames
- * are to be sent.
- */
- reg = upstream_port << GLOBAL_MONITOR_CONTROL_INGRESS_SHIFT |
- upstream_port << GLOBAL_MONITOR_CONTROL_EGRESS_SHIFT |
- upstream_port << GLOBAL_MONITOR_CONTROL_ARP_SHIFT;
- REG_WRITE(REG_GLOBAL, GLOBAL_MONITOR_CONTROL, reg);
-
- /* Disable remote management for now, and set the switch's
- * DSA device number.
- */
- REG_WRITE(REG_GLOBAL, GLOBAL_CONTROL_2, ds->index & 0x1f);
-
- return 0;
-}
-
-static int mv88e6123_61_65_setup(struct dsa_switch *ds)
-{
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
- int ret;
-
- ret = mv88e6xxx_setup_common(ds);
- if (ret < 0)
- return ret;
-
- switch (ps->id) {
- case PORT_SWITCH_ID_6123:
- ps->num_ports = 3;
- break;
- case PORT_SWITCH_ID_6161:
- case PORT_SWITCH_ID_6165:
- ps->num_ports = 6;
- break;
- default:
- return -ENODEV;
- }
-
- ret = mv88e6xxx_switch_reset(ds, false);
- if (ret < 0)
- return ret;
-
- ret = mv88e6123_61_65_setup_global(ds);
- if (ret < 0)
- return ret;
-
- return mv88e6xxx_setup_ports(ds);
-}
-
-struct dsa_switch_driver mv88e6123_61_65_switch_driver = {
- .tag_protocol = DSA_TAG_PROTO_EDSA,
- .priv_size = sizeof(struct mv88e6xxx_priv_state),
- .probe = mv88e6123_61_65_probe,
- .setup = mv88e6123_61_65_setup,
- .set_addr = mv88e6xxx_set_addr_indirect,
- .phy_read = mv88e6xxx_phy_read,
- .phy_write = mv88e6xxx_phy_write,
- .get_strings = mv88e6xxx_get_strings,
- .get_ethtool_stats = mv88e6xxx_get_ethtool_stats,
- .get_sset_count = mv88e6xxx_get_sset_count,
- .adjust_link = mv88e6xxx_adjust_link,
-#ifdef CONFIG_NET_DSA_HWMON
- .get_temp = mv88e6xxx_get_temp,
-#endif
- .get_regs_len = mv88e6xxx_get_regs_len,
- .get_regs = mv88e6xxx_get_regs,
-};
-
-MODULE_ALIAS("platform:mv88e6123");
-MODULE_ALIAS("platform:mv88e6161");
-MODULE_ALIAS("platform:mv88e6165");
diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index cf34681af4f6..493ae8b5a48e 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -2653,8 +2653,8 @@ static int __init mv88e6xxx_init(void)
#if IS_ENABLED(CONFIG_NET_DSA_MV88E6131)
register_switch_driver(&mv88e6131_switch_driver);
#endif
-#if IS_ENABLED(CONFIG_NET_DSA_MV88E6123_61_65)
- register_switch_driver(&mv88e6123_61_65_switch_driver);
+#if IS_ENABLED(CONFIG_NET_DSA_MV88E6123)
+ register_switch_driver(&mv88e6123_switch_driver);
#endif
#if IS_ENABLED(CONFIG_NET_DSA_MV88E6352)
register_switch_driver(&mv88e6352_switch_driver);
diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h
index ca08f913d302..931a09b92b9e 100644
--- a/drivers/net/dsa/mv88e6xxx.h
+++ b/drivers/net/dsa/mv88e6xxx.h
@@ -506,7 +506,7 @@ int mv88e6xxx_phy_page_write(struct dsa_switch *ds, int port, int page,
int reg, int val);
extern struct dsa_switch_driver mv88e6131_switch_driver;
-extern struct dsa_switch_driver mv88e6123_61_65_switch_driver;
+extern struct dsa_switch_driver mv88e6123_switch_driver;
extern struct dsa_switch_driver mv88e6352_switch_driver;
extern struct dsa_switch_driver mv88e6171_switch_driver;
--
2.7.0
^ permalink raw reply related [flat|nested] 47+ messages in thread
* [PATCH RFC v2 03/32] dsa: Make setup and finish more symmetrical
2016-02-28 16:41 [PATCH RFC v2 00/32] Make DSA switches linux devices Andrew Lunn
2016-02-28 16:41 ` [PATCH RFC v2 01/32] net: dsa: Move platform data allocation for OF Andrew Lunn
2016-02-28 16:41 ` [PATCH RFC v2 02/32] dsa: Rename mv88e6123_61_65 to mv88e6123 to be consistent Andrew Lunn
@ 2016-02-28 16:41 ` Andrew Lunn
2016-03-11 23:54 ` Florian Fainelli
2016-02-28 16:41 ` [PATCH RFC v2 04/32] net: dsa: Pass the dsa device to the switch drivers Andrew Lunn
` (29 subsequent siblings)
32 siblings, 1 reply; 47+ messages in thread
From: Andrew Lunn @ 2016-02-28 16:41 UTC (permalink / raw)
To: Florian Fainelli, Vivien Didelot, netdev; +Cc: Andrew Lunn
Rename and reposition dsa_switch_destroy() to dsa_switch_finish_one()
to make it clear it is the opposite of dsa_switch_setup_one().
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
---
net/dsa/dsa.c | 90 +++++++++++++++++++++++++++++------------------------------
1 file changed, 45 insertions(+), 45 deletions(-)
diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c
index be68c00b8cfd..6e9176545dda 100644
--- a/net/dsa/dsa.c
+++ b/net/dsa/dsa.c
@@ -374,6 +374,50 @@ out:
return ret;
}
+static void dsa_switch_finish_one(struct dsa_switch *ds)
+{
+ struct device_node *port_dn;
+ struct phy_device *phydev;
+ struct dsa_chip_data *cd = ds->pd;
+ int port;
+
+#ifdef CONFIG_NET_DSA_HWMON
+ if (ds->hwmon_dev)
+ hwmon_device_unregister(ds->hwmon_dev);
+#endif
+
+ /* Disable configuration of the CPU and DSA ports */
+ for (port = 0; port < DSA_MAX_PORTS; port++) {
+ if (!(dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port)))
+ continue;
+
+ port_dn = cd->port_dn[port];
+ if (of_phy_is_fixed_link(port_dn)) {
+ phydev = of_phy_find_device(port_dn);
+ if (phydev) {
+ int addr = phydev->mdio.addr;
+
+ phy_device_free(phydev);
+ of_node_put(port_dn);
+ fixed_phy_del(addr);
+ }
+ }
+ }
+
+ /* Destroy network devices for physical switch ports. */
+ for (port = 0; port < DSA_MAX_PORTS; port++) {
+ if (!(ds->phys_port_mask & (1 << port)))
+ continue;
+
+ if (!ds->ports[port])
+ continue;
+
+ dsa_slave_destroy(ds->ports[port]);
+ }
+
+ mdiobus_unregister(ds->slave_mii_bus);
+}
+
static struct dsa_switch *
dsa_switch_setup(struct dsa_switch_tree *dst, int index,
struct device *parent, struct device *host_dev)
@@ -418,50 +462,6 @@ dsa_switch_setup(struct dsa_switch_tree *dst, int index,
return ds;
}
-static void dsa_switch_destroy(struct dsa_switch *ds)
-{
- struct device_node *port_dn;
- struct phy_device *phydev;
- struct dsa_chip_data *cd = ds->pd;
- int port;
-
-#ifdef CONFIG_NET_DSA_HWMON
- if (ds->hwmon_dev)
- hwmon_device_unregister(ds->hwmon_dev);
-#endif
-
- /* Disable configuration of the CPU and DSA ports */
- for (port = 0; port < DSA_MAX_PORTS; port++) {
- if (!(dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port)))
- continue;
-
- port_dn = cd->port_dn[port];
- if (of_phy_is_fixed_link(port_dn)) {
- phydev = of_phy_find_device(port_dn);
- if (phydev) {
- int addr = phydev->mdio.addr;
-
- phy_device_free(phydev);
- of_node_put(port_dn);
- fixed_phy_del(addr);
- }
- }
- }
-
- /* Destroy network devices for physical switch ports. */
- for (port = 0; port < DSA_MAX_PORTS; port++) {
- if (!(ds->phys_port_mask & (1 << port)))
- continue;
-
- if (!ds->ports[port])
- continue;
-
- dsa_slave_destroy(ds->ports[port]);
- }
-
- mdiobus_unregister(ds->slave_mii_bus);
-}
-
#ifdef CONFIG_PM_SLEEP
static int dsa_switch_suspend(struct dsa_switch *ds)
{
@@ -928,7 +928,7 @@ static void dsa_remove_dst(struct dsa_switch_tree *dst)
struct dsa_switch *ds = dst->ds[i];
if (ds)
- dsa_switch_destroy(ds);
+ dsa_switch_finish_one(ds);
}
dev_put(dst->master_netdev);
--
2.7.0
^ permalink raw reply related [flat|nested] 47+ messages in thread
* [PATCH RFC v2 04/32] net: dsa: Pass the dsa device to the switch drivers
2016-02-28 16:41 [PATCH RFC v2 00/32] Make DSA switches linux devices Andrew Lunn
` (2 preceding siblings ...)
2016-02-28 16:41 ` [PATCH RFC v2 03/32] dsa: Make setup and finish more symmetrical Andrew Lunn
@ 2016-02-28 16:41 ` Andrew Lunn
2016-02-28 16:41 ` [PATCH RFC v2 05/32] net: dsa: Have the switch driver allocate there own private memory Andrew Lunn
` (28 subsequent siblings)
32 siblings, 0 replies; 47+ messages in thread
From: Andrew Lunn @ 2016-02-28 16:41 UTC (permalink / raw)
To: Florian Fainelli, Vivien Didelot, netdev; +Cc: Andrew Lunn
By passing a device structure to the switch devices, it allows them
to use devm_* methods for resource management.
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
Acked-by: Florian Fainelli <f.fainelli@gmail.com>
---
drivers/net/dsa/bcm_sf2.c | 2 +-
drivers/net/dsa/mv88e6060.c | 2 +-
drivers/net/dsa/mv88e6123.c | 2 +-
drivers/net/dsa/mv88e6131.c | 2 +-
drivers/net/dsa/mv88e6171.c | 2 +-
drivers/net/dsa/mv88e6352.c | 2 +-
include/net/dsa.h | 2 +-
net/dsa/dsa.c | 2 +-
8 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c
index 6f946fedbb77..6925b3c13895 100644
--- a/drivers/net/dsa/bcm_sf2.c
+++ b/drivers/net/dsa/bcm_sf2.c
@@ -926,7 +926,7 @@ static void bcm_sf2_identify_ports(struct bcm_sf2_priv *priv,
}
}
-static int bcm_sf2_sw_setup(struct dsa_switch *ds)
+static int bcm_sf2_sw_setup(struct dsa_switch *ds, struct device *dev)
{
const char *reg_names[BCM_SF2_REGS_NUM] = BCM_SF2_REGS_NAME;
struct bcm_sf2_priv *priv = ds_to_priv(ds);
diff --git a/drivers/net/dsa/mv88e6060.c b/drivers/net/dsa/mv88e6060.c
index 0527f485c3dc..34bc374882c7 100644
--- a/drivers/net/dsa/mv88e6060.c
+++ b/drivers/net/dsa/mv88e6060.c
@@ -172,7 +172,7 @@ static int mv88e6060_setup_port(struct dsa_switch *ds, int p)
return 0;
}
-static int mv88e6060_setup(struct dsa_switch *ds)
+static int mv88e6060_setup(struct dsa_switch *ds, struct device *dev)
{
int i;
int ret;
diff --git a/drivers/net/dsa/mv88e6123.c b/drivers/net/dsa/mv88e6123.c
index 69a6f79dcb10..fab428bb7545 100644
--- a/drivers/net/dsa/mv88e6123.c
+++ b/drivers/net/dsa/mv88e6123.c
@@ -68,7 +68,7 @@ static int mv88e6123_setup_global(struct dsa_switch *ds)
return 0;
}
-static int mv88e6123_setup(struct dsa_switch *ds)
+static int mv88e6123_setup(struct dsa_switch *ds, struct device *dev)
{
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
int ret;
diff --git a/drivers/net/dsa/mv88e6131.c b/drivers/net/dsa/mv88e6131.c
index a92ca651c399..d82cf3d38455 100644
--- a/drivers/net/dsa/mv88e6131.c
+++ b/drivers/net/dsa/mv88e6131.c
@@ -86,7 +86,7 @@ static int mv88e6131_setup_global(struct dsa_switch *ds)
return 0;
}
-static int mv88e6131_setup(struct dsa_switch *ds)
+static int mv88e6131_setup(struct dsa_switch *ds, struct device *dev)
{
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
int ret;
diff --git a/drivers/net/dsa/mv88e6171.c b/drivers/net/dsa/mv88e6171.c
index 6e18213b9c04..9635f14ec1fb 100644
--- a/drivers/net/dsa/mv88e6171.c
+++ b/drivers/net/dsa/mv88e6171.c
@@ -64,7 +64,7 @@ static int mv88e6171_setup_global(struct dsa_switch *ds)
return 0;
}
-static int mv88e6171_setup(struct dsa_switch *ds)
+static int mv88e6171_setup(struct dsa_switch *ds, struct device *dev)
{
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
int ret;
diff --git a/drivers/net/dsa/mv88e6352.c b/drivers/net/dsa/mv88e6352.c
index cc6c54553418..c2c4153e3423 100644
--- a/drivers/net/dsa/mv88e6352.c
+++ b/drivers/net/dsa/mv88e6352.c
@@ -75,7 +75,7 @@ static int mv88e6352_setup_global(struct dsa_switch *ds)
return 0;
}
-static int mv88e6352_setup(struct dsa_switch *ds)
+static int mv88e6352_setup(struct dsa_switch *ds, struct device *dev)
{
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
int ret;
diff --git a/include/net/dsa.h b/include/net/dsa.h
index 26a0e86e611e..f5b4f1bcfdf3 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -213,7 +213,7 @@ struct dsa_switch_driver {
* Probing and setup.
*/
char *(*probe)(struct device *host_dev, int sw_addr);
- int (*setup)(struct dsa_switch *ds);
+ int (*setup)(struct dsa_switch *ds, struct device *dev);
int (*set_addr)(struct dsa_switch *ds, u8 *addr);
u32 (*get_phy_flags)(struct dsa_switch *ds, int port);
diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c
index 6e9176545dda..d6ea1f1a1a34 100644
--- a/net/dsa/dsa.c
+++ b/net/dsa/dsa.c
@@ -300,7 +300,7 @@ static int dsa_switch_setup_one(struct dsa_switch *ds, struct device *parent)
/*
* Do basic register setup.
*/
- ret = drv->setup(ds);
+ ret = drv->setup(ds, parent);
if (ret < 0)
goto out;
--
2.7.0
^ permalink raw reply related [flat|nested] 47+ messages in thread
* [PATCH RFC v2 05/32] net: dsa: Have the switch driver allocate there own private memory
2016-02-28 16:41 [PATCH RFC v2 00/32] Make DSA switches linux devices Andrew Lunn
` (3 preceding siblings ...)
2016-02-28 16:41 ` [PATCH RFC v2 04/32] net: dsa: Pass the dsa device to the switch drivers Andrew Lunn
@ 2016-02-28 16:41 ` Andrew Lunn
2016-02-28 16:41 ` [PATCH RFC v2 06/32] net: dsa: Remove allocation of driver " Andrew Lunn
` (27 subsequent siblings)
32 siblings, 0 replies; 47+ messages in thread
From: Andrew Lunn @ 2016-02-28 16:41 UTC (permalink / raw)
To: Florian Fainelli, Vivien Didelot, netdev; +Cc: Andrew Lunn
Now the switch devices have a dev pointer, make use if it for allocating
the drivers private data structures using a devm_kzalloc().
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
Acked-by: Florian Fainelli <f.fainelli@gmail.com>
---
v2: Added missing assignment of priv to ds->priv.
---
drivers/net/dsa/bcm_sf2.c | 9 +++++++--
drivers/net/dsa/mv88e6123.c | 6 +++---
drivers/net/dsa/mv88e6131.c | 6 +++---
drivers/net/dsa/mv88e6171.c | 6 +++---
drivers/net/dsa/mv88e6352.c | 6 +++---
drivers/net/dsa/mv88e6xxx.c | 13 ++++++++++---
drivers/net/dsa/mv88e6xxx.h | 5 ++++-
include/net/dsa.h | 8 +++++++-
8 files changed, 40 insertions(+), 19 deletions(-)
diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c
index 6925b3c13895..fbb17e042e7b 100644
--- a/drivers/net/dsa/bcm_sf2.c
+++ b/drivers/net/dsa/bcm_sf2.c
@@ -929,7 +929,7 @@ static void bcm_sf2_identify_ports(struct bcm_sf2_priv *priv,
static int bcm_sf2_sw_setup(struct dsa_switch *ds, struct device *dev)
{
const char *reg_names[BCM_SF2_REGS_NUM] = BCM_SF2_REGS_NAME;
- struct bcm_sf2_priv *priv = ds_to_priv(ds);
+ struct bcm_sf2_priv *priv;
struct device_node *dn;
void __iomem **base;
unsigned int port;
@@ -937,6 +937,12 @@ static int bcm_sf2_sw_setup(struct dsa_switch *ds, struct device *dev)
u32 reg, rev;
int ret;
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ ds->priv = priv;
+
spin_lock_init(&priv->indir_lock);
mutex_init(&priv->stats_mutex);
@@ -1365,7 +1371,6 @@ static int bcm_sf2_sw_set_wol(struct dsa_switch *ds, int port,
static struct dsa_switch_driver bcm_sf2_switch_driver = {
.tag_protocol = DSA_TAG_PROTO_BRCM,
- .priv_size = sizeof(struct bcm_sf2_priv),
.probe = bcm_sf2_sw_probe,
.setup = bcm_sf2_sw_setup,
.set_addr = bcm_sf2_sw_set_addr,
diff --git a/drivers/net/dsa/mv88e6123.c b/drivers/net/dsa/mv88e6123.c
index fab428bb7545..9d39f108793b 100644
--- a/drivers/net/dsa/mv88e6123.c
+++ b/drivers/net/dsa/mv88e6123.c
@@ -70,13 +70,14 @@ static int mv88e6123_setup_global(struct dsa_switch *ds)
static int mv88e6123_setup(struct dsa_switch *ds, struct device *dev)
{
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+ struct mv88e6xxx_priv_state *ps;
int ret;
- ret = mv88e6xxx_setup_common(ds);
+ ret = mv88e6xxx_setup_common(ds, dev);
if (ret < 0)
return ret;
+ ps = ds_to_priv(ds);
switch (ps->id) {
case PORT_SWITCH_ID_6123:
ps->num_ports = 3;
@@ -102,7 +103,6 @@ static int mv88e6123_setup(struct dsa_switch *ds, struct device *dev)
struct dsa_switch_driver mv88e6123_switch_driver = {
.tag_protocol = DSA_TAG_PROTO_EDSA,
- .priv_size = sizeof(struct mv88e6xxx_priv_state),
.probe = mv88e6123_probe,
.setup = mv88e6123_setup,
.set_addr = mv88e6xxx_set_addr_indirect,
diff --git a/drivers/net/dsa/mv88e6131.c b/drivers/net/dsa/mv88e6131.c
index d82cf3d38455..3103b4953af4 100644
--- a/drivers/net/dsa/mv88e6131.c
+++ b/drivers/net/dsa/mv88e6131.c
@@ -88,13 +88,14 @@ static int mv88e6131_setup_global(struct dsa_switch *ds)
static int mv88e6131_setup(struct dsa_switch *ds, struct device *dev)
{
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+ struct mv88e6xxx_priv_state *ps;
int ret;
- ret = mv88e6xxx_setup_common(ds);
+ ret = mv88e6xxx_setup_common(ds, dev);
if (ret < 0)
return ret;
+ ps = ds_to_priv(ds);
mv88e6xxx_ppu_state_init(ds);
switch (ps->id) {
@@ -159,7 +160,6 @@ mv88e6131_phy_write(struct dsa_switch *ds,
struct dsa_switch_driver mv88e6131_switch_driver = {
.tag_protocol = DSA_TAG_PROTO_DSA,
- .priv_size = sizeof(struct mv88e6xxx_priv_state),
.probe = mv88e6131_probe,
.setup = mv88e6131_setup,
.set_addr = mv88e6xxx_set_addr_direct,
diff --git a/drivers/net/dsa/mv88e6171.c b/drivers/net/dsa/mv88e6171.c
index 9635f14ec1fb..29a77366afc6 100644
--- a/drivers/net/dsa/mv88e6171.c
+++ b/drivers/net/dsa/mv88e6171.c
@@ -66,13 +66,14 @@ static int mv88e6171_setup_global(struct dsa_switch *ds)
static int mv88e6171_setup(struct dsa_switch *ds, struct device *dev)
{
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+ struct mv88e6xxx_priv_state *ps;
int ret;
- ret = mv88e6xxx_setup_common(ds);
+ ret = mv88e6xxx_setup_common(ds, dev);
if (ret < 0)
return ret;
+ ps = ds_to_priv(ds);
ps->num_ports = 7;
ret = mv88e6xxx_switch_reset(ds, true);
@@ -88,7 +89,6 @@ static int mv88e6171_setup(struct dsa_switch *ds, struct device *dev)
struct dsa_switch_driver mv88e6171_switch_driver = {
.tag_protocol = DSA_TAG_PROTO_EDSA,
- .priv_size = sizeof(struct mv88e6xxx_priv_state),
.probe = mv88e6171_probe,
.setup = mv88e6171_setup,
.set_addr = mv88e6xxx_set_addr_indirect,
diff --git a/drivers/net/dsa/mv88e6352.c b/drivers/net/dsa/mv88e6352.c
index c2c4153e3423..eb57a379b9cc 100644
--- a/drivers/net/dsa/mv88e6352.c
+++ b/drivers/net/dsa/mv88e6352.c
@@ -77,13 +77,14 @@ static int mv88e6352_setup_global(struct dsa_switch *ds)
static int mv88e6352_setup(struct dsa_switch *ds, struct device *dev)
{
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+ struct mv88e6xxx_priv_state *ps;
int ret;
- ret = mv88e6xxx_setup_common(ds);
+ ret = mv88e6xxx_setup_common(ds, dev);
if (ret < 0)
return ret;
+ ps = ds_to_priv(ds);
ps->num_ports = 7;
mutex_init(&ps->eeprom_mutex);
@@ -301,7 +302,6 @@ static int mv88e6352_set_eeprom(struct dsa_switch *ds,
struct dsa_switch_driver mv88e6352_switch_driver = {
.tag_protocol = DSA_TAG_PROTO_EDSA,
- .priv_size = sizeof(struct mv88e6xxx_priv_state),
.probe = mv88e6352_probe,
.setup = mv88e6352_setup,
.set_addr = mv88e6xxx_set_addr_indirect,
diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index 493ae8b5a48e..c2d26168fdf8 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -281,7 +281,7 @@ static void mv88e6xxx_ppu_reenable_work(struct work_struct *ugly)
ps = container_of(ugly, struct mv88e6xxx_priv_state, ppu_work);
if (mutex_trylock(&ps->ppu_mutex)) {
- struct dsa_switch *ds = ((struct dsa_switch *)ps) - 1;
+ struct dsa_switch *ds = ps->ds;
if (mv88e6xxx_ppu_enable(ds) == 0)
ps->ppu_disabled = 0;
@@ -2200,9 +2200,16 @@ int mv88e6xxx_setup_ports(struct dsa_switch *ds)
return 0;
}
-int mv88e6xxx_setup_common(struct dsa_switch *ds)
+int mv88e6xxx_setup_common(struct dsa_switch *ds, struct device *dev)
{
- struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+ struct mv88e6xxx_priv_state *ps;
+
+ ps = devm_kzalloc(dev, sizeof(*ps), GFP_KERNEL);
+ if (!ps)
+ return -ENOMEM;
+
+ ds->priv = ps;
+ ps->ds = ds;
mutex_init(&ps->smi_mutex);
diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h
index 931a09b92b9e..8a13162353cd 100644
--- a/drivers/net/dsa/mv88e6xxx.h
+++ b/drivers/net/dsa/mv88e6xxx.h
@@ -380,6 +380,9 @@ struct mv88e6xxx_vtu_stu_entry {
};
struct mv88e6xxx_priv_state {
+ /* The dsa_switch this private structure is related to */
+ struct dsa_switch *ds;
+
/* When using multi-chip addressing, this mutex protects
* access to the indirect access registers. (In single-chip
* mode, this mutex is effectively useless.)
@@ -439,7 +442,7 @@ char *mv88e6xxx_lookup_name(struct device *host_dev, int sw_addr,
const struct mv88e6xxx_switch_id *table,
unsigned int num);
int mv88e6xxx_setup_ports(struct dsa_switch *ds);
-int mv88e6xxx_setup_common(struct dsa_switch *ds);
+int mv88e6xxx_setup_common(struct dsa_switch *ds, struct device *dev);
int mv88e6xxx_setup_global(struct dsa_switch *ds);
int mv88e6xxx_reg_read(struct dsa_switch *ds, int addr, int reg);
int mv88e6xxx_reg_write(struct dsa_switch *ds, int addr, int reg, u16 val);
diff --git a/include/net/dsa.h b/include/net/dsa.h
index f5b4f1bcfdf3..05067b030962 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -130,6 +130,12 @@ struct dsa_switch {
int index;
/*
+ * Give the switch driver somewhere to hang its private data
+ * structure.
+ */
+ void *priv;
+
+ /*
* Tagging protocol understood by this switch
*/
enum dsa_tag_protocol tag_protocol;
@@ -340,7 +346,7 @@ 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)
--
2.7.0
^ permalink raw reply related [flat|nested] 47+ messages in thread
* [PATCH RFC v2 06/32] net: dsa: Remove allocation of driver private memory
2016-02-28 16:41 [PATCH RFC v2 00/32] Make DSA switches linux devices Andrew Lunn
` (4 preceding siblings ...)
2016-02-28 16:41 ` [PATCH RFC v2 05/32] net: dsa: Have the switch driver allocate there own private memory Andrew Lunn
@ 2016-02-28 16:41 ` Andrew Lunn
2016-02-28 16:41 ` [PATCH RFC v2 07/32] net: dsa: Keep the mii bus and address in the private structure Andrew Lunn
` (26 subsequent siblings)
32 siblings, 0 replies; 47+ messages in thread
From: Andrew Lunn @ 2016-02-28 16:41 UTC (permalink / raw)
To: Florian Fainelli, Vivien Didelot, netdev; +Cc: Andrew Lunn
The drivers now allocate their own memory for private usage. Remove
the allocation from the core code.
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
Acked-by: Florian Fainelli <f.fainelli@gmail.com>
---
include/net/dsa.h | 1 -
net/dsa/dsa.c | 2 +-
2 files changed, 1 insertion(+), 2 deletions(-)
diff --git a/include/net/dsa.h b/include/net/dsa.h
index 05067b030962..f6b8001a500f 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -213,7 +213,6 @@ struct dsa_switch_driver {
struct list_head list;
enum dsa_tag_protocol tag_protocol;
- int priv_size;
/*
* Probing and setup.
diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c
index d6ea1f1a1a34..6c9d1d812873 100644
--- a/net/dsa/dsa.c
+++ b/net/dsa/dsa.c
@@ -444,7 +444,7 @@ dsa_switch_setup(struct dsa_switch_tree *dst, int index,
/*
* Allocate and initialise switch state.
*/
- ds = devm_kzalloc(parent, sizeof(*ds) + drv->priv_size, GFP_KERNEL);
+ ds = devm_kzalloc(parent, sizeof(*ds), GFP_KERNEL);
if (ds == NULL)
return ERR_PTR(-ENOMEM);
--
2.7.0
^ permalink raw reply related [flat|nested] 47+ messages in thread
* [PATCH RFC v2 07/32] net: dsa: Keep the mii bus and address in the private structure
2016-02-28 16:41 [PATCH RFC v2 00/32] Make DSA switches linux devices Andrew Lunn
` (5 preceding siblings ...)
2016-02-28 16:41 ` [PATCH RFC v2 06/32] net: dsa: Remove allocation of driver " Andrew Lunn
@ 2016-02-28 16:41 ` Andrew Lunn
2016-02-28 16:41 ` [PATCH RFC v2 08/32] net: dsa: dsa.c: Refactor to increase symmetry Andrew Lunn
` (25 subsequent siblings)
32 siblings, 0 replies; 47+ messages in thread
From: Andrew Lunn @ 2016-02-28 16:41 UTC (permalink / raw)
To: Florian Fainelli, Vivien Didelot, netdev; +Cc: Andrew Lunn
Rather than looking up the mii bus and address every time, do it once
and setup, and keep it in the private structure.
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
Acked-by: Florian Fainelli <f.fainelli@gmail.com>
---
v2: Add check for valid mii_bus.
---
drivers/net/dsa/mv88e6060.c | 27 +++++++++++++++++----------
drivers/net/dsa/mv88e6060.h | 11 +++++++++++
drivers/net/dsa/mv88e6xxx.c | 19 +++++++++----------
drivers/net/dsa/mv88e6xxx.h | 6 ++++++
4 files changed, 43 insertions(+), 20 deletions(-)
diff --git a/drivers/net/dsa/mv88e6060.c b/drivers/net/dsa/mv88e6060.c
index 34bc374882c7..faf9834fe1cc 100644
--- a/drivers/net/dsa/mv88e6060.c
+++ b/drivers/net/dsa/mv88e6060.c
@@ -19,12 +19,9 @@
static int reg_read(struct dsa_switch *ds, int addr, int reg)
{
- struct mii_bus *bus = dsa_host_dev_to_mii_bus(ds->master_dev);
+ struct mv88e6060_priv *priv = ds_to_priv(ds);
- if (bus == NULL)
- return -EINVAL;
-
- return mdiobus_read_nested(bus, ds->pd->sw_addr + addr, reg);
+ return mdiobus_read_nested(priv->bus, priv->sw_addr + addr, reg);
}
#define REG_READ(addr, reg) \
@@ -40,12 +37,9 @@ static int reg_read(struct dsa_switch *ds, int addr, int reg)
static int reg_write(struct dsa_switch *ds, int addr, int reg, u16 val)
{
- struct mii_bus *bus = dsa_host_dev_to_mii_bus(ds->master_dev);
-
- if (bus == NULL)
- return -EINVAL;
+ struct mv88e6060_priv *priv = ds_to_priv(ds);
- return mdiobus_write_nested(bus, ds->pd->sw_addr + addr, reg, val);
+ return mdiobus_write_nested(priv->bus, priv->sw_addr + addr, reg, val);
}
#define REG_WRITE(addr, reg, val) \
@@ -176,6 +170,19 @@ static int mv88e6060_setup(struct dsa_switch *ds, struct device *dev)
{
int i;
int ret;
+ struct mv88e6060_priv *priv;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ ds->priv = priv;
+
+ priv->bus = dsa_host_dev_to_mii_bus(ds->master_dev);
+ if (!priv->bus)
+ return -ENODEV;
+
+ priv->sw_addr = ds->pd->sw_addr;
ret = mv88e6060_switch_reset(ds);
if (ret < 0)
diff --git a/drivers/net/dsa/mv88e6060.h b/drivers/net/dsa/mv88e6060.h
index cc9b2ed4aff4..10249bd16292 100644
--- a/drivers/net/dsa/mv88e6060.h
+++ b/drivers/net/dsa/mv88e6060.h
@@ -108,4 +108,15 @@
#define GLOBAL_ATU_MAC_23 0x0e
#define GLOBAL_ATU_MAC_45 0x0f
+struct mv88e6060_priv {
+ /* MDIO bus and address on bus to use. When in single chip
+ * mode, address is 0, and the switch uses multiple addresses
+ * on the bus. When in multi-chip mode, the switch uses a
+ * single address which contains two registers used for
+ * indirect access to more registers.
+ */
+ struct mii_bus *bus;
+ int sw_addr;
+};
+
#endif
diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index c2d26168fdf8..2e945f325db1 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -94,15 +94,12 @@ static int __mv88e6xxx_reg_read(struct mii_bus *bus, int sw_addr, int addr,
static int _mv88e6xxx_reg_read(struct dsa_switch *ds, int addr, int reg)
{
- struct mii_bus *bus = dsa_host_dev_to_mii_bus(ds->master_dev);
+ struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
int ret;
assert_smi_lock(ds);
- if (bus == NULL)
- return -EINVAL;
-
- ret = __mv88e6xxx_reg_read(bus, ds->pd->sw_addr, addr, reg);
+ ret = __mv88e6xxx_reg_read(ps->bus, ps->sw_addr, addr, reg);
if (ret < 0)
return ret;
@@ -159,17 +156,14 @@ static int __mv88e6xxx_reg_write(struct mii_bus *bus, int sw_addr, int addr,
static int _mv88e6xxx_reg_write(struct dsa_switch *ds, int addr, int reg,
u16 val)
{
- struct mii_bus *bus = dsa_host_dev_to_mii_bus(ds->master_dev);
+ struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
assert_smi_lock(ds);
- if (bus == NULL)
- return -EINVAL;
-
dev_dbg(ds->master_dev, "-> addr: 0x%.2x reg: 0x%.2x val: 0x%.4x\n",
addr, reg, val);
- return __mv88e6xxx_reg_write(bus, ds->pd->sw_addr, addr, reg, val);
+ return __mv88e6xxx_reg_write(ps->bus, ps->sw_addr, addr, reg, val);
}
int mv88e6xxx_reg_write(struct dsa_switch *ds, int addr, int reg, u16 val)
@@ -2210,6 +2204,11 @@ int mv88e6xxx_setup_common(struct dsa_switch *ds, struct device *dev)
ds->priv = ps;
ps->ds = ds;
+ ps->bus = dsa_host_dev_to_mii_bus(ds->master_dev);
+ if (!ps->bus)
+ return -ENODEV;
+
+ ps->sw_addr = ds->pd->sw_addr;
mutex_init(&ps->smi_mutex);
diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h
index 8a13162353cd..53f2fc82069b 100644
--- a/drivers/net/dsa/mv88e6xxx.h
+++ b/drivers/net/dsa/mv88e6xxx.h
@@ -389,6 +389,12 @@ struct mv88e6xxx_priv_state {
*/
struct mutex smi_mutex;
+ /* The MII bus and the address on the bus that is used to
+ * communication with the switch
+ */
+ struct mii_bus *bus;
+ int sw_addr;
+
#ifdef CONFIG_NET_DSA_MV88E6XXX_NEED_PPU
/* Handles automatic disabling and re-enabling of the PHY
* polling unit.
--
2.7.0
^ permalink raw reply related [flat|nested] 47+ messages in thread
* [PATCH RFC v2 08/32] net: dsa: dsa.c: Refactor to increase symmetry
2016-02-28 16:41 [PATCH RFC v2 00/32] Make DSA switches linux devices Andrew Lunn
` (6 preceding siblings ...)
2016-02-28 16:41 ` [PATCH RFC v2 07/32] net: dsa: Keep the mii bus and address in the private structure Andrew Lunn
@ 2016-02-28 16:41 ` Andrew Lunn
2016-03-11 23:54 ` Florian Fainelli
2016-02-28 16:41 ` [PATCH RFC v2 09/32] driver: component: Add support for empty match table Andrew Lunn
` (24 subsequent siblings)
32 siblings, 1 reply; 47+ messages in thread
From: Andrew Lunn @ 2016-02-28 16:41 UTC (permalink / raw)
To: Florian Fainelli, Vivien Didelot, netdev; +Cc: Andrew Lunn
Create a dsa_switch_finish() which does the opposite of dsa_switch_setup().
Create a dsa_finish_dst() which does the opposite of dsa_setup_dst().
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
---
net/dsa/dsa.c | 44 +++++++++++++++++++++++++++++---------------
1 file changed, 29 insertions(+), 15 deletions(-)
diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c
index 6c9d1d812873..5062ca91852d 100644
--- a/net/dsa/dsa.c
+++ b/net/dsa/dsa.c
@@ -462,6 +462,13 @@ dsa_switch_setup(struct dsa_switch_tree *dst, int index,
return ds;
}
+static void dsa_switch_finish(struct dsa_switch *ds, struct device *parent)
+{
+ dsa_switch_finish_one(ds);
+
+ devm_kfree(parent, ds);
+}
+
#ifdef CONFIG_PM_SLEEP
static int dsa_switch_suspend(struct dsa_switch *ds)
{
@@ -855,6 +862,26 @@ static int dsa_setup_dst(struct dsa_switch_tree *dst, struct net_device *dev,
return 0;
}
+static void dsa_finish_dst(struct dsa_switch_tree *dst, struct device *parent,
+ struct dsa_platform_data *pd)
+{
+ struct net_device *dev = dst->master_netdev;
+ int i;
+
+ dev->dsa_ptr = NULL;
+ /* Ensure no more packets get sent to the tag receive
+ * function.
+ */
+ wmb();
+
+ for (i = 0; i < pd->nr_chips; i++) {
+ struct dsa_switch *ds = dst->ds[i];
+
+ dsa_switch_finish(ds, parent);
+ dst->ds[i] = NULL;
+ }
+}
+
static int dsa_probe(struct platform_device *pdev)
{
struct dsa_platform_data *pd = pdev->dev.platform_data;
@@ -920,27 +947,14 @@ out:
return ret;
}
-static void dsa_remove_dst(struct dsa_switch_tree *dst)
-{
- int i;
-
- for (i = 0; i < dst->pd->nr_chips; i++) {
- struct dsa_switch *ds = dst->ds[i];
-
- if (ds)
- dsa_switch_finish_one(ds);
- }
-
- dev_put(dst->master_netdev);
-}
-
static int dsa_remove(struct platform_device *pdev)
{
struct dsa_switch_tree *dst = platform_get_drvdata(pdev);
struct dsa_platform_data *pd = pdev->dev.platform_data;
- dsa_remove_dst(dst);
+ dsa_finish_dst(dst, &pdev->dev, pd);
dsa_of_remove(&pdev->dev, pd);
+ dev_put(dst->master_netdev);
return 0;
}
--
2.7.0
^ permalink raw reply related [flat|nested] 47+ messages in thread
* [PATCH RFC v2 09/32] driver: component: Add support for empty match table
2016-02-28 16:41 [PATCH RFC v2 00/32] Make DSA switches linux devices Andrew Lunn
` (7 preceding siblings ...)
2016-02-28 16:41 ` [PATCH RFC v2 08/32] net: dsa: dsa.c: Refactor to increase symmetry Andrew Lunn
@ 2016-02-28 16:41 ` Andrew Lunn
2016-02-28 16:41 ` [PATCH RFC v2 10/32] net: dsa: Add basic support for component master support Andrew Lunn
` (23 subsequent siblings)
32 siblings, 0 replies; 47+ messages in thread
From: Andrew Lunn @ 2016-02-28 16:41 UTC (permalink / raw)
To: Florian Fainelli, Vivien Didelot, netdev; +Cc: Andrew Lunn
Before calling component_master_add_with_match(), matches should be
added using component_match_add() to the opaque match. How many
matches are added typically depends on the contents of the device
tree. It is not inconceivable that the number is zero, for example the
components are optional.
This results in calling component_master_add_with_match() passing a
NULL pointer for the match structure. The component infrastructure
does not like this. So handle the case by allocating a match with zero
entries.
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
---
drivers/base/component.c | 33 ++++++++++++++++++++++++++-------
1 file changed, 26 insertions(+), 7 deletions(-)
diff --git a/drivers/base/component.c b/drivers/base/component.c
index 89f5cf68d80a..36c4cf626fa8 100644
--- a/drivers/base/component.c
+++ b/drivers/base/component.c
@@ -237,6 +237,24 @@ static int component_match_realloc(struct device *dev,
}
/*
+ * Allocate a match array.
+ *
+ */
+static struct component_match *component_match_alloc(struct device *master)
+{
+ struct component_match *match;
+
+ match = devres_alloc(devm_component_match_release,
+ sizeof(*match), GFP_KERNEL);
+ if (!match)
+ return ERR_PTR(-ENOMEM);
+
+ devres_add(master, match);
+
+ return match;
+}
+
+/*
* Add a component to be matched, with a release function.
*
* The match array is first created or extended if necessary.
@@ -252,14 +270,9 @@ void component_match_add_release(struct device *master,
return;
if (!match) {
- match = devres_alloc(devm_component_match_release,
- sizeof(*match), GFP_KERNEL);
- if (!match) {
- *matchptr = ERR_PTR(-ENOMEM);
+ match = component_match_alloc(master);
+ if (IS_ERR(match))
return;
- }
-
- devres_add(master, match);
*matchptr = match;
}
@@ -290,6 +303,12 @@ int component_master_add_with_match(struct device *dev,
struct master *master;
int ret;
+ if (!match) {
+ match = component_match_alloc(dev);
+ if (IS_ERR(match))
+ return PTR_ERR(match);
+ }
+
/* Reallocate the match array for its true size */
ret = component_match_realloc(dev, match, match->num);
if (ret)
--
2.7.0
^ permalink raw reply related [flat|nested] 47+ messages in thread
* [PATCH RFC v2 10/32] net: dsa: Add basic support for component master support
2016-02-28 16:41 [PATCH RFC v2 00/32] Make DSA switches linux devices Andrew Lunn
` (8 preceding siblings ...)
2016-02-28 16:41 ` [PATCH RFC v2 09/32] driver: component: Add support for empty match table Andrew Lunn
@ 2016-02-28 16:41 ` Andrew Lunn
2016-02-28 16:41 ` [PATCH RFC v2 11/32] net: dsa: Keep a reference to the switch device for component matching Andrew Lunn
` (22 subsequent siblings)
32 siblings, 0 replies; 47+ messages in thread
From: Andrew Lunn @ 2016-02-28 16:41 UTC (permalink / raw)
To: Florian Fainelli, Vivien Didelot, netdev; +Cc: Andrew Lunn
Start using the component framework. The DSA device will be the
master, and the switch drivers will be slaves. Add basic component
master support to the DSA framework.
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
---
net/dsa/dsa.c | 54 ++++++++++++++++++++++++++++++++++++++++--------------
1 file changed, 40 insertions(+), 14 deletions(-)
diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c
index 5062ca91852d..a139c35061a1 100644
--- a/net/dsa/dsa.c
+++ b/net/dsa/dsa.c
@@ -9,6 +9,7 @@
* (at your option) any later version.
*/
+#include <linux/component.h>
#include <linux/ctype.h>
#include <linux/device.h>
#include <linux/hwmon.h>
@@ -28,7 +29,7 @@
#include "dsa_priv.h"
char dsa_driver_version[] = "0.1";
-
+static const struct component_master_ops dsa_ops;
/* switch driver registration ***********************************************/
static DEFINE_MUTEX(dsa_switch_drivers_mutex);
@@ -820,13 +821,12 @@ static inline void dsa_of_remove(struct device *dev,
#endif
static int dsa_setup_dst(struct dsa_switch_tree *dst, struct net_device *dev,
- struct device *parent, struct dsa_platform_data *pd)
+ struct device *parent)
{
int i;
unsigned configured = 0;
+ struct dsa_platform_data *pd = dst->pd;
- dst->pd = pd;
- dst->master_netdev = dev;
dst->cpu_switch = -1;
dst->cpu_port = -1;
@@ -885,6 +885,7 @@ static void dsa_finish_dst(struct dsa_switch_tree *dst, struct device *parent,
static int dsa_probe(struct platform_device *pdev)
{
struct dsa_platform_data *pd = pdev->dev.platform_data;
+ struct component_match *match = NULL;
struct net_device *dev;
struct dsa_switch_tree *dst;
int ret;
@@ -931,15 +932,13 @@ static int dsa_probe(struct platform_device *pdev)
goto out;
}
+ dst->pd = pd;
+ dst->master_netdev = dev;
+
platform_set_drvdata(pdev, dst);
- ret = dsa_setup_dst(dst, dev, &pdev->dev, pd);
- if (ret) {
- dev_put(dev);
- goto out;
- }
- return 0;
+ return component_master_add_with_match(&pdev->dev, &dsa_ops, match);
out:
dsa_of_remove(&pdev->dev, pd);
@@ -947,22 +946,49 @@ out:
return ret;
}
-static int dsa_remove(struct platform_device *pdev)
+static int dsa_bind(struct device *dev)
{
+ struct dsa_switch_tree *dst = dev_get_drvdata(dev);
+ int ret;
+
+ ret = component_bind_all(dev, dst);
+ if (ret)
+ return ret;
+
+ return dsa_setup_dst(dst, dst->master_netdev, dev);
+}
+
+static void dsa_unbind(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
struct dsa_switch_tree *dst = platform_get_drvdata(pdev);
struct dsa_platform_data *pd = pdev->dev.platform_data;
dsa_finish_dst(dst, &pdev->dev, pd);
- dsa_of_remove(&pdev->dev, pd);
- dev_put(dst->master_netdev);
- return 0;
+ dev_put(dst->master_netdev);
}
+static const struct component_master_ops dsa_ops = {
+ .bind = dsa_bind,
+ .unbind = dsa_unbind,
+};
+
static void dsa_shutdown(struct platform_device *pdev)
{
}
+static int dsa_remove(struct platform_device *pdev)
+{
+ struct dsa_platform_data *pd = pdev->dev.platform_data;
+
+ component_master_del(&pdev->dev, &dsa_ops);
+
+ dsa_of_remove(&pdev->dev, pd);
+
+ return 0;
+}
+
static int dsa_switch_rcv(struct sk_buff *skb, struct net_device *dev,
struct packet_type *pt, struct net_device *orig_dev)
{
--
2.7.0
^ permalink raw reply related [flat|nested] 47+ messages in thread
* [PATCH RFC v2 11/32] net: dsa: Keep a reference to the switch device for component matching
2016-02-28 16:41 [PATCH RFC v2 00/32] Make DSA switches linux devices Andrew Lunn
` (9 preceding siblings ...)
2016-02-28 16:41 ` [PATCH RFC v2 10/32] net: dsa: Add basic support for component master support Andrew Lunn
@ 2016-02-28 16:41 ` Andrew Lunn
2016-02-28 16:41 ` [PATCH RFC v2 12/32] net: dsa: Add slave component matches based on a phandle to the slave Andrew Lunn
` (21 subsequent siblings)
32 siblings, 0 replies; 47+ messages in thread
From: Andrew Lunn @ 2016-02-28 16:41 UTC (permalink / raw)
To: Florian Fainelli, Vivien Didelot, netdev; +Cc: Andrew Lunn
The switch devices are component slaves. Such devices have a "switch"
property in the DSA device tree which is a phandle to the switch
device. When the slaves bind they register to DSA. So the DSA can
match the switch to the correct switch instance in the device tree,
keep a reference to the device tree node during parsing of the device
tree.
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
---
Documentation/devicetree/bindings/net/dsa/dsa.txt | 2 ++
include/net/dsa.h | 3 +++
net/dsa/dsa.c | 6 +++++-
3 files changed, 10 insertions(+), 1 deletion(-)
diff --git a/Documentation/devicetree/bindings/net/dsa/dsa.txt b/Documentation/devicetree/bindings/net/dsa/dsa.txt
index 5fdbbcdf8c4b..f99e5694a61f 100644
--- a/Documentation/devicetree/bindings/net/dsa/dsa.txt
+++ b/Documentation/devicetree/bindings/net/dsa/dsa.txt
@@ -27,6 +27,8 @@ Each of these switch child nodes should have the following required properties:
A switch child node has the following optional property:
+- switch : A phandle to a switch device.
+
- eeprom-length : Set to the length of an EEPROM connected to the
switch. Must be set if the switch can not detect
the presence and/or size of a connected EEPROM,
diff --git a/include/net/dsa.h b/include/net/dsa.h
index f6b8001a500f..ea4cfdf1b549 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -48,6 +48,9 @@ struct dsa_chip_data {
*/
struct device_node *of_node;
+ /* Device tree node pointer for the switch chip device. */
+ struct device_node *of_chip;
+
/*
* The names of the switch's ports. Use "cpu" to
* designate the switch port that the cpu is connected to,
diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c
index a139c35061a1..f2af801554ec 100644
--- a/net/dsa/dsa.c
+++ b/net/dsa/dsa.c
@@ -662,7 +662,7 @@ static void dsa_of_free_platform_data(struct dsa_platform_data *pd)
static int dsa_of_probe(struct device *dev, struct dsa_platform_data *pd)
{
struct device_node *np = dev->of_node;
- struct device_node *child, *mdio, *ethernet, *port;
+ struct device_node *child, *chip, *mdio, *ethernet, *port;
struct mii_bus *mdio_bus, *mdio_bus_switch;
struct net_device *ethernet_dev;
struct dsa_chip_data *cd;
@@ -712,6 +712,10 @@ static int dsa_of_probe(struct device *dev, struct dsa_platform_data *pd)
cd->of_node = child;
+ chip = of_parse_phandle(child, "switch", 0);
+ if (chip)
+ cd->of_chip = chip;
+
/* When assigning the host device, increment its refcount */
cd->host_dev = get_device(&mdio_bus->dev);
--
2.7.0
^ permalink raw reply related [flat|nested] 47+ messages in thread
* [PATCH RFC v2 12/32] net: dsa: Add slave component matches based on a phandle to the slave.
2016-02-28 16:41 [PATCH RFC v2 00/32] Make DSA switches linux devices Andrew Lunn
` (10 preceding siblings ...)
2016-02-28 16:41 ` [PATCH RFC v2 11/32] net: dsa: Keep a reference to the switch device for component matching Andrew Lunn
@ 2016-02-28 16:41 ` Andrew Lunn
2016-02-28 16:41 ` [PATCH RFC v2 13/32] net: dsa: Make dsa,mii-bus optional Andrew Lunn
` (20 subsequent siblings)
32 siblings, 0 replies; 47+ messages in thread
From: Andrew Lunn @ 2016-02-28 16:41 UTC (permalink / raw)
To: Florian Fainelli, Vivien Didelot, netdev; +Cc: Andrew Lunn
Switch devices are component slaves. Such devices have a "switch"
property in the DSA device tree which is a phandle to the switch
device. Add a component match on the device node.
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
---
net/dsa/dsa.c | 17 +++++++++++++++--
1 file changed, 15 insertions(+), 2 deletions(-)
diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c
index f2af801554ec..73a3fd561ef3 100644
--- a/net/dsa/dsa.c
+++ b/net/dsa/dsa.c
@@ -886,18 +886,25 @@ static void dsa_finish_dst(struct dsa_switch_tree *dst, struct device *parent,
}
}
+static int compare_of(struct device *dev, void *data)
+{
+ return dev->of_node == data;
+}
+
static int dsa_probe(struct platform_device *pdev)
{
struct dsa_platform_data *pd = pdev->dev.platform_data;
+ struct device_node *np = pdev->dev.of_node;
struct component_match *match = NULL;
+ struct device_node *chip;
struct net_device *dev;
struct dsa_switch_tree *dst;
- int ret;
+ int i, ret;
pr_notice_once("Distributed Switch Architecture driver version %s\n",
dsa_driver_version);
- if (pdev->dev.of_node) {
+ if (np) {
pd = devm_kzalloc(&pdev->dev, sizeof(*pd), GFP_KERNEL);
if (!pd)
return -ENOMEM;
@@ -941,6 +948,12 @@ static int dsa_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, dst);
+ for (i = 0; i < pd->nr_chips; i++) {
+ chip = pd->chip[i].of_chip;
+ if (chip)
+ component_match_add(&pdev->dev, &match, compare_of,
+ chip);
+ }
return component_master_add_with_match(&pdev->dev, &dsa_ops, match);
--
2.7.0
^ permalink raw reply related [flat|nested] 47+ messages in thread
* [PATCH RFC v2 13/32] net: dsa: Make dsa,mii-bus optional
2016-02-28 16:41 [PATCH RFC v2 00/32] Make DSA switches linux devices Andrew Lunn
` (11 preceding siblings ...)
2016-02-28 16:41 ` [PATCH RFC v2 12/32] net: dsa: Add slave component matches based on a phandle to the slave Andrew Lunn
@ 2016-02-28 16:41 ` Andrew Lunn
2016-02-28 16:41 ` [PATCH RFC v2 14/32] net: dsa: Add register/unregister functions for switch drivers Andrew Lunn
` (19 subsequent siblings)
32 siblings, 0 replies; 47+ messages in thread
From: Andrew Lunn @ 2016-02-28 16:41 UTC (permalink / raw)
To: Florian Fainelli, Vivien Didelot, netdev; +Cc: Andrew Lunn
When all the switches are devices and register to the DSA framework,
having a dsa,mii-bus property is not required.
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
Acked-by: Florian Fainelli <f.fainelli@gmail.com>
---
Documentation/devicetree/bindings/net/dsa/dsa.txt | 3 +-
net/dsa/dsa.c | 36 +++++++++++++----------
2 files changed, 23 insertions(+), 16 deletions(-)
diff --git a/Documentation/devicetree/bindings/net/dsa/dsa.txt b/Documentation/devicetree/bindings/net/dsa/dsa.txt
index f99e5694a61f..625b2e5d8ae2 100644
--- a/Documentation/devicetree/bindings/net/dsa/dsa.txt
+++ b/Documentation/devicetree/bindings/net/dsa/dsa.txt
@@ -8,11 +8,12 @@ Required properties:
Second cell is used only when cascading/chaining.
- #size-cells : Must be 0
- dsa,ethernet : Should be a phandle to a valid Ethernet device node
-- dsa,mii-bus : Should be a phandle to a valid MDIO bus device node
Optional properties:
- interrupts : property with a value describing the switch
interrupt number (not supported by the driver)
+- dsa,mii-bus : Should be a phandle to a valid MDIO bus device node.
+ Required when not all switches are devices.
A DSA node can contain multiple switch chips which are therefore child nodes of
the parent DSA node. The maximum number of allowed child nodes is 4
diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c
index 73a3fd561ef3..fb6d390503e1 100644
--- a/net/dsa/dsa.c
+++ b/net/dsa/dsa.c
@@ -662,8 +662,8 @@ static void dsa_of_free_platform_data(struct dsa_platform_data *pd)
static int dsa_of_probe(struct device *dev, struct dsa_platform_data *pd)
{
struct device_node *np = dev->of_node;
- struct device_node *child, *chip, *mdio, *ethernet, *port;
- struct mii_bus *mdio_bus, *mdio_bus_switch;
+ struct device_node *child, *chip, *mdio, *switch_mdio, *ethernet, *port;
+ struct mii_bus *mdio_bus = NULL, *mdio_bus_switch;
struct net_device *ethernet_dev;
struct dsa_chip_data *cd;
const char *port_name;
@@ -676,12 +676,6 @@ static int dsa_of_probe(struct device *dev, struct dsa_platform_data *pd)
int ret = 0;
mdio = of_parse_phandle(np, "dsa,mii-bus", 0);
- if (!mdio)
- return -EINVAL;
-
- mdio_bus = of_mdio_find_bus(mdio);
- if (!mdio_bus)
- return -EPROBE_DEFER;
ethernet = of_parse_phandle(np, "dsa,ethernet", 0);
if (!ethernet) {
@@ -713,11 +707,22 @@ static int dsa_of_probe(struct device *dev, struct dsa_platform_data *pd)
cd->of_node = child;
chip = of_parse_phandle(child, "switch", 0);
- if (chip)
+ if (chip) {
cd->of_chip = chip;
+ } else {
+ if (!mdio)
+ return -EINVAL;
- /* When assigning the host device, increment its refcount */
- cd->host_dev = get_device(&mdio_bus->dev);
+ mdio_bus = of_mdio_find_bus(mdio);
+ if (!mdio_bus)
+ return -EPROBE_DEFER;
+
+ /*
+ * When assigning the host device, increment
+ * its refcount
+ */
+ cd->host_dev = get_device(&mdio_bus->dev);
+ }
sw_addr = of_get_property(child, "reg", NULL);
if (!sw_addr)
@@ -730,9 +735,9 @@ static int dsa_of_probe(struct device *dev, struct dsa_platform_data *pd)
if (!of_property_read_u32(child, "eeprom-length", &eeprom_len))
cd->eeprom_len = eeprom_len;
- mdio = of_parse_phandle(child, "mii-bus", 0);
- if (mdio) {
- mdio_bus_switch = of_mdio_find_bus(mdio);
+ switch_mdio = of_parse_phandle(child, "mii-bus", 0);
+ if (switch_mdio) {
+ mdio_bus_switch = of_mdio_find_bus(switch_mdio);
if (!mdio_bus_switch) {
ret = -EPROBE_DEFER;
goto out_free_chip;
@@ -791,7 +796,8 @@ static int dsa_of_probe(struct device *dev, struct dsa_platform_data *pd)
/* The individual chips hold their own refcount on the mdio bus,
* so drop ours */
- put_device(&mdio_bus->dev);
+ if (mdio_bus)
+ put_device(&mdio_bus->dev);
return 0;
--
2.7.0
^ permalink raw reply related [flat|nested] 47+ messages in thread
* [PATCH RFC v2 14/32] net: dsa: Add register/unregister functions for switch drivers
2016-02-28 16:41 [PATCH RFC v2 00/32] Make DSA switches linux devices Andrew Lunn
` (12 preceding siblings ...)
2016-02-28 16:41 ` [PATCH RFC v2 13/32] net: dsa: Make dsa,mii-bus optional Andrew Lunn
@ 2016-02-28 16:41 ` Andrew Lunn
2016-02-28 16:41 ` [PATCH RFC v2 15/32] net: dsa: Rename DSA probe function Andrew Lunn
` (18 subsequent siblings)
32 siblings, 0 replies; 47+ messages in thread
From: Andrew Lunn @ 2016-02-28 16:41 UTC (permalink / raw)
To: Florian Fainelli, Vivien Didelot, netdev; +Cc: Andrew Lunn
A switch device driver registers with DSA as part of the component
slave bind and unregisters on component slave unbind.
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
---
include/net/dsa.h | 3 +++
net/dsa/dsa.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 56 insertions(+)
diff --git a/include/net/dsa.h b/include/net/dsa.h
index ea4cfdf1b549..dbb90f2c475b 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -345,6 +345,9 @@ struct dsa_switch_driver {
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);
+int dsa_switch_register(struct dsa_switch_tree *dst, struct dsa_switch *ds,
+ struct device_node *np, const char *name);
+void dsa_switch_unregister(struct dsa_switch *ds);
static inline void *ds_to_priv(struct dsa_switch *ds)
{
diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c
index fb6d390503e1..0be85a14a835 100644
--- a/net/dsa/dsa.c
+++ b/net/dsa/dsa.c
@@ -997,6 +997,59 @@ static const struct component_master_ops dsa_ops = {
.unbind = dsa_unbind,
};
+static int dsa_find_chip_index(struct dsa_switch_tree *dst,
+ struct device_node *np)
+{
+ struct dsa_platform_data *pd = dst->pd;
+ struct dsa_chip_data *cd;
+ int i;
+
+ for (i = 0; i < pd->nr_chips; i++) {
+ cd = &pd->chip[i];
+ if (cd->of_chip == np)
+ return i;
+ }
+ return -ENODEV;
+}
+
+int dsa_switch_register(struct dsa_switch_tree *dst, struct dsa_switch *ds,
+ struct device_node *np, const char *name)
+{
+ struct dsa_platform_data *pd = dst->pd;
+ int index = dsa_find_chip_index(dst, np);
+
+ if (index < 0)
+ return index;
+
+ netdev_info(dst->master_netdev, "[%d]: detected a %s switch\n",
+ index, name);
+
+ if (dst->ds[index])
+ return -EINVAL;
+
+ ds->index = index;
+ ds->pd = &pd->chip[index];
+ ds->dst = dst;
+ dst->ds[index] = ds;
+ ds->tag_protocol = ds->drv->tag_protocol;
+ ds->master_dev = &dst->master_netdev->dev;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(dsa_switch_register);
+
+void dsa_switch_unregister(struct dsa_switch *ds)
+{
+ struct dsa_switch_tree *dst = ds->dst;
+ int index = ds->index;
+
+#ifdef CONFIG_PM_SLEEP
+ dsa_switch_suspend(ds);
+#endif
+ dst->ds[index] = NULL;
+}
+EXPORT_SYMBOL_GPL(dsa_switch_unregister);
+
static void dsa_shutdown(struct platform_device *pdev)
{
}
--
2.7.0
^ permalink raw reply related [flat|nested] 47+ messages in thread
* [PATCH RFC v2 15/32] net: dsa: Rename DSA probe function.
2016-02-28 16:41 [PATCH RFC v2 00/32] Make DSA switches linux devices Andrew Lunn
` (13 preceding siblings ...)
2016-02-28 16:41 ` [PATCH RFC v2 14/32] net: dsa: Add register/unregister functions for switch drivers Andrew Lunn
@ 2016-02-28 16:41 ` Andrew Lunn
2016-02-28 16:41 ` [PATCH RFC v2 16/32] dsa: mv88e6xxx: Use bus in mv88e6xxx_lookup_name() Andrew Lunn
` (17 subsequent siblings)
32 siblings, 0 replies; 47+ messages in thread
From: Andrew Lunn @ 2016-02-28 16:41 UTC (permalink / raw)
To: Florian Fainelli, Vivien Didelot, netdev; +Cc: Andrew Lunn
Rename the function called from the DSA to perform a probe for the
switch. This makes the normal _probe() name available for a standard
Linux device driver probe function.
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
---
drivers/net/dsa/bcm_sf2.c | 4 ++--
drivers/net/dsa/mv88e6060.c | 4 ++--
drivers/net/dsa/mv88e6123.c | 4 ++--
drivers/net/dsa/mv88e6131.c | 4 ++--
drivers/net/dsa/mv88e6171.c | 4 ++--
drivers/net/dsa/mv88e6352.c | 4 ++--
6 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c
index fbb17e042e7b..c0c83c2f2691 100644
--- a/drivers/net/dsa/bcm_sf2.c
+++ b/drivers/net/dsa/bcm_sf2.c
@@ -135,7 +135,7 @@ static int bcm_sf2_sw_get_sset_count(struct dsa_switch *ds)
return BCM_SF2_STATS_SIZE;
}
-static char *bcm_sf2_sw_probe(struct device *host_dev, int sw_addr)
+static char *bcm_sf2_sw_drv_probe(struct device *host_dev, int sw_addr)
{
return "Broadcom Starfighter 2";
}
@@ -1371,7 +1371,7 @@ static int bcm_sf2_sw_set_wol(struct dsa_switch *ds, int port,
static struct dsa_switch_driver bcm_sf2_switch_driver = {
.tag_protocol = DSA_TAG_PROTO_BRCM,
- .probe = bcm_sf2_sw_probe,
+ .probe = bcm_sf2_sw_drv_probe,
.setup = bcm_sf2_sw_setup,
.set_addr = bcm_sf2_sw_set_addr,
.get_phy_flags = bcm_sf2_sw_get_phy_flags,
diff --git a/drivers/net/dsa/mv88e6060.c b/drivers/net/dsa/mv88e6060.c
index faf9834fe1cc..59e8b0fb8431 100644
--- a/drivers/net/dsa/mv88e6060.c
+++ b/drivers/net/dsa/mv88e6060.c
@@ -51,7 +51,7 @@ static int reg_write(struct dsa_switch *ds, int addr, int reg, u16 val)
return __ret; \
})
-static char *mv88e6060_probe(struct device *host_dev, int sw_addr)
+static char *mv88e6060_drv_probe(struct device *host_dev, int sw_addr)
{
struct mii_bus *bus = dsa_host_dev_to_mii_bus(host_dev);
int ret;
@@ -245,7 +245,7 @@ mv88e6060_phy_write(struct dsa_switch *ds, int port, int regnum, u16 val)
static struct dsa_switch_driver mv88e6060_switch_driver = {
.tag_protocol = DSA_TAG_PROTO_TRAILER,
- .probe = mv88e6060_probe,
+ .probe = mv88e6060_drv_probe,
.setup = mv88e6060_setup,
.set_addr = mv88e6060_set_addr,
.phy_read = mv88e6060_phy_read,
diff --git a/drivers/net/dsa/mv88e6123.c b/drivers/net/dsa/mv88e6123.c
index 9d39f108793b..6d6fca62e8b1 100644
--- a/drivers/net/dsa/mv88e6123.c
+++ b/drivers/net/dsa/mv88e6123.c
@@ -29,7 +29,7 @@ static const struct mv88e6xxx_switch_id mv88e6123_table[] = {
{ PORT_SWITCH_ID_6165_A2, "Marvell 88e6165 (A2)" },
};
-static char *mv88e6123_probe(struct device *host_dev, int sw_addr)
+static char *mv88e6123_drv_probe(struct device *host_dev, int sw_addr)
{
return mv88e6xxx_lookup_name(host_dev, sw_addr, mv88e6123_table,
ARRAY_SIZE(mv88e6123_table));
@@ -103,7 +103,7 @@ static int mv88e6123_setup(struct dsa_switch *ds, struct device *dev)
struct dsa_switch_driver mv88e6123_switch_driver = {
.tag_protocol = DSA_TAG_PROTO_EDSA,
- .probe = mv88e6123_probe,
+ .probe = mv88e6123_drv_probe,
.setup = mv88e6123_setup,
.set_addr = mv88e6xxx_set_addr_indirect,
.phy_read = mv88e6xxx_phy_read,
diff --git a/drivers/net/dsa/mv88e6131.c b/drivers/net/dsa/mv88e6131.c
index 3103b4953af4..e0aa3be7f5a9 100644
--- a/drivers/net/dsa/mv88e6131.c
+++ b/drivers/net/dsa/mv88e6131.c
@@ -25,7 +25,7 @@ static const struct mv88e6xxx_switch_id mv88e6131_table[] = {
{ PORT_SWITCH_ID_6185, "Marvell 88E6185" },
};
-static char *mv88e6131_probe(struct device *host_dev, int sw_addr)
+static char *mv88e6131_drv_probe(struct device *host_dev, int sw_addr)
{
return mv88e6xxx_lookup_name(host_dev, sw_addr, mv88e6131_table,
ARRAY_SIZE(mv88e6131_table));
@@ -160,7 +160,7 @@ mv88e6131_phy_write(struct dsa_switch *ds,
struct dsa_switch_driver mv88e6131_switch_driver = {
.tag_protocol = DSA_TAG_PROTO_DSA,
- .probe = mv88e6131_probe,
+ .probe = mv88e6131_drv_probe,
.setup = mv88e6131_setup,
.set_addr = mv88e6xxx_set_addr_direct,
.phy_read = mv88e6131_phy_read,
diff --git a/drivers/net/dsa/mv88e6171.c b/drivers/net/dsa/mv88e6171.c
index 29a77366afc6..8fc4db23744e 100644
--- a/drivers/net/dsa/mv88e6171.c
+++ b/drivers/net/dsa/mv88e6171.c
@@ -24,7 +24,7 @@ static const struct mv88e6xxx_switch_id mv88e6171_table[] = {
{ PORT_SWITCH_ID_6351, "Marvell 88E6351" },
};
-static char *mv88e6171_probe(struct device *host_dev, int sw_addr)
+static char *mv88e6171_drv_probe(struct device *host_dev, int sw_addr)
{
return mv88e6xxx_lookup_name(host_dev, sw_addr, mv88e6171_table,
ARRAY_SIZE(mv88e6171_table));
@@ -89,7 +89,7 @@ static int mv88e6171_setup(struct dsa_switch *ds, struct device *dev)
struct dsa_switch_driver mv88e6171_switch_driver = {
.tag_protocol = DSA_TAG_PROTO_EDSA,
- .probe = mv88e6171_probe,
+ .probe = mv88e6171_drv_probe,
.setup = mv88e6171_setup,
.set_addr = mv88e6xxx_set_addr_indirect,
.phy_read = mv88e6xxx_phy_read_indirect,
diff --git a/drivers/net/dsa/mv88e6352.c b/drivers/net/dsa/mv88e6352.c
index eb57a379b9cc..2877ad8acefa 100644
--- a/drivers/net/dsa/mv88e6352.c
+++ b/drivers/net/dsa/mv88e6352.c
@@ -36,7 +36,7 @@ static const struct mv88e6xxx_switch_id mv88e6352_table[] = {
{ PORT_SWITCH_ID_6352_A1, "Marvell 88E6352 (A1)" },
};
-static char *mv88e6352_probe(struct device *host_dev, int sw_addr)
+static char *mv88e6352_drv_probe(struct device *host_dev, int sw_addr)
{
return mv88e6xxx_lookup_name(host_dev, sw_addr, mv88e6352_table,
ARRAY_SIZE(mv88e6352_table));
@@ -302,7 +302,7 @@ static int mv88e6352_set_eeprom(struct dsa_switch *ds,
struct dsa_switch_driver mv88e6352_switch_driver = {
.tag_protocol = DSA_TAG_PROTO_EDSA,
- .probe = mv88e6352_probe,
+ .probe = mv88e6352_drv_probe,
.setup = mv88e6352_setup,
.set_addr = mv88e6xxx_set_addr_indirect,
.phy_read = mv88e6xxx_phy_read_indirect,
--
2.7.0
^ permalink raw reply related [flat|nested] 47+ messages in thread
* [PATCH RFC v2 16/32] dsa: mv88e6xxx: Use bus in mv88e6xxx_lookup_name()
2016-02-28 16:41 [PATCH RFC v2 00/32] Make DSA switches linux devices Andrew Lunn
` (14 preceding siblings ...)
2016-02-28 16:41 ` [PATCH RFC v2 15/32] net: dsa: Rename DSA probe function Andrew Lunn
@ 2016-02-28 16:41 ` Andrew Lunn
2016-02-28 16:41 ` [PATCH RFC v2 17/32] dsa: mv88e6xxx: Add shared code for binding/unbinding a switch driver Andrew Lunn
` (16 subsequent siblings)
32 siblings, 0 replies; 47+ messages in thread
From: Andrew Lunn @ 2016-02-28 16:41 UTC (permalink / raw)
To: Florian Fainelli, Vivien Didelot, netdev; +Cc: Andrew Lunn
mv88e6xxx_lookup_name() returns the model name of a switch at a given
address on an MII bus. Using mii_bus to identify the bus rather than
the host device is more logical, so change the parameter.
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
---
v2: Check bus is valid before dereferencing it.
---
drivers/net/dsa/mv88e6123.c | 4 +++-
drivers/net/dsa/mv88e6131.c | 4 +++-
drivers/net/dsa/mv88e6171.c | 4 +++-
drivers/net/dsa/mv88e6352.c | 4 +++-
drivers/net/dsa/mv88e6xxx.c | 6 +++---
drivers/net/dsa/mv88e6xxx.h | 2 +-
6 files changed, 16 insertions(+), 8 deletions(-)
diff --git a/drivers/net/dsa/mv88e6123.c b/drivers/net/dsa/mv88e6123.c
index 6d6fca62e8b1..2c23762cbed8 100644
--- a/drivers/net/dsa/mv88e6123.c
+++ b/drivers/net/dsa/mv88e6123.c
@@ -31,7 +31,9 @@ static const struct mv88e6xxx_switch_id mv88e6123_table[] = {
static char *mv88e6123_drv_probe(struct device *host_dev, int sw_addr)
{
- return mv88e6xxx_lookup_name(host_dev, sw_addr, mv88e6123_table,
+ struct mii_bus *bus = dsa_host_dev_to_mii_bus(host_dev);
+
+ return mv88e6xxx_lookup_name(bus, sw_addr, mv88e6123_table,
ARRAY_SIZE(mv88e6123_table));
}
diff --git a/drivers/net/dsa/mv88e6131.c b/drivers/net/dsa/mv88e6131.c
index e0aa3be7f5a9..02d2bca095af 100644
--- a/drivers/net/dsa/mv88e6131.c
+++ b/drivers/net/dsa/mv88e6131.c
@@ -27,7 +27,9 @@ static const struct mv88e6xxx_switch_id mv88e6131_table[] = {
static char *mv88e6131_drv_probe(struct device *host_dev, int sw_addr)
{
- return mv88e6xxx_lookup_name(host_dev, sw_addr, mv88e6131_table,
+ struct mii_bus *bus = dsa_host_dev_to_mii_bus(host_dev);
+
+ return mv88e6xxx_lookup_name(bus, sw_addr, mv88e6131_table,
ARRAY_SIZE(mv88e6131_table));
}
diff --git a/drivers/net/dsa/mv88e6171.c b/drivers/net/dsa/mv88e6171.c
index 8fc4db23744e..d557be12feb7 100644
--- a/drivers/net/dsa/mv88e6171.c
+++ b/drivers/net/dsa/mv88e6171.c
@@ -26,7 +26,9 @@ static const struct mv88e6xxx_switch_id mv88e6171_table[] = {
static char *mv88e6171_drv_probe(struct device *host_dev, int sw_addr)
{
- return mv88e6xxx_lookup_name(host_dev, sw_addr, mv88e6171_table,
+ struct mii_bus *bus = dsa_host_dev_to_mii_bus(host_dev);
+
+ return mv88e6xxx_lookup_name(bus, sw_addr, mv88e6171_table,
ARRAY_SIZE(mv88e6171_table));
}
diff --git a/drivers/net/dsa/mv88e6352.c b/drivers/net/dsa/mv88e6352.c
index 2877ad8acefa..959835d69af6 100644
--- a/drivers/net/dsa/mv88e6352.c
+++ b/drivers/net/dsa/mv88e6352.c
@@ -38,7 +38,9 @@ static const struct mv88e6xxx_switch_id mv88e6352_table[] = {
static char *mv88e6352_drv_probe(struct device *host_dev, int sw_addr)
{
- return mv88e6xxx_lookup_name(host_dev, sw_addr, mv88e6352_table,
+ struct mii_bus *bus = dsa_host_dev_to_mii_bus(host_dev);
+
+ return mv88e6xxx_lookup_name(bus, sw_addr, mv88e6352_table,
ARRAY_SIZE(mv88e6352_table));
}
diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index 2e945f325db1..7f67bf47cdb6 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -2622,11 +2622,10 @@ int mv88e6xxx_get_temp_alarm(struct dsa_switch *ds, bool *alarm)
}
#endif /* CONFIG_NET_DSA_HWMON */
-char *mv88e6xxx_lookup_name(struct device *host_dev, int sw_addr,
+char *mv88e6xxx_lookup_name(struct mii_bus *bus, int sw_addr,
const struct mv88e6xxx_switch_id *table,
unsigned int num)
{
- struct mii_bus *bus = dsa_host_dev_to_mii_bus(host_dev);
int i, ret;
if (!bus)
@@ -2644,7 +2643,8 @@ char *mv88e6xxx_lookup_name(struct device *host_dev, int sw_addr,
/* Look up only the product number */
for (i = 0; i < num; ++i) {
if (table[i].id == (ret & PORT_SWITCH_ID_PROD_NUM_MASK)) {
- dev_warn(host_dev, "unknown revision %d, using base switch 0x%x\n",
+ dev_warn(&bus->dev,
+ "unknown revision %d, using base switch 0x%x\n",
ret & PORT_SWITCH_ID_REV_MASK,
ret & PORT_SWITCH_ID_PROD_NUM_MASK);
return table[i].name;
diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h
index 53f2fc82069b..dce72d1007c2 100644
--- a/drivers/net/dsa/mv88e6xxx.h
+++ b/drivers/net/dsa/mv88e6xxx.h
@@ -444,7 +444,7 @@ struct mv88e6xxx_hw_stat {
};
int mv88e6xxx_switch_reset(struct dsa_switch *ds, bool ppu_active);
-char *mv88e6xxx_lookup_name(struct device *host_dev, int sw_addr,
+char *mv88e6xxx_lookup_name(struct mii_bus *bus, int sw_addr,
const struct mv88e6xxx_switch_id *table,
unsigned int num);
int mv88e6xxx_setup_ports(struct dsa_switch *ds);
--
2.7.0
^ permalink raw reply related [flat|nested] 47+ messages in thread
* [PATCH RFC v2 17/32] dsa: mv88e6xxx: Add shared code for binding/unbinding a switch driver.
2016-02-28 16:41 [PATCH RFC v2 00/32] Make DSA switches linux devices Andrew Lunn
` (15 preceding siblings ...)
2016-02-28 16:41 ` [PATCH RFC v2 16/32] dsa: mv88e6xxx: Use bus in mv88e6xxx_lookup_name() Andrew Lunn
@ 2016-02-28 16:41 ` Andrew Lunn
2016-02-28 16:41 ` [PATCH RFC v2 18/32] dsa: mv88e6xxx: Prepare for turning this into a library module Andrew Lunn
` (15 subsequent siblings)
32 siblings, 0 replies; 47+ messages in thread
From: Andrew Lunn @ 2016-02-28 16:41 UTC (permalink / raw)
To: Florian Fainelli, Vivien Didelot, netdev; +Cc: Andrew Lunn
Switch drivers are component slaves. When they are bound to a master
component, the bind function is called and resources can be reserved.
Add the shared code.
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
---
drivers/net/dsa/mv88e6xxx.c | 77 ++++++++++++++++++++++++++++++++++++++-------
drivers/net/dsa/mv88e6xxx.h | 5 +++
2 files changed, 71 insertions(+), 11 deletions(-)
diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index 7f67bf47cdb6..4a4af245b0eb 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -4,6 +4,7 @@
*
* Copyright (c) 2015 CMC Electronics, Inc.
* Added support for VLAN Table Unit operations
+ * Copyright (c) 2015 Andrew Lunn <andrew@lunn.ch>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -12,14 +13,16 @@
*/
#include <linux/delay.h>
+#include <linux/device.h>
#include <linux/etherdevice.h>
#include <linux/ethtool.h>
+#include <linux/gpio/consumer.h>
#include <linux/if_bridge.h>
#include <linux/jiffies.h>
#include <linux/list.h>
+#include <linux/mdio.h>
#include <linux/module.h>
#include <linux/netdevice.h>
-#include <linux/gpio/consumer.h>
#include <linux/phy.h>
#include <net/dsa.h>
#include <net/switchdev.h>
@@ -2196,19 +2199,22 @@ int mv88e6xxx_setup_ports(struct dsa_switch *ds)
int mv88e6xxx_setup_common(struct dsa_switch *ds, struct device *dev)
{
- struct mv88e6xxx_priv_state *ps;
+ struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
- ps = devm_kzalloc(dev, sizeof(*ps), GFP_KERNEL);
- if (!ps)
- return -ENOMEM;
+ if (!ps) {
+ ps = devm_kzalloc(dev, sizeof(*ps), GFP_KERNEL);
+ if (!ps)
+ return -ENOMEM;
- ds->priv = ps;
- ps->ds = ds;
- ps->bus = dsa_host_dev_to_mii_bus(ds->master_dev);
- if (!ps->bus)
- return -ENODEV;
+ ds->priv = ps;
+ ps->ds = ds;
- ps->sw_addr = ds->pd->sw_addr;
+ ps->bus = dsa_host_dev_to_mii_bus(ds->master_dev);
+ if (!ps->bus)
+ return -ENODEV;
+
+ ps->sw_addr = ds->pd->sw_addr;
+ }
mutex_init(&ps->smi_mutex);
@@ -2654,6 +2660,55 @@ char *mv88e6xxx_lookup_name(struct mii_bus *bus, int sw_addr,
return NULL;
}
+int mv88e6xxx_bind(struct device *dev,
+ struct dsa_switch_tree *dst,
+ struct dsa_switch_driver *ops,
+ const struct mv88e6xxx_switch_id *table,
+ unsigned int table_size)
+{
+ struct mdio_device *mdiodev = to_mdio_device(dev);
+ struct mv88e6xxx_priv_state *ps;
+ struct device_node *np = dev->of_node;
+ struct dsa_switch *ds;
+ const char *name;
+
+ ds = devm_kzalloc(dev, sizeof(*ds) + sizeof(*ps), GFP_KERNEL);
+ if (!ds)
+ return -ENOMEM;
+
+ ps = (struct mv88e6xxx_priv_state *)(ds + 1);
+ ds->priv = ps;
+ ps->ds = ds;
+ ps->bus = mdiodev->bus;
+ ps->sw_addr = mdiodev->addr;
+
+ get_device(&ps->bus->dev);
+
+ ds->drv = ops;
+
+ name = mv88e6xxx_lookup_name(ps->bus, ps->sw_addr, table, table_size);
+ if (!name) {
+ dev_err(dev, "Failed to find switch");
+ return -ENODEV;
+ }
+
+ dev_set_drvdata(dev, ds);
+ dsa_switch_register(dst, ds, np, name);
+
+ return 0;
+}
+
+void mv88e6xxx_unbind(struct device *dev, struct device *master, void *data)
+{
+ struct dsa_switch *ds = dev_get_drvdata(dev);
+ struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+
+ dsa_switch_unregister(ds);
+ devm_kfree(dev, ds);
+
+ put_device(&ps->bus->dev);
+}
+
static int __init mv88e6xxx_init(void)
{
#if IS_ENABLED(CONFIG_NET_DSA_MV88E6131)
diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h
index dce72d1007c2..a4ae99b7cfd0 100644
--- a/drivers/net/dsa/mv88e6xxx.h
+++ b/drivers/net/dsa/mv88e6xxx.h
@@ -447,6 +447,11 @@ int mv88e6xxx_switch_reset(struct dsa_switch *ds, bool ppu_active);
char *mv88e6xxx_lookup_name(struct mii_bus *bus, int sw_addr,
const struct mv88e6xxx_switch_id *table,
unsigned int num);
+int mv88e6xxx_bind(struct device *dev, struct dsa_switch_tree *dst,
+ struct dsa_switch_driver *ops,
+ const struct mv88e6xxx_switch_id *table,
+ unsigned int table_size);
+void mv88e6xxx_unbind(struct device *dev, struct device *master, void *data);
int mv88e6xxx_setup_ports(struct dsa_switch *ds);
int mv88e6xxx_setup_common(struct dsa_switch *ds, struct device *dev);
int mv88e6xxx_setup_global(struct dsa_switch *ds);
--
2.7.0
^ permalink raw reply related [flat|nested] 47+ messages in thread
* [PATCH RFC v2 18/32] dsa: mv88e6xxx: Prepare for turning this into a library module
2016-02-28 16:41 [PATCH RFC v2 00/32] Make DSA switches linux devices Andrew Lunn
` (16 preceding siblings ...)
2016-02-28 16:41 ` [PATCH RFC v2 17/32] dsa: mv88e6xxx: Add shared code for binding/unbinding a switch driver Andrew Lunn
@ 2016-02-28 16:41 ` Andrew Lunn
2016-02-29 2:40 ` Vivien Didelot
2016-02-28 16:41 ` [PATCH RFC v2 19/32] dsa: mv88e6xxx: Add macro for registering the drivers Andrew Lunn
` (14 subsequent siblings)
32 siblings, 1 reply; 47+ messages in thread
From: Andrew Lunn @ 2016-02-28 16:41 UTC (permalink / raw)
To: Florian Fainelli, Vivien Didelot, netdev; +Cc: Andrew Lunn
Export all the functions so that we can later turn the module into a
library module.
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
---
drivers/net/dsa/mv88e6xxx.c | 46 +++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 46 insertions(+)
diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index 4a4af245b0eb..b0838bf77fd9 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -123,6 +123,7 @@ int mv88e6xxx_reg_read(struct dsa_switch *ds, int addr, int reg)
return ret;
}
+EXPORT_SYMBOL_GPL(mv88e6xxx_reg_read);
static int __mv88e6xxx_reg_write(struct mii_bus *bus, int sw_addr, int addr,
int reg, u16 val)
@@ -180,6 +181,7 @@ int mv88e6xxx_reg_write(struct dsa_switch *ds, int addr, int reg, u16 val)
return ret;
}
+EXPORT_SYMBOL_GPL(mv88e6xxx_reg_write);
int mv88e6xxx_set_addr_direct(struct dsa_switch *ds, u8 *addr)
{
@@ -189,6 +191,7 @@ int mv88e6xxx_set_addr_direct(struct dsa_switch *ds, u8 *addr)
return 0;
}
+EXPORT_SYMBOL_GPL(mv88e6xxx_set_addr_direct);
int mv88e6xxx_set_addr_indirect(struct dsa_switch *ds, u8 *addr)
{
@@ -214,6 +217,7 @@ int mv88e6xxx_set_addr_indirect(struct dsa_switch *ds, u8 *addr)
return 0;
}
+EXPORT_SYMBOL_GPL(mv88e6xxx_set_addr_indirect);
static int _mv88e6xxx_phy_read(struct dsa_switch *ds, int addr, int regnum)
{
@@ -339,6 +343,7 @@ void mv88e6xxx_ppu_state_init(struct dsa_switch *ds)
ps->ppu_timer.data = (unsigned long)ps;
ps->ppu_timer.function = mv88e6xxx_ppu_reenable_timer;
}
+EXPORT_SYMBOL_GPL(mv88e6xxx_ppu_state_init);
int mv88e6xxx_phy_read_ppu(struct dsa_switch *ds, int addr, int regnum)
{
@@ -352,6 +357,7 @@ int mv88e6xxx_phy_read_ppu(struct dsa_switch *ds, int addr, int regnum)
return ret;
}
+EXPORT_SYMBOL_GPL(mv88e6xxx_phy_read_ppu);
int mv88e6xxx_phy_write_ppu(struct dsa_switch *ds, int addr,
int regnum, u16 val)
@@ -366,6 +372,7 @@ int mv88e6xxx_phy_write_ppu(struct dsa_switch *ds, int addr,
return ret;
}
+EXPORT_SYMBOL_GPL(mv88e6xxx_phy_write_ppu);
#endif
static bool mv88e6xxx_6065_family(struct dsa_switch *ds)
@@ -546,6 +553,7 @@ void mv88e6xxx_adjust_link(struct dsa_switch *ds, int port,
out:
mutex_unlock(&ps->smi_mutex);
}
+EXPORT_SYMBOL_GPL(mv88e6xxx_adjust_link);
static int _mv88e6xxx_stats_wait(struct dsa_switch *ds)
{
@@ -742,6 +750,7 @@ void mv88e6xxx_get_strings(struct dsa_switch *ds, int port, uint8_t *data)
}
}
}
+EXPORT_SYMBOL_GPL(mv88e6xxx_get_strings);
int mv88e6xxx_get_sset_count(struct dsa_switch *ds)
{
@@ -755,6 +764,7 @@ int mv88e6xxx_get_sset_count(struct dsa_switch *ds)
}
return j;
}
+EXPORT_SYMBOL_GPL(mv88e6xxx_get_sset_count);
void
mv88e6xxx_get_ethtool_stats(struct dsa_switch *ds,
@@ -782,11 +792,13 @@ mv88e6xxx_get_ethtool_stats(struct dsa_switch *ds,
mutex_unlock(&ps->smi_mutex);
}
+EXPORT_SYMBOL_GPL(mv88e6xxx_get_ethtool_stats);
int mv88e6xxx_get_regs_len(struct dsa_switch *ds, int port)
{
return 32 * sizeof(u16);
}
+EXPORT_SYMBOL_GPL(mv88e6xxx_get_regs_len);
void mv88e6xxx_get_regs(struct dsa_switch *ds, int port,
struct ethtool_regs *regs, void *_p)
@@ -806,6 +818,7 @@ void mv88e6xxx_get_regs(struct dsa_switch *ds, int port,
p[i] = ret;
}
}
+EXPORT_SYMBOL_GPL(mv88e6xxx_get_regs);
static int _mv88e6xxx_wait(struct dsa_switch *ds, int reg, int offset,
u16 mask)
@@ -849,12 +862,14 @@ int mv88e6xxx_eeprom_load_wait(struct dsa_switch *ds)
return mv88e6xxx_wait(ds, REG_GLOBAL2, GLOBAL2_EEPROM_OP,
GLOBAL2_EEPROM_OP_LOAD);
}
+EXPORT_SYMBOL_GPL(mv88e6xxx_eeprom_load_wait);
int mv88e6xxx_eeprom_busy_wait(struct dsa_switch *ds)
{
return mv88e6xxx_wait(ds, REG_GLOBAL2, GLOBAL2_EEPROM_OP,
GLOBAL2_EEPROM_OP_BUSY);
}
+EXPORT_SYMBOL_GPL(mv88e6xxx_eeprom_busy_wait);
static int _mv88e6xxx_atu_wait(struct dsa_switch *ds)
{
@@ -921,6 +936,7 @@ out:
mutex_unlock(&ps->smi_mutex);
return reg;
}
+EXPORT_SYMBOL_GPL(mv88e6xxx_get_eee);
int mv88e6xxx_set_eee(struct dsa_switch *ds, int port,
struct phy_device *phydev, struct ethtool_eee *e)
@@ -947,6 +963,7 @@ out:
return ret;
}
+EXPORT_SYMBOL_GPL(mv88e6xxx_set_eee);
static int _mv88e6xxx_atu_cmd(struct dsa_switch *ds, u16 cmd)
{
@@ -1134,6 +1151,7 @@ int mv88e6xxx_port_stp_update(struct dsa_switch *ds, int port, u8 state)
return 0;
}
+EXPORT_SYMBOL_GPL(mv88e6xxx_port_stp_update);
static int _mv88e6xxx_port_pvid_get(struct dsa_switch *ds, int port, u16 *pvid)
{
@@ -1160,6 +1178,7 @@ int mv88e6xxx_port_pvid_get(struct dsa_switch *ds, int port, u16 *pvid)
return 0;
}
+EXPORT_SYMBOL_GPL(mv88e6xxx_port_pvid_get);
static int _mv88e6xxx_port_pvid_set(struct dsa_switch *ds, int port, u16 pvid)
{
@@ -1481,6 +1500,7 @@ int mv88e6xxx_port_vlan_prepare(struct dsa_switch *ds, int port,
*/
return 0;
}
+EXPORT_SYMBOL_GPL(mv88e6xxx_port_vlan_prepare);
static int _mv88e6xxx_port_vlan_add(struct dsa_switch *ds, int port, u16 vid,
bool untagged)
@@ -1535,6 +1555,7 @@ unlock:
return err;
}
+EXPORT_SYMBOL_GPL(mv88e6xxx_port_vlan_add);
static int _mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port, u16 vid)
{
@@ -1605,6 +1626,7 @@ unlock:
return err;
}
+EXPORT_SYMBOL_GPL(mv88e6xxx_port_vlan_del);
int mv88e6xxx_vlan_getnext(struct dsa_switch *ds, u16 *vid,
unsigned long *ports, unsigned long *untagged)
@@ -1651,6 +1673,7 @@ unlock:
return 0;
}
+EXPORT_SYMBOL_GPL(mv88e6xxx_vlan_getnext);
static int _mv88e6xxx_atu_mac_write(struct dsa_switch *ds,
const unsigned char *addr)
@@ -1738,6 +1761,7 @@ int mv88e6xxx_port_fdb_prepare(struct dsa_switch *ds, int port,
*/
return 0;
}
+EXPORT_SYMBOL_GPL(mv88e6xxx_port_fdb_prepare);
int mv88e6xxx_port_fdb_add(struct dsa_switch *ds, int port,
const struct switchdev_obj_port_fdb *fdb,
@@ -1755,6 +1779,7 @@ int mv88e6xxx_port_fdb_add(struct dsa_switch *ds, int port,
return ret;
}
+EXPORT_SYMBOL_GPL(mv88e6xxx_port_fdb_add);
int mv88e6xxx_port_fdb_del(struct dsa_switch *ds, int port,
const struct switchdev_obj_port_fdb *fdb)
@@ -1769,6 +1794,7 @@ int mv88e6xxx_port_fdb_del(struct dsa_switch *ds, int port,
return ret;
}
+EXPORT_SYMBOL_GPL(mv88e6xxx_port_fdb_del);
static int _mv88e6xxx_atu_getnext(struct dsa_switch *ds, u16 fid,
struct mv88e6xxx_atu_entry *entry)
@@ -1883,6 +1909,7 @@ unlock:
return err;
}
+EXPORT_SYMBOL_GPL(mv88e6xxx_port_fdb_dump);
int mv88e6xxx_port_bridge_join(struct dsa_switch *ds, int port, u32 members)
{
@@ -1898,6 +1925,7 @@ int mv88e6xxx_port_bridge_join(struct dsa_switch *ds, int port, u32 members)
mutex_unlock(&ps->smi_mutex);
return err;
}
+EXPORT_SYMBOL_GPL(mv88e6xxx_port_bridge_join);
int mv88e6xxx_port_bridge_leave(struct dsa_switch *ds, int port, u32 members)
{
@@ -1913,6 +1941,7 @@ int mv88e6xxx_port_bridge_leave(struct dsa_switch *ds, int port, u32 members)
mutex_unlock(&ps->smi_mutex);
return err;
}
+EXPORT_SYMBOL_GPL(mv88e6xxx_port_bridge_leave);
static void mv88e6xxx_bridge_work(struct work_struct *work)
{
@@ -2196,6 +2225,7 @@ int mv88e6xxx_setup_ports(struct dsa_switch *ds)
}
return 0;
}
+EXPORT_SYMBOL_GPL(mv88e6xxx_setup_ports);
int mv88e6xxx_setup_common(struct dsa_switch *ds, struct device *dev)
{
@@ -2224,6 +2254,7 @@ int mv88e6xxx_setup_common(struct dsa_switch *ds, struct device *dev)
return 0;
}
+EXPORT_SYMBOL_GPL(mv88e6xxx_setup_common);
int mv88e6xxx_setup_global(struct dsa_switch *ds)
{
@@ -2344,6 +2375,7 @@ unlock:
return ret;
}
+EXPORT_SYMBOL_GPL(mv88e6xxx_setup_global);
int mv88e6xxx_switch_reset(struct dsa_switch *ds, bool ppu_active)
{
@@ -2393,6 +2425,7 @@ int mv88e6xxx_switch_reset(struct dsa_switch *ds, bool ppu_active)
return 0;
}
+EXPORT_SYMBOL_GPL(mv88e6xxx_switch_reset);
int mv88e6xxx_phy_page_read(struct dsa_switch *ds, int port, int page, int reg)
{
@@ -2409,6 +2442,7 @@ error:
mutex_unlock(&ps->smi_mutex);
return ret;
}
+EXPORT_SYMBOL_GPL(mv88e6xxx_phy_page_write);
int mv88e6xxx_phy_page_write(struct dsa_switch *ds, int port, int page,
int reg, int val)
@@ -2427,6 +2461,7 @@ error:
mutex_unlock(&ps->smi_mutex);
return ret;
}
+EXPORT_SYMBOL_GPL(mv88e6xxx_phy_page_read);
static int mv88e6xxx_port_to_phy_addr(struct dsa_switch *ds, int port)
{
@@ -2452,6 +2487,7 @@ mv88e6xxx_phy_read(struct dsa_switch *ds, int port, int regnum)
mutex_unlock(&ps->smi_mutex);
return ret;
}
+EXPORT_SYMBOL_GPL(mv88e6xxx_phy_read);
int
mv88e6xxx_phy_write(struct dsa_switch *ds, int port, int regnum, u16 val)
@@ -2468,6 +2504,7 @@ mv88e6xxx_phy_write(struct dsa_switch *ds, int port, int regnum, u16 val)
mutex_unlock(&ps->smi_mutex);
return ret;
}
+EXPORT_SYMBOL_GPL(mv88e6xxx_phy_write);
int
mv88e6xxx_phy_read_indirect(struct dsa_switch *ds, int port, int regnum)
@@ -2484,6 +2521,7 @@ mv88e6xxx_phy_read_indirect(struct dsa_switch *ds, int port, int regnum)
mutex_unlock(&ps->smi_mutex);
return ret;
}
+EXPORT_SYMBOL_GPL(mv88e6xxx_phy_read_indirect);
int
mv88e6xxx_phy_write_indirect(struct dsa_switch *ds, int port, int regnum,
@@ -2501,6 +2539,7 @@ mv88e6xxx_phy_write_indirect(struct dsa_switch *ds, int port, int regnum,
mutex_unlock(&ps->smi_mutex);
return ret;
}
+EXPORT_SYMBOL_GPL(mv88e6xxx_phy_write_indirect);
#ifdef CONFIG_NET_DSA_HWMON
@@ -2572,6 +2611,7 @@ int mv88e6xxx_get_temp(struct dsa_switch *ds, int *temp)
return mv88e61xx_get_temp(ds, temp);
}
+EXPORT_SYMBOL_GPL(mv88e6xxx_get_temp);
int mv88e6xxx_get_temp_limit(struct dsa_switch *ds, int *temp)
{
@@ -2591,6 +2631,7 @@ int mv88e6xxx_get_temp_limit(struct dsa_switch *ds, int *temp)
return 0;
}
+EXPORT_SYMBOL_GPL(mv88e6xxx_get_temp_limit);
int mv88e6xxx_set_temp_limit(struct dsa_switch *ds, int temp)
{
@@ -2607,6 +2648,7 @@ int mv88e6xxx_set_temp_limit(struct dsa_switch *ds, int temp)
return mv88e6xxx_phy_page_write(ds, phy, 6, 26,
(ret & 0xe0ff) | (temp << 8));
}
+EXPORT_SYMBOL_GPL(mv88e6xxx_set_temp_limit);
int mv88e6xxx_get_temp_alarm(struct dsa_switch *ds, bool *alarm)
{
@@ -2626,6 +2668,7 @@ int mv88e6xxx_get_temp_alarm(struct dsa_switch *ds, bool *alarm)
return 0;
}
+EXPORT_SYMBOL_GPL(mv88e6xxx_get_temp_alarm);
#endif /* CONFIG_NET_DSA_HWMON */
char *mv88e6xxx_lookup_name(struct mii_bus *bus, int sw_addr,
@@ -2659,6 +2702,7 @@ char *mv88e6xxx_lookup_name(struct mii_bus *bus, int sw_addr,
return NULL;
}
+EXPORT_SYMBOL_GPL(mv88e6xxx_lookup_name);
int mv88e6xxx_bind(struct device *dev,
struct dsa_switch_tree *dst,
@@ -2697,6 +2741,7 @@ int mv88e6xxx_bind(struct device *dev,
return 0;
}
+EXPORT_SYMBOL_GPL(mv88e6xxx_bind);
void mv88e6xxx_unbind(struct device *dev, struct device *master, void *data)
{
@@ -2708,6 +2753,7 @@ void mv88e6xxx_unbind(struct device *dev, struct device *master, void *data)
put_device(&ps->bus->dev);
}
+EXPORT_SYMBOL_GPL(mv88e6xxx_unbind);
static int __init mv88e6xxx_init(void)
{
--
2.7.0
^ permalink raw reply related [flat|nested] 47+ messages in thread
* [PATCH RFC v2 19/32] dsa: mv88e6xxx: Add macro for registering the drivers
2016-02-28 16:41 [PATCH RFC v2 00/32] Make DSA switches linux devices Andrew Lunn
` (17 preceding siblings ...)
2016-02-28 16:41 ` [PATCH RFC v2 18/32] dsa: mv88e6xxx: Prepare for turning this into a library module Andrew Lunn
@ 2016-02-28 16:41 ` Andrew Lunn
2016-02-28 16:41 ` [PATCH RFC v2 20/32] dsa: Add mdio device support to Marvell switches Andrew Lunn
` (13 subsequent siblings)
32 siblings, 0 replies; 47+ messages in thread
From: Andrew Lunn @ 2016-02-28 16:41 UTC (permalink / raw)
To: Florian Fainelli, Vivien Didelot, netdev; +Cc: Andrew Lunn
The macro cuts down on boilerplate. The switch driver needs to both
register itself as an MDIO driver and register itself as a switch
driver. This second registration is needed to retain backwards
compatibility with the old binding.
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
---
drivers/net/dsa/mv88e6xxx.h | 23 +++++++++++++++++++++++
1 file changed, 23 insertions(+)
diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h
index a4ae99b7cfd0..ce05964da85f 100644
--- a/drivers/net/dsa/mv88e6xxx.h
+++ b/drivers/net/dsa/mv88e6xxx.h
@@ -546,3 +546,26 @@ extern struct dsa_switch_driver mv88e6171_switch_driver;
#endif
+
+/**
+ * mv88e6xxx_module_driver() - Helper macro for registering mv88e6xxx drivers
+ *
+ * Helper macro for mv88e6xxx 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 mv88e6xxx_module_driver(_mdio_driver, _switch_driver) \
+static int __init mv88e6xxx_module_init(void) \
+{ \
+ register_switch_driver(&_switch_driver); \
+ return mdio_driver_register(&_mdio_driver); \
+} \
+module_init(mv88e6xxx_module_init); \
+ \
+static void __exit mv88e6xxx_module_exit(void) \
+{ \
+ mdio_driver_unregister(&_mdio_driver); \
+ unregister_switch_driver(&_switch_driver); \
+} \
+module_exit(mv88e6xxx_module_exit)
+
--
2.7.0
^ permalink raw reply related [flat|nested] 47+ messages in thread
* [PATCH RFC v2 20/32] dsa: Add mdio device support to Marvell switches
2016-02-28 16:41 [PATCH RFC v2 00/32] Make DSA switches linux devices Andrew Lunn
` (18 preceding siblings ...)
2016-02-28 16:41 ` [PATCH RFC v2 19/32] dsa: mv88e6xxx: Add macro for registering the drivers Andrew Lunn
@ 2016-02-28 16:41 ` Andrew Lunn
2016-02-28 16:41 ` [PATCH RFC v2 21/32] net: mdio: Add mdiodev_{read|write} helpers Andrew Lunn
` (12 subsequent siblings)
32 siblings, 0 replies; 47+ messages in thread
From: Andrew Lunn @ 2016-02-28 16:41 UTC (permalink / raw)
To: Florian Fainelli, Vivien Didelot, netdev; +Cc: Andrew Lunn
Allow Marvell switches to be mdio devices, which probe and then
register with the DSA framework, as component slaves.
At the same time, make them separate modules, and make mv88e6xxx a
library module.
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
---
v2: s/Copywrite/Copyright
---
.../devicetree/bindings/net/dsa/marvell.txt | 29 +++++
drivers/net/dsa/Makefile | 19 +---
drivers/net/dsa/mv88e6060.c | 122 ++++++++++++++++++---
drivers/net/dsa/mv88e6123.c | 50 ++++++++-
drivers/net/dsa/mv88e6131.c | 51 ++++++++-
drivers/net/dsa/mv88e6171.c | 51 ++++++++-
drivers/net/dsa/mv88e6352.c | 53 ++++++++-
drivers/net/dsa/mv88e6xxx.c | 35 ------
8 files changed, 329 insertions(+), 81 deletions(-)
create mode 100644 Documentation/devicetree/bindings/net/dsa/marvell.txt
diff --git a/Documentation/devicetree/bindings/net/dsa/marvell.txt b/Documentation/devicetree/bindings/net/dsa/marvell.txt
new file mode 100644
index 000000000000..51b7cd9408f2
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/dsa/marvell.txt
@@ -0,0 +1,29 @@
+Marvell DSA Switch Device Tree Bindings
+---------------------------------------
+
+WARNING: This binding is currently unstable. Do not program it into a
+FLASH never to be changed again. Once this binding is stable, this
+warning will be removed.
+
+If you need a stable binding, use the old dsa.txt binding.
+
+Marvell Switches are MDIO devices. The following properties should be
+placed as a child node of an mdio device.
+
+Required properties:
+- compatible : Should be one of "marvell,mv88e6123",
+ "marvell,mv88e6131", "marvell,mv88e6171",
+ "marvell,mv88e6352" or "marvell,mv88e6060"
+- reg : Address on the MII bus for the switch.
+
+Example:
+
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ switch0: switch@1 {
+ reg = <0>;
+ compatible = "marvell,mv88e6131";
+ };
+ };
diff --git a/drivers/net/dsa/Makefile b/drivers/net/dsa/Makefile
index a6e09939be65..3e1f36120e02 100644
--- a/drivers/net/dsa/Makefile
+++ b/drivers/net/dsa/Makefile
@@ -1,16 +1,7 @@
obj-$(CONFIG_NET_DSA_MV88E6060) += mv88e6060.o
-obj-$(CONFIG_NET_DSA_MV88E6XXX) += mv88e6xxx_drv.o
-mv88e6xxx_drv-y += mv88e6xxx.o
-ifdef CONFIG_NET_DSA_MV88E6123
-mv88e6xxx_drv-y += mv88e6123.o
-endif
-ifdef CONFIG_NET_DSA_MV88E6131
-mv88e6xxx_drv-y += mv88e6131.o
-endif
-ifdef CONFIG_NET_DSA_MV88E6352
-mv88e6xxx_drv-y += mv88e6352.o
-endif
-ifdef CONFIG_NET_DSA_MV88E6171
-mv88e6xxx_drv-y += mv88e6171.o
-endif
+obj-$(CONFIG_NET_DSA_MV88E6XXX) += mv88e6xxx.o
+obj-$(CONFIG_NET_DSA_MV88E6131) += mv88e6123.o
+obj-$(CONFIG_NET_DSA_MV88E6131) += mv88e6131.o
+obj-$(CONFIG_NET_DSA_MV88E6352) += mv88e6352.o
+obj-$(CONFIG_NET_DSA_MV88E6171) += mv88e6171.o
obj-$(CONFIG_NET_DSA_BCM_SF2) += bcm_sf2.o
diff --git a/drivers/net/dsa/mv88e6060.c b/drivers/net/dsa/mv88e6060.c
index 59e8b0fb8431..723273c8ff32 100644
--- a/drivers/net/dsa/mv88e6060.c
+++ b/drivers/net/dsa/mv88e6060.c
@@ -1,6 +1,7 @@
/*
* net/dsa/mv88e6060.c - Driver for Marvell 88e6060 switch chips
* Copyright (c) 2008-2009 Marvell Semiconductor
+ * Copyright (c) 2015 Andrew Lunn <andrew@lunn.ch>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -8,12 +9,14 @@
* (at your option) any later version.
*/
+#include <linux/component.h>
#include <linux/delay.h>
#include <linux/jiffies.h>
#include <linux/list.h>
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/phy.h>
+#include <linux/platform_device.h>
#include <net/dsa.h>
#include "mv88e6060.h"
@@ -51,14 +54,10 @@ static int reg_write(struct dsa_switch *ds, int addr, int reg, u16 val)
return __ret; \
})
-static char *mv88e6060_drv_probe(struct device *host_dev, int sw_addr)
+static char *mv88e6060_name(struct mii_bus *bus, int sw_addr)
{
- struct mii_bus *bus = dsa_host_dev_to_mii_bus(host_dev);
int ret;
- if (bus == NULL)
- return NULL;
-
ret = mdiobus_read(bus, sw_addr + REG_PORT(0), PORT_SWITCH_ID);
if (ret >= 0) {
if (ret == PORT_SWITCH_ID_6060)
@@ -73,6 +72,16 @@ static char *mv88e6060_drv_probe(struct device *host_dev, int sw_addr)
return NULL;
}
+static char *mv88e6060_drv_probe(struct device *host_dev, int sw_addr)
+{
+ struct mii_bus *bus = dsa_host_dev_to_mii_bus(host_dev);
+
+ if (!bus)
+ return NULL;
+
+ return mv88e6060_name(bus, sw_addr);
+}
+
static int mv88e6060_switch_reset(struct dsa_switch *ds)
{
int i;
@@ -170,19 +179,22 @@ static int mv88e6060_setup(struct dsa_switch *ds, struct device *dev)
{
int i;
int ret;
- struct mv88e6060_priv *priv;
+ struct mv88e6060_priv *priv = ds_to_priv(ds);
- priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
- if (!priv)
- return -ENOMEM;
+ if (!priv) {
+ /* Old method when dsa creates the switch */
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
- ds->priv = priv;
+ ds->priv = priv;
- priv->bus = dsa_host_dev_to_mii_bus(ds->master_dev);
- if (!priv->bus)
- return -ENODEV;
+ priv->bus = dsa_host_dev_to_mii_bus(ds->master_dev);
+ if (!priv->bus)
+ return -ENODEV;
- priv->sw_addr = ds->pd->sw_addr;
+ priv->sw_addr = ds->pd->sw_addr;
+ }
ret = mv88e6060_switch_reset(ds);
if (ret < 0)
@@ -252,15 +264,95 @@ static struct dsa_switch_driver mv88e6060_switch_driver = {
.phy_write = mv88e6060_phy_write,
};
+static int mv88e6060_bind(struct device *dev,
+ struct device *master, void *data)
+{
+ struct mdio_device *mdiodev = to_mdio_device(dev);
+ struct dsa_switch_tree *dst = data;
+ struct mv88e6060_priv *priv;
+ struct device_node *np = dev->of_node;
+ struct dsa_switch *ds;
+ const char *name;
+
+ ds = devm_kzalloc(dev, sizeof(*ds) + sizeof(*priv), GFP_KERNEL);
+ if (!ds)
+ return -ENOMEM;
+
+ priv = (struct mv88e6060_priv *)(ds + 1);
+ ds->priv = priv;
+ priv->bus = mdiodev->bus;
+ priv->sw_addr = mdiodev->addr;
+
+ get_device(&priv->bus->dev);
+
+ ds->drv = &mv88e6060_switch_driver;
+
+ name = mv88e6060_name(priv->bus, priv->sw_addr);
+ if (!name) {
+ dev_err(dev, "Failed to find switch");
+ return -ENODEV;
+ }
+
+ dev_set_drvdata(dev, ds);
+ dsa_switch_register(dst, ds, np, name);
+
+ return 0;
+}
+
+static void mv88e6060_unbind(struct device *dev, struct device *master,
+ void *data)
+{
+ struct dsa_switch *ds = dev_get_drvdata(dev);
+ struct mv88e6060_priv *priv = ds_to_priv(ds);
+
+ dsa_switch_unregister(ds);
+ put_device(&priv->bus->dev);
+}
+
+static const struct component_ops mv88e6060_component_ops = {
+ .bind = mv88e6060_bind,
+ .unbind = mv88e6060_unbind,
+};
+
+static int mv88e6060_remove(struct platform_device *pdev)
+{
+ component_del(&pdev->dev, &mv88e6060_component_ops);
+
+ return 0;
+}
+
+static int mv88e6060_probe(struct platform_device *pdev)
+{
+ return component_add(&pdev->dev, &mv88e6060_component_ops);
+}
+
+static const struct of_device_id mv88e6060_of_match[] = {
+ { .compatible = "marvell,mv88e6060" },
+ { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, mv88e6060_of_match);
+
+static struct platform_driver mv88e6060_driver = {
+ .probe = mv88e6060_probe,
+ .remove = mv88e6060_remove,
+ .driver = {
+ .name = "mv88e6060",
+ .of_match_table = mv88e6060_of_match,
+ },
+};
+
static int __init mv88e6060_init(void)
{
register_switch_driver(&mv88e6060_switch_driver);
- return 0;
+
+ return platform_driver_register(&mv88e6060_driver);
}
module_init(mv88e6060_init);
static void __exit mv88e6060_cleanup(void)
{
+ platform_driver_unregister(&mv88e6060_driver);
+
unregister_switch_driver(&mv88e6060_switch_driver);
}
module_exit(mv88e6060_cleanup);
diff --git a/drivers/net/dsa/mv88e6123.c b/drivers/net/dsa/mv88e6123.c
index 2c23762cbed8..4c488f9f2a34 100644
--- a/drivers/net/dsa/mv88e6123.c
+++ b/drivers/net/dsa/mv88e6123.c
@@ -1,6 +1,7 @@
/*
* net/dsa/mv88e6123_61_65.c - Marvell 88e6123/6161/6165 switch chip support
* Copyright (c) 2008-2009 Marvell Semiconductor
+ * Copyright (c) 2015 Andrew Lunn <andrew@lunn.ch>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -8,9 +9,11 @@
* (at your option) any later version.
*/
+#include <linux/component.h>
#include <linux/delay.h>
#include <linux/jiffies.h>
#include <linux/list.h>
+#include <linux/mdio.h>
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/phy.h>
@@ -121,6 +124,47 @@ struct dsa_switch_driver mv88e6123_switch_driver = {
.get_regs = mv88e6xxx_get_regs,
};
-MODULE_ALIAS("platform:mv88e6123");
-MODULE_ALIAS("platform:mv88e6161");
-MODULE_ALIAS("platform:mv88e6165");
+static int mv88e6123_bind(struct device *dev,
+ struct device *master, void *data)
+{
+ struct dsa_switch_tree *dst = data;
+
+ return mv88e6xxx_bind(dev, dst, &mv88e6123_switch_driver,
+ mv88e6123_table,
+ ARRAY_SIZE(mv88e6123_table));
+}
+
+static const struct component_ops mv88e6123_component_ops = {
+ .bind = mv88e6123_bind,
+ .unbind = mv88e6xxx_unbind,
+};
+
+static void mv88e6123_remove(struct mdio_device *mdiodev)
+{
+ component_del(&mdiodev->dev, &mv88e6123_component_ops);
+}
+
+static int mv88e6123_probe(struct mdio_device *mdiodev)
+{
+ return component_add(&mdiodev->dev, &mv88e6123_component_ops);
+}
+
+static const struct of_device_id mv88e6123_of_match[] = {
+ { .compatible = "marvell,mv88e6123" },
+ { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, mv88e6123_of_match);
+
+static struct mdio_driver mv88e6123_driver = {
+ .probe = mv88e6123_probe,
+ .remove = mv88e6123_remove,
+ .mdiodrv.driver = {
+ .name = "mv88e6123",
+ .of_match_table = mv88e6123_of_match,
+ },
+};
+
+mv88e6xxx_module_driver(mv88e6123_driver, mv88e6123_switch_driver);
+
+MODULE_DESCRIPTION("Driver for Marvell 6123 family ethernet switch chips");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/dsa/mv88e6131.c b/drivers/net/dsa/mv88e6131.c
index 02d2bca095af..e5a4e2b11322 100644
--- a/drivers/net/dsa/mv88e6131.c
+++ b/drivers/net/dsa/mv88e6131.c
@@ -1,6 +1,7 @@
/*
* net/dsa/mv88e6131.c - Marvell 88e6095/6095f/6131 switch chip support
* Copyright (c) 2008-2009 Marvell Semiconductor
+ * Copyright (c) 2015 Andrew Lunn <andrew@lunn.ch>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -8,9 +9,11 @@
* (at your option) any later version.
*/
+#include <linux/component.h>
#include <linux/delay.h>
#include <linux/jiffies.h>
#include <linux/list.h>
+#include <linux/mdio.h>
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/phy.h>
@@ -173,7 +176,47 @@ struct dsa_switch_driver mv88e6131_switch_driver = {
.adjust_link = mv88e6xxx_adjust_link,
};
-MODULE_ALIAS("platform:mv88e6085");
-MODULE_ALIAS("platform:mv88e6095");
-MODULE_ALIAS("platform:mv88e6095f");
-MODULE_ALIAS("platform:mv88e6131");
+static int mv88e6131_bind(struct device *dev,
+ struct device *master, void *data)
+{
+ struct dsa_switch_tree *dst = data;
+
+ return mv88e6xxx_bind(dev, dst, &mv88e6131_switch_driver,
+ mv88e6131_table,
+ ARRAY_SIZE(mv88e6131_table));
+}
+
+static const struct component_ops mv88e6131_component_ops = {
+ .bind = mv88e6131_bind,
+ .unbind = mv88e6xxx_unbind,
+};
+
+static void mv88e6131_remove(struct mdio_device *mdiodev)
+{
+ component_del(&mdiodev->dev, &mv88e6131_component_ops);
+}
+
+static int mv88e6131_probe(struct mdio_device *mdiodev)
+{
+ return component_add(&mdiodev->dev, &mv88e6131_component_ops);
+}
+
+static const struct of_device_id mv88e6131_of_match[] = {
+ { .compatible = "marvell,mv88e6131" },
+ { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, mv88e6131_of_match);
+
+static struct mdio_driver mv88e6131_driver = {
+ .probe = mv88e6131_probe,
+ .remove = mv88e6131_remove,
+ .mdiodrv.driver = {
+ .name = "mv88e6131",
+ .of_match_table = mv88e6131_of_match,
+ },
+};
+
+mv88e6xxx_module_driver(mv88e6131_driver, mv88e6131_switch_driver);
+
+MODULE_DESCRIPTION("Driver for Marvell 6131 family ethernet switch chips");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/dsa/mv88e6171.c b/drivers/net/dsa/mv88e6171.c
index d557be12feb7..249c2c075a2d 100644
--- a/drivers/net/dsa/mv88e6171.c
+++ b/drivers/net/dsa/mv88e6171.c
@@ -1,6 +1,7 @@
/* net/dsa/mv88e6171.c - Marvell 88e6171 switch chip support
* Copyright (c) 2008-2009 Marvell Semiconductor
* Copyright (c) 2014 Claudio Leite <leitec@staticky.com>
+ * Copyright (c) 2015 Andrew Lunn <andrew@lunn.ch>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -8,9 +9,11 @@
* (at your option) any later version.
*/
+#include <linux/component.h>
#include <linux/delay.h>
#include <linux/jiffies.h>
#include <linux/list.h>
+#include <linux/mdio.h>
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/phy.h>
@@ -119,7 +122,47 @@ struct dsa_switch_driver mv88e6171_switch_driver = {
.port_fdb_dump = mv88e6xxx_port_fdb_dump,
};
-MODULE_ALIAS("platform:mv88e6171");
-MODULE_ALIAS("platform:mv88e6175");
-MODULE_ALIAS("platform:mv88e6350");
-MODULE_ALIAS("platform:mv88e6351");
+static int mv88e6171_bind(struct device *dev,
+ struct device *master, void *data)
+{
+ struct dsa_switch_tree *dst = data;
+
+ return mv88e6xxx_bind(dev, dst, &mv88e6171_switch_driver,
+ mv88e6171_table,
+ ARRAY_SIZE(mv88e6171_table));
+}
+
+static const struct component_ops mv88e6171_component_ops = {
+ .bind = mv88e6171_bind,
+ .unbind = mv88e6xxx_unbind,
+};
+
+static void mv88e6171_remove(struct mdio_device *mdiodev)
+{
+ component_del(&mdiodev->dev, &mv88e6171_component_ops);
+}
+
+static int mv88e6171_probe(struct mdio_device *mdiodev)
+{
+ return component_add(&mdiodev->dev, &mv88e6171_component_ops);
+}
+
+static const struct of_device_id mv88e6171_of_match[] = {
+ { .compatible = "marvell,mv88e6171" },
+ { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, mv88e6171_of_match);
+
+static struct mdio_driver mv88e6171_driver = {
+ .probe = mv88e6171_probe,
+ .remove = mv88e6171_remove,
+ .mdiodrv.driver = {
+ .name = "mv88e6171",
+ .of_match_table = mv88e6171_of_match,
+ },
+};
+
+mv88e6xxx_module_driver(mv88e6171_driver, mv88e6171_switch_driver);
+
+MODULE_DESCRIPTION("Driver for Marvell 6171 family ethernet switch chips");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/dsa/mv88e6352.c b/drivers/net/dsa/mv88e6352.c
index 959835d69af6..0d245f76e557 100644
--- a/drivers/net/dsa/mv88e6352.c
+++ b/drivers/net/dsa/mv88e6352.c
@@ -2,6 +2,7 @@
* net/dsa/mv88e6352.c - Marvell 88e6352 switch chip support
*
* Copyright (c) 2014 Guenter Roeck
+ * Copyright (c) 2015 Andrew Lunn <andrew@lunn.ch>
*
* Derived from mv88e6123_61_65.c
* Copyright (c) 2008-2009 Marvell Semiconductor
@@ -12,12 +13,13 @@
* (at your option) any later version.
*/
+#include <linux/component.h>
#include <linux/delay.h>
#include <linux/jiffies.h>
#include <linux/list.h>
+#include <linux/mdio.h>
#include <linux/module.h>
#include <linux/netdevice.h>
-#include <linux/platform_device.h>
#include <linux/phy.h>
#include <net/dsa.h>
#include "mv88e6xxx.h"
@@ -339,8 +341,47 @@ struct dsa_switch_driver mv88e6352_switch_driver = {
.port_fdb_dump = mv88e6xxx_port_fdb_dump,
};
-MODULE_ALIAS("platform:mv88e6172");
-MODULE_ALIAS("platform:mv88e6176");
-MODULE_ALIAS("platform:mv88e6320");
-MODULE_ALIAS("platform:mv88e6321");
-MODULE_ALIAS("platform:mv88e6352");
+static int mv88e6352_bind(struct device *dev,
+ struct device *master, void *data)
+{
+ struct dsa_switch_tree *dst = data;
+
+ return mv88e6xxx_bind(dev, dst, &mv88e6352_switch_driver,
+ mv88e6352_table,
+ ARRAY_SIZE(mv88e6352_table));
+}
+
+static const struct component_ops mv88e6352_component_ops = {
+ .bind = mv88e6352_bind,
+ .unbind = mv88e6xxx_unbind,
+};
+
+static void mv88e6352_remove(struct mdio_device *mdiodev)
+{
+ component_del(&mdiodev->dev, &mv88e6352_component_ops);
+}
+
+static int mv88e6352_probe(struct mdio_device *mdiodev)
+{
+ return component_add(&mdiodev->dev, &mv88e6352_component_ops);
+}
+
+static const struct of_device_id mv88e6352_of_match[] = {
+ { .compatible = "marvell,mv88e6352" },
+ { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, mv88e6352_of_match);
+
+static struct mdio_driver mv88e6352_driver = {
+ .probe = mv88e6352_probe,
+ .remove = mv88e6352_remove,
+ .mdiodrv.driver = {
+ .name = "mv88e6352",
+ .of_match_table = mv88e6352_of_match,
+ },
+};
+
+mv88e6xxx_module_driver(mv88e6352_driver, mv88e6352_switch_driver);
+
+MODULE_DESCRIPTION("Driver for Marvell 6352 family ethernet switch chips");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index b0838bf77fd9..3dca92b8d592 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -2755,41 +2755,6 @@ void mv88e6xxx_unbind(struct device *dev, struct device *master, void *data)
}
EXPORT_SYMBOL_GPL(mv88e6xxx_unbind);
-static int __init mv88e6xxx_init(void)
-{
-#if IS_ENABLED(CONFIG_NET_DSA_MV88E6131)
- register_switch_driver(&mv88e6131_switch_driver);
-#endif
-#if IS_ENABLED(CONFIG_NET_DSA_MV88E6123)
- register_switch_driver(&mv88e6123_switch_driver);
-#endif
-#if IS_ENABLED(CONFIG_NET_DSA_MV88E6352)
- register_switch_driver(&mv88e6352_switch_driver);
-#endif
-#if IS_ENABLED(CONFIG_NET_DSA_MV88E6171)
- register_switch_driver(&mv88e6171_switch_driver);
-#endif
- return 0;
-}
-module_init(mv88e6xxx_init);
-
-static void __exit mv88e6xxx_cleanup(void)
-{
-#if IS_ENABLED(CONFIG_NET_DSA_MV88E6171)
- unregister_switch_driver(&mv88e6171_switch_driver);
-#endif
-#if IS_ENABLED(CONFIG_NET_DSA_MV88E6352)
- unregister_switch_driver(&mv88e6352_switch_driver);
-#endif
-#if IS_ENABLED(CONFIG_NET_DSA_MV88E6123_61_65)
- unregister_switch_driver(&mv88e6123_61_65_switch_driver);
-#endif
-#if IS_ENABLED(CONFIG_NET_DSA_MV88E6131)
- unregister_switch_driver(&mv88e6131_switch_driver);
-#endif
-}
-module_exit(mv88e6xxx_cleanup);
-
MODULE_AUTHOR("Lennert Buytenhek <buytenh@wantstofly.org>");
MODULE_DESCRIPTION("Driver for Marvell 88E6XXX ethernet switch chips");
MODULE_LICENSE("GPL");
--
2.7.0
^ permalink raw reply related [flat|nested] 47+ messages in thread
* [PATCH RFC v2 21/32] net: mdio: Add mdiodev_{read|write} helpers
2016-02-28 16:41 [PATCH RFC v2 00/32] Make DSA switches linux devices Andrew Lunn
` (19 preceding siblings ...)
2016-02-28 16:41 ` [PATCH RFC v2 20/32] dsa: Add mdio device support to Marvell switches Andrew Lunn
@ 2016-02-28 16:41 ` Andrew Lunn
2016-02-28 16:41 ` [PATCH RFC v2 22/32] net: dsa: Better integrate the drivers with mdio device Andrew Lunn
` (11 subsequent siblings)
32 siblings, 0 replies; 47+ messages in thread
From: Andrew Lunn @ 2016-02-28 16:41 UTC (permalink / raw)
To: Florian Fainelli, Vivien Didelot, netdev; +Cc: Andrew Lunn
An mdio driver will want to perform reads/writes on its device.
Provide an abstraction over the mdiobus functions, which require more
knowledge of bus addresses.
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
---
drivers/net/phy/mdio_device.c | 68 +++++++++++++++++++++++++++++++++++++++++++
include/linux/mdio.h | 5 ++++
2 files changed, 73 insertions(+)
diff --git a/drivers/net/phy/mdio_device.c b/drivers/net/phy/mdio_device.c
index 9c88e6749b9a..5bf6a2b93773 100644
--- a/drivers/net/phy/mdio_device.c
+++ b/drivers/net/phy/mdio_device.c
@@ -23,6 +23,74 @@
#include <linux/string.h>
#include <linux/unistd.h>
+/**
+ * mdiodev_read_nested - Nested version of the mdiodev_read function
+ * @mdiodev: the mdio device to read
+ * @regnum: register number to read
+ *
+ * In case of nested MDIO bus access avoid lockdep false positives by
+ * using mutex_lock_nested().
+ *
+ * NOTE: MUST NOT be called from interrupt context,
+ * because the bus read/write functions may wait for an interrupt
+ * to conclude the operation.
+ */
+int mdiodev_read_nested(struct mdio_device *mdiodev, u32 regnum)
+{
+ return mdiobus_read_nested(mdiodev->bus, mdiodev->addr, regnum);
+}
+EXPORT_SYMBOL(mdiodev_read_nested);
+
+/**
+ * mdiodev_read - Convenience function for reading a given MII mgmt register
+ * @mdiodev: the mdio device to read
+ * @regnum: register number to read
+ *
+ * NOTE: MUST NOT be called from interrupt context,
+ * because the bus read/write functions may wait for an interrupt
+ * to conclude the operation.
+ */
+int mdiodev_read(struct mdio_device *mdiodev, u32 regnum)
+{
+ return mdiobus_read(mdiodev->bus, mdiodev->addr, regnum);
+}
+EXPORT_SYMBOL(mdiodev_read);
+
+/**
+ * mdiodev_write_nested - Nested version of the mdiodev_write function
+ * @mdiodev: the mdio device to read
+ * @regnum: register number to write
+ * @val: value to write to @regnum
+ *
+ * In case of nested MDIO bus access avoid lockdep false positives by
+ * using mutex_lock_nested().
+ *
+ * NOTE: MUST NOT be called from interrupt context,
+ * because the bus read/write functions may wait for an interrupt
+ * to conclude the operation.
+ */
+int mdiodev_write_nested(struct mdio_device *mdiodev, u32 regnum, u16 val)
+{
+ return mdiobus_write_nested(mdiodev->bus, mdiodev->addr, regnum, val);
+}
+EXPORT_SYMBOL(mdiodev_write_nested);
+
+/**
+ * mdiodev_write - Convenience function for writing a given MII mgmt register
+ * @mdiodev: the mdio device to read
+ * @regnum: register number to write
+ * @val: value to write to @regnum
+ *
+ * NOTE: MUST NOT be called from interrupt context,
+ * because the bus read/write functions may wait for an interrupt
+ * to conclude the operation.
+ */
+int mdiodev_write(struct mdio_device *mdiodev, u32 regnum, u16 val)
+{
+ return mdiobus_write(mdiodev->bus, mdiodev->addr, regnum, val);
+}
+EXPORT_SYMBOL(mdiodev_write);
+
void mdio_device_free(struct mdio_device *mdiodev)
{
put_device(&mdiodev->dev);
diff --git a/include/linux/mdio.h b/include/linux/mdio.h
index 5bfd99d1a40a..58e39fbaa3e8 100644
--- a/include/linux/mdio.h
+++ b/include/linux/mdio.h
@@ -227,6 +227,11 @@ int mdiobus_read_nested(struct mii_bus *bus, int addr, u32 regnum);
int mdiobus_write(struct mii_bus *bus, int addr, u32 regnum, u16 val);
int mdiobus_write_nested(struct mii_bus *bus, int addr, u32 regnum, u16 val);
+int mdiodev_read(struct mdio_device *mdiodev, u32 regnum);
+int mdiodev_read_nested(struct mdio_device *mdiodev, u32 regnum);
+int mdiodev_write(struct mdio_device *mdiodev, u32 regnum, u16 val);
+int mdiodev_write_nested(struct mdio_device *mdiodev, u32 regnum, u16 val);
+
int mdiobus_register_device(struct mdio_device *mdiodev);
int mdiobus_unregister_device(struct mdio_device *mdiodev);
bool mdiobus_is_registered_device(struct mii_bus *bus, int addr);
--
2.7.0
^ permalink raw reply related [flat|nested] 47+ messages in thread
* [PATCH RFC v2 22/32] net: dsa: Better integrate the drivers with mdio device
2016-02-28 16:41 [PATCH RFC v2 00/32] Make DSA switches linux devices Andrew Lunn
` (20 preceding siblings ...)
2016-02-28 16:41 ` [PATCH RFC v2 21/32] net: mdio: Add mdiodev_{read|write} helpers Andrew Lunn
@ 2016-02-28 16:41 ` Andrew Lunn
2016-02-28 16:41 ` [PATCH RFC v2 23/32] net: dsa: bcm_sf2: make it a real platform driver Andrew Lunn
` (10 subsequent siblings)
32 siblings, 0 replies; 47+ messages in thread
From: Andrew Lunn @ 2016-02-28 16:41 UTC (permalink / raw)
To: Florian Fainelli, Vivien Didelot, netdev; +Cc: Andrew Lunn
Don't unpack the mdiodev into its bus and address value. Rather keep
it is a core data structure for addressing. This does however mean
when the driver is instantiated the old way, we have to create a dummy
mdiodev structure.
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
---
drivers/net/dsa/mv88e6060.c | 27 ++++++++++--------
drivers/net/dsa/mv88e6060.h | 3 +-
drivers/net/dsa/mv88e6123.c | 7 +++--
drivers/net/dsa/mv88e6131.c | 7 +++--
drivers/net/dsa/mv88e6171.c | 7 +++--
drivers/net/dsa/mv88e6352.c | 7 +++--
drivers/net/dsa/mv88e6xxx.c | 68 +++++++++++++++++++++++----------------------
drivers/net/dsa/mv88e6xxx.h | 9 ++----
8 files changed, 74 insertions(+), 61 deletions(-)
diff --git a/drivers/net/dsa/mv88e6060.c b/drivers/net/dsa/mv88e6060.c
index 723273c8ff32..27834cac422f 100644
--- a/drivers/net/dsa/mv88e6060.c
+++ b/drivers/net/dsa/mv88e6060.c
@@ -24,7 +24,8 @@ static int reg_read(struct dsa_switch *ds, int addr, int reg)
{
struct mv88e6060_priv *priv = ds_to_priv(ds);
- return mdiobus_read_nested(priv->bus, priv->sw_addr + addr, reg);
+ return mdiobus_read_nested(priv->mdiodev->bus,
+ priv->mdiodev->addr + addr, reg);
}
#define REG_READ(addr, reg) \
@@ -42,7 +43,8 @@ static int reg_write(struct dsa_switch *ds, int addr, int reg, u16 val)
{
struct mv88e6060_priv *priv = ds_to_priv(ds);
- return mdiobus_write_nested(priv->bus, priv->sw_addr + addr, reg, val);
+ return mdiobus_write_nested(priv->mdiodev->bus,
+ priv->mdiodev->addr + addr, reg, val);
}
#define REG_WRITE(addr, reg, val) \
@@ -179,6 +181,7 @@ static int mv88e6060_setup(struct dsa_switch *ds, struct device *dev)
{
int i;
int ret;
+ struct mdio_device *mdiodev;
struct mv88e6060_priv *priv = ds_to_priv(ds);
if (!priv) {
@@ -187,13 +190,18 @@ static int mv88e6060_setup(struct dsa_switch *ds, struct device *dev)
if (!priv)
return -ENOMEM;
+ mdiodev = devm_kzalloc(dev, sizeof(*mdiodev), GFP_KERNEL);
+ if (!mdiodev)
+ return -ENOMEM;
+
ds->priv = priv;
- priv->bus = dsa_host_dev_to_mii_bus(ds->master_dev);
- if (!priv->bus)
+ mdiodev->bus = dsa_host_dev_to_mii_bus(ds->master_dev);
+ if (!mdiodev->bus)
return -ENODEV;
- priv->sw_addr = ds->pd->sw_addr;
+ mdiodev->addr = ds->pd->sw_addr;
+ priv->mdiodev = mdiodev;
}
ret = mv88e6060_switch_reset(ds);
@@ -280,14 +288,11 @@ static int mv88e6060_bind(struct device *dev,
priv = (struct mv88e6060_priv *)(ds + 1);
ds->priv = priv;
- priv->bus = mdiodev->bus;
- priv->sw_addr = mdiodev->addr;
-
- get_device(&priv->bus->dev);
+ priv->mdiodev = mdiodev;
ds->drv = &mv88e6060_switch_driver;
- name = mv88e6060_name(priv->bus, priv->sw_addr);
+ name = mv88e6060_name(priv->mdiodev->bus, priv->mdiodev->addr);
if (!name) {
dev_err(dev, "Failed to find switch");
return -ENODEV;
@@ -303,10 +308,8 @@ static void mv88e6060_unbind(struct device *dev, struct device *master,
void *data)
{
struct dsa_switch *ds = dev_get_drvdata(dev);
- struct mv88e6060_priv *priv = ds_to_priv(ds);
dsa_switch_unregister(ds);
- put_device(&priv->bus->dev);
}
static const struct component_ops mv88e6060_component_ops = {
diff --git a/drivers/net/dsa/mv88e6060.h b/drivers/net/dsa/mv88e6060.h
index 10249bd16292..bf0b8d5bde11 100644
--- a/drivers/net/dsa/mv88e6060.h
+++ b/drivers/net/dsa/mv88e6060.h
@@ -115,8 +115,7 @@ struct mv88e6060_priv {
* single address which contains two registers used for
* indirect access to more registers.
*/
- struct mii_bus *bus;
- int sw_addr;
+ struct mdio_device *mdiodev;
};
#endif
diff --git a/drivers/net/dsa/mv88e6123.c b/drivers/net/dsa/mv88e6123.c
index 4c488f9f2a34..76e88e037311 100644
--- a/drivers/net/dsa/mv88e6123.c
+++ b/drivers/net/dsa/mv88e6123.c
@@ -34,9 +34,12 @@ static const struct mv88e6xxx_switch_id mv88e6123_table[] = {
static char *mv88e6123_drv_probe(struct device *host_dev, int sw_addr)
{
- struct mii_bus *bus = dsa_host_dev_to_mii_bus(host_dev);
+ struct mdio_device mdiodev;
- return mv88e6xxx_lookup_name(bus, sw_addr, mv88e6123_table,
+ mdiodev.bus = dsa_host_dev_to_mii_bus(host_dev);
+ mdiodev.addr = sw_addr;
+
+ return mv88e6xxx_lookup_name(&mdiodev, mv88e6123_table,
ARRAY_SIZE(mv88e6123_table));
}
diff --git a/drivers/net/dsa/mv88e6131.c b/drivers/net/dsa/mv88e6131.c
index e5a4e2b11322..6696ce638bbc 100644
--- a/drivers/net/dsa/mv88e6131.c
+++ b/drivers/net/dsa/mv88e6131.c
@@ -30,9 +30,12 @@ static const struct mv88e6xxx_switch_id mv88e6131_table[] = {
static char *mv88e6131_drv_probe(struct device *host_dev, int sw_addr)
{
- struct mii_bus *bus = dsa_host_dev_to_mii_bus(host_dev);
+ struct mdio_device mdiodev;
- return mv88e6xxx_lookup_name(bus, sw_addr, mv88e6131_table,
+ mdiodev.bus = dsa_host_dev_to_mii_bus(host_dev);
+ mdiodev.addr = sw_addr;
+
+ return mv88e6xxx_lookup_name(&mdiodev, mv88e6131_table,
ARRAY_SIZE(mv88e6131_table));
}
diff --git a/drivers/net/dsa/mv88e6171.c b/drivers/net/dsa/mv88e6171.c
index 249c2c075a2d..de0ba67e34b8 100644
--- a/drivers/net/dsa/mv88e6171.c
+++ b/drivers/net/dsa/mv88e6171.c
@@ -29,9 +29,12 @@ static const struct mv88e6xxx_switch_id mv88e6171_table[] = {
static char *mv88e6171_drv_probe(struct device *host_dev, int sw_addr)
{
- struct mii_bus *bus = dsa_host_dev_to_mii_bus(host_dev);
+ struct mdio_device mdiodev;
- return mv88e6xxx_lookup_name(bus, sw_addr, mv88e6171_table,
+ mdiodev.bus = dsa_host_dev_to_mii_bus(host_dev);
+ mdiodev.addr = sw_addr;
+
+ return mv88e6xxx_lookup_name(&mdiodev, mv88e6171_table,
ARRAY_SIZE(mv88e6171_table));
}
diff --git a/drivers/net/dsa/mv88e6352.c b/drivers/net/dsa/mv88e6352.c
index 0d245f76e557..796558614964 100644
--- a/drivers/net/dsa/mv88e6352.c
+++ b/drivers/net/dsa/mv88e6352.c
@@ -40,9 +40,12 @@ static const struct mv88e6xxx_switch_id mv88e6352_table[] = {
static char *mv88e6352_drv_probe(struct device *host_dev, int sw_addr)
{
- struct mii_bus *bus = dsa_host_dev_to_mii_bus(host_dev);
+ struct mdio_device mdiodev;
- return mv88e6xxx_lookup_name(bus, sw_addr, mv88e6352_table,
+ mdiodev.bus = dsa_host_dev_to_mii_bus(host_dev);
+ mdiodev.addr = sw_addr;
+
+ return mv88e6xxx_lookup_name(&mdiodev, mv88e6352_table,
ARRAY_SIZE(mv88e6352_table));
}
diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index 3dca92b8d592..4f1da145b814 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -46,13 +46,13 @@ static void assert_smi_lock(struct dsa_switch *ds)
* an indirect addressing mechanism needs to be used to access its
* registers.
*/
-static int mv88e6xxx_reg_wait_ready(struct mii_bus *bus, int sw_addr)
+static int mv88e6xxx_reg_wait_ready(struct mdio_device *mdiodev)
{
int ret;
int i;
for (i = 0; i < 16; i++) {
- ret = mdiobus_read_nested(bus, sw_addr, SMI_CMD);
+ ret = mdiodev_read_nested(mdiodev, SMI_CMD);
if (ret < 0)
return ret;
@@ -63,32 +63,31 @@ static int mv88e6xxx_reg_wait_ready(struct mii_bus *bus, int sw_addr)
return -ETIMEDOUT;
}
-static int __mv88e6xxx_reg_read(struct mii_bus *bus, int sw_addr, int addr,
- int reg)
+static int __mv88e6xxx_reg_read(struct mdio_device *mdiodev, int addr, int reg)
{
int ret;
- if (sw_addr == 0)
- return mdiobus_read_nested(bus, addr, reg);
+ if (mdiodev->addr == 0)
+ return mdiobus_read_nested(mdiodev->bus, addr, reg);
/* Wait for the bus to become free. */
- ret = mv88e6xxx_reg_wait_ready(bus, sw_addr);
+ ret = mv88e6xxx_reg_wait_ready(mdiodev);
if (ret < 0)
return ret;
/* Transmit the read command. */
- ret = mdiobus_write_nested(bus, sw_addr, SMI_CMD,
+ ret = mdiodev_write_nested(mdiodev, SMI_CMD,
SMI_CMD_OP_22_READ | (addr << 5) | reg);
if (ret < 0)
return ret;
/* Wait for the read command to complete. */
- ret = mv88e6xxx_reg_wait_ready(bus, sw_addr);
+ ret = mv88e6xxx_reg_wait_ready(mdiodev);
if (ret < 0)
return ret;
/* Read the data. */
- ret = mdiobus_read_nested(bus, sw_addr, SMI_DATA);
+ ret = mdiodev_read_nested(mdiodev, SMI_DATA);
if (ret < 0)
return ret;
@@ -102,7 +101,7 @@ static int _mv88e6xxx_reg_read(struct dsa_switch *ds, int addr, int reg)
assert_smi_lock(ds);
- ret = __mv88e6xxx_reg_read(ps->bus, ps->sw_addr, addr, reg);
+ ret = __mv88e6xxx_reg_read(ps->mdiodev, addr, reg);
if (ret < 0)
return ret;
@@ -125,32 +124,32 @@ int mv88e6xxx_reg_read(struct dsa_switch *ds, int addr, int reg)
}
EXPORT_SYMBOL_GPL(mv88e6xxx_reg_read);
-static int __mv88e6xxx_reg_write(struct mii_bus *bus, int sw_addr, int addr,
+static int __mv88e6xxx_reg_write(struct mdio_device *mdiodev, int addr,
int reg, u16 val)
{
int ret;
- if (sw_addr == 0)
- return mdiobus_write_nested(bus, addr, reg, val);
+ if (mdiodev->addr == 0)
+ return mdiobus_write_nested(mdiodev->bus, addr, reg, val);
/* Wait for the bus to become free. */
- ret = mv88e6xxx_reg_wait_ready(bus, sw_addr);
+ ret = mv88e6xxx_reg_wait_ready(mdiodev);
if (ret < 0)
return ret;
/* Transmit the data to write. */
- ret = mdiobus_write_nested(bus, sw_addr, SMI_DATA, val);
+ ret = mdiodev_write_nested(mdiodev, SMI_DATA, val);
if (ret < 0)
return ret;
/* Transmit the write command. */
- ret = mdiobus_write_nested(bus, sw_addr, SMI_CMD,
+ ret = mdiodev_write_nested(mdiodev, SMI_CMD,
SMI_CMD_OP_22_WRITE | (addr << 5) | reg);
if (ret < 0)
return ret;
/* Wait for the write command to complete. */
- ret = mv88e6xxx_reg_wait_ready(bus, sw_addr);
+ ret = mv88e6xxx_reg_wait_ready(mdiodev);
if (ret < 0)
return ret;
@@ -167,7 +166,7 @@ static int _mv88e6xxx_reg_write(struct dsa_switch *ds, int addr, int reg,
dev_dbg(ds->master_dev, "-> addr: 0x%.2x reg: 0x%.2x val: 0x%.4x\n",
addr, reg, val);
- return __mv88e6xxx_reg_write(ps->bus, ps->sw_addr, addr, reg, val);
+ return __mv88e6xxx_reg_write(ps->mdiodev, addr, reg, val);
}
int mv88e6xxx_reg_write(struct dsa_switch *ds, int addr, int reg, u16 val)
@@ -2230,20 +2229,26 @@ EXPORT_SYMBOL_GPL(mv88e6xxx_setup_ports);
int mv88e6xxx_setup_common(struct dsa_switch *ds, struct device *dev)
{
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+ struct mdio_device *mdiodev;
if (!ps) {
+ /* Old method when dsa create the switch */
ps = devm_kzalloc(dev, sizeof(*ps), GFP_KERNEL);
if (!ps)
return -ENOMEM;
+ mdiodev = devm_kzalloc(dev, sizeof(*mdiodev), GFP_KERNEL);
+ if (!mdiodev)
+ return -ENOMEM;
+
ds->priv = ps;
ps->ds = ds;
-
- ps->bus = dsa_host_dev_to_mii_bus(ds->master_dev);
- if (!ps->bus)
+ mdiodev->bus = dsa_host_dev_to_mii_bus(ds->master_dev);
+ if (!mdiodev->bus)
return -ENODEV;
- ps->sw_addr = ds->pd->sw_addr;
+ mdiodev->addr = ds->pd->sw_addr;
+ ps->mdiodev = mdiodev;
}
mutex_init(&ps->smi_mutex);
@@ -2671,16 +2676,16 @@ int mv88e6xxx_get_temp_alarm(struct dsa_switch *ds, bool *alarm)
EXPORT_SYMBOL_GPL(mv88e6xxx_get_temp_alarm);
#endif /* CONFIG_NET_DSA_HWMON */
-char *mv88e6xxx_lookup_name(struct mii_bus *bus, int sw_addr,
+char *mv88e6xxx_lookup_name(struct mdio_device *mdiodev,
const struct mv88e6xxx_switch_id *table,
unsigned int num)
{
int i, ret;
- if (!bus)
+ if (!mdiodev->bus)
return NULL;
- ret = __mv88e6xxx_reg_read(bus, sw_addr, REG_PORT(0), PORT_SWITCH_ID);
+ ret = __mv88e6xxx_reg_read(mdiodev, REG_PORT(0), PORT_SWITCH_ID);
if (ret < 0)
return NULL;
@@ -2692,7 +2697,7 @@ char *mv88e6xxx_lookup_name(struct mii_bus *bus, int sw_addr,
/* Look up only the product number */
for (i = 0; i < num; ++i) {
if (table[i].id == (ret & PORT_SWITCH_ID_PROD_NUM_MASK)) {
- dev_warn(&bus->dev,
+ dev_warn(&mdiodev->bus->dev,
"unknown revision %d, using base switch 0x%x\n",
ret & PORT_SWITCH_ID_REV_MASK,
ret & PORT_SWITCH_ID_PROD_NUM_MASK);
@@ -2723,14 +2728,11 @@ int mv88e6xxx_bind(struct device *dev,
ps = (struct mv88e6xxx_priv_state *)(ds + 1);
ds->priv = ps;
ps->ds = ds;
- ps->bus = mdiodev->bus;
- ps->sw_addr = mdiodev->addr;
-
- get_device(&ps->bus->dev);
+ ps->mdiodev = mdiodev;
ds->drv = ops;
- name = mv88e6xxx_lookup_name(ps->bus, ps->sw_addr, table, table_size);
+ name = mv88e6xxx_lookup_name(mdiodev, table, table_size);
if (!name) {
dev_err(dev, "Failed to find switch");
return -ENODEV;
@@ -2751,7 +2753,7 @@ void mv88e6xxx_unbind(struct device *dev, struct device *master, void *data)
dsa_switch_unregister(ds);
devm_kfree(dev, ds);
- put_device(&ps->bus->dev);
+ put_device(&ps->mdiodev->bus->dev);
}
EXPORT_SYMBOL_GPL(mv88e6xxx_unbind);
diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h
index ce05964da85f..27e7faf619e9 100644
--- a/drivers/net/dsa/mv88e6xxx.h
+++ b/drivers/net/dsa/mv88e6xxx.h
@@ -389,11 +389,8 @@ struct mv88e6xxx_priv_state {
*/
struct mutex smi_mutex;
- /* The MII bus and the address on the bus that is used to
- * communication with the switch
- */
- struct mii_bus *bus;
- int sw_addr;
+ /* Which mdio device is this switch? */
+ struct mdio_device *mdiodev;
#ifdef CONFIG_NET_DSA_MV88E6XXX_NEED_PPU
/* Handles automatic disabling and re-enabling of the PHY
@@ -444,7 +441,7 @@ struct mv88e6xxx_hw_stat {
};
int mv88e6xxx_switch_reset(struct dsa_switch *ds, bool ppu_active);
-char *mv88e6xxx_lookup_name(struct mii_bus *bus, int sw_addr,
+char *mv88e6xxx_lookup_name(struct mdio_device *mdiodev,
const struct mv88e6xxx_switch_id *table,
unsigned int num);
int mv88e6xxx_bind(struct device *dev, struct dsa_switch_tree *dst,
--
2.7.0
^ permalink raw reply related [flat|nested] 47+ messages in thread
* [PATCH RFC v2 23/32] net: dsa: bcm_sf2: make it a real platform driver
2016-02-28 16:41 [PATCH RFC v2 00/32] Make DSA switches linux devices Andrew Lunn
` (21 preceding siblings ...)
2016-02-28 16:41 ` [PATCH RFC v2 22/32] net: dsa: Better integrate the drivers with mdio device Andrew Lunn
@ 2016-02-28 16:41 ` Andrew Lunn
2016-03-03 18:33 ` Florian Fainelli
2016-02-28 16:41 ` [PATCH RFC v2 24/32] net: dsa: Add some debug prints for error cases Andrew Lunn
` (9 subsequent siblings)
32 siblings, 1 reply; 47+ messages in thread
From: Andrew Lunn @ 2016-02-28 16:41 UTC (permalink / raw)
To: Florian Fainelli, Vivien Didelot, netdev; +Cc: Andrew Lunn
From: Florian Fainelli <f.fainelli@gmail.com>
The Broadcom Starfighter 2 switch driver should be a proper platform
driver, now that the DSA code has been updated to allow that, register
a switch device, feed it with the proper configuration data coming
from Device Tree and register our switch device with DSA.
The bulk of the changes consist in moving what bcm_sf2_sw_setup() did
into the component slave bind function.
This change does not however prevent the old DSA binding from working.
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
---
.../devicetree/bindings/net/dsa/broadcom.txt | 54 ++++
drivers/net/dsa/bcm_sf2.c | 293 ++++++++++++---------
2 files changed, 224 insertions(+), 123 deletions(-)
create mode 100644 Documentation/devicetree/bindings/net/dsa/broadcom.txt
diff --git a/Documentation/devicetree/bindings/net/dsa/broadcom.txt b/Documentation/devicetree/bindings/net/dsa/broadcom.txt
new file mode 100644
index 000000000000..ea7c40b611fc
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/dsa/broadcom.txt
@@ -0,0 +1,54 @@
+* Broadcom Starfighter 2 integrated switch device
+
+WARNING: This binding is currently UNSTABLE. Do not write it into a
+FLASH never to be upgraded. Once it is stable, this warning will be
+removed.
+
+If you need a stable binding, see the old dsa.txt.
+
+Required properties:
+
+- compatible: should be "brcm,brcm-sf2"
+- reg: addresses and length of the register sets for the device, must be 6
+ pairs of register addresses and lengths
+- interrupts: interrupts for the devices, must be two interrupts
+
+- reg-names: litteral names for the device base register addresses,
+ when present must be: "core", "reg", "intrl2_0", "intrl2_1", "fcb",
+ "acb"
+
+- interrupt-names: litternal names for the device interrupt lines,
+ when present must be: "switch_0" and "switch_1"
+
+- brcm,num-gphy: specify the maximum number of integrated gigabit PHYs
+ in the switch
+
+Optional properties:
+
+- brcm,num-rgmii-ports: specify the maximum number of RGMII interfaces
+ supported by the switch
+
+- brcm,fcb-pause-override: boolean property, if present indicates that
+ the switch supports Failover Control Block pause override capability
+
+- brcm,acb-packets-inflight: boolean property, if present indicates
+ that the switch Admission Control Block supports reporting the
+ number of packets in-flight in a switch queue
+
+Example:
+
+ switchdev0: switchdev0 {
+ compatible = "brcm,brcm-sf2";
+ reg = <0x0 0x40000
+ 0x40000 0x110
+ 0x40340 0x30
+ 0x40380 0x30
+ 0x40400 0x34
+ 0x40600 0x208>;
+ interrupts = <0 0x18 0
+ 0 0x19 0>;
+ brcm,num-gphy = <1>;
+ brcm,num-rgmii-ports = <2>;
+ brcm,fcb-pause-override;
+ brcm,acb-packets-inflight;
+ };
diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c
index c0c83c2f2691..b23b044d8401 100644
--- a/drivers/net/dsa/bcm_sf2.c
+++ b/drivers/net/dsa/bcm_sf2.c
@@ -9,6 +9,7 @@
* (at your option) any later version.
*/
+#include <linux/component.h>
#include <linux/list.h>
#include <linux/module.h>
#include <linux/netdevice.h>
@@ -928,83 +929,8 @@ static void bcm_sf2_identify_ports(struct bcm_sf2_priv *priv,
static int bcm_sf2_sw_setup(struct dsa_switch *ds, struct device *dev)
{
- const char *reg_names[BCM_SF2_REGS_NUM] = BCM_SF2_REGS_NAME;
- struct bcm_sf2_priv *priv;
- struct device_node *dn;
- void __iomem **base;
- unsigned int port;
- unsigned int i;
- u32 reg, rev;
- int ret;
-
- priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
- if (!priv)
- return -ENOMEM;
-
- ds->priv = priv;
-
- spin_lock_init(&priv->indir_lock);
- mutex_init(&priv->stats_mutex);
-
- /* All the interesting properties are at the parent device_node
- * level
- */
- dn = ds->pd->of_node->parent;
- bcm_sf2_identify_ports(priv, ds->pd->of_node);
-
- priv->irq0 = irq_of_parse_and_map(dn, 0);
- priv->irq1 = irq_of_parse_and_map(dn, 1);
-
- base = &priv->core;
- for (i = 0; i < BCM_SF2_REGS_NUM; i++) {
- *base = of_iomap(dn, i);
- if (*base == NULL) {
- pr_err("unable to find register: %s\n", reg_names[i]);
- ret = -ENOMEM;
- goto out_unmap;
- }
- base++;
- }
-
- ret = bcm_sf2_sw_rst(priv);
- if (ret) {
- pr_err("unable to software reset switch: %d\n", ret);
- goto out_unmap;
- }
-
- /* Disable all interrupts and request them */
- bcm_sf2_intr_disable(priv);
-
- ret = request_irq(priv->irq0, bcm_sf2_switch_0_isr, 0,
- "switch_0", priv);
- if (ret < 0) {
- pr_err("failed to request switch_0 IRQ\n");
- goto out_unmap;
- }
-
- ret = request_irq(priv->irq1, bcm_sf2_switch_1_isr, 0,
- "switch_1", priv);
- if (ret < 0) {
- pr_err("failed to request switch_1 IRQ\n");
- goto out_free_irq0;
- }
-
- /* Reset the MIB counters */
- reg = core_readl(priv, CORE_GMNCFGCFG);
- reg |= RST_MIB_CNT;
- core_writel(priv, reg, CORE_GMNCFGCFG);
- reg &= ~RST_MIB_CNT;
- core_writel(priv, reg, CORE_GMNCFGCFG);
-
- /* Get the maximum number of ports for this switch */
- priv->hw_params.num_ports = core_readl(priv, CORE_IMP0_PRT_ID) + 1;
- if (priv->hw_params.num_ports > DSA_MAX_PORTS)
- priv->hw_params.num_ports = DSA_MAX_PORTS;
-
- /* Assume a single GPHY setup if we can't read that property */
- if (of_property_read_u32(dn, "brcm,num-gphy",
- &priv->hw_params.num_gphy))
- priv->hw_params.num_gphy = 1;
+ struct bcm_sf2_priv *priv = ds_to_priv(ds);
+ int port;
/* Enable all valid ports and disable those unused */
for (port = 0; port < priv->hw_params.num_ports; port++) {
@@ -1017,47 +943,7 @@ static int bcm_sf2_sw_setup(struct dsa_switch *ds, struct device *dev)
bcm_sf2_port_disable(ds, port, NULL);
}
- /* Include the pseudo-PHY address and the broadcast PHY address to
- * divert reads towards our workaround. This is only required for
- * 7445D0, since 7445E0 disconnects the internal switch pseudo-PHY such
- * that we can use the regular SWITCH_MDIO master controller instead.
- *
- * By default, DSA initializes ds->phys_mii_mask to ds->phys_port_mask
- * to have a 1:1 mapping between Port address and PHY address in order
- * to utilize the slave_mii_bus instance to read from Port PHYs. This is
- * not what we want here, so we initialize phys_mii_mask 0 to always
- * utilize the "master" MDIO bus backed by the "mdio-unimac" driver.
- */
- if (of_machine_is_compatible("brcm,bcm7445d0"))
- ds->phys_mii_mask |= ((1 << BRCM_PSEUDO_PHY_ADDR) | (1 << 0));
- else
- ds->phys_mii_mask = 0;
-
- rev = reg_readl(priv, REG_SWITCH_REVISION);
- priv->hw_params.top_rev = (rev >> SWITCH_TOP_REV_SHIFT) &
- SWITCH_TOP_REV_MASK;
- priv->hw_params.core_rev = (rev & SF2_REV_MASK);
-
- rev = reg_readl(priv, REG_PHY_REVISION);
- priv->hw_params.gphy_rev = rev & PHY_REVISION_MASK;
-
- pr_info("Starfighter 2 top: %x.%02x, core: %x.%02x base: 0x%p, IRQs: %d, %d\n",
- priv->hw_params.top_rev >> 8, priv->hw_params.top_rev & 0xff,
- priv->hw_params.core_rev >> 8, priv->hw_params.core_rev & 0xff,
- priv->core, priv->irq0, priv->irq1);
-
return 0;
-
-out_free_irq0:
- free_irq(priv->irq0, priv);
-out_unmap:
- base = &priv->core;
- for (i = 0; i < BCM_SF2_REGS_NUM; i++) {
- if (*base)
- iounmap(*base);
- base++;
- }
- return ret;
}
static int bcm_sf2_sw_set_addr(struct dsa_switch *ds, u8 *addr)
@@ -1399,19 +1285,180 @@ static struct dsa_switch_driver bcm_sf2_switch_driver = {
.port_fdb_dump = bcm_sf2_sw_fdb_dump,
};
-static int __init bcm_sf2_init(void)
+static int bcm_sf2_sw_bind(struct device *dev,
+ struct device *master, void *data)
{
- register_switch_driver(&bcm_sf2_switch_driver);
+ const char *reg_names[BCM_SF2_REGS_NUM] = BCM_SF2_REGS_NAME;
+ struct platform_device *pdev = to_platform_device(dev);
+ struct dsa_switch_tree *dst = data;
+ struct bcm_sf2_priv *priv;
+ struct device_node *dn;
+ struct dsa_switch *ds;
+ void __iomem **base;
+ unsigned int i;
+ u32 reg, rev;
+ int ret;
+
+ ds = devm_kzalloc(&pdev->dev, sizeof(*ds) + sizeof(*priv), GFP_KERNEL);
+ if (!ds)
+ return -ENOMEM;
+
+ priv = (struct bcm_sf2_priv *)(ds + 1);
+ ds->priv = priv;
+ ds->drv = &bcm_sf2_switch_driver;
+
+ spin_lock_init(&priv->indir_lock);
+ mutex_init(&priv->stats_mutex);
+
+ /* All the interesting properties are at the parent device_node
+ * level
+ */
+ dn = ds->pd->of_node->parent;
+ bcm_sf2_identify_ports(priv, ds->pd->of_node);
+
+ priv->irq0 = irq_of_parse_and_map(dn, 0);
+ priv->irq1 = irq_of_parse_and_map(dn, 1);
+
+ base = &priv->core;
+ for (i = 0; i < BCM_SF2_REGS_NUM; i++) {
+ *base = of_iomap(dn, i);
+ if (!base) {
+ pr_err("unable to find register: %s\n", reg_names[i]);
+ ret = -ENOMEM;
+ goto out_unmap;
+ }
+ base++;
+ }
+
+ ret = bcm_sf2_sw_rst(priv);
+ if (ret) {
+ pr_err("unable to software reset switch: %d\n", ret);
+ goto out_unmap;
+ }
+
+ /* Disable all interrupts and request them */
+ bcm_sf2_intr_disable(priv);
+
+ ret = request_irq(priv->irq0, bcm_sf2_switch_0_isr, 0,
+ "switch_0", priv);
+ if (ret < 0) {
+ pr_err("failed to request switch_0 IRQ\n");
+ goto out_unmap;
+ }
+
+ ret = request_irq(priv->irq1, bcm_sf2_switch_1_isr, 0,
+ "switch_1", priv);
+ if (ret < 0) {
+ pr_err("failed to request switch_1 IRQ\n");
+ goto out_free_irq0;
+ }
+
+ /* Reset the MIB counters */
+ reg = core_readl(priv, CORE_GMNCFGCFG);
+ reg |= RST_MIB_CNT;
+ core_writel(priv, reg, CORE_GMNCFGCFG);
+ reg &= ~RST_MIB_CNT;
+ core_writel(priv, reg, CORE_GMNCFGCFG);
+
+ /* Get the maximum number of ports for this switch */
+ priv->hw_params.num_ports = core_readl(priv, CORE_IMP0_PRT_ID) + 1;
+ if (priv->hw_params.num_ports > DSA_MAX_PORTS)
+ priv->hw_params.num_ports = DSA_MAX_PORTS;
+
+ /* Assume a single GPHY setup if we can't read that property */
+ if (of_property_read_u32(dn, "brcm,num-gphy",
+ &priv->hw_params.num_gphy))
+ priv->hw_params.num_gphy = 1;
+
+ /* Include the pseudo-PHY address and the broadcast PHY address to
+ * divert reads towards our workaround. This is only required for
+ * 7445D0, since 7445E0 disconnects the internal switch pseudo-PHY such
+ * that we can use the regular SWITCH_MDIO master controller instead.
+ *
+ * By default, DSA initializes ds->phys_mii_mask to ds->phys_port_mask
+ * to have a 1:1 mapping between Port address and PHY address in order
+ * to utilize the slave_mii_bus instance to read from Port PHYs. This is
+ * not what we want here, so we initialize phys_mii_mask 0 to always
+ * utilize the "master" MDIO bus backed by the "mdio-unimac" driver.
+ */
+ if (of_machine_is_compatible("brcm,bcm7445d0"))
+ ds->phys_mii_mask |= ((1 << BRCM_PSEUDO_PHY_ADDR) | (1 << 0));
+ else
+ ds->phys_mii_mask = 0;
+
+ rev = reg_readl(priv, REG_SWITCH_REVISION);
+ priv->hw_params.top_rev = (rev >> SWITCH_TOP_REV_SHIFT) &
+ SWITCH_TOP_REV_MASK;
+ priv->hw_params.core_rev = (rev & SF2_REV_MASK);
+
+ rev = reg_readl(priv, REG_PHY_REVISION);
+ priv->hw_params.gphy_rev = rev & PHY_REVISION_MASK;
+
+ pr_info("Starfighter 2 top: %x.%02x, core: %x.%02x base: 0x%p, IRQs: %d, %d\n",
+ priv->hw_params.top_rev >> 8, priv->hw_params.top_rev & 0xff,
+ priv->hw_params.core_rev >> 8, priv->hw_params.core_rev & 0xff,
+ priv->core, priv->irq0, priv->irq1);
+
+ platform_set_drvdata(pdev, ds);
+
+ return dsa_switch_register(dst, ds, dn, "Starfighter 2");
+
+out_free_irq0:
+ free_irq(priv->irq0, priv);
+out_unmap:
+ base = &priv->core;
+ for (i = 0; i < BCM_SF2_REGS_NUM; i++) {
+ if (*base)
+ iounmap(*base);
+ base++;
+ }
+ return ret;
+}
+
+static void bcm_sf2_sw_unbind(struct device *dev,
+ struct device *master, void *data)
+{
+ struct dsa_switch *ds = dev_get_drvdata(dev);
+ struct bcm_sf2_priv *priv = ds_to_priv(ds);
+
+ /* Disable all ports and interrupts */
+ priv->wol_ports_mask = 0;
+ bcm_sf2_sw_suspend(ds);
+ dsa_switch_unregister(ds);
+}
+
+static const struct component_ops bcm_sf2_component_ops = {
+ .bind = bcm_sf2_sw_bind,
+ .unbind = bcm_sf2_sw_unbind,
+};
+
+static int bcm_sf2_sw_remove(struct platform_device *pdev)
+{
+ component_del(&pdev->dev, &bcm_sf2_component_ops);
return 0;
}
-module_init(bcm_sf2_init);
-static void __exit bcm_sf2_exit(void)
+static int bcm_sf2_sw_probe(struct platform_device *pdev)
{
- unregister_switch_driver(&bcm_sf2_switch_driver);
+ return component_add(&pdev->dev, &bcm_sf2_component_ops);
}
-module_exit(bcm_sf2_exit);
+
+static const struct of_device_id bcm_sf2_of_match[] = {
+ { .compatible = "brcm,brcm-sf2" },
+ { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, bcm_sf2_of_match);
+
+static struct platform_driver bcm_sf2_driver = {
+ .probe = bcm_sf2_sw_probe,
+ .remove = bcm_sf2_sw_remove,
+ .driver = {
+ .name = "brcm-sf2",
+ .of_match_table = bcm_sf2_of_match,
+ },
+};
+module_platform_driver(bcm_sf2_driver);
MODULE_AUTHOR("Broadcom Corporation");
MODULE_DESCRIPTION("Driver for Broadcom Starfighter 2 ethernet switch chip");
--
2.7.0
^ permalink raw reply related [flat|nested] 47+ messages in thread
* [PATCH RFC v2 24/32] net: dsa: Add some debug prints for error cases
2016-02-28 16:41 [PATCH RFC v2 00/32] Make DSA switches linux devices Andrew Lunn
` (22 preceding siblings ...)
2016-02-28 16:41 ` [PATCH RFC v2 23/32] net: dsa: bcm_sf2: make it a real platform driver Andrew Lunn
@ 2016-02-28 16:41 ` Andrew Lunn
2016-02-28 16:41 ` [PATCH RFC v2 25/32] net: dsa: Setup the switches after all have been probed Andrew Lunn
` (8 subsequent siblings)
32 siblings, 0 replies; 47+ messages in thread
From: Andrew Lunn @ 2016-02-28 16:41 UTC (permalink / raw)
To: Florian Fainelli, Vivien Didelot, netdev; +Cc: Andrew Lunn
Due to the complexity it can be hard to know why DSA fails to probe.
Add some debug prints for the common error cases.
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
Acked-by: Florian Fainelli <f.fainelli@gmail.com>
---
net/dsa/dsa.c | 13 ++++++++++---
1 file changed, 10 insertions(+), 3 deletions(-)
diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c
index 0be85a14a835..9acfbe7c34f7 100644
--- a/net/dsa/dsa.c
+++ b/net/dsa/dsa.c
@@ -679,6 +679,7 @@ static int dsa_of_probe(struct device *dev, struct dsa_platform_data *pd)
ethernet = of_parse_phandle(np, "dsa,ethernet", 0);
if (!ethernet) {
+ dev_dbg(dev, "Missing mandatory dsa,ethernet property\n");
ret = -EINVAL;
goto out_put_mdio;
}
@@ -710,8 +711,10 @@ static int dsa_of_probe(struct device *dev, struct dsa_platform_data *pd)
if (chip) {
cd->of_chip = chip;
} else {
- if (!mdio)
+ if (!mdio) {
+ dev_dbg(dev, "Missing required dsa,mii-bus property\n");
return -EINVAL;
+ }
mdio_bus = of_mdio_find_bus(mdio);
if (!mdio_bus)
@@ -1018,14 +1021,18 @@ int dsa_switch_register(struct dsa_switch_tree *dst, struct dsa_switch *ds,
struct dsa_platform_data *pd = dst->pd;
int index = dsa_find_chip_index(dst, np);
- if (index < 0)
+ if (index < 0) {
+ netdev_dbg(dst->master_netdev, "Registration for unknown switch\n");
return index;
+ }
netdev_info(dst->master_netdev, "[%d]: detected a %s switch\n",
index, name);
- if (dst->ds[index])
+ if (dst->ds[index]) {
+ netdev_dbg(dst->master_netdev, "Device already registered\n");
return -EINVAL;
+ }
ds->index = index;
ds->pd = &pd->chip[index];
--
2.7.0
^ permalink raw reply related [flat|nested] 47+ messages in thread
* [PATCH RFC v2 25/32] net: dsa: Setup the switches after all have been probed
2016-02-28 16:41 [PATCH RFC v2 00/32] Make DSA switches linux devices Andrew Lunn
` (23 preceding siblings ...)
2016-02-28 16:41 ` [PATCH RFC v2 24/32] net: dsa: Add some debug prints for error cases Andrew Lunn
@ 2016-02-28 16:41 ` Andrew Lunn
2016-02-28 16:41 ` [PATCH RFC v2 26/32] net: dsa: Only setup platform switches, not device switches Andrew Lunn
` (7 subsequent siblings)
32 siblings, 0 replies; 47+ messages in thread
From: Andrew Lunn @ 2016-02-28 16:41 UTC (permalink / raw)
To: Florian Fainelli, Vivien Didelot, netdev; +Cc: Andrew Lunn
Some switches register themselves with DSA, which others are probed by
DSA itself. Move the setup call to after all switches have been
successfully probed. Similarly, finish each before releasing them.
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
---
net/dsa/dsa.c | 27 ++++++++++++++++-----------
1 file changed, 16 insertions(+), 11 deletions(-)
diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c
index 9acfbe7c34f7..b9b10e050927 100644
--- a/net/dsa/dsa.c
+++ b/net/dsa/dsa.c
@@ -426,7 +426,6 @@ dsa_switch_setup(struct dsa_switch_tree *dst, int index,
struct dsa_chip_data *pd = dst->pd->chip + index;
struct dsa_switch_driver *drv;
struct dsa_switch *ds;
- int ret;
char *name;
/*
@@ -456,17 +455,11 @@ dsa_switch_setup(struct dsa_switch_tree *dst, int index,
ds->tag_protocol = drv->tag_protocol;
ds->master_dev = host_dev;
- ret = dsa_switch_setup_one(ds, parent);
- if (ret)
- return ERR_PTR(ret);
-
return ds;
}
static void dsa_switch_finish(struct dsa_switch *ds, struct device *parent)
{
- dsa_switch_finish_one(ds);
-
devm_kfree(parent, ds);
}
@@ -836,22 +829,28 @@ static inline void dsa_of_remove(struct device *dev,
static int dsa_setup_dst(struct dsa_switch_tree *dst, struct net_device *dev,
struct device *parent)
{
- int i;
+ int i, ret;
unsigned configured = 0;
+ struct dsa_switch *ds;
struct dsa_platform_data *pd = dst->pd;
dst->cpu_switch = -1;
dst->cpu_port = -1;
for (i = 0; i < pd->nr_chips; i++) {
- struct dsa_switch *ds;
-
ds = dsa_switch_setup(dst, i, parent, pd->chip[i].host_dev);
if (IS_ERR(ds)) {
netdev_err(dev, "[%d]: couldn't create dsa switch instance (error %ld)\n",
i, PTR_ERR(ds));
continue;
}
+ }
+
+ for (i = 0; i < pd->nr_chips; i++) {
+ ds = dst->ds[i];
+ ret = dsa_switch_setup_one(ds, parent);
+ if (ret)
+ return ret;
dst->ds[i] = ds;
@@ -879,6 +878,7 @@ static void dsa_finish_dst(struct dsa_switch_tree *dst, struct device *parent,
struct dsa_platform_data *pd)
{
struct net_device *dev = dst->master_netdev;
+ struct dsa_switch *ds;
int i;
dev->dsa_ptr = NULL;
@@ -888,7 +888,12 @@ static void dsa_finish_dst(struct dsa_switch_tree *dst, struct device *parent,
wmb();
for (i = 0; i < pd->nr_chips; i++) {
- struct dsa_switch *ds = dst->ds[i];
+ ds = dst->ds[i];
+ dsa_switch_finish_one(ds);
+ }
+
+ for (i = 0; i < pd->nr_chips; i++) {
+ ds = dst->ds[i];
dsa_switch_finish(ds, parent);
dst->ds[i] = NULL;
--
2.7.0
^ permalink raw reply related [flat|nested] 47+ messages in thread
* [PATCH RFC v2 26/32] net: dsa: Only setup platform switches, not device switches
2016-02-28 16:41 [PATCH RFC v2 00/32] Make DSA switches linux devices Andrew Lunn
` (24 preceding siblings ...)
2016-02-28 16:41 ` [PATCH RFC v2 25/32] net: dsa: Setup the switches after all have been probed Andrew Lunn
@ 2016-02-28 16:41 ` Andrew Lunn
2016-02-28 16:41 ` [PATCH RFC v2 27/32] net: dsa: If a switch fails to probe, defer probing Andrew Lunn
` (6 subsequent siblings)
32 siblings, 0 replies; 47+ messages in thread
From: Andrew Lunn @ 2016-02-28 16:41 UTC (permalink / raw)
To: Florian Fainelli, Vivien Didelot, netdev; +Cc: Andrew Lunn
Switches which are linux devices will register themselves with DSA.
Such switches already have a dsa_switch in the dsa_switch_tree, and
don't need to be probed using the old mechanism.
Similarly, it is the responsibility of the switch driver to free its
resources when it unregisters.
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
---
net/dsa/dsa.c | 37 ++++++++++++++++++-------------------
1 file changed, 18 insertions(+), 19 deletions(-)
diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c
index b9b10e050927..f3ffc937b152 100644
--- a/net/dsa/dsa.c
+++ b/net/dsa/dsa.c
@@ -830,19 +830,25 @@ static int dsa_setup_dst(struct dsa_switch_tree *dst, struct net_device *dev,
struct device *parent)
{
int i, ret;
- unsigned configured = 0;
struct dsa_switch *ds;
+ struct dsa_chip_data *cd;
struct dsa_platform_data *pd = dst->pd;
dst->cpu_switch = -1;
dst->cpu_port = -1;
for (i = 0; i < pd->nr_chips; i++) {
- ds = dsa_switch_setup(dst, i, parent, pd->chip[i].host_dev);
- if (IS_ERR(ds)) {
- netdev_err(dev, "[%d]: couldn't create dsa switch instance (error %ld)\n",
- i, PTR_ERR(ds));
- continue;
+ cd = &pd->chip[i];
+ if (!cd->of_chip) {
+ ds = dsa_switch_setup(dst, i, parent,
+ pd->chip[i].host_dev);
+ if (IS_ERR(ds)) {
+ netdev_err(dev, "[%d]: couldn't create dsa switch instance (error %ld)\n",
+ i, PTR_ERR(ds));
+ return PTR_ERR(ds);
+ }
+
+ dst->ds[i] = ds;
}
}
@@ -851,19 +857,9 @@ static int dsa_setup_dst(struct dsa_switch_tree *dst, struct net_device *dev,
ret = dsa_switch_setup_one(ds, parent);
if (ret)
return ret;
-
- dst->ds[i] = ds;
-
- ++configured;
}
/*
- * If no switch was found, exit cleanly
- */
- if (!configured)
- return -EPROBE_DEFER;
-
- /*
* If we use a tagging format that doesn't have an ethertype
* field, make sure that all packets from this point on get
* sent to the tag format's receive function.
@@ -878,6 +874,7 @@ static void dsa_finish_dst(struct dsa_switch_tree *dst, struct device *parent,
struct dsa_platform_data *pd)
{
struct net_device *dev = dst->master_netdev;
+ struct dsa_chip_data *cd;
struct dsa_switch *ds;
int i;
@@ -893,9 +890,11 @@ static void dsa_finish_dst(struct dsa_switch_tree *dst, struct device *parent,
}
for (i = 0; i < pd->nr_chips; i++) {
- ds = dst->ds[i];
-
- dsa_switch_finish(ds, parent);
+ cd = &pd->chip[i];
+ if (!cd->of_chip) {
+ ds = dst->ds[i];
+ dsa_switch_finish(ds, parent);
+ }
dst->ds[i] = NULL;
}
}
--
2.7.0
^ permalink raw reply related [flat|nested] 47+ messages in thread
* [PATCH RFC v2 27/32] net: dsa: If a switch fails to probe, defer probing
2016-02-28 16:41 [PATCH RFC v2 00/32] Make DSA switches linux devices Andrew Lunn
` (25 preceding siblings ...)
2016-02-28 16:41 ` [PATCH RFC v2 26/32] net: dsa: Only setup platform switches, not device switches Andrew Lunn
@ 2016-02-28 16:41 ` Andrew Lunn
2016-02-28 16:41 ` [PATCH RFC v2 28/32] Documentation: DSA: Describe how probe of DSA and switches work Andrew Lunn
` (5 subsequent siblings)
32 siblings, 0 replies; 47+ messages in thread
From: Andrew Lunn @ 2016-02-28 16:41 UTC (permalink / raw)
To: Florian Fainelli, Vivien Didelot, netdev; +Cc: Andrew Lunn
Switches are either listed in device tree or platform_data. They
should exist. If the probe fails, defer the probe, which is the likely
cause of failure, not broken device tree or platform data.
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
Acked-by: Florian Fainelli <f.fainelli@gmail.com>
---
net/dsa/dsa.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c
index f3ffc937b152..c61b7ab092f5 100644
--- a/net/dsa/dsa.c
+++ b/net/dsa/dsa.c
@@ -435,7 +435,7 @@ dsa_switch_setup(struct dsa_switch_tree *dst, int index,
if (drv == NULL) {
netdev_err(dst->master_netdev, "[%d]: could not detect attached switch\n",
index);
- return ERR_PTR(-EINVAL);
+ return ERR_PTR(-EPROBE_DEFER);
}
netdev_info(dst->master_netdev, "[%d]: detected a %s switch\n",
index, name);
--
2.7.0
^ permalink raw reply related [flat|nested] 47+ messages in thread
* [PATCH RFC v2 28/32] Documentation: DSA: Describe how probe of DSA and switches work.
2016-02-28 16:41 [PATCH RFC v2 00/32] Make DSA switches linux devices Andrew Lunn
` (26 preceding siblings ...)
2016-02-28 16:41 ` [PATCH RFC v2 27/32] net: dsa: If a switch fails to probe, defer probing Andrew Lunn
@ 2016-02-28 16:41 ` Andrew Lunn
2016-02-29 11:42 ` Sergei Shtylyov
2016-02-28 16:41 ` [PATCH RFC v2 29/32] dsa: slave: Don't reference NULL pointer during phy_disconnect Andrew Lunn
` (4 subsequent siblings)
32 siblings, 1 reply; 47+ messages in thread
From: Andrew Lunn @ 2016-02-28 16:41 UTC (permalink / raw)
To: Florian Fainelli, Vivien Didelot, netdev; +Cc: Andrew Lunn
With the introduction of switches as linux devices and the use of the
component framework, probing has become more complex. Add some
documentation.
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
---
Documentation/networking/dsa/dsa.txt | 48 ++++++++++++++++++++++++++++++++++++
1 file changed, 48 insertions(+)
diff --git a/Documentation/networking/dsa/dsa.txt b/Documentation/networking/dsa/dsa.txt
index aa9c1f9313cd..376afa135a81 100644
--- a/Documentation/networking/dsa/dsa.txt
+++ b/Documentation/networking/dsa/dsa.txt
@@ -398,6 +398,54 @@ Switch configuration
on the management interface and "hardcode"/"force" this MAC address for the
CPU/management interface as an optimization
+Call flow
+---------
+
+With the ability for switch devices to be true linux devices, the call
+flow is somewhat complex. The component framework is used to link the
+dsa framework as the master, with switch devices, as slaves.
+
+A switch device should add itself as a component in its probe
+function.
+
+The DSA framework can either be configured using a platform_data
+structure or from the device tree. If device tree is being used, the
+dsa framework probe function will allocate a platform_data structure,
+and populate it using the device tree, via the dsa_of_probe()
+function. Within the DSA device tree, switch devices are represented
+by a phandle to the switch device. These phandles are saved into the
+platform data so that when switch slaves register themselves, they can
+be correctly positioned in the DSA cluster.
+
+The DSA probe function then creates a dsa_switch_tree structure which
+is the overarching structure representing a switch cluster. The probe
+function then looks in the platform data for the phandles to slave
+devices, and adds a component match based on the phandle. The
+component master is then created. This causes the component framework
+to link slaves to the master.
+
+If all the slave switch can be found, the masters bind function is
+called, dsa_bind(). This in tern causes the switch slaves bind
+function to be called.
+
+The switches bind function allocated memory for its own private use,
+and for a dsa_switch structure, which represents one switch in a DSA
+cluster. The switch then registers with the DSA framework using
+dsa_switch_register().
+
+dsa_switch_register() looks in the platform data and finds the
+position within the cluster for the switch which is registering. The
+switches dsa_switch structure is then attached to the dsa_switch_tree
+structure in the correct place.
+
+Once all slave switches have registered, dsa_setup_dst() is used to
+complete the construction of the dsa_switch_tree structure. This
+starts by setting up switches which are not slave devices. The MDIO
+address of the switch is passed to each switch driver to see if it can
+drive the switch. If it can, a dsa_switch structure is allocated to
+represent the switch and linked into the dsa_switch_tree at the
+correct location.
+
PHY devices and link management
-------------------------------
--
2.7.0
^ permalink raw reply related [flat|nested] 47+ messages in thread
* [PATCH RFC v2 29/32] dsa: slave: Don't reference NULL pointer during phy_disconnect
2016-02-28 16:41 [PATCH RFC v2 00/32] Make DSA switches linux devices Andrew Lunn
` (27 preceding siblings ...)
2016-02-28 16:41 ` [PATCH RFC v2 28/32] Documentation: DSA: Describe how probe of DSA and switches work Andrew Lunn
@ 2016-02-28 16:41 ` Andrew Lunn
2016-02-28 16:41 ` [PATCH RFC v2 30/32] dsa: Destroy fixed link phys after the phy has been disconnected Andrew Lunn
` (3 subsequent siblings)
32 siblings, 0 replies; 47+ messages in thread
From: Andrew Lunn @ 2016-02-28 16:41 UTC (permalink / raw)
To: Florian Fainelli, Vivien Didelot, netdev; +Cc: Andrew Lunn
When the phy is disconnected, the parent pointer to the netdev it was
attached to is set to NULL. The code then tries to suspend the phy,
but dsa_slave_fixed_link_update needs the parent pointer to determine
which switch the phy is connected to. So it dereferenced a NULL
pointer. Check for this condition.
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
---
net/dsa/slave.c | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index 40b9ca72aae3..d0d29f73e2f2 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -982,11 +982,15 @@ static void dsa_slave_adjust_link(struct net_device *dev)
static int dsa_slave_fixed_link_update(struct net_device *dev,
struct fixed_phy_status *status)
{
- struct dsa_slave_priv *p = netdev_priv(dev);
- struct dsa_switch *ds = p->parent;
+ struct dsa_slave_priv *p;
+ struct dsa_switch *ds;
- if (ds->drv->fixed_link_update)
- ds->drv->fixed_link_update(ds, p->port, status);
+ if (dev) {
+ p = netdev_priv(dev);
+ ds = p->parent;
+ if (ds->drv->fixed_link_update)
+ ds->drv->fixed_link_update(ds, p->port, status);
+ }
return 0;
}
--
2.7.0
^ permalink raw reply related [flat|nested] 47+ messages in thread
* [PATCH RFC v2 30/32] dsa: Destroy fixed link phys after the phy has been disconnected
2016-02-28 16:41 [PATCH RFC v2 00/32] Make DSA switches linux devices Andrew Lunn
` (28 preceding siblings ...)
2016-02-28 16:41 ` [PATCH RFC v2 29/32] dsa: slave: Don't reference NULL pointer during phy_disconnect Andrew Lunn
@ 2016-02-28 16:41 ` Andrew Lunn
2016-02-28 16:41 ` [PATCH RFC v2 31/32] dsa: dsa: Fix freeing of fixed-phys from user ports Andrew Lunn
` (2 subsequent siblings)
32 siblings, 0 replies; 47+ messages in thread
From: Andrew Lunn @ 2016-02-28 16:41 UTC (permalink / raw)
To: Florian Fainelli, Vivien Didelot, netdev; +Cc: Andrew Lunn
The phy is disconnected from the slave in dsa_slave_destroy(). Don't
destroy fixed link phys until after this, since there can be fixed
linked phys connected to ports.
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
---
net/dsa/dsa.c | 24 ++++++++++++------------
1 file changed, 12 insertions(+), 12 deletions(-)
diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c
index c61b7ab092f5..73f962d81d40 100644
--- a/net/dsa/dsa.c
+++ b/net/dsa/dsa.c
@@ -387,7 +387,18 @@ static void dsa_switch_finish_one(struct dsa_switch *ds)
hwmon_device_unregister(ds->hwmon_dev);
#endif
- /* Disable configuration of the CPU and DSA ports */
+ /* Destroy network devices for physical switch ports. */
+ for (port = 0; port < DSA_MAX_PORTS; port++) {
+ if (!(ds->phys_port_mask & (1 << port)))
+ continue;
+
+ if (!ds->ports[port])
+ continue;
+
+ dsa_slave_destroy(ds->ports[port]);
+ }
+
+ /* Remove any fixed link PHYs */
for (port = 0; port < DSA_MAX_PORTS; port++) {
if (!(dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port)))
continue;
@@ -405,17 +416,6 @@ static void dsa_switch_finish_one(struct dsa_switch *ds)
}
}
- /* Destroy network devices for physical switch ports. */
- for (port = 0; port < DSA_MAX_PORTS; port++) {
- if (!(ds->phys_port_mask & (1 << port)))
- continue;
-
- if (!ds->ports[port])
- continue;
-
- dsa_slave_destroy(ds->ports[port]);
- }
-
mdiobus_unregister(ds->slave_mii_bus);
}
--
2.7.0
^ permalink raw reply related [flat|nested] 47+ messages in thread
* [PATCH RFC v2 31/32] dsa: dsa: Fix freeing of fixed-phys from user ports.
2016-02-28 16:41 [PATCH RFC v2 00/32] Make DSA switches linux devices Andrew Lunn
` (29 preceding siblings ...)
2016-02-28 16:41 ` [PATCH RFC v2 30/32] dsa: Destroy fixed link phys after the phy has been disconnected Andrew Lunn
@ 2016-02-28 16:41 ` Andrew Lunn
2016-02-28 16:41 ` [PATCH RFC v2 32/32] phy: fixed: Fix removal of phys Andrew Lunn
2016-03-03 18:49 ` [PATCH RFC v2 00/32] Make DSA switches linux devices Florian Fainelli
32 siblings, 0 replies; 47+ messages in thread
From: Andrew Lunn @ 2016-02-28 16:41 UTC (permalink / raw)
To: Florian Fainelli, Vivien Didelot, netdev; +Cc: Andrew Lunn
All ports types can have a fixed PHY associated with it. Remove the
check which limits removal to only CPU and DSA ports.
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
---
net/dsa/dsa.c | 3 ---
1 file changed, 3 deletions(-)
diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c
index 73f962d81d40..e969a43f7a21 100644
--- a/net/dsa/dsa.c
+++ b/net/dsa/dsa.c
@@ -400,9 +400,6 @@ static void dsa_switch_finish_one(struct dsa_switch *ds)
/* Remove any fixed link PHYs */
for (port = 0; port < DSA_MAX_PORTS; port++) {
- if (!(dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port)))
- continue;
-
port_dn = cd->port_dn[port];
if (of_phy_is_fixed_link(port_dn)) {
phydev = of_phy_find_device(port_dn);
--
2.7.0
^ permalink raw reply related [flat|nested] 47+ messages in thread
* [PATCH RFC v2 32/32] phy: fixed: Fix removal of phys.
2016-02-28 16:41 [PATCH RFC v2 00/32] Make DSA switches linux devices Andrew Lunn
` (30 preceding siblings ...)
2016-02-28 16:41 ` [PATCH RFC v2 31/32] dsa: dsa: Fix freeing of fixed-phys from user ports Andrew Lunn
@ 2016-02-28 16:41 ` Andrew Lunn
2016-03-03 18:49 ` [PATCH RFC v2 00/32] Make DSA switches linux devices Florian Fainelli
32 siblings, 0 replies; 47+ messages in thread
From: Andrew Lunn @ 2016-02-28 16:41 UTC (permalink / raw)
To: Florian Fainelli, Vivien Didelot, netdev; +Cc: Andrew Lunn
The fixed phys delete function simply removed the fixed phy from the
internal linked list and freed the memory. It however did not
unregister the associated phy device. This meant it was still possible
to find the phy device on the mdio bus.
Make fixed_phy_del() an internal function and add a
fixed_phy_unregister() to unregisters the phy device and then uses
fixed_phy_del() to free resources.
Modify DSA to use this new API function. It then becomes possible to
unload and load driver modules with setups that use fixed phys.
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
---
drivers/net/phy/fixed_phy.c | 10 ++++++++--
include/linux/phy_fixed.h | 5 ++---
net/dsa/dsa.c | 4 +---
3 files changed, 11 insertions(+), 8 deletions(-)
diff --git a/drivers/net/phy/fixed_phy.c b/drivers/net/phy/fixed_phy.c
index ab9c473d75ea..a6caf99a3904 100644
--- a/drivers/net/phy/fixed_phy.c
+++ b/drivers/net/phy/fixed_phy.c
@@ -285,7 +285,7 @@ err_regs:
}
EXPORT_SYMBOL_GPL(fixed_phy_add);
-void fixed_phy_del(int phy_addr)
+static void fixed_phy_del(int phy_addr)
{
struct fixed_mdio_bus *fmb = &platform_fmb;
struct fixed_phy *fp, *tmp;
@@ -300,7 +300,6 @@ void fixed_phy_del(int phy_addr)
}
}
}
-EXPORT_SYMBOL_GPL(fixed_phy_del);
static int phy_fixed_addr;
static DEFINE_SPINLOCK(phy_fixed_addr_lock);
@@ -371,6 +370,13 @@ struct phy_device *fixed_phy_register(unsigned int irq,
}
EXPORT_SYMBOL_GPL(fixed_phy_register);
+void fixed_phy_unregister(struct phy_device *phy)
+{
+ phy_device_remove(phy);
+
+ fixed_phy_del(phy->mdio.addr);
+}
+
static int __init fixed_mdio_bus_init(void)
{
struct fixed_mdio_bus *fmb = &platform_fmb;
diff --git a/include/linux/phy_fixed.h b/include/linux/phy_fixed.h
index 2400d2ea4f34..1d41ec44e39d 100644
--- a/include/linux/phy_fixed.h
+++ b/include/linux/phy_fixed.h
@@ -19,7 +19,7 @@ extern struct phy_device *fixed_phy_register(unsigned int irq,
struct fixed_phy_status *status,
int link_gpio,
struct device_node *np);
-extern void fixed_phy_del(int phy_addr);
+extern void fixed_phy_unregister(struct phy_device *phydev);
extern int fixed_phy_set_link_update(struct phy_device *phydev,
int (*link_update)(struct net_device *,
struct fixed_phy_status *));
@@ -40,9 +40,8 @@ static inline struct phy_device *fixed_phy_register(unsigned int irq,
{
return ERR_PTR(-ENODEV);
}
-static inline int fixed_phy_del(int phy_addr)
+static inline void fixed_phy_unregister(struct phy_device *phydev)
{
- return -ENODEV;
}
static inline int fixed_phy_set_link_update(struct phy_device *phydev,
int (*link_update)(struct net_device *,
diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c
index e969a43f7a21..445097927131 100644
--- a/net/dsa/dsa.c
+++ b/net/dsa/dsa.c
@@ -404,11 +404,9 @@ static void dsa_switch_finish_one(struct dsa_switch *ds)
if (of_phy_is_fixed_link(port_dn)) {
phydev = of_phy_find_device(port_dn);
if (phydev) {
- int addr = phydev->mdio.addr;
-
phy_device_free(phydev);
of_node_put(port_dn);
- fixed_phy_del(addr);
+ fixed_phy_unregister(phydev);
}
}
}
--
2.7.0
^ permalink raw reply related [flat|nested] 47+ messages in thread
* Re: [PATCH RFC v2 18/32] dsa: mv88e6xxx: Prepare for turning this into a library module
2016-02-28 16:41 ` [PATCH RFC v2 18/32] dsa: mv88e6xxx: Prepare for turning this into a library module Andrew Lunn
@ 2016-02-29 2:40 ` Vivien Didelot
2016-02-29 14:53 ` Andrew Lunn
0 siblings, 1 reply; 47+ messages in thread
From: Vivien Didelot @ 2016-02-29 2:40 UTC (permalink / raw)
To: Andrew Lunn, Florian Fainelli, netdev; +Cc: Andrew Lunn
Hi Andrew,
Andrew Lunn <andrew@lunn.ch> writes:
> Export all the functions so that we can later turn the module into a
> library module.
As I mentioned in the first RFC [1], wouldn't that be preferable to
avoid adding modules and factorize everything into a single one?
The common code would have a single probe function which calls
mv88e6xxx_lookup_name for every model tables until it finds the good
one.
For the rest of the code, a few additional switch family checks should
do the job. What do you think?
[1] https://patchwork.ozlabs.org/patch/560540/
Thanks,
-v
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH RFC v2 28/32] Documentation: DSA: Describe how probe of DSA and switches work.
2016-02-28 16:41 ` [PATCH RFC v2 28/32] Documentation: DSA: Describe how probe of DSA and switches work Andrew Lunn
@ 2016-02-29 11:42 ` Sergei Shtylyov
0 siblings, 0 replies; 47+ messages in thread
From: Sergei Shtylyov @ 2016-02-29 11:42 UTC (permalink / raw)
To: Andrew Lunn, Florian Fainelli, Vivien Didelot, netdev
Hello.
On 2/28/2016 7:41 PM, Andrew Lunn wrote:
> With the introduction of switches as linux devices and the use of the
> component framework, probing has become more complex. Add some
> documentation.
>
> Signed-off-by: Andrew Lunn <andrew@lunn.ch>
> ---
> Documentation/networking/dsa/dsa.txt | 48 ++++++++++++++++++++++++++++++++++++
> 1 file changed, 48 insertions(+)
>
> diff --git a/Documentation/networking/dsa/dsa.txt b/Documentation/networking/dsa/dsa.txt
> index aa9c1f9313cd..376afa135a81 100644
> --- a/Documentation/networking/dsa/dsa.txt
> +++ b/Documentation/networking/dsa/dsa.txt
> @@ -398,6 +398,54 @@ Switch configuration
> on the management interface and "hardcode"/"force" this MAC address for the
> CPU/management interface as an optimization
>
> +Call flow
> +---------
> +
> +With the ability for switch devices to be true linux devices, the call
Linux.
> +flow is somewhat complex. The component framework is used to link the
> +dsa framework as the master, with switch devices, as slaves.
Commas not needed before "as".
> +
> +A switch device should add itself as a component in its probe
> +function.
> +
> +The DSA framework can either be configured using a platform_data
> +structure or from the device tree. If device tree is being used, the
> +dsa framework probe function will allocate a platform_data structure,
> +and populate it using the device tree, via the dsa_of_probe()
> +function. Within the DSA device tree, switch devices are represented
> +by a phandle to the switch device. These phandles are saved into the
> +platform data so that when switch slaves register themselves, they can
> +be correctly positioned in the DSA cluster.
> +
> +The DSA probe function then creates a dsa_switch_tree structure which
> +is the overarching structure representing a switch cluster. The probe
> +function then looks in the platform data for the phandles to slave
Platform data and phandles?
> +devices, and adds a component match based on the phandle. The
> +component master is then created. This causes the component framework
> +to link slaves to the master.
> +
> +If all the slave switch can be found, the masters bind function is
Switches? Master's?
> +called, dsa_bind(). This in tern causes the switch slaves bind
In term?
> +function to be called.
> +
> +The switches bind function allocated memory for its own private use,
Switch's?
> +and for a dsa_switch structure, which represents one switch in a DSA
> +cluster. The switch then registers with the DSA framework using
> +dsa_switch_register().
> +
> +dsa_switch_register() looks in the platform data and finds the
> +position within the cluster for the switch which is registering. The
> +switches dsa_switch structure is then attached to the dsa_switch_tree
Switch's?
> +structure in the correct place.
[...]
MBR, Sergei
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH RFC v2 18/32] dsa: mv88e6xxx: Prepare for turning this into a library module
2016-02-29 2:40 ` Vivien Didelot
@ 2016-02-29 14:53 ` Andrew Lunn
0 siblings, 0 replies; 47+ messages in thread
From: Andrew Lunn @ 2016-02-29 14:53 UTC (permalink / raw)
To: Vivien Didelot; +Cc: Florian Fainelli, netdev
On Sun, Feb 28, 2016 at 09:40:56PM -0500, Vivien Didelot wrote:
> Hi Andrew,
>
> Andrew Lunn <andrew@lunn.ch> writes:
>
> > Export all the functions so that we can later turn the module into a
> > library module.
>
> As I mentioned in the first RFC [1], wouldn't that be preferable to
> avoid adding modules and factorize everything into a single one?
>
> The common code would have a single probe function which calls
> mv88e6xxx_lookup_name for every model tables until it finds the good
> one.
Hi Vivien
This is all possible, but is not the point of what i'm trying to do
with this patchset. I want switch drivers to be linux devices, which
probe in the usual way. The changes i made here is the minimum needed
to allow that. What you are suggesting are further steps that could be
made. But since i already have 30 patches, i would prefer to get them
accepted and then think about this refactoring into one module. Such
refactoring should not change the device tree binding, so it can be
deferred.
Andrew
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH RFC v2 23/32] net: dsa: bcm_sf2: make it a real platform driver
2016-02-28 16:41 ` [PATCH RFC v2 23/32] net: dsa: bcm_sf2: make it a real platform driver Andrew Lunn
@ 2016-03-03 18:33 ` Florian Fainelli
2016-03-03 19:12 ` Andrew Lunn
0 siblings, 1 reply; 47+ messages in thread
From: Florian Fainelli @ 2016-03-03 18:33 UTC (permalink / raw)
To: Andrew Lunn, Vivien Didelot, netdev
On 28/02/16 08:41, Andrew Lunn wrote:
> From: Florian Fainelli <f.fainelli@gmail.com>
>
> The Broadcom Starfighter 2 switch driver should be a proper platform
> driver, now that the DSA code has been updated to allow that, register
> a switch device, feed it with the proper configuration data coming
> from Device Tree and register our switch device with DSA.
>
> The bulk of the changes consist in moving what bcm_sf2_sw_setup() did
> into the component slave bind function.
>
> This change does not however prevent the old DSA binding from working.
>
> Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
> Signed-off-by: Andrew Lunn <andrew@lunn.ch>
> ---
[snip]
> + /* All the interesting properties are at the parent device_node
> + * level
> + */
> + dn = ds->pd->of_node->parent;
This is no longer true with the binding you are proposing, but see more
below.
> + bcm_sf2_identify_ports(priv, ds->pd->of_node);
> +
> + priv->irq0 = irq_of_parse_and_map(dn, 0);
> + priv->irq1 = irq_of_parse_and_map(dn, 1);
> +
> + base = &priv->core;
> + for (i = 0; i < BCM_SF2_REGS_NUM; i++) {
> + *base = of_iomap(dn, i);
> + if (!base) {
> + pr_err("unable to find register: %s\n", reg_names[i]);
> + ret = -ENOMEM;
> + goto out_unmap;
> + }
> + base++;
> + }
> +
> + ret = bcm_sf2_sw_rst(priv);
> + if (ret) {
> + pr_err("unable to software reset switch: %d\n", ret);
> + goto out_unmap;
> + }
> +
> + /* Disable all interrupts and request them */
> + bcm_sf2_intr_disable(priv);
> +
> + ret = request_irq(priv->irq0, bcm_sf2_switch_0_isr, 0,
> + "switch_0", priv);
> + if (ret < 0) {
> + pr_err("failed to request switch_0 IRQ\n");
> + goto out_unmap;
> + }
> +
> + ret = request_irq(priv->irq1, bcm_sf2_switch_1_isr, 0,
> + "switch_1", priv);
> + if (ret < 0) {
> + pr_err("failed to request switch_1 IRQ\n");
> + goto out_free_irq0;
> + }
> +
> + /* Reset the MIB counters */
> + reg = core_readl(priv, CORE_GMNCFGCFG);
> + reg |= RST_MIB_CNT;
> + core_writel(priv, reg, CORE_GMNCFGCFG);
> + reg &= ~RST_MIB_CNT;
> + core_writel(priv, reg, CORE_GMNCFGCFG);
> +
> + /* Get the maximum number of ports for this switch */
> + priv->hw_params.num_ports = core_readl(priv, CORE_IMP0_PRT_ID) + 1;
> + if (priv->hw_params.num_ports > DSA_MAX_PORTS)
> + priv->hw_params.num_ports = DSA_MAX_PORTS;
> +
> + /* Assume a single GPHY setup if we can't read that property */
> + if (of_property_read_u32(dn, "brcm,num-gphy",
> + &priv->hw_params.num_gphy))
> + priv->hw_params.num_gphy = 1;
> +
> + /* Include the pseudo-PHY address and the broadcast PHY address to
> + * divert reads towards our workaround. This is only required for
> + * 7445D0, since 7445E0 disconnects the internal switch pseudo-PHY such
> + * that we can use the regular SWITCH_MDIO master controller instead.
> + *
> + * By default, DSA initializes ds->phys_mii_mask to ds->phys_port_mask
> + * to have a 1:1 mapping between Port address and PHY address in order
> + * to utilize the slave_mii_bus instance to read from Port PHYs. This is
> + * not what we want here, so we initialize phys_mii_mask 0 to always
> + * utilize the "master" MDIO bus backed by the "mdio-unimac" driver.
> + */
> + if (of_machine_is_compatible("brcm,bcm7445d0"))
> + ds->phys_mii_mask |= ((1 << BRCM_PSEUDO_PHY_ADDR) | (1 << 0));
> + else
> + ds->phys_mii_mask = 0;
> +
> + rev = reg_readl(priv, REG_SWITCH_REVISION);
> + priv->hw_params.top_rev = (rev >> SWITCH_TOP_REV_SHIFT) &
> + SWITCH_TOP_REV_MASK;
> + priv->hw_params.core_rev = (rev & SF2_REV_MASK);
> +
> + rev = reg_readl(priv, REG_PHY_REVISION);
> + priv->hw_params.gphy_rev = rev & PHY_REVISION_MASK;
> +
> + pr_info("Starfighter 2 top: %x.%02x, core: %x.%02x base: 0x%p, IRQs: %d, %d\n",
> + priv->hw_params.top_rev >> 8, priv->hw_params.top_rev & 0xff,
> + priv->hw_params.core_rev >> 8, priv->hw_params.core_rev & 0xff,
> + priv->core, priv->irq0, priv->irq1);
> +
> + platform_set_drvdata(pdev, ds);
> +
> + return dsa_switch_register(dst, ds, dn, "Starfighter 2");
> +
> +out_free_irq0:
> + free_irq(priv->irq0, priv);
> +out_unmap:
> + base = &priv->core;
> + for (i = 0; i < BCM_SF2_REGS_NUM; i++) {
> + if (*base)
> + iounmap(*base);
> + base++;
> + }
> + return ret;
> +}
> +
> +static void bcm_sf2_sw_unbind(struct device *dev,
> + struct device *master, void *data)
> +{
> + struct dsa_switch *ds = dev_get_drvdata(dev);
> + struct bcm_sf2_priv *priv = ds_to_priv(ds);
> +
> + /* Disable all ports and interrupts */
> + priv->wol_ports_mask = 0;
> + bcm_sf2_sw_suspend(ds);
> + dsa_switch_unregister(ds);
> +}
> +
> +static const struct component_ops bcm_sf2_component_ops = {
> + .bind = bcm_sf2_sw_bind,
> + .unbind = bcm_sf2_sw_unbind,
> +};
> +
> +static int bcm_sf2_sw_remove(struct platform_device *pdev)
> +{
> + component_del(&pdev->dev, &bcm_sf2_component_ops);
>
> return 0;
> }
> -module_init(bcm_sf2_init);
>
> -static void __exit bcm_sf2_exit(void)
> +static int bcm_sf2_sw_probe(struct platform_device *pdev)
> {
> - unregister_switch_driver(&bcm_sf2_switch_driver);
> + return component_add(&pdev->dev, &bcm_sf2_component_ops);
> }
> -module_exit(bcm_sf2_exit);
> +
> +static const struct of_device_id bcm_sf2_of_match[] = {
> + { .compatible = "brcm,brcm-sf2" },
As I mentioned before, this is a no go for the SF2 platforms out there
which are using the old DSA binding (incorrectly maybe, but using it)
and whose bootloader cannot be changed, but I still have a fundamental
problem with how this is approached here, my initial attempts at making
the SF2 driver a real platform driver was to take the
brcm,bcm7445-switch-v4.0 compatible string as match here, and call
dsa_of_probe() to get the old binding to populate the dsa_platform_data
structure on our behalf, and not require the "dsa" platform device to be
there at all, just some piece of code to be resident in the kernel that
exposes dsa_switch_register().
So, not really the same direction we are taking here, and as I will
reply shortly in the cover letter, the need for the special "dsa"
platform device is only an artifact now, and to catch older setups, it
does not need to exist.
--
Florian
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH RFC v2 00/32] Make DSA switches linux devices.
2016-02-28 16:41 [PATCH RFC v2 00/32] Make DSA switches linux devices Andrew Lunn
` (31 preceding siblings ...)
2016-02-28 16:41 ` [PATCH RFC v2 32/32] phy: fixed: Fix removal of phys Andrew Lunn
@ 2016-03-03 18:49 ` Florian Fainelli
2016-03-03 20:27 ` Andrew Lunn
32 siblings, 1 reply; 47+ messages in thread
From: Florian Fainelli @ 2016-03-03 18:49 UTC (permalink / raw)
To: Andrew Lunn, Vivien Didelot, netdev
Hi Andrew,
On 28/02/16 08:41, Andrew Lunn wrote:
> This is the second RFC for rearchitecturing how DSA devices are
> probed. This patchset allows switches to be linux devices, probed by
> the ususal mechanism for whatever bus they hang off. They then
> register with the DSA core.
>
> DSA has been limited to devices which hang off an MDIO bus, or with a
> bit of work, memory mapped devices. This refactoring generalizes DSA
> so that switches on other sorts of busses, eg. SPI can be supported.
>
> The code should remain backwards compatible. The old device tree
> binding are still supported. It is extended with phandles to switch
> devices.
Still reviewing the individual patches, but there is still something
that seems awkward with this design, is that we still need the special
"dsa" platform device to be there, and this is a problem for many
different reasons:
- first of all, the original design around the special platform device
did not allow multiple switch trees within the same system to coexist
(dsa platform device were not numbered (id = -1)), but such a thing
could exist and is desirable, you could have a single switch hanging off
eth0, and more switches hanging off eth1 for instance, and not be part
of the same tree
- the direction we want to move people to is to make them use DSA for
their switch needs and get the proven benefits from having a consistent
per-port slave network device model along with a good binding for
representing ports within a switch (and all thedetails associated with
that), the next step is to make this available to not just MDIO drivers,
which you are addressing here, but then, being able to call
dsa_switch_register() just becomes a service from the network stack with
DSA support included, if we need the special dsa platform device again,
we are not way better than where we were before
- the dsa platform device was used as a single point of synchronization
which was known to have the entire knowledge about the switch tree, but
with modules being possible again now, this tree is going to see
switches come and go, and that should be the desired model for
developers working on this subsystem, and people making products might
decide to build everything in the kernel to get the same guarantees as
before
I still see the need for the dsa platform device more as an artifact
than something absolutely needed. The way I would see the probing logic
(simplified) is something along these lines:
- switch driver gets probed (from a bus subsystem)
- if it is the first one in the tree (thanks to the chip index telling
it so), it registers with dsa, locates the master netdev, and creates
the dst structure for it there in master netdev->dsa_ptr
- if not, then return EPROBE_DEFER until we get the first switch in tree
to be probed
- subsequent switches also locate their chip index, locate the master
netdev, fetch a valid netdev->dsa_ptr now, and add themselves there
and do to that, there is just resident code in the kernel, just waiting
for sucht hings to appear, which is already more or less the case, it
does not need to be a platform device though.
>
> The changes also make it eaiser for the drivers to be kernel modules,
> and the patches contain cleanups and fixes so that the modules can be
> unloaded and loaded.
>
> Patches can be found in
>
> https://github.com/lunn/linux.git v4.5-rc2-net-next-dsa-proposal-4
>
>
> Andrew Lunn (30):
> dsa: Rename mv88e6123_61_65 to mv88e6123 to be consistent
> dsa: Make setup and finish more symmetrical
> net: dsa: Pass the dsa device to the switch drivers
> net: dsa: Have the switch driver allocate there own private memory
> net: dsa: Remove allocation of driver private memory
> net: dsa: Keep the mii bus and address in the private structure
> net: dsa: dsa.c: Refactor to increase symmetry
> driver: component: Add support for empty match table
> net: dsa: Add basic support for component master support
> net: dsa: Keep a reference to the switch device for component matching
> net: dsa: Add slave component matches based on a phandle to the slave.
> net: dsa: Make dsa,mii-bus optional
> net: dsa: Add register/unregister functions for switch drivers
> net: dsa: Rename DSA probe function.
> dsa: mv88e6xxx: Use bus in mv88e6xxx_lookup_name()
> dsa: mv88e6xxx: Add shared code for binding/unbinding a switch driver.
> dsa: mv88e6xxx: Prepare for turning this into a library module
> dsa: mv88e6xxx: Add macro for registering the drivers
> dsa: Add mdio device support to Marvell switches
> net: mdio: Add mdiodev_{read|write} helpers
> net: dsa: Better integrate the drivers with mdio device
> net: dsa: Add some debug prints for error cases
> net: dsa: Setup the switches after all have been probed
> net: dsa: Only setup platform switches, not device switches
> net: dsa: If a switch fails to probe, defer probing
> Documentation: DSA: Describe how probe of DSA and switches work.
> dsa: slave: Don't reference NULL pointer during phy_disconnect
> dsa: Destroy fixed link phys after the phy has been disconnected
> dsa: dsa: Fix freeing of fixed-phys from user ports.
> phy: fixed: Fix removal of phys.
>
> Florian Fainelli (2):
> net: dsa: Move platform data allocation for OF
> net: dsa: bcm_sf2: make it a real platform driver
>
> .../devicetree/bindings/net/dsa/broadcom.txt | 54 +++
> Documentation/devicetree/bindings/net/dsa/dsa.txt | 5 +-
> .../devicetree/bindings/net/dsa/marvell.txt | 29 ++
> Documentation/networking/dsa/dsa.txt | 48 +++
> drivers/base/component.c | 33 +-
> drivers/net/dsa/Kconfig | 2 +-
> drivers/net/dsa/Makefile | 19 +-
> drivers/net/dsa/bcm_sf2.c | 292 +++++++++-------
> drivers/net/dsa/mv88e6060.c | 138 +++++++-
> drivers/net/dsa/mv88e6060.h | 10 +
> drivers/net/dsa/mv88e6123.c | 173 ++++++++++
> drivers/net/dsa/mv88e6123_61_65.c | 124 -------
> drivers/net/dsa/mv88e6131.c | 70 +++-
> drivers/net/dsa/mv88e6171.c | 70 +++-
> drivers/net/dsa/mv88e6352.c | 72 +++-
> drivers/net/dsa/mv88e6xxx.c | 200 +++++++----
> drivers/net/dsa/mv88e6xxx.h | 40 ++-
> drivers/net/phy/fixed_phy.c | 10 +-
> drivers/net/phy/mdio_device.c | 68 ++++
> include/linux/mdio.h | 5 +
> include/linux/phy_fixed.h | 2 +-
> include/net/dsa.h | 17 +-
> net/dsa/dsa.c | 372 ++++++++++++++-------
> net/dsa/slave.c | 12 +-
> 24 files changed, 1339 insertions(+), 526 deletions(-)
> create mode 100644 Documentation/devicetree/bindings/net/dsa/broadcom.txt
> create mode 100644 Documentation/devicetree/bindings/net/dsa/marvell.txt
> create mode 100644 drivers/net/dsa/mv88e6123.c
> delete mode 100644 drivers/net/dsa/mv88e6123_61_65.c
>
--
Florian
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH RFC v2 23/32] net: dsa: bcm_sf2: make it a real platform driver
2016-03-03 18:33 ` Florian Fainelli
@ 2016-03-03 19:12 ` Andrew Lunn
0 siblings, 0 replies; 47+ messages in thread
From: Andrew Lunn @ 2016-03-03 19:12 UTC (permalink / raw)
To: Florian Fainelli; +Cc: Vivien Didelot, netdev
> As I mentioned before, this is a no go for the SF2 platforms out there
> which are using the old DSA binding
Hi Florian
This is a clear bug and needs fixing. The old binding will be kept
working.
Lets get the big picture agreed, and then i will come back and fix
this.
Andrew
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH RFC v2 00/32] Make DSA switches linux devices.
2016-03-03 18:49 ` [PATCH RFC v2 00/32] Make DSA switches linux devices Florian Fainelli
@ 2016-03-03 20:27 ` Andrew Lunn
2016-03-11 23:41 ` Florian Fainelli
0 siblings, 1 reply; 47+ messages in thread
From: Andrew Lunn @ 2016-03-03 20:27 UTC (permalink / raw)
To: Florian Fainelli; +Cc: Vivien Didelot, netdev
> - first of all, the original design around the special platform device
> did not allow multiple switch trees within the same system to coexist
> (dsa platform device were not numbered (id = -1)), but such a thing
> could exist and is desirable, you could have a single switch hanging off
> eth0, and more switches hanging off eth1 for instance, and not be part
> of the same tree
I have hardware i can test such a setup on.
>
> - the direction we want to move people to is to make them use DSA for
> their switch needs and get the proven benefits from having a consistent
> per-port slave network device model along with a good binding for
> representing ports within a switch (and all thedetails associated with
> that), the next step is to make this available to not just MDIO drivers,
> which you are addressing here, but then, being able to call
> dsa_switch_register() just becomes a service from the network stack with
> DSA support included, if we need the special dsa platform device again,
> we are not way better than where we were before
We are a bit better. dsa_switch_register() does not care about the
communication channel to the switch. An SPI based switch should now be
possible, as well as a cleaner way to do MMIO switches.
> I still see the need for the dsa platform device more as an artifact
> than something absolutely needed. The way I would see the probing logic
> (simplified) is something along these lines:
>
> - switch driver gets probed (from a bus subsystem)
> - if it is the first one in the tree (thanks to the chip index telling
> it so), it registers with dsa, locates the master netdev, and creates
> the dst structure for it there in master netdev->dsa_ptr
> - if not, then return EPROBE_DEFER until we get the first switch in tree
> to be probed
> - subsequent switches also locate their chip index, locate the master
> netdev, fetch a valid netdev->dsa_ptr now, and add themselves there
>
> and do to that, there is just resident code in the kernel, just waiting
> for sucht hings to appear, which is already more or less the case, it
> does not need to be a platform device though.
So lets take an example. I posted a dts file for a board with three
switches:
http://www.spinics.net/lists/arm-kernel/msg484955.html
This board has an MDIO bus per switch, via a mux:
mdio-mux {
compatible = "mdio-mux-gpio";
pinctrl-0 = <&pinctrl_mdio_mux>;
pinctrl-names = "default";
gpios = <&gpio0 8 GPIO_ACTIVE_HIGH
&gpio0 9 GPIO_ACTIVE_HIGH
&gpio0 24 GPIO_ACTIVE_HIGH
&gpio0 25 GPIO_ACTIVE_HIGH>;
mdio-parent-bus = <&mdio1>;
#address-cells = <1>;
#size-cells = <0>;
mdio_mux_1: mdio@1 {
reg = <1>;
#address-cells = <1>;
#size-cells = <0>;
};
mdio_mux_2: mdio@2 {
reg = <2>;
#address-cells = <1>;
#size-cells = <0>;
};
mdio_mux_4: mdio@4 {
reg = <4>;
#address-cells = <1>;
#size-cells = <0>;
};
mdio_mux_8: mdio@8 {
reg = <8>;
#address-cells = <1>;
#size-cells = <0>;
};
};
And the current switches are represented thus:
dsa@0 {
compatible = "marvell,dsa";
#address-cells = <2>;
#size-cells = <0>;
dsa,ethernet = <&fec1>;
dsa,mii-bus = <&mdio_mux_1>;
/* 6352 - Primary - 7 ports */
switch0: switch@2 {
#address-cells = <1>;
#size-cells = <0>;
reg = <0x00 0>;
eeprom-length = <512>;
port@0 {
reg = <0>;
label = "lan0";
};
port@1 {
reg = <1>;
label = "lan1";
};
port@2 {
reg = <2>;
label = "lan2";
};
switch0port5: port@5 {
reg = <5>;
label = "dsa";
phy-mode = "rgmii-txid";
link = <&switch1port6
&switch2port9>;
fixed-link {
speed = <1000>;
full-duplex;
};
};
port@6 {
reg = <6>;
label = "cpu";
fixed-link {
speed = <100>;
full-duplex;
};
};
};
/* 6352 - Secondary - 7 ports */
switch1: switch@0 {
#address-cells = <1>;
#size-cells = <0>;
reg = <0x00 1>;
eeprom-length = <512>;
mii-bus = <&mdio_mux_2>;
port@0 {
reg = <0>;
label = "lan3";
};
port@1 {
reg = <1>;
label = "lan4";
};
port@2 {
reg = <2>;
label = "lan5";
};
switch1port5: port@5 {
reg = <5>;
label = "dsa";
link = <&switch2port9>;
phy-mode = "rgmii-txid";
fixed-link {
speed = <1000>;
full-duplex;
};
};
switch1port6: port@6 {
reg = <6>;
label = "dsa";
phy-mode = "rgmii-txid";
link = <&switch0port5>;
fixed-link {
speed = <1000>;
full-duplex;
};
};
};
/* 6185 - 10 ports */
switch2: switch@6 {
#address-cells = <1>;
#size-cells = <0>;
reg = <0x00 2>;
mii-bus = <&mdio_mux_4>;
port@0 {
reg = <0>;
label = "lan6";
};
port@1 {
reg = <1>;
label = "lan7";
};
port@2 {
reg = <2>;
label = "lan8";
};
port@3 {
reg = <3>;
label = "optical3";
fixed-link {
speed = <1000>;
full-duplex;
link-gpios = <&gpio6 2 GPIO_ACTIVE_HIGH>;
};
};
port@4 {
reg = <4>;
label = "optical4";
fixed-link {
speed = <1000>;
full-duplex;
link-gpios = <&gpio6 3 GPIO_ACTIVE_HIGH>;
};
};
switch2port9: port@9 {
reg = <9>;
label = "dsa";
phy-mode = "rgmii-txid";
link = <&switch1port5
&switch0port5>;
fixed-link {
speed = <1000>;
full-duplex;
};
};
};
};
};
We want to break this up into three switch devices, each hanging off
their mdio bus.
Here is the first switch:
mdio_mux_1: mdio@1 {
reg = <1>;
#address-cells = <1>;
#size-cells = <0>;
/* 6352 - Primary - 7 ports */
switch0: switch@2 {
compatible = "marvell,mv88e6352";
compatible string now needed here.
#address-cells = <1>;
#size-cells = <0>;
reg = <0x00>;
reg is now the mdio address, or for an SPI device, the address on the
SPI bus. We need some other identifier for where this switch fits into
the dst.
dsa,member = <0 0>;
This property is used to associate switches together. The first digit
identifies which switch tree this switch belongs in. The second digit
is the location within that tree.
Does 0 need to be special? I don't think so. See the CPU port below,
and the points at the end.
eeprom-length = <512>;
port@0 {
reg = <0>;
label = "lan0";
};
...
switch0port5: port@5 {
reg = <5>;
label = "dsa";
phy-mode = "rgmii-txid";
link = <&switch1port6
&switch2port9>;
These phandles have to be unique, otherwise the DT compiler will
complain. So this should be enough for us to unique identify the
switch on the other end.
fixed-link {
speed = <1000>;
full-duplex;
};
};
port@6 {
reg = <6>;
label = "cpu";
ethernet = <&fec1>;
We put the link to the host here. This makes it easier in the future
to have multiple CPU interfaces.
fixed-link {
speed = <100>;
full-duplex;
};
};
};
};
The second switch on a different mdio bus
mdio_mux_2: mdio@2 {
reg = <2>;
#address-cells = <1>;
#size-cells = <0>;
/* 6352 - Secondary - 7 ports */
switch1: switch@0 {
compatible = "marvell,mv88e6352";
#address-cells = <1>;
#size-cells = <0>;
reg = <0x00>;
dsa,member = <0 1>;
See switch tree 0, switch 1 on that tree.
eeprom-length = <512>;
port@0 {
reg = <0>;
label = "lan3";
};
switch1port6: port@6 {
reg = <6>;
label = "dsa";
phy-mode = "rgmii-txid";
link = <&switch0port5>;
The corresponding links to those in switch 0.
fixed-link {
speed = <1000>;
full-duplex;
};
};
};
The third switch is as you would expect, dsa,member = <0 2>;
The probe order does not actually matter. You allocate the dst when
the first switch arrives, and plug that switch in. You then evaluate
the dst. Are all dsa links fulfilled. If yes, you have the full tree,
and you can set it up and running. If no, wait until more switches are
registered.
This is quite a big change, so why not make it bigger...
One thing i don't like is the complexity we have in matching phys to
ports, and fixed-link phys. Maybe we should consolidate this:
1) The switch device should use mdiobus_alloc()/mdiobus_register() for
its own MDIO bus.
2) ports use phy-handle to point to phys on their own mdio bus.
Ordering should be O.K, the switch needs to instantiate its own mdio
bus before calling dsa_switch_register().
3) We make a fixed-link-mdio device, which also uses
mdiobus_alloc()/mdiobus_register(), giving us fixed-link phys we can
reference in the normal way with phy-handle.
This last change makes MAC drivers simpler, they just need to support
phy-handle and they get fixed-phy for free. It removes the 32
fixed-phy restrictions, since we can have multiple instances of the
fixed-link-mdio device. And it fixes the problems with alloc/free
cycles in the current fixed phy code. And dsa does not need to do
anything special for fixed-phys.
One down side is that it is totally fictitious hardware, so should not
really be in device tree....
Andrew
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH RFC v2 00/32] Make DSA switches linux devices.
2016-03-03 20:27 ` Andrew Lunn
@ 2016-03-11 23:41 ` Florian Fainelli
2016-03-12 17:08 ` Andrew Lunn
0 siblings, 1 reply; 47+ messages in thread
From: Florian Fainelli @ 2016-03-11 23:41 UTC (permalink / raw)
To: Andrew Lunn; +Cc: Vivien Didelot, netdev
On 03/03/16 12:27, Andrew Lunn wrote:
>> - first of all, the original design around the special platform device
>> did not allow multiple switch trees within the same system to coexist
>> (dsa platform device were not numbered (id = -1)), but such a thing
>> could exist and is desirable, you could have a single switch hanging off
>> eth0, and more switches hanging off eth1 for instance, and not be part
>> of the same tree
>
> I have hardware i can test such a setup on.
>
>>
>> - the direction we want to move people to is to make them use DSA for
>> their switch needs and get the proven benefits from having a consistent
>> per-port slave network device model along with a good binding for
>> representing ports within a switch (and all thedetails associated with
>> that), the next step is to make this available to not just MDIO drivers,
>> which you are addressing here, but then, being able to call
>> dsa_switch_register() just becomes a service from the network stack with
>> DSA support included, if we need the special dsa platform device again,
>> we are not way better than where we were before
>
> We are a bit better. dsa_switch_register() does not care about the
> communication channel to the switch. An SPI based switch should now be
> possible, as well as a cleaner way to do MMIO switches.
Right, thanks to your patch series and recent efforts, and that is
exactly the direction we want.
[snip]
>
> The third switch is as you would expect, dsa,member = <0 2>;
I like that representation.
>
> The probe order does not actually matter. You allocate the dst when
> the first switch arrives, and plug that switch in. You then evaluate
> the dst. Are all dsa links fulfilled. If yes, you have the full tree,
> and you can set it up and running. If no, wait until more switches are
> registered.
So does that mean you agree we do not need the DSA platform device
anymore :)? If not, why, and how much help from the Device Tree do we
need to instantiate that special "dsa" platform device?
>
> This is quite a big change, so why not make it bigger...
>
> One thing i don't like is the complexity we have in matching phys to
> ports, and fixed-link phys. Maybe we should consolidate this:
Very true, we support a wide variety of setups, and that creates a lot
of complexity that could probably be absorbed by a more generic helper
function?
>
> 1) The switch device should use mdiobus_alloc()/mdiobus_register() for
> its own MDIO bus.
Agreed, possibly with the help of the DSA slave code, since some of that
is already doing its magic for most drivers here.
> 2) ports use phy-handle to point to phys on their own mdio bus.
I would refrain from needing that unless the mapping between Port and
built-in PHY is design/board-level configurable, or we connect to PHYs
external to the switch which are not located on its own internal MDIO
bus controller.
--
Florian
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH RFC v2 03/32] dsa: Make setup and finish more symmetrical
2016-02-28 16:41 ` [PATCH RFC v2 03/32] dsa: Make setup and finish more symmetrical Andrew Lunn
@ 2016-03-11 23:54 ` Florian Fainelli
0 siblings, 0 replies; 47+ messages in thread
From: Florian Fainelli @ 2016-03-11 23:54 UTC (permalink / raw)
To: Andrew Lunn, Vivien Didelot, netdev
On 28/02/16 08:41, Andrew Lunn wrote:
> Rename and reposition dsa_switch_destroy() to dsa_switch_finish_one()
> to make it clear it is the opposite of dsa_switch_setup_one().
>
> Signed-off-by: Andrew Lunn <andrew@lunn.ch>
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
--
Florian
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH RFC v2 08/32] net: dsa: dsa.c: Refactor to increase symmetry
2016-02-28 16:41 ` [PATCH RFC v2 08/32] net: dsa: dsa.c: Refactor to increase symmetry Andrew Lunn
@ 2016-03-11 23:54 ` Florian Fainelli
0 siblings, 0 replies; 47+ messages in thread
From: Florian Fainelli @ 2016-03-11 23:54 UTC (permalink / raw)
To: Andrew Lunn, Vivien Didelot, netdev
On 28/02/16 08:41, Andrew Lunn wrote:
> Create a dsa_switch_finish() which does the opposite of dsa_switch_setup().
> Create a dsa_finish_dst() which does the opposite of dsa_setup_dst().
>
> Signed-off-by: Andrew Lunn <andrew@lunn.ch>
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
--
Florian
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH RFC v2 00/32] Make DSA switches linux devices.
2016-03-11 23:41 ` Florian Fainelli
@ 2016-03-12 17:08 ` Andrew Lunn
2016-03-13 7:26 ` Vivien Didelot
2016-03-14 19:36 ` Florian Fainelli
0 siblings, 2 replies; 47+ messages in thread
From: Andrew Lunn @ 2016-03-12 17:08 UTC (permalink / raw)
To: Florian Fainelli; +Cc: Vivien Didelot, netdev
> [snip]
>
> >
> > The third switch is as you would expect, dsa,member = <0 2>;
>
> I like that representation.
>
...
> So does that mean you agree we do not need the DSA platform device
> anymore :)?
It looks like it can be done without the DSA platform device.
My previous approach was to keep the new binding as similar as
possible to the current one. If however, we decide we are going for
something totally new, we can remove this platform device.
It probably means we need to turn slave.c and parts of dsa.c into a
library. Add a new dsa_v2.c file, containing the new binding
code. With things like having the switch devices instantiate there own
MDIO bus, fixed phys on a compatible MDIO bus referenced via phandles,
etc, I hope we can make parts of the dsa_v2 simpler.
> Very true, we support a wide variety of setups, and that creates a lot
> of complexity that could probably be absorbed by a more generic helper
> function?
No, i want to go the other direction. Make all these phy setups look
identical. It is just a phy-handle=<&phandle> property. With my MDIO
fixed-phy bus patches, it just works for user ports, and the only
thing we need to deal with is phy-mode.
DSA and CPU ports are harder, due to a lack of a netdev. Horrible, but
maybe would could do a alloc_netdev(), but never register_netdev()?
It gives us something to attach the phy to.
> > 1) The switch device should use mdiobus_alloc()/mdiobus_register() for
> > its own MDIO bus.
>
> Agreed, possibly with the help of the DSA slave code, since some of that
> is already doing its magic for most drivers here.
I think the switch driver should instantiate the MDIO bus, not the
core. The core could however offer some helper code.
Andrew
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH RFC v2 00/32] Make DSA switches linux devices.
2016-03-12 17:08 ` Andrew Lunn
@ 2016-03-13 7:26 ` Vivien Didelot
2016-03-14 19:36 ` Florian Fainelli
1 sibling, 0 replies; 47+ messages in thread
From: Vivien Didelot @ 2016-03-13 7:26 UTC (permalink / raw)
To: Andrew Lunn, Florian Fainelli; +Cc: netdev
Hi Andrew, Florian,
Andrew Lunn <andrew@lunn.ch> writes:
> It probably means we need to turn slave.c and parts of dsa.c into a
> library. Add a new dsa_v2.c file, containing the new binding
> code. With things like having the switch devices instantiate there own
> MDIO bus, fixed phys on a compatible MDIO bus referenced via phandles,
> etc, I hope we can make parts of the dsa_v2 simpler.
Nothing critical here, but as we are talking about better isolation of
the DSA slave code, wouldn't it be the good moment to make it a
dsa_switch driver, instead of a library? This code is actually pretty
generic, and for example home routers could register an instance of such
module.
Thanks,
-v
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH RFC v2 00/32] Make DSA switches linux devices.
2016-03-12 17:08 ` Andrew Lunn
2016-03-13 7:26 ` Vivien Didelot
@ 2016-03-14 19:36 ` Florian Fainelli
2016-03-14 20:51 ` Andrew Lunn
1 sibling, 1 reply; 47+ messages in thread
From: Florian Fainelli @ 2016-03-14 19:36 UTC (permalink / raw)
To: Andrew Lunn; +Cc: Vivien Didelot, netdev
On 12/03/16 09:08, Andrew Lunn wrote:
>> [snip]
>>
>>>
>>> The third switch is as you would expect, dsa,member = <0 2>;
>>
>> I like that representation.
>>
>
> ...
>
>> So does that mean you agree we do not need the DSA platform device
>> anymore :)?
>
> It looks like it can be done without the DSA platform device.
>
> My previous approach was to keep the new binding as similar as
> possible to the current one. If however, we decide we are going for
> something totally new, we can remove this platform device.
The old binding can and should remain available, we just don't want to
match it anymore using a generic DSA platform device, but that does not
prevent a driver using the old binding to get a struct dsa_platform_data
to be properly filed if it was using it through dsa_of_probe(). With the
networking stack offfering resident code to deal with DSA, we could also
warn if we see a node in tree with "marvell,dsa".
The new binding looks very similar to the previous one and this is
certainly a good thing to do. With that in mind the new binding should
probably be keeping the per-port Device Tree node representation and
properties, because that one seems correct, the parts that had gone
wrong were definitively the "reg" property and the dsa,mii-bus property
if not the dsa,ethernet as well, but code will talk.
>
> It probably means we need to turn slave.c and parts of dsa.c into a
> library. Add a new dsa_v2.c file, containing the new binding
> code. With things like having the switch devices instantiate there own
> MDIO bus, fixed phys on a compatible MDIO bus referenced via phandles,
> etc, I hope we can make parts of the dsa_v2 simpler.
Looks like we still need to get this one ironed out.
>
>> Very true, we support a wide variety of setups, and that creates a lot
>> of complexity that could probably be absorbed by a more generic helper
>> function?
>
> No, i want to go the other direction. Make all these phy setups look
> identical. It is just a phy-handle=<&phandle> property. With my MDIO
> fixed-phy bus patches, it just works for user ports, and the only
> thing we need to deal with is phy-mode.
>
> DSA and CPU ports are harder, due to a lack of a netdev. Horrible, but
> maybe would could do a alloc_netdev(), but never register_netdev()?
> It gives us something to attach the phy to.
Humm, I suppose that could work, in practice, having a full-fledged
"cpu" network device would be more useful than having e.g: eth0, now
being the conduit interface, because that one, really is useless to
applications because it needs a tag to be applied and there is nothing
doing that. Food for thought.
>
>>> 1) The switch device should use mdiobus_alloc()/mdiobus_register() for
>>> its own MDIO bus.
>>
>> Agreed, possibly with the help of the DSA slave code, since some of that
>> is already doing its magic for most drivers here.
>
> I think the switch driver should instantiate the MDIO bus, not the
> core. The core could however offer some helper code.
Works for me.
--
Florian
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH RFC v2 00/32] Make DSA switches linux devices.
2016-03-14 19:36 ` Florian Fainelli
@ 2016-03-14 20:51 ` Andrew Lunn
0 siblings, 0 replies; 47+ messages in thread
From: Andrew Lunn @ 2016-03-14 20:51 UTC (permalink / raw)
To: Florian Fainelli; +Cc: Vivien Didelot, netdev
On Mon, Mar 14, 2016 at 12:36:18PM -0700, Florian Fainelli wrote:
> On 12/03/16 09:08, Andrew Lunn wrote:
> >> [snip]
> >>
> >>>
> >>> The third switch is as you would expect, dsa,member = <0 2>;
> >>
> >> I like that representation.
> >>
> >
> > ...
> >
> >> So does that mean you agree we do not need the DSA platform device
> >> anymore :)?
> >
> > It looks like it can be done without the DSA platform device.
> >
> > My previous approach was to keep the new binding as similar as
> > possible to the current one. If however, we decide we are going for
> > something totally new, we can remove this platform device.
>
> The old binding can and should remain available
Agreed. "marvell,dsa" will remain and will invoke a platform device,
as is today. That is the old binding.
I'm currently thinking that switch drivers will probe, and then call
something like
int dsa_switch_register(struct dsa_switch *ds, struct device_node *np);
The code behind that will be responsible for allocating the dst,
parsing the binding pointed to by np. It will also evaluate if all the
dsa links are available, and if so, call the setup() method in
ds->drv, etc.
> The new binding looks very similar to the previous one and this is
> certainly a good thing to do. With that in mind the new binding should
> probably be keeping the per-port Device Tree node representation and
> properties, because that one seems correct.
There are some changes. A cpu node will have the phandle to the
ethernet device. I really would like to only have a phandle to a phy,
but we will see, and i want to remove the limit of one cpu node. The
driver can then return -EINVAL during setup() if it cannot handle it.
> the parts that had gone
> wrong were definitively the "reg" property and the dsa,mii-bus property
> if not the dsa,ethernet as well, but code will talk.
reg at the switch level. Yes. We still need reg at the port level.
dsa,mii-bus is gone, and dsa,ethernet moved into the cpu port.
Andrew
^ permalink raw reply [flat|nested] 47+ messages in thread
end of thread, other threads:[~2016-03-14 20:51 UTC | newest]
Thread overview: 47+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-02-28 16:41 [PATCH RFC v2 00/32] Make DSA switches linux devices Andrew Lunn
2016-02-28 16:41 ` [PATCH RFC v2 01/32] net: dsa: Move platform data allocation for OF Andrew Lunn
2016-02-28 16:41 ` [PATCH RFC v2 02/32] dsa: Rename mv88e6123_61_65 to mv88e6123 to be consistent Andrew Lunn
2016-02-28 16:41 ` [PATCH RFC v2 03/32] dsa: Make setup and finish more symmetrical Andrew Lunn
2016-03-11 23:54 ` Florian Fainelli
2016-02-28 16:41 ` [PATCH RFC v2 04/32] net: dsa: Pass the dsa device to the switch drivers Andrew Lunn
2016-02-28 16:41 ` [PATCH RFC v2 05/32] net: dsa: Have the switch driver allocate there own private memory Andrew Lunn
2016-02-28 16:41 ` [PATCH RFC v2 06/32] net: dsa: Remove allocation of driver " Andrew Lunn
2016-02-28 16:41 ` [PATCH RFC v2 07/32] net: dsa: Keep the mii bus and address in the private structure Andrew Lunn
2016-02-28 16:41 ` [PATCH RFC v2 08/32] net: dsa: dsa.c: Refactor to increase symmetry Andrew Lunn
2016-03-11 23:54 ` Florian Fainelli
2016-02-28 16:41 ` [PATCH RFC v2 09/32] driver: component: Add support for empty match table Andrew Lunn
2016-02-28 16:41 ` [PATCH RFC v2 10/32] net: dsa: Add basic support for component master support Andrew Lunn
2016-02-28 16:41 ` [PATCH RFC v2 11/32] net: dsa: Keep a reference to the switch device for component matching Andrew Lunn
2016-02-28 16:41 ` [PATCH RFC v2 12/32] net: dsa: Add slave component matches based on a phandle to the slave Andrew Lunn
2016-02-28 16:41 ` [PATCH RFC v2 13/32] net: dsa: Make dsa,mii-bus optional Andrew Lunn
2016-02-28 16:41 ` [PATCH RFC v2 14/32] net: dsa: Add register/unregister functions for switch drivers Andrew Lunn
2016-02-28 16:41 ` [PATCH RFC v2 15/32] net: dsa: Rename DSA probe function Andrew Lunn
2016-02-28 16:41 ` [PATCH RFC v2 16/32] dsa: mv88e6xxx: Use bus in mv88e6xxx_lookup_name() Andrew Lunn
2016-02-28 16:41 ` [PATCH RFC v2 17/32] dsa: mv88e6xxx: Add shared code for binding/unbinding a switch driver Andrew Lunn
2016-02-28 16:41 ` [PATCH RFC v2 18/32] dsa: mv88e6xxx: Prepare for turning this into a library module Andrew Lunn
2016-02-29 2:40 ` Vivien Didelot
2016-02-29 14:53 ` Andrew Lunn
2016-02-28 16:41 ` [PATCH RFC v2 19/32] dsa: mv88e6xxx: Add macro for registering the drivers Andrew Lunn
2016-02-28 16:41 ` [PATCH RFC v2 20/32] dsa: Add mdio device support to Marvell switches Andrew Lunn
2016-02-28 16:41 ` [PATCH RFC v2 21/32] net: mdio: Add mdiodev_{read|write} helpers Andrew Lunn
2016-02-28 16:41 ` [PATCH RFC v2 22/32] net: dsa: Better integrate the drivers with mdio device Andrew Lunn
2016-02-28 16:41 ` [PATCH RFC v2 23/32] net: dsa: bcm_sf2: make it a real platform driver Andrew Lunn
2016-03-03 18:33 ` Florian Fainelli
2016-03-03 19:12 ` Andrew Lunn
2016-02-28 16:41 ` [PATCH RFC v2 24/32] net: dsa: Add some debug prints for error cases Andrew Lunn
2016-02-28 16:41 ` [PATCH RFC v2 25/32] net: dsa: Setup the switches after all have been probed Andrew Lunn
2016-02-28 16:41 ` [PATCH RFC v2 26/32] net: dsa: Only setup platform switches, not device switches Andrew Lunn
2016-02-28 16:41 ` [PATCH RFC v2 27/32] net: dsa: If a switch fails to probe, defer probing Andrew Lunn
2016-02-28 16:41 ` [PATCH RFC v2 28/32] Documentation: DSA: Describe how probe of DSA and switches work Andrew Lunn
2016-02-29 11:42 ` Sergei Shtylyov
2016-02-28 16:41 ` [PATCH RFC v2 29/32] dsa: slave: Don't reference NULL pointer during phy_disconnect Andrew Lunn
2016-02-28 16:41 ` [PATCH RFC v2 30/32] dsa: Destroy fixed link phys after the phy has been disconnected Andrew Lunn
2016-02-28 16:41 ` [PATCH RFC v2 31/32] dsa: dsa: Fix freeing of fixed-phys from user ports Andrew Lunn
2016-02-28 16:41 ` [PATCH RFC v2 32/32] phy: fixed: Fix removal of phys Andrew Lunn
2016-03-03 18:49 ` [PATCH RFC v2 00/32] Make DSA switches linux devices Florian Fainelli
2016-03-03 20:27 ` Andrew Lunn
2016-03-11 23:41 ` Florian Fainelli
2016-03-12 17:08 ` Andrew Lunn
2016-03-13 7:26 ` Vivien Didelot
2016-03-14 19:36 ` Florian Fainelli
2016-03-14 20:51 ` Andrew Lunn
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).