Auto-detect whether to use hw assisted crc32c
authorJens Axboe <axboe@kernel.dk>
Wed, 22 Feb 2012 19:28:17 +0000 (20:28 +0100)
committerJens Axboe <axboe@kernel.dk>
Wed, 22 Feb 2012 19:28:17 +0000 (20:28 +0100)
Little point in separating the two. If the hardware assisted
crypto is available, always use it.

Signed-off-by: Jens Axboe <axboe@kernel.dk>
crc/crc32c-intel.c
crc/crc32c.c
crc/crc32c.h
options.c
verify.c

index 5040efeae9030005af296bfa72c07414535144a4..8a6e6dcefb749b41ed5ecddb7035ae6a8c247adf 100644 (file)
@@ -18,6 +18,8 @@
  * Volume 2A: Instruction Set Reference, A-M
  */
 
+int crc32c_intel_available = 0;
+
 #ifdef ARCH_HAVE_SSE4_2
 
 #if BITS_PER_LONG == 64
@@ -28,6 +30,8 @@
 #define SCALE_F 4
 #endif
 
+static int crc32c_probed;
+
 static uint32_t crc32c_intel_le_hw_byte(uint32_t crc, unsigned char const *data,
                                        unsigned long length)
 {
@@ -90,14 +94,17 @@ static void do_cpuid(unsigned int *eax, unsigned int *ebx, unsigned int *ecx,
                : "eax", "ebx", "ecx", "edx");
 }
 
-int crc32c_intel_works(void)
+void crc32c_intel_probe(void)
 {
-       unsigned int eax, ebx, ecx, edx;
+       if (!crc32c_probed) {
+               unsigned int eax, ebx, ecx, edx;
 
-       eax = 1;
+               eax = 1;
 
-       do_cpuid(&eax, &ebx, &ecx, &edx);
-       return (ecx & (1 << 20)) != 0;
+               do_cpuid(&eax, &ebx, &ecx, &edx);
+               crc32c_intel_available = (ecx & (1 << 20)) != 0;
+               crc32c_probed = 1;
+       }
 }
 
 #endif /* ARCH_HAVE_SSE */
index 8bbea685c47c5614e2d0f8303d3bb28d394bb30d..b830b9fe026ba77e5727e4a485121fa6a1f76d2e 100644 (file)
@@ -113,7 +113,7 @@ static const uint32_t crc32c_table[256] = {
  * crc using table.
  */
 
-uint32_t crc32c(unsigned char const *data, unsigned long length)
+uint32_t crc32c_sw(unsigned char const *data, unsigned long length)
 {
        uint32_t crc = ~0;
 
index 596fd6c56a98f835933ee68c17b1e845e0309a7d..46c106393ef13f6012d977d55e36fb414ede87f9 100644 (file)
 
 #include "../arch/arch.h"
 
-extern uint32_t crc32c(unsigned char const *, unsigned long);
+extern uint32_t crc32c_sw(unsigned char const *, unsigned long);
+extern int crc32c_intel_available;
 
 #ifdef ARCH_HAVE_SSE4_2
 extern uint32_t crc32c_intel(unsigned char const *, unsigned long);
-extern int crc32c_intel_works(void);
+extern void crc32c_intel_probe(void);
 #else
-#define crc32c_intel crc32c
-static inline int crc32c_intel_works(void)
+#define crc32c_intel crc32c_sw
+static inline void crc32c_intel_probe(void)
 {
-       return 0;
 }
 #endif
 
+static inline uint32_t crc32c(unsigned char const *buf, unsigned long len)
+{
+       if (crc32c_intel_available)
+               return crc32c_intel(buf, len);
+
+       return crc32c_sw(buf, len);
+}
+
 #endif
index bd8141a83f34d8a012742991dbd1422fb20c54d6..d777efc7efe8293320ed3ff2f529f31047af21a2 100644 (file)
--- a/options.c
+++ b/options.c
@@ -245,12 +245,9 @@ static int str_verify_cb(void *data, const char *mem)
 {
        struct thread_data *td = data;
 
-       if (td->o.verify != VERIFY_CRC32C_INTEL)
-               return 0;
-
-       if (!crc32c_intel_works()) {
-               log_info("fio: System does not support hw accelerated crc32c. Falling back to sw crc32c.\n");
-               td->o.verify = VERIFY_CRC32C;
+       if (td->o.verify == VERIFY_CRC32C_INTEL ||
+           td->o.verify == VERIFY_CRC32C) {
+               crc32c_intel_probe();
        }
 
        return 0;
@@ -1482,12 +1479,12 @@ static struct fio_option options[FIO_MAX_OPTS] = {
                            .help = "Use crc32 checksums for verification",
                          },
                          { .ival = "crc32c-intel",
-                           .oval = VERIFY_CRC32C_INTEL,
-                           .help = "Use hw crc32c checksums for verification",
+                           .oval = VERIFY_CRC32C,
+                           .help = "Use crc32c checksums for verification (hw assisted, if available)",
                          },
                          { .ival = "crc32c",
                            .oval = VERIFY_CRC32C,
-                           .help = "Use crc32c checksums for verification",
+                           .help = "Use crc32c checksums for verification (hw assisted, if available)",
                          },
                          { .ival = "crc16",
                            .oval = VERIFY_CRC16,
index 8bf14ae05fb08ecb4b960051c8444635219d933c..d6abb983a5d6dbcab39a93d3efa822352893d890 100644 (file)
--- a/verify.c
+++ b/verify.c
@@ -551,10 +551,7 @@ static int verify_io_u_crc32c(struct verify_header *hdr, struct vcont *vc)
 
        dprint(FD_VERIFY, "crc32c verify io_u %p, len %u\n", vc->io_u, hdr->len);
 
-       if (hdr->verify_type == VERIFY_CRC32C_INTEL)
-               c = crc32c_intel(p, hdr->len - hdr_size(hdr));
-       else
-               c = crc32c(p, hdr->len - hdr_size(hdr));
+       c = crc32c(p, hdr->len - hdr_size(hdr));
 
        if (c == vh->crc32)
                return 0;
@@ -833,10 +830,7 @@ static void fill_crc32c(struct verify_header *hdr, void *p, unsigned int len)
 {
        struct vhdr_crc32 *vh = hdr_priv(hdr);
 
-       if (hdr->verify_type == VERIFY_CRC32C_INTEL)
-               vh->crc32 = crc32c_intel(p, len);
-       else
-               vh->crc32 = crc32c(p, len);
+       vh->crc32 = crc32c(p, len);
 }
 
 static void fill_crc64(struct verify_header *hdr, void *p, unsigned int len)