crc32.h 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * CRC-32 implemented with the z/Architecture Vector Extension Facility.
  4. *
  5. * Copyright IBM Corp. 2015
  6. * Author(s): Hendrik Brueckner <brueckner@linux.vnet.ibm.com>
  7. */
  8. #include <linux/cpufeature.h>
  9. #include <asm/fpu.h>
  10. #include "crc32-vx.h"
  11. #define VX_MIN_LEN 64
  12. #define VX_ALIGNMENT 16L
  13. #define VX_ALIGN_MASK (VX_ALIGNMENT - 1)
  14. /*
  15. * DEFINE_CRC32_VX() - Define a CRC-32 function using the vector extension
  16. *
  17. * Creates a function to perform a particular CRC-32 computation. Depending
  18. * on the message buffer, the hardware-accelerated or software implementation
  19. * is used. Note that the message buffer is aligned to improve fetch
  20. * operations of VECTOR LOAD MULTIPLE instructions.
  21. */
  22. #define DEFINE_CRC32_VX(___fname, ___crc32_vx, ___crc32_sw) \
  23. static inline u32 ___fname(u32 crc, const u8 *data, size_t datalen) \
  24. { \
  25. unsigned long prealign, aligned, remaining; \
  26. DECLARE_KERNEL_FPU_ONSTACK16(vxstate); \
  27. \
  28. if (datalen < VX_MIN_LEN + VX_ALIGN_MASK || !cpu_has_vx()) \
  29. return ___crc32_sw(crc, data, datalen); \
  30. \
  31. if ((unsigned long)data & VX_ALIGN_MASK) { \
  32. prealign = VX_ALIGNMENT - \
  33. ((unsigned long)data & VX_ALIGN_MASK); \
  34. datalen -= prealign; \
  35. crc = ___crc32_sw(crc, data, prealign); \
  36. data = (void *)((unsigned long)data + prealign); \
  37. } \
  38. \
  39. aligned = datalen & ~VX_ALIGN_MASK; \
  40. remaining = datalen & VX_ALIGN_MASK; \
  41. \
  42. kernel_fpu_begin(&vxstate, KERNEL_VXR_LOW); \
  43. crc = ___crc32_vx(crc, data, aligned); \
  44. kernel_fpu_end(&vxstate, KERNEL_VXR_LOW); \
  45. \
  46. if (remaining) \
  47. crc = ___crc32_sw(crc, data + aligned, remaining); \
  48. \
  49. return crc; \
  50. }
  51. DEFINE_CRC32_VX(crc32_le_arch, crc32_le_vgfm_16, crc32_le_base)
  52. DEFINE_CRC32_VX(crc32_be_arch, crc32_be_vgfm_16, crc32_be_base)
  53. DEFINE_CRC32_VX(crc32c_arch, crc32c_le_vgfm_16, crc32c_base)
  54. static inline u32 crc32_optimizations_arch(void)
  55. {
  56. if (cpu_has_vx()) {
  57. return CRC32_LE_OPTIMIZATION |
  58. CRC32_BE_OPTIMIZATION |
  59. CRC32C_OPTIMIZATION;
  60. }
  61. return 0;
  62. }