Commit b4024c9e authored by Claudiu Manoil's avatar Claudiu Manoil Committed by David S. Miller

felix: Fix initialization of ioremap resources

The caller of devm_ioremap_resource(), either accidentally
or by wrong assumption, is writing back derived resource data
to global static resource initialization tables that should
have been constant.  Meaning that after it computes the final
physical start address it saves the address for no reason
in the static tables.  This doesn't affect the first driver
probing after reboot, but it breaks consecutive driver reloads
(i.e. driver unbind & bind) because the initialization tables
no longer have the correct initial values.  So the next probe()
will map the device registers to wrong physical addresses,
causing ARM SError async exceptions.
This patch fixes all of the above.

Fixes: 56051948 ("net: dsa: ocelot: add driver for Felix switch family")
Signed-off-by: default avatarClaudiu Manoil <claudiu.manoil@nxp.com>
Reviewed-by: default avatarVladimir Oltean <vladimir.oltean@nxp.com>
Tested-by: default avatarVladimir Oltean <vladimir.oltean@nxp.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent bd697222
...@@ -388,6 +388,7 @@ static int felix_init_structs(struct felix *felix, int num_phys_ports) ...@@ -388,6 +388,7 @@ static int felix_init_structs(struct felix *felix, int num_phys_ports)
struct ocelot *ocelot = &felix->ocelot; struct ocelot *ocelot = &felix->ocelot;
phy_interface_t *port_phy_modes; phy_interface_t *port_phy_modes;
resource_size_t switch_base; resource_size_t switch_base;
struct resource res;
int port, i, err; int port, i, err;
ocelot->num_phys_ports = num_phys_ports; ocelot->num_phys_ports = num_phys_ports;
...@@ -422,17 +423,16 @@ static int felix_init_structs(struct felix *felix, int num_phys_ports) ...@@ -422,17 +423,16 @@ static int felix_init_structs(struct felix *felix, int num_phys_ports)
for (i = 0; i < TARGET_MAX; i++) { for (i = 0; i < TARGET_MAX; i++) {
struct regmap *target; struct regmap *target;
struct resource *res;
if (!felix->info->target_io_res[i].name) if (!felix->info->target_io_res[i].name)
continue; continue;
res = &felix->info->target_io_res[i]; memcpy(&res, &felix->info->target_io_res[i], sizeof(res));
res->flags = IORESOURCE_MEM; res.flags = IORESOURCE_MEM;
res->start += switch_base; res.start += switch_base;
res->end += switch_base; res.end += switch_base;
target = ocelot_regmap_init(ocelot, res); target = ocelot_regmap_init(ocelot, &res);
if (IS_ERR(target)) { if (IS_ERR(target)) {
dev_err(ocelot->dev, dev_err(ocelot->dev,
"Failed to map device memory space\n"); "Failed to map device memory space\n");
...@@ -453,7 +453,6 @@ static int felix_init_structs(struct felix *felix, int num_phys_ports) ...@@ -453,7 +453,6 @@ static int felix_init_structs(struct felix *felix, int num_phys_ports)
for (port = 0; port < num_phys_ports; port++) { for (port = 0; port < num_phys_ports; port++) {
struct ocelot_port *ocelot_port; struct ocelot_port *ocelot_port;
void __iomem *port_regs; void __iomem *port_regs;
struct resource *res;
ocelot_port = devm_kzalloc(ocelot->dev, ocelot_port = devm_kzalloc(ocelot->dev,
sizeof(struct ocelot_port), sizeof(struct ocelot_port),
...@@ -465,12 +464,12 @@ static int felix_init_structs(struct felix *felix, int num_phys_ports) ...@@ -465,12 +464,12 @@ static int felix_init_structs(struct felix *felix, int num_phys_ports)
return -ENOMEM; return -ENOMEM;
} }
res = &felix->info->port_io_res[port]; memcpy(&res, &felix->info->port_io_res[port], sizeof(res));
res->flags = IORESOURCE_MEM; res.flags = IORESOURCE_MEM;
res->start += switch_base; res.start += switch_base;
res->end += switch_base; res.end += switch_base;
port_regs = devm_ioremap_resource(ocelot->dev, res); port_regs = devm_ioremap_resource(ocelot->dev, &res);
if (IS_ERR(port_regs)) { if (IS_ERR(port_regs)) {
dev_err(ocelot->dev, dev_err(ocelot->dev,
"failed to map registers for port %d\n", port); "failed to map registers for port %d\n", port);
......
...@@ -8,9 +8,9 @@ ...@@ -8,9 +8,9 @@
/* Platform-specific information */ /* Platform-specific information */
struct felix_info { struct felix_info {
struct resource *target_io_res; const struct resource *target_io_res;
struct resource *port_io_res; const struct resource *port_io_res;
struct resource *imdio_res; const struct resource *imdio_res;
const struct reg_field *regfields; const struct reg_field *regfields;
const u32 *const *map; const u32 *const *map;
const struct ocelot_ops *ops; const struct ocelot_ops *ops;
......
...@@ -333,10 +333,8 @@ static const u32 *vsc9959_regmap[] = { ...@@ -333,10 +333,8 @@ static const u32 *vsc9959_regmap[] = {
[GCB] = vsc9959_gcb_regmap, [GCB] = vsc9959_gcb_regmap,
}; };
/* Addresses are relative to the PCI device's base address and /* Addresses are relative to the PCI device's base address */
* will be fixed up at ioremap time. static const struct resource vsc9959_target_io_res[] = {
*/
static struct resource vsc9959_target_io_res[] = {
[ANA] = { [ANA] = {
.start = 0x0280000, .start = 0x0280000,
.end = 0x028ffff, .end = 0x028ffff,
...@@ -379,7 +377,7 @@ static struct resource vsc9959_target_io_res[] = { ...@@ -379,7 +377,7 @@ static struct resource vsc9959_target_io_res[] = {
}, },
}; };
static struct resource vsc9959_port_io_res[] = { static const struct resource vsc9959_port_io_res[] = {
{ {
.start = 0x0100000, .start = 0x0100000,
.end = 0x010ffff, .end = 0x010ffff,
...@@ -415,7 +413,7 @@ static struct resource vsc9959_port_io_res[] = { ...@@ -415,7 +413,7 @@ static struct resource vsc9959_port_io_res[] = {
/* Port MAC 0 Internal MDIO bus through which the SerDes acting as an /* Port MAC 0 Internal MDIO bus through which the SerDes acting as an
* SGMII/QSGMII MAC PCS can be found. * SGMII/QSGMII MAC PCS can be found.
*/ */
static struct resource vsc9959_imdio_res = { static const struct resource vsc9959_imdio_res = {
.start = 0x8030, .start = 0x8030,
.end = 0x8040, .end = 0x8040,
.name = "imdio", .name = "imdio",
...@@ -1111,7 +1109,7 @@ static int vsc9959_mdio_bus_alloc(struct ocelot *ocelot) ...@@ -1111,7 +1109,7 @@ static int vsc9959_mdio_bus_alloc(struct ocelot *ocelot)
struct device *dev = ocelot->dev; struct device *dev = ocelot->dev;
resource_size_t imdio_base; resource_size_t imdio_base;
void __iomem *imdio_regs; void __iomem *imdio_regs;
struct resource *res; struct resource res;
struct enetc_hw *hw; struct enetc_hw *hw;
struct mii_bus *bus; struct mii_bus *bus;
int port; int port;
...@@ -1128,12 +1126,12 @@ static int vsc9959_mdio_bus_alloc(struct ocelot *ocelot) ...@@ -1128,12 +1126,12 @@ static int vsc9959_mdio_bus_alloc(struct ocelot *ocelot)
imdio_base = pci_resource_start(felix->pdev, imdio_base = pci_resource_start(felix->pdev,
felix->info->imdio_pci_bar); felix->info->imdio_pci_bar);
res = felix->info->imdio_res; memcpy(&res, felix->info->imdio_res, sizeof(res));
res->flags = IORESOURCE_MEM; res.flags = IORESOURCE_MEM;
res->start += imdio_base; res.start += imdio_base;
res->end += imdio_base; res.end += imdio_base;
imdio_regs = devm_ioremap_resource(dev, res); imdio_regs = devm_ioremap_resource(dev, &res);
if (IS_ERR(imdio_regs)) { if (IS_ERR(imdio_regs)) {
dev_err(dev, "failed to map internal MDIO registers\n"); dev_err(dev, "failed to map internal MDIO registers\n");
return PTR_ERR(imdio_regs); return PTR_ERR(imdio_regs);
......
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