diff options
| author | Dan Williams <dan.j.williams@intel.com> | 2019-03-11 15:37:55 -0400 |
|---|---|---|
| committer | Dan Williams <dan.j.williams@intel.com> | 2019-03-11 15:37:55 -0400 |
| commit | 4083014e32699af04a8e6eaa4855b08dba36a47a (patch) | |
| tree | fa37f9f9691fe64ca8a3c0cdc0315dc12462e6e4 /arch/x86/lib/iomem.c | |
| parent | 6fd96ff557963de8e62842a0dc360a6e3610d2bb (diff) | |
| parent | 78153dd45e7e0596ba32b15d02bda08e1513111e (diff) | |
Merge branch 'for-5.1/nfit/ars' into libnvdimm-for-next
Merge several updates to the ARS implementation. Highlights include:
* Support retrieval of short-ARS results if the ARS state is "requires
continuation", and even if the "no_init_ars" module parameter is
specified.
* Allow busy-polling of the kernel ARS state by allowing root to reset
the exponential back-off timer.
* Filter potentially stale ARS results by tracking query-ARS relative to
the previous start-ARS.
Diffstat (limited to 'arch/x86/lib/iomem.c')
| -rw-r--r-- | arch/x86/lib/iomem.c | 33 |
1 files changed, 30 insertions, 3 deletions
diff --git a/arch/x86/lib/iomem.c b/arch/x86/lib/iomem.c index 66894675f3c8..df50451d94ef 100644 --- a/arch/x86/lib/iomem.c +++ b/arch/x86/lib/iomem.c | |||
| @@ -2,8 +2,11 @@ | |||
| 2 | #include <linux/module.h> | 2 | #include <linux/module.h> |
| 3 | #include <linux/io.h> | 3 | #include <linux/io.h> |
| 4 | 4 | ||
| 5 | #define movs(type,to,from) \ | ||
| 6 | asm volatile("movs" type:"=&D" (to), "=&S" (from):"0" (to), "1" (from):"memory") | ||
| 7 | |||
| 5 | /* Originally from i386/string.h */ | 8 | /* Originally from i386/string.h */ |
| 6 | static __always_inline void __iomem_memcpy(void *to, const void *from, size_t n) | 9 | static __always_inline void rep_movs(void *to, const void *from, size_t n) |
| 7 | { | 10 | { |
| 8 | unsigned long d0, d1, d2; | 11 | unsigned long d0, d1, d2; |
| 9 | asm volatile("rep ; movsl\n\t" | 12 | asm volatile("rep ; movsl\n\t" |
| @@ -21,13 +24,37 @@ static __always_inline void __iomem_memcpy(void *to, const void *from, size_t n) | |||
| 21 | 24 | ||
| 22 | void memcpy_fromio(void *to, const volatile void __iomem *from, size_t n) | 25 | void memcpy_fromio(void *to, const volatile void __iomem *from, size_t n) |
| 23 | { | 26 | { |
| 24 | __iomem_memcpy(to, (const void *)from, n); | 27 | if (unlikely(!n)) |
| 28 | return; | ||
| 29 | |||
| 30 | /* Align any unaligned source IO */ | ||
| 31 | if (unlikely(1 & (unsigned long)from)) { | ||
| 32 | movs("b", to, from); | ||
| 33 | n--; | ||
| 34 | } | ||
| 35 | if (n > 1 && unlikely(2 & (unsigned long)from)) { | ||
| 36 | movs("w", to, from); | ||
| 37 | n-=2; | ||
| 38 | } | ||
| 39 | rep_movs(to, (const void *)from, n); | ||
| 25 | } | 40 | } |
| 26 | EXPORT_SYMBOL(memcpy_fromio); | 41 | EXPORT_SYMBOL(memcpy_fromio); |
| 27 | 42 | ||
| 28 | void memcpy_toio(volatile void __iomem *to, const void *from, size_t n) | 43 | void memcpy_toio(volatile void __iomem *to, const void *from, size_t n) |
| 29 | { | 44 | { |
| 30 | __iomem_memcpy((void *)to, (const void *) from, n); | 45 | if (unlikely(!n)) |
| 46 | return; | ||
| 47 | |||
| 48 | /* Align any unaligned destination IO */ | ||
| 49 | if (unlikely(1 & (unsigned long)to)) { | ||
| 50 | movs("b", to, from); | ||
| 51 | n--; | ||
| 52 | } | ||
| 53 | if (n > 1 && unlikely(2 & (unsigned long)to)) { | ||
| 54 | movs("w", to, from); | ||
| 55 | n-=2; | ||
| 56 | } | ||
| 57 | rep_movs((void *)to, (const void *) from, n); | ||
| 31 | } | 58 | } |
| 32 | EXPORT_SYMBOL(memcpy_toio); | 59 | EXPORT_SYMBOL(memcpy_toio); |
| 33 | 60 | ||
