Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ath9k: export HW random number generator

We measured the FFT-based entropy in 3 ways, Shannon entropy,
collision entropy, and directly measured min-entropy. Just to
be conservative, we recommend the estimated min-Entropy to be
10 bits per 16-bit value.

Analysis was done by Jacobson,David(djacobso@qti.qualcomm.com).

Signed-off-by: Miaoqing Pan <miaoqing@qca.qualcomm.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>

authored by

Miaoqing Pan and committed by
Kalle Valo
6301566e fa5b8c8a

+110
+7
drivers/net/wireless/ath/ath9k/Kconfig
··· 176 176 depends on ATH9K_HTC && DEBUG_FS 177 177 ---help--- 178 178 Say Y, if you need access to ath9k_htc's statistics. 179 + 180 + config ATH9K_HWRNG 181 + bool "Random number generator support" 182 + depends on ATH9K && (HW_RANDOM = y || HW_RANDOM = ATH9K) 183 + default y 184 + ---help--- 185 + Provides a hardware random number generator to the kernel.
+1
drivers/net/wireless/ath/ath9k/Makefile
··· 15 15 ath9k-$(CONFIG_ATH9K_DFS_CERTIFIED) += dfs.o 16 16 ath9k-$(CONFIG_ATH9K_TX99) += tx99.o 17 17 ath9k-$(CONFIG_ATH9K_WOW) += wow.o 18 + ath9k-$(CONFIG_ATH9K_HWRNG) += rng.o 18 19 19 20 ath9k-$(CONFIG_ATH9K_DEBUGFS) += debug.o 20 21
+23
drivers/net/wireless/ath/ath9k/ath9k.h
··· 23 23 #include <linux/leds.h> 24 24 #include <linux/completion.h> 25 25 #include <linux/time.h> 26 + #include <linux/hw_random.h> 26 27 27 28 #include "common.h" 28 29 #include "debug.h" ··· 1042 1041 u32 wow_intr_before_sleep; 1043 1042 bool force_wow; 1044 1043 #endif 1044 + 1045 + #ifdef CONFIG_ATH9K_HWRNG 1046 + struct hwrng rng; 1047 + bool rng_initialized; 1048 + u32 rng_last; 1049 + #endif 1045 1050 }; 1046 1051 1047 1052 /********/ ··· 1069 1062 return 0; 1070 1063 } 1071 1064 #endif /* CONFIG_ATH9K_TX99 */ 1065 + 1066 + /***************************/ 1067 + /* Random Number Generator */ 1068 + /***************************/ 1069 + #ifdef CONFIG_ATH9K_HWRNG 1070 + void ath9k_rng_register(struct ath_softc *sc); 1071 + void ath9k_rng_unregister(struct ath_softc *sc); 1072 + #else 1073 + static inline void ath9k_rng_register(struct ath_softc *sc) 1074 + { 1075 + } 1076 + 1077 + static inline void ath9k_rng_unregister(struct ath_softc *sc) 1078 + { 1079 + } 1080 + #endif 1072 1081 1073 1082 static inline void ath_read_cachesize(struct ath_common *common, int *csz) 1074 1083 {
+4
drivers/net/wireless/ath/ath9k/main.c
··· 739 739 740 740 ath9k_ps_restore(sc); 741 741 742 + ath9k_rng_register(sc); 743 + 742 744 return 0; 743 745 } 744 746 ··· 829 827 bool prev_idle; 830 828 831 829 ath9k_deinit_channel_context(sc); 830 + 831 + ath9k_rng_unregister(sc); 832 832 833 833 mutex_lock(&sc->mutex); 834 834
+75
drivers/net/wireless/ath/ath9k/rng.c
··· 1 + /* 2 + * Copyright (c) 2015 Qualcomm Atheros, Inc. 3 + * 4 + * Permission to use, copy, modify, and/or distribute this software for any 5 + * purpose with or without fee is hereby granted, provided that the above 6 + * copyright notice and this permission notice appear in all copies. 7 + * 8 + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 + */ 16 + 17 + #include "ath9k.h" 18 + #include "hw.h" 19 + #include "ar9003_phy.h" 20 + 21 + static int ath9k_rng_data_read(struct hwrng *rng, u32 *data) 22 + { 23 + u32 v1, v2; 24 + struct ath_softc *sc = (struct ath_softc *)rng->priv; 25 + struct ath_hw *ah = sc->sc_ah; 26 + 27 + ath9k_ps_wakeup(sc); 28 + 29 + REG_RMW_FIELD(ah, AR_PHY_TEST, AR_PHY_TEST_BBB_OBS_SEL, 5); 30 + REG_CLR_BIT(ah, AR_PHY_TEST, AR_PHY_TEST_RX_OBS_SEL_BIT5); 31 + REG_RMW_FIELD(ah, AR_PHY_TEST_CTL_STATUS, AR_PHY_TEST_CTL_RX_OBS_SEL, 0); 32 + 33 + v1 = REG_READ(ah, AR_PHY_TST_ADC); 34 + v2 = REG_READ(ah, AR_PHY_TST_ADC); 35 + 36 + ath9k_ps_restore(sc); 37 + 38 + /* wait for data ready */ 39 + if (v1 && v2 && sc->rng_last != v1 && v1 != v2) { 40 + *data = (v1 & 0xffff) | (v2 << 16); 41 + sc->rng_last = v2; 42 + 43 + return sizeof(u32); 44 + } 45 + 46 + sc->rng_last = v2; 47 + 48 + return 0; 49 + } 50 + 51 + void ath9k_rng_register(struct ath_softc *sc) 52 + { 53 + struct ath_hw *ah = sc->sc_ah; 54 + 55 + if (WARN_ON(sc->rng_initialized)) 56 + return; 57 + 58 + if (!AR_SREV_9300_20_OR_LATER(ah)) 59 + return; 60 + 61 + sc->rng.name = "ath9k"; 62 + sc->rng.data_read = ath9k_rng_data_read; 63 + sc->rng.priv = (unsigned long)sc; 64 + 65 + if (!hwrng_register(&sc->rng)) 66 + sc->rng_initialized = true; 67 + } 68 + 69 + void ath9k_rng_unregister(struct ath_softc *sc) 70 + { 71 + if (sc->rng_initialized) { 72 + hwrng_unregister(&sc->rng); 73 + sc->rng_initialized = false; 74 + } 75 + }