Skip to content

Commit 69d2ea9

Browse files
ffainellidavem330
authored andcommitted
net: bcmgenet: Use correct I/O accessors
The GENET 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 <f.fainelli@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent b6eb9d5 commit 69d2ea9

2 files changed

Lines changed: 58 additions & 30 deletions

File tree

drivers/net/ethernet/broadcom/genet/bcmgenet.c

Lines changed: 47 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -72,31 +72,50 @@
7272
#define GENET_RDMA_REG_OFF (priv->hw_params->rdma_offset + \
7373
TOTAL_DESC * DMA_DESC_SIZE)
7474

75+
static inline void bcmgenet_writel(u32 value, void __iomem *offset)
76+
{
77+
/* MIPS chips strapped for BE will automagically configure the
78+
* peripheral registers for CPU-native byte order.
79+
*/
80+
if (IS_ENABLED(CONFIG_MIPS) && IS_ENABLED(CONFIG_CPU_BIG_ENDIAN))
81+
__raw_writel(value, offset);
82+
else
83+
writel_relaxed(value, offset);
84+
}
85+
86+
static inline u32 bcmgenet_readl(void __iomem *offset)
87+
{
88+
if (IS_ENABLED(CONFIG_MIPS) && IS_ENABLED(CONFIG_CPU_BIG_ENDIAN))
89+
return __raw_readl(offset);
90+
else
91+
return readl_relaxed(offset);
92+
}
93+
7594
static inline void dmadesc_set_length_status(struct bcmgenet_priv *priv,
7695
void __iomem *d, u32 value)
7796
{
78-
__raw_writel(value, d + DMA_DESC_LENGTH_STATUS);
97+
bcmgenet_writel(value, d + DMA_DESC_LENGTH_STATUS);
7998
}
8099

81100
static inline u32 dmadesc_get_length_status(struct bcmgenet_priv *priv,
82101
void __iomem *d)
83102
{
84-
return __raw_readl(d + DMA_DESC_LENGTH_STATUS);
103+
return bcmgenet_readl(d + DMA_DESC_LENGTH_STATUS);
85104
}
86105

87106
static inline void dmadesc_set_addr(struct bcmgenet_priv *priv,
88107
void __iomem *d,
89108
dma_addr_t addr)
90109
{
91-
__raw_writel(lower_32_bits(addr), d + DMA_DESC_ADDRESS_LO);
110+
bcmgenet_writel(lower_32_bits(addr), d + DMA_DESC_ADDRESS_LO);
92111

93112
/* Register writes to GISB bus can take couple hundred nanoseconds
94113
* and are done for each packet, save these expensive writes unless
95114
* the platform is explicitly configured for 64-bits/LPAE.
96115
*/
97116
#ifdef CONFIG_PHYS_ADDR_T_64BIT
98117
if (priv->hw_params->flags & GENET_HAS_40BITS)
99-
__raw_writel(upper_32_bits(addr), d + DMA_DESC_ADDRESS_HI);
118+
bcmgenet_writel(upper_32_bits(addr), d + DMA_DESC_ADDRESS_HI);
100119
#endif
101120
}
102121

@@ -113,15 +132,15 @@ static inline dma_addr_t dmadesc_get_addr(struct bcmgenet_priv *priv,
113132
{
114133
dma_addr_t addr;
115134

116-
addr = __raw_readl(d + DMA_DESC_ADDRESS_LO);
135+
addr = bcmgenet_readl(d + DMA_DESC_ADDRESS_LO);
117136

118137
/* Register writes to GISB bus can take couple hundred nanoseconds
119138
* and are done for each packet, save these expensive writes unless
120139
* the platform is explicitly configured for 64-bits/LPAE.
121140
*/
122141
#ifdef CONFIG_PHYS_ADDR_T_64BIT
123142
if (priv->hw_params->flags & GENET_HAS_40BITS)
124-
addr |= (u64)__raw_readl(d + DMA_DESC_ADDRESS_HI) << 32;
143+
addr |= (u64)bcmgenet_readl(d + DMA_DESC_ADDRESS_HI) << 32;
125144
#endif
126145
return addr;
127146
}
@@ -156,16 +175,16 @@ static inline u32 bcmgenet_tbuf_ctrl_get(struct bcmgenet_priv *priv)
156175
if (GENET_IS_V1(priv))
157176
return bcmgenet_rbuf_readl(priv, TBUF_CTRL_V1);
158177
else
159-
return __raw_readl(priv->base +
160-
priv->hw_params->tbuf_offset + TBUF_CTRL);
178+
return bcmgenet_readl(priv->base +
179+
priv->hw_params->tbuf_offset + TBUF_CTRL);
161180
}
162181

163182
static inline void bcmgenet_tbuf_ctrl_set(struct bcmgenet_priv *priv, u32 val)
164183
{
165184
if (GENET_IS_V1(priv))
166185
bcmgenet_rbuf_writel(priv, val, TBUF_CTRL_V1);
167186
else
168-
__raw_writel(val, priv->base +
187+
bcmgenet_writel(val, priv->base +
169188
priv->hw_params->tbuf_offset + TBUF_CTRL);
170189
}
171190

@@ -174,16 +193,16 @@ static inline u32 bcmgenet_bp_mc_get(struct bcmgenet_priv *priv)
174193
if (GENET_IS_V1(priv))
175194
return bcmgenet_rbuf_readl(priv, TBUF_BP_MC_V1);
176195
else
177-
return __raw_readl(priv->base +
178-
priv->hw_params->tbuf_offset + TBUF_BP_MC);
196+
return bcmgenet_readl(priv->base +
197+
priv->hw_params->tbuf_offset + TBUF_BP_MC);
179198
}
180199

181200
static inline void bcmgenet_bp_mc_set(struct bcmgenet_priv *priv, u32 val)
182201
{
183202
if (GENET_IS_V1(priv))
184203
bcmgenet_rbuf_writel(priv, val, TBUF_BP_MC_V1);
185204
else
186-
__raw_writel(val, priv->base +
205+
bcmgenet_writel(val, priv->base +
187206
priv->hw_params->tbuf_offset + TBUF_BP_MC);
188207
}
189208

@@ -326,28 +345,28 @@ static inline struct bcmgenet_priv *dev_to_priv(struct device *dev)
326345
static inline u32 bcmgenet_tdma_readl(struct bcmgenet_priv *priv,
327346
enum dma_reg r)
328347
{
329-
return __raw_readl(priv->base + GENET_TDMA_REG_OFF +
330-
DMA_RINGS_SIZE + bcmgenet_dma_regs[r]);
348+
return bcmgenet_readl(priv->base + GENET_TDMA_REG_OFF +
349+
DMA_RINGS_SIZE + bcmgenet_dma_regs[r]);
331350
}
332351

333352
static inline void bcmgenet_tdma_writel(struct bcmgenet_priv *priv,
334353
u32 val, enum dma_reg r)
335354
{
336-
__raw_writel(val, priv->base + GENET_TDMA_REG_OFF +
355+
bcmgenet_writel(val, priv->base + GENET_TDMA_REG_OFF +
337356
DMA_RINGS_SIZE + bcmgenet_dma_regs[r]);
338357
}
339358

340359
static inline u32 bcmgenet_rdma_readl(struct bcmgenet_priv *priv,
341360
enum dma_reg r)
342361
{
343-
return __raw_readl(priv->base + GENET_RDMA_REG_OFF +
344-
DMA_RINGS_SIZE + bcmgenet_dma_regs[r]);
362+
return bcmgenet_readl(priv->base + GENET_RDMA_REG_OFF +
363+
DMA_RINGS_SIZE + bcmgenet_dma_regs[r]);
345364
}
346365

347366
static inline void bcmgenet_rdma_writel(struct bcmgenet_priv *priv,
348367
u32 val, enum dma_reg r)
349368
{
350-
__raw_writel(val, priv->base + GENET_RDMA_REG_OFF +
369+
bcmgenet_writel(val, priv->base + GENET_RDMA_REG_OFF +
351370
DMA_RINGS_SIZE + bcmgenet_dma_regs[r]);
352371
}
353372

@@ -418,16 +437,16 @@ static inline u32 bcmgenet_tdma_ring_readl(struct bcmgenet_priv *priv,
418437
unsigned int ring,
419438
enum dma_ring_reg r)
420439
{
421-
return __raw_readl(priv->base + GENET_TDMA_REG_OFF +
422-
(DMA_RING_SIZE * ring) +
423-
genet_dma_ring_regs[r]);
440+
return bcmgenet_readl(priv->base + GENET_TDMA_REG_OFF +
441+
(DMA_RING_SIZE * ring) +
442+
genet_dma_ring_regs[r]);
424443
}
425444

426445
static inline void bcmgenet_tdma_ring_writel(struct bcmgenet_priv *priv,
427446
unsigned int ring, u32 val,
428447
enum dma_ring_reg r)
429448
{
430-
__raw_writel(val, priv->base + GENET_TDMA_REG_OFF +
449+
bcmgenet_writel(val, priv->base + GENET_TDMA_REG_OFF +
431450
(DMA_RING_SIZE * ring) +
432451
genet_dma_ring_regs[r]);
433452
}
@@ -436,16 +455,16 @@ static inline u32 bcmgenet_rdma_ring_readl(struct bcmgenet_priv *priv,
436455
unsigned int ring,
437456
enum dma_ring_reg r)
438457
{
439-
return __raw_readl(priv->base + GENET_RDMA_REG_OFF +
440-
(DMA_RING_SIZE * ring) +
441-
genet_dma_ring_regs[r]);
458+
return bcmgenet_readl(priv->base + GENET_RDMA_REG_OFF +
459+
(DMA_RING_SIZE * ring) +
460+
genet_dma_ring_regs[r]);
442461
}
443462

444463
static inline void bcmgenet_rdma_ring_writel(struct bcmgenet_priv *priv,
445464
unsigned int ring, u32 val,
446465
enum dma_ring_reg r)
447466
{
448-
__raw_writel(val, priv->base + GENET_RDMA_REG_OFF +
467+
bcmgenet_writel(val, priv->base + GENET_RDMA_REG_OFF +
449468
(DMA_RING_SIZE * ring) +
450469
genet_dma_ring_regs[r]);
451470
}
@@ -991,12 +1010,12 @@ static void bcmgenet_eee_enable_set(struct net_device *dev, bool enable)
9911010
bcmgenet_umac_writel(priv, reg, UMAC_EEE_CTRL);
9921011

9931012
/* Enable EEE and switch to a 27Mhz clock automatically */
994-
reg = __raw_readl(priv->base + off);
1013+
reg = bcmgenet_readl(priv->base + off);
9951014
if (enable)
9961015
reg |= TBUF_EEE_EN | TBUF_PM_EN;
9971016
else
9981017
reg &= ~(TBUF_EEE_EN | TBUF_PM_EN);
999-
__raw_writel(reg, priv->base + off);
1018+
bcmgenet_writel(reg, priv->base + off);
10001019

10011020
/* Do the same for thing for RBUF */
10021021
reg = bcmgenet_rbuf_readl(priv, RBUF_ENERGY_CTRL);

drivers/net/ethernet/broadcom/genet/bcmgenet.h

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -672,12 +672,21 @@ struct bcmgenet_priv {
672672
static inline u32 bcmgenet_##name##_readl(struct bcmgenet_priv *priv, \
673673
u32 off) \
674674
{ \
675-
return __raw_readl(priv->base + offset + off); \
675+
/* MIPS chips strapped for BE will automagically configure the \
676+
* peripheral registers for CPU-native byte order. \
677+
*/ \
678+
if (IS_ENABLED(CONFIG_MIPS) && IS_ENABLED(CONFIG_CPU_BIG_ENDIAN)) \
679+
return __raw_readl(priv->base + offset + off); \
680+
else \
681+
return readl_relaxed(priv->base + offset + off); \
676682
} \
677683
static inline void bcmgenet_##name##_writel(struct bcmgenet_priv *priv, \
678684
u32 val, u32 off) \
679685
{ \
680-
__raw_writel(val, priv->base + offset + off); \
686+
if (IS_ENABLED(CONFIG_MIPS) && IS_ENABLED(CONFIG_CPU_BIG_ENDIAN)) \
687+
return __raw_writel(val, priv->base + offset + off); \
688+
else \
689+
writel_relaxed(val, priv->base + offset + off); \
681690
}
682691

683692
GENET_IO_MACRO(ext, GENET_EXT_OFF);

0 commit comments

Comments
 (0)