[PATCH v2] net: Rework mdio-ofgpio driver to use of_mdio infrastructure
Changes to the fs_enet driver (aa73832c5a80d6c52c69b18af858d88fa595dd3c) cause kernel crashes when using the mdio-ofgpio driver. The following patch replicates similar changes made to the fs_enet mii-bitbang drivers. --- This version attempts to address Grant's comments below: Grant Likely wrote: You should refactor mdio_gpio_bus_init() to not call mdiobus_register() at all, and instead just return a pointer to the unregistered new_bus. Then mdio_gpio_probe() and mdio_ofgpio_probe() can call the correct register variant directly. Fewer ugly #ifdefs this way. It also eliminates the need to cast the void* pointer. drivers/net/phy/mdio-gpio.c | 77 --- 1 files changed, 36 insertions(+), 41 deletions(-) diff --git a/drivers/net/phy/mdio-gpio.c b/drivers/net/phy/mdio-gpio.c index 33984b7..22cdd45 100644 --- a/drivers/net/phy/mdio-gpio.c +++ b/drivers/net/phy/mdio-gpio.c @@ -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 @@ out_free_bus: 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); @@ -215,14 +206,18 @@ static int __devinit mdio_ofgpio_probe(struct of_device *ofdev, ret = of_get_gpio(ofdev-node, 1); if (ret 0) -goto out_free; + goto out_free; pdata-mdio = ret; - while ((np = of_get_next_child(ofdev-node, np))) - if (!strcmp(np-type, ethernet-phy)) -
Re: [PATCH v2] net: Rework mdio-ofgpio driver to use of_mdio infrastructure
On Tue, Jul 21, 2009 at 3:50 AM, Mark Waremw...@elphinstone.net wrote: Changes to the fs_enet driver (aa73832c5a80d6c52c69b18af858d88fa595dd3c) cause kernel crashes when using the mdio-ofgpio driver. The following patch replicates similar changes made to the fs_enet mii-bitbang drivers. This looks good to me. I've not tested it though (no hardware that uses it). You should specify the testing you've done in the commit log. Your signed-off-by: line is also missing. Acked-by: Grant Likely grant.lik...@secretlab.ca David, once the above issues are solved, this one needs to be merged for 2.6.31. Cheers, g. --- This version attempts to address Grant's comments below: Grant Likely wrote: You should refactor mdio_gpio_bus_init() to not call mdiobus_register() at all, and instead just return a pointer to the unregistered new_bus. Then mdio_gpio_probe() and mdio_ofgpio_probe() can call the correct register variant directly. Fewer ugly #ifdefs this way. It also eliminates the need to cast the void* pointer. drivers/net/phy/mdio-gpio.c | 77 --- 1 files changed, 36 insertions(+), 41 deletions(-) diff --git a/drivers/net/phy/mdio-gpio.c b/drivers/net/phy/mdio-gpio.c index 33984b7..22cdd45 100644 --- a/drivers/net/phy/mdio-gpio.c +++ b/drivers/net/phy/mdio-gpio.c @@ -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 @@ out_free_bus: 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