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

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
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#ifdef CONFIG_OF_GPIO #ifdef CONFIG_OF_GPIO
#include <linux/of_gpio.h> #include <linux/of_gpio.h>
#include <linux/of_mdio.h>
#include <linux/of_platform.h> #include <linux/of_platform.h>
#endif #endif
...@@ -81,13 +82,12 @@ static struct mdiobb_ops mdio_gpio_ops = { ...@@ -81,13 +82,12 @@ static struct mdiobb_ops mdio_gpio_ops = {
.get_mdio_data = mdio_get, .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, struct mdio_gpio_platform_data *pdata,
int bus_id) int bus_id)
{ {
struct mii_bus *new_bus; struct mii_bus *new_bus;
struct mdio_gpio_info *bitbang; struct mdio_gpio_info *bitbang;
int ret = -ENOMEM;
int i; int i;
bitbang = kzalloc(sizeof(*bitbang), GFP_KERNEL); bitbang = kzalloc(sizeof(*bitbang), GFP_KERNEL);
...@@ -104,8 +104,6 @@ static int __devinit mdio_gpio_bus_init(struct device *dev, ...@@ -104,8 +104,6 @@ static int __devinit mdio_gpio_bus_init(struct device *dev,
new_bus->name = "GPIO Bitbanged MDIO", new_bus->name = "GPIO Bitbanged MDIO",
ret = -ENODEV;
new_bus->phy_mask = pdata->phy_mask; new_bus->phy_mask = pdata->phy_mask;
new_bus->irq = pdata->irqs; new_bus->irq = pdata->irqs;
new_bus->parent = dev; new_bus->parent = dev;
...@@ -129,15 +127,8 @@ static int __devinit mdio_gpio_bus_init(struct device *dev, ...@@ -129,15 +127,8 @@ static int __devinit mdio_gpio_bus_init(struct device *dev,
dev_set_drvdata(dev, new_bus); dev_set_drvdata(dev, new_bus);
ret = mdiobus_register(new_bus); return new_bus;
if (ret)
goto out_free_all;
return 0;
out_free_all:
dev_set_drvdata(dev, NULL);
gpio_free(bitbang->mdio);
out_free_mdc: out_free_mdc:
gpio_free(bitbang->mdc); gpio_free(bitbang->mdc);
out_free_bus: out_free_bus:
...@@ -145,30 +136,47 @@ static int __devinit mdio_gpio_bus_init(struct device *dev, ...@@ -145,30 +136,47 @@ static int __devinit mdio_gpio_bus_init(struct device *dev,
out_free_bitbang: out_free_bitbang:
kfree(bitbang); kfree(bitbang);
out: 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 mii_bus *bus = dev_get_drvdata(dev);
struct mdio_gpio_info *bitbang = bus->priv; struct mdio_gpio_info *bitbang = bus->priv;
mdiobus_unregister(bus);
free_mdio_bitbang(bus);
dev_set_drvdata(dev, NULL); dev_set_drvdata(dev, NULL);
gpio_free(bitbang->mdc);
gpio_free(bitbang->mdio); gpio_free(bitbang->mdio);
gpio_free(bitbang->mdc);
free_mdio_bitbang(bus);
kfree(bitbang); 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) static int __devinit mdio_gpio_probe(struct platform_device *pdev)
{ {
struct mdio_gpio_platform_data *pdata = pdev->dev.platform_data; struct mdio_gpio_platform_data *pdata = pdev->dev.platform_data;
struct mii_bus *new_bus;
int ret;
if (!pdata) if (!pdata)
return -ENODEV; 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) static int __devexit mdio_gpio_remove(struct platform_device *pdev)
...@@ -179,29 +187,12 @@ 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 #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, static int __devinit mdio_ofgpio_probe(struct of_device *ofdev,
const struct of_device_id *match) const struct of_device_id *match)
{ {
struct device_node *np = NULL;
struct mdio_gpio_platform_data *pdata; struct mdio_gpio_platform_data *pdata;
struct mii_bus *new_bus;
int ret; int ret;
pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
...@@ -218,11 +209,15 @@ static int __devinit mdio_ofgpio_probe(struct of_device *ofdev, ...@@ -218,11 +209,15 @@ static int __devinit mdio_ofgpio_probe(struct of_device *ofdev,
goto out_free; goto out_free;
pdata->mdio = ret; pdata->mdio = ret;
while ((np = of_get_next_child(ofdev->node, np))) new_bus = mdio_gpio_bus_init(&ofdev->dev, pdata, pdata->mdc);
if (!strcmp(np->type, "ethernet-phy")) if (!new_bus)
add_phy(pdata, np); 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: out_free:
kfree(pdata); kfree(pdata);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment