ath9k: Fix IRQ nobody cared issue with ath9k
[pandora-kernel.git] / drivers / net / wireless / ath9k / main.c
index 9549524..acebdf1 100644 (file)
@@ -206,7 +206,6 @@ static int ath_key_config(struct ath_softc *sc,
        if (!ret)
                return -EIO;
 
-       sc->sc_keytype = hk.kv_type;
        return 0;
 }
 
@@ -368,6 +367,20 @@ static int ath9k_tx(struct ieee80211_hw *hw,
 {
        struct ath_softc *sc = hw->priv;
        int hdrlen, padsize;
+       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+
+       /*
+        * As a temporary workaround, assign seq# here; this will likely need
+        * to be cleaned up to work better with Beacon transmission and virtual
+        * BSSes.
+        */
+       if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
+               struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+               if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)
+                       sc->seq_no += 0x10;
+               hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
+               hdr->seq_ctrl |= cpu_to_le16(sc->seq_no);
+       }
 
        /* Add the padding after the header if this is not already done */
        hdrlen = ieee80211_get_hdrlen_from_skb(skb);
@@ -507,7 +520,13 @@ static int ath9k_config(struct ieee80211_hw *hw,
        }
 
        sc->sc_ah->ah_channels[pos].chanmode =
-               (curchan->band == IEEE80211_BAND_2GHZ) ? CHANNEL_G : CHANNEL_A;
+               (curchan->band == IEEE80211_BAND_2GHZ) ?
+               CHANNEL_G : CHANNEL_A;
+
+       if (sc->sc_curaid && hw->conf.ht_conf.ht_supported)
+               sc->sc_ah->ah_channels[pos].chanmode =
+                       ath_get_extchanmode(sc, curchan);
+
        sc->sc_config.txpowlimit = 2 * conf->power_level;
 
        /* set h/w channel */
@@ -700,7 +719,7 @@ static int ath9k_conf_tx(struct ieee80211_hw *hw,
                         const struct ieee80211_tx_queue_params *params)
 {
        struct ath_softc *sc = hw->priv;
-       struct ath9k_txq_info qi;
+       struct ath9k_tx_queue_info qi;
        int ret = 0, qnum;
 
        if (queue >= WME_NUM_AC)
@@ -750,13 +769,13 @@ static int ath9k_set_key(struct ieee80211_hw *hw,
                        key->hw_key_idx = key->keyidx;
                        /* push IV and Michael MIC generation to stack */
                        key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
-                       key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
+                       if (key->alg == ALG_TKIP)
+                               key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
                }
                break;
        case DISABLE_KEY:
                ath_key_delete(sc, key);
                clear_bit(key->keyidx, sc->sc_keymap);
-               sc->sc_keytype = ATH9K_CIPHER_CLR;
                break;
        default:
                ret = -EINVAL;
@@ -1059,8 +1078,16 @@ void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
                tx_info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK;
                tx_status->flags &= ~ATH_TX_BAR;
        }
-       if (tx_status->flags)
-               tx_info->status.excessive_retries = 1;
+
+       if (tx_status->flags & (ATH_TX_ERROR | ATH_TX_XRETRY)) {
+               if (!(tx_info->flags & IEEE80211_TX_CTL_NO_ACK)) {
+                       /* Frame was not ACKed, but an ACK was expected */
+                       tx_info->status.excessive_retries = 1;
+               }
+       } else {
+               /* Frame was ACKed */
+               tx_info->flags |= IEEE80211_TX_STAT_ACK;
+       }
 
        tx_info->status.retry_count = tx_status->retries;
 
@@ -1145,75 +1172,6 @@ enum ath9k_ht_macmode ath_cwm_macmode(struct ath_softc *sc)
        return sc->sc_ht_info.tx_chan_width;
 }
 
-void ath_setup_rate(struct ath_softc *sc,
-                   enum wireless_mode wMode,
-                   enum RATE_TYPE type,
-                   const struct ath9k_rate_table *rt)
-{
-       int i, maxrates, a = 0, b = 0;
-       struct ieee80211_supported_band *band_2ghz;
-       struct ieee80211_supported_band *band_5ghz;
-       struct ieee80211_rate *rates_2ghz;
-       struct ieee80211_rate *rates_5ghz;
-
-       if ((wMode >= WIRELESS_MODE_MAX) || (type != NORMAL_RATE))
-               return;
-
-       band_2ghz = &sc->sbands[IEEE80211_BAND_2GHZ];
-       band_5ghz = &sc->sbands[IEEE80211_BAND_5GHZ];
-       rates_2ghz = sc->rates[IEEE80211_BAND_2GHZ];
-       rates_5ghz = sc->rates[IEEE80211_BAND_5GHZ];
-
-       if (rt->rateCount > ATH_RATE_MAX)
-               maxrates = ATH_RATE_MAX;
-       else
-               maxrates = rt->rateCount;
-
-       if ((band_2ghz->n_bitrates != 0) && (band_5ghz->n_bitrates != 0)) {
-               DPRINTF(sc, ATH_DBG_CONFIG,
-                       "%s: Rates already setup\n", __func__);
-               return;
-       }
-
-       for (i = 0; i < maxrates; i++) {
-               switch (wMode) {
-               case WIRELESS_MODE_11b:
-               case WIRELESS_MODE_11g:
-                       rates_2ghz[a].bitrate = rt->info[i].rateKbps / 100;
-                       rates_2ghz[a].hw_value = rt->info[i].rateCode;
-                       a++;
-                       band_2ghz->n_bitrates = a;
-                       break;
-               case WIRELESS_MODE_11a:
-                       rates_5ghz[b].bitrate = rt->info[i].rateKbps / 100;
-                       rates_5ghz[b].hw_value = rt->info[i].rateCode;
-                       b++;
-                       band_5ghz->n_bitrates = b;
-                       break;
-               default:
-                       break;
-               }
-       }
-
-       if (band_2ghz->n_bitrates) {
-               for (i = 0; i < band_2ghz->n_bitrates; i++) {
-                       DPRINTF(sc, ATH_DBG_CONFIG,
-                               "%s: 2GHz Rate: %2dMbps, ratecode: %2d\n",
-                               __func__,
-                               rates_2ghz[i].bitrate / 10,
-                               rates_2ghz[i].hw_value);
-               }
-       } else if (band_5ghz->n_bitrates) {
-               for (i = 0; i < band_5ghz->n_bitrates; i++) {
-                       DPRINTF(sc, ATH_DBG_CONFIG,
-                               "%s: 5Ghz Rate: %2dMbps, ratecode: %2d\n",
-                               __func__,
-                               rates_5ghz[i].bitrate / 10,
-                               rates_5ghz[i].hw_value);
-               }
-       }
-}
-
 static int ath_detach(struct ath_softc *sc)
 {
        struct ieee80211_hw *hw = sc->hw;
@@ -1268,14 +1226,14 @@ static int ath_attach(u16 devid,
                sc->rates[IEEE80211_BAND_2GHZ];
        sc->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ;
 
-       if (sc->sc_ah->ah_caps.halHTSupport)
+       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);
 
        hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
                &sc->sbands[IEEE80211_BAND_2GHZ];
 
-       if (sc->sc_ah->ah_caps.halWirelessModes & ATH9K_MODE_SEL_11A) {
+       if (test_bit(ATH9K_MODE_11A, sc->sc_ah->ah_caps.wireless_modes)) {
                sc->sbands[IEEE80211_BAND_5GHZ].channels =
                        sc->channels[IEEE80211_BAND_5GHZ];
                sc->sbands[IEEE80211_BAND_5GHZ].bitrates =
@@ -1283,7 +1241,7 @@ static int ath_attach(u16 devid,
                sc->sbands[IEEE80211_BAND_5GHZ].band =
                        IEEE80211_BAND_5GHZ;
 
-               if (sc->sc_ah->ah_caps.halHTSupport)
+               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);
 
@@ -1453,10 +1411,17 @@ static void ath_pci_remove(struct pci_dev *pdev)
 {
        struct ieee80211_hw *hw = pci_get_drvdata(pdev);
        struct ath_softc *sc = hw->priv;
+       enum ath9k_int status;
 
-       if (pdev->irq)
+       if (pdev->irq) {
+               ath9k_hw_set_interrupts(sc->sc_ah, 0);
+               /* clear the ISR */
+               ath9k_hw_getisr(sc->sc_ah, &status);
+               sc->sc_invalid = 1;
                free_irq(pdev->irq, sc);
+       }
        ath_detach(sc);
+
        pci_iounmap(pdev, sc->mem);
        pci_release_region(pdev, 0);
        pci_disable_device(pdev);