lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:	Wed, 29 Apr 2015 18:57:41 -0700
From:	Florian Fainelli <f.fainelli@...il.com>
To:	netdev@...r.kernel.org
Cc:	dave@...emloft.net, Florian Fainelli <f.fainelli@...il.com>,
	vivien.didelot@...oirfairelinux.com,
	jerome.oufella@...oirfairelinux.com, linux@...ck-us.net,
	andrew@...n.ch, cphealy@...il.com, mathieu@...eaurora.org,
	jonasj76@...il.com, andrey.volkov@...vision.fr,
	Chris.Packham@...iedtelesis.co.nz
Subject: [RFC PATCH net-next 5/8] net: dsa: add new API to register switch devices

Add a new API to register DSA switch devices:

- dsa_switch_register
- dsa_switch_unregister

Signed-off-by: Florian Fainelli <f.fainelli@...il.com>
---
 include/net/dsa.h |  15 +++++
 net/dsa/dsa.c     | 182 +++++++++++++++++++++++++++++++++++++++++++++---------
 2 files changed, 168 insertions(+), 29 deletions(-)

diff --git a/include/net/dsa.h b/include/net/dsa.h
index fbca63ba8f73..b057536f6a77 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -139,6 +139,12 @@ struct dsa_switch {
 	struct dsa_chip_data	*pd;
 
 	/*
+	 * Configuration came from "classic" platform_data
+	 * registration
+	 */
+	bool			from_pd;
+
+	/*
 	 * The used switch driver.
 	 */
 	struct dsa_switch_driver	*drv;
@@ -317,4 +323,13 @@ static inline bool dsa_uses_tagged_protocol(struct dsa_switch_tree *dst)
 {
 	return dst->rcv != NULL;
 }
+
+static inline struct dsa_switch *dsa_alloc_switch(size_t priv_size)
+{
+	return kzalloc(sizeof(struct dsa_switch) + priv_size, GFP_KERNEL);
+}
+
+int dsa_switch_register(struct dsa_switch *ds);
+int dsa_switch_register_phydev(struct dsa_switch *ds, struct phy_device *phy);
+void dsa_switch_unregister(struct dsa_switch *ds);
 #endif
diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c
index 58b99ff4591b..2d9762974880 100644
--- a/net/dsa/dsa.c
+++ b/net/dsa/dsa.c
@@ -364,6 +364,7 @@ dsa_switch_setup(struct dsa_switch_tree *dst, int index,
 	ds->dst = dst;
 	ds->index = index;
 	ds->pd = pd;
+	ds->from_pd = true;
 	ds->drv = drv;
 	ds->tag_protocol = drv->tag_protocol;
 	ds->master_dev = host_dev;
@@ -570,12 +571,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 phy_device *phydev)
 {
 	struct device_node *np = dev->of_node;
 	struct device_node *child, *mdio, *ethernet, *port, *link;
-	struct mii_bus *mdio_bus;
-	struct net_device *ethernet_dev;
+	struct mii_bus *mdio_bus = NULL;
+	struct net_device *ethernet_dev = NULL;
 	struct dsa_platform_data *pd;
 	struct dsa_chip_data *cd;
 	const char *port_name;
@@ -584,28 +585,38 @@ static int dsa_of_probe(struct device *dev)
 	u32 eeprom_len;
 	int ret;
 
-	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)
-		return -EINVAL;
-
-	ethernet_dev = of_find_net_device_by_node(ethernet);
-	if (!ethernet_dev)
-		return -EPROBE_DEFER;
+	/* Parsing of these properties only makes sense in the context of
+	 * non-MDIO probed devices (phydev == NULL) since all of these are
+	 * already implied by the PHY device:
+	 *
+	 * phydev->attached_dev is our netdev
+	 * phydev->bus is our MDIO bus
+	 */
+	if (!phydev) {
+		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)
+			return -EINVAL;
+
+		ethernet_dev = of_find_net_device_by_node(ethernet);
+		if (!ethernet_dev)
+			return -EPROBE_DEFER;
+	}
 
 	pd = kzalloc(sizeof(*pd), GFP_KERNEL);
 	if (!pd)
 		return -ENOMEM;
 
 	dev->platform_data = pd;
-	pd->of_netdev = ethernet_dev;
+	if (!phydev)
+		pd->of_netdev = ethernet_dev;
 	pd->nr_chips = of_get_available_child_count(np);
 	if (pd->nr_chips > DSA_MAX_SWITCHES)
 		pd->nr_chips = DSA_MAX_SWITCHES;
@@ -623,15 +634,21 @@ static int dsa_of_probe(struct device *dev)
 		cd = &pd->chip[chip_index];
 
 		cd->of_node = child;
-		cd->host_dev = &mdio_bus->dev;
-
-		sw_addr = of_get_property(child, "reg", NULL);
-		if (!sw_addr)
-			continue;
+		if (!phydev)
+			cd->host_dev = &mdio_bus->dev;
+		else
+			cd->host_dev = &phydev->bus->dev;
+
+		if (!phydev) {
+			sw_addr = of_get_property(child, "reg", NULL);
+			if (!sw_addr)
+				continue;
 
-		cd->sw_addr = be32_to_cpup(sw_addr);
-		if (cd->sw_addr > PHY_MAX_ADDR)
-			continue;
+			cd->sw_addr = be32_to_cpup(sw_addr);
+			if (cd->sw_addr > PHY_MAX_ADDR)
+				continue;
+		} else
+			cd->sw_addr = phydev->addr;
 
 		if (!of_property_read_u32(np, "eeprom-length", &eeprom_len))
 			cd->eeprom_len = eeprom_len;
@@ -761,7 +778,7 @@ static int dsa_probe(struct platform_device *pdev)
 		       dsa_driver_version);
 
 	if (pdev->dev.of_node) {
-		ret = dsa_of_probe(&pdev->dev);
+		ret = dsa_of_probe(&pdev->dev, NULL);
 		if (ret)
 			return ret;
 
@@ -807,6 +824,107 @@ out:
 	return ret;
 }
 
+static int __dsa_switch_register(struct dsa_switch *ds,
+				 struct phy_device *phydev)
+{
+	struct dsa_switch_tree *dst;
+	struct dsa_platform_data *pd = NULL;
+	struct net_device *dev;
+	int ret;
+
+	/* If using Device Tree, just try to parse standard properties */
+	if (ds->master_dev->of_node) {
+		ret = dsa_of_probe(ds->master_dev, phydev);
+		if (ret)
+			return ret;
+
+		pd = ds->master_dev->platform_data;
+	}
+
+	if (pd == NULL)
+		return -ENODEV;
+
+	/* Cannot find the network device */
+	if (!phydev && (pd->netdev == NULL || pd->of_netdev == NULL))
+		return -ENODEV;
+
+	if (pd->of_netdev) {
+		dev = pd->of_netdev;
+		dev_hold(dev);
+	} else if (phydev == NULL) {
+		dev = dev_to_net_device(pd->netdev);
+	} else {
+		dev = phydev->attached_dev;
+		dev_hold(dev);
+	}
+
+	/* Regardless of our position within a switch tree, we should be
+	 * attached to a network device
+	 */
+	if (dev == NULL) {
+		dev_err(ds->master_dev, "invalid network device\n");
+		if (pd->of_netdev)
+			dev_put(pd->of_netdev);
+		if (phydev)
+			dev_put(phydev->attached_dev);
+		ret = -EPROBE_DEFER;
+		goto out;
+	}
+
+	/* For now we just bail out, but we would want to deal with stacked
+	 * setups with different tagging protocols sitting on top of each other
+	 * in the future
+	 */
+	if (dev->dsa_ptr != NULL) {
+		dev_put(dev);
+		ret = -EEXIST;
+		goto out;
+	}
+
+	dst = kzalloc(sizeof(*dst), GFP_KERNEL);
+	if (!dst) {
+		dev_put(dev);
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	dst->pd = pd;
+	ds->dst = dst;
+	ds->index = 0;
+	dst->master_netdev = dev;
+	dst->cpu_switch = -1;
+	dst->cpu_port = -1;
+	ds->pd = (struct dsa_chip_data *)dst->pd->chip + ds->index;
+
+	ret = dsa_switch_setup_one(ds, ds->master_dev);
+	if (ret)
+		return ret;
+
+	dst->ds[ds->index] = ds;
+
+	dsa_setup_dst_end(dev, dst);
+
+	netdev_info(dev, "Attached switch@%d\n", ds->index);
+
+	return 0;
+
+out:
+	dsa_of_remove(ds->master_dev);
+	return ret;
+}
+
+int dsa_switch_register(struct dsa_switch *ds)
+{
+	return __dsa_switch_register(ds, NULL);
+}
+EXPORT_SYMBOL_GPL(dsa_switch_register);
+
+int dsa_switch_register_phydev(struct dsa_switch *ds, struct phy_device *phydev)
+{
+	return __dsa_switch_register(ds, phydev);
+}
+EXPORT_SYMBOL_GPL(dsa_switch_register_phydev);
+
 static void dsa_remove_dst(struct dsa_switch_tree *dst)
 {
 	int i;
@@ -824,6 +942,13 @@ static void dsa_remove_dst(struct dsa_switch_tree *dst)
 	}
 }
 
+void dsa_switch_unregister(struct dsa_switch *ds)
+{
+	dsa_remove_dst(ds->dst);
+	dsa_of_remove(ds->master_dev);
+}
+EXPORT_SYMBOL_GPL(dsa_switch_unregister);
+
 static int dsa_remove(struct platform_device *pdev)
 {
 	struct dsa_switch_tree *dst = platform_get_drvdata(pdev);
@@ -897,7 +1022,6 @@ static int dsa_resume(struct device *d)
 static SIMPLE_DEV_PM_OPS(dsa_pm_ops, dsa_suspend, dsa_resume);
 
 static const struct of_device_id dsa_of_match_table[] = {
-	{ .compatible = "brcm,bcm7445-switch-v4.0" },
 	{ .compatible = "marvell,dsa", },
 	{}
 };
-- 
2.1.0

--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Powered by blists - more mailing lists