From f1dd1993dbd1b9eb3ea92fc1e7af9857d4cefe57 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Tue, 29 Aug 2017 13:35:15 -0700 Subject: net: systemport: Use correct I/O accessors The SYSTEMPORT driver currently uses __raw_{read,write}l which means native I/O endian. This works correctly for an ARM LE kernel (default) but fails miserably on an ARM BE (BE8) kernel where registers are kept little endian, so replace uses with {read,write}l_relaxed here which is what we want because this is all performance sensitive code. Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bcmsysport.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bcmsysport.c b/drivers/net/ethernet/broadcom/bcmsysport.c index b3a21418f511..a7e84292af50 100644 --- a/drivers/net/ethernet/broadcom/bcmsysport.c +++ b/drivers/net/ethernet/broadcom/bcmsysport.c @@ -32,13 +32,13 @@ #define BCM_SYSPORT_IO_MACRO(name, offset) \ static inline u32 name##_readl(struct bcm_sysport_priv *priv, u32 off) \ { \ - u32 reg = __raw_readl(priv->base + offset + off); \ + u32 reg = readl_relaxed(priv->base + offset + off); \ return reg; \ } \ static inline void name##_writel(struct bcm_sysport_priv *priv, \ u32 val, u32 off) \ { \ - __raw_writel(val, priv->base + offset + off); \ + writel_relaxed(val, priv->base + offset + off); \ } \ BCM_SYSPORT_IO_MACRO(intrl2_0, SYS_PORT_INTRL2_0_OFFSET); @@ -59,14 +59,14 @@ static inline u32 rdma_readl(struct bcm_sysport_priv *priv, u32 off) { if (priv->is_lite && off >= RDMA_STATUS) off += 4; - return __raw_readl(priv->base + SYS_PORT_RDMA_OFFSET + off); + return readl_relaxed(priv->base + SYS_PORT_RDMA_OFFSET + off); } static inline void rdma_writel(struct bcm_sysport_priv *priv, u32 val, u32 off) { if (priv->is_lite && off >= RDMA_STATUS) off += 4; - __raw_writel(val, priv->base + SYS_PORT_RDMA_OFFSET + off); + writel_relaxed(val, priv->base + SYS_PORT_RDMA_OFFSET + off); } static inline u32 tdma_control_bit(struct bcm_sysport_priv *priv, u32 bit) @@ -110,10 +110,10 @@ static inline void dma_desc_set_addr(struct bcm_sysport_priv *priv, dma_addr_t addr) { #ifdef CONFIG_PHYS_ADDR_T_64BIT - __raw_writel(upper_32_bits(addr) & DESC_ADDR_HI_MASK, + writel_relaxed(upper_32_bits(addr) & DESC_ADDR_HI_MASK, d + DESC_ADDR_HI_STATUS_LEN); #endif - __raw_writel(lower_32_bits(addr), d + DESC_ADDR_LO); + writel_relaxed(lower_32_bits(addr), d + DESC_ADDR_LO); } static inline void tdma_port_write_desc_addr(struct bcm_sysport_priv *priv, -- cgit From fdb71a2d1adcaca0df2f73ced7851fe0c85312f8 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Tue, 29 Aug 2017 13:35:16 -0700 Subject: net: dsa: bcm_sf2: Use correct I/O accessors The Starfigther 2 driver currently uses __raw_{read,write}l which means native I/O endian. This works correctly for an ARM LE kernel (default) but fails miserably on an ARM BE (BE8) kernel where registers are kept little endian, so replace uses with {read,write}l_relaxed here which is what we want because this is all performance sensitive code. Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/dsa/bcm_sf2.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/net/dsa/bcm_sf2.h b/drivers/net/dsa/bcm_sf2.h index 7d3030e04f11..d9c96b281fc0 100644 --- a/drivers/net/dsa/bcm_sf2.h +++ b/drivers/net/dsa/bcm_sf2.h @@ -130,12 +130,12 @@ static inline u32 bcm_sf2_mangle_addr(struct bcm_sf2_priv *priv, u32 off) #define SF2_IO_MACRO(name) \ static inline u32 name##_readl(struct bcm_sf2_priv *priv, u32 off) \ { \ - return __raw_readl(priv->name + off); \ + return readl_relaxed(priv->name + off); \ } \ static inline void name##_writel(struct bcm_sf2_priv *priv, \ u32 val, u32 off) \ { \ - __raw_writel(val, priv->name + off); \ + writel_relaxed(val, priv->name + off); \ } \ /* Accesses to 64-bits register requires us to latch the hi/lo pairs @@ -179,23 +179,23 @@ static inline void intrl2_##which##_mask_set(struct bcm_sf2_priv *priv, \ static inline u32 core_readl(struct bcm_sf2_priv *priv, u32 off) { u32 tmp = bcm_sf2_mangle_addr(priv, off); - return __raw_readl(priv->core + tmp); + return readl_relaxed(priv->core + tmp); } static inline void core_writel(struct bcm_sf2_priv *priv, u32 val, u32 off) { u32 tmp = bcm_sf2_mangle_addr(priv, off); - __raw_writel(val, priv->core + tmp); + writel_relaxed(val, priv->core + tmp); } static inline u32 reg_readl(struct bcm_sf2_priv *priv, u16 off) { - return __raw_readl(priv->reg + priv->reg_offsets[off]); + return readl_relaxed(priv->reg + priv->reg_offsets[off]); } static inline void reg_writel(struct bcm_sf2_priv *priv, u32 val, u16 off) { - __raw_writel(val, priv->reg + priv->reg_offsets[off]); + writel_relaxed(val, priv->reg + priv->reg_offsets[off]); } SF2_IO64_MACRO(core); -- cgit From 389a06bc534ec19778598242e40c59bc73d2a87d Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Tue, 29 Aug 2017 13:35:17 -0700 Subject: net: systemport: Set correct RSB endian bits based on host RSB_SWAP0 needs to match the host CPU endian, and it needs to be set for LE and clear for BE. RSB_SWAP1 must always be cleared for SYSTEMPORT Lite. With these settings, we have the Receive Status Block always match the host endian and we do not need to perform any conversion. Since there is not necessarily a CONFIG_CPU_LITTLE_ENDIAN option defined, we test for !CONFIG_CPU_BIG_ENDIAN which is guaranteed to be set. Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bcmsysport.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bcmsysport.c b/drivers/net/ethernet/broadcom/bcmsysport.c index a7e84292af50..931751e4f369 100644 --- a/drivers/net/ethernet/broadcom/bcmsysport.c +++ b/drivers/net/ethernet/broadcom/bcmsysport.c @@ -1762,10 +1762,14 @@ static void rbuf_init(struct bcm_sysport_priv *priv) reg = rbuf_readl(priv, RBUF_CONTROL); reg |= RBUF_4B_ALGN | RBUF_RSB_EN; /* Set a correct RSB format on SYSTEMPORT Lite */ - if (priv->is_lite) { + if (priv->is_lite) reg &= ~RBUF_RSB_SWAP1; + + /* Set a correct RSB format based on host endian */ + if (!IS_ENABLED(CONFIG_CPU_BIG_ENDIAN)) reg |= RBUF_RSB_SWAP0; - } + else + reg &= ~RBUF_RSB_SWAP0; rbuf_writel(priv, reg, RBUF_CONTROL); } -- cgit From cb51a0916ae768ecbb246535fa68bb1ae05e8c97 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Tue, 29 Aug 2017 13:35:18 -0700 Subject: net: phy: mdio-bcm-unimac: Use correct I/O accessors The driver currently uses __raw_{read,write}l which works for all platforms supported: Broadcom MIPS LE/BE (native endian), ARM LE (native endian) but not ARM BE (registers are still LE). Switch to using the proper accessors for all platforms and explain why Broadcom MIPS BE is special here, in doing so, we introduce a couple of helper functions to abstract these differences. Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/phy/mdio-bcm-unimac.c | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/drivers/net/phy/mdio-bcm-unimac.c b/drivers/net/phy/mdio-bcm-unimac.c index 73c5267a11fd..08e0647b85e2 100644 --- a/drivers/net/phy/mdio-bcm-unimac.c +++ b/drivers/net/phy/mdio-bcm-unimac.c @@ -47,18 +47,38 @@ struct unimac_mdio_priv { void *wait_func_data; }; +static inline u32 unimac_mdio_readl(struct unimac_mdio_priv *priv, u32 offset) +{ + /* MIPS chips strapped for BE will automagically configure the + * peripheral registers for CPU-native byte order. + */ + if (IS_ENABLED(CONFIG_MIPS) && IS_ENABLED(CONFIG_CPU_BIG_ENDIAN)) + return __raw_readl(priv->base + offset); + else + return readl_relaxed(priv->base + offset); +} + +static inline void unimac_mdio_writel(struct unimac_mdio_priv *priv, u32 val, + u32 offset) +{ + if (IS_ENABLED(CONFIG_MIPS) && IS_ENABLED(CONFIG_CPU_BIG_ENDIAN)) + __raw_writel(val, priv->base + offset); + else + writel_relaxed(val, priv->base + offset); +} + static inline void unimac_mdio_start(struct unimac_mdio_priv *priv) { u32 reg; - reg = __raw_readl(priv->base + MDIO_CMD); + reg = unimac_mdio_readl(priv, MDIO_CMD); reg |= MDIO_START_BUSY; - __raw_writel(reg, priv->base + MDIO_CMD); + unimac_mdio_writel(priv, reg, MDIO_CMD); } static inline unsigned int unimac_mdio_busy(struct unimac_mdio_priv *priv) { - return __raw_readl(priv->base + MDIO_CMD) & MDIO_START_BUSY; + return unimac_mdio_readl(priv, MDIO_CMD) & MDIO_START_BUSY; } static int unimac_mdio_poll(void *wait_func_data) @@ -87,7 +107,7 @@ static int unimac_mdio_read(struct mii_bus *bus, int phy_id, int reg) /* Prepare the read operation */ cmd = MDIO_RD | (phy_id << MDIO_PMD_SHIFT) | (reg << MDIO_REG_SHIFT); - __raw_writel(cmd, priv->base + MDIO_CMD); + unimac_mdio_writel(priv, cmd, MDIO_CMD); /* Start MDIO transaction */ unimac_mdio_start(priv); @@ -96,7 +116,7 @@ static int unimac_mdio_read(struct mii_bus *bus, int phy_id, int reg) if (ret) return ret; - cmd = __raw_readl(priv->base + MDIO_CMD); + cmd = unimac_mdio_readl(priv, MDIO_CMD); /* Some broken devices are known not to release the line during * turn-around, e.g: Broadcom BCM53125 external switches, so check for @@ -118,7 +138,7 @@ static int unimac_mdio_write(struct mii_bus *bus, int phy_id, /* Prepare the write operation */ cmd = MDIO_WR | (phy_id << MDIO_PMD_SHIFT) | (reg << MDIO_REG_SHIFT) | (0xffff & val); - __raw_writel(cmd, priv->base + MDIO_CMD); + unimac_mdio_writel(priv, cmd, MDIO_CMD); unimac_mdio_start(priv); -- cgit