Hi Felix,

I have a question about https://dev.openwrt.org/changeset/38486. While 
backporting the aforementioned patch from trunk to attitude adjustment, I 
noticed that the patch does not include a gettor function for the adc entropy 
of the ar9002 chip, only those of ar5008 and ar9003.

static void ar9003_hw_get_adc_entropy(struct ath_hw *ah, u8 *buf, size_t len)
static void ar5008_hw_get_adc_entropy(struct ath_hw *ah, u8 *buf, size_t len)

but no

static void ar9002_hw_get_adc_entropy(struct ath_hw *ah, u8 *buf, size_t len)

Furthermore, when the phy_ops are constructed in ar9002_hw_attach_phy_ops, the 
get_adc_entropy function pointer is never assigned.

I can be wrong ofcourse, but am under the impression this will create a 
problem when the driver is probed for an ar9002 chip and possibly result in a 
kernel oops, because "ath9k_hw_get_adc_entropy" expects the ath_hw struct to 
have a valid (non-NULL) function pointer for get_adc_entropy. See below:

static inline void ath9k_hw_get_adc_entropy(struct ath_hw *ah,
               u8 *buf, size_t len)
{
       ath9k_hw_ops(ah)->get_adc_entropy(ah, buf, len);
}

Did changes in ar9002_phy.c somehow miss inclusion in the patch?

When testing the backported patch for my ar9003 chip, I was confronted with a 
kernel oops at initialisation, which I narrowed down to ath9k_hw_reset 
function, called from ath_get_initial_entropy, where the channels in 
ieee80211_conf data field in common hardware config are not yet initialised it 
seems. I changed the condition to verify for a valid pointer before 
dereferencing it, which seems to solve the problem.
This is different in the mac82011 version from trunk (compat-
wireless-2013-11-05), where channelFlags from channel are used in the 
condition, which is an u32, and thus can not result in a null pointer 
dereference. My question now is, although the fix seems sufficient, is it also 
correct/expected behaviour?

This is the backport of the patch thus far. I included the changes for the 
ar9002 chip. I would expect the implementation for get_adc_entropy for ar9002 
to be close(r) to ar9003, but since ar5008 depends on defines from 
ar9002_phy.h and the latter are missing those from ar9003_phy.h, I copied the 
implementation for ar5008 to ar9002, which may be very wrong ofcourse 
(untested, as I have no ar9002 chip). The patch/driver does work for me now 
(char buf being filled with entropy).

Signed-off-by: Tijs Van Buggenhout <t...@able.be>
--

diff -u -Naur a/drivers/net/wireless/ath/ath9k/hw.h 
b/drivers/net/wireless/ath/ath9k/hw.h
--- a/drivers/net/wireless/ath/ath9k/hw.h       2013-10-28 18:00:58.000000000 
+0100
+++ b/drivers/net/wireless/ath/ath9k/hw.h       2013-11-19 13:32:56.000000000 
+0100
@@ -700,6 +700,7 @@
  * @config_pci_powersave:
  * @calibrate: periodic calibration for NF, ANI, IQ, ADC gain, ADC-DC
  *
+ * @get_adc_entropy: get entropy from the raw ADC I/Q output
  * @spectral_scan_config: set parameters for spectral scan and enable/disable 
it
  * @spectral_scan_trigger: trigger a spectral scan run
  * @spectral_scan_wait: wait for a spectral scan run to finish
@@ -722,6 +723,7 @@
                        struct ath_hw_antcomb_conf *antconf);
        void (*antdiv_comb_conf_set)(struct ath_hw *ah,
                        struct ath_hw_antcomb_conf *antconf);
+       void (*get_adc_entropy)(struct ath_hw *ah, u8 *buf, size_t len);
        void (*antctrl_shared_chain_lnadiv)(struct ath_hw *hw, bool enable);
        void (*spectral_scan_config)(struct ath_hw *ah,
                                     struct ath_spec_scan *param);
diff -u -Naur a/drivers/net/wireless/ath/ath9k/hw.c 
b/drivers/net/wireless/ath/ath9k/hw.c
--- a/drivers/net/wireless/ath/ath9k/hw.c       2013-10-28 18:00:58.000000000 
+0100
+++ b/drivers/net/wireless/ath/ath9k/hw.c       2013-12-05 21:05:25.000000000 
+0100
@@ -131,8 +131,8 @@
 
 static void ath9k_hw_set_clockrate(struct ath_hw *ah)
 {
-       struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf;
        struct ath_common *common = ath9k_hw_common(ah);
+       struct ieee80211_conf *conf = &common->hw->conf;
        unsigned int clockrate;
 
        /* AR9287 v1.3+ uses async FIFO and runs the MAC at 117 MHz */
@@ -140,7 +140,7 @@
                clockrate = 117;
        else if (!ah->curchan) /* should really check for CCK instead */
                clockrate = ATH9K_CLOCK_RATE_CCK;
-       else if (conf->chandef.chan->band == IEEE80211_BAND_2GHZ)
+       else if (conf->chandef.chan && conf->chandef.chan->band == 
IEEE80211_BAND_2GHZ)
                clockrate = ATH9K_CLOCK_RATE_2GHZ_OFDM;
        else if (ah->caps.hw_caps & ATH9K_HW_CAP_FASTCLOCK)
                clockrate = ATH9K_CLOCK_FAST_RATE_5GHZ_OFDM;

diff -u -Naur a/drivers/net/wireless/ath/ath9k/ar9003_phy.c 
b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c       2013-10-28 
18:00:58.000000000 +0100
+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c       2013-12-05 
19:09:34.000000000 +0100
@@ -1603,6 +1603,26 @@
        }
 }
 
+static void ar9003_hw_get_adc_entropy(struct ath_hw *ah, u8 *buf, size_t len)
+{
+       int i, j;
+
+       REG_RMW_FIELD(ah, AR_PHY_TEST, AR_PHY_TEST_BBB_OBS_SEL, 1);
+       REG_CLR_BIT(ah, AR_PHY_TEST, AR_PHY_TEST_RX_OBS_SEL_BIT5);
+       REG_RMW_FIELD(ah, AR_PHY_TEST_CTL_STATUS, AR_PHY_TEST_CTL_RX_OBS_SEL, 
0);
+
+       memset(buf, 0, len);
+       for (i = 0; i < len; i++) {
+               for (j = 0; j < 4; j++) {
+                       u32 regval = REG_READ(ah, AR_PHY_TST_ADC);
+
+                       buf[i] <<= 2;
+                       buf[i] |= (regval & 1) | ((regval & BIT(10)) >> 9);
+                       udelay(1);
+               }
+       }
+}
+
 void ar9003_hw_attach_phy_ops(struct ath_hw *ah)
 {
        struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
@@ -1633,6 +1653,7 @@
        priv_ops->set_radar_params = ar9003_hw_set_radar_params;
        priv_ops->fast_chan_change = ar9003_hw_fast_chan_change;
 
+       ops->get_adc_entropy = ar9003_hw_get_adc_entropy;
        ops->antdiv_comb_conf_get = ar9003_hw_antdiv_comb_conf_get;
        ops->antdiv_comb_conf_set = ar9003_hw_antdiv_comb_conf_set;
        ops->antctrl_shared_chain_lnadiv = 
ar9003_hw_antctrl_shared_chain_lnadiv;
diff -u -Naur a/drivers/net/wireless/ath/ath9k/init.c 
b/drivers/net/wireless/ath/ath9k/init.c
--- a/drivers/net/wireless/ath/ath9k/init.c     2013-10-28 18:00:58.000000000 
+0100
+++ b/drivers/net/wireless/ath/ath9k/init.c     2013-12-05 21:09:13.000000000 
+0100
@@ -735,7 +735,8 @@
        if (ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
                ath9k_init_band_txpower(sc, IEEE80211_BAND_5GHZ);
 
-       ah->curchan = curchan;
+       if (curchan)
+               ah->curchan = curchan;
 }
 
 void ath9k_reload_chainmask_settings(struct ath_softc *sc)
@@ -880,6 +881,18 @@
        SET_IEEE80211_PERM_ADDR(hw, common->macaddr);
 }
 
+static void ath_get_initial_entropy(struct ath_softc *sc)
+{
+       struct ath_hw *ah = sc->sc_ah;
+       char buf[256];
+
+       /* reuse last channel initialized by the tx power test */
+       ath9k_hw_reset(ah, ah->curchan, NULL, false);
+
+       ath9k_hw_get_adc_entropy(ah, buf, sizeof(buf));
+       add_device_randomness(buf, sizeof(buf));
+}
+
 int ath9k_init_device(u16 devid, struct ath_softc *sc,
                    const struct ath_bus_ops *bus_ops)
 {
@@ -925,6 +938,8 @@
                ARRAY_SIZE(ath9k_tpt_blink));
 #endif
 
+       ath_get_initial_entropy(sc);
+
        /* Register with mac80211 */
        error = ieee80211_register_hw(hw);
        if (error)
diff -u -Naur a/drivers/net/wireless/ath/ath9k/hw-ops.h 
b/drivers/net/wireless/ath/ath9k/hw-ops.h
--- a/drivers/net/wireless/ath/ath9k/hw-ops.h   2013-06-30 16:34:53.000000000 
+0200
+++ b/drivers/net/wireless/ath/ath9k/hw-ops.h   2013-11-19 13:34:39.000000000 
+0100
@@ -78,6 +78,12 @@
        ath9k_hw_ops(ah)->antdiv_comb_conf_set(ah, antconf);
 }
 
+static inline void ath9k_hw_get_adc_entropy(struct ath_hw *ah,
+               u8 *buf, size_t len)
+{
+       ath9k_hw_ops(ah)->get_adc_entropy(ah, buf, len);
+}
+
 static inline void ath9k_hw_antctrl_shared_chain_lnadiv(struct ath_hw *ah,
                                                        bool enable)
 {
diff -u -Naur a/drivers/net/wireless/ath/ath9k/link.c 
b/drivers/net/wireless/ath/ath9k/link.c
--- a/drivers/net/wireless/ath/ath9k/link.c     2013-06-30 16:34:53.000000000 
+0200
+++ b/drivers/net/wireless/ath/ath9k/link.c     2013-12-05 21:09:34.000000000 
+0100
@@ -342,6 +342,11 @@
        unsigned int timestamp = jiffies_to_msecs(jiffies);
        u32 cal_interval, short_cal_interval, long_cal_interval;
        unsigned long flags;
+       char buf[256];
+
+       /* gather entropy */
+       ath9k_hw_get_adc_entropy(ah, buf, sizeof(buf));
+       add_device_randomness(buf, sizeof(buf));
 
        if (ah->caldata && ah->caldata->nfcal_interference)
                long_cal_interval = ATH_LONG_CALINTERVAL_INT;diff -u -Naur 
a/drivers/net/wireless/ath/ath9k/ar5008_phy.c 
b/drivers/net/wireless/ath/ath9k/ar5008_phy.c
--- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c       2013-06-30 
16:34:53.000000000 +0200
+++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c       2013-12-05 
19:08:38.000000000 +0100
@@ -1310,9 +1310,30 @@
        conf->radar_inband = 8;
 }
 
+static void ar5008_hw_get_adc_entropy(struct ath_hw *ah, u8 *buf, size_t len)
+{
+       int i, j;
+
+       REG_RMW_FIELD(ah, AR_PHY_TEST, AR_PHY_TEST_BBB_OBS_SEL, 1);
+       REG_CLR_BIT(ah, AR_PHY_TEST, AR_PHY_TEST_RX_OBS_SEL_BIT5);
+       REG_RMW_FIELD(ah, AR_PHY_TEST2, AR_PHY_TEST2_RX_OBS_SEL, 0);
+
+       memset(buf, 0, len);
+       for (i = 0; i < len; i++) {
+               for (j = 0; j < 4; j++) {
+                       u32 regval = REG_READ(ah, AR_PHY_TST_ADC);
+
+                       buf[i] <<= 2;
+                       buf[i] |= (regval & 1) | ((regval & BIT(9)) >> 8);
+                       udelay(1);
+               }
+       }
+}
+
 int ar5008_hw_attach_phy_ops(struct ath_hw *ah)
 {
        struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
+       struct ath_hw_ops *ops = ath9k_hw_ops(ah);
        static const u32 ar5416_cca_regs[6] = {
                AR_PHY_CCA,
                AR_PHY_CH1_CCA,
@@ -1327,6 +1348,8 @@
        if (ret)
            return ret;
 
+       ops->get_adc_entropy = ar5008_hw_get_adc_entropy;
+
        priv_ops->rf_set_freq = ar5008_hw_set_channel;
        priv_ops->spur_mitigate_freq = ar5008_hw_spur_mitigate;
 
diff -u -Naur a/drivers/net/wireless/ath/ath9k/ar9002_phy.h 
b/drivers/net/wireless/ath/ath9k/ar9002_phy.h
--- a/drivers/net/wireless/ath/ath9k/ar9002_phy.h       2013-06-30 
16:34:53.000000000 +0200
+++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.h       2013-11-19 
13:32:00.000000000 +0100
@@ -20,6 +20,12 @@
 #define PHY_AGC_CLR             0x10000000
 #define RFSILENT_BB             0x00002000
 
+#define AR_PHY_TEST_BBB_OBS_SEL       0x780000
+#define AR_PHY_TEST_BBB_OBS_SEL_S     19
+
+#define AR_PHY_TEST_RX_OBS_SEL_BIT5_S 23
+#define AR_PHY_TEST_RX_OBS_SEL_BIT5   (1 << AR_PHY_TEST_RX_OBS_SEL_BIT5_S)
+
 #define AR_PHY_TURBO                0x9804
 #define AR_PHY_FC_TURBO_MODE        0x00000001
 #define AR_PHY_FC_TURBO_SHORT       0x00000002
@@ -36,6 +42,9 @@
 
 #define AR_PHY_TEST2                   0x9808
 
+#define AR_PHY_TEST2_RX_OBS_SEL        0x3C00
+#define AR_PHY_TEST2_RX_OBS_SEL_S      10
+
 #define AR_PHY_TIMING2           0x9810
 #define AR_PHY_TIMING3           0x9814
 #define AR_PHY_TIMING3_DSC_MAN   0xFFFE0000
@@ -388,6 +397,8 @@
 #define AR_PHY_RFBUS_GRANT       0x9C20
 #define AR_PHY_RFBUS_GRANT_EN    0x00000001
 
+#define AR_PHY_TST_ADC      0x9C24
+
 #define AR_PHY_CHAN_INFO_GAIN_DIFF             0x9CF4
 #define AR_PHY_CHAN_INFO_GAIN_DIFF_UPPER_LIMIT 320
 
diff -u -Naur a/drivers/net/wireless/ath/ath9k/ar9002_phy.c 
b/drivers/net/wireless/ath/ath9k/ar9002_phy.c
--- a/drivers/net/wireless/ath/ath9k/ar9002_phy.c       2013-06-30 
16:34:53.000000000 +0200
+++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.c       2013-12-05 
19:18:44.000000000 +0100
@@ -616,6 +616,26 @@
        }
 }
 
+static void ar9002_hw_get_adc_entropy(struct ath_hw *ah, u8 *buf, size_t len)
+{
+       int i, j;
+
+       REG_RMW_FIELD(ah, AR_PHY_TEST, AR_PHY_TEST_BBB_OBS_SEL, 1);
+       REG_CLR_BIT(ah, AR_PHY_TEST, AR_PHY_TEST_RX_OBS_SEL_BIT5);
+       REG_RMW_FIELD(ah, AR_PHY_TEST2, AR_PHY_TEST2_RX_OBS_SEL, 0);
+
+       memset(buf, 0, len);
+       for (i = 0; i < len; i++) {
+               for (j = 0; j < 4; j++) {
+                       u32 regval = REG_READ(ah, AR_PHY_TST_ADC);
+
+                       buf[i] <<= 2;
+                       buf[i] |= (regval & 1) | ((regval & BIT(9)) >> 8);
+                       udelay(1);
+               }
+       }
+}
+
 void ar9002_hw_attach_phy_ops(struct ath_hw *ah)
 {
        struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
@@ -628,6 +648,7 @@
        priv_ops->compute_pll_control = ar9002_hw_compute_pll_control;
        priv_ops->do_getnf = ar9002_hw_do_getnf;
 
+       ops->get_adc_entropy = ar9002_hw_get_adc_entropy;
        ops->antdiv_comb_conf_get = ar9002_hw_antdiv_comb_conf_get;
        ops->antdiv_comb_conf_set = ar9002_hw_antdiv_comb_conf_set;
        ops->spectral_scan_config = ar9002_hw_spectral_scan_config;
_______________________________________________
openwrt-devel mailing list
openwrt-devel@lists.openwrt.org
https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel

Reply via email to