diff options
author | Roland Dreier <roland@purestorage.com> | 2011-05-24 20:13:09 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-05-25 11:39:44 -0400 |
commit | dbee8a0affd5e6eaa5d7c816c4bc233f6f110f50 (patch) | |
tree | 485bba5ec4436e9e8c84aacf25590ca8f8a6332b | |
parent | 818b667ba57f68bf1e7240fa441dda0b11e6b944 (diff) |
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>
-rw-r--r-- | arch/x86/Kconfig | 2 | ||||
-rw-r--r-- | arch/x86/include/asm/io.h | 24 | ||||
-rw-r--r-- | drivers/acpi/apei/einj.c | 8 | ||||
-rw-r--r-- | drivers/acpi/atomicio.c | 4 | ||||
-rw-r--r-- | drivers/edac/i3200_edac.c | 13 | ||||
-rw-r--r-- | drivers/platform/x86/ibm_rtl.c | 13 | ||||
-rw-r--r-- | drivers/platform/x86/intel_ips.c | 13 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_nx.c | 21 |
8 files changed, 74 insertions, 24 deletions
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 880fcb6c86f..fa2cc8c5d01 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig | |||
@@ -17,8 +17,6 @@ config X86_64 | |||
17 | config X86 | 17 | config X86 |
18 | def_bool y | 18 | def_bool y |
19 | select HAVE_AOUT if X86_32 | 19 | select HAVE_AOUT if X86_32 |
20 | select HAVE_READQ | ||
21 | select HAVE_WRITEQ | ||
22 | select HAVE_UNSTABLE_SCHED_CLOCK | 20 | select HAVE_UNSTABLE_SCHED_CLOCK |
23 | select HAVE_IDE | 21 | select HAVE_IDE |
24 | select HAVE_OPROFILE | 22 | select HAVE_OPROFILE |
diff --git a/arch/x86/include/asm/io.h b/arch/x86/include/asm/io.h index 07227308252..d02804d650c 100644 --- a/arch/x86/include/asm/io.h +++ b/arch/x86/include/asm/io.h | |||
@@ -38,7 +38,6 @@ | |||
38 | 38 | ||
39 | #include <linux/string.h> | 39 | #include <linux/string.h> |
40 | #include <linux/compiler.h> | 40 | #include <linux/compiler.h> |
41 | #include <asm-generic/int-ll64.h> | ||
42 | #include <asm/page.h> | 41 | #include <asm/page.h> |
43 | 42 | ||
44 | #include <xen/xen.h> | 43 | #include <xen/xen.h> |
@@ -87,27 +86,6 @@ build_mmio_write(__writel, "l", unsigned int, "r", ) | |||
87 | build_mmio_read(readq, "q", unsigned long, "=r", :"memory") | 86 | build_mmio_read(readq, "q", unsigned long, "=r", :"memory") |
88 | build_mmio_write(writeq, "q", unsigned long, "r", :"memory") | 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 | #define readq_relaxed(a) readq(a) | 89 | #define readq_relaxed(a) readq(a) |
112 | 90 | ||
113 | #define __raw_readq(a) readq(a) | 91 | #define __raw_readq(a) readq(a) |
@@ -117,6 +95,8 @@ static inline void writeq(__u64 val, volatile void __iomem *addr) | |||
117 | #define readq readq | 95 | #define readq readq |
118 | #define writeq writeq | 96 | #define writeq writeq |
119 | 97 | ||
98 | #endif | ||
99 | |||
120 | /** | 100 | /** |
121 | * virt_to_phys - map virtual addresses to physical | 101 | * virt_to_phys - map virtual addresses to physical |
122 | * @address: address to remap | 102 | * @address: address to remap |
diff --git a/drivers/acpi/apei/einj.c b/drivers/acpi/apei/einj.c index 096aebfe7f3..f74b2ea11f2 100644 --- a/drivers/acpi/apei/einj.c +++ b/drivers/acpi/apei/einj.c | |||
@@ -101,6 +101,14 @@ static DEFINE_MUTEX(einj_mutex); | |||
101 | 101 | ||
102 | static struct einj_parameter *einj_param; | 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 | static void einj_exec_ctx_init(struct apei_exec_context *ctx) | 112 | static void einj_exec_ctx_init(struct apei_exec_context *ctx) |
105 | { | 113 | { |
106 | apei_exec_ctx_init(ctx, einj_ins_type, ARRAY_SIZE(einj_ins_type), | 114 | apei_exec_ctx_init(ctx, einj_ins_type, ARRAY_SIZE(einj_ins_type), |
diff --git a/drivers/acpi/atomicio.c b/drivers/acpi/atomicio.c index 542e5390389..7489b89c300 100644 --- a/drivers/acpi/atomicio.c +++ b/drivers/acpi/atomicio.c | |||
@@ -280,9 +280,11 @@ static int acpi_atomic_read_mem(u64 paddr, u64 *val, u32 width) | |||
280 | case 32: | 280 | case 32: |
281 | *val = readl(addr); | 281 | *val = readl(addr); |
282 | break; | 282 | break; |
283 | #ifdef readq | ||
283 | case 64: | 284 | case 64: |
284 | *val = readq(addr); | 285 | *val = readq(addr); |
285 | break; | 286 | break; |
287 | #endif | ||
286 | default: | 288 | default: |
287 | return -EINVAL; | 289 | return -EINVAL; |
288 | } | 290 | } |
@@ -307,9 +309,11 @@ static int acpi_atomic_write_mem(u64 paddr, u64 val, u32 width) | |||
307 | case 32: | 309 | case 32: |
308 | writel(val, addr); | 310 | writel(val, addr); |
309 | break; | 311 | break; |
312 | #ifdef writeq | ||
310 | case 64: | 313 | case 64: |
311 | writeq(val, addr); | 314 | writeq(val, addr); |
312 | break; | 315 | break; |
316 | #endif | ||
313 | default: | 317 | default: |
314 | return -EINVAL; | 318 | return -EINVAL; |
315 | } | 319 | } |
diff --git a/drivers/edac/i3200_edac.c b/drivers/edac/i3200_edac.c index d41f9002da4..aa08497a075 100644 --- a/drivers/edac/i3200_edac.c +++ b/drivers/edac/i3200_edac.c | |||
@@ -101,6 +101,19 @@ struct i3200_priv { | |||
101 | 101 | ||
102 | static int nr_channels; | 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 | static int how_many_channels(struct pci_dev *pdev) | 117 | static int how_many_channels(struct pci_dev *pdev) |
105 | { | 118 | { |
106 | unsigned char capid0_8b; /* 8th byte of CAPID0 */ | 119 | unsigned char capid0_8b; /* 8th byte of CAPID0 */ |
diff --git a/drivers/platform/x86/ibm_rtl.c b/drivers/platform/x86/ibm_rtl.c index 94a114aa8e2..b1396e5b295 100644 --- a/drivers/platform/x86/ibm_rtl.c +++ b/drivers/platform/x86/ibm_rtl.c | |||
@@ -81,6 +81,19 @@ static void __iomem *rtl_cmd_addr; | |||
81 | static u8 rtl_cmd_type; | 81 | static u8 rtl_cmd_type; |
82 | static u8 rtl_cmd_width; | 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 | static void __iomem *rtl_port_map(phys_addr_t addr, unsigned long len) | 97 | static void __iomem *rtl_port_map(phys_addr_t addr, unsigned long len) |
85 | { | 98 | { |
86 | if (rtl_cmd_type == RTL_ADDR_TYPE_MMIO) | 99 | if (rtl_cmd_type == RTL_ADDR_TYPE_MMIO) |
diff --git a/drivers/platform/x86/intel_ips.c b/drivers/platform/x86/intel_ips.c index 85c8ad43c0c..5ffe7c39814 100644 --- a/drivers/platform/x86/intel_ips.c +++ b/drivers/platform/x86/intel_ips.c | |||
@@ -344,6 +344,19 @@ struct ips_driver { | |||
344 | static bool | 344 | static bool |
345 | ips_gpu_turbo_enabled(struct ips_driver *ips); | 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 | * ips_cpu_busy - is CPU busy? | 361 | * ips_cpu_busy - is CPU busy? |
349 | * @ips: IPS driver struct | 362 | * @ips: IPS driver struct |
diff --git a/drivers/scsi/qla4xxx/ql4_nx.c b/drivers/scsi/qla4xxx/ql4_nx.c index 35381cb0936..03e522b2fe0 100644 --- a/drivers/scsi/qla4xxx/ql4_nx.c +++ b/drivers/scsi/qla4xxx/ql4_nx.c | |||
@@ -655,6 +655,27 @@ static int qla4_8xxx_pci_is_same_window(struct scsi_qla_host *ha, | |||
655 | return 0; | 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 | static int qla4_8xxx_pci_mem_read_direct(struct scsi_qla_host *ha, | 679 | static int qla4_8xxx_pci_mem_read_direct(struct scsi_qla_host *ha, |
659 | u64 off, void *data, int size) | 680 | u64 off, void *data, int size) |
660 | { | 681 | { |