ath9k: correct signal quality report
[pandora-kernel.git] / drivers / net / wireless / ath9k / main.c
index f05f584..32acaf7 100644 (file)
@@ -61,24 +61,24 @@ static u32 ath_get_extchanmode(struct ath_softc *sc,
 
        switch (chan->band) {
        case IEEE80211_BAND_2GHZ:
-               if ((ext_chan_offset == IEEE80211_HT_IE_CHA_SEC_NONE) &&
+               if ((ext_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_NONE) &&
                    (tx_chan_width == ATH9K_HT_MACMODE_20))
                        chanmode = CHANNEL_G_HT20;
-               if ((ext_chan_offset == IEEE80211_HT_IE_CHA_SEC_ABOVE) &&
+               if ((ext_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_ABOVE) &&
                    (tx_chan_width == ATH9K_HT_MACMODE_2040))
                        chanmode = CHANNEL_G_HT40PLUS;
-               if ((ext_chan_offset == IEEE80211_HT_IE_CHA_SEC_BELOW) &&
+               if ((ext_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_BELOW) &&
                    (tx_chan_width == ATH9K_HT_MACMODE_2040))
                        chanmode = CHANNEL_G_HT40MINUS;
                break;
        case IEEE80211_BAND_5GHZ:
-               if ((ext_chan_offset == IEEE80211_HT_IE_CHA_SEC_NONE) &&
+               if ((ext_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_NONE) &&
                    (tx_chan_width == ATH9K_HT_MACMODE_20))
                        chanmode = CHANNEL_A_HT20;
-               if ((ext_chan_offset == IEEE80211_HT_IE_CHA_SEC_ABOVE) &&
+               if ((ext_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_ABOVE) &&
                    (tx_chan_width == ATH9K_HT_MACMODE_2040))
                        chanmode = CHANNEL_A_HT40PLUS;
-               if ((ext_chan_offset == IEEE80211_HT_IE_CHA_SEC_BELOW) &&
+               if ((ext_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_BELOW) &&
                    (tx_chan_width == ATH9K_HT_MACMODE_2040))
                        chanmode = CHANNEL_A_HT40MINUS;
                break;
@@ -215,24 +215,24 @@ static void ath_key_delete(struct ath_softc *sc, struct ieee80211_key_conf *key)
        ath_key_reset(sc, key->keyidx, freeslot);
 }
 
-static void setup_ht_cap(struct ieee80211_ht_info *ht_info)
+static void setup_ht_cap(struct ieee80211_sta_ht_cap *ht_info)
 {
 #define        ATH9K_HT_CAP_MAXRXAMPDU_65536 0x3       /* 2 ^ 16 */
 #define        ATH9K_HT_CAP_MPDUDENSITY_8 0x6          /* 8 usec */
 
-       ht_info->ht_supported = 1;
-       ht_info->cap = (u16)IEEE80211_HT_CAP_SUP_WIDTH
-                       |(u16)IEEE80211_HT_CAP_SM_PS
-                       |(u16)IEEE80211_HT_CAP_SGI_40
-                       |(u16)IEEE80211_HT_CAP_DSSSCCK40;
+       ht_info->ht_supported = true;
+       ht_info->cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
+                      IEEE80211_HT_CAP_SM_PS |
+                      IEEE80211_HT_CAP_SGI_40 |
+                      IEEE80211_HT_CAP_DSSSCCK40;
 
        ht_info->ampdu_factor = ATH9K_HT_CAP_MAXRXAMPDU_65536;
        ht_info->ampdu_density = ATH9K_HT_CAP_MPDUDENSITY_8;
-       /* setup supported mcs set */
-       memset(ht_info->supp_mcs_set, 0, 16);
-       ht_info->supp_mcs_set[0] = 0xff;
-       ht_info->supp_mcs_set[1] = 0xff;
-       ht_info->supp_mcs_set[12] = IEEE80211_HT_CAP_MCS_TX_DEFINED;
+       /* set up supported mcs set */
+       memset(&ht_info->mcs, 0, sizeof(ht_info->mcs));
+       ht_info->mcs.rx_mask[0] = 0xff;
+       ht_info->mcs.rx_mask[1] = 0xff;
+       ht_info->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
 }
 
 static int ath_rate2idx(struct ath_softc *sc, int rate)
@@ -279,8 +279,15 @@ static void ath9k_rx_prepare(struct ath_softc *sc,
        rx_status->rate_idx = ath_rate2idx(sc, (status->rateKbps / 100));
        rx_status->antenna = status->antenna;
 
-       /* XXX Fix me, 64 cannot be the max rssi value, rigure it out */
-       rx_status->qual = status->rssi * 100 / 64;
+       /* at 45 you will be able to use MCS 15 reliably. A more elaborate
+        * scheme can be used here but it requires tables of SNR/throughput for
+        * each possible mode used. */
+       rx_status->qual = status->rssi * 100 / 45;
+
+       /* rssi can be more than 45 though, anything above that
+        * should be considered at 100% */
+       if (rx_status->qual > 100)
+               rx_status->qual = 100;
 
        if (status->flags & ATH_RX_MIC_ERROR)
                rx_status->flag |= RX_FLAG_MMIC_ERROR;
@@ -328,31 +335,18 @@ static u8 parse_mpdudensity(u8 mpdudensity)
 static void ath9k_ht_conf(struct ath_softc *sc,
                          struct ieee80211_bss_conf *bss_conf)
 {
-#define IEEE80211_HT_CAP_40MHZ_INTOLERANT BIT(14)
        struct ath_ht_info *ht_info = &sc->sc_ht_info;
 
-       if (bss_conf->assoc_ht) {
-               ht_info->ext_chan_offset =
-                       bss_conf->ht_bss_conf->bss_cap &
-                               IEEE80211_HT_IE_CHA_SEC_OFFSET;
+       if (sc->hw->conf.ht.enabled) {
+               ht_info->ext_chan_offset = bss_conf->ht.secondary_channel_offset;
 
-               if (!(bss_conf->ht_conf->cap &
-                       IEEE80211_HT_CAP_40MHZ_INTOLERANT) &&
-                           (bss_conf->ht_bss_conf->bss_cap &
-                               IEEE80211_HT_IE_CHA_WIDTH))
+               if (bss_conf->ht.width_40_ok)
                        ht_info->tx_chan_width = ATH9K_HT_MACMODE_2040;
                else
                        ht_info->tx_chan_width = ATH9K_HT_MACMODE_20;
 
                ath9k_hw_set11nmac2040(sc->sc_ah, ht_info->tx_chan_width);
-               ht_info->maxampdu = 1 << (IEEE80211_HTCAP_MAXRXAMPDU_FACTOR +
-                                       bss_conf->ht_conf->ampdu_factor);
-               ht_info->mpdudensity =
-                       parse_mpdudensity(bss_conf->ht_conf->ampdu_density);
-
        }
-
-#undef IEEE80211_HT_CAP_40MHZ_INTOLERANT
 }
 
 static void ath9k_bss_assoc_info(struct ath_softc *sc,
@@ -362,7 +356,6 @@ static void ath9k_bss_assoc_info(struct ath_softc *sc,
        struct ieee80211_channel *curchan = hw->conf.channel;
        struct ath_vap *avp;
        int pos;
-       DECLARE_MAC_BUF(mac);
 
        if (bss_conf->assoc) {
                DPRINTF(sc, ATH_DBG_CONFIG, "%s: Bss Info ASSOC %d\n",
@@ -394,12 +387,12 @@ static void ath9k_bss_assoc_info(struct ath_softc *sc,
                sc->sc_halstats.ns_avgtxrate = ATH_RATE_DUMMY_MARKER;
 
                /* Update chainmask */
-               ath_update_chainmask(sc, bss_conf->assoc_ht);
+               ath_update_chainmask(sc, hw->conf.ht.enabled);
 
                DPRINTF(sc, ATH_DBG_CONFIG,
-                       "%s: bssid %s aid 0x%x\n",
+                       "%s: bssid %pM aid 0x%x\n",
                        __func__,
-                       print_mac(mac, sc->sc_curbssid), sc->sc_curaid);
+                       sc->sc_curbssid, sc->sc_curaid);
 
                DPRINTF(sc, ATH_DBG_CONFIG, "%s: Set channel: %d MHz\n",
                        __func__,
@@ -412,7 +405,7 @@ static void ath9k_bss_assoc_info(struct ath_softc *sc,
                        return;
                }
 
-               if (hw->conf.ht_conf.ht_supported)
+               if (hw->conf.ht.enabled)
                        sc->sc_ah->ah_channels[pos].chanmode =
                                ath_get_extchanmode(sc, curchan);
                else
@@ -535,7 +528,6 @@ int _ath_rx_indicate(struct ath_softc *sc,
 
        if (an) {
                ath_rx_input(sc, an,
-                            hw->conf.ht_conf.ht_supported,
                             skb, status, &st);
        }
        if (!an || (st != ATH_RX_CONSUMED))
@@ -944,7 +936,7 @@ static int ath_attach(u16 devid,
 
        if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT)
                /* Setup HT capabilities for 2.4Ghz*/
-               setup_ht_cap(&sc->sbands[IEEE80211_BAND_2GHZ].ht_info);
+               setup_ht_cap(&sc->sbands[IEEE80211_BAND_2GHZ].ht_cap);
 
        hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
                &sc->sbands[IEEE80211_BAND_2GHZ];
@@ -959,7 +951,7 @@ static int ath_attach(u16 devid,
 
                if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT)
                        /* Setup HT capabilities for 5Ghz*/
-                       setup_ht_cap(&sc->sbands[IEEE80211_BAND_5GHZ].ht_info);
+                       setup_ht_cap(&sc->sbands[IEEE80211_BAND_5GHZ].ht_cap);
 
                hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
                        &sc->sbands[IEEE80211_BAND_5GHZ];
@@ -1234,17 +1226,20 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw,
                        __func__, error);
 }
 
-static int ath9k_config(struct ieee80211_hw *hw,
-                       struct ieee80211_conf *conf)
+static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
 {
        struct ath_softc *sc = hw->priv;
        struct ieee80211_channel *curchan = hw->conf.channel;
+       struct ieee80211_conf *conf = &hw->conf;
        int pos;
 
        DPRINTF(sc, ATH_DBG_CONFIG, "%s: Set channel: %d MHz\n",
                __func__,
                curchan->center_freq);
 
+       /* Update chainmask */
+       ath_update_chainmask(sc, conf->ht.enabled);
+
        pos = ath_get_channel(sc, curchan);
        if (pos == -1) {
                DPRINTF(sc, ATH_DBG_FATAL, "%s: Invalid channel\n", __func__);
@@ -1255,7 +1250,7 @@ static int ath9k_config(struct ieee80211_hw *hw,
                (curchan->band == IEEE80211_BAND_2GHZ) ?
                CHANNEL_G : CHANNEL_A;
 
-       if (sc->sc_curaid && hw->conf.ht_conf.ht_supported)
+       if (sc->sc_curaid && hw->conf.ht.enabled)
                sc->sc_ah->ah_channels[pos].chanmode =
                        ath_get_extchanmode(sc, curchan);
 
@@ -1278,7 +1273,6 @@ static int ath9k_config_interface(struct ieee80211_hw *hw,
        struct ath_vap *avp;
        u32 rfilt = 0;
        int error, i;
-       DECLARE_MAC_BUF(mac);
 
        avp = sc->sc_vaps[0];
        if (avp == NULL) {
@@ -1333,9 +1327,9 @@ static int ath9k_config_interface(struct ieee80211_hw *hw,
                        sc->sc_imask &= ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS);
 
                        DPRINTF(sc, ATH_DBG_CONFIG,
-                               "%s: RX filter 0x%x bssid %s aid 0x%x\n",
+                               "%s: RX filter 0x%x bssid %pM aid 0x%x\n",
                                __func__, rfilt,
-                               print_mac(mac, sc->sc_curbssid), sc->sc_curaid);
+                               sc->sc_curbssid, sc->sc_curaid);
 
                        /* need to reconfigure the beacon */
                        sc->sc_flags &= ~SC_OP_BEACONS ;
@@ -1424,7 +1418,6 @@ static void ath9k_sta_notify(struct ieee80211_hw *hw,
        struct ath_softc *sc = hw->priv;
        struct ath_node *an;
        unsigned long flags;
-       DECLARE_MAC_BUF(mac);
 
        spin_lock_irqsave(&sc->node_lock, flags);
        an = ath_node_find(sc, sta->addr);
@@ -1435,11 +1428,19 @@ static void ath9k_sta_notify(struct ieee80211_hw *hw,
                spin_lock_irqsave(&sc->node_lock, flags);
                if (!an) {
                        ath_node_attach(sc, sta->addr, 0);
-                       DPRINTF(sc, ATH_DBG_CONFIG, "%s: Attach a node: %s\n",
-                               __func__, print_mac(mac, sta->addr));
+                       DPRINTF(sc, ATH_DBG_CONFIG, "%s: Attach a node: %pM\n",
+                               __func__, sta->addr);
                } else {
                        ath_node_get(sc, sta->addr);
                }
+
+               /* XXX: Is this right? Can the capabilities change? */
+               an = ath_node_find(sc, sta->addr);
+               an->maxampdu = 1 << (IEEE80211_HTCAP_MAXRXAMPDU_FACTOR +
+                                       sta->ht_cap.ampdu_factor);
+               an->mpdudensity =
+                       parse_mpdudensity(sta->ht_cap.ampdu_density);
+
                spin_unlock_irqrestore(&sc->node_lock, flags);
                break;
        case STA_NOTIFY_REMOVE:
@@ -1449,9 +1450,9 @@ static void ath9k_sta_notify(struct ieee80211_hw *hw,
                                __func__);
                else {
                        ath_node_put(sc, an, ATH9K_BH_STATUS_INTACT);
-                       DPRINTF(sc, ATH_DBG_CONFIG, "%s: Put a node: %s\n",
+                       DPRINTF(sc, ATH_DBG_CONFIG, "%s: Put a node: %pM\n",
                                __func__,
-                               print_mac(mac, sta->addr));
+                               sta->addr);
                }
                break;
        default:
@@ -1558,9 +1559,8 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
        }
 
        if (changed & BSS_CHANGED_HT) {
-               DPRINTF(sc, ATH_DBG_CONFIG, "%s: BSS Changed HT %d\n",
-                       __func__,
-                       bss_conf->assoc_ht);
+               DPRINTF(sc, ATH_DBG_CONFIG, "%s: BSS Changed HT\n",
+                       __func__);
                ath9k_ht_conf(sc, bss_conf);
        }
 
@@ -1665,7 +1665,6 @@ static struct ieee80211_ops ath9k_ops = {
        .get_tkip_seq       = NULL,
        .set_rts_threshold  = NULL,
        .set_frag_threshold = NULL,
-       .set_retry_limit    = NULL,
        .get_tsf            = ath9k_get_tsf,
        .reset_tsf          = ath9k_reset_tsf,
        .tx_last_beacon     = NULL,