Skip to content

Commit f2ce8a9

Browse files
andy-shevdavem330
authored andcommitted
net/macb: improve big endian CPU support
The commit a50dad3 (net: macb: Add big endian CPU support) converted I/O accessors to readl_relaxed() and writel_relaxed() and consequentially broke MACB driver on AVR32 platforms such as ATNGW100. This patch improves I/O access by checking endiannes first and use the corresponding methods. Fixes: a50dad3 (net: macb: Add big endian CPU support) Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent dfbafc9 commit f2ce8a9

File tree

2 files changed

+87
-44
lines changed

2 files changed

+87
-44
lines changed

drivers/net/ethernet/cadence/macb.c

Lines changed: 76 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,57 @@ static void *macb_rx_buffer(struct macb *bp, unsigned int index)
104104
return bp->rx_buffers + bp->rx_buffer_size * macb_rx_ring_wrap(index);
105105
}
106106

107+
/* I/O accessors */
108+
static u32 hw_readl_native(struct macb *bp, int offset)
109+
{
110+
return __raw_readl(bp->regs + offset);
111+
}
112+
113+
static void hw_writel_native(struct macb *bp, int offset, u32 value)
114+
{
115+
__raw_writel(value, bp->regs + offset);
116+
}
117+
118+
static u32 hw_readl(struct macb *bp, int offset)
119+
{
120+
return readl_relaxed(bp->regs + offset);
121+
}
122+
123+
static void hw_writel(struct macb *bp, int offset, u32 value)
124+
{
125+
writel_relaxed(value, bp->regs + offset);
126+
}
127+
128+
/*
129+
* Find the CPU endianness by using the loopback bit of NCR register. When the
130+
* CPU is in big endian we need to program swaped mode for management
131+
* descriptor access.
132+
*/
133+
static bool hw_is_native_io(void __iomem *addr)
134+
{
135+
u32 value = MACB_BIT(LLB);
136+
137+
__raw_writel(value, addr + MACB_NCR);
138+
value = __raw_readl(addr + MACB_NCR);
139+
140+
/* Write 0 back to disable everything */
141+
__raw_writel(0, addr + MACB_NCR);
142+
143+
return value == MACB_BIT(LLB);
144+
}
145+
146+
static bool hw_is_gem(void __iomem *addr, bool native_io)
147+
{
148+
u32 id;
149+
150+
if (native_io)
151+
id = __raw_readl(addr + MACB_MID);
152+
else
153+
id = readl_relaxed(addr + MACB_MID);
154+
155+
return MACB_BFEXT(IDNUM, id) >= 0x2;
156+
}
157+
107158
static void macb_set_hwaddr(struct macb *bp)
108159
{
109160
u32 bottom;
@@ -449,14 +500,14 @@ static int macb_mii_init(struct macb *bp)
449500

450501
static void macb_update_stats(struct macb *bp)
451502
{
452-
u32 __iomem *reg = bp->regs + MACB_PFR;
453503
u32 *p = &bp->hw_stats.macb.rx_pause_frames;
454504
u32 *end = &bp->hw_stats.macb.tx_pause_frames + 1;
505+
int offset = MACB_PFR;
455506

456507
WARN_ON((unsigned long)(end - p - 1) != (MACB_TPF - MACB_PFR) / 4);
457508

458-
for(; p < end; p++, reg++)
459-
*p += readl_relaxed(reg);
509+
for(; p < end; p++, offset += 4)
510+
*p += bp->readl(bp, offset);
460511
}
461512

462513
static int macb_halt_tx(struct macb *bp)
@@ -1603,7 +1654,6 @@ static u32 macb_dbw(struct macb *bp)
16031654
static void macb_configure_dma(struct macb *bp)
16041655
{
16051656
u32 dmacfg;
1606-
u32 tmp, ncr;
16071657

16081658
if (macb_is_gem(bp)) {
16091659
dmacfg = gem_readl(bp, DMACFG) & ~GEM_BF(RXBS, -1L);
@@ -1613,22 +1663,11 @@ static void macb_configure_dma(struct macb *bp)
16131663
dmacfg |= GEM_BIT(TXPBMS) | GEM_BF(RXBMS, -1L);
16141664
dmacfg &= ~GEM_BIT(ENDIA_PKT);
16151665

1616-
/* Find the CPU endianness by using the loopback bit of net_ctrl
1617-
* register. save it first. When the CPU is in big endian we
1618-
* need to program swaped mode for management descriptor access.
1619-
*/
1620-
ncr = macb_readl(bp, NCR);
1621-
__raw_writel(MACB_BIT(LLB), bp->regs + MACB_NCR);
1622-
tmp = __raw_readl(bp->regs + MACB_NCR);
1623-
1624-
if (tmp == MACB_BIT(LLB))
1666+
if (bp->native_io)
16251667
dmacfg &= ~GEM_BIT(ENDIA_DESC);
16261668
else
16271669
dmacfg |= GEM_BIT(ENDIA_DESC); /* CPU in big endian */
16281670

1629-
/* Restore net_ctrl */
1630-
macb_writel(bp, NCR, ncr);
1631-
16321671
if (bp->dev->features & NETIF_F_HW_CSUM)
16331672
dmacfg |= GEM_BIT(TXCOEN);
16341673
else
@@ -1902,14 +1941,14 @@ static void gem_update_stats(struct macb *bp)
19021941

19031942
for (i = 0; i < GEM_STATS_LEN; ++i, ++p) {
19041943
u32 offset = gem_statistics[i].offset;
1905-
u64 val = readl_relaxed(bp->regs + offset);
1944+
u64 val = bp->readl(bp, offset);
19061945

19071946
bp->ethtool_stats[i] += val;
19081947
*p += val;
19091948

19101949
if (offset == GEM_OCTTXL || offset == GEM_OCTRXL) {
19111950
/* Add GEM_OCTTXH, GEM_OCTRXH */
1912-
val = readl_relaxed(bp->regs + offset + 4);
1951+
val = bp->readl(bp, offset + 4);
19131952
bp->ethtool_stats[i] += ((u64)val) << 32;
19141953
*(++p) += val;
19151954
}
@@ -2190,7 +2229,7 @@ static void macb_configure_caps(struct macb *bp, const struct macb_config *dt_co
21902229
if (dt_conf)
21912230
bp->caps = dt_conf->caps;
21922231

2193-
if (macb_is_gem_hw(bp->regs)) {
2232+
if (hw_is_gem(bp->regs, bp->native_io)) {
21942233
bp->caps |= MACB_CAPS_MACB_IS_GEM;
21952234

21962235
dcfg = gem_readl(bp, DCFG1);
@@ -2205,6 +2244,7 @@ static void macb_configure_caps(struct macb *bp, const struct macb_config *dt_co
22052244
}
22062245

22072246
static void macb_probe_queues(void __iomem *mem,
2247+
bool native_io,
22082248
unsigned int *queue_mask,
22092249
unsigned int *num_queues)
22102250
{
@@ -2219,7 +2259,7 @@ static void macb_probe_queues(void __iomem *mem,
22192259
* we are early in the probe process and don't have the
22202260
* MACB_CAPS_MACB_IS_GEM flag positioned
22212261
*/
2222-
if (!macb_is_gem_hw(mem))
2262+
if (!hw_is_gem(mem, native_io))
22232263
return;
22242264

22252265
/* bit 0 is never set but queue 0 always exists */
@@ -2786,6 +2826,7 @@ static int macb_probe(struct platform_device *pdev)
27862826
struct clk *pclk, *hclk, *tx_clk;
27872827
unsigned int queue_mask, num_queues;
27882828
struct macb_platform_data *pdata;
2829+
bool native_io;
27892830
struct phy_device *phydev;
27902831
struct net_device *dev;
27912832
struct resource *regs;
@@ -2794,6 +2835,11 @@ static int macb_probe(struct platform_device *pdev)
27942835
struct macb *bp;
27952836
int err;
27962837

2838+
regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
2839+
mem = devm_ioremap_resource(&pdev->dev, regs);
2840+
if (IS_ERR(mem))
2841+
return PTR_ERR(mem);
2842+
27972843
if (np) {
27982844
const struct of_device_id *match;
27992845

@@ -2809,14 +2855,9 @@ static int macb_probe(struct platform_device *pdev)
28092855
if (err)
28102856
return err;
28112857

2812-
regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
2813-
mem = devm_ioremap_resource(&pdev->dev, regs);
2814-
if (IS_ERR(mem)) {
2815-
err = PTR_ERR(mem);
2816-
goto err_disable_clocks;
2817-
}
2858+
native_io = hw_is_native_io(mem);
28182859

2819-
macb_probe_queues(mem, &queue_mask, &num_queues);
2860+
macb_probe_queues(mem, native_io, &queue_mask, &num_queues);
28202861
dev = alloc_etherdev_mq(sizeof(*bp), num_queues);
28212862
if (!dev) {
28222863
err = -ENOMEM;
@@ -2831,6 +2872,14 @@ static int macb_probe(struct platform_device *pdev)
28312872
bp->pdev = pdev;
28322873
bp->dev = dev;
28332874
bp->regs = mem;
2875+
bp->native_io = native_io;
2876+
if (native_io) {
2877+
bp->readl = hw_readl_native;
2878+
bp->writel = hw_writel_native;
2879+
} else {
2880+
bp->readl = hw_readl;
2881+
bp->writel = hw_writel;
2882+
}
28342883
bp->num_queues = num_queues;
28352884
bp->queue_mask = queue_mask;
28362885
if (macb_config)

drivers/net/ethernet/cadence/macb.h

Lines changed: 11 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -429,18 +429,12 @@
429429
| GEM_BF(name, value))
430430

431431
/* Register access macros */
432-
#define macb_readl(port,reg) \
433-
readl_relaxed((port)->regs + MACB_##reg)
434-
#define macb_writel(port,reg,value) \
435-
writel_relaxed((value), (port)->regs + MACB_##reg)
436-
#define gem_readl(port, reg) \
437-
readl_relaxed((port)->regs + GEM_##reg)
438-
#define gem_writel(port, reg, value) \
439-
writel_relaxed((value), (port)->regs + GEM_##reg)
440-
#define queue_readl(queue, reg) \
441-
readl_relaxed((queue)->bp->regs + (queue)->reg)
442-
#define queue_writel(queue, reg, value) \
443-
writel_relaxed((value), (queue)->bp->regs + (queue)->reg)
432+
#define macb_readl(port, reg) (port)->readl((port), MACB_##reg)
433+
#define macb_writel(port, reg, value) (port)->writel((port), MACB_##reg, (value))
434+
#define gem_readl(port, reg) (port)->readl((port), GEM_##reg)
435+
#define gem_writel(port, reg, value) (port)->writel((port), GEM_##reg, (value))
436+
#define queue_readl(queue, reg) (queue)->bp->readl((queue)->bp, (queue)->reg)
437+
#define queue_writel(queue, reg, value) (queue)->bp->writel((queue)->bp, (queue)->reg, (value))
444438

445439
/* Conditional GEM/MACB macros. These perform the operation to the correct
446440
* register dependent on whether the device is a GEM or a MACB. For registers
@@ -785,6 +779,11 @@ struct macb_queue {
785779

786780
struct macb {
787781
void __iomem *regs;
782+
bool native_io;
783+
784+
/* hardware IO accessors */
785+
u32 (*readl)(struct macb *bp, int offset);
786+
void (*writel)(struct macb *bp, int offset, u32 value);
788787

789788
unsigned int rx_tail;
790789
unsigned int rx_prepared_head;
@@ -843,9 +842,4 @@ static inline bool macb_is_gem(struct macb *bp)
843842
return !!(bp->caps & MACB_CAPS_MACB_IS_GEM);
844843
}
845844

846-
static inline bool macb_is_gem_hw(void __iomem *addr)
847-
{
848-
return !!(MACB_BFEXT(IDNUM, readl_relaxed(addr + MACB_MID)) >= 0x2);
849-
}
850-
851845
#endif /* _MACB_H */

0 commit comments

Comments
 (0)