Skip to content

Commit 9c05e45

Browse files
Mikulas Patockagregkh
authored andcommitted
alpha: fix memory barriers so that they conform to the specification
commit 54505a1 upstream. The commits cd0e00c and 92d7223 broke boot on the Alpha Avanti platform. The patches move memory barriers after a write before the write. The result is that if there's iowrite followed by ioread, there is no barrier between them. The Alpha architecture allows reordering of the accesses to the I/O space, and the missing barrier between write and read causes hang with serial port and real time clock. This patch makes barriers confiorm to the specification. 1. We add mb() before readX_relaxed and writeX_relaxed - memory-barriers.txt claims that these functions must be ordered w.r.t. each other. Alpha doesn't order them, so we need an explicit barrier. 2. We add mb() before reads from the I/O space - so that if there's a write followed by a read, there should be a barrier between them. Signed-off-by: Mikulas Patocka <mpatocka@redhat.com> Fixes: cd0e00c ("alpha: io: reorder barriers to guarantee writeX() and iowriteX() ordering") Fixes: 92d7223 ("alpha: io: reorder barriers to guarantee writeX() and iowriteX() ordering STMicroelectronics#2") Cc: stable@vger.kernel.org # v4.17+ Acked-by: Ivan Kokshaysky <ink@jurassic.park.msu.ru> Reviewed-by: Maciej W. Rozycki <macro@linux-mips.org> Signed-off-by: Matt Turner <mattst88@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 1eb02eb commit 9c05e45

2 files changed

Lines changed: 112 additions & 22 deletions

File tree

arch/alpha/include/asm/io.h

Lines changed: 59 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -310,14 +310,18 @@ static inline int __is_mmio(const volatile void __iomem *addr)
310310
#if IO_CONCAT(__IO_PREFIX,trivial_io_bw)
311311
extern inline unsigned int ioread8(void __iomem *addr)
312312
{
313-
unsigned int ret = IO_CONCAT(__IO_PREFIX,ioread8)(addr);
313+
unsigned int ret;
314+
mb();
315+
ret = IO_CONCAT(__IO_PREFIX,ioread8)(addr);
314316
mb();
315317
return ret;
316318
}
317319

318320
extern inline unsigned int ioread16(void __iomem *addr)
319321
{
320-
unsigned int ret = IO_CONCAT(__IO_PREFIX,ioread16)(addr);
322+
unsigned int ret;
323+
mb();
324+
ret = IO_CONCAT(__IO_PREFIX,ioread16)(addr);
321325
mb();
322326
return ret;
323327
}
@@ -358,7 +362,9 @@ extern inline void outw(u16 b, unsigned long port)
358362
#if IO_CONCAT(__IO_PREFIX,trivial_io_lq)
359363
extern inline unsigned int ioread32(void __iomem *addr)
360364
{
361-
unsigned int ret = IO_CONCAT(__IO_PREFIX,ioread32)(addr);
365+
unsigned int ret;
366+
mb();
367+
ret = IO_CONCAT(__IO_PREFIX,ioread32)(addr);
362368
mb();
363369
return ret;
364370
}
@@ -403,14 +409,18 @@ extern inline void __raw_writew(u16 b, volatile void __iomem *addr)
403409

404410
extern inline u8 readb(const volatile void __iomem *addr)
405411
{
406-
u8 ret = __raw_readb(addr);
412+
u8 ret;
413+
mb();
414+
ret = __raw_readb(addr);
407415
mb();
408416
return ret;
409417
}
410418

411419
extern inline u16 readw(const volatile void __iomem *addr)
412420
{
413-
u16 ret = __raw_readw(addr);
421+
u16 ret;
422+
mb();
423+
ret = __raw_readw(addr);
414424
mb();
415425
return ret;
416426
}
@@ -451,14 +461,18 @@ extern inline void __raw_writeq(u64 b, volatile void __iomem *addr)
451461

452462
extern inline u32 readl(const volatile void __iomem *addr)
453463
{
454-
u32 ret = __raw_readl(addr);
464+
u32 ret;
465+
mb();
466+
ret = __raw_readl(addr);
455467
mb();
456468
return ret;
457469
}
458470

459471
extern inline u64 readq(const volatile void __iomem *addr)
460472
{
461-
u64 ret = __raw_readq(addr);
473+
u64 ret;
474+
mb();
475+
ret = __raw_readq(addr);
462476
mb();
463477
return ret;
464478
}
@@ -487,14 +501,44 @@ extern inline void writeq(u64 b, volatile void __iomem *addr)
487501
#define outb_p outb
488502
#define outw_p outw
489503
#define outl_p outl
490-
#define readb_relaxed(addr) __raw_readb(addr)
491-
#define readw_relaxed(addr) __raw_readw(addr)
492-
#define readl_relaxed(addr) __raw_readl(addr)
493-
#define readq_relaxed(addr) __raw_readq(addr)
494-
#define writeb_relaxed(b, addr) __raw_writeb(b, addr)
495-
#define writew_relaxed(b, addr) __raw_writew(b, addr)
496-
#define writel_relaxed(b, addr) __raw_writel(b, addr)
497-
#define writeq_relaxed(b, addr) __raw_writeq(b, addr)
504+
505+
extern u8 readb_relaxed(const volatile void __iomem *addr);
506+
extern u16 readw_relaxed(const volatile void __iomem *addr);
507+
extern u32 readl_relaxed(const volatile void __iomem *addr);
508+
extern u64 readq_relaxed(const volatile void __iomem *addr);
509+
510+
#if IO_CONCAT(__IO_PREFIX,trivial_io_bw)
511+
extern inline u8 readb_relaxed(const volatile void __iomem *addr)
512+
{
513+
mb();
514+
return __raw_readb(addr);
515+
}
516+
517+
extern inline u16 readw_relaxed(const volatile void __iomem *addr)
518+
{
519+
mb();
520+
return __raw_readw(addr);
521+
}
522+
#endif
523+
524+
#if IO_CONCAT(__IO_PREFIX,trivial_io_lq)
525+
extern inline u32 readl_relaxed(const volatile void __iomem *addr)
526+
{
527+
mb();
528+
return __raw_readl(addr);
529+
}
530+
531+
extern inline u64 readq_relaxed(const volatile void __iomem *addr)
532+
{
533+
mb();
534+
return __raw_readq(addr);
535+
}
536+
#endif
537+
538+
#define writeb_relaxed writeb
539+
#define writew_relaxed writew
540+
#define writel_relaxed writel
541+
#define writeq_relaxed writeq
498542

499543
/*
500544
* String version of IO memory access ops:

arch/alpha/kernel/io.c

Lines changed: 53 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,21 +16,27 @@
1616
unsigned int
1717
ioread8(void __iomem *addr)
1818
{
19-
unsigned int ret = IO_CONCAT(__IO_PREFIX,ioread8)(addr);
19+
unsigned int ret;
20+
mb();
21+
ret = IO_CONCAT(__IO_PREFIX,ioread8)(addr);
2022
mb();
2123
return ret;
2224
}
2325

2426
unsigned int ioread16(void __iomem *addr)
2527
{
26-
unsigned int ret = IO_CONCAT(__IO_PREFIX,ioread16)(addr);
28+
unsigned int ret;
29+
mb();
30+
ret = IO_CONCAT(__IO_PREFIX,ioread16)(addr);
2731
mb();
2832
return ret;
2933
}
3034

3135
unsigned int ioread32(void __iomem *addr)
3236
{
33-
unsigned int ret = IO_CONCAT(__IO_PREFIX,ioread32)(addr);
37+
unsigned int ret;
38+
mb();
39+
ret = IO_CONCAT(__IO_PREFIX,ioread32)(addr);
3440
mb();
3541
return ret;
3642
}
@@ -148,28 +154,36 @@ EXPORT_SYMBOL(__raw_writeq);
148154

149155
u8 readb(const volatile void __iomem *addr)
150156
{
151-
u8 ret = __raw_readb(addr);
157+
u8 ret;
158+
mb();
159+
ret = __raw_readb(addr);
152160
mb();
153161
return ret;
154162
}
155163

156164
u16 readw(const volatile void __iomem *addr)
157165
{
158-
u16 ret = __raw_readw(addr);
166+
u16 ret;
167+
mb();
168+
ret = __raw_readw(addr);
159169
mb();
160170
return ret;
161171
}
162172

163173
u32 readl(const volatile void __iomem *addr)
164174
{
165-
u32 ret = __raw_readl(addr);
175+
u32 ret;
176+
mb();
177+
ret = __raw_readl(addr);
166178
mb();
167179
return ret;
168180
}
169181

170182
u64 readq(const volatile void __iomem *addr)
171183
{
172-
u64 ret = __raw_readq(addr);
184+
u64 ret;
185+
mb();
186+
ret = __raw_readq(addr);
173187
mb();
174188
return ret;
175189
}
@@ -207,6 +221,38 @@ EXPORT_SYMBOL(writew);
207221
EXPORT_SYMBOL(writel);
208222
EXPORT_SYMBOL(writeq);
209223

224+
/*
225+
* The _relaxed functions must be ordered w.r.t. each other, but they don't
226+
* have to be ordered w.r.t. other memory accesses.
227+
*/
228+
u8 readb_relaxed(const volatile void __iomem *addr)
229+
{
230+
mb();
231+
return __raw_readb(addr);
232+
}
233+
234+
u16 readw_relaxed(const volatile void __iomem *addr)
235+
{
236+
mb();
237+
return __raw_readw(addr);
238+
}
239+
240+
u32 readl_relaxed(const volatile void __iomem *addr)
241+
{
242+
mb();
243+
return __raw_readl(addr);
244+
}
245+
246+
u64 readq_relaxed(const volatile void __iomem *addr)
247+
{
248+
mb();
249+
return __raw_readq(addr);
250+
}
251+
252+
EXPORT_SYMBOL(readb_relaxed);
253+
EXPORT_SYMBOL(readw_relaxed);
254+
EXPORT_SYMBOL(readl_relaxed);
255+
EXPORT_SYMBOL(readq_relaxed);
210256

211257
/*
212258
* Read COUNT 8-bit bytes from port PORT into memory starting at SRC.

0 commit comments

Comments
 (0)