ath10k: rework legacy rx rate decoding
authorMichal Kazior <michal.kazior@tieto.com>
Mon, 30 Mar 2015 06:51:56 +0000 (09:51 +0300)
committerKalle Valo <kvalo@qca.qualcomm.com>
Mon, 30 Mar 2015 12:09:38 +0000 (15:09 +0300)
Instead of using a hacky table and magic values
use supported band information advertised to
mac80211.

This may impact performance a little when dealing
with legacy rx rates depending on system
architecture. It's probably negligible.

This also fixes a highly theoretical corner case
when HT/VHT rates weren't reported correctly if
channel frequency wasn't known.

Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
drivers/net/wireless/ath/ath10k/htt_rx.c
drivers/net/wireless/ath/ath10k/mac.c
drivers/net/wireless/ath/ath10k/mac.h

index a4d19d0..157dc8d 100644 (file)
@@ -643,44 +643,15 @@ struct amsdu_subframe_hdr {
        __be16 len;
 } __packed;
 
-static const u8 rx_legacy_rate_idx[] = {
-       3,      /* 0x00  - 11Mbps  */
-       2,      /* 0x01  - 5.5Mbps */
-       1,      /* 0x02  - 2Mbps   */
-       0,      /* 0x03  - 1Mbps   */
-       3,      /* 0x04  - 11Mbps  */
-       2,      /* 0x05  - 5.5Mbps */
-       1,      /* 0x06  - 2Mbps   */
-       0,      /* 0x07  - 1Mbps   */
-       10,     /* 0x08  - 48Mbps  */
-       8,      /* 0x09  - 24Mbps  */
-       6,      /* 0x0A  - 12Mbps  */
-       4,      /* 0x0B  - 6Mbps   */
-       11,     /* 0x0C  - 54Mbps  */
-       9,      /* 0x0D  - 36Mbps  */
-       7,      /* 0x0E  - 18Mbps  */
-       5,      /* 0x0F  - 9Mbps   */
-};
-
 static void ath10k_htt_rx_h_rates(struct ath10k *ar,
                                  struct ieee80211_rx_status *status,
                                  struct htt_rx_desc *rxd)
 {
-       enum ieee80211_band band;
-       u8 cck, rate, rate_idx, bw, sgi, mcs, nss;
+       struct ieee80211_supported_band *sband;
+       u8 cck, rate, bw, sgi, mcs, nss;
        u8 preamble = 0;
        u32 info1, info2, info3;
 
-       /* Band value can't be set as undefined but freq can be 0 - use that to
-        * determine whether band is provided.
-        *
-        * FIXME: Perhaps this can go away if CCK rate reporting is a little
-        * reworked?
-        */
-       if (!status->freq)
-               return;
-
-       band = status->band;
        info1 = __le32_to_cpu(rxd->ppdu_start.info1);
        info2 = __le32_to_cpu(rxd->ppdu_start.info2);
        info3 = __le32_to_cpu(rxd->ppdu_start.info3);
@@ -689,31 +660,18 @@ static void ath10k_htt_rx_h_rates(struct ath10k *ar,
 
        switch (preamble) {
        case HTT_RX_LEGACY:
+               /* To get legacy rate index band is required. Since band can't
+                * be undefined check if freq is non-zero.
+                */
+               if (!status->freq)
+                       return;
+
                cck = info1 & RX_PPDU_START_INFO1_L_SIG_RATE_SELECT;
                rate = MS(info1, RX_PPDU_START_INFO1_L_SIG_RATE);
-               rate_idx = 0;
-
-               if (rate < 0x08 || rate > 0x0F)
-                       break;
-
-               switch (band) {
-               case IEEE80211_BAND_2GHZ:
-                       if (cck)
-                               rate &= ~BIT(3);
-                       rate_idx = rx_legacy_rate_idx[rate];
-                       break;
-               case IEEE80211_BAND_5GHZ:
-                       rate_idx = rx_legacy_rate_idx[rate];
-                       /* We are using same rate table registering
-                          HW - ath10k_rates[]. In case of 5GHz skip
-                          CCK rates, so -4 here */
-                       rate_idx -= 4;
-                       break;
-               default:
-                       break;
-               }
+               rate &= ~RX_PPDU_START_RATE_FLAG;
 
-               status->rate_idx = rate_idx;
+               sband = &ar->mac.sbands[status->band];
+               status->rate_idx = ath10k_mac_hw_rate_to_idx(sband, rate);
                break;
        case HTT_RX_HT:
        case HTT_RX_HT_WITH_TXBF:
index 743fac8..8bb4c19 100644 (file)
 /*********/
 
 static struct ieee80211_rate ath10k_rates[] = {
-       { .bitrate = 10, .hw_value = ATH10K_HW_RATE_CCK_LP_1M },
-       { .bitrate = 20, .hw_value = ATH10K_HW_RATE_CCK_LP_2M },
-       { .bitrate = 55, .hw_value = ATH10K_HW_RATE_CCK_LP_5_5M },
-       { .bitrate = 110, .hw_value = ATH10K_HW_RATE_CCK_LP_11M },
+       { .bitrate = 10,
+         .hw_value = ATH10K_HW_RATE_CCK_LP_1M },
+       { .bitrate = 20,
+         .hw_value = ATH10K_HW_RATE_CCK_LP_2M,
+         .hw_value_short = ATH10K_HW_RATE_CCK_SP_2M,
+         .flags = IEEE80211_RATE_SHORT_PREAMBLE },
+       { .bitrate = 55,
+         .hw_value = ATH10K_HW_RATE_CCK_LP_5_5M,
+         .hw_value_short = ATH10K_HW_RATE_CCK_SP_5_5M,
+         .flags = IEEE80211_RATE_SHORT_PREAMBLE },
+       { .bitrate = 110,
+         .hw_value = ATH10K_HW_RATE_CCK_LP_11M,
+         .hw_value_short = ATH10K_HW_RATE_CCK_SP_11M,
+         .flags = IEEE80211_RATE_SHORT_PREAMBLE },
 
        { .bitrate = 60, .hw_value = ATH10K_HW_RATE_OFDM_6M },
        { .bitrate = 90, .hw_value = ATH10K_HW_RATE_OFDM_9M },
@@ -75,6 +85,25 @@ static u8 ath10k_mac_bitrate_to_rate(int bitrate)
               (ath10k_mac_bitrate_is_cck(bitrate) ? BIT(7) : 0);
 }
 
+u8 ath10k_mac_hw_rate_to_idx(const struct ieee80211_supported_band *sband,
+                            u8 hw_rate)
+{
+       const struct ieee80211_rate *rate;
+       int i;
+
+       for (i = 0; i < sband->n_bitrates; i++) {
+               rate = &sband->bitrates[i];
+
+               if (rate->hw_value == hw_rate)
+                       return i;
+               else if (rate->flags & IEEE80211_RATE_SHORT_PREAMBLE &&
+                        rate->hw_value_short == hw_rate)
+                       return i;
+       }
+
+       return 0;
+}
+
 /**********/
 /* Crypto */
 /**********/
index 2cdf68d..af806c6 100644 (file)
@@ -55,6 +55,8 @@ bool ath10k_mac_is_peer_wep_key_set(struct ath10k *ar, const u8 *addr,
                                    u8 keyidx);
 void ath10k_mac_handle_beacon(struct ath10k *ar, struct sk_buff *skb);
 void ath10k_mac_handle_beacon_miss(struct ath10k *ar, u32 vdev_id);
+u8 ath10k_mac_hw_rate_to_idx(const struct ieee80211_supported_band *sband,
+                            u8 hw_rate);
 
 static inline struct ath10k_vif *ath10k_vif_to_arvif(struct ieee80211_vif *vif)
 {