VisionFive2 Linux kernel

StarFive Tech Linux Kernel for VisionFive (JH7110) boards (mirror)

More than 9999 Commits   32 Branches   54 Tags
40b0b3f8fb2d8 (Thomas Gleixner    2019-06-03 07:44:46 +0200   1) // SPDX-License-Identifier: GPL-2.0-only
f11f594edba7f (Martin K. Petersen 2008-06-25 11:22:42 -0400   2) /*
f11f594edba7f (Martin K. Petersen 2008-06-25 11:22:42 -0400   3)  * T10 Data Integrity Field CRC16 calculation
f11f594edba7f (Martin K. Petersen 2008-06-25 11:22:42 -0400   4)  *
f11f594edba7f (Martin K. Petersen 2008-06-25 11:22:42 -0400   5)  * Copyright (c) 2007 Oracle Corporation.  All rights reserved.
f11f594edba7f (Martin K. Petersen 2008-06-25 11:22:42 -0400   6)  * Written by Martin K. Petersen <martin.petersen@oracle.com>
f11f594edba7f (Martin K. Petersen 2008-06-25 11:22:42 -0400   7)  */
f11f594edba7f (Martin K. Petersen 2008-06-25 11:22:42 -0400   8) 
f11f594edba7f (Martin K. Petersen 2008-06-25 11:22:42 -0400   9) #include <linux/types.h>
f11f594edba7f (Martin K. Petersen 2008-06-25 11:22:42 -0400  10) #include <linux/module.h>
f11f594edba7f (Martin K. Petersen 2008-06-25 11:22:42 -0400  11) #include <linux/crc-t10dif.h>
68411521cc605 (Herbert Xu         2013-09-07 12:56:26 +1000  12) #include <linux/err.h>
68411521cc605 (Herbert Xu         2013-09-07 12:56:26 +1000  13) #include <linux/init.h>
68411521cc605 (Herbert Xu         2013-09-07 12:56:26 +1000  14) #include <crypto/hash.h>
b76377543b738 (Martin K. Petersen 2018-08-30 11:00:15 -0400  15) #include <crypto/algapi.h>
26052f9b9bb8d (Herbert Xu         2013-09-12 15:31:34 +1000  16) #include <linux/static_key.h>
b76377543b738 (Martin K. Petersen 2018-08-30 11:00:15 -0400  17) #include <linux/notifier.h>
f11f594edba7f (Martin K. Petersen 2008-06-25 11:22:42 -0400  18) 
b76377543b738 (Martin K. Petersen 2018-08-30 11:00:15 -0400  19) static struct crypto_shash __rcu *crct10dif_tfm;
be924e0aaa315 (Eric Biggers       2020-06-09 23:39:42 -0700  20) static DEFINE_STATIC_KEY_TRUE(crct10dif_fallback);
a7e7edfea23fa (kbuild test robot  2018-09-05 01:52:44 +0800  21) static DEFINE_MUTEX(crc_t10dif_mutex);
3906f640224db (Herbert Xu         2020-06-05 16:59:18 +1000  22) static struct work_struct crct10dif_rehash_work;
b76377543b738 (Martin K. Petersen 2018-08-30 11:00:15 -0400  23) 
3906f640224db (Herbert Xu         2020-06-05 16:59:18 +1000  24) static int crc_t10dif_notify(struct notifier_block *self, unsigned long val, void *data)
b76377543b738 (Martin K. Petersen 2018-08-30 11:00:15 -0400  25) {
b76377543b738 (Martin K. Petersen 2018-08-30 11:00:15 -0400  26) 	struct crypto_alg *alg = data;
b76377543b738 (Martin K. Petersen 2018-08-30 11:00:15 -0400  27) 
b76377543b738 (Martin K. Petersen 2018-08-30 11:00:15 -0400  28) 	if (val != CRYPTO_MSG_ALG_LOADED ||
29195232fa2f7 (Eric Biggers       2020-06-09 23:39:43 -0700  29) 	    strcmp(alg->cra_name, CRC_T10DIF_STRING))
29195232fa2f7 (Eric Biggers       2020-06-09 23:39:43 -0700  30) 		return NOTIFY_DONE;
b76377543b738 (Martin K. Petersen 2018-08-30 11:00:15 -0400  31) 
3906f640224db (Herbert Xu         2020-06-05 16:59:18 +1000  32) 	schedule_work(&crct10dif_rehash_work);
29195232fa2f7 (Eric Biggers       2020-06-09 23:39:43 -0700  33) 	return NOTIFY_OK;
3906f640224db (Herbert Xu         2020-06-05 16:59:18 +1000  34) }
3906f640224db (Herbert Xu         2020-06-05 16:59:18 +1000  35) 
3906f640224db (Herbert Xu         2020-06-05 16:59:18 +1000  36) static void crc_t10dif_rehash(struct work_struct *work)
3906f640224db (Herbert Xu         2020-06-05 16:59:18 +1000  37) {
3906f640224db (Herbert Xu         2020-06-05 16:59:18 +1000  38) 	struct crypto_shash *new, *old;
3906f640224db (Herbert Xu         2020-06-05 16:59:18 +1000  39) 
b76377543b738 (Martin K. Petersen 2018-08-30 11:00:15 -0400  40) 	mutex_lock(&crc_t10dif_mutex);
b76377543b738 (Martin K. Petersen 2018-08-30 11:00:15 -0400  41) 	old = rcu_dereference_protected(crct10dif_tfm,
b76377543b738 (Martin K. Petersen 2018-08-30 11:00:15 -0400  42) 					lockdep_is_held(&crc_t10dif_mutex));
29195232fa2f7 (Eric Biggers       2020-06-09 23:39:43 -0700  43) 	new = crypto_alloc_shash(CRC_T10DIF_STRING, 0, 0);
b76377543b738 (Martin K. Petersen 2018-08-30 11:00:15 -0400  44) 	if (IS_ERR(new)) {
b76377543b738 (Martin K. Petersen 2018-08-30 11:00:15 -0400  45) 		mutex_unlock(&crc_t10dif_mutex);
3906f640224db (Herbert Xu         2020-06-05 16:59:18 +1000  46) 		return;
b76377543b738 (Martin K. Petersen 2018-08-30 11:00:15 -0400  47) 	}
b76377543b738 (Martin K. Petersen 2018-08-30 11:00:15 -0400  48) 	rcu_assign_pointer(crct10dif_tfm, new);
b76377543b738 (Martin K. Petersen 2018-08-30 11:00:15 -0400  49) 	mutex_unlock(&crc_t10dif_mutex);
b76377543b738 (Martin K. Petersen 2018-08-30 11:00:15 -0400  50) 
be924e0aaa315 (Eric Biggers       2020-06-09 23:39:42 -0700  51) 	if (old) {
be924e0aaa315 (Eric Biggers       2020-06-09 23:39:42 -0700  52) 		synchronize_rcu();
be924e0aaa315 (Eric Biggers       2020-06-09 23:39:42 -0700  53) 		crypto_free_shash(old);
be924e0aaa315 (Eric Biggers       2020-06-09 23:39:42 -0700  54) 	} else {
be924e0aaa315 (Eric Biggers       2020-06-09 23:39:42 -0700  55) 		static_branch_disable(&crct10dif_fallback);
be924e0aaa315 (Eric Biggers       2020-06-09 23:39:42 -0700  56) 	}
b76377543b738 (Martin K. Petersen 2018-08-30 11:00:15 -0400  57) }
b76377543b738 (Martin K. Petersen 2018-08-30 11:00:15 -0400  58) 
b76377543b738 (Martin K. Petersen 2018-08-30 11:00:15 -0400  59) static struct notifier_block crc_t10dif_nb = {
3906f640224db (Herbert Xu         2020-06-05 16:59:18 +1000  60) 	.notifier_call = crc_t10dif_notify,
b76377543b738 (Martin K. Petersen 2018-08-30 11:00:15 -0400  61) };
f11f594edba7f (Martin K. Petersen 2008-06-25 11:22:42 -0400  62) 
10081fb532a2a (Akinobu Mita       2015-05-01 15:23:50 +0900  63) __u16 crc_t10dif_update(__u16 crc, const unsigned char *buffer, size_t len)
f11f594edba7f (Martin K. Petersen 2008-06-25 11:22:42 -0400  64) {
68411521cc605 (Herbert Xu         2013-09-07 12:56:26 +1000  65) 	struct {
68411521cc605 (Herbert Xu         2013-09-07 12:56:26 +1000  66) 		struct shash_desc shash;
29195232fa2f7 (Eric Biggers       2020-06-09 23:39:43 -0700  67) 		__u16 crc;
68411521cc605 (Herbert Xu         2013-09-07 12:56:26 +1000  68) 	} desc;
68411521cc605 (Herbert Xu         2013-09-07 12:56:26 +1000  69) 	int err;
68411521cc605 (Herbert Xu         2013-09-07 12:56:26 +1000  70) 
be924e0aaa315 (Eric Biggers       2020-06-09 23:39:42 -0700  71) 	if (static_branch_unlikely(&crct10dif_fallback))
10081fb532a2a (Akinobu Mita       2015-05-01 15:23:50 +0900  72) 		return crc_t10dif_generic(crc, buffer, len);
26052f9b9bb8d (Herbert Xu         2013-09-12 15:31:34 +1000  73) 
b76377543b738 (Martin K. Petersen 2018-08-30 11:00:15 -0400  74) 	rcu_read_lock();
b76377543b738 (Martin K. Petersen 2018-08-30 11:00:15 -0400  75) 	desc.shash.tfm = rcu_dereference(crct10dif_tfm);
29195232fa2f7 (Eric Biggers       2020-06-09 23:39:43 -0700  76) 	desc.crc = crc;
68411521cc605 (Herbert Xu         2013-09-07 12:56:26 +1000  77) 	err = crypto_shash_update(&desc.shash, buffer, len);
b76377543b738 (Martin K. Petersen 2018-08-30 11:00:15 -0400  78) 	rcu_read_unlock();
b76377543b738 (Martin K. Petersen 2018-08-30 11:00:15 -0400  79) 
68411521cc605 (Herbert Xu         2013-09-07 12:56:26 +1000  80) 	BUG_ON(err);
f11f594edba7f (Martin K. Petersen 2008-06-25 11:22:42 -0400  81) 
29195232fa2f7 (Eric Biggers       2020-06-09 23:39:43 -0700  82) 	return desc.crc;
f11f594edba7f (Martin K. Petersen 2008-06-25 11:22:42 -0400  83) }
10081fb532a2a (Akinobu Mita       2015-05-01 15:23:50 +0900  84) EXPORT_SYMBOL(crc_t10dif_update);
10081fb532a2a (Akinobu Mita       2015-05-01 15:23:50 +0900  85) 
10081fb532a2a (Akinobu Mita       2015-05-01 15:23:50 +0900  86) __u16 crc_t10dif(const unsigned char *buffer, size_t len)
10081fb532a2a (Akinobu Mita       2015-05-01 15:23:50 +0900  87) {
10081fb532a2a (Akinobu Mita       2015-05-01 15:23:50 +0900  88) 	return crc_t10dif_update(0, buffer, len);
10081fb532a2a (Akinobu Mita       2015-05-01 15:23:50 +0900  89) }
f11f594edba7f (Martin K. Petersen 2008-06-25 11:22:42 -0400  90) EXPORT_SYMBOL(crc_t10dif);
f11f594edba7f (Martin K. Petersen 2008-06-25 11:22:42 -0400  91) 
68411521cc605 (Herbert Xu         2013-09-07 12:56:26 +1000  92) static int __init crc_t10dif_mod_init(void)
68411521cc605 (Herbert Xu         2013-09-07 12:56:26 +1000  93) {
3906f640224db (Herbert Xu         2020-06-05 16:59:18 +1000  94) 	INIT_WORK(&crct10dif_rehash_work, crc_t10dif_rehash);
b76377543b738 (Martin K. Petersen 2018-08-30 11:00:15 -0400  95) 	crypto_register_notifier(&crc_t10dif_nb);
be924e0aaa315 (Eric Biggers       2020-06-09 23:39:42 -0700  96) 	crc_t10dif_rehash(&crct10dif_rehash_work);
26052f9b9bb8d (Herbert Xu         2013-09-12 15:31:34 +1000  97) 	return 0;
68411521cc605 (Herbert Xu         2013-09-07 12:56:26 +1000  98) }
68411521cc605 (Herbert Xu         2013-09-07 12:56:26 +1000  99) 
68411521cc605 (Herbert Xu         2013-09-07 12:56:26 +1000 100) static void __exit crc_t10dif_mod_fini(void)
68411521cc605 (Herbert Xu         2013-09-07 12:56:26 +1000 101) {
b76377543b738 (Martin K. Petersen 2018-08-30 11:00:15 -0400 102) 	crypto_unregister_notifier(&crc_t10dif_nb);
3906f640224db (Herbert Xu         2020-06-05 16:59:18 +1000 103) 	cancel_work_sync(&crct10dif_rehash_work);
3906f640224db (Herbert Xu         2020-06-05 16:59:18 +1000 104) 	crypto_free_shash(rcu_dereference_protected(crct10dif_tfm, 1));
68411521cc605 (Herbert Xu         2013-09-07 12:56:26 +1000 105) }
68411521cc605 (Herbert Xu         2013-09-07 12:56:26 +1000 106) 
68411521cc605 (Herbert Xu         2013-09-07 12:56:26 +1000 107) module_init(crc_t10dif_mod_init);
68411521cc605 (Herbert Xu         2013-09-07 12:56:26 +1000 108) module_exit(crc_t10dif_mod_fini);
68411521cc605 (Herbert Xu         2013-09-07 12:56:26 +1000 109) 
11dcb1037f40a (Martin K. Petersen 2018-08-30 11:00:16 -0400 110) static int crc_t10dif_transform_show(char *buffer, const struct kernel_param *kp)
11dcb1037f40a (Martin K. Petersen 2018-08-30 11:00:16 -0400 111) {
3906f640224db (Herbert Xu         2020-06-05 16:59:18 +1000 112) 	struct crypto_shash *tfm;
3906f640224db (Herbert Xu         2020-06-05 16:59:18 +1000 113) 	int len;
3906f640224db (Herbert Xu         2020-06-05 16:59:18 +1000 114) 
be924e0aaa315 (Eric Biggers       2020-06-09 23:39:42 -0700 115) 	if (static_branch_unlikely(&crct10dif_fallback))
11dcb1037f40a (Martin K. Petersen 2018-08-30 11:00:16 -0400 116) 		return sprintf(buffer, "fallback\n");
11dcb1037f40a (Martin K. Petersen 2018-08-30 11:00:16 -0400 117) 
3906f640224db (Herbert Xu         2020-06-05 16:59:18 +1000 118) 	rcu_read_lock();
3906f640224db (Herbert Xu         2020-06-05 16:59:18 +1000 119) 	tfm = rcu_dereference(crct10dif_tfm);
29195232fa2f7 (Eric Biggers       2020-06-09 23:39:43 -0700 120) 	len = snprintf(buffer, PAGE_SIZE, "%s\n",
29195232fa2f7 (Eric Biggers       2020-06-09 23:39:43 -0700 121) 		       crypto_shash_driver_name(tfm));
3906f640224db (Herbert Xu         2020-06-05 16:59:18 +1000 122) 	rcu_read_unlock();
3906f640224db (Herbert Xu         2020-06-05 16:59:18 +1000 123) 
3906f640224db (Herbert Xu         2020-06-05 16:59:18 +1000 124) 	return len;
11dcb1037f40a (Martin K. Petersen 2018-08-30 11:00:16 -0400 125) }
11dcb1037f40a (Martin K. Petersen 2018-08-30 11:00:16 -0400 126) 
29195232fa2f7 (Eric Biggers       2020-06-09 23:39:43 -0700 127) module_param_call(transform, NULL, crc_t10dif_transform_show, NULL, 0444);
11dcb1037f40a (Martin K. Petersen 2018-08-30 11:00:16 -0400 128) 
29195232fa2f7 (Eric Biggers       2020-06-09 23:39:43 -0700 129) MODULE_DESCRIPTION("T10 DIF CRC calculation (library API)");
f11f594edba7f (Martin K. Petersen 2008-06-25 11:22:42 -0400 130) MODULE_LICENSE("GPL");
68411521cc605 (Herbert Xu         2013-09-07 12:56:26 +1000 131) MODULE_SOFTDEP("pre: crct10dif");