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:
parent
fda48a0d7a
commit
3b1fd3e55a
1 changed files with 14 additions and 6 deletions
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue