rng.c (3151B)
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 <linux/hw_random.h> 18#include <linux/kthread.h> 19 20#include "ath9k.h" 21#include "hw.h" 22#include "ar9003_phy.h" 23 24static int ath9k_rng_data_read(struct ath_softc *sc, u32 *buf, u32 buf_size) 25{ 26 int i, j; 27 u32 v1, v2, rng_last = sc->rng_last; 28 struct ath_hw *ah = sc->sc_ah; 29 30 ath9k_ps_wakeup(sc); 31 32 REG_RMW_FIELD(ah, AR_PHY_TEST, AR_PHY_TEST_BBB_OBS_SEL, 1); 33 REG_CLR_BIT(ah, AR_PHY_TEST, AR_PHY_TEST_RX_OBS_SEL_BIT5); 34 REG_RMW_FIELD(ah, AR_PHY_TEST_CTL_STATUS, AR_PHY_TEST_CTL_RX_OBS_SEL, 0); 35 36 for (i = 0, j = 0; i < buf_size; i++) { 37 v1 = REG_READ(ah, AR_PHY_TST_ADC) & 0xffff; 38 v2 = REG_READ(ah, AR_PHY_TST_ADC) & 0xffff; 39 40 /* wait for data ready */ 41 if (v1 && v2 && rng_last != v1 && v1 != v2 && v1 != 0xffff && 42 v2 != 0xffff) 43 buf[j++] = (v1 << 16) | v2; 44 45 rng_last = v2; 46 } 47 48 ath9k_ps_restore(sc); 49 50 sc->rng_last = rng_last; 51 52 return j << 2; 53} 54 55static u32 ath9k_rng_delay_get(u32 fail_stats) 56{ 57 u32 delay; 58 59 if (fail_stats < 100) 60 delay = 10; 61 else if (fail_stats < 105) 62 delay = 1000; 63 else 64 delay = 10000; 65 66 return delay; 67} 68 69static int ath9k_rng_read(struct hwrng *rng, void *buf, size_t max, bool wait) 70{ 71 struct ath_softc *sc = container_of(rng, struct ath_softc, rng_ops); 72 u32 fail_stats = 0, word; 73 int bytes_read = 0; 74 75 for (;;) { 76 if (max & ~3UL) 77 bytes_read = ath9k_rng_data_read(sc, buf, max >> 2); 78 if ((max & 3UL) && ath9k_rng_data_read(sc, &word, 1)) { 79 memcpy(buf + bytes_read, &word, max & 3UL); 80 bytes_read += max & 3UL; 81 memzero_explicit(&word, sizeof(word)); 82 } 83 if (!wait || !max || likely(bytes_read) || fail_stats > 110) 84 break; 85 86 msleep_interruptible(ath9k_rng_delay_get(++fail_stats)); 87 } 88 89 if (wait && !bytes_read && max) 90 bytes_read = -EIO; 91 return bytes_read; 92} 93 94void ath9k_rng_start(struct ath_softc *sc) 95{ 96 static atomic_t serial = ATOMIC_INIT(0); 97 struct ath_hw *ah = sc->sc_ah; 98 99 if (sc->rng_ops.read) 100 return; 101 102 if (!AR_SREV_9300_20_OR_LATER(ah)) 103 return; 104 105 snprintf(sc->rng_name, sizeof(sc->rng_name), "ath9k_%u", 106 (atomic_inc_return(&serial) - 1) & U16_MAX); 107 sc->rng_ops.name = sc->rng_name; 108 sc->rng_ops.read = ath9k_rng_read; 109 sc->rng_ops.quality = 320; 110 111 if (devm_hwrng_register(sc->dev, &sc->rng_ops)) 112 sc->rng_ops.read = NULL; 113} 114 115void ath9k_rng_stop(struct ath_softc *sc) 116{ 117 if (sc->rng_ops.read) { 118 devm_hwrng_unregister(sc->dev, &sc->rng_ops); 119 sc->rng_ops.read = NULL; 120 } 121}