[PATCH] fs_enet: Adjust BDs after tx error
This patch fixes an occasional transmit lockup in the mac-fcc which occurs after a tx error. The test scenario had the local port set to autoneg and the other end fixed at 100FD, resulting in a large number of late collisions. According to the MPC8280RM 30.10.1.3 (also 8272RM 29.10.1.3), after a tx error occurs, TBPTR may sometimes point beyond BDs still marked as ready. This patch walks back through the BDs and points TBPTR to the earliest one marked as ready. Tested on a custom board with a MPC8280. Signed-off-by: Mark Ware mw...@elphinstone.net --- drivers/net/fs_enet/mac-fcc.c | 49 - 1 files changed, 43 insertions(+), 6 deletions(-) diff --git a/drivers/net/fs_enet/mac-fcc.c b/drivers/net/fs_enet/mac-fcc.c index 22e5a84..6023f15 100644 --- a/drivers/net/fs_enet/mac-fcc.c +++ b/drivers/net/fs_enet/mac-fcc.c @@ -503,17 +503,54 @@ static int get_regs_len(struct net_device *dev) } /* Some transmit errors cause the transmitter to shut - * down. We now issue a restart transmit. Since the - * errors close the BD and update the pointers, the restart - * _should_ pick up without having to reset any of our - * pointers either. Also, To workaround 8260 device erratum - * CPM37, we must disable and then re-enable the transmitter - * following a Late Collision, Underrun, or Retry Limit error. + * down. We now issue a restart transmit. + * Also, to workaround 8260 device erratum CPM37, we must + * disable and then re-enable the transmitterfollowing a + * Late Collision, Underrun, or Retry Limit error. + * In addition, tbptr may point beyond BDs beyond still marked + * as ready due to internal pipelining, so we need to look back + * through the BDs and adjust tbptr to point to the last BD + * marked as ready. This may result in some buffers being + * retransmitted. */ static void tx_restart(struct net_device *dev) { struct fs_enet_private *fep = netdev_priv(dev); fcc_t __iomem *fccp = fep-fcc.fccp; + const struct fs_platform_info *fpi = fep-fpi; + fcc_enet_t __iomem *ep = fep-fcc.ep; + cbd_t __iomem *curr_tbptr; + cbd_t __iomem *recheck_bd; + cbd_t __iomem *prev_bd; + cbd_t __iomem *last_tx_bd; + + last_tx_bd = fep-tx_bd_base + (fpi-tx_ring * sizeof(cbd_t)); + + /* get the current bd held in TBPTR and scan back from this point */ + recheck_bd = curr_tbptr = (cbd_t __iomem *) + ((R32(ep, fen_genfcc.fcc_tbptr) - fep-ring_mem_addr) + + fep-ring_base); + + prev_bd = (recheck_bd == fep-tx_bd_base) ? last_tx_bd : recheck_bd - 1; + + /* Move through the bds in reverse, look for the earliest buffer +* that is not ready. Adjust TBPTR to the following buffer */ + while ((CBDR_SC(prev_bd) BD_ENET_TX_READY) != 0) { + /* Go back one buffer */ + recheck_bd = prev_bd; + + /* update the previous buffer */ + prev_bd = (prev_bd == fep-tx_bd_base) ? last_tx_bd : prev_bd - 1; + + /* We should never see all bds marked as ready, check anyway */ + if (recheck_bd == curr_tbptr) + break; + } + /* Now update the TBPTR and dirty flag to the current buffer */ + W32(ep, fen_genfcc.fcc_tbptr, + (uint) (((void *)recheck_bd - fep-ring_base) + + fep-ring_mem_addr)); + fep-dirty_tx = recheck_bd; C32(fccp, fcc_gfmr, FCC_GFMR_ENT); udelay(10); -- 1.5.6.5 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [PATCH v2] cpm2_pic: Allow correct flow_types for port C interrupts
Scott Wood wrote: Anton Vorontsov wrote: +if ((flow_type != IRQ_TYPE_EDGE_BOTH) + (flow_type != IRQ_TYPE_EDGE_FALLING)) { I'd place one more tab here. Or better, align one flow_type with the other. -Scott Thanks Anton and Scott. Scott's suggestion is also my preferred style, but a (brief) search through the source didn't reveal much support. I'll send a new version shortly including you suggestions. - Mark ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v3] cpm2_pic: Allow correct flow_types for port C interrupts
Port C interrupts can be either falling edge, or either edge. Other external interrupts are either falling edge or active low. Tested on a custom 8280 based board. Signed-off-by: Mark Ware mw...@elphinstone.net --- Changed in v3: - Cosmetic improvements as suggested by Anton and Scott - Added tested note to changelog arch/powerpc/sysdev/cpm2_pic.c | 28 +--- 1 files changed, 21 insertions(+), 7 deletions(-) diff --git a/arch/powerpc/sysdev/cpm2_pic.c b/arch/powerpc/sysdev/cpm2_pic.c index 78f1f7c..b1e9206 100644 --- a/arch/powerpc/sysdev/cpm2_pic.c +++ b/arch/powerpc/sysdev/cpm2_pic.c @@ -141,13 +141,23 @@ static int cpm2_set_irq_type(unsigned int virq, unsigned int flow_type) struct irq_desc *desc = get_irq_desc(virq); unsigned int vold, vnew, edibit; - if (flow_type == IRQ_TYPE_NONE) - flow_type = IRQ_TYPE_LEVEL_LOW; - - if (flow_type IRQ_TYPE_EDGE_RISING) { - printk(KERN_ERR CPM2 PIC: sense type 0x%x not supported\n, - flow_type); - return -EINVAL; + /* Port C interrupts are either IRQ_TYPE_EDGE_FALLING or +* IRQ_TYPE_EDGE_BOTH (default). All others are IRQ_TYPE_EDGE_FALLING +* or IRQ_TYPE_LEVEL_LOW (default) +*/ + if (src = CPM2_IRQ_PORTC15 src = CPM2_IRQ_PORTC0) { + if (flow_type == IRQ_TYPE_NONE) + flow_type = IRQ_TYPE_EDGE_BOTH; + + if (flow_type != IRQ_TYPE_EDGE_BOTH + flow_type != IRQ_TYPE_EDGE_FALLING) + goto err_sense; + } else { + if (flow_type == IRQ_TYPE_NONE) + flow_type = IRQ_TYPE_LEVEL_LOW; + + if (flow_type (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_LEVEL_HIGH)) + goto err_sense; } desc-status = ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL); @@ -179,6 +189,10 @@ static int cpm2_set_irq_type(unsigned int virq, unsigned int flow_type) if (vold != vnew) out_be32(cpm2_intctl-ic_siexr, vnew); return 0; + +err_sense: + pr_err(CPM2 PIC: sense type 0x%x not supported\n, flow_type); + return -EINVAL; } static struct irq_chip cpm2_pic = { -- 1.5.6.5 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [PATCH] cpm2_pic: Allow correct flow_types for port C interrupts
Any comments/Acks/Nacks on this patch? - Mark Mark Ware wrote: CPM2 Port C interrupts can be either falling edge, or either edge. Other external interrupts are either falling edge or active low. Signed-Off-By: Mark Ware mw...@elphinstone.net --- arch/powerpc/sysdev/cpm2_pic.c | 29 ++--- 1 files changed, 22 insertions(+), 7 deletions(-) diff --git a/arch/powerpc/sysdev/cpm2_pic.c b/arch/powerpc/sysdev/cpm2_pic.c index 78f1f7c..179822c 100644 --- a/arch/powerpc/sysdev/cpm2_pic.c +++ b/arch/powerpc/sysdev/cpm2_pic.c @@ -141,13 +141,28 @@ static int cpm2_set_irq_type(unsigned int virq, unsigned int flow_type) struct irq_desc *desc = get_irq_desc(virq); unsigned int vold, vnew, edibit; - if (flow_type == IRQ_TYPE_NONE) - flow_type = IRQ_TYPE_LEVEL_LOW; - - if (flow_type IRQ_TYPE_EDGE_RISING) { - printk(KERN_ERR CPM2 PIC: sense type 0x%x not supported\n, - flow_type); - return -EINVAL; + /* Port C interrupts are either IRQ_TYPE_EDGE_FALLING or + * IRQ_TYPE_EDGE_BOTH (default). All others are IRQ_TYPE_EDGE_FALLING + * or IRQ_TYPE_LEVEL_LOW (default) + */ + if (src = CPM2_IRQ_PORTC15 src = CPM2_IRQ_PORTC0) { + if (flow_type == IRQ_TYPE_NONE) + flow_type = IRQ_TYPE_EDGE_BOTH; + + if (flow_type ~IRQ_TYPE_EDGE_BOTH) { + printk(KERN_ERR CPM2 PIC: sense type 0x%x not supported\n, + flow_type); + return -EINVAL; + } + } else { + if (flow_type == IRQ_TYPE_NONE) + flow_type = IRQ_TYPE_LEVEL_LOW; + + if (flow_type (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_LEVEL_HIGH)) { + printk(KERN_ERR CPM2 PIC: sense type 0x%x not supported\n, + flow_type); + return -EINVAL; + } } desc-status = ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL); ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [PATCH] cpm2_pic: Allow correct flow_types for port C interrupts
Scott Wood wrote: Mark Ware wrote: Mark Ware wrote: CPM2 Port C interrupts can be either falling edge, or either edge. Other external interrupts are either falling edge or active low. [snip] +/* Port C interrupts are either IRQ_TYPE_EDGE_FALLING or + * IRQ_TYPE_EDGE_BOTH (default). All others are IRQ_TYPE_EDGE_FALLING + * or IRQ_TYPE_LEVEL_LOW (default) + */ +if (src = CPM2_IRQ_PORTC15 src = CPM2_IRQ_PORTC0) { +if (flow_type == IRQ_TYPE_NONE) +flow_type = IRQ_TYPE_EDGE_BOTH; + +if (flow_type ~IRQ_TYPE_EDGE_BOTH) { +printk(KERN_ERR CPM2 PIC: sense type 0x%x not supported\n, +flow_type); +return -EINVAL; +} The above code looks like it would allow rising-only, which according to the changelog isn't supported. -Scott Thanks Scott, you're right. I'll update and send v2 shortly. - Mark ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v2] cpm2_pic: Allow correct flow_types for port C interrupts
Port C interrupts can be either falling edge, or either edge. Other external interrupts are either falling edge or active low. Signed-Off-By: Mark Ware mw...@elphinstone.net --- Changed in v2: - Disallow rising edge only on Port C arch/powerpc/sysdev/cpm2_pic.c | 30 +++--- 1 files changed, 23 insertions(+), 7 deletions(-) diff --git a/arch/powerpc/sysdev/cpm2_pic.c b/arch/powerpc/sysdev/cpm2_pic.c index 78f1f7c..eba5f24 100644 --- a/arch/powerpc/sysdev/cpm2_pic.c +++ b/arch/powerpc/sysdev/cpm2_pic.c @@ -141,13 +141,29 @@ static int cpm2_set_irq_type(unsigned int virq, unsigned int flow_type) struct irq_desc *desc = get_irq_desc(virq); unsigned int vold, vnew, edibit; - if (flow_type == IRQ_TYPE_NONE) - flow_type = IRQ_TYPE_LEVEL_LOW; - - if (flow_type IRQ_TYPE_EDGE_RISING) { - printk(KERN_ERR CPM2 PIC: sense type 0x%x not supported\n, - flow_type); - return -EINVAL; + /* Port C interrupts are either IRQ_TYPE_EDGE_FALLING or +* IRQ_TYPE_EDGE_BOTH (default). All others are IRQ_TYPE_EDGE_FALLING +* or IRQ_TYPE_LEVEL_LOW (default) +*/ + if (src = CPM2_IRQ_PORTC15 src = CPM2_IRQ_PORTC0) { + if (flow_type == IRQ_TYPE_NONE) + flow_type = IRQ_TYPE_EDGE_BOTH; + + if ((flow_type != IRQ_TYPE_EDGE_BOTH) + (flow_type != IRQ_TYPE_EDGE_FALLING)) { + printk(KERN_ERR CPM2 PIC: sense type 0x%x not supported\n, + flow_type); + return -EINVAL; + } + } else { + if (flow_type == IRQ_TYPE_NONE) + flow_type = IRQ_TYPE_LEVEL_LOW; + + if (flow_type (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_LEVEL_HIGH)) { + printk(KERN_ERR CPM2 PIC: sense type 0x%x not supported\n, + flow_type); + return -EINVAL; + } } desc-status = ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL); -- 1.5.6.5 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH] cpm2_pic: Allow correct flow_types for port C interrupts
CPM2 Port C interrupts can be either falling edge, or either edge. Other external interrupts are either falling edge or active low. Signed-Off-By: Mark Ware mw...@elphinstone.net --- arch/powerpc/sysdev/cpm2_pic.c | 29 ++--- 1 files changed, 22 insertions(+), 7 deletions(-) diff --git a/arch/powerpc/sysdev/cpm2_pic.c b/arch/powerpc/sysdev/cpm2_pic.c index 78f1f7c..179822c 100644 --- a/arch/powerpc/sysdev/cpm2_pic.c +++ b/arch/powerpc/sysdev/cpm2_pic.c @@ -141,13 +141,28 @@ static int cpm2_set_irq_type(unsigned int virq, unsigned int flow_type) struct irq_desc *desc = get_irq_desc(virq); unsigned int vold, vnew, edibit; - if (flow_type == IRQ_TYPE_NONE) - flow_type = IRQ_TYPE_LEVEL_LOW; - - if (flow_type IRQ_TYPE_EDGE_RISING) { - printk(KERN_ERR CPM2 PIC: sense type 0x%x not supported\n, - flow_type); - return -EINVAL; + /* Port C interrupts are either IRQ_TYPE_EDGE_FALLING or +* IRQ_TYPE_EDGE_BOTH (default). All others are IRQ_TYPE_EDGE_FALLING +* or IRQ_TYPE_LEVEL_LOW (default) +*/ + if (src = CPM2_IRQ_PORTC15 src = CPM2_IRQ_PORTC0) { + if (flow_type == IRQ_TYPE_NONE) + flow_type = IRQ_TYPE_EDGE_BOTH; + + if (flow_type ~IRQ_TYPE_EDGE_BOTH) { + printk(KERN_ERR CPM2 PIC: sense type 0x%x not supported\n, + flow_type); + return -EINVAL; + } + } else { + if (flow_type == IRQ_TYPE_NONE) + flow_type = IRQ_TYPE_LEVEL_LOW; + + if (flow_type (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_LEVEL_HIGH)) { + printk(KERN_ERR CPM2 PIC: sense type 0x%x not supported\n, + flow_type); + return -EINVAL; + } } desc-status = ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL); -- 1.5.6.5 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v3 RESEND] 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. 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: Mark Ware mw...@elphinstone.net Acked-by: Grant Likely grant.lik...@secretlab.ca --- The only changes in v3 are to the commit message. Resent due to patch mangling by mail client. This time for sure... 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)) - add_phy(pdata, np); + new_bus = mdio_gpio_bus_init(ofdev-dev, pdata, pdata-mdc
Re: [PATCH v3] net: Rework mdio-ofgpio driver to use of_mdioinfrastructure
On Thu 23/07/09 2:10 AM , David Miller da...@davemloft.net sent: Your email client has massively corrupted this patch, I even tried to fix it up but it's so bad that I just gave up half-way through. Please use an attachment or whatever is necessary to get this patch submitted cleanly and without it getting damaged. Read: linux/Documentation/email-clients.txt for tips. Thanks. Sorry for the waste of time. I've obviously somehow broken my thunderbird config. Patch is attached, hopefully with correct MIME type - this webmail client is worse than Outlook. (Incidently, I was able to apply the corrupted patch after the following two substitutions: s/^ / / and s/^$/ /) Regards, Mark ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: Re: [PATCH v3] net: Rework mdio-ofgpio driver to use of_mdio infrastructure
On Thu 23/07/09 2:10 AM , David Miller da...@davemloft.net sent: Your email client has massively corrupted this patch, I even tried to fix it up but it's so bad that I just gave up half-way through. Please use an attachment or whatever is necessary to get this patch submitted cleanly and without it getting damaged. Read: linux/Documentation/email-clients.txt for tips. Thanks. Dave, The patch is actually attached this time. (I hope - did I mention my dislike for this webmail interface?) Sorry for the further noise. Regards, Mark ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[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)) -
[PATCH v3] 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. 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: Mark Ware mw...@elphinstone.net Acked-by: Grant Likely grant.lik...@secretlab.ca --- The only changes in v3 are to the commit message. 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)) - 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
[RFC/PATCH] powerpc: Don't use alloc_bootmem in cpm_uart_cpm2.c
This is another alloc_bootmem() - kzalloc() change, this time to fix the non-fatal badness caused when booting with a cpm2_uart console. Signed-Off-By: Mark Ware mw...@elphinstone.net --- drivers/serial/cpm_uart/cpm_uart_cpm2.c |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/drivers/serial/cpm_uart/cpm_uart_cpm2.c b/drivers/serial/cpm_uart/cpm_uart_cpm2.c index 141c0a3..a9802e7 100644 --- a/drivers/serial/cpm_uart/cpm_uart_cpm2.c +++ b/drivers/serial/cpm_uart/cpm_uart_cpm2.c @@ -132,7 +132,7 @@ int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con) memsz = L1_CACHE_ALIGN(pinfo-rx_nrfifos * pinfo-rx_fifosize) + L1_CACHE_ALIGN(pinfo-tx_nrfifos * pinfo-tx_fifosize); if (is_con) { - mem_addr = alloc_bootmem(memsz); + mem_addr = kzalloc(memsz, GFP_NOWAIT); dma_addr = virt_to_bus(mem_addr); } else -- 1.5.6.5 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [PATCH] i2c-cpm: Pass dev ptr to dma_*_coherent rather than NULL
Ben Dooks wrote: On Wed, Apr 29, 2009 at 08:43:14AM -0500, Kumar Gala wrote: On Apr 22, 2009, at 4:56 PM, Ben Dooks wrote: On Tue, Apr 21, 2009 at 10:11:51AM -0500, Kumar Gala wrote: On Apr 21, 2009, at 7:49 AM, Mark Ware wrote: Recent DMA changes result in a BUG() when NULL is passed to dma_alloc_coherent in place of a device. Signed-off-by: Mark Ware mw...@elphinstone.net --- This patch fixes the BUG() during boot that has appeared during the 2.6.30 window. It has been tested and appears correct on my 8280 based board. Sent to both linuxppc-dev and linux-i2c, since I'm not sure where it belongs. drivers/i2c/busses/i2c-cpm.c | 14 -- 1 files changed, 8 insertions(+), 6 deletions(-) Acked-by: Kumar Gala ga...@kernel.crashing.org Ben, I'm expecting you to pick this up unless you tell me otherwise. Yes. This go in yet? I've had to do a manual apply due to some changes in the driver, so can someone please do a build of my git tree at: git://aeryn.fluff.org.uk/bjdooks/linux.git i2c-for-2630-rc5 or tell me which arch and defconfig to build. Ping. Is there anything still blocking this? Mark Ware ___ Linuxppc-dev mailing list Linuxppc-dev@ozlabs.org https://ozlabs.org/mailman/listinfo/linuxppc-dev
Re: [PATCH] i2c-cpm: Pass dev ptr to dma_*_coherent rather than NULL
Ben Dooks wrote: On Wed, Apr 29, 2009 at 08:43:14AM -0500, Kumar Gala wrote: On Apr 22, 2009, at 4:56 PM, Ben Dooks wrote: On Tue, Apr 21, 2009 at 10:11:51AM -0500, Kumar Gala wrote: On Apr 21, 2009, at 7:49 AM, Mark Ware wrote: Recent DMA changes result in a BUG() when NULL is passed to dma_alloc_coherent in place of a device. Signed-off-by: Mark Ware mw...@elphinstone.net --- This patch fixes the BUG() during boot that has appeared during the 2.6.30 window. It has been tested and appears correct on my 8280 based board. Sent to both linuxppc-dev and linux-i2c, since I'm not sure where it belongs. drivers/i2c/busses/i2c-cpm.c | 14 -- 1 files changed, 8 insertions(+), 6 deletions(-) Acked-by: Kumar Gala ga...@kernel.crashing.org Ben, I'm expecting you to pick this up unless you tell me otherwise. Yes. This go in yet? I've had to do a manual apply due to some changes in the driver, so can someone please do a build of my git tree at: git://aeryn.fluff.org.uk/bjdooks/linux.git i2c-for-2630-rc5 or tell me which arch and defconfig to build. Fails to build, due to a typo. Once fixed (diff below), it builds and tests OK on my MPC8280 based hardware Thanks. Mark diff --git a/drivers/i2c/busses/i2c-cpm.c b/drivers/i2c/busses/i2c-cpm.c index b4c0448..b5db8b8 100644 --- a/drivers/i2c/busses/i2c-cpm.c +++ b/drivers/i2c/busses/i2c-cpm.c @@ -585,7 +585,7 @@ static int __devinit cpm_i2c_setup(struct cpm_i2c *cpm) out_muram: for (i = 0; i CPM_MAXBD; i++) { if (cpm-rxbuf[i]) - dma_free_coherent(cpm-ofdev-devL, CPM_MAX_READ + 1, + dma_free_coherent(cpm-ofdev-dev, CPM_MAX_READ + 1, cpm-rxbuf[i], cpm-rxdma[i]); if (cpm-txbuf[i]) dma_free_coherent(cpm-ofdev-dev, CPM_MAX_READ + 1, ___ Linuxppc-dev mailing list Linuxppc-dev@ozlabs.org https://ozlabs.org/mailman/listinfo/linuxppc-dev
[PATCH] i2c-cpm: Pass dev ptr to dma_*_coherent rather than NULL
Recent DMA changes result in a BUG() when NULL is passed to dma_alloc_coherent in place of a device. Signed-off-by: Mark Ware mw...@elphinstone.net --- This patch fixes the BUG() during boot that has appeared during the 2.6.30 window. It has been tested and appears correct on my 8280 based board. Sent to both linuxppc-dev and linux-i2c, since I'm not sure where it belongs. drivers/i2c/busses/i2c-cpm.c | 14 -- 1 files changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/i2c/busses/i2c-cpm.c b/drivers/i2c/busses/i2c-cpm.c index 3fcf78e..83276d2 100644 --- a/drivers/i2c/busses/i2c-cpm.c +++ b/drivers/i2c/busses/i2c-cpm.c @@ -532,7 +532,8 @@ static int __devinit cpm_i2c_setup(struct cpm_i2c *cpm) for (i = 0; i CPM_MAXBD; i++) { cpm-rxbuf[i] = dma_alloc_coherent( - NULL, CPM_MAX_READ + 1, cpm-rxdma[i], GFP_KERNEL); + cpm-ofdev-dev, CPM_MAX_READ + 1, cpm-rxdma[i], + GFP_KERNEL); if (!cpm-rxbuf[i]) { ret = -ENOMEM; goto out_muram; @@ -540,7 +541,8 @@ static int __devinit cpm_i2c_setup(struct cpm_i2c *cpm) out_be32(rbdf[i].cbd_bufaddr, ((cpm-rxdma[i] + 1) ~1)); cpm-txbuf[i] = (unsigned char *)dma_alloc_coherent( - NULL, CPM_MAX_READ + 1, cpm-txdma[i], GFP_KERNEL); + cpm-ofdev-dev, CPM_MAX_READ + 1, cpm-txdma[i], + GFP_KERNEL); if (!cpm-txbuf[i]) { ret = -ENOMEM; goto out_muram; @@ -585,10 +587,10 @@ static int __devinit cpm_i2c_setup(struct cpm_i2c *cpm) out_muram: for (i = 0; i CPM_MAXBD; i++) { if (cpm-rxbuf[i]) - dma_free_coherent(NULL, CPM_MAX_READ + 1, + dma_free_coherent(cpm-ofdev-dev, CPM_MAX_READ + 1, cpm-rxbuf[i], cpm-rxdma[i]); if (cpm-txbuf[i]) - dma_free_coherent(NULL, CPM_MAX_READ + 1, + dma_free_coherent(cpm-ofdev-dev, CPM_MAX_READ + 1, cpm-txbuf[i], cpm-txdma[i]); } cpm_muram_free(cpm-dp_addr); @@ -619,9 +621,9 @@ static void cpm_i2c_shutdown(struct cpm_i2c *cpm) /* Free all memory */ for (i = 0; i CPM_MAXBD; i++) { - dma_free_coherent(NULL, CPM_MAX_READ + 1, + dma_free_coherent(cpm-ofdev-dev, CPM_MAX_READ + 1, cpm-rxbuf[i], cpm-rxdma[i]); - dma_free_coherent(NULL, CPM_MAX_READ + 1, + dma_free_coherent(cpm-ofdev-dev, CPM_MAX_READ + 1, cpm-txbuf[i], cpm-txdma[i]); } -- 1.5.6.5 ___ Linuxppc-dev mailing list Linuxppc-dev@ozlabs.org https://ozlabs.org/mailman/listinfo/linuxppc-dev
RE: CPM2 mii-bitbang: Allowing mdio on port pins other than port C
Hi Laurent, -Original Message- From: Laurent Pinchart [mailto:[EMAIL PROTECTED] Sent: Monday, 16 June 2008 18:53 To: linuxppc-dev@ozlabs.org Cc: Mark Ware Subject: Re: CPM2 mii-bitbang: Allowing mdio on port pins other than port C Hi Mark, On Monday 16 June 2008 08:19, Mark Ware wrote: Hello, I am preparing a board port (from 2.4.18!) for a proprietary board which has it's mdio on a different port than mdc. The current mii-bitbang driver in fs_enet assumes both pins are connected to port C. I have created a fairly simple patch to make this more flexible, but I'm new to device trees and am unsure how best to describe the situation in the dts. The current mdio node for CPM2 looks something like: [EMAIL PROTECTED] { device_type = mdio; compatible = fsl,cpm2-mdio-bitbang; #address-cells = 1; #size-cells = 0 reg = 0x10d40 0x14; fsl,mdio-pin = 12; fsl,mdc-pin = 15; } I have made mdio work on our board by adding a second reg range and using the first one for mdc and the second one for mdio: reg = 0x10d40 0x14 0x10d60 0x14; // mdc=port D, mdio=port A fsl,mdio-pin = 12;// PD12 fsl,mdc-pin = 15; // PC15 The code remains backwards compatible, in that if only one reg range is present it is used for both. Is this a valid (and acceptable) way to extend the reg property? It is. Sergej Stepanov submitted similar patches some times ago. You can find them at http://www.spinics.net/lists/netdev/msg45778.html http://www.spinics.net/lists/netdev/msg47159.html Is their a cleaner way I should look at? Using the GPIO lib might be cleaner. Have a look at http://www.nabble.com/-PATCH-0-2--MDIO-on-GPIO-support-for-the -fs_enet-driver-ts17468958.html for a patch. Thanks for the links. It looks like I should have been searching in netdev not powerpc for this. I will look at Sergej's patch and perhaps submit a merged version, but with the GPIO version likely to be merged is there much point? The GPIO lib method appears to be a more generic replacement. Regards, Mark ___ Linuxppc-dev mailing list Linuxppc-dev@ozlabs.org https://ozlabs.org/mailman/listinfo/linuxppc-dev
CPM2 mii-bitbang: Allowing mdio on port pins other than port C
Hello, I am preparing a board port (from 2.4.18!) for a proprietary board which has it's mdio on a different port than mdc. The current mii-bitbang driver in fs_enet assumes both pins are connected to port C. I have created a fairly simple patch to make this more flexible, but I'm new to device trees and am unsure how best to describe the situation in the dts. The current mdio node for CPM2 looks something like: [EMAIL PROTECTED] { device_type = mdio; compatible = fsl,cpm2-mdio-bitbang; #address-cells = 1; #size-cells = 0 reg = 0x10d40 0x14; fsl,mdio-pin = 12; fsl,mdc-pin = 15; } I have made mdio work on our board by adding a second reg range and using the first one for mdc and the second one for mdio: reg = 0x10d40 0x14 0x10d60 0x14; // mdc=port D, mdio=port A fsl,mdio-pin = 12;// PD12 fsl,mdc-pin = 15; // PC15 The code remains backwards compatible, in that if only one reg range is present it is used for both. Is this a valid (and acceptable) way to extend the reg property? Is their a cleaner way I should look at? Regards, Mark Ware B2010.dts Description: B2010.dts B2010.dts Description: B2010.dts ___ Linuxppc-dev mailing list Linuxppc-dev@ozlabs.org https://ozlabs.org/mailman/listinfo/linuxppc-dev