Commit dbee8a0affd5e6eaa5d7c816c4bc233f6f110f50

Authored by Roland Dreier
Committed by Linus Torvalds
1 parent 818b667ba5

x86: remove 32-bit versions of readq()/writeq()

The presense of a writeq() implementation on 32-bit x86 that splits the
64-bit write into two 32-bit writes turns out to break the mpt2sas driver
(and in general is risky for drivers as was discussed in
<http://lkml.kernel.org/r/adaab6c1h7c.fsf@cisco.com>).  To fix this,
revert 2c5643b1c5c7 ("x86: provide readq()/writeq() on 32-bit too") and
follow-on cleanups.

This unfortunately leads to pushing non-atomic definitions of readq() and
write() to various x86-only drivers that in the meantime started using the
definitions in the x86 version of <asm/io.h>.  However as discussed
exhaustively, this is actually the right thing to do, because the right
way to split a 64-bit transaction is hardware dependent and therefore
belongs in the hardware driver (eg mpt2sas needs a spinlock to make sure
no other accesses occur in between the two halves of the access).

Build tested on 32- and 64-bit x86 allmodconfig.

Link: http://lkml.kernel.org/r/x86-32-writeq-is-broken@mdm.bga.com
Acked-by: Hitoshi Mitake <h.mitake@gmail.com>
Cc: Kashyap Desai <Kashyap.Desai@lsi.com>
Cc: Len Brown <lenb@kernel.org>
Cc: Ravi Anand <ravi.anand@qlogic.com>
Cc: Vikas Chaudhary <vikas.chaudhary@qlogic.com>
Cc: Matthew Garrett <mjg@redhat.com>
Cc: Jason Uhlenkott <juhlenko@akamai.com>
Acked-by: James Bottomley <James.Bottomley@parallels.com>
Acked-by: Ingo Molnar <mingo@elte.hu>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Signed-off-by: Roland Dreier <roland@purestorage.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

Showing 8 changed files with 74 additions and 24 deletions Side-by-side Diff

... ... @@ -17,8 +17,6 @@
17 17 config X86
18 18 def_bool y
19 19 select HAVE_AOUT if X86_32
20   - select HAVE_READQ
21   - select HAVE_WRITEQ
22 20 select HAVE_UNSTABLE_SCHED_CLOCK
23 21 select HAVE_IDE
24 22 select HAVE_OPROFILE
arch/x86/include/asm/io.h
... ... @@ -38,7 +38,6 @@
38 38  
39 39 #include <linux/string.h>
40 40 #include <linux/compiler.h>
41   -#include <asm-generic/int-ll64.h>
42 41 #include <asm/page.h>
43 42  
44 43 #include <xen/xen.h>
... ... @@ -87,27 +86,6 @@
87 86 build_mmio_read(readq, "q", unsigned long, "=r", :"memory")
88 87 build_mmio_write(writeq, "q", unsigned long, "r", :"memory")
89 88  
90   -#else
91   -
92   -static inline __u64 readq(const volatile void __iomem *addr)
93   -{
94   - const volatile u32 __iomem *p = addr;
95   - u32 low, high;
96   -
97   - low = readl(p);
98   - high = readl(p + 1);
99   -
100   - return low + ((u64)high << 32);
101   -}
102   -
103   -static inline void writeq(__u64 val, volatile void __iomem *addr)
104   -{
105   - writel(val, addr);
106   - writel(val >> 32, addr+4);
107   -}
108   -
109   -#endif
110   -
111 89 #define readq_relaxed(a) readq(a)
112 90  
113 91 #define __raw_readq(a) readq(a)
... ... @@ -116,6 +94,8 @@
116 94 /* Let people know that we have them */
117 95 #define readq readq
118 96 #define writeq writeq
  97 +
  98 +#endif
119 99  
120 100 /**
121 101 * virt_to_phys - map virtual addresses to physical
drivers/acpi/apei/einj.c
... ... @@ -101,6 +101,14 @@
101 101  
102 102 static struct einj_parameter *einj_param;
103 103  
  104 +#ifndef writeq
  105 +static inline void writeq(__u64 val, volatile void __iomem *addr)
  106 +{
  107 + writel(val, addr);
  108 + writel(val >> 32, addr+4);
  109 +}
  110 +#endif
  111 +
104 112 static void einj_exec_ctx_init(struct apei_exec_context *ctx)
105 113 {
106 114 apei_exec_ctx_init(ctx, einj_ins_type, ARRAY_SIZE(einj_ins_type),
drivers/acpi/atomicio.c
... ... @@ -280,9 +280,11 @@
280 280 case 32:
281 281 *val = readl(addr);
282 282 break;
  283 +#ifdef readq
283 284 case 64:
284 285 *val = readq(addr);
285 286 break;
  287 +#endif
286 288 default:
287 289 return -EINVAL;
288 290 }
289 291  
... ... @@ -307,9 +309,11 @@
307 309 case 32:
308 310 writel(val, addr);
309 311 break;
  312 +#ifdef writeq
310 313 case 64:
311 314 writeq(val, addr);
312 315 break;
  316 +#endif
313 317 default:
314 318 return -EINVAL;
315 319 }
drivers/edac/i3200_edac.c
... ... @@ -101,6 +101,19 @@
101 101  
102 102 static int nr_channels;
103 103  
  104 +#ifndef readq
  105 +static inline __u64 readq(const volatile void __iomem *addr)
  106 +{
  107 + const volatile u32 __iomem *p = addr;
  108 + u32 low, high;
  109 +
  110 + low = readl(p);
  111 + high = readl(p + 1);
  112 +
  113 + return low + ((u64)high << 32);
  114 +}
  115 +#endif
  116 +
104 117 static int how_many_channels(struct pci_dev *pdev)
105 118 {
106 119 unsigned char capid0_8b; /* 8th byte of CAPID0 */
drivers/platform/x86/ibm_rtl.c
... ... @@ -81,6 +81,19 @@
81 81 static u8 rtl_cmd_type;
82 82 static u8 rtl_cmd_width;
83 83  
  84 +#ifndef readq
  85 +static inline __u64 readq(const volatile void __iomem *addr)
  86 +{
  87 + const volatile u32 __iomem *p = addr;
  88 + u32 low, high;
  89 +
  90 + low = readl(p);
  91 + high = readl(p + 1);
  92 +
  93 + return low + ((u64)high << 32);
  94 +}
  95 +#endif
  96 +
84 97 static void __iomem *rtl_port_map(phys_addr_t addr, unsigned long len)
85 98 {
86 99 if (rtl_cmd_type == RTL_ADDR_TYPE_MMIO)
drivers/platform/x86/intel_ips.c
... ... @@ -344,6 +344,19 @@
344 344 static bool
345 345 ips_gpu_turbo_enabled(struct ips_driver *ips);
346 346  
  347 +#ifndef readq
  348 +static inline __u64 readq(const volatile void __iomem *addr)
  349 +{
  350 + const volatile u32 __iomem *p = addr;
  351 + u32 low, high;
  352 +
  353 + low = readl(p);
  354 + high = readl(p + 1);
  355 +
  356 + return low + ((u64)high << 32);
  357 +}
  358 +#endif
  359 +
347 360 /**
348 361 * ips_cpu_busy - is CPU busy?
349 362 * @ips: IPS driver struct
drivers/scsi/qla4xxx/ql4_nx.c
... ... @@ -655,6 +655,27 @@
655 655 return 0;
656 656 }
657 657  
  658 +#ifndef readq
  659 +static inline __u64 readq(const volatile void __iomem *addr)
  660 +{
  661 + const volatile u32 __iomem *p = addr;
  662 + u32 low, high;
  663 +
  664 + low = readl(p);
  665 + high = readl(p + 1);
  666 +
  667 + return low + ((u64)high << 32);
  668 +}
  669 +#endif
  670 +
  671 +#ifndef writeq
  672 +static inline void writeq(__u64 val, volatile void __iomem *addr)
  673 +{
  674 + writel(val, addr);
  675 + writel(val >> 32, addr+4);
  676 +}
  677 +#endif
  678 +
658 679 static int qla4_8xxx_pci_mem_read_direct(struct scsi_qla_host *ha,
659 680 u64 off, void *data, int size)
660 681 {