Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit dacac4da authored by Mark Ware's avatar Mark Ware Committed by David S. Miller
Browse files

net: Rework mdio-ofgpio driver to use of_mdio infrastructure



Changes to the fs_enet driver aa73832c
("net: Rework fs_enet driver to use of_mdio infrastructure")
cause kernel crashes when using the mdio-ofgpio driver.
 
This patch replicates similar changes made to the fs_enet mii-bitbang
drivers.  It has been tested on a custom mpc8280 based board using an
NFS mounted root.
 
Signed-off-by: default avatarMark Ware <mware@elphinstone.net>
Acked-by: default avatarGrant Likely <grant.likely@secretlab.ca>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 78a9c9c9
Loading
Loading
Loading
Loading
+36 −41
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@

#ifdef CONFIG_OF_GPIO
#include <linux/of_gpio.h>
#include <linux/of_mdio.h>
#include <linux/of_platform.h>
#endif

@@ -81,13 +82,12 @@ static struct mdiobb_ops mdio_gpio_ops = {
	.get_mdio_data = mdio_get,
};

static int __devinit mdio_gpio_bus_init(struct device *dev,
static struct mii_bus * __devinit mdio_gpio_bus_init(struct device *dev,
					struct mdio_gpio_platform_data *pdata,
					int bus_id)
{
	struct mii_bus *new_bus;
	struct mdio_gpio_info *bitbang;
	int ret = -ENOMEM;
	int i;

	bitbang = kzalloc(sizeof(*bitbang), GFP_KERNEL);
@@ -104,8 +104,6 @@ static int __devinit mdio_gpio_bus_init(struct device *dev,

	new_bus->name = "GPIO Bitbanged MDIO",

	ret = -ENODEV;

	new_bus->phy_mask = pdata->phy_mask;
	new_bus->irq = pdata->irqs;
	new_bus->parent = dev;
@@ -129,15 +127,8 @@ static int __devinit mdio_gpio_bus_init(struct device *dev,

	dev_set_drvdata(dev, new_bus);

	ret = mdiobus_register(new_bus);
	if (ret)
		goto out_free_all;

	return 0;
	return new_bus;

out_free_all:
	dev_set_drvdata(dev, NULL);
	gpio_free(bitbang->mdio);
out_free_mdc:
	gpio_free(bitbang->mdc);
out_free_bus:
@@ -145,30 +136,47 @@ static int __devinit mdio_gpio_bus_init(struct device *dev,
out_free_bitbang:
	kfree(bitbang);
out:
	return ret;
	return NULL;
}

static void __devexit mdio_gpio_bus_destroy(struct device *dev)
static void __devinit mdio_gpio_bus_deinit(struct device *dev)
{
	struct mii_bus *bus = dev_get_drvdata(dev);
	struct mdio_gpio_info *bitbang = bus->priv;

	mdiobus_unregister(bus);
	free_mdio_bitbang(bus);
	dev_set_drvdata(dev, NULL);
	gpio_free(bitbang->mdc);
	gpio_free(bitbang->mdio);
	gpio_free(bitbang->mdc);
	free_mdio_bitbang(bus);
	kfree(bitbang);
}

static void __devexit mdio_gpio_bus_destroy(struct device *dev)
{
	struct mii_bus *bus = dev_get_drvdata(dev);

	mdiobus_unregister(bus);
	mdio_gpio_bus_deinit(dev);
}

static int __devinit mdio_gpio_probe(struct platform_device *pdev)
{
	struct mdio_gpio_platform_data *pdata = pdev->dev.platform_data;
	struct mii_bus *new_bus;
	int ret;

	if (!pdata)
		return -ENODEV;

	return mdio_gpio_bus_init(&pdev->dev, pdata, pdev->id);
	new_bus = mdio_gpio_bus_init(&pdev->dev, pdata, pdev->id);
	if (!new_bus)
		return -ENODEV;

	ret = mdiobus_register(new_bus);
	if (ret)
		mdio_gpio_bus_deinit(&pdev->dev);

	return ret;
}

static int __devexit mdio_gpio_remove(struct platform_device *pdev)
@@ -179,29 +187,12 @@ static int __devexit mdio_gpio_remove(struct platform_device *pdev)
}

#ifdef CONFIG_OF_GPIO
static void __devinit add_phy(struct mdio_gpio_platform_data *pdata,
			      struct device_node *np)
{
	const u32 *data;
	int len, id, irq;

	data = of_get_property(np, "reg", &len);
	if (!data || len != 4)
		return;

	id = *data;
	pdata->phy_mask &= ~(1 << id);

	irq = of_irq_to_resource(np, 0, NULL);
	if (irq)
		pdata->irqs[id] = irq;
}

static int __devinit mdio_ofgpio_probe(struct of_device *ofdev,
                                        const struct of_device_id *match)
{
	struct device_node *np = NULL;
	struct mdio_gpio_platform_data *pdata;
	struct mii_bus *new_bus;
	int ret;

	pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
@@ -218,11 +209,15 @@ static int __devinit mdio_ofgpio_probe(struct of_device *ofdev,
		goto out_free;
	pdata->mdio = ret;

	while ((np = of_get_next_child(ofdev->node, np)))
		if (!strcmp(np->type, "ethernet-phy"))
			add_phy(pdata, np);
	new_bus = mdio_gpio_bus_init(&ofdev->dev, pdata, pdata->mdc);
	if (!new_bus)
		return -ENODEV;

	return mdio_gpio_bus_init(&ofdev->dev, pdata, pdata->mdc);
	ret = of_mdiobus_register(new_bus, ofdev->node);
	if (ret)
		mdio_gpio_bus_deinit(&ofdev->dev);

	return ret;

out_free:
	kfree(pdata);