2016-04-05 02:08:37

by Zhaoxiu Zeng

[permalink] [raw]
Subject: [PATCH V2 01/30] bitops: add parity functions

From: Zhaoxiu Zeng <[email protected]>

These patches provide generic and architecture-specific odd parity
calculations.

I did not use GCC's __builtin_parity* functions, based on the following
reasons:
1. I don't know where to identify which version of GCC from the beginning
supported __builtin_parity for the architecture.
2. For the architectures that doesn't have popcount instruction, GCC
instead use
"call __paritysi2" (__paritydi2 for 64-bits). So if use
__builtin_parity, we must
provide __paritysi2 and __paritydi2 functions for these architectures.
Additionally, parity4,8,16 might be "__builtin_parity(x & mask)",
but the "& mask"
operation is totally unnecessary.
3. For the architectures that have popcount instruction, we do the
same things.
4. For powerpc, sparc, and x86, we do runtime patching to use
popcount instruction
if the CPU support.

I have compiled successfully with x86_64_defconfig, i386_defconfig,
pseries_defconfig
and sparc64_defconfig. And I used the following codes to test:

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

#ifdef __x86_64__
/* popcnt %edi, %eax -- redundant REX prefix for alignment */
#define POPCNT32 ".byte 0xf3,0x40,0x0f,0xb8,0xc7"
/* popcnt %rdi, %rax */
#define POPCNT64 ".byte 0xf3,0x48,0x0f,0xb8,0xc7"
#define REG_IN "D"
#define REG_OUT "a"
#else
/* popcnt %eax, %eax */
#define POPCNT32 ".byte 0xf3,0x0f,0xb8,0xc0"
#define REG_IN "a"
#define REG_OUT "a"
#endif

static inline int c_parity4(unsigned int w)
{
w &= 0xf;
return (0x6996 >> w) & 1;
}

static inline int c_parity8(unsigned int w)
{
w ^= w >> 4;
return c_parity4(w);
}

static inline int c_parity16(unsigned int w)
{
w ^= w >> 8;
return c_parity8(w);
}

static inline int c_parity32(unsigned int w)
{
w ^= w >> 16;
return c_parity16(w);
}

static inline int c_parity64(uint64_t w)
{
return c_parity32((unsigned int)w ^ (unsigned int)(w >> 32));
}

static inline int asm_parity4(unsigned int w)
{
unsigned int res = 0;

asm("test $0xf, %1 \n"
"setpo %b0 \n"
: "+q" (res)
: "r" (w)
: "cc");

return res;
}

static inline int asm_parity8(unsigned int w)
{
unsigned int res = 0;

asm("test %1, %1 \n"
"setpo %b0 \n"
: "+q" (res)
: "r" (w)
: "cc");

return res;
}

static inline int asm_parity16(unsigned int w)
{
unsigned int res = 0;

asm("xor %h1, %b1 \n"
"setpo %b0 \n"
: "+q" (res), "+q" (w)
: : "cc");

return res;
}

static inline int asm_parity32_1(unsigned int w)
{
unsigned int res;

w ^= w >> 16;
asm("xor %%ah, %%al \n"
"mov $0, %%eax \n"
"setpo %%al \n"
: "=a" (res)
: "a" (w)
: "cc");

return res;
}

static inline int asm_parity32_2(unsigned int w)
{
unsigned int res;

asm(POPCNT32 " \n"
"andl $1, %0 \n"
: "="REG_OUT (res)
: REG_IN (w)
: "cc");

return res;
}

#ifdef __x86_64__
static inline int asm_parity64_1(uint64_t w)
{
unsigned int res = (unsigned int)w ^ (unsigned int)(w >> 32);

res ^= res >> 16;
asm("xor %%ah, %%al \n"
"mov $0, %%eax \n"
"setpo %%al \n"
: "=a" (res)
: "a" (res)
: "cc");

return res;
}

static inline int asm_parity64_2(uint64_t w)
{
unsigned int res;

asm(POPCNT64 " \n"
"andl $1, %0 \n"
: "="REG_OUT (res)
: REG_IN (w)
: "cc");

return res;
}
#else
static inline int asm_parity64_1(uint64_t w)
{
return asm_parity32_1((unsigned int)(w >> 32) ^ (unsigned int)w);
}

static inline int asm_parity64_2(uint64_t w)
{
return asm_parity32_2((unsigned int)(w >> 32) ^ (unsigned int)w);
}
#endif

int main(int argc, char **argv)
{
int ok = 1;
int count = 1000, i;

if (argc >= 2)
count = atoi(argv[1]);

srand((unsigned)time(NULL));

for (i = 0; i < count; i++) {
uint64_t w = rand() | (uint64_t)rand() << 32;
int p4_1 = c_parity4(w);
int p4_2 = asm_parity4(w);
int p8_1 = c_parity8(w);
int p8_2 = asm_parity8(w);
int p16_1 = c_parity16(w);
int p16_2 = asm_parity16(w);
int p32_1 = c_parity32(w);
int p32_2 = asm_parity32_1(w);
int p32_3 = asm_parity32_2(w);
int p64_1 = c_parity64(w);
int p64_2 = asm_parity64_1(w);
int p64_3 = asm_parity64_2(w);
if (p4_1 != p4_2 ||
p8_1 != p8_2 ||
p16_1 != p16_2 ||
p32_1 != p32_2 || p32_1 != p32_3 ||
p64_1 != p64_2 || p64_1 != p64_3) {
fprintf(stderr, "Err: %llx\n"
"\tc_parity4 = %d, asm_parity4 = %d,\n"
"\tc_parity8 = %d, asm_parity8 = %d,\n"
"\tc_parity16 = %d, asm_parity16 = %d,\n"
"\tc_parity32 = %d, asm_parity32_1 = %d,
asm_parity32_2 = %d\n"
"\tc_parity64 = %d, asm_parity64_1 = %d,
asm_parity64_2 = %d\n",
w, p4_1, p4_2, p8_1, p8_2, p16_1, p16_2,
p32_1, p32_2, p32_3, p64_1, p64_2, p64_3);
ok = 0;
}
}

fprintf(stderr, "%s\n", ok ? "OK" : "FAIL");
return 0;
}

---
include/asm-generic/bitops.h | 1 +
include/asm-generic/bitops/arch_parity.h | 39
+++++++++++++++++++++++++++++++
include/asm-generic/bitops/const_parity.h | 36
++++++++++++++++++++++++++++
include/asm-generic/bitops/parity.h | 7 ++++++
include/linux/bitops.h | 5 ++++
5 files changed, 88 insertions(+)
create mode 100644 include/asm-generic/bitops/arch_parity.h
create mode 100644 include/asm-generic/bitops/const_parity.h
create mode 100644 include/asm-generic/bitops/parity.h

diff --git a/include/asm-generic/bitops.h b/include/asm-generic/bitops.h
index dcdcacf..d85722f 100644
--- a/include/asm-generic/bitops.h
+++ b/include/asm-generic/bitops.h
@@ -27,6 +27,7 @@
#include <asm-generic/bitops/sched.h>
#include <asm-generic/bitops/ffs.h>
#include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
#include <asm-generic/bitops/lock.h>

#include <asm-generic/bitops/atomic.h>
diff --git a/include/asm-generic/bitops/arch_parity.h
b/include/asm-generic/bitops/arch_parity.h
new file mode 100644
index 0000000..cddc555
--- /dev/null
+++ b/include/asm-generic/bitops/arch_parity.h
@@ -0,0 +1,39 @@
+#ifndef _ASM_GENERIC_BITOPS_ARCH_PARITY_H_
+#define _ASM_GENERIC_BITOPS_ARCH_PARITY_H_
+
+#include <asm/types.h>
+
+/*
+ * Refrence to
'https://graphics.stanford.edu/~seander/bithacks.html#ParityParallel'.
+ */
+
+static inline unsigned int __arch_parity4(unsigned int w)
+{
+ w &= 0xf;
+ return (0x6996 >> w) & 1;
+}
+
+static inline unsigned int __arch_parity8(unsigned int w)
+{
+ w ^= w >> 4;
+ return __arch_parity4(w);
+}
+
+static inline unsigned int __arch_parity16(unsigned int w)
+{
+ w ^= w >> 8;
+ return __arch_parity8(w);
+}
+
+static inline unsigned int __arch_parity32(unsigned int w)
+{
+ w ^= w >> 16;
+ return __arch_parity16(w);
+}
+
+static inline unsigned int __arch_parity64(__u64 w)
+{
+ return __arch_parity32((unsigned int)(w >> 32) ^ (unsigned int)w);
+}
+
+#endif /* _ASM_GENERIC_BITOPS_ARCH_PARITY_H_ */
diff --git a/include/asm-generic/bitops/const_parity.h
b/include/asm-generic/bitops/const_parity.h
new file mode 100644
index 0000000..6af7987
--- /dev/null
+++ b/include/asm-generic/bitops/const_parity.h
@@ -0,0 +1,36 @@
+#ifndef _ASM_GENERIC_BITOPS_CONST_PARITY_H_
+#define _ASM_GENERIC_BITOPS_CONST_PARITY_H_
+
+/*
+ * Compile time versions of __arch_parityN()
+ */
+#define __const_parity4(w) ((0x6996 >> ((w) & 0xf)) & 1)
+#define __const_parity8(w) (__const_parity4((w) ^ ((w) >> 4)))
+#define __const_parity16(w) (__const_parity8((w) ^ ((w) >> 8)))
+#define __const_parity32(w) (__const_parity16((w) ^ ((w) >> 16)))
+#define __const_parity64(w) (__const_parity32((w) ^ ((w) >> 32)))
+
+/*
+ * Generic interface.
+ */
+#define parity4(w) (__builtin_constant_p(w) ? __const_parity4(w) :
__arch_parity4(w))
+#define parity8(w) (__builtin_constant_p(w) ? __const_parity8(w) :
__arch_parity8(w))
+#define parity16(w) (__builtin_constant_p(w) ? __const_parity16(w) :
__arch_parity16(w))
+#define parity32(w) (__builtin_constant_p(w) ? __const_parity32(w) :
__arch_parity32(w))
+#define parity64(w) (__builtin_constant_p(w) ? __const_parity64(w) :
__arch_parity64(w))
+
+/*
+ * Interface for known constant arguments
+ */
+#define PARITY4(w) (BUILD_BUG_ON_ZERO(!__builtin_constant_p(w)) +
__const_parity4(w))
+#define PARITY8(w) (BUILD_BUG_ON_ZERO(!__builtin_constant_p(w)) +
__const_parity8(w))
+#define PARITY16(w) (BUILD_BUG_ON_ZERO(!__builtin_constant_p(w)) +
__const_parity16(w))
+#define PARITY32(w) (BUILD_BUG_ON_ZERO(!__builtin_constant_p(w)) +
__const_parity32(w))
+#define PARITY64(w) (BUILD_BUG_ON_ZERO(!__builtin_constant_p(w)) +
__const_parity64(w))
+
+/*
+ * Type invariant interface to the compile time constant parity functions.
+ */
+#define PARITY(w) PARITY64((u64)(w))
+
+#endif /* _ASM_GENERIC_BITOPS_CONST_PARITY_H_ */
diff --git a/include/asm-generic/bitops/parity.h
b/include/asm-generic/bitops/parity.h
new file mode 100644
index 0000000..a91dce7
--- /dev/null
+++ b/include/asm-generic/bitops/parity.h
@@ -0,0 +1,7 @@
+#ifndef _ASM_GENERIC_BITOPS_PARITY_H_
+#define _ASM_GENERIC_BITOPS_PARITY_H_
+
+#include <asm-generic/bitops/arch_parity.h>
+#include <asm-generic/bitops/const_parity.h>
+
+#endif /* _ASM_GENERIC_BITOPS_PARITY_H_ */
diff --git a/include/linux/bitops.h b/include/linux/bitops.h
index defeaac..8952f88 100644
--- a/include/linux/bitops.h
+++ b/include/linux/bitops.h
@@ -80,6 +80,11 @@ static __always_inline unsigned long
hweight_long(unsigned long w)
return sizeof(w) == 4 ? hweight32(w) : hweight64(w);
}

+static __always_inline unsigned int parity_long(unsigned long w)
+{
+ return sizeof(w) == 4 ? parity32(w) : parity64(w);
+}
+
/**
* rol64 - rotate a 64-bit value left
* @word: value to rotate
--
2.5.0


2016-04-05 04:23:50

by Zhaoxiu Zeng

[permalink] [raw]
Subject: [PATCH V2 02/30] Include generic parity.h in some architectures' bitops.h

From: Zhaoxiu Zeng <[email protected]>

Use the generic version
---
arch/arc/include/asm/bitops.h | 1 +
arch/arm/include/asm/bitops.h | 1 +
arch/arm64/include/asm/bitops.h | 1 +
arch/avr32/include/asm/bitops.h | 1 +
arch/c6x/include/asm/bitops.h | 1 +
arch/cris/include/asm/bitops.h | 1 +
arch/frv/include/asm/bitops.h | 1 +
arch/h8300/include/asm/bitops.h | 1 +
arch/hexagon/include/asm/bitops.h | 1 +
arch/m32r/include/asm/bitops.h | 1 +
arch/m68k/include/asm/bitops.h | 1 +
arch/metag/include/asm/bitops.h | 1 +
arch/mn10300/include/asm/bitops.h | 1 +
arch/openrisc/include/asm/bitops.h | 1 +
arch/parisc/include/asm/bitops.h | 1 +
arch/s390/include/asm/bitops.h | 1 +
arch/sh/include/asm/bitops.h | 1 +
arch/xtensa/include/asm/bitops.h | 1 +
18 files changed, 18 insertions(+)

diff --git a/arch/arc/include/asm/bitops.h b/arch/arc/include/asm/bitops.h
index 0352fb8..7967e47 100644
--- a/arch/arc/include/asm/bitops.h
+++ b/arch/arc/include/asm/bitops.h
@@ -370,6 +370,7 @@ static inline __attribute__ ((const)) int
__ffs(unsigned long x)
#define ffz(x) __ffs(~(x))

#include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
#include <asm-generic/bitops/fls64.h>
#include <asm-generic/bitops/sched.h>
#include <asm-generic/bitops/lock.h>
diff --git a/arch/arm/include/asm/bitops.h b/arch/arm/include/asm/bitops.h
index e943e6c..99f28a6 100644
--- a/arch/arm/include/asm/bitops.h
+++ b/arch/arm/include/asm/bitops.h
@@ -313,6 +313,7 @@ static inline unsigned long __ffs(unsigned long x)

#include <asm-generic/bitops/sched.h>
#include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
#include <asm-generic/bitops/lock.h>

#ifdef __ARMEB__
diff --git a/arch/arm64/include/asm/bitops.h
b/arch/arm64/include/asm/bitops.h
index 9c19594..eac4965 100644
--- a/arch/arm64/include/asm/bitops.h
+++ b/arch/arm64/include/asm/bitops.h
@@ -44,6 +44,7 @@ extern int test_and_change_bit(int nr, volatile
unsigned long *p);

#include <asm-generic/bitops/sched.h>
#include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
#include <asm-generic/bitops/lock.h>

#include <asm-generic/bitops/non-atomic.h>
diff --git a/arch/avr32/include/asm/bitops.h
b/arch/avr32/include/asm/bitops.h
index 910d537..9f4a2ce 100644
--- a/arch/avr32/include/asm/bitops.h
+++ b/arch/avr32/include/asm/bitops.h
@@ -298,6 +298,7 @@ static inline int ffs(unsigned long word)
#include <asm-generic/bitops/fls64.h>
#include <asm-generic/bitops/sched.h>
#include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
#include <asm-generic/bitops/lock.h>

extern unsigned long find_next_zero_bit_le(const void *addr,
diff --git a/arch/c6x/include/asm/bitops.h b/arch/c6x/include/asm/bitops.h
index f0ab012..94eb0d1 100644
--- a/arch/c6x/include/asm/bitops.h
+++ b/arch/c6x/include/asm/bitops.h
@@ -87,6 +87,7 @@ static inline int ffs(int x)

#include <asm-generic/bitops/sched.h>
#include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
#include <asm-generic/bitops/lock.h>

#include <asm-generic/bitops/atomic.h>
diff --git a/arch/cris/include/asm/bitops.h b/arch/cris/include/asm/bitops.h
index 8062cb5..06bc246 100644
--- a/arch/cris/include/asm/bitops.h
+++ b/arch/cris/include/asm/bitops.h
@@ -36,6 +36,7 @@
#include <asm-generic/bitops/__fls.h>
#include <asm-generic/bitops/fls64.h>
#include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
#include <asm-generic/bitops/find.h>
#include <asm-generic/bitops/lock.h>

diff --git a/arch/frv/include/asm/bitops.h b/arch/frv/include/asm/bitops.h
index 0df8e95..f2a7ee8 100644
--- a/arch/frv/include/asm/bitops.h
+++ b/arch/frv/include/asm/bitops.h
@@ -314,6 +314,7 @@ int __ilog2_u64(u64 n)

#include <asm-generic/bitops/sched.h>
#include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
#include <asm-generic/bitops/lock.h>

#include <asm-generic/bitops/le.h>
diff --git a/arch/h8300/include/asm/bitops.h
b/arch/h8300/include/asm/bitops.h
index 05999ab..e392db2 100644
--- a/arch/h8300/include/asm/bitops.h
+++ b/arch/h8300/include/asm/bitops.h
@@ -172,6 +172,7 @@ static inline unsigned long __ffs(unsigned long word)
#include <asm-generic/bitops/find.h>
#include <asm-generic/bitops/sched.h>
#include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
#include <asm-generic/bitops/lock.h>
#include <asm-generic/bitops/le.h>
#include <asm-generic/bitops/ext2-atomic.h>
diff --git a/arch/hexagon/include/asm/bitops.h
b/arch/hexagon/include/asm/bitops.h
index 5e4a59b..2df614e 100644
--- a/arch/hexagon/include/asm/bitops.h
+++ b/arch/hexagon/include/asm/bitops.h
@@ -290,6 +290,7 @@ static inline unsigned long __fls(unsigned long word)
#include <asm-generic/bitops/fls64.h>
#include <asm-generic/bitops/sched.h>
#include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>

#include <asm-generic/bitops/le.h>
#include <asm-generic/bitops/ext2-atomic.h>
diff --git a/arch/m32r/include/asm/bitops.h b/arch/m32r/include/asm/bitops.h
index 86ba2b4..e3cf46b 100644
--- a/arch/m32r/include/asm/bitops.h
+++ b/arch/m32r/include/asm/bitops.h
@@ -259,6 +259,7 @@ static __inline__ int test_and_change_bit(int nr,
volatile void * addr)
#include <asm-generic/bitops/find.h>
#include <asm-generic/bitops/ffs.h>
#include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
#include <asm-generic/bitops/lock.h>

#endif /* __KERNEL__ */
diff --git a/arch/m68k/include/asm/bitops.h b/arch/m68k/include/asm/bitops.h
index b4a9b0d..fd673ea 100644
--- a/arch/m68k/include/asm/bitops.h
+++ b/arch/m68k/include/asm/bitops.h
@@ -519,6 +519,7 @@ static inline int __fls(int x)
#include <asm-generic/bitops/fls64.h>
#include <asm-generic/bitops/sched.h>
#include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
#include <asm-generic/bitops/lock.h>
#endif /* __KERNEL__ */

diff --git a/arch/metag/include/asm/bitops.h
b/arch/metag/include/asm/bitops.h
index 2671134..ad13087 100644
--- a/arch/metag/include/asm/bitops.h
+++ b/arch/metag/include/asm/bitops.h
@@ -118,6 +118,7 @@ static inline int test_and_change_bit(unsigned int bit,
#include <asm-generic/bitops/__fls.h>
#include <asm-generic/bitops/fls64.h>
#include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
#include <asm-generic/bitops/lock.h>
#include <asm-generic/bitops/sched.h>
#include <asm-generic/bitops/le.h>
diff --git a/arch/mn10300/include/asm/bitops.h
b/arch/mn10300/include/asm/bitops.h
index fe6f8e2..60761b7 100644
--- a/arch/mn10300/include/asm/bitops.h
+++ b/arch/mn10300/include/asm/bitops.h
@@ -225,6 +225,7 @@ int ffs(int x)
#include <asm-generic/bitops/find.h>
#include <asm-generic/bitops/sched.h>
#include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
#include <asm-generic/bitops/ext2-atomic-setbit.h>
#include <asm-generic/bitops/le.h>

diff --git a/arch/openrisc/include/asm/bitops.h
b/arch/openrisc/include/asm/bitops.h
index 3003cda..8c97642 100644
--- a/arch/openrisc/include/asm/bitops.h
+++ b/arch/openrisc/include/asm/bitops.h
@@ -43,6 +43,7 @@
#include <asm-generic/bitops/sched.h>
#include <asm/bitops/ffs.h>
#include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
#include <asm-generic/bitops/lock.h>

#include <asm-generic/bitops/atomic.h>
diff --git a/arch/parisc/include/asm/bitops.h
b/arch/parisc/include/asm/bitops.h
index 3f9406d..867ba10 100644
--- a/arch/parisc/include/asm/bitops.h
+++ b/arch/parisc/include/asm/bitops.h
@@ -211,6 +211,7 @@ static __inline__ int fls(int x)
#include <asm-generic/bitops/__fls.h>
#include <asm-generic/bitops/fls64.h>
#include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
#include <asm-generic/bitops/lock.h>
#include <asm-generic/bitops/sched.h>

diff --git a/arch/s390/include/asm/bitops.h b/arch/s390/include/asm/bitops.h
index 8043f10..198eead 100644
--- a/arch/s390/include/asm/bitops.h
+++ b/arch/s390/include/asm/bitops.h
@@ -460,6 +460,7 @@ static inline int fls(int word)
#include <asm-generic/bitops/ffz.h>
#include <asm-generic/bitops/find.h>
#include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
#include <asm-generic/bitops/sched.h>
#include <asm-generic/bitops/le.h>
#include <asm-generic/bitops/ext2-atomic-setbit.h>
diff --git a/arch/sh/include/asm/bitops.h b/arch/sh/include/asm/bitops.h
index fc8e652..4bf0c35 100644
--- a/arch/sh/include/asm/bitops.h
+++ b/arch/sh/include/asm/bitops.h
@@ -86,6 +86,7 @@ static inline unsigned long ffz(unsigned long word)
#include <asm-generic/bitops/find.h>
#include <asm-generic/bitops/ffs.h>
#include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
#include <asm-generic/bitops/lock.h>
#include <asm-generic/bitops/sched.h>
#include <asm-generic/bitops/le.h>
diff --git a/arch/xtensa/include/asm/bitops.h
b/arch/xtensa/include/asm/bitops.h
index 3f44fa2..981fa83 100644
--- a/arch/xtensa/include/asm/bitops.h
+++ b/arch/xtensa/include/asm/bitops.h
@@ -229,6 +229,7 @@ test_and_change_bit(unsigned int bit, volatile
unsigned long *p)
#include <asm-generic/bitops/ext2-atomic-setbit.h>

#include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
#include <asm-generic/bitops/lock.h>
#include <asm-generic/bitops/sched.h>

--
2.5.0

2016-04-05 19:04:41

by Sam Ravnborg

[permalink] [raw]
Subject: Re: [PATCH V2 01/30] bitops: add parity functions

On Tue, Apr 05, 2016 at 10:06:21AM +0800, Zeng Zhaoxiu wrote:
> From: Zhaoxiu Zeng <[email protected]>
>
> These patches provide generic and architecture-specific odd parity
> calculations.

Hi Zeng.

Can you please fix your mail script.
I see only 1/30 (sent to linux-arch) - and patch looks mangeled (broken lines)
No mail was sent to sparclinux - but sparc was mentioned.

git send-mail usually do the trick.

Sam

2016-04-06 05:33:43

by Zhaoxiu Zeng

[permalink] [raw]
Subject: Re: [PATCH V2 01/30] bitops: add parity functions

在 2016年04月06日 03:04, Sam Ravnborg 写道:
> On Tue, Apr 05, 2016 at 10:06:21AM +0800, Zeng Zhaoxiu wrote:
>> From: Zhaoxiu Zeng <[email protected]>
>>
>> These patches provide generic and architecture-specific odd parity
>> calculations.
> Hi Zeng.
>
> Can you please fix your mail script.
> I see only 1/30 (sent to linux-arch) - and patch looks mangeled (broken lines)
> No mail was sent to sparclinux - but sparc was mentioned.
>
> git send-mail usually do the trick.
>
> Sam

When I do "git send-email", I got:
...
5.7.14 JTibJDWdGxPcfa-E9KgtF-grMQl9w> Please log in via your web browser and
5.7.14 then try again.
5.7.14 Learn more at
5.7.14 https://support.google.com/mail/answer/78754 zp5sm464879pac.9 - gsmtp
...

So I use thunderbird to send email, but the text wrap error.

2016-04-06 08:25:07

by Sam Ravnborg

[permalink] [raw]
Subject: Re: [PATCH V2 01/30] bitops: add parity functions

On Wed, Apr 06, 2016 at 01:33:35PM +0800, Zeng Zhaoxiu wrote:
> 在 2016年04月06日 03:04, Sam Ravnborg 写道:
> >On Tue, Apr 05, 2016 at 10:06:21AM +0800, Zeng Zhaoxiu wrote:
> >>From: Zhaoxiu Zeng <[email protected]>
> >>
> >>These patches provide generic and architecture-specific odd parity
> >>calculations.
> >Hi Zeng.
> >
> >Can you please fix your mail script.
> >I see only 1/30 (sent to linux-arch) - and patch looks mangeled (broken lines)
> >No mail was sent to sparclinux - but sparc was mentioned.
> >
> >git send-mail usually do the trick.
> >
> > Sam
>
> When I do "git send-email", I got:
> ...
> 5.7.14 JTibJDWdGxPcfa-E9KgtF-grMQl9w> Please log in via your web browser and
> 5.7.14 then try again.
> 5.7.14 Learn more at
> 5.7.14 https://support.google.com/mail/answer/78754 zp5sm464879pac.9 - gsmtp
> ...
>
> So I use thunderbird to send email, but the text wrap error.
Please try to search for "How to configure git send-email to use Gmail"
and follow the instructions given in some of the links.
Test with your own mail address before you send to a list.

Also linux-arch only saw 1/30 - make sure to address this too.

Sam

2016-04-06 08:40:53

by Zhaoxiu Zeng

[permalink] [raw]
Subject: [PATCH v2 01/30] bitops: add parity functions

From: Zhaoxiu Zeng <[email protected]>

These patches provide generic and architecture-specific odd parity calculations.

I did not use GCC's __builtin_parity* functions, based on the following reasons:
1. I don't know where to identify which version of GCC from the beginning
supported __builtin_parity for the architecture.
2. For the architecture that doesn't has popcount instruction, GCC instead use
"call __paritysi2" (__paritydi2 for 64-bits). So if use __builtin_parity, we must
provide __paritysi2 and __paritydi2 functions for these architectures.
Additionally, parity4,8,16 might be "__builtin_parity(x & mask)", but the "& mask"
operation is totally unnecessary.
3. For the architecture that has popcount instruction, we do the same things.
4. For powerpc64, sparc64, and x86, we do runtime patching to use popcount instruction
if the CPU support.

I have compiled successfully with x86_64_defconfig, i386_defconfig, pseries_defconfig
and sparc64_defconfig. And I used the following codes to test:

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

#ifdef __x86_64__
/* popcnt %edi, %eax -- redundant REX prefix for alignment */
#define POPCNT32 ".byte 0xf3,0x40,0x0f,0xb8,0xc7"
/* popcnt %rdi, %rax */
#define POPCNT64 ".byte 0xf3,0x48,0x0f,0xb8,0xc7"
#define REG_IN "D"
#define REG_OUT "a"
#else
/* popcnt %eax, %eax */
#define POPCNT32 ".byte 0xf3,0x0f,0xb8,0xc0"
#define REG_IN "a"
#define REG_OUT "a"
#endif

static inline int c_parity4(unsigned int w)
{
w &= 0xf;
return (0x6996 >> w) & 1;
}

static inline int c_parity8(unsigned int w)
{
w ^= w >> 4;
return c_parity4(w);
}

static inline int c_parity16(unsigned int w)
{
w ^= w >> 8;
return c_parity8(w);
}

static inline int c_parity32(unsigned int w)
{
w ^= w >> 16;
return c_parity16(w);
}

static inline int c_parity64(uint64_t w)
{
return c_parity32((unsigned int)w ^ (unsigned int)(w >> 32));
}

static inline int asm_parity4(unsigned int w)
{
unsigned int res = 0;

asm("test $0xf, %1 \n"
"setpo %b0 \n"
: "+q" (res)
: "r" (w)
: "cc");

return res;
}

static inline int asm_parity8(unsigned int w)
{
unsigned int res = 0;

asm("test %1, %1 \n"
"setpo %b0 \n"
: "+q" (res)
: "r" (w)
: "cc");

return res;
}

static inline int asm_parity16(unsigned int w)
{
unsigned int res = 0;

asm("xor %h1, %b1 \n"
"setpo %b0 \n"
: "+q" (res), "+q" (w)
: : "cc");

return res;
}

static inline int asm_parity32_1(unsigned int w)
{
unsigned int res;

w ^= w >> 16;
asm("xor %%ah, %%al \n"
"mov $0, %%eax \n"
"setpo %%al \n"
: "=a" (res)
: "a" (w)
: "cc");

return res;
}

static inline int asm_parity32_2(unsigned int w)
{
unsigned int res;

asm(POPCNT32 " \n"
"andl $1, %0 \n"
: "="REG_OUT (res)
: REG_IN (w)
: "cc");

return res;
}

#ifdef __x86_64__
static inline int asm_parity64_1(uint64_t w)
{
unsigned int res = (unsigned int)w ^ (unsigned int)(w >> 32);

res ^= res >> 16;
asm("xor %%ah, %%al \n"
"mov $0, %%eax \n"
"setpo %%al \n"
: "=a" (res)
: "a" (res)
: "cc");

return res;
}

static inline int asm_parity64_2(uint64_t w)
{
unsigned int res;

asm(POPCNT64 " \n"
"andl $1, %0 \n"
: "="REG_OUT (res)
: REG_IN (w)
: "cc");

return res;
}
#else
static inline int asm_parity64_1(uint64_t w)
{
return asm_parity32_1((unsigned int)(w >> 32) ^ (unsigned int)w);
}

static inline int asm_parity64_2(uint64_t w)
{
return asm_parity32_2((unsigned int)(w >> 32) ^ (unsigned int)w);
}
#endif

int main(int argc, char **argv)
{
int ok = 1;
int count = 1000, i;

if (argc >= 2)
count = atoi(argv[1]);

srand((unsigned)time(NULL));

for (i = 0; i < count; i++) {
uint64_t w = rand() | (uint64_t)rand() << 32;
int p4_1 = c_parity4(w);
int p4_2 = asm_parity4(w);
int p8_1 = c_parity8(w);
int p8_2 = asm_parity8(w);
int p16_1 = c_parity16(w);
int p16_2 = asm_parity16(w);
int p32_1 = c_parity32(w);
int p32_2 = asm_parity32_1(w);
int p32_3 = asm_parity32_2(w);
int p64_1 = c_parity64(w);
int p64_2 = asm_parity64_1(w);
int p64_3 = asm_parity64_2(w);
if (p4_1 != p4_2 ||
p8_1 != p8_2 ||
p16_1 != p16_2 ||
p32_1 != p32_2 || p32_1 != p32_3 ||
p64_1 != p64_2 || p64_1 != p64_3) {
fprintf(stderr, "Err: %llx\n"
"\tc_parity4 = %d, asm_parity4 = %d,\n"
"\tc_parity8 = %d, asm_parity8 = %d,\n"
"\tc_parity16 = %d, asm_parity16 = %d,\n"
"\tc_parity32 = %d, asm_parity32_1 = %d, asm_parity32_2 = %d\n"
"\tc_parity64 = %d, asm_parity64_1 = %d, asm_parity64_2 = %d\n",
w, p4_1, p4_2, p8_1, p8_2, p16_1, p16_2, p32_1, p32_2, p32_3, p64_1, p64_2, p64_3);
ok = 0;
}
}

fprintf(stderr, "%s\n", ok ? "OK" : "FAIL");
return 0;
}

Signed-off-by: Zhaoxiu Zeng <[email protected]>
---
include/asm-generic/bitops.h | 1 +
include/asm-generic/bitops/arch_parity.h | 39 +++++++++++++++++++++++++++++++
include/asm-generic/bitops/const_parity.h | 36 ++++++++++++++++++++++++++++
include/asm-generic/bitops/parity.h | 7 ++++++
include/linux/bitops.h | 5 ++++
5 files changed, 88 insertions(+)
create mode 100644 include/asm-generic/bitops/arch_parity.h
create mode 100644 include/asm-generic/bitops/const_parity.h
create mode 100644 include/asm-generic/bitops/parity.h

diff --git a/include/asm-generic/bitops.h b/include/asm-generic/bitops.h
index dcdcacf..d85722f 100644
--- a/include/asm-generic/bitops.h
+++ b/include/asm-generic/bitops.h
@@ -27,6 +27,7 @@
#include <asm-generic/bitops/sched.h>
#include <asm-generic/bitops/ffs.h>
#include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
#include <asm-generic/bitops/lock.h>

#include <asm-generic/bitops/atomic.h>
diff --git a/include/asm-generic/bitops/arch_parity.h b/include/asm-generic/bitops/arch_parity.h
new file mode 100644
index 0000000..cddc555
--- /dev/null
+++ b/include/asm-generic/bitops/arch_parity.h
@@ -0,0 +1,39 @@
+#ifndef _ASM_GENERIC_BITOPS_ARCH_PARITY_H_
+#define _ASM_GENERIC_BITOPS_ARCH_PARITY_H_
+
+#include <asm/types.h>
+
+/*
+ * Refrence to 'https://graphics.stanford.edu/~seander/bithacks.html#ParityParallel'.
+ */
+
+static inline unsigned int __arch_parity4(unsigned int w)
+{
+ w &= 0xf;
+ return (0x6996 >> w) & 1;
+}
+
+static inline unsigned int __arch_parity8(unsigned int w)
+{
+ w ^= w >> 4;
+ return __arch_parity4(w);
+}
+
+static inline unsigned int __arch_parity16(unsigned int w)
+{
+ w ^= w >> 8;
+ return __arch_parity8(w);
+}
+
+static inline unsigned int __arch_parity32(unsigned int w)
+{
+ w ^= w >> 16;
+ return __arch_parity16(w);
+}
+
+static inline unsigned int __arch_parity64(__u64 w)
+{
+ return __arch_parity32((unsigned int)(w >> 32) ^ (unsigned int)w);
+}
+
+#endif /* _ASM_GENERIC_BITOPS_ARCH_PARITY_H_ */
diff --git a/include/asm-generic/bitops/const_parity.h b/include/asm-generic/bitops/const_parity.h
new file mode 100644
index 0000000..6af7987
--- /dev/null
+++ b/include/asm-generic/bitops/const_parity.h
@@ -0,0 +1,36 @@
+#ifndef _ASM_GENERIC_BITOPS_CONST_PARITY_H_
+#define _ASM_GENERIC_BITOPS_CONST_PARITY_H_
+
+/*
+ * Compile time versions of __arch_parityN()
+ */
+#define __const_parity4(w) ((0x6996 >> ((w) & 0xf)) & 1)
+#define __const_parity8(w) (__const_parity4((w) ^ ((w) >> 4)))
+#define __const_parity16(w) (__const_parity8((w) ^ ((w) >> 8)))
+#define __const_parity32(w) (__const_parity16((w) ^ ((w) >> 16)))
+#define __const_parity64(w) (__const_parity32((w) ^ ((w) >> 32)))
+
+/*
+ * Generic interface.
+ */
+#define parity4(w) (__builtin_constant_p(w) ? __const_parity4(w) : __arch_parity4(w))
+#define parity8(w) (__builtin_constant_p(w) ? __const_parity8(w) : __arch_parity8(w))
+#define parity16(w) (__builtin_constant_p(w) ? __const_parity16(w) : __arch_parity16(w))
+#define parity32(w) (__builtin_constant_p(w) ? __const_parity32(w) : __arch_parity32(w))
+#define parity64(w) (__builtin_constant_p(w) ? __const_parity64(w) : __arch_parity64(w))
+
+/*
+ * Interface for known constant arguments
+ */
+#define PARITY4(w) (BUILD_BUG_ON_ZERO(!__builtin_constant_p(w)) + __const_parity4(w))
+#define PARITY8(w) (BUILD_BUG_ON_ZERO(!__builtin_constant_p(w)) + __const_parity8(w))
+#define PARITY16(w) (BUILD_BUG_ON_ZERO(!__builtin_constant_p(w)) + __const_parity16(w))
+#define PARITY32(w) (BUILD_BUG_ON_ZERO(!__builtin_constant_p(w)) + __const_parity32(w))
+#define PARITY64(w) (BUILD_BUG_ON_ZERO(!__builtin_constant_p(w)) + __const_parity64(w))
+
+/*
+ * Type invariant interface to the compile time constant parity functions.
+ */
+#define PARITY(w) PARITY64((u64)(w))
+
+#endif /* _ASM_GENERIC_BITOPS_CONST_PARITY_H_ */
diff --git a/include/asm-generic/bitops/parity.h b/include/asm-generic/bitops/parity.h
new file mode 100644
index 0000000..a91dce7
--- /dev/null
+++ b/include/asm-generic/bitops/parity.h
@@ -0,0 +1,7 @@
+#ifndef _ASM_GENERIC_BITOPS_PARITY_H_
+#define _ASM_GENERIC_BITOPS_PARITY_H_
+
+#include <asm-generic/bitops/arch_parity.h>
+#include <asm-generic/bitops/const_parity.h>
+
+#endif /* _ASM_GENERIC_BITOPS_PARITY_H_ */
diff --git a/include/linux/bitops.h b/include/linux/bitops.h
index defeaac..8952f88 100644
--- a/include/linux/bitops.h
+++ b/include/linux/bitops.h
@@ -80,6 +80,11 @@ static __always_inline unsigned long hweight_long(unsigned long w)
return sizeof(w) == 4 ? hweight32(w) : hweight64(w);
}

+static __always_inline unsigned int parity_long(unsigned long w)
+{
+ return sizeof(w) == 4 ? parity32(w) : parity64(w);
+}
+
/**
* rol64 - rotate a 64-bit value left
* @word: value to rotate
--
2.5.0


2016-04-06 08:47:06

by Zhaoxiu Zeng

[permalink] [raw]
Subject: [PATCH v2 03/30] Add alpha-specific parity functions

From: Zhaoxiu Zeng <[email protected]>

Signed-off-by: Zhaoxiu Zeng <[email protected]>
---
arch/alpha/include/asm/bitops.h | 27 +++++++++++++++++++++++++++
1 file changed, 27 insertions(+)

diff --git a/arch/alpha/include/asm/bitops.h b/arch/alpha/include/asm/bitops.h
index 4bdfbd4..95a43fa 100644
--- a/arch/alpha/include/asm/bitops.h
+++ b/arch/alpha/include/asm/bitops.h
@@ -421,11 +421,38 @@ static inline unsigned int __arch_hweight8(unsigned int w)
{
return __arch_hweight64(w & 0xff);
}
+
+static inline unsigned int __arch_parity64(unsigned long w)
+{
+ return (unsigned int)__kernel_ctpop(w) & 1;
+}
+
+static inline unsigned int __arch_parity32(unsigned int w)
+{
+ return __arch_parity64(w);
+}
+
+static inline unsigned int __arch_parity16(unsigned int w)
+{
+ return __arch_parity64(w & 0xffff);
+}
+
+static inline unsigned int __arch_parity8(unsigned int w)
+{
+ return __arch_parity64(w & 0xff);
+}
+
+static inline unsigned int __arch_parity4(unsigned int w)
+{
+ return __arch_parity64(w & 0xf);
+}
#else
#include <asm-generic/bitops/arch_hweight.h>
+#include <asm-generic/bitops/arch_parity.h>
#endif

#include <asm-generic/bitops/const_hweight.h>
+#include <asm-generic/bitops/const_parity.h>

#endif /* __KERNEL__ */

--
2.5.0


2016-04-06 08:47:27

by Zhaoxiu Zeng

[permalink] [raw]
Subject: [PATCH v2 02/30] Include generic parity.h in some architectures' bitops.h

From: Zhaoxiu Zeng <[email protected]>

Use the generic version

Signed-off-by: Zhaoxiu Zeng <[email protected]>
---
arch/arc/include/asm/bitops.h | 1 +
arch/arm/include/asm/bitops.h | 1 +
arch/arm64/include/asm/bitops.h | 1 +
arch/avr32/include/asm/bitops.h | 1 +
arch/c6x/include/asm/bitops.h | 1 +
arch/cris/include/asm/bitops.h | 1 +
arch/frv/include/asm/bitops.h | 1 +
arch/h8300/include/asm/bitops.h | 1 +
arch/hexagon/include/asm/bitops.h | 1 +
arch/m32r/include/asm/bitops.h | 1 +
arch/m68k/include/asm/bitops.h | 1 +
arch/metag/include/asm/bitops.h | 1 +
arch/mn10300/include/asm/bitops.h | 1 +
arch/openrisc/include/asm/bitops.h | 1 +
arch/parisc/include/asm/bitops.h | 1 +
arch/s390/include/asm/bitops.h | 1 +
arch/sh/include/asm/bitops.h | 1 +
arch/xtensa/include/asm/bitops.h | 1 +
18 files changed, 18 insertions(+)

diff --git a/arch/arc/include/asm/bitops.h b/arch/arc/include/asm/bitops.h
index 0352fb8..7967e47 100644
--- a/arch/arc/include/asm/bitops.h
+++ b/arch/arc/include/asm/bitops.h
@@ -370,6 +370,7 @@ static inline __attribute__ ((const)) int __ffs(unsigned long x)
#define ffz(x) __ffs(~(x))

#include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
#include <asm-generic/bitops/fls64.h>
#include <asm-generic/bitops/sched.h>
#include <asm-generic/bitops/lock.h>
diff --git a/arch/arm/include/asm/bitops.h b/arch/arm/include/asm/bitops.h
index e943e6c..99f28a6 100644
--- a/arch/arm/include/asm/bitops.h
+++ b/arch/arm/include/asm/bitops.h
@@ -313,6 +313,7 @@ static inline unsigned long __ffs(unsigned long x)

#include <asm-generic/bitops/sched.h>
#include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
#include <asm-generic/bitops/lock.h>

#ifdef __ARMEB__
diff --git a/arch/arm64/include/asm/bitops.h b/arch/arm64/include/asm/bitops.h
index 9c19594..eac4965 100644
--- a/arch/arm64/include/asm/bitops.h
+++ b/arch/arm64/include/asm/bitops.h
@@ -44,6 +44,7 @@ extern int test_and_change_bit(int nr, volatile unsigned long *p);

#include <asm-generic/bitops/sched.h>
#include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
#include <asm-generic/bitops/lock.h>

#include <asm-generic/bitops/non-atomic.h>
diff --git a/arch/avr32/include/asm/bitops.h b/arch/avr32/include/asm/bitops.h
index 910d537..9f4a2ce 100644
--- a/arch/avr32/include/asm/bitops.h
+++ b/arch/avr32/include/asm/bitops.h
@@ -298,6 +298,7 @@ static inline int ffs(unsigned long word)
#include <asm-generic/bitops/fls64.h>
#include <asm-generic/bitops/sched.h>
#include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
#include <asm-generic/bitops/lock.h>

extern unsigned long find_next_zero_bit_le(const void *addr,
diff --git a/arch/c6x/include/asm/bitops.h b/arch/c6x/include/asm/bitops.h
index f0ab012..94eb0d1 100644
--- a/arch/c6x/include/asm/bitops.h
+++ b/arch/c6x/include/asm/bitops.h
@@ -87,6 +87,7 @@ static inline int ffs(int x)

#include <asm-generic/bitops/sched.h>
#include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
#include <asm-generic/bitops/lock.h>

#include <asm-generic/bitops/atomic.h>
diff --git a/arch/cris/include/asm/bitops.h b/arch/cris/include/asm/bitops.h
index 8062cb5..06bc246 100644
--- a/arch/cris/include/asm/bitops.h
+++ b/arch/cris/include/asm/bitops.h
@@ -36,6 +36,7 @@
#include <asm-generic/bitops/__fls.h>
#include <asm-generic/bitops/fls64.h>
#include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
#include <asm-generic/bitops/find.h>
#include <asm-generic/bitops/lock.h>

diff --git a/arch/frv/include/asm/bitops.h b/arch/frv/include/asm/bitops.h
index 0df8e95..f2a7ee8 100644
--- a/arch/frv/include/asm/bitops.h
+++ b/arch/frv/include/asm/bitops.h
@@ -314,6 +314,7 @@ int __ilog2_u64(u64 n)

#include <asm-generic/bitops/sched.h>
#include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
#include <asm-generic/bitops/lock.h>

#include <asm-generic/bitops/le.h>
diff --git a/arch/h8300/include/asm/bitops.h b/arch/h8300/include/asm/bitops.h
index 05999ab..e392db2 100644
--- a/arch/h8300/include/asm/bitops.h
+++ b/arch/h8300/include/asm/bitops.h
@@ -172,6 +172,7 @@ static inline unsigned long __ffs(unsigned long word)
#include <asm-generic/bitops/find.h>
#include <asm-generic/bitops/sched.h>
#include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
#include <asm-generic/bitops/lock.h>
#include <asm-generic/bitops/le.h>
#include <asm-generic/bitops/ext2-atomic.h>
diff --git a/arch/hexagon/include/asm/bitops.h b/arch/hexagon/include/asm/bitops.h
index 5e4a59b..2df614e 100644
--- a/arch/hexagon/include/asm/bitops.h
+++ b/arch/hexagon/include/asm/bitops.h
@@ -290,6 +290,7 @@ static inline unsigned long __fls(unsigned long word)
#include <asm-generic/bitops/fls64.h>
#include <asm-generic/bitops/sched.h>
#include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>

#include <asm-generic/bitops/le.h>
#include <asm-generic/bitops/ext2-atomic.h>
diff --git a/arch/m32r/include/asm/bitops.h b/arch/m32r/include/asm/bitops.h
index 86ba2b4..e3cf46b 100644
--- a/arch/m32r/include/asm/bitops.h
+++ b/arch/m32r/include/asm/bitops.h
@@ -259,6 +259,7 @@ static __inline__ int test_and_change_bit(int nr, volatile void * addr)
#include <asm-generic/bitops/find.h>
#include <asm-generic/bitops/ffs.h>
#include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
#include <asm-generic/bitops/lock.h>

#endif /* __KERNEL__ */
diff --git a/arch/m68k/include/asm/bitops.h b/arch/m68k/include/asm/bitops.h
index b4a9b0d..fd673ea 100644
--- a/arch/m68k/include/asm/bitops.h
+++ b/arch/m68k/include/asm/bitops.h
@@ -519,6 +519,7 @@ static inline int __fls(int x)
#include <asm-generic/bitops/fls64.h>
#include <asm-generic/bitops/sched.h>
#include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
#include <asm-generic/bitops/lock.h>
#endif /* __KERNEL__ */

diff --git a/arch/metag/include/asm/bitops.h b/arch/metag/include/asm/bitops.h
index 2671134..ad13087 100644
--- a/arch/metag/include/asm/bitops.h
+++ b/arch/metag/include/asm/bitops.h
@@ -118,6 +118,7 @@ static inline int test_and_change_bit(unsigned int bit,
#include <asm-generic/bitops/__fls.h>
#include <asm-generic/bitops/fls64.h>
#include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
#include <asm-generic/bitops/lock.h>
#include <asm-generic/bitops/sched.h>
#include <asm-generic/bitops/le.h>
diff --git a/arch/mn10300/include/asm/bitops.h b/arch/mn10300/include/asm/bitops.h
index fe6f8e2..60761b7 100644
--- a/arch/mn10300/include/asm/bitops.h
+++ b/arch/mn10300/include/asm/bitops.h
@@ -225,6 +225,7 @@ int ffs(int x)
#include <asm-generic/bitops/find.h>
#include <asm-generic/bitops/sched.h>
#include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
#include <asm-generic/bitops/ext2-atomic-setbit.h>
#include <asm-generic/bitops/le.h>

diff --git a/arch/openrisc/include/asm/bitops.h b/arch/openrisc/include/asm/bitops.h
index 3003cda..8c97642 100644
--- a/arch/openrisc/include/asm/bitops.h
+++ b/arch/openrisc/include/asm/bitops.h
@@ -43,6 +43,7 @@
#include <asm-generic/bitops/sched.h>
#include <asm/bitops/ffs.h>
#include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
#include <asm-generic/bitops/lock.h>

#include <asm-generic/bitops/atomic.h>
diff --git a/arch/parisc/include/asm/bitops.h b/arch/parisc/include/asm/bitops.h
index 3f9406d..867ba10 100644
--- a/arch/parisc/include/asm/bitops.h
+++ b/arch/parisc/include/asm/bitops.h
@@ -211,6 +211,7 @@ static __inline__ int fls(int x)
#include <asm-generic/bitops/__fls.h>
#include <asm-generic/bitops/fls64.h>
#include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
#include <asm-generic/bitops/lock.h>
#include <asm-generic/bitops/sched.h>

diff --git a/arch/s390/include/asm/bitops.h b/arch/s390/include/asm/bitops.h
index 8043f10..198eead 100644
--- a/arch/s390/include/asm/bitops.h
+++ b/arch/s390/include/asm/bitops.h
@@ -460,6 +460,7 @@ static inline int fls(int word)
#include <asm-generic/bitops/ffz.h>
#include <asm-generic/bitops/find.h>
#include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
#include <asm-generic/bitops/sched.h>
#include <asm-generic/bitops/le.h>
#include <asm-generic/bitops/ext2-atomic-setbit.h>
diff --git a/arch/sh/include/asm/bitops.h b/arch/sh/include/asm/bitops.h
index fc8e652..4bf0c35 100644
--- a/arch/sh/include/asm/bitops.h
+++ b/arch/sh/include/asm/bitops.h
@@ -86,6 +86,7 @@ static inline unsigned long ffz(unsigned long word)
#include <asm-generic/bitops/find.h>
#include <asm-generic/bitops/ffs.h>
#include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
#include <asm-generic/bitops/lock.h>
#include <asm-generic/bitops/sched.h>
#include <asm-generic/bitops/le.h>
diff --git a/arch/xtensa/include/asm/bitops.h b/arch/xtensa/include/asm/bitops.h
index 3f44fa2..981fa83 100644
--- a/arch/xtensa/include/asm/bitops.h
+++ b/arch/xtensa/include/asm/bitops.h
@@ -229,6 +229,7 @@ test_and_change_bit(unsigned int bit, volatile unsigned long *p)
#include <asm-generic/bitops/ext2-atomic-setbit.h>

#include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
#include <asm-generic/bitops/lock.h>
#include <asm-generic/bitops/sched.h>

--
2.5.0


2016-04-06 08:58:19

by Zhaoxiu Zeng

[permalink] [raw]
Subject: [PATCH v2 05/30] Add ia64-specific parity functions

From: Zhaoxiu Zeng <[email protected]>

Signed-off-by: Zhaoxiu Zeng <[email protected]>
---
arch/ia64/include/asm/bitops.h | 31 +++++++++++++++++++++++++++++++
1 file changed, 31 insertions(+)

diff --git a/arch/ia64/include/asm/bitops.h b/arch/ia64/include/asm/bitops.h
index 71e8145..041d1d6 100644
--- a/arch/ia64/include/asm/bitops.h
+++ b/arch/ia64/include/asm/bitops.h
@@ -439,6 +439,37 @@ static __inline__ unsigned long __arch_hweight64(unsigned long x)

#include <asm-generic/bitops/const_hweight.h>

+/*
+ * parityN: returns the parity of a N-bit word,
+ * i.e. the number of 1-bits in x modulo 2.
+ */
+static __inline__ unsigned int __arch_parity64(unsigned long x)
+{
+ return (unsigned int)ia64_popcnt(x) & 1;
+}
+
+static __inline__ unsigned int __arch_parity32(unsigned int x)
+{
+ return __arch_parity64((unsigned long)x << 32);
+}
+
+static __inline__ unsigned int __arch_parity16(unsigned int x)
+{
+ return __arch_parity64((unsigned long)x << 48);
+}
+
+static __inline__ unsigned int __arch_parity8(unsigned int x)
+{
+ return __arch_parity64((unsigned long)x << 56);
+}
+
+static __inline__ unsigned int __arch_parity4(unsigned int x)
+{
+ return __arch_parity64((unsigned long)x << 60);
+}
+
+#include <asm-generic/bitops/const_parity.h>
+
#endif /* __KERNEL__ */

#include <asm-generic/bitops/find.h>
--
2.5.0


2016-04-06 09:00:22

by Zhaoxiu Zeng

[permalink] [raw]
Subject: [PATCH v2 06/30] Add mips-specific parity functions

From: Zhaoxiu Zeng <[email protected]>

Lifted from arch_hweight.h

Signed-off-by: Zhaoxiu Zeng <[email protected]>
---
arch/mips/include/asm/arch_parity.h | 44 +++++++++++++++++++++++++++++++++++++
arch/mips/include/asm/bitops.h | 3 +++
2 files changed, 47 insertions(+)
create mode 100644 arch/mips/include/asm/arch_parity.h

diff --git a/arch/mips/include/asm/arch_parity.h b/arch/mips/include/asm/arch_parity.h
new file mode 100644
index 0000000..23b3c23
--- /dev/null
+++ b/arch/mips/include/asm/arch_parity.h
@@ -0,0 +1,44 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ */
+#ifndef _ASM_ARCH_PARITY_H
+#define _ASM_ARCH_PARITY_H
+
+#ifdef ARCH_HAS_USABLE_BUILTIN_POPCOUNT
+
+#include <asm/types.h>
+
+static inline unsigned int __arch_parity32(unsigned int w)
+{
+ return __builtin_popcount(w) & 1;
+}
+
+static inline unsigned int __arch_parity16(unsigned int w)
+{
+ return __arch_parity32(w & 0xffff);
+}
+
+static inline unsigned int __arch_parity8(unsigned int w)
+{
+ return __arch_parity32(w & 0xff);
+}
+
+static inline unsigned int __arch_parity4(unsigned int w)
+{
+ return __arch_parity32(w & 0xf);
+}
+
+static inline unsigned int __arch_parity64(__u64 w)
+{
+ return (unsigned int)__builtin_popcountll(w) & 1;
+}
+
+#else
+#include <asm-generic/bitops/arch_hweight.h>
+#include <asm-generic/bitops/arch_parity.h>
+#endif
+
+#endif /* _ASM_ARCH_PARITY_H */
diff --git a/arch/mips/include/asm/bitops.h b/arch/mips/include/asm/bitops.h
index ce9666c..0b87734 100644
--- a/arch/mips/include/asm/bitops.h
+++ b/arch/mips/include/asm/bitops.h
@@ -626,6 +626,9 @@ static inline int ffs(int word)
#include <asm/arch_hweight.h>
#include <asm-generic/bitops/const_hweight.h>

+#include <asm/arch_parity.h>
+#include <asm-generic/bitops/const_parity.h>
+
#include <asm-generic/bitops/le.h>
#include <asm-generic/bitops/ext2-atomic.h>

--
2.5.0


2016-04-06 09:05:52

by Zhaoxiu Zeng

[permalink] [raw]
Subject: [PATCH v2 07/30] Add powerpc-specific parity functions

From: Zhaoxiu Zeng <[email protected]>

Use runtime patching for ppc64, lifted from hweight_64

Signed-off-by: Zhaoxiu Zeng <[email protected]>
---
arch/powerpc/include/asm/bitops.h | 11 ++++
arch/powerpc/lib/Makefile | 2 +-
arch/powerpc/lib/parity_64.S | 107 ++++++++++++++++++++++++++++++++++++++
arch/powerpc/lib/ppc_ksyms.c | 5 ++
4 files changed, 124 insertions(+), 1 deletion(-)
create mode 100644 arch/powerpc/lib/parity_64.S

diff --git a/arch/powerpc/include/asm/bitops.h b/arch/powerpc/include/asm/bitops.h
index 59abc62..cb92783 100644
--- a/arch/powerpc/include/asm/bitops.h
+++ b/arch/powerpc/include/asm/bitops.h
@@ -269,8 +269,19 @@ unsigned int __arch_hweight16(unsigned int w);
unsigned int __arch_hweight32(unsigned int w);
unsigned long __arch_hweight64(__u64 w);
#include <asm-generic/bitops/const_hweight.h>
+static inline unsigned int __arch_parity4(unsigned int w)
+{
+ w &= 0xf;
+ return (0x6996 >> w) & 1;
+}
+unsigned int __arch_parity8(unsigned int w);
+unsigned int __arch_parity16(unsigned int w);
+unsigned int __arch_parity32(unsigned int w);
+unsigned int __arch_parity64(__u64 w);
+#include <asm-generic/bitops/const_parity.h>
#else
#include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
#endif

#include <asm-generic/bitops/find.h>
diff --git a/arch/powerpc/lib/Makefile b/arch/powerpc/lib/Makefile
index ba21be1..cae2e7f 100644
--- a/arch/powerpc/lib/Makefile
+++ b/arch/powerpc/lib/Makefile
@@ -16,7 +16,7 @@ obj-$(CONFIG_PPC32) += div64.o copy_32.o

obj64-y += copypage_64.o copyuser_64.o usercopy_64.o mem_64.o hweight_64.o \
copyuser_power7.o string_64.o copypage_power7.o memcpy_power7.o \
- memcpy_64.o memcmp_64.o
+ memcpy_64.o memcmp_64.o parity_64.o

obj64-$(CONFIG_SMP) += locks.o
obj64-$(CONFIG_ALTIVEC) += vmx-helper.o
diff --git a/arch/powerpc/lib/parity_64.S b/arch/powerpc/lib/parity_64.S
new file mode 100644
index 0000000..f8a2771
--- /dev/null
+++ b/arch/powerpc/lib/parity_64.S
@@ -0,0 +1,107 @@
+#include <asm/processor.h>
+#include <asm/ppc_asm.h>
+
+/* Note: This code relies on -mminimal-toc */
+
+_GLOBAL(__arch_parity8)
+BEGIN_FTR_SECTION
+ srdi r4,r3,4
+ xor r3,r3,r4
+ clrldi r3,r3,64-4
+ li r4,0x6996
+ srd r3,r4,r3
+ clrldi r3,r3,64-1
+ blr
+FTR_SECTION_ELSE
+ PPC_POPCNTB(R3,R3)
+ clrldi r3,r3,64-1
+ blr
+ALT_FTR_SECTION_END_IFCLR(CPU_FTR_POPCNTB)
+
+_GLOBAL(__arch_parity16)
+BEGIN_FTR_SECTION
+ srdi r4,r3,8
+ xor r3,r3,r4
+ srdi r4,r3,4
+ xor r3,r3,r4
+ clrldi r3,r3,64-4
+ li r4,0x6996
+ srd r3,r4,r3
+ clrldi r3,r3,64-1
+ blr
+FTR_SECTION_ELSE
+ BEGIN_FTR_SECTION_NESTED(50)
+ PPC_POPCNTB(R3,R3)
+ srdi r4,r3,8
+ add r3,r4,r3
+ clrldi r3,r3,64-1
+ blr
+ FTR_SECTION_ELSE_NESTED(50)
+ clrlwi r3,r3,16
+ PPC_POPCNTW(R3,R3)
+ clrldi r3,r3,64-1
+ blr
+ ALT_FTR_SECTION_END_NESTED_IFCLR(CPU_FTR_POPCNTD, 50)
+ALT_FTR_SECTION_END_IFCLR(CPU_FTR_POPCNTB)
+
+_GLOBAL(__arch_parity32)
+BEGIN_FTR_SECTION
+ srdi r4,r3,16
+ xor r3,r3,r4
+ srdi r4,r3,8
+ xor r3,r3,r4
+ srdi r4,r3,4
+ xor r3,r3,r4
+ clrldi r3,r3,64-4
+ li r4,0x6996
+ srd r3,r4,r3
+ clrldi r3,r3,64-1
+ blr
+FTR_SECTION_ELSE
+ BEGIN_FTR_SECTION_NESTED(51)
+ PPC_POPCNTB(R3,R3)
+ srdi r4,r3,16
+ add r3,r4,r3
+ srdi r4,r3,8
+ add r3,r4,r3
+ clrldi r3,r3,64-1
+ blr
+ FTR_SECTION_ELSE_NESTED(51)
+ PPC_POPCNTW(R3,R3)
+ clrldi r3,r3,64-1
+ blr
+ ALT_FTR_SECTION_END_NESTED_IFCLR(CPU_FTR_POPCNTD, 51)
+ALT_FTR_SECTION_END_IFCLR(CPU_FTR_POPCNTB)
+
+_GLOBAL(__arch_parity64)
+BEGIN_FTR_SECTION
+ srdi r4,r3,32
+ xor r3,r3,r4
+ srdi r4,r3,16
+ xor r3,r3,r4
+ srdi r4,r3,8
+ xor r3,r3,r4
+ srdi r4,r3,4
+ xor r3,r3,r4
+ clrldi r3,r3,64-4
+ li r4,0x6996
+ srd r3,r4,r3
+ clrldi r3,r3,64-1
+ blr
+FTR_SECTION_ELSE
+ BEGIN_FTR_SECTION_NESTED(52)
+ PPC_POPCNTB(R3,R3)
+ srdi r4,r3,32
+ add r3,r4,r3
+ srdi r4,r3,16
+ add r3,r4,r3
+ srdi r4,r3,8
+ add r3,r4,r3
+ clrldi r3,r3,64-1
+ blr
+ FTR_SECTION_ELSE_NESTED(52)
+ PPC_POPCNTD(R3,R3)
+ clrldi r3,r3,64-1
+ blr
+ ALT_FTR_SECTION_END_NESTED_IFCLR(CPU_FTR_POPCNTD, 52)
+ALT_FTR_SECTION_END_IFCLR(CPU_FTR_POPCNTB)
diff --git a/arch/powerpc/lib/ppc_ksyms.c b/arch/powerpc/lib/ppc_ksyms.c
index c422812..1ccfc29 100644
--- a/arch/powerpc/lib/ppc_ksyms.c
+++ b/arch/powerpc/lib/ppc_ksyms.c
@@ -30,4 +30,9 @@ EXPORT_SYMBOL(__arch_hweight8);
EXPORT_SYMBOL(__arch_hweight16);
EXPORT_SYMBOL(__arch_hweight32);
EXPORT_SYMBOL(__arch_hweight64);
+
+EXPORT_SYMBOL(__arch_parity8);
+EXPORT_SYMBOL(__arch_parity16);
+EXPORT_SYMBOL(__arch_parity32);
+EXPORT_SYMBOL(__arch_parity64);
#endif
--
2.5.0


2016-04-06 09:08:56

by Zhaoxiu Zeng

[permalink] [raw]
Subject: [PATCH v2 09/30] Add tile-specific parity functions

From: Zhaoxiu Zeng <[email protected]>

Signed-off-by: Zhaoxiu Zeng <[email protected]>
---
arch/tile/include/asm/bitops.h | 26 ++++++++++++++++++++++++++
1 file changed, 26 insertions(+)

diff --git a/arch/tile/include/asm/bitops.h b/arch/tile/include/asm/bitops.h
index 20caa34..370d007 100644
--- a/arch/tile/include/asm/bitops.h
+++ b/arch/tile/include/asm/bitops.h
@@ -81,10 +81,36 @@ static inline unsigned long __arch_hweight64(__u64 w)
return __builtin_popcountll(w);
}

+static inline unsigned int __arch_parity32(unsigned int w)
+{
+ return __builtin_popcount(w) & 1;
+}
+
+static inline unsigned int __arch_parity16(unsigned int w)
+{
+ return __arch_parity32(w & 0xffff);
+}
+
+static inline unsigned int __arch_parity8(unsigned int w)
+{
+ return __arch_parity32(w & 0xff);
+}
+
+static inline unsigned int __arch_parity4(unsigned int w)
+{
+ return __arch_parity32(w & 0xf);
+}
+
+static inline unsigned int __arch_parity64(__u64 w)
+{
+ return (unsigned int)__builtin_popcountll(w) & 1;
+}
+
#include <asm-generic/bitops/builtin-__ffs.h>
#include <asm-generic/bitops/builtin-__fls.h>
#include <asm-generic/bitops/builtin-ffs.h>
#include <asm-generic/bitops/const_hweight.h>
+#include <asm-generic/bitops/const_parity.h>
#include <asm-generic/bitops/lock.h>
#include <asm-generic/bitops/find.h>
#include <asm-generic/bitops/sched.h>
--
2.5.0


2016-04-06 09:09:22

by Zhaoxiu Zeng

[permalink] [raw]
Subject: [PATCH v2 04/30] Add blackfin-specific parity functions

From: Zhaoxiu Zeng <[email protected]>

Signed-off-by: Zhaoxiu Zeng <[email protected]>
---
arch/blackfin/include/asm/bitops.h | 31 +++++++++++++++++++++++++++++++
1 file changed, 31 insertions(+)

diff --git a/arch/blackfin/include/asm/bitops.h b/arch/blackfin/include/asm/bitops.h
index b298b65..6609b7e 100644
--- a/arch/blackfin/include/asm/bitops.h
+++ b/arch/blackfin/include/asm/bitops.h
@@ -23,6 +23,7 @@
#include <asm-generic/bitops/sched.h>
#include <asm-generic/bitops/ffs.h>
#include <asm-generic/bitops/const_hweight.h>
+#include <asm-generic/bitops/const_parity.h>
#include <asm-generic/bitops/lock.h>

#include <asm-generic/bitops/ext2-atomic.h>
@@ -137,4 +138,34 @@ static inline unsigned int __arch_hweight8(unsigned int w)
return __arch_hweight32(w & 0xff);
}

+/*
+ * parityN: returns the parity of a N-bit word,
+ * i.e. the number of 1-bits in w modulo 2.
+ */
+
+static inline unsigned int __arch_parity32(unsigned int w)
+{
+ return __arch_hweight32(w) & 1;
+}
+
+static inline unsigned int __arch_parity64(__u64 w)
+{
+ return __arch_parity32((unsigned int)(w >> 32) ^ (unsigned int)w);
+}
+
+static inline unsigned int __arch_parity16(unsigned int w)
+{
+ return __arch_parity32(w & 0xffff);
+}
+
+static inline unsigned int __arch_parity8(unsigned int w)
+{
+ return __arch_parity32(w & 0xff);
+}
+
+static inline unsigned int __arch_parity4(unsigned int w)
+{
+ return __arch_parity32(w & 0xf);
+}
+
#endif /* _BLACKFIN_BITOPS_H */
--
2.5.0


2016-04-06 09:08:56

by Zhaoxiu Zeng

[permalink] [raw]
Subject: [PATCH v2 08/30] Add sparc-specific parity functions

From: Zhaoxiu Zeng <[email protected]>

Use runtime patching for sparc64, lifted from hweight

Signed-off-by: Zhaoxiu Zeng <[email protected]>
---
arch/sparc/include/asm/bitops_32.h | 1 +
arch/sparc/include/asm/bitops_64.h | 18 ++++++++
arch/sparc/kernel/sparc_ksyms_64.c | 6 +++
arch/sparc/lib/Makefile | 2 +-
arch/sparc/lib/parity.S | 93 ++++++++++++++++++++++++++++++++++++++
5 files changed, 119 insertions(+), 1 deletion(-)
create mode 100644 arch/sparc/lib/parity.S

diff --git a/arch/sparc/include/asm/bitops_32.h b/arch/sparc/include/asm/bitops_32.h
index 600ed1d..8c41896 100644
--- a/arch/sparc/include/asm/bitops_32.h
+++ b/arch/sparc/include/asm/bitops_32.h
@@ -98,6 +98,7 @@ static inline void change_bit(unsigned long nr, volatile unsigned long *addr)
#include <asm-generic/bitops/__fls.h>
#include <asm-generic/bitops/fls64.h>
#include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/parity.h>
#include <asm-generic/bitops/lock.h>
#include <asm-generic/bitops/find.h>
#include <asm-generic/bitops/le.h>
diff --git a/arch/sparc/include/asm/bitops_64.h b/arch/sparc/include/asm/bitops_64.h
index 2d52240..5312fed 100644
--- a/arch/sparc/include/asm/bitops_64.h
+++ b/arch/sparc/include/asm/bitops_64.h
@@ -47,6 +47,24 @@ unsigned int __arch_hweight16(unsigned int w);
unsigned int __arch_hweight8(unsigned int w);

#include <asm-generic/bitops/const_hweight.h>
+
+/*
+ * parityN: returns the parity of a N-bit word,
+ * i.e. the number of 1-bits in w modulo 2.
+ */
+
+static inline unsigned int __arch_parity4(unsigned int w)
+{
+ w &= 0xf;
+ return (0x6996 >> w) & 1;
+}
+unsigned int __arch_parity8(unsigned int w);
+unsigned int __arch_parity16(unsigned int w);
+unsigned int __arch_parity32(unsigned int w);
+unsigned int __arch_parity64(__u64 w);
+
+#include <asm-generic/bitops/const_parity.h>
+
#include <asm-generic/bitops/lock.h>
#endif /* __KERNEL__ */

diff --git a/arch/sparc/kernel/sparc_ksyms_64.c b/arch/sparc/kernel/sparc_ksyms_64.c
index 9e034f2..7ee0818 100644
--- a/arch/sparc/kernel/sparc_ksyms_64.c
+++ b/arch/sparc/kernel/sparc_ksyms_64.c
@@ -45,6 +45,12 @@ EXPORT_SYMBOL(__arch_hweight16);
EXPORT_SYMBOL(__arch_hweight32);
EXPORT_SYMBOL(__arch_hweight64);

+/* from parity.S */
+EXPORT_SYMBOL(__arch_parity8);
+EXPORT_SYMBOL(__arch_parity16);
+EXPORT_SYMBOL(__arch_parity32);
+EXPORT_SYMBOL(__arch_parity64);
+
/* from ffs_ffz.S */
EXPORT_SYMBOL(ffs);
EXPORT_SYMBOL(__ffs);
diff --git a/arch/sparc/lib/Makefile b/arch/sparc/lib/Makefile
index 3269b02..2dbbcb1 100644
--- a/arch/sparc/lib/Makefile
+++ b/arch/sparc/lib/Makefile
@@ -39,7 +39,7 @@ lib-$(CONFIG_SPARC64) += GENmemcpy.o GENcopy_from_user.o GENcopy_to_user.o
lib-$(CONFIG_SPARC64) += GENpatch.o GENpage.o GENbzero.o

lib-$(CONFIG_SPARC64) += copy_in_user.o user_fixup.o memmove.o
-lib-$(CONFIG_SPARC64) += mcount.o ipcsum.o xor.o hweight.o ffs.o
+lib-$(CONFIG_SPARC64) += mcount.o ipcsum.o xor.o hweight.o ffs.o parity.o

obj-$(CONFIG_SPARC64) += iomap.o
obj-$(CONFIG_SPARC32) += atomic32.o ucmpdi2.o
diff --git a/arch/sparc/lib/parity.S b/arch/sparc/lib/parity.S
new file mode 100644
index 0000000..b1945e3
--- /dev/null
+++ b/arch/sparc/lib/parity.S
@@ -0,0 +1,93 @@
+#include <linux/linkage.h>
+
+ .text
+ .align 32
+
+ENTRY(__arch_parity8)
+ srl %o0, 4, %g1
+ xor %o0, %g1, %o0
+ and %o0, 0xf, %o0
+ sethi %hi(0x6996), %g1
+ or %g1, %lo(0x6996), %g1
+ srl %g1, %o0, %o0
+ retl
+ and %o0, 1, %o0
+ENDPROC(__arch_parity8)
+ .section .popc_6insn_patch, "ax"
+ .word __arch_parity8
+ sllx %o0, 64-8, %g1
+ popc %g1, %o0
+ retl
+ and %o0, 1, %o0
+ nop
+ nop
+ .previous
+
+ENTRY(__arch_parity16)
+ srl %o0, 8, %g1
+ xor %o0, %g1, %o0
+ srl %o0, 4, %g1
+ xor %o0, %g1, %o0
+ and %o0, 0xf, %o0
+ sethi %hi(0x6996), %g1
+ or %g1, %lo(0x6996), %g1
+ srl %g1, %o0, %o0
+ retl
+ and %o0, 1, %o0
+ENDPROC(__arch_parity16)
+ .section .popc_6insn_patch, "ax"
+ .word __arch_parity16
+ sllx %o0, 64-16, %g1
+ popc %g1, %o0
+ retl
+ and %o0, 1, %o0
+ nop
+ nop
+ .previous
+
+ENTRY(__arch_parity32)
+ srl %o0, 16, %g1
+ xor %o0, %g1, %o0
+ srl %o0, 8, %g1
+ xor %o0, %g1, %o0
+ srl %o0, 4, %g1
+ xor %o0, %g1, %o0
+ and %o0, 0xf, %o0
+ sethi %hi(0x6996), %g1
+ or %g1, %lo(0x6996), %g1
+ srl %g1, %o0, %o0
+ retl
+ and %o0, 1, %o0
+ENDPROC(__arch_parity32)
+ .section .popc_6insn_patch, "ax"
+ .word __arch_parity32
+ sllx %o0, 64-32, %g1
+ popc %g1, %o0
+ retl
+ and %o0, 1, %o0
+ nop
+ nop
+ .previous
+
+ENTRY(__arch_parity64)
+ srlx %o0, 32, %g1
+ xor %o0, %g1, %o0
+ srl %o0, 16, %g1
+ xor %o0, %g1, %o0
+ srl %o0, 8, %g1
+ xor %o0, %g1, %o0
+ srl %o0, 4, %g1
+ xor %o0, %g1, %o0
+ and %o0, 0xf, %o0
+ sethi %hi(0x6996), %g1
+ or %g1, %lo(0x6996), %g1
+ srl %g1, %o0, %o0
+ retl
+ and %o0, 1, %o0
+ENDPROC(__arch_parity64)
+ .section .popc_3insn_patch, "ax"
+ .word __arch_parity64
+ popc %o0, %o0
+ retl
+ and %o0, 1, %o0
+ .previous
--
2.5.0


2016-04-06 09:21:19

by Zhaoxiu Zeng

[permalink] [raw]
Subject: [PATCH v2 10/30] Add x86-specific parity functions

From: Zhaoxiu Zeng <[email protected]>

Use alternatives, lifted from arch_hweight

Signed-off-by: Zhaoxiu Zeng <[email protected]>
---
arch/x86/include/asm/arch_hweight.h | 5 ++
arch/x86/include/asm/arch_parity.h | 102 ++++++++++++++++++++++++++++++++++++
arch/x86/include/asm/bitops.h | 4 +-
arch/x86/lib/Makefile | 8 +++
arch/x86/lib/parity.c | 32 ++++++++++++
5 files changed, 150 insertions(+), 1 deletion(-)
create mode 100644 arch/x86/include/asm/arch_parity.h
create mode 100644 arch/x86/lib/parity.c

diff --git a/arch/x86/include/asm/arch_hweight.h b/arch/x86/include/asm/arch_hweight.h
index 02e799f..c79d50d 100644
--- a/arch/x86/include/asm/arch_hweight.h
+++ b/arch/x86/include/asm/arch_hweight.h
@@ -63,4 +63,9 @@ static __always_inline unsigned long __arch_hweight64(__u64 w)
}
#endif /* CONFIG_X86_32 */

+#undef POPCNT32
+#undef POPCNT64
+#undef REG_IN
+#undef REG_OUT
+
#endif
diff --git a/arch/x86/include/asm/arch_parity.h b/arch/x86/include/asm/arch_parity.h
new file mode 100644
index 0000000..09463fd
--- /dev/null
+++ b/arch/x86/include/asm/arch_parity.h
@@ -0,0 +1,100 @@
+#ifndef _ASM_X86_PARITY_H
+#define _ASM_X86_PARITY_H
+
+#include <asm/cpufeatures.h>
+
+#ifdef CONFIG_64BIT
+/* popcnt %edi, %eax -- redundant REX prefix for alignment */
+#define POPCNT32 ".byte 0xf3,0x40,0x0f,0xb8,0xc7"
+/* popcnt %rdi, %rax */
+#define POPCNT64 ".byte 0xf3,0x48,0x0f,0xb8,0xc7"
+#define REG_IN "D"
+#define REG_OUT "a"
+#else
+/* popcnt %eax, %eax */
+#define POPCNT32 ".byte 0xf3,0x0f,0xb8,0xc0"
+#define REG_IN "a"
+#define REG_OUT "a"
+#endif
+
+/*
+ * __sw_parityXX are called from within the alternatives below
+ * and callee-clobbered registers need to be taken care of. See
+ * ARCH_HWEIGHT_CFLAGS in <arch/x86/Kconfig> for the respective
+ * compiler switches.
+ */
+unsigned int __sw_parity32(unsigned int w);
+#ifndef CONFIG_X86_32
+unsigned int __sw_parity64(__u64 w);
+#endif
+
+static inline unsigned int __arch_parity4(unsigned int w)
+{
+ unsigned int res = 0;
+
+ asm("test $0xf, %1; setpo %b0"
+ : "+q" (res)
+ : "r" (w)
+ : "cc");
+
+ return res;
+}
+
+static inline unsigned int __arch_parity8(unsigned int w)
+{
+ unsigned int res = 0;
+
+ asm("test %1, %1; setpo %b0"
+ : "+q" (res)
+ : "r" (w)
+ : "cc");
+
+ return res;
+}
+
+static inline unsigned int __arch_parity16(unsigned int w)
+{
+ unsigned int res = 0;
+
+ asm("xor %h1, %b1; setpo %b0"
+ : "+q" (res), "+q" (w)
+ : : "cc");
+
+ return res;
+}
+
+static __always_inline unsigned int __arch_parity32(unsigned int w)
+{
+ unsigned int res;
+
+ asm(ALTERNATIVE("call __sw_parity32", POPCNT32 "; and $1, %0", X86_FEATURE_POPCNT)
+ : "="REG_OUT (res)
+ : REG_IN (w)
+ : "cc");
+
+ return res;
+}
+
+#ifdef CONFIG_X86_32
+static inline unsigned long __arch_parity64(__u64 w)
+{
+ return __arch_parity32((u32)w ^ (u32)(w >> 32));
+}
+#else
+static __always_inline unsigned long __arch_parity64(__u64 w)
+{
+ unsigned long res;
+
+ asm(ALTERNATIVE("call __sw_parity64", POPCNT64 "; and $1, %0", X86_FEATURE_POPCNT)
+ : "="REG_OUT (res)
+ : REG_IN (w)
+ : "cc");
+
+ return res;
+}
+#endif /* CONFIG_X86_32 */
+
+#undef POPCNT32
+#undef POPCNT64
+#undef REG_IN
+#undef REG_OUT
+
+#endif
diff --git a/arch/x86/include/asm/bitops.h b/arch/x86/include/asm/bitops.h
index 7766d1c..f5b0122 100644
--- a/arch/x86/include/asm/bitops.h
+++ b/arch/x86/include/asm/bitops.h
@@ -498,9 +498,11 @@ static __always_inline int fls64(__u64 x)
#include <asm-generic/bitops/sched.h>

#include <asm/arch_hweight.h>
-
#include <asm-generic/bitops/const_hweight.h>

+#include <asm/arch_parity.h>
+#include <asm-generic/bitops/const_parity.h>
+
#include <asm-generic/bitops/le.h>

#include <asm-generic/bitops/ext2-atomic-setbit.h>
diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile
index 72a5767..5716295 100644
--- a/arch/x86/lib/Makefile
+++ b/arch/x86/lib/Makefile
@@ -4,6 +4,9 @@

# Produces uninteresting flaky coverage.
KCOV_INSTRUMENT_delay.o := n
+# Kernel does not boot if we instrument this file as it uses custom calling
+# convention (see CONFIG_ARCH_HWEIGHT_CFLAGS).
+KCOV_INSTRUMENT_parity.o := n

inat_tables_script = $(srctree)/arch/x86/tools/gen-insn-attr-x86.awk
inat_tables_maps = $(srctree)/arch/x86/lib/x86-opcode-map.txt
@@ -45,3 +48,8 @@ else
lib-y += copy_user_64.o
lib-y += cmpxchg16b_emu.o
endif
+
+GCOV_PROFILE_parity.o := n
+CFLAGS_parity.o = $(subst $(quote),,$(CONFIG_ARCH_HWEIGHT_CFLAGS))
+obj-y += parity.o
+
diff --git a/arch/x86/lib/parity.c b/arch/x86/lib/parity.c
new file mode 100644
index 0000000..762117b
--- /dev/null
+++ b/arch/x86/lib/parity.c
@@ -0,0 +1,32 @@
+#include <linux/export.h>
+#include <linux/bitops.h>
+
+unsigned int __sw_parity32(unsigned int w)
+{
+ unsigned int res;
+ w ^= w >> 16;
+ asm("xor %%ah, %%al \n"
+ "mov $0, %%eax \n"
+ "setpo %%al \n"
+ : "=a" (res)
+ : "a" (w)
+ : "cc");
+ return res;
+}
+EXPORT_SYMBOL(__sw_parity32);
+
+#ifndef CONFIG_X86_32
+unsigned int __sw_parity64(__u64 w)
+{
+ unsigned int res = (unsigned int)w ^ (unsigned int)(w >> 32);
+ res ^= res >> 16;
+ asm("xor %%ah, %%al \n"
+ "mov $0, %%eax \n"
+ "setpo %%al \n"
+ : "=a" (res)
+ : "a" (res)
+ : "cc");
+ return res;
+}
+EXPORT_SYMBOL(__sw_parity64);
+#endif
--
2.5.0


2016-04-06 09:30:21

by Zhaoxiu Zeng

[permalink] [raw]
Subject: [PATCH v2 11/30] sunrpc: use parity8

From: Zhaoxiu Zeng <[email protected]>

Signed-off-by: Zhaoxiu Zeng <[email protected]>
---
net/sunrpc/auth_gss/gss_krb5_keys.c | 6 +-----
1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/net/sunrpc/auth_gss/gss_krb5_keys.c b/net/sunrpc/auth_gss/gss_krb5_keys.c
index 8701331..c41b389 100644
--- a/net/sunrpc/auth_gss/gss_krb5_keys.c
+++ b/net/sunrpc/auth_gss/gss_krb5_keys.c
@@ -243,16 +243,12 @@ err_return:
return ret;
}

-#define smask(step) ((1<<step)-1)
-#define pstep(x, step) (((x)&smask(step))^(((x)>>step)&smask(step)))
-#define parity_char(x) pstep(pstep(pstep((x), 4), 2), 1)
-
static void mit_des_fixup_key_parity(u8 key[8])
{
int i;
for (i = 0; i < 8; i++) {
key[i] &= 0xfe;
- key[i] |= 1^parity_char(key[i]);
+ key[i] |= !parity8(key[i]);
}
}

--
2.5.0


2016-04-06 09:31:14

by Zhaoxiu Zeng

[permalink] [raw]
Subject: [PATCH v2 12/30] mips: use parity functions in cerr-sb1.c

From: Zhaoxiu Zeng <[email protected]>

Signed-off-by: Zhaoxiu Zeng <[email protected]>
---
arch/mips/mm/cerr-sb1.c | 67 +++++++++++++------------------------------------
1 file changed, 17 insertions(+), 50 deletions(-)

diff --git a/arch/mips/mm/cerr-sb1.c b/arch/mips/mm/cerr-sb1.c
index ee5c1ff..2e7d660 100644
--- a/arch/mips/mm/cerr-sb1.c
+++ b/arch/mips/mm/cerr-sb1.c
@@ -264,27 +264,6 @@ asmlinkage void sb1_cache_error(void)
#endif
}

-
-/* Parity lookup table. */
-static const uint8_t parity[256] = {
- 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
- 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
- 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
- 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
- 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
- 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
- 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
- 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
- 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
- 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
- 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
- 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
- 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
- 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
- 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
- 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0
-};
-
/* Masks to select bits for Hamming parity, mask_72_64[i] for bit[i] */
static const uint64_t mask_72_64[8] = {
0x0738C808099264FFULL,
@@ -298,34 +277,28 @@ static const uint64_t mask_72_64[8] = {
};

/* Calculate the parity on a range of bits */
-static char range_parity(uint64_t dword, int max, int min)
+static inline char range_parity(uint64_t dword, int max, int min)
{
- char parity = 0;
- int i;
- dword >>= min;
- for (i=max-min; i>=0; i--) {
- if (dword & 0x1)
- parity = !parity;
- dword >>= 1;
+ int n = max - min + 1;
+ if (__builtin_constant_p(n)) {
+ if (n <= 8)
+ return parity8((unsigned int)(dword >> min) & ((1U << n) - 1));
+ if (n <= 16)
+ return parity16((unsigned int)(dword >> min) & ((1U << n) - 1));
+ if (n <= 32)
+ return parity32((unsigned int)(dword >> min) & ((1U << n) - 1));
}
- return parity;
+ return parity64((dword >> min) & ((1ULL << n) - 1));
}

/* Calculate the 4-bit even byte-parity for an instruction */
-static unsigned char inst_parity(uint32_t word)
+static inline unsigned char inst_parity(uint32_t word)
{
- int i, j;
- char parity = 0;
- for (j=0; j<4; j++) {
- char byte_parity = 0;
- for (i=0; i<8; i++) {
- if (word & 0x80000000)
- byte_parity = !byte_parity;
- word <<= 1;
- }
- parity <<= 1;
- parity |= byte_parity;
- }
+ char parity;
+ parity = parity8(word >> 24) << 3;
+ parity |= parity8(word >> 16) << 2;
+ parity |= parity8(word >> 8) << 1;
+ parity |= parity8(word);
return parity;
}

@@ -436,7 +409,6 @@ static uint32_t extract_ic(unsigned short addr, int data)
static uint8_t dc_ecc(uint64_t dword)
{
uint64_t t;
- uint32_t w;
uint8_t p;
int i;

@@ -445,12 +417,7 @@ static uint8_t dc_ecc(uint64_t dword)
{
p <<= 1;
t = dword & mask_72_64[i];
- w = (uint32_t)(t >> 32);
- p ^= (parity[w>>24] ^ parity[(w>>16) & 0xFF]
- ^ parity[(w>>8) & 0xFF] ^ parity[w & 0xFF]);
- w = (uint32_t)(t & 0xFFFFFFFF);
- p ^= (parity[w>>24] ^ parity[(w>>16) & 0xFF]
- ^ parity[(w>>8) & 0xFF] ^ parity[w & 0xFF]);
+ p |= parity64(t);
}
return p;
}
--
2.5.0


2016-04-06 09:37:20

by Zhaoxiu Zeng

[permalink] [raw]
Subject: [PATCH v2 13/30] bch: use parity32

From: Zhaoxiu Zeng <[email protected]>

Signed-off-by: Zhaoxiu Zeng <[email protected]>
---
lib/bch.c | 14 +-------------
1 file changed, 1 insertion(+), 13 deletions(-)

diff --git a/lib/bch.c b/lib/bch.c
index bc89dfe4..6c6e8d4 100644
--- a/lib/bch.c
+++ b/lib/bch.c
@@ -278,18 +278,6 @@ static inline int deg(unsigned int poly)
return fls(poly)-1;
}

-static inline int parity(unsigned int x)
-{
- /*
- * public domain code snippet, lifted from
- * http://www-graphics.stanford.edu/~seander/bithacks.html
- */
- x ^= x >> 1;
- x ^= x >> 2;
- x = (x & 0x11111111U) * 0x11111111U;
- return (x >> 28) & 1;
-}
-
/* Galois field basic operations: multiply, divide, inverse, etc. */

static inline unsigned int gf_mul(struct bch_control *bch, unsigned int a,
@@ -494,7 +482,7 @@ static int solve_linear_system(struct bch_control *bch, unsigned int *rows,
tmp = 0;
for (r = m-1; r >= 0; r--) {
mask = rows[r] & (tmp|1);
- tmp |= parity(mask) << (m-r);
+ tmp |= parity32(mask) << (m-r);
}
sol[p] = tmp >> 1;
}
--
2.5.0


2016-04-06 09:39:44

by Zhaoxiu Zeng

[permalink] [raw]
Subject: [PATCH v2 14/30] media: use parity8 in vivid-vbi-gen.c

From: Zhaoxiu Zeng <[email protected]>

Signed-off-by: Zhaoxiu Zeng <[email protected]>
---
drivers/media/platform/vivid/vivid-vbi-gen.c | 9 ++-------
1 file changed, 2 insertions(+), 7 deletions(-)

diff --git a/drivers/media/platform/vivid/vivid-vbi-gen.c b/drivers/media/platform/vivid/vivid-vbi-gen.c
index a2159de..d5ba0fc 100644
--- a/drivers/media/platform/vivid/vivid-vbi-gen.c
+++ b/drivers/media/platform/vivid/vivid-vbi-gen.c
@@ -175,14 +175,9 @@ static const u8 vivid_cc_sequence2[30] = {
0x14, 0x2f, /* End of Caption */
};

-static u8 calc_parity(u8 val)
+static inline u8 calc_parity(u8 val)
{
- unsigned i;
- unsigned tot = 0;
-
- for (i = 0; i < 7; i++)
- tot += (val & (1 << i)) ? 1 : 0;
- return val | ((tot & 1) ? 0 : 0x80);
+ return (!parity8(val) << 7) | val;
}

static void vivid_vbi_gen_set_time_of_day(u8 *packet)
--
2.5.0


2016-04-06 09:41:51

by Zhaoxiu Zeng

[permalink] [raw]
Subject: [PATCH v2 15/30] media: use parity functions in saa7115

From: Zhaoxiu Zeng <[email protected]>

Signed-off-by: Zhaoxiu Zeng <[email protected]>
---
drivers/media/i2c/saa7115.c | 17 ++---------------
1 file changed, 2 insertions(+), 15 deletions(-)

diff --git a/drivers/media/i2c/saa7115.c b/drivers/media/i2c/saa7115.c
index d2a1ce2..4c22df8 100644
--- a/drivers/media/i2c/saa7115.c
+++ b/drivers/media/i2c/saa7115.c
@@ -672,15 +672,6 @@ static const unsigned char saa7115_init_misc[] = {
0x00, 0x00
};

-static int saa711x_odd_parity(u8 c)
-{
- c ^= (c >> 4);
- c ^= (c >> 2);
- c ^= (c >> 1);
-
- return c & 1;
-}
-
static int saa711x_decode_vps(u8 *dst, u8 *p)
{
static const u8 biphase_tbl[] = {
@@ -733,7 +724,6 @@ static int saa711x_decode_wss(u8 *p)
static const int wss_bits[8] = {
0, 0, 0, 1, 0, 1, 1, 1
};
- unsigned char parity;
int wss = 0;
int i;

@@ -745,11 +735,8 @@ static int saa711x_decode_wss(u8 *p)
return -1;
wss |= b2 << i;
}
- parity = wss & 15;
- parity ^= parity >> 2;
- parity ^= parity >> 1;

- if (!(parity & 1))
+ if (!parity4(wss))
return -1;

return wss;
@@ -1235,7 +1222,7 @@ static int saa711x_decode_vbi_line(struct v4l2_subdev *sd, struct v4l2_decode_vb
vbi->type = V4L2_SLICED_TELETEXT_B;
break;
case 4:
- if (!saa711x_odd_parity(p[0]) || !saa711x_odd_parity(p[1]))
+ if (!parity8(p[0]) || !parity8(p[1]))
return 0;
vbi->type = V4L2_SLICED_CAPTION_525;
break;
--
2.5.0


2016-04-06 09:43:40

by Zhaoxiu Zeng

[permalink] [raw]
Subject: [PATCH v2 16/30] input: use parity32 in grip_mp

From: Zhaoxiu Zeng <[email protected]>

Signed-off-by: Zhaoxiu Zeng <[email protected]>
---
drivers/input/joystick/grip_mp.c | 16 +---------------
1 file changed, 1 insertion(+), 15 deletions(-)

diff --git a/drivers/input/joystick/grip_mp.c b/drivers/input/joystick/grip_mp.c
index 573191d..3e29eb1 100644
--- a/drivers/input/joystick/grip_mp.c
+++ b/drivers/input/joystick/grip_mp.c
@@ -112,20 +112,6 @@ static const int axis_map[] = { 5, 9, 1, 5, 6, 10, 2, 6, 4, 8, 0, 4, 5, 9, 1, 5
static int register_slot(int i, struct grip_mp *grip);

/*
- * Returns whether an odd or even number of bits are on in pkt.
- */
-
-static int bit_parity(u32 pkt)
-{
- int x = pkt ^ (pkt >> 16);
- x ^= x >> 8;
- x ^= x >> 4;
- x ^= x >> 2;
- x ^= x >> 1;
- return x & 1;
-}
-
-/*
* Poll gameport; return true if all bits set in 'onbits' are on and
* all bits set in 'offbits' are off.
*/
@@ -235,7 +221,7 @@ static int mp_io(struct gameport* gameport, int sendflags, int sendcode, u32 *pa
pkt = (pkt >> 2) | 0xf0000000;
}

- if (bit_parity(pkt) == 1)
+ if (parity32(pkt))
return IO_RESET;

/* Acknowledge packet receipt */
--
2.5.0


2016-04-06 09:44:47

by Zhaoxiu Zeng

[permalink] [raw]
Subject: [PATCH v2 17/30] input: use parity64 in sidewinder

From: Zhaoxiu Zeng <[email protected]>

Signed-off-by: Zhaoxiu Zeng <[email protected]>
---
drivers/input/joystick/sidewinder.c | 24 ++++--------------------
1 file changed, 4 insertions(+), 20 deletions(-)

diff --git a/drivers/input/joystick/sidewinder.c b/drivers/input/joystick/sidewinder.c
index 4a95b22..7ea486e 100644
--- a/drivers/input/joystick/sidewinder.c
+++ b/drivers/input/joystick/sidewinder.c
@@ -259,22 +259,6 @@ static void sw_init_digital(struct gameport *gameport)
}

/*
- * sw_parity() computes parity of __u64
- */
-
-static int sw_parity(__u64 t)
-{
- int x = t ^ (t >> 32);
-
- x ^= x >> 16;
- x ^= x >> 8;
- x ^= x >> 4;
- x ^= x >> 2;
- x ^= x >> 1;
- return x & 1;
-}
-
-/*
* sw_ccheck() checks synchronization bits and computes checksum of nibbles.
*/

@@ -334,7 +318,7 @@ static int sw_parse(unsigned char *buf, struct sw *sw)

for (i = 0; i < sw->number; i ++) {

- if (sw_parity(GB(i*15,15)))
+ if (parity64(GB(i*15,15)))
return -1;

input_report_abs(sw->dev[i], ABS_X, GB(i*15+3,1) - GB(i*15+2,1));
@@ -351,7 +335,7 @@ static int sw_parse(unsigned char *buf, struct sw *sw)
case SW_ID_PP:
case SW_ID_FFP:

- if (!sw_parity(GB(0,48)) || (hat = GB(42,4)) > 8)
+ if (!parity64(GB(0,48)) || (hat = GB(42,4)) > 8)
return -1;

dev = sw->dev[0];
@@ -372,7 +356,7 @@ static int sw_parse(unsigned char *buf, struct sw *sw)

case SW_ID_FSP:

- if (!sw_parity(GB(0,43)) || (hat = GB(28,4)) > 8)
+ if (!parity64(GB(0,43)) || (hat = GB(28,4)) > 8)
return -1;

dev = sw->dev[0];
@@ -397,7 +381,7 @@ static int sw_parse(unsigned char *buf, struct sw *sw)

case SW_ID_FFW:

- if (!sw_parity(GB(0,33)))
+ if (!parity64(GB(0,33)))
return -1;

dev = sw->dev[0];
--
2.5.0


2016-04-06 09:45:46

by Zhaoxiu Zeng

[permalink] [raw]
Subject: [PATCH v2 18/30] input: use parity16 in ams_delta_serio

From: Zhaoxiu Zeng <[email protected]>

Signed-off-by: Zhaoxiu Zeng <[email protected]>
---
drivers/input/serio/ams_delta_serio.c | 8 ++------
1 file changed, 2 insertions(+), 6 deletions(-)

diff --git a/drivers/input/serio/ams_delta_serio.c b/drivers/input/serio/ams_delta_serio.c
index 45887e3..85459b3 100644
--- a/drivers/input/serio/ams_delta_serio.c
+++ b/drivers/input/serio/ams_delta_serio.c
@@ -48,13 +48,9 @@ static int check_data(int data)
data);
return SERIO_FRAME;
}
- /* calculate the parity */
- for (i = 1; i < 10; i++) {
- if (data & (1 << i))
- parity++;
- }
/* it should be odd */
- if (!(parity & 0x01)) {
+ parity = parity16(data & 0x3fe);
+ if (!parity) {
dev_warn(&ams_delta_serio->dev,
"paritiy check failed, data=0x%X parity=0x%X\n",
data, parity);
--
2.5.0


2016-04-06 09:48:18

by Zhaoxiu Zeng

[permalink] [raw]
Subject: [PATCH v2 19/30] scsi: use parity32 in isci's phy

From: Zhaoxiu Zeng <[email protected]>

Signed-off-by: Zhaoxiu Zeng <[email protected]>
---
drivers/scsi/isci/phy.c | 15 +--------------
1 file changed, 1 insertion(+), 14 deletions(-)

diff --git a/drivers/scsi/isci/phy.c b/drivers/scsi/isci/phy.c
index cb87b2e..a06aff6 100644
--- a/drivers/scsi/isci/phy.c
+++ b/drivers/scsi/isci/phy.c
@@ -122,8 +122,6 @@ sci_phy_link_layer_initialization(struct isci_phy *iphy,
int phy_idx = iphy->phy_index;
struct sci_phy_cap phy_cap;
u32 phy_configuration;
- u32 parity_check = 0;
- u32 parity_count = 0;
u32 llctl, link_rate;
u32 clksm_value = 0;
u32 sp_timeouts = 0;
@@ -225,18 +223,7 @@ sci_phy_link_layer_initialization(struct isci_phy *iphy,
/* The SAS specification indicates that the phy_capabilities that
* are transmitted shall have an even parity. Calculate the parity.
*/
- parity_check = phy_cap.all;
- while (parity_check != 0) {
- if (parity_check & 0x1)
- parity_count++;
- parity_check >>= 1;
- }
-
- /* If parity indicates there are an odd number of bits set, then
- * set the parity bit to 1 in the phy capabilities.
- */
- if ((parity_count % 2) != 0)
- phy_cap.parity = 1;
+ phy_cap.parity = parity32(phy_cap.all);

writel(phy_cap.all, &llr->phy_capabilities);

--
2.5.0


2016-04-06 09:53:48

by Zhaoxiu Zeng

[permalink] [raw]
Subject: [PATCH v2 20/30] mtd: use parity16 in ssfdc

From: Zhaoxiu Zeng <[email protected]>

The original get_parity return even parity of the input number. So
hweight of "block_address & 0x7ff" must be odd if block_address is valid.

This patch use parity16, and rearrange the code.

Signed-off-by: Zhaoxiu Zeng <[email protected]>
---
drivers/mtd/ssfdc.c | 31 ++++++++-----------------------
1 file changed, 8 insertions(+), 23 deletions(-)

diff --git a/drivers/mtd/ssfdc.c b/drivers/mtd/ssfdc.c
index daf82ba..1d55f15 100644
--- a/drivers/mtd/ssfdc.c
+++ b/drivers/mtd/ssfdc.c
@@ -182,24 +182,10 @@ static int read_raw_oob(struct mtd_info *mtd, loff_t offs, uint8_t *buf)
return 0;
}

-/* Parity calculator on a word of n bit size */
-static int get_parity(int number, int size)
-{
- int k;
- int parity;
-
- parity = 1;
- for (k = 0; k < size; k++) {
- parity += (number >> k);
- parity &= 1;
- }
- return parity;
-}
-
/* Read and validate the logical block address field stored in the OOB */
static int get_logical_address(uint8_t *oob_buf)
{
- int block_address, parity;
+ int block_address;
int offset[2] = {6, 11}; /* offset of the 2 address fields within OOB */
int j;
int ok = 0;
@@ -215,18 +201,17 @@ static int get_logical_address(uint8_t *oob_buf)

/* Check for the signature bits in the address field (MSBits) */
if ((block_address & ~0x7FF) == 0x1000) {
- parity = block_address & 0x01;
block_address &= 0x7FF;
- block_address >>= 1;

- if (get_parity(block_address, 10) != parity) {
- pr_debug("SSFDC_RO: logical address field%d"
- "parity error(0x%04X)\n", j+1,
- block_address);
- } else {
- ok = 1;
+ ok = parity16(block_address);
+ if (ok) {
+ block_address >>= 1;
break;
}
+
+ pr_debug("SSFDC_RO: logical address field%d"
+ "parity error(0x%04X)\n", j+1,
+ block_address);
}
}

--
2.5.0


2016-04-06 09:55:03

by Zhaoxiu Zeng

[permalink] [raw]
Subject: [PATCH v2 21/30] mtd: use parity functions in inftlcore

From: Zhaoxiu Zeng <[email protected]>

Signed-off-by: Zhaoxiu Zeng <[email protected]>
---
drivers/mtd/inftlcore.c | 17 ++++-------------
1 file changed, 4 insertions(+), 13 deletions(-)

diff --git a/drivers/mtd/inftlcore.c b/drivers/mtd/inftlcore.c
index b66b541..8c9457b 100644
--- a/drivers/mtd/inftlcore.c
+++ b/drivers/mtd/inftlcore.c
@@ -457,15 +457,6 @@ static u16 INFTL_makefreeblock(struct INFTLrecord *inftl, unsigned pendingblock)
return INFTL_foldchain(inftl, LongestChain, pendingblock);
}

-static int nrbits(unsigned int val, int bitcount)
-{
- int i, total = 0;
-
- for (i = 0; (i < bitcount); i++)
- total += (((0x1 << i) & val) ? 1 : 0);
- return total;
-}
-
/*
* INFTL_findwriteunit: Return the unit number into which we can write
* for this block. Make it available if it isn't already.
@@ -593,10 +584,10 @@ hitused:
if (prev_block < inftl->nb_blocks)
prev_block -= inftl->firstEUN;

- parity = (nrbits(thisVUC, 16) & 0x1) ? 0x1 : 0;
- parity |= (nrbits(prev_block, 16) & 0x1) ? 0x2 : 0;
- parity |= (nrbits(anac, 8) & 0x1) ? 0x4 : 0;
- parity |= (nrbits(nacs, 8) & 0x1) ? 0x8 : 0;
+ parity = parity16(thisVUC);
+ parity |= parity16(prev_block) << 1;
+ parity |= parity8(anac) << 2;
+ parity |= parity8(nacs) << 3;

oob.u.a.virtualUnitNo = cpu_to_le16(thisVUC);
oob.u.a.prevUnitNo = cpu_to_le16(prev_block);
--
2.5.0


2016-04-06 09:59:25

by Zhaoxiu Zeng

[permalink] [raw]
Subject: [PATCH v2 22/30] crypto: use parity functions in qat_hal

From: Zhaoxiu Zeng <[email protected]>

Signed-off-by: Zhaoxiu Zeng <[email protected]>
---
drivers/crypto/qat/qat_common/qat_hal.c | 32 ++++++++++----------------------
1 file changed, 10 insertions(+), 22 deletions(-)

diff --git a/drivers/crypto/qat/qat_common/qat_hal.c b/drivers/crypto/qat/qat_common/qat_hal.c
index 1e480f1..318558f 100644
--- a/drivers/crypto/qat/qat_common/qat_hal.c
+++ b/drivers/crypto/qat/qat_common/qat_hal.c
@@ -546,17 +546,6 @@ static void qat_hal_disable_ctx(struct icp_qat_fw_loader_handle *handle,
qat_hal_wr_ae_csr(handle, ae, CTX_ENABLES, ctx);
}

-static uint64_t qat_hal_parity_64bit(uint64_t word)
-{
- word ^= word >> 1;
- word ^= word >> 2;
- word ^= word >> 4;
- word ^= word >> 8;
- word ^= word >> 16;
- word ^= word >> 32;
- return word & 1;
-}
-
static uint64_t qat_hal_set_uword_ecc(uint64_t uword)
{
uint64_t bit0_mask = 0xff800007fffULL, bit1_mask = 0x1f801ff801fULL,
@@ -566,13 +555,13 @@ static uint64_t qat_hal_set_uword_ecc(uint64_t uword)

/* clear the ecc bits */
uword &= ~(0x7fULL << 0x2C);
- uword |= qat_hal_parity_64bit(bit0_mask & uword) << 0x2C;
- uword |= qat_hal_parity_64bit(bit1_mask & uword) << 0x2D;
- uword |= qat_hal_parity_64bit(bit2_mask & uword) << 0x2E;
- uword |= qat_hal_parity_64bit(bit3_mask & uword) << 0x2F;
- uword |= qat_hal_parity_64bit(bit4_mask & uword) << 0x30;
- uword |= qat_hal_parity_64bit(bit5_mask & uword) << 0x31;
- uword |= qat_hal_parity_64bit(bit6_mask & uword) << 0x32;
+ uword |= (uint64_t)parity64(bit0_mask & uword) << 0x2C;
+ uword |= (uint64_t)parity64(bit1_mask & uword) << 0x2D;
+ uword |= (uint64_t)parity64(bit2_mask & uword) << 0x2E;
+ uword |= (uint64_t)parity64(bit3_mask & uword) << 0x2F;
+ uword |= (uint64_t)parity64(bit4_mask & uword) << 0x30;
+ uword |= (uint64_t)parity64(bit5_mask & uword) << 0x31;
+ uword |= (uint64_t)parity64(bit6_mask & uword) << 0x32;
return uword;
}

@@ -853,15 +842,14 @@ void qat_hal_wr_umem(struct icp_qat_fw_loader_handle *handle,
uaddr |= UA_ECS;
qat_hal_wr_ae_csr(handle, ae, USTORE_ADDRESS, uaddr);
for (i = 0; i < words_num; i++) {
- unsigned int uwrd_lo, uwrd_hi, tmp;
+ unsigned int uwrd_lo, uwrd_hi;

uwrd_lo = ((data[i] & 0xfff0000) << 4) | (0x3 << 18) |
((data[i] & 0xff00) << 2) |
(0x3 << 8) | (data[i] & 0xff);
uwrd_hi = (0xf << 4) | ((data[i] & 0xf0000000) >> 28);
- uwrd_hi |= (hweight32(data[i] & 0xffff) & 0x1) << 8;
- tmp = ((data[i] >> 0x10) & 0xffff);
- uwrd_hi |= (hweight32(tmp) & 0x1) << 9;
+ uwrd_hi |= parity16(data[i]) << 8;
+ uwrd_hi |= parity16(data[i] >> 16) << 9;
qat_hal_wr_ae_csr(handle, ae, USTORE_DATA_LOWER, uwrd_lo);
qat_hal_wr_ae_csr(handle, ae, USTORE_DATA_UPPER, uwrd_hi);
}
--
2.5.0


2016-04-06 10:06:59

by Zhaoxiu Zeng

[permalink] [raw]
Subject: [PATCH v2 23/30] mtd: use parity16 in sm_ftl

From: Zhaoxiu Zeng <[email protected]>

Signed-off-by: Zhaoxiu Zeng <[email protected]>
---
drivers/mtd/sm_ftl.c | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/mtd/sm_ftl.c b/drivers/mtd/sm_ftl.c
index b096f8b..345ff1a 100644
--- a/drivers/mtd/sm_ftl.c
+++ b/drivers/mtd/sm_ftl.c
@@ -136,7 +136,7 @@ static int sm_get_lba(uint8_t *lba)
return -2;

/* check parity - endianness doesn't matter */
- if (hweight16(*(uint16_t *)lba) & 1)
+ if (parity16(*(uint16_t *)lba))
return -2;

return (lba[1] >> 1) | ((lba[0] & 0x07) << 7);
@@ -183,8 +183,7 @@ static void sm_write_lba(struct sm_oob *oob, uint16_t lba)
tmp[0] = 0x10 | ((lba >> 7) & 0x07);
tmp[1] = (lba << 1) & 0xFF;

- if (hweight16(*(uint16_t *)tmp) & 0x01)
- tmp[1] |= 1;
+ tmp[1] |= parity16(*(uint16_t *)tmp);

oob->lba_copy1[0] = oob->lba_copy2[0] = tmp[0];
oob->lba_copy1[1] = oob->lba_copy2[1] = tmp[1];
--
2.5.0


2016-04-06 10:13:07

by Borislav Petkov

[permalink] [raw]
Subject: Re: [PATCH v2 10/30] Add x86-specific parity functions

On Wed, Apr 06, 2016 at 05:14:45PM +0800, [email protected] wrote:
> From: Zhaoxiu Zeng <[email protected]>
>
> Use alternatives, lifted from arch_hweight
>
> Signed-off-by: Zhaoxiu Zeng <[email protected]>
> ---
> arch/x86/include/asm/arch_hweight.h | 5 ++
> arch/x86/include/asm/arch_parity.h | 102 ++++++++++++++++++++++++++++++++++++
> arch/x86/include/asm/bitops.h | 4 +-
> arch/x86/lib/Makefile | 8 +++
> arch/x86/lib/parity.c | 32 ++++++++++++
> 5 files changed, 150 insertions(+), 1 deletion(-)
> create mode 100644 arch/x86/include/asm/arch_parity.h
> create mode 100644 arch/x86/lib/parity.c

...

> +static __always_inline unsigned int __arch_parity32(unsigned int w)
> +{
> + unsigned int res;
> +
> + asm(ALTERNATIVE("call __sw_parity32", POPCNT32 "; and $1, %0", X86_FEATURE_POPCNT)
> + : "="REG_OUT (res)
> + : REG_IN (w)
> + : "cc");

So why all that churn instead of simply doing:

static __always_inline unsigned int __arch_parity32(unsigned int w)
{
return hweight32(w) & 1;
}

Ditto for the 64-bit version.

--
Regards/Gruss,
Boris.

SUSE Linux GmbH, GF: Felix Imendörffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nürnberg)
--

2016-04-06 10:13:38

by Zhaoxiu Zeng

[permalink] [raw]
Subject: [PATCH v2 24/30] ethernet: use parity8 in sun/niu.c

From: Zhaoxiu Zeng <[email protected]>

Signed-off-by: Zhaoxiu Zeng <[email protected]>
---
drivers/net/ethernet/sun/niu.c | 10 ++--------
1 file changed, 2 insertions(+), 8 deletions(-)

diff --git a/drivers/net/ethernet/sun/niu.c b/drivers/net/ethernet/sun/niu.c
index 9cc4564..8c344ef 100644
--- a/drivers/net/ethernet/sun/niu.c
+++ b/drivers/net/ethernet/sun/niu.c
@@ -2742,18 +2742,12 @@ static int niu_set_alt_mac_rdc_table(struct niu *np, int idx,

static u64 vlan_entry_set_parity(u64 reg_val)
{
- u64 port01_mask;
- u64 port23_mask;
-
- port01_mask = 0x00ff;
- port23_mask = 0xff00;
-
- if (hweight64(reg_val & port01_mask) & 1)
+ if (parity8(reg_val))
reg_val |= ENET_VLAN_TBL_PARITY0;
else
reg_val &= ~ENET_VLAN_TBL_PARITY0;

- if (hweight64(reg_val & port23_mask) & 1)
+ if (parity8((unsigned int)reg_val >> 8))
reg_val |= ENET_VLAN_TBL_PARITY1;
else
reg_val &= ~ENET_VLAN_TBL_PARITY1;
--
2.5.0


2016-04-06 10:14:50

by Zhaoxiu Zeng

[permalink] [raw]
Subject: [PATCH v2 25/30] input: use parity8 in pcips2

From: Zhaoxiu Zeng <[email protected]>

Signed-off-by: Zhaoxiu Zeng <[email protected]>
---
drivers/input/serio/pcips2.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/input/serio/pcips2.c b/drivers/input/serio/pcips2.c
index e862c6e..a51e7f0 100644
--- a/drivers/input/serio/pcips2.c
+++ b/drivers/input/serio/pcips2.c
@@ -77,7 +77,7 @@ static irqreturn_t pcips2_interrupt(int irq, void *devid)

flag = (status & PS2_STAT_PARITY) ? 0 : SERIO_PARITY;

- if (hweight8(scancode) & 1)
+ if (parity8(scancode))
flag ^= SERIO_PARITY;

serio_interrupt(ps2if->io, scancode, flag);
--
2.5.0


2016-04-06 10:15:36

by Zhaoxiu Zeng

[permalink] [raw]
Subject: [PATCH v2 26/30] input: use parity8 in sa1111ps2

From: Zhaoxiu Zeng <[email protected]>

Signed-off-by: Zhaoxiu Zeng <[email protected]>
---
drivers/input/serio/sa1111ps2.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/input/serio/sa1111ps2.c b/drivers/input/serio/sa1111ps2.c
index b3e6889..324b193 100644
--- a/drivers/input/serio/sa1111ps2.c
+++ b/drivers/input/serio/sa1111ps2.c
@@ -74,7 +74,7 @@ static irqreturn_t ps2_rxint(int irq, void *dev_id)

scancode = sa1111_readl(ps2if->base + PS2DATA) & 0xff;

- if (hweight8(scancode) & 1)
+ if (parity8(scancode))
flag ^= SERIO_PARITY;

serio_interrupt(ps2if->io, scancode, flag);
--
2.5.0


2016-04-06 10:18:37

by Zhaoxiu Zeng

[permalink] [raw]
Subject: [PATCH v2 27/30] iio: use parity32 in adxrs450

From: Zhaoxiu Zeng <[email protected]>

Signed-off-by: Zhaoxiu Zeng <[email protected]>
---
drivers/iio/gyro/adxrs450.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/iio/gyro/adxrs450.c b/drivers/iio/gyro/adxrs450.c
index a330d42..307f55b 100644
--- a/drivers/iio/gyro/adxrs450.c
+++ b/drivers/iio/gyro/adxrs450.c
@@ -109,7 +109,7 @@ static int adxrs450_spi_read_reg_16(struct iio_dev *indio_dev,
mutex_lock(&st->buf_lock);
tx = ADXRS450_READ_DATA | (reg_address << 17);

- if (!(hweight32(tx) & 1))
+ if (!parity32(tx))
tx |= ADXRS450_P;

st->tx = cpu_to_be32(tx);
@@ -145,7 +145,7 @@ static int adxrs450_spi_write_reg_16(struct iio_dev *indio_dev,
mutex_lock(&st->buf_lock);
tx = ADXRS450_WRITE_DATA | (reg_address << 17) | (val << 1);

- if (!(hweight32(tx) & 1))
+ if (!parity32(tx))
tx |= ADXRS450_P;

st->tx = cpu_to_be32(tx);
--
2.5.0


2016-04-06 10:20:28

by Zhaoxiu Zeng

[permalink] [raw]
Subject: [PATCH v2 28/30] serial: use parity32 in max3100

From: Zhaoxiu Zeng <[email protected]>

Signed-off-by: Zhaoxiu Zeng <[email protected]>
---
drivers/tty/serial/max3100.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/tty/serial/max3100.c b/drivers/tty/serial/max3100.c
index 5c4c280..a0cc84a 100644
--- a/drivers/tty/serial/max3100.c
+++ b/drivers/tty/serial/max3100.c
@@ -155,7 +155,7 @@ static int max3100_do_parity(struct max3100_port *s, u16 c)
else
c &= 0xff;

- parity = parity ^ (hweight8(c) & 1);
+ parity ^= parity8(c);
return parity;
}

--
2.5.0


2016-04-06 10:21:33

by Zhaoxiu Zeng

[permalink] [raw]
Subject: [PATCH v2 29/30] input: use parity8 in elantech

From: Zhaoxiu Zeng <[email protected]>

Remove even parity table, use parity8 instead.

Signed-off-by: Zhaoxiu Zeng <[email protected]>
---
drivers/input/mouse/elantech.c | 10 +++-------
drivers/input/mouse/elantech.h | 1 -
2 files changed, 3 insertions(+), 8 deletions(-)

diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c
index 78f93cf..bbb4aa6 100644
--- a/drivers/input/mouse/elantech.c
+++ b/drivers/input/mouse/elantech.c
@@ -693,9 +693,9 @@ static int elantech_packet_check_v1(struct psmouse *psmouse)

p3 = (packet[0] & 0x04) >> 2;

- return etd->parity[packet[1]] == p1 &&
- etd->parity[packet[2]] == p2 &&
- etd->parity[packet[3]] == p3;
+ return parity8(packet[1]) != p1 &&
+ parity8(packet[2]) != p2 &&
+ parity8(packet[3]) != p3;
}

static int elantech_debounce_check_v2(struct psmouse *psmouse)
@@ -1635,10 +1635,6 @@ int elantech_init(struct psmouse *psmouse)

psmouse_reset(psmouse);

- etd->parity[0] = 1;
- for (i = 1; i < 256; i++)
- etd->parity[i] = etd->parity[i & (i - 1)] ^ 1;
-
/*
* Do the version query again so we can store the result
*/
diff --git a/drivers/input/mouse/elantech.h b/drivers/input/mouse/elantech.h
index e1cbf40..542c5d9 100644
--- a/drivers/input/mouse/elantech.h
+++ b/drivers/input/mouse/elantech.h
@@ -141,7 +141,6 @@ struct elantech_data {
unsigned int y_max;
unsigned int width;
struct finger_pos mt[ETP_MAX_FINGERS];
- unsigned char parity[256];
int (*send_cmd)(struct psmouse *psmouse, unsigned char c, unsigned char *param);
void (*original_set_rate)(struct psmouse *psmouse, unsigned int rate);
};
--
2.5.0


2016-04-06 10:22:00

by Zhaoxiu Zeng

[permalink] [raw]
Subject: [PATCH v2 30/30] ethernet: use parity8 in broadcom/tg3.c

From: Zhaoxiu Zeng <[email protected]>

Signed-off-by: Zhaoxiu Zeng <[email protected]>
---
drivers/net/ethernet/broadcom/tg3.c | 6 +-----
1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c
index 3010080..802a429 100644
--- a/drivers/net/ethernet/broadcom/tg3.c
+++ b/drivers/net/ethernet/broadcom/tg3.c
@@ -12939,11 +12939,7 @@ static int tg3_test_nvram(struct tg3 *tp)

err = -EIO;
for (i = 0; i < NVRAM_SELFBOOT_DATA_SIZE; i++) {
- u8 hw8 = hweight8(data[i]);
-
- if ((hw8 & 0x1) && parity[i])
- goto out;
- else if (!(hw8 & 0x1) && !parity[i])
+ if (parity8(data[i]) == !!parity[i])
goto out;
}
err = 0;
--
2.5.0


2016-04-06 10:24:10

by Zhaoxiu Zeng

[permalink] [raw]
Subject: [PATCH v2 06/30] Add mips-specific parity functions

From: Zhaoxiu Zeng <[email protected]>

Lifted from arch_hweight.h

Signed-off-by: Zhaoxiu Zeng <[email protected]>
---
arch/mips/include/asm/arch_parity.h | 43 +++++++++++++++++++++++++++++++++++++
arch/mips/include/asm/bitops.h | 3 +++
2 files changed, 46 insertions(+)
create mode 100644 arch/mips/include/asm/arch_parity.h

diff --git a/arch/mips/include/asm/arch_parity.h b/arch/mips/include/asm/arch_parity.h
new file mode 100644
index 0000000..23b3c23
--- /dev/null
+++ b/arch/mips/include/asm/arch_parity.h
@@ -0,0 +1,44 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ */
+#ifndef _ASM_ARCH_PARITY_H
+#define _ASM_ARCH_PARITY_H
+
+#ifdef ARCH_HAS_USABLE_BUILTIN_POPCOUNT
+
+#include <asm/types.h>
+
+static inline unsigned int __arch_parity32(unsigned int w)
+{
+ return __builtin_popcount(w) & 1;
+}
+
+static inline unsigned int __arch_parity16(unsigned int w)
+{
+ return __arch_parity32(w & 0xffff);
+}
+
+static inline unsigned int __arch_parity8(unsigned int w)
+{
+ return __arch_parity32(w & 0xff);
+}
+
+static inline unsigned int __arch_parity4(unsigned int w)
+{
+ return __arch_parity32(w & 0xf);
+}
+
+static inline unsigned int __arch_parity64(__u64 w)
+{
+ return (unsigned int)__builtin_popcountll(w) & 1;
+}
+
+#else
+#include <asm-generic/bitops/arch_parity.h>
+#endif
+
+#endif /* _ASM_ARCH_PARITY_H */
diff --git a/arch/mips/include/asm/bitops.h b/arch/mips/include/asm/bitops.h
index ce9666c..0b87734 100644
--- a/arch/mips/include/asm/bitops.h
+++ b/arch/mips/include/asm/bitops.h
@@ -626,6 +626,9 @@ static inline int ffs(int word)
#include <asm/arch_hweight.h>
#include <asm-generic/bitops/const_hweight.h>

+#include <asm/arch_parity.h>
+#include <asm-generic/bitops/const_parity.h>
+
#include <asm-generic/bitops/le.h>
#include <asm-generic/bitops/ext2-atomic.h>

--
2.5.0


2016-04-06 10:26:05

by Greg Kroah-Hartman

[permalink] [raw]
Subject: Re: [PATCH v2 28/30] serial: use parity32 in max3100

On Wed, Apr 06, 2016 at 06:18:42PM +0800, [email protected] wrote:
> From: Zhaoxiu Zeng <[email protected]>
>
> Signed-off-by: Zhaoxiu Zeng <[email protected]>
> ---
> drivers/tty/serial/max3100.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)

I can't take patches without any changelog text :(

2016-04-06 10:38:10

by Alan Cox

[permalink] [raw]
Subject: Re: [PATCH v2 10/30] Add x86-specific parity functions

On Wed, 6 Apr 2016 12:13:00 +0200
Borislav Petkov <[email protected]> wrote:

> On Wed, Apr 06, 2016 at 05:14:45PM +0800, [email protected] wrote:
> > From: Zhaoxiu Zeng <[email protected]>
> >
> > Use alternatives, lifted from arch_hweight
> >
> > Signed-off-by: Zhaoxiu Zeng <[email protected]>
> > ---
> > arch/x86/include/asm/arch_hweight.h | 5 ++
> > arch/x86/include/asm/arch_parity.h | 102 ++++++++++++++++++++++++++++++++++++
> > arch/x86/include/asm/bitops.h | 4 +-
> > arch/x86/lib/Makefile | 8 +++
> > arch/x86/lib/parity.c | 32 ++++++++++++
> > 5 files changed, 150 insertions(+), 1 deletion(-)
> > create mode 100644 arch/x86/include/asm/arch_parity.h
> > create mode 100644 arch/x86/lib/parity.c
>
> ...
>
> > +static __always_inline unsigned int __arch_parity32(unsigned int w)
> > +{
> > + unsigned int res;
> > +
> > + asm(ALTERNATIVE("call __sw_parity32", POPCNT32 "; and $1, %0", X86_FEATURE_POPCNT)
> > + : "="REG_OUT (res)
> > + : REG_IN (w)
> > + : "cc");
>
> So why all that churn instead of simply doing:
>
> static __always_inline unsigned int __arch_parity32(unsigned int w)
> {
> return hweight32(w) & 1;
> }
>
> Ditto for the 64-bit version.

Even that would still be wrong for the smaller parity values. The CPU
supports 8bit parity directly going back to the 8086 so the
implementation for 8bit and I think 16bit is still wrong.

Alan

2016-04-06 10:53:45

by Borislav Petkov

[permalink] [raw]
Subject: Re: [PATCH v2 10/30] Add x86-specific parity functions

On Wed, Apr 06, 2016 at 11:37:37AM +0100, One Thousand Gnomes wrote:
> Even that would still be wrong for the smaller parity values. The CPU
> supports 8bit parity directly going back to the 8086 so the
> implementation for 8bit and I think 16bit is still wrong.

I was objecting to the unnecessary replication of the hweight/popcnt
glue.

And yes, one could look up the definition of the parity flag on x86 and
then base the implementation of all those smaller ones on that as the
hardware does it for one practically for free there.

:-)

--
Regards/Gruss,
Boris.

SUSE Linux GmbH, GF: Felix Imendörffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nürnberg)
--

2016-04-06 13:28:01

by Chris Metcalf

[permalink] [raw]
Subject: Re: [PATCH v2 09/30] Add tile-specific parity functions

On 4/6/2016 5:08 AM, [email protected] wrote:
> From: Zhaoxiu Zeng<[email protected]>
>
> Signed-off-by: Zhaoxiu Zeng<[email protected]>
> ---
> arch/tile/include/asm/bitops.h | 26 ++++++++++++++++++++++++++
> 1 file changed, 26 insertions(+)

Since all the code you are adding here is architecture-independent,
I think it would make more sense to have it be in a file like
include/asm-generic/bitops/parity-popcount.h, which can then
be included from arch/tile/include/asm/bitops.h.

--
Chris Metcalf, Mellanox Technologies
http://www.mellanox.com

2016-04-06 18:44:57

by Sam Ravnborg

[permalink] [raw]
Subject: Re: [PATCH v2 08/30] Add sparc-specific parity functions

Hi Zeng.

>
> Use runtime patching for sparc64, lifted from hweight
No errors found in patch - but a few comments.
In general patch looks good.

> +++ b/arch/sparc/include/asm/bitops_64.h
> @@ -47,6 +47,24 @@ unsigned int __arch_hweight16(unsigned int w);
> unsigned int __arch_hweight8(unsigned int w);
>
> #include <asm-generic/bitops/const_hweight.h>
> +
> +/*
> + * parityN: returns the parity of a N-bit word,
> + * i.e. the number of 1-bits in w modulo 2.
> + */
> +
> +static inline unsigned int __arch_parity4(unsigned int w)
> +{
> + w &= 0xf;
> + return (0x6996 >> w) & 1;
> +}
As Josef already said - this constant should have a name.
PARITY_BIT
?

> +++ b/arch/sparc/kernel/sparc_ksyms_64.c
> @@ -45,6 +45,12 @@ EXPORT_SYMBOL(__arch_hweight16);
> EXPORT_SYMBOL(__arch_hweight32);
> EXPORT_SYMBOL(__arch_hweight64);
>
> +/* from parity.S */
> +EXPORT_SYMBOL(__arch_parity8);
> +EXPORT_SYMBOL(__arch_parity16);
> +EXPORT_SYMBOL(__arch_parity32);
> +EXPORT_SYMBOL(__arch_parity64);

Did you compile this?
I wonder if bitops_64.h is indirectly included.

> index 0000000..b1945e3
> --- /dev/null
> +++ b/arch/sparc/lib/parity.S
> @@ -0,0 +1,93 @@
> +#include <linux/linkage.h>
> +
> + .text
> + .align 32
> +
> +ENTRY(__arch_parity8)
> + srl %o0, 4, %g1
> + xor %o0, %g1, %o0
> + and %o0, 0xf, %o0
> + sethi %hi(0x6996), %g1
> + or %g1, %lo(0x6996), %g1
> + srl %g1, %o0, %o0
> + retl
> + and %o0, 1, %o0
> +ENDPROC(__arch_parity8)

I know the level of comments in hweight is equal to none.
But please do not follow this bad example.
At least for each function a one-liner of the C code.
And in the top of the file maybe two lines that the functions
are patched at run-time if the processor has popc available.


Sam

2016-04-06 19:45:31

by Andi Kleen

[permalink] [raw]
Subject: Re: [PATCH v2 10/30] Add x86-specific parity functions

[email protected] writes:

> From: Zhaoxiu Zeng <[email protected]>
>
> Use alternatives, lifted from arch_hweight

Is there actually anything performance critical in the kernel that uses
parity?

FWIW the arch hweight custom calling convention is a problem for LTO
because it needs different special flags, so I usually have to disable
it. Likely other reasonable usages, such as automatic source code
analysis, and other tool chain based usages have similar problems.

As far as I can tell both for hweight and likely for parity it is
badly overengineering and normal calling conventions would work as well,
and cause much less problems.

So if parity is really worth adding here (which I find doubtful,
but you may have numbers), please add it without these magic
calling hacks.

-Andi

--
[email protected] -- Speaking for myself only

2016-04-07 03:55:30

by Zhaoxiu Zeng

[permalink] [raw]
Subject: Re: [PATCH v2 10/30] Add x86-specific parity functions

在 2016年04月06日 18:13, Borislav Petkov 写道:
> On Wed, Apr 06, 2016 at 05:14:45PM +0800, [email protected] wrote:
>> From: Zhaoxiu Zeng <[email protected]>
>>
>> Use alternatives, lifted from arch_hweight
>>
>> Signed-off-by: Zhaoxiu Zeng <[email protected]>
>> ---
>> arch/x86/include/asm/arch_hweight.h | 5 ++
>> arch/x86/include/asm/arch_parity.h | 102 ++++++++++++++++++++++++++++++++++++
>> arch/x86/include/asm/bitops.h | 4 +-
>> arch/x86/lib/Makefile | 8 +++
>> arch/x86/lib/parity.c | 32 ++++++++++++
>> 5 files changed, 150 insertions(+), 1 deletion(-)
>> create mode 100644 arch/x86/include/asm/arch_parity.h
>> create mode 100644 arch/x86/lib/parity.c
> ...
>
>> +static __always_inline unsigned int __arch_parity32(unsigned int w)
>> +{
>> + unsigned int res;
>> +
>> + asm(ALTERNATIVE("call __sw_parity32", POPCNT32 "; and $1, %0", X86_FEATURE_POPCNT)
>> + : "="REG_OUT (res)
>> + : REG_IN (w)
>> + : "cc");
> So why all that churn instead of simply doing:
>
> static __always_inline unsigned int __arch_parity32(unsigned int w)
> {
> return hweight32(w) & 1;
> }
>
> Ditto for the 64-bit version.
>

__sw_parity32 is faster than __sw_hweight32.
I don't know how many CPUs do not support the popc, if they are outdated,
use __arch_hweight32 is the easiest way.

2016-04-07 03:55:58

by Zhaoxiu Zeng

[permalink] [raw]
Subject: Re: [PATCH v2 10/30] Add x86-specific parity functions

在 2016年04月06日 18:53, Borislav Petkov 写道:
> On Wed, Apr 06, 2016 at 11:37:37AM +0100, One Thousand Gnomes wrote:
>> Even that would still be wrong for the smaller parity values. The CPU
>> supports 8bit parity directly going back to the 8086 so the
>> implementation for 8bit and I think 16bit is still wrong.
> I was objecting to the unnecessary replication of the hweight/popcnt
> glue.
>
> And yes, one could look up the definition of the parity flag on x86 and
> then base the implementation of all those smaller ones on that as the
> hardware does it for one practically for free there.
>
> :-)
>

SETcc (SETPO etc.) added since 80386, is this a problem?

2016-04-07 03:56:01

by Zhaoxiu Zeng

[permalink] [raw]
Subject: Re: [PATCH v2 09/30] Add tile-specific parity functions

在 2016年04月06日 21:27, Chris Metcalf 写道:
> On 4/6/2016 5:08 AM, [email protected] wrote:
>> From: Zhaoxiu Zeng<[email protected]>
>>
>> Signed-off-by: Zhaoxiu Zeng<[email protected]>
>> ---
>> arch/tile/include/asm/bitops.h | 26 ++++++++++++++++++++++++++
>> 1 file changed, 26 insertions(+)
>
> Since all the code you are adding here is architecture-independent,
> I think it would make more sense to have it be in a file like
> include/asm-generic/bitops/parity-popcount.h, which can then
> be included from arch/tile/include/asm/bitops.h.
>

Agreed, thanks!

2016-04-07 03:56:17

by Zhaoxiu Zeng

[permalink] [raw]
Subject: Re: [PATCH v2 08/30] Add sparc-specific parity functions

在 2016年04月07日 02:44, Sam Ravnborg 写道:
> Hi Zeng.
>
>> Use runtime patching for sparc64, lifted from hweight
> No errors found in patch - but a few comments.
> In general patch looks good.

Thanks. Sparc, powerpc, and x86 are all new to me.

>> +++ b/arch/sparc/include/asm/bitops_64.h
>> @@ -47,6 +47,24 @@ unsigned int __arch_hweight16(unsigned int w);
>> unsigned int __arch_hweight8(unsigned int w);
>>
>> #include <asm-generic/bitops/const_hweight.h>
>> +
>> +/*
>> + * parityN: returns the parity of a N-bit word,
>> + * i.e. the number of 1-bits in w modulo 2.
>> + */
>> +
>> +static inline unsigned int __arch_parity4(unsigned int w)
>> +{
>> + w &= 0xf;
>> + return (0x6996 >> w) & 1;
>> +}
> As Josef already said - this constant should have a name.
> PARITY_BIT
> ?
>

Maybe PARITY_MAGIC?

>> +++ b/arch/sparc/kernel/sparc_ksyms_64.c
>> @@ -45,6 +45,12 @@ EXPORT_SYMBOL(__arch_hweight16);
>> EXPORT_SYMBOL(__arch_hweight32);
>> EXPORT_SYMBOL(__arch_hweight64);
>>
>> +/* from parity.S */
>> +EXPORT_SYMBOL(__arch_parity8);
>> +EXPORT_SYMBOL(__arch_parity16);
>> +EXPORT_SYMBOL(__arch_parity32);
>> +EXPORT_SYMBOL(__arch_parity64);
> Did you compile this?
> I wonder if bitops_64.h is indirectly included.

Yes.

>> index 0000000..b1945e3
>> --- /dev/null
>> +++ b/arch/sparc/lib/parity.S
>> @@ -0,0 +1,93 @@
>> +#include <linux/linkage.h>
>> +
>> + .text
>> + .align 32
>> +
>> +ENTRY(__arch_parity8)
>> + srl %o0, 4, %g1
>> + xor %o0, %g1, %o0
>> + and %o0, 0xf, %o0
>> + sethi %hi(0x6996), %g1
>> + or %g1, %lo(0x6996), %g1
>> + srl %g1, %o0, %o0
>> + retl
>> + and %o0, 1, %o0
>> +ENDPROC(__arch_parity8)
> I know the level of comments in hweight is equal to none.
> But please do not follow this bad example.
> At least for each function a one-liner of the C code.
> And in the top of the file maybe two lines that the functions
> are patched at run-time if the processor has popc available.
>
>
> Sam

OK. I will try, but my english is very poor! :-)

2016-04-07 03:56:21

by Zhaoxiu Zeng

[permalink] [raw]
Subject: Re: [PATCH v2 10/30] Add x86-specific parity functions

?? 2016??04??07?? 03:45, Andi Kleen д??:
> [email protected] writes:
>
>> From: Zhaoxiu Zeng <[email protected]>
>>
>> Use alternatives, lifted from arch_hweight
> Is there actually anything performance critical in the kernel that uses
> parity?
>
> FWIW the arch hweight custom calling convention is a problem for LTO
> because it needs different special flags, so I usually have to disable
> it. Likely other reasonable usages, such as automatic source code
> analysis, and other tool chain based usages have similar problems.
>
> As far as I can tell both for hweight and likely for parity it is
> badly overengineering and normal calling conventions would work as well,
> and cause much less problems.
>
> So if parity is really worth adding here (which I find doubtful,
> but you may have numbers), please add it without these magic
> calling hacks.
>
> -Andi
>

Thanks. I will instead use __arch_hweight.

2016-04-07 06:31:32

by Dmitry Vyukov

[permalink] [raw]
Subject: Re: [PATCH v2 10/30] Add x86-specific parity functions

On Wed, Apr 6, 2016 at 9:45 PM, Andi Kleen <[email protected]> wrote:
> [email protected] writes:
>
>> From: Zhaoxiu Zeng <[email protected]>
>>
>> Use alternatives, lifted from arch_hweight
>
> Is there actually anything performance critical in the kernel that uses
> parity?
>
> FWIW the arch hweight custom calling convention is a problem for LTO
> because it needs different special flags, so I usually have to disable
> it. Likely other reasonable usages, such as automatic source code
> analysis, and other tool chain based usages have similar problems.
>
> As far as I can tell both for hweight and likely for parity it is
> badly overengineering and normal calling conventions would work as well,
> and cause much less problems.
>
> So if parity is really worth adding here (which I find doubtful,
> but you may have numbers), please add it without these magic
> calling hacks.


Hweight custom calling convention caused crashes with KCOV coverage.
We had to disable instrumentation of the file.

2016-04-07 09:39:59

by Borislav Petkov

[permalink] [raw]
Subject: Re: [PATCH v2 10/30] Add x86-specific parity functions

On Thu, Apr 07, 2016 at 11:55:51AM +0800, Zeng Zhaoxiu wrote:
> SETcc (SETPO etc.) added since 80386, is this a problem?

Sounds to me you didn't make the effort to look up the definition of the
Parity Flag...

--
Regards/Gruss,
Boris.

SUSE Linux GmbH, GF: Felix Imendörffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nürnberg)
--

2016-04-07 09:41:21

by Borislav Petkov

[permalink] [raw]
Subject: Re: [PATCH v2 10/30] Add x86-specific parity functions

On Thu, Apr 07, 2016 at 11:55:22AM +0800, Zeng Zhaoxiu wrote:
> __sw_parity32 is faster than __sw_hweight32.
> I don't know how many CPUs do not support the popc, if they are outdated,
> use __arch_hweight32 is the easiest way.

I don't really understand what you're trying to tell me here. And it's
not like I didn't try.

--
Regards/Gruss,
Boris.

SUSE Linux GmbH, GF: Felix Imendörffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nürnberg)
--

2016-04-07 09:43:37

by Borislav Petkov

[permalink] [raw]
Subject: Re: [PATCH v2 10/30] Add x86-specific parity functions

On Thu, Apr 07, 2016 at 08:31:09AM +0200, Dmitry Vyukov wrote:
> Hweight custom calling convention caused crashes with KCOV coverage.
> We had to disable instrumentation of the file.

I guess we can do something like this:

if (likely(static_cpu_has(X86_FEATURE_POPCNT)))
asm volatile(POPCNT32
: "="REG_OUT (res)
: REG_IN (w));
else
res = __sw_hweight32(w);

and get rid of the custom calling convention.

Along with some numbers showing that the change doesn't cause any
noticeable slowdown...

--
Regards/Gruss,
Boris.

SUSE Linux GmbH, GF: Felix Imendörffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nürnberg)
--

2016-04-07 14:10:54

by Alan Cox

[permalink] [raw]
Subject: Re: [PATCH v2 10/30] Add x86-specific parity functions

On Wed, 06 Apr 2016 12:45:27 -0700
Andi Kleen <[email protected]> wrote:

> [email protected] writes:
>
> > From: Zhaoxiu Zeng <[email protected]>
> >
> > Use alternatives, lifted from arch_hweight
>
> Is there actually anything performance critical in the kernel that uses
> parity?

On very low end devices some of the flash, but the implementation here is
ironically pretty much worst-case for such x86 devices 8)

Alan

2016-04-10 14:37:47

by Jonathan Cameron

[permalink] [raw]
Subject: Re: [PATCH v2 27/30] iio: use parity32 in adxrs450

On 06/04/16 11:16, [email protected] wrote:
> From: Zhaoxiu Zeng <[email protected]>
>
> Signed-off-by: Zhaoxiu Zeng <[email protected]>
Applied to the togreg branch of iio.git as you seem to have addressed
Lars' comments.

Thanks,

Jonathan
> ---
> drivers/iio/gyro/adxrs450.c | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/iio/gyro/adxrs450.c b/drivers/iio/gyro/adxrs450.c
> index a330d42..307f55b 100644
> --- a/drivers/iio/gyro/adxrs450.c
> +++ b/drivers/iio/gyro/adxrs450.c
> @@ -109,7 +109,7 @@ static int adxrs450_spi_read_reg_16(struct iio_dev *indio_dev,
> mutex_lock(&st->buf_lock);
> tx = ADXRS450_READ_DATA | (reg_address << 17);
>
> - if (!(hweight32(tx) & 1))
> + if (!parity32(tx))
> tx |= ADXRS450_P;
>
> st->tx = cpu_to_be32(tx);
> @@ -145,7 +145,7 @@ static int adxrs450_spi_write_reg_16(struct iio_dev *indio_dev,
> mutex_lock(&st->buf_lock);
> tx = ADXRS450_WRITE_DATA | (reg_address << 17) | (val << 1);
>
> - if (!(hweight32(tx) & 1))
> + if (!parity32(tx))
> tx |= ADXRS450_P;
>
> st->tx = cpu_to_be32(tx);
>

2016-04-10 15:00:20

by Lars-Peter Clausen

[permalink] [raw]
Subject: Re: [PATCH v2 27/30] iio: use parity32 in adxrs450

On 04/10/2016 04:37 PM, Jonathan Cameron wrote:
> On 06/04/16 11:16, [email protected] wrote:
>> From: Zhaoxiu Zeng <[email protected]>
>>
>> Signed-off-by: Zhaoxiu Zeng <[email protected]>
> Applied to the togreg branch of iio.git as you seem to have addressed
> Lars' comments.

The whole series needs to go through the same tree since the new functions
are introduced in the beginning.

2016-04-10 15:13:35

by Jonathan Cameron

[permalink] [raw]
Subject: Re: [PATCH v2 27/30] iio: use parity32 in adxrs450

On 10/04/16 15:41, Lars-Peter Clausen wrote:
> On 04/10/2016 04:37 PM, Jonathan Cameron wrote:
>> On 06/04/16 11:16, [email protected] wrote:
>>> From: Zhaoxiu Zeng <[email protected]>
>>>
>>> Signed-off-by: Zhaoxiu Zeng <[email protected]>
>> Applied to the togreg branch of iio.git as you seem to have addressed
>> Lars' comments.
>
> The whole series needs to go through the same tree since the new functions
> are introduced in the beginning.
Yeah, I just realized that when my build test failed!

Acked-by: Jonathan Cameron <[email protected]>
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-iio" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>

2016-04-10 15:14:15

by Jonathan Cameron

[permalink] [raw]
Subject: Re: [PATCH v2 27/30] iio: use parity32 in adxrs450

On 10/04/16 16:13, Jonathan Cameron wrote:
> On 10/04/16 15:41, Lars-Peter Clausen wrote:
>> On 04/10/2016 04:37 PM, Jonathan Cameron wrote:
>>> On 06/04/16 11:16, [email protected] wrote:
>>>> From: Zhaoxiu Zeng <[email protected]>
>>>>
>>>> Signed-off-by: Zhaoxiu Zeng <[email protected]>
>>> Applied to the togreg branch of iio.git as you seem to have addressed
>>> Lars' comments.
>>
>> The whole series needs to go through the same tree since the new functions
>> are introduced in the beginning.
> Yeah, I just realized that when my build test failed!
>
> Acked-by: Jonathan Cameron <[email protected]>
Backed out of the togreg branch of iio.git...

oops and thanks Lars!
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-iio" in
>> the body of a message to [email protected]
>> More majordomo info at http://vger.kernel.org/majordomo-info.html
>>
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-iio" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>

2016-04-11 02:43:46

by Zhaoxiu Zeng

[permalink] [raw]
Subject: Re: [PATCH v2 10/30] Add x86-specific parity functions

在 2016年04月06日 18:37, One Thousand Gnomes 写道:
> Even that would still be wrong for the smaller parity values. The CPU
> supports 8bit parity directly going back to the 8086 so the
> implementation for 8bit and I think 16bit is still wrong.
>
> Alan

I don't know where the errors. X86 is new to me.

The definition of the parity flag on x86 from Wikipedia:

In x86 processors, the parity flag reflects the parity only of the least significant
byte of the result, and is set if the number of set bits of ones is even. According to
80386 Intel manual, the parity flag is changed in the x86 processor family by the
following instructions:
All arithmetic instructions;
Compare instruction (equivalent to a subtract instruction without storing the result);
Logical instructions - XOR, AND, OR;
the TEST instruction (equivalent to the AND instruction without storing the result).
the POPF instruction

2016-04-15 00:10:30

by Borislav Petkov

[permalink] [raw]
Subject: Re: [PATCH v2 10/30] Add x86-specific parity functions

On Mon, Apr 11, 2016 at 10:43:32AM +0800, Zeng Zhaoxiu wrote:
> I don't know where the errors. X86 is new to me.

Ok, let me try again by pasting here the relevant text from the manual:

"Parity Flag (PF). Bit 2. Hardware sets the parity flag to 1 if there
is an even number of 1 bits in the least-significant byte of the last
result of certain operations. Otherwise (i.e., for an odd number of 1
bits), hardware clears the flag to 0. Software can read the flag to
implement parity checking."

--
Regards/Gruss,
Boris.

SUSE Linux GmbH, GF: Felix Imendörffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nürnberg)
--