fsl_pq_mdio: Fix kernel oops during OF address translation

Old P1020RDB device trees were not specifing tbipa address for
MDIO nodes, which is now causing this kernel oops:

 ...
 eth2: TX BD ring size for Q[6]: 256
 eth2: TX BD ring size for Q[7]: 256
 Unable to handle kernel paging request for data at address 0x00000000
 Faulting instruction address: 0xc0015504
 Oops: Kernel access of bad area, sig: 11 [#1]
 ...
 NIP [c0015504] memcpy+0x3c/0x9c
 LR [c000a9f8] __of_translate_address+0xfc/0x21c
 Call Trace:
 [df839e00] [c000a94c] __of_translate_address+0x50/0x21c (unreliable)
 [df839e50] [c01a33e8] get_gfar_tbipa+0xb0/0xe0
 ...

The old device trees are buggy, though having a dead ethernet is
better than a dead kernel, so fix the issue by using of_iomap().

Also, a somewhat similar issue exist in the probe() routine, though
there the oops is only a possibility. Nonetheless, fix it too.

Signed-off-by: Anton Vorontsov <avorontsov@mvista.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Anton Vorontsov 2010-04-23 07:12:35 +00:00 committed by David S. Miller
parent fda48a0d7a
commit 3b1fd3e55a

View file

@ -205,8 +205,6 @@ static int fsl_pq_mdio_find_free(struct mii_bus *new_bus)
static u32 __iomem *get_gfar_tbipa(struct fsl_pq_mdio __iomem *regs, struct device_node *np) static u32 __iomem *get_gfar_tbipa(struct fsl_pq_mdio __iomem *regs, struct device_node *np)
{ {
struct gfar __iomem *enet_regs; struct gfar __iomem *enet_regs;
u32 __iomem *ioremap_tbipa;
u64 addr, size;
/* /*
* This is mildly evil, but so is our hardware for doing this. * This is mildly evil, but so is our hardware for doing this.
@ -220,9 +218,7 @@ static u32 __iomem *get_gfar_tbipa(struct fsl_pq_mdio __iomem *regs, struct devi
return &enet_regs->tbipa; return &enet_regs->tbipa;
} else if (of_device_is_compatible(np, "fsl,etsec2-mdio") || } else if (of_device_is_compatible(np, "fsl,etsec2-mdio") ||
of_device_is_compatible(np, "fsl,etsec2-tbi")) { of_device_is_compatible(np, "fsl,etsec2-tbi")) {
addr = of_translate_address(np, of_get_address(np, 1, &size, NULL)); return of_iomap(np, 1);
ioremap_tbipa = ioremap(addr, size);
return ioremap_tbipa;
} else } else
return NULL; return NULL;
} }
@ -279,6 +275,7 @@ static int fsl_pq_mdio_probe(struct of_device *ofdev,
u32 __iomem *tbipa; u32 __iomem *tbipa;
struct mii_bus *new_bus; struct mii_bus *new_bus;
int tbiaddr = -1; int tbiaddr = -1;
const u32 *addrp;
u64 addr = 0, size = 0; u64 addr = 0, size = 0;
int err = 0; int err = 0;
@ -297,8 +294,19 @@ static int fsl_pq_mdio_probe(struct of_device *ofdev,
new_bus->priv = priv; new_bus->priv = priv;
fsl_pq_mdio_bus_name(new_bus->id, np); fsl_pq_mdio_bus_name(new_bus->id, np);
addrp = of_get_address(np, 0, &size, NULL);
if (!addrp) {
err = -EINVAL;
goto err_free_bus;
}
/* Set the PHY base address */ /* Set the PHY base address */
addr = of_translate_address(np, of_get_address(np, 0, &size, NULL)); addr = of_translate_address(np, addrp);
if (addr == OF_BAD_ADDR) {
err = -EINVAL;
goto err_free_bus;
}
map = ioremap(addr, size); map = ioremap(addr, size);
if (!map) { if (!map) {
err = -ENOMEM; err = -ENOMEM;