From e3aaafc4e902a0f78b8ee4d4bc85f8edac6e09d2 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 22 Feb 2012 20:28:17 +0100 Subject: [PATCH] Auto-detect whether to use hw assisted crc32c Little point in separating the two. If the hardware assisted crypto is available, always use it. Signed-off-by: Jens Axboe --- crc/crc32c-intel.c | 17 ++++++++++++----- crc/crc32c.c | 2 +- crc/crc32c.h | 18 +++++++++++++----- options.c | 15 ++++++--------- verify.c | 10 ++-------- 5 files changed, 34 insertions(+), 28 deletions(-) diff --git a/crc/crc32c-intel.c b/crc/crc32c-intel.c index 5040efea..8a6e6dce 100644 --- a/crc/crc32c-intel.c +++ b/crc/crc32c-intel.c @@ -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 */ diff --git a/crc/crc32c.c b/crc/crc32c.c index 8bbea685..b830b9fe 100644 --- a/crc/crc32c.c +++ b/crc/crc32c.c @@ -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; diff --git a/crc/crc32c.h b/crc/crc32c.h index 596fd6c5..46c10639 100644 --- a/crc/crc32c.h +++ b/crc/crc32c.h @@ -20,17 +20,25 @@ #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 diff --git a/options.c b/options.c index bd8141a8..d777efc7 100644 --- 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, diff --git a/verify.c b/verify.c index 8bf14ae0..d6abb983 100644 --- 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) -- 2.25.1