+
+#ifdef HAVE_ADLER
+/* Adler-32 is supported */
+#define CHECKSUM_ADLER OBD_CKSUM_ADLER
+#else
+#define CHECKSUM_ADLER 0
+#endif
+
+#ifdef X86_FEATURE_XMM4_2
+/* Call Nehalem+ CRC32C harware acceleration instruction on individual bytes. */
+static inline __u32 crc32c_hw_byte(__u32 crc, unsigned char const *p,
+ size_t bytes)
+{
+ while (bytes--) {
+ __asm__ __volatile__ (
+ ".byte 0xf2, 0xf, 0x38, 0xf0, 0xf1"
+ : "=S"(crc)
+ : "0"(crc), "c"(*p)
+ );
+ p++;
+ }
+
+ return crc;
+}
+
+#if BITS_PER_LONG > 32
+#define WORD_SHIFT 3
+#define WORD_MASK 7
+#define REX "0x48, "
+#else
+#define WORD_SHIFT 2
+#define WORD_MASK 3
+#define REX ""
+#endif
+
+/* Do we need to worry about unaligned input data here? */
+static inline __u32 crc32c_hw(__u32 crc, unsigned char const *p, size_t len)
+{
+ unsigned int words = len >> WORD_SHIFT;
+ unsigned int bytes = len & WORD_MASK;
+ long *ptmp = (long *)p;
+
+ while (words--) {
+ __asm__ __volatile__(
+ ".byte 0xf2, " REX "0xf, 0x38, 0xf1, 0xf1;"
+ : "=S"(crc)
+ : "0"(crc), "c"(*ptmp)
+ );
+ ptmp++;
+ }
+
+ if (bytes)
+ crc = crc32c_hw_byte(crc, (unsigned char *)ptmp, bytes);
+
+ return crc;
+}
+#else
+/* We should never call this unless the CPU has previously been detected to
+ * support this instruction in the SSE4.2 feature set. b=23549 */
+static inline __u32 crc32c_hw(__u32 crc, unsigned char const *p,size_t len)
+{
+ LBUG();
+}
+#endif