Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

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