ath9k: Use definition from ieee80211.h
[safe/jmp/linux-2.6] / drivers / net / wireless / ath9k / main.c
index 262fd7a..2b3b11b 100644 (file)
@@ -22,8 +22,6 @@
 #define ATH_PCI_VERSION "0.1"
 
 #define IEEE80211_HTCAP_MAXRXAMPDU_FACTOR      13
-#define IEEE80211_ACTION_CAT_HT                        7
-#define IEEE80211_ACTION_HT_TXCHWIDTH          0
 
 static char *dev_info = "ath9k";
 
@@ -212,21 +210,16 @@ static int ath_key_config(struct ath_softc *sc,
 
 static void ath_key_delete(struct ath_softc *sc, struct ieee80211_key_conf *key)
 {
-#define ATH_MAX_NUM_KEYS 4
        int freeslot;
 
-       freeslot = (key->keyidx >= ATH_MAX_NUM_KEYS) ? 1 : 0;
+       freeslot = (key->keyidx >= 4) ? 1 : 0;
        ath_key_reset(sc, key->keyidx, freeslot);
-#undef ATH_MAX_NUM_KEYS
 }
 
 static void setup_ht_cap(struct ieee80211_ht_info *ht_info)
 {
-/* Until mac80211 includes these fields */
-
-#define IEEE80211_HT_CAP_DSSSCCK40 0x1000
-#define        IEEE80211_HT_CAP_MAXRXAMPDU_65536 0x3   /* 2 ^ 16 */
-#define        IEEE80211_HT_CAP_MPDUDENSITY_8 0x6      /* 8 usec */
+#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
@@ -234,8 +227,8 @@ static void setup_ht_cap(struct ieee80211_ht_info *ht_info)
                        |(u16)IEEE80211_HT_CAP_SGI_40
                        |(u16)IEEE80211_HT_CAP_DSSSCCK40;
 
-       ht_info->ampdu_factor = IEEE80211_HT_CAP_MAXRXAMPDU_65536;
-       ht_info->ampdu_density = IEEE80211_HT_CAP_MPDUDENSITY_8;
+       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;
@@ -368,6 +361,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);
@@ -426,10 +433,13 @@ static int ath9k_add_interface(struct ieee80211_hw *hw,
        case IEEE80211_IF_TYPE_IBSS:
                ic_opmode = ATH9K_M_IBSS;
                break;
+       case IEEE80211_IF_TYPE_AP:
+               ic_opmode = ATH9K_M_HOSTAP;
+               break;
        default:
                DPRINTF(sc, ATH_DBG_FATAL,
-                       "%s: Only STA and IBSS are supported currently\n",
-                       __func__);
+                       "%s: Interface type %d not yet supported\n",
+                       __func__, conf->type);
                return -EOPNOTSUPP;
        }
 
@@ -472,7 +482,8 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw,
        ath_rate_newstate(sc, avp);
 
        /* Reclaim beacon resources */
-       if (sc->sc_opmode == ATH9K_M_HOSTAP || sc->sc_opmode == ATH9K_M_IBSS) {
+       if (sc->sc_ah->ah_opmode == ATH9K_M_HOSTAP ||
+           sc->sc_ah->ah_opmode == ATH9K_M_IBSS) {
                ath9k_hw_stoptxdma(sc->sc_ah, sc->sc_bhalq);
                ath_beacon_return(sc, avp);
        }
@@ -480,7 +491,7 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw,
        /* Set interrupt mask */
        sc->sc_imask &= ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS);
        ath9k_hw_set_interrupts(sc->sc_ah, sc->sc_imask & ~ATH9K_INT_GLOBAL);
-       sc->sc_beacons = 0;
+       sc->sc_flags &= ~SC_OP_BEACONS;
 
        error = ath_vap_detach(sc, 0);
        if (error)
@@ -529,6 +540,7 @@ static int ath9k_config_interface(struct ieee80211_hw *hw,
                                  struct ieee80211_if_conf *conf)
 {
        struct ath_softc *sc = hw->priv;
+       struct ath_hal *ah = sc->sc_ah;
        struct ath_vap *avp;
        u32 rfilt = 0;
        int error, i;
@@ -541,6 +553,17 @@ static int ath9k_config_interface(struct ieee80211_hw *hw,
                return -EINVAL;
        }
 
+       /* TODO: Need to decide which hw opmode to use for multi-interface
+        * cases */
+       if (vif->type == IEEE80211_IF_TYPE_AP &&
+           ah->ah_opmode != ATH9K_M_HOSTAP) {
+               ah->ah_opmode = ATH9K_M_HOSTAP;
+               ath9k_hw_setopmode(ah);
+               ath9k_hw_write_associd(ah, sc->sc_myaddr, 0);
+               /* Request full reset to get hw opmode changed properly */
+               sc->sc_flags |= SC_OP_FULL_RESET;
+       }
+
        if ((conf->changed & IEEE80211_IFCC_BSSID) &&
            !is_zero_ether_addr(conf->bssid)) {
                switch (vif->type) {
@@ -581,7 +604,7 @@ static int ath9k_config_interface(struct ieee80211_hw *hw,
                                print_mac(mac, sc->sc_curbssid), sc->sc_curaid);
 
                        /* need to reconfigure the beacon */
-                       sc->sc_beacons = 0;
+                       sc->sc_flags &= ~SC_OP_BEACONS ;
 
                        break;
                default:
@@ -590,7 +613,8 @@ static int ath9k_config_interface(struct ieee80211_hw *hw,
        }
 
        if ((conf->changed & IEEE80211_IFCC_BEACON) &&
-           (vif->type == IEEE80211_IF_TYPE_IBSS)) {
+           ((vif->type == IEEE80211_IF_TYPE_IBSS) ||
+            (vif->type == IEEE80211_IF_TYPE_AP))) {
                /*
                 * Allocate and setup the beacon frame.
                 *
@@ -832,7 +856,7 @@ static void ath9k_bss_assoc_info(struct ath_softc *sc,
 
                /* Configure the beacon */
                ath_beacon_config(sc, 0);
-               sc->sc_beacons = 1;
+               sc->sc_flags |= SC_OP_BEACONS;
 
                /* Reset rssi stats */
                sc->sc_halstats.ns_avgbrssi = ATH_RSSI_DUMMY_MARKER;
@@ -895,9 +919,9 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
                        __func__,
                        bss_conf->use_short_preamble);
                if (bss_conf->use_short_preamble)
-                       sc->sc_flags |= ATH_PREAMBLE_SHORT;
+                       sc->sc_flags |= SC_OP_PREAMBLE_SHORT;
                else
-                       sc->sc_flags &= ~ATH_PREAMBLE_SHORT;
+                       sc->sc_flags &= ~SC_OP_PREAMBLE_SHORT;
        }
 
        if (changed & BSS_CHANGED_ERP_CTS_PROT) {
@@ -906,9 +930,9 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
                        bss_conf->use_cts_prot);
                if (bss_conf->use_cts_prot &&
                    hw->conf.channel->band != IEEE80211_BAND_5GHZ)
-                       sc->sc_flags |= ATH_PROTECT_ENABLE;
+                       sc->sc_flags |= SC_OP_PROTECT_ENABLE;
                else
-                       sc->sc_flags &= ~ATH_PROTECT_ENABLE;
+                       sc->sc_flags &= ~SC_OP_PROTECT_ENABLE;
        }
 
        if (changed & BSS_CHANGED_HT) {
@@ -1036,15 +1060,6 @@ void ath_get_beaconconfig(struct ath_softc *sc,
        conf->bmiss_timeout = ATH_DEFAULT_BMISS_LIMIT * conf->listen_interval;
 }
 
-int ath_update_beacon(struct ath_softc *sc,
-                     int if_id,
-                     struct ath_beacon_offset *bo,
-                     struct sk_buff *skb,
-                     int mcast)
-{
-       return 0;
-}
-
 void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
                     struct ath_xmit_status *tx_status, struct ath_node *an)
 {
@@ -1066,8 +1081,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;