mac80211: use multi-queue master netdevice
[deliverable/linux.git] / drivers / net / wireless / ath5k / base.c
index 393b5f3c25a7899be452966b4beebaa0e688cbe6..18e9422d26ddee628128a59f5513468338978c15 100644 (file)
 #include "reg.h"
 #include "debug.h"
 
-/* unaligned little endian access */
-#define LE_READ_2(_p) (le16_to_cpu(get_unaligned((__le16 *)(_p))))
-#define LE_READ_4(_p) (le32_to_cpu(get_unaligned((__le32 *)(_p))))
-
 enum {
        ATH_LED_TX,
        ATH_LED_RX,
@@ -118,12 +114,15 @@ static struct ath5k_srev_name srev_names[] = {
        { "5212",       AR5K_VERSION_VER,       AR5K_SREV_VER_AR5212 },
        { "5213",       AR5K_VERSION_VER,       AR5K_SREV_VER_AR5213 },
        { "5213A",      AR5K_VERSION_VER,       AR5K_SREV_VER_AR5213A },
+       { "2413",       AR5K_VERSION_VER,       AR5K_SREV_VER_AR2413 },
+       { "2414",       AR5K_VERSION_VER,       AR5K_SREV_VER_AR2414 },
        { "2424",       AR5K_VERSION_VER,       AR5K_SREV_VER_AR2424 },
        { "5424",       AR5K_VERSION_VER,       AR5K_SREV_VER_AR5424 },
        { "5413",       AR5K_VERSION_VER,       AR5K_SREV_VER_AR5413 },
        { "5414",       AR5K_VERSION_VER,       AR5K_SREV_VER_AR5414 },
        { "5416",       AR5K_VERSION_VER,       AR5K_SREV_VER_AR5416 },
        { "5418",       AR5K_VERSION_VER,       AR5K_SREV_VER_AR5418 },
+       { "2425",       AR5K_VERSION_VER,       AR5K_SREV_VER_AR2425 },
        { "xxxxx",      AR5K_VERSION_VER,       AR5K_SREV_UNKNOWN },
        { "5110",       AR5K_VERSION_RAD,       AR5K_SREV_RAD_5110 },
        { "5111",       AR5K_VERSION_RAD,       AR5K_SREV_RAD_5111 },
@@ -132,6 +131,7 @@ static struct ath5k_srev_name srev_names[] = {
        { "5112A",      AR5K_VERSION_RAD,       AR5K_SREV_RAD_5112A },
        { "2112",       AR5K_VERSION_RAD,       AR5K_SREV_RAD_2112 },
        { "2112A",      AR5K_VERSION_RAD,       AR5K_SREV_RAD_2112A },
+       { "SChip",      AR5K_VERSION_RAD,       AR5K_SREV_RAD_SC0 },
        { "SChip",      AR5K_VERSION_RAD,       AR5K_SREV_RAD_SC1 },
        { "SChip",      AR5K_VERSION_RAD,       AR5K_SREV_RAD_SC2 },
        { "5133",       AR5K_VERSION_RAD,       AR5K_SREV_RAD_5133 },
@@ -167,8 +167,7 @@ static struct pci_driver ath5k_pci_driver = {
 /*
  * Prototypes - MAC 802.11 stack related functions
  */
-static int ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
-               struct ieee80211_tx_control *ctl);
+static int ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb);
 static int ath5k_reset(struct ieee80211_hw *hw);
 static int ath5k_start(struct ieee80211_hw *hw);
 static void ath5k_stop(struct ieee80211_hw *hw);
@@ -196,8 +195,7 @@ static int ath5k_get_tx_stats(struct ieee80211_hw *hw,
 static u64 ath5k_get_tsf(struct ieee80211_hw *hw);
 static void ath5k_reset_tsf(struct ieee80211_hw *hw);
 static int ath5k_beacon_update(struct ieee80211_hw *hw,
-               struct sk_buff *skb,
-               struct ieee80211_tx_control *ctl);
+               struct sk_buff *skb);
 
 static struct ieee80211_ops ath5k_hw_ops = {
        .tx             = ath5k_tx,
@@ -251,9 +249,7 @@ static void ath5k_desc_free(struct ath5k_softc *sc,
 static int     ath5k_rxbuf_setup(struct ath5k_softc *sc,
                                struct ath5k_buf *bf);
 static int     ath5k_txbuf_setup(struct ath5k_softc *sc,
-                               struct ath5k_buf *bf,
-                               struct ieee80211_tx_control *ctl);
-
+                               struct ath5k_buf *bf);
 static inline void ath5k_txbuf_free(struct ath5k_softc *sc,
                                struct ath5k_buf *bf)
 {
@@ -280,7 +276,8 @@ static int  ath5k_rx_start(struct ath5k_softc *sc);
 static void    ath5k_rx_stop(struct ath5k_softc *sc);
 static unsigned int ath5k_rx_decrypted(struct ath5k_softc *sc,
                                        struct ath5k_desc *ds,
-                                       struct sk_buff *skb);
+                                       struct sk_buff *skb,
+                                       struct ath5k_rx_status *rs);
 static void    ath5k_tasklet_rx(unsigned long data);
 /* Tx handling */
 static void    ath5k_tx_processq(struct ath5k_softc *sc,
@@ -288,8 +285,7 @@ static void         ath5k_tx_processq(struct ath5k_softc *sc,
 static void    ath5k_tasklet_tx(unsigned long data);
 /* Beacon handling */
 static int     ath5k_beacon_setup(struct ath5k_softc *sc,
-                               struct ath5k_buf *bf,
-                               struct ieee80211_tx_control *ctl);
+                                       struct ath5k_buf *bf);
 static void    ath5k_beacon_send(struct ath5k_softc *sc);
 static void    ath5k_beacon_config(struct ath5k_softc *sc);
 static void    ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf);
@@ -457,13 +453,11 @@ ath5k_pci_probe(struct pci_dev *pdev,
 
        /* Initialize driver private data */
        SET_IEEE80211_DEV(hw, &pdev->dev);
-       hw->flags = IEEE80211_HW_RX_INCLUDES_FCS;
+       hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
+                   IEEE80211_HW_SIGNAL_DBM |
+                   IEEE80211_HW_NOISE_DBM;
        hw->extra_tx_headroom = 2;
        hw->channel_change_time = 5000;
-       /* these names are misleading */
-       hw->max_rssi = -110; /* signal in dBm */
-       hw->max_noise = -110; /* noise in dBm */
-       hw->max_signal = 100; /* we will provide a percentage based on rssi */
        sc = hw->priv;
        sc->hw = hw;
        sc->pdev = pdev;
@@ -1296,36 +1290,36 @@ ath5k_rxbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
 }
 
 static int
-ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf,
-               struct ieee80211_tx_control *ctl)
+ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
 {
        struct ath5k_hw *ah = sc->ah;
        struct ath5k_txq *txq = sc->txq;
        struct ath5k_desc *ds = bf->desc;
        struct sk_buff *skb = bf->skb;
+       struct ieee80211_tx_info *info = (void*) skb->cb;
        unsigned int pktlen, flags, keyidx = AR5K_TXKEYIX_INVALID;
        int ret;
 
        flags = AR5K_TXDESC_INTREQ | AR5K_TXDESC_CLRDMASK;
-       bf->ctl = *ctl;
+
        /* XXX endianness */
        bf->skbaddr = pci_map_single(sc->pdev, skb->data, skb->len,
                        PCI_DMA_TODEVICE);
 
-       if (ctl->flags & IEEE80211_TXCTL_NO_ACK)
+       if (info->flags & IEEE80211_TX_CTL_NO_ACK)
                flags |= AR5K_TXDESC_NOACK;
 
        pktlen = skb->len;
 
-       if (!(ctl->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT)) {
-               keyidx = ctl->key_idx;
-               pktlen += ctl->icv_len;
+       if (!(info->flags & IEEE80211_TX_CTL_DO_NOT_ENCRYPT)) {
+               keyidx = info->control.hw_key->hw_key_idx;
+               pktlen += info->control.icv_len;
        }
-
        ret = ah->ah_setup_tx_desc(ah, ds, pktlen,
                ieee80211_get_hdrlen_from_skb(skb), AR5K_PKT_TYPE_NORMAL,
-               (sc->power_level * 2), ctl->tx_rate->hw_value,
-               ctl->retry_limit, keyidx, 0, flags, 0, 0);
+               (sc->power_level * 2),
+               ieee80211_get_tx_rate(sc->hw, info)->hw_value,
+               info->control.retry_limit, keyidx, 0, flags, 0, 0);
        if (ret)
                goto err_unmap;
 
@@ -1334,7 +1328,7 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf,
 
        spin_lock_bh(&txq->lock);
        list_add_tail(&bf->list, &txq->q);
-       sc->tx_stats.data[txq->qnum].len++;
+       sc->tx_stats[txq->qnum].len++;
        if (txq->link == NULL) /* is this first packet? */
                ath5k_hw_put_tx_buf(ah, txq->qnum, bf->daddr);
        else /* no, so only link it */
@@ -1560,13 +1554,12 @@ ath5k_txq_drainq(struct ath5k_softc *sc, struct ath5k_txq *txq)
         */
        spin_lock_bh(&txq->lock);
        list_for_each_entry_safe(bf, bf0, &txq->q, list) {
-               ath5k_debug_printtxbuf(sc, bf, !sc->ah->ah_proc_tx_desc(sc->ah,
-                                       bf->desc));
+               ath5k_debug_printtxbuf(sc, bf);
 
                ath5k_txbuf_free(sc, bf);
 
                spin_lock_bh(&sc->txbuflock);
-               sc->tx_stats.data[txq->qnum].len--;
+               sc->tx_stats[txq->qnum].len--;
                list_move_tail(&bf->list, &sc->txbuf);
                sc->txbuf_len++;
                spin_unlock_bh(&sc->txbuflock);
@@ -1601,7 +1594,7 @@ ath5k_txq_cleanup(struct ath5k_softc *sc)
                                        sc->txqs[i].link);
                        }
        }
-       ieee80211_start_queues(sc->hw); /* XXX move to callers */
+       ieee80211_wake_queues(sc->hw); /* XXX move to callers */
 
        for (i = 0; i < ARRAY_SIZE(sc->txqs); i++)
                if (sc->txqs[i].setup)
@@ -1686,20 +1679,20 @@ ath5k_rx_stop(struct ath5k_softc *sc)
 
 static unsigned int
 ath5k_rx_decrypted(struct ath5k_softc *sc, struct ath5k_desc *ds,
-               struct sk_buff *skb)
+               struct sk_buff *skb, struct ath5k_rx_status *rs)
 {
        struct ieee80211_hdr *hdr = (void *)skb->data;
        unsigned int keyix, hlen = ieee80211_get_hdrlen_from_skb(skb);
 
-       if (!(ds->ds_rxstat.rs_status & AR5K_RXERR_DECRYPT) &&
-                       ds->ds_rxstat.rs_keyix != AR5K_RXKEYIX_INVALID)
+       if (!(rs->rs_status & AR5K_RXERR_DECRYPT) &&
+                       rs->rs_keyix != AR5K_RXKEYIX_INVALID)
                return RX_FLAG_DECRYPTED;
 
        /* Apparently when a default key is used to decrypt the packet
           the hw does not set the index used to decrypt.  In such cases
           get the index from the packet. */
        if ((le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_PROTECTED) &&
-                       !(ds->ds_rxstat.rs_status & AR5K_RXERR_DECRYPT) &&
+                       !(rs->rs_status & AR5K_RXERR_DECRYPT) &&
                        skb->len >= hlen + 4) {
                keyix = skb->data[hlen + 3] >> 6;
 
@@ -1712,8 +1705,10 @@ ath5k_rx_decrypted(struct ath5k_softc *sc, struct ath5k_desc *ds,
 
 
 static void
-ath5k_check_ibss_hw_merge(struct ath5k_softc *sc, struct sk_buff *skb)
+ath5k_check_ibss_tsf(struct ath5k_softc *sc, struct sk_buff *skb,
+                    struct ieee80211_rx_status *rxs)
 {
+       u64 tsf, bc_tstamp;
        u32 hw_tu;
        struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data;
 
@@ -1724,16 +1719,48 @@ ath5k_check_ibss_hw_merge(struct ath5k_softc *sc, struct sk_buff *skb)
            le16_to_cpu(mgmt->u.beacon.capab_info) & WLAN_CAPABILITY_IBSS &&
            memcmp(mgmt->bssid, sc->ah->ah_bssid, ETH_ALEN) == 0) {
                /*
-                * Received an IBSS beacon with the same BSSID. Hardware might
-                * have updated the TSF, check if we need to update timers.
+                * Received an IBSS beacon with the same BSSID. Hardware *must*
+                * have updated the local TSF. We have to work around various
+                * hardware bugs, though...
+                */
+               tsf = ath5k_hw_get_tsf64(sc->ah);
+               bc_tstamp = le64_to_cpu(mgmt->u.beacon.timestamp);
+               hw_tu = TSF_TO_TU(tsf);
+
+               ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON,
+                       "beacon %llx mactime %llx (diff %lld) tsf now %llx\n",
+                       (unsigned long long)bc_tstamp,
+                       (unsigned long long)rxs->mactime,
+                       (unsigned long long)(rxs->mactime - bc_tstamp),
+                       (unsigned long long)tsf);
+
+               /*
+                * Sometimes the HW will give us a wrong tstamp in the rx
+                * status, causing the timestamp extension to go wrong.
+                * (This seems to happen especially with beacon frames bigger
+                * than 78 byte (incl. FCS))
+                * But we know that the receive timestamp must be later than the
+                * timestamp of the beacon since HW must have synced to that.
+                *
+                * NOTE: here we assume mactime to be after the frame was
+                * received, not like mac80211 which defines it at the start.
                 */
-               hw_tu = TSF_TO_TU(ath5k_hw_get_tsf64(sc->ah));
-               if (hw_tu >= sc->nexttbtt) {
-                       ath5k_beacon_update_timers(sc,
-                               le64_to_cpu(mgmt->u.beacon.timestamp));
+               if (bc_tstamp > rxs->mactime) {
                        ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON,
-                               "detected HW merge from received beacon\n");
+                               "fixing mactime from %llx to %llx\n",
+                               (unsigned long long)rxs->mactime,
+                               (unsigned long long)tsf);
+                       rxs->mactime = tsf;
                }
+
+               /*
+                * Local TSF might have moved higher than our beacon timers,
+                * in that case we have to update them to continue sending
+                * beacons. This also takes care of synchronizing beacon sending
+                * times with other stations.
+                */
+               if (hw_tu >= sc->nexttbtt)
+                       ath5k_beacon_update_timers(sc, bc_tstamp);
        }
 }
 
@@ -1742,18 +1769,19 @@ static void
 ath5k_tasklet_rx(unsigned long data)
 {
        struct ieee80211_rx_status rxs = {};
+       struct ath5k_rx_status rs = {};
        struct sk_buff *skb;
        struct ath5k_softc *sc = (void *)data;
        struct ath5k_buf *bf;
        struct ath5k_desc *ds;
-       u16 len;
-       u8 stat;
        int ret;
        int hdrlen;
        int pad;
 
        spin_lock(&sc->rxbuflock);
        do {
+               rxs.flag = 0;
+
                if (unlikely(list_empty(&sc->rxbuf))) {
                        ATH5K_WARN(sc, "empty rx buf pool\n");
                        break;
@@ -1770,7 +1798,7 @@ ath5k_tasklet_rx(unsigned long data)
                if (unlikely(ds->ds_link == bf->daddr)) /* this is the end */
                        break;
 
-               ret = sc->ah->ah_proc_rx_desc(sc->ah, ds);
+               ret = sc->ah->ah_proc_rx_desc(sc->ah, ds, &rs);
                if (unlikely(ret == -EINPROGRESS))
                        break;
                else if (unlikely(ret)) {
@@ -1779,16 +1807,15 @@ ath5k_tasklet_rx(unsigned long data)
                        return;
                }
 
-               if (unlikely(ds->ds_rxstat.rs_more)) {
+               if (unlikely(rs.rs_more)) {
                        ATH5K_WARN(sc, "unsupported jumbo\n");
                        goto next;
                }
 
-               stat = ds->ds_rxstat.rs_status;
-               if (unlikely(stat)) {
-                       if (stat & AR5K_RXERR_PHY)
+               if (unlikely(rs.rs_status)) {
+                       if (rs.rs_status & AR5K_RXERR_PHY)
                                goto next;
-                       if (stat & AR5K_RXERR_DECRYPT) {
+                       if (rs.rs_status & AR5K_RXERR_DECRYPT) {
                                /*
                                 * Decrypt error.  If the error occurred
                                 * because there was no hardware key, then
@@ -1799,30 +1826,29 @@ ath5k_tasklet_rx(unsigned long data)
                                 *
                                 * XXX do key cache faulting
                                 */
-                               if (ds->ds_rxstat.rs_keyix ==
-                                               AR5K_RXKEYIX_INVALID &&
-                                               !(stat & AR5K_RXERR_CRC))
+                               if (rs.rs_keyix == AR5K_RXKEYIX_INVALID &&
+                                   !(rs.rs_status & AR5K_RXERR_CRC))
                                        goto accept;
                        }
-                       if (stat & AR5K_RXERR_MIC) {
+                       if (rs.rs_status & AR5K_RXERR_MIC) {
                                rxs.flag |= RX_FLAG_MMIC_ERROR;
                                goto accept;
                        }
 
                        /* let crypto-error packets fall through in MNTR */
-                       if ((stat & ~(AR5K_RXERR_DECRYPT|AR5K_RXERR_MIC)) ||
+                       if ((rs.rs_status &
+                               ~(AR5K_RXERR_DECRYPT|AR5K_RXERR_MIC)) ||
                                        sc->opmode != IEEE80211_IF_TYPE_MNTR)
                                goto next;
                }
 accept:
-               len = ds->ds_rxstat.rs_datalen;
-               pci_dma_sync_single_for_cpu(sc->pdev, bf->skbaddr, len,
-                               PCI_DMA_FROMDEVICE);
+               pci_dma_sync_single_for_cpu(sc->pdev, bf->skbaddr,
+                               rs.rs_datalen, PCI_DMA_FROMDEVICE);
                pci_unmap_single(sc->pdev, bf->skbaddr, sc->rxbufsize,
                                PCI_DMA_FROMDEVICE);
                bf->skb = NULL;
 
-               skb_put(skb, len);
+               skb_put(skb, rs.rs_datalen);
 
                /*
                 * the hardware adds a padding to 4 byte boundaries between
@@ -1844,41 +1870,40 @@ accept:
                 * 15bit only. that means TSF extension has to be done within
                 * 32768usec (about 32ms). it might be necessary to move this to
                 * the interrupt handler, like it is done in madwifi.
+                *
+                * Unfortunately we don't know when the hardware takes the rx
+                * timestamp (beginning of phy frame, data frame, end of rx?).
+                * The only thing we know is that it is hardware specific...
+                * On AR5213 it seems the rx timestamp is at the end of the
+                * frame, but i'm not sure.
+                *
+                * NOTE: mac80211 defines mactime at the beginning of the first
+                * data symbol. Since we don't have any time references it's
+                * impossible to comply to that. This affects IBSS merge only
+                * right now, so it's not too bad...
                 */
-               rxs.mactime = ath5k_extend_tsf(sc->ah, ds->ds_rxstat.rs_tstamp);
+               rxs.mactime = ath5k_extend_tsf(sc->ah, rs.rs_tstamp);
                rxs.flag |= RX_FLAG_TSFT;
 
                rxs.freq = sc->curchan->center_freq;
                rxs.band = sc->curband->band;
 
-               /*
-                * signal quality:
-                * the names here are misleading and the usage of these
-                * values by iwconfig makes it even worse
-                */
-               /* noise floor in dBm, from the last noise calibration */
                rxs.noise = sc->ah->ah_noise_floor;
-               /* signal level in dBm */
-               rxs.ssi = rxs.noise + ds->ds_rxstat.rs_rssi;
-               /*
-                * "signal" is actually displayed as Link Quality by iwconfig
-                * we provide a percentage based on rssi (assuming max rssi 64)
-                */
-               rxs.signal = ds->ds_rxstat.rs_rssi * 100 / 64;
+               rxs.signal = rxs.noise + rs.rs_rssi;
+               rxs.qual = rs.rs_rssi * 100 / 64;
 
-               rxs.antenna = ds->ds_rxstat.rs_antenna;
-               rxs.rate_idx = ath5k_hw_to_driver_rix(sc,
-                       ds->ds_rxstat.rs_rate);
-               rxs.flag |= ath5k_rx_decrypted(sc, ds, skb);
+               rxs.antenna = rs.rs_antenna;
+               rxs.rate_idx = ath5k_hw_to_driver_rix(sc, rs.rs_rate);
+               rxs.flag |= ath5k_rx_decrypted(sc, ds, skb, &rs);
 
                ath5k_debug_dump_skb(sc, skb, "RX  ", 0);
 
                /* check beacons in IBSS mode */
                if (sc->opmode == IEEE80211_IF_TYPE_IBSS)
-                       ath5k_check_ibss_hw_merge(sc, skb);
+                       ath5k_check_ibss_tsf(sc, skb, &rxs);
 
                __ieee80211_rx(sc->hw, skb, &rxs);
-               sc->led_rxrate = ds->ds_rxstat.rs_rate;
+               sc->led_rxrate = rs.rs_rate;
                ath5k_led_event(sc, ATH_LED_RX);
 next:
                list_move_tail(&bf->list, &sc->rxbuf);
@@ -1896,10 +1921,11 @@ next:
 static void
 ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq)
 {
-       struct ieee80211_tx_status txs = {};
+       struct ath5k_tx_status ts = {};
        struct ath5k_buf *bf, *bf0;
        struct ath5k_desc *ds;
        struct sk_buff *skb;
+       struct ieee80211_tx_info *info;
        int ret;
 
        spin_lock(&txq->lock);
@@ -1909,7 +1935,7 @@ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq)
                /* TODO only one segment */
                pci_dma_sync_single_for_cpu(sc->pdev, sc->desc_daddr,
                                sc->desc_len, PCI_DMA_FROMDEVICE);
-               ret = sc->ah->ah_proc_tx_desc(sc->ah, ds);
+               ret = sc->ah->ah_proc_tx_desc(sc->ah, ds, &ts);
                if (unlikely(ret == -EINPROGRESS))
                        break;
                else if (unlikely(ret)) {
@@ -1919,29 +1945,29 @@ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq)
                }
 
                skb = bf->skb;
+               info = (void*) skb->cb;
                bf->skb = NULL;
+
                pci_unmap_single(sc->pdev, bf->skbaddr, skb->len,
                                PCI_DMA_TODEVICE);
 
-               txs.control = bf->ctl;
-               txs.retry_count = ds->ds_txstat.ts_shortretry +
-                       ds->ds_txstat.ts_longretry / 6;
-               if (unlikely(ds->ds_txstat.ts_status)) {
+               info->status.retry_count = ts.ts_shortretry + ts.ts_longretry / 6;
+               if (unlikely(ts.ts_status)) {
                        sc->ll_stats.dot11ACKFailureCount++;
-                       if (ds->ds_txstat.ts_status & AR5K_TXERR_XRETRY)
-                               txs.excessive_retries = 1;
-                       else if (ds->ds_txstat.ts_status & AR5K_TXERR_FILT)
-                               txs.flags |= IEEE80211_TX_STATUS_TX_FILTERED;
+                       if (ts.ts_status & AR5K_TXERR_XRETRY)
+                               info->status.excessive_retries = 1;
+                       else if (ts.ts_status & AR5K_TXERR_FILT)
+                               info->flags |= IEEE80211_TX_STAT_TX_FILTERED;
                } else {
-                       txs.flags |= IEEE80211_TX_STATUS_ACK;
-                       txs.ack_signal = ds->ds_txstat.ts_rssi;
+                       info->flags |= IEEE80211_TX_STAT_ACK;
+                       info->status.ack_signal = ts.ts_rssi;
                }
 
-               ieee80211_tx_status(sc->hw, skb, &txs);
-               sc->tx_stats.data[txq->qnum].count++;
+               ieee80211_tx_status(sc->hw, skb);
+               sc->tx_stats[txq->qnum].count++;
 
                spin_lock(&sc->txbuflock);
-               sc->tx_stats.data[txq->qnum].len--;
+               sc->tx_stats[txq->qnum].len--;
                list_move_tail(&bf->list, &sc->txbuf);
                sc->txbuf_len++;
                spin_unlock(&sc->txbuflock);
@@ -1974,10 +2000,10 @@ ath5k_tasklet_tx(unsigned long data)
  * Setup the beacon frame for transmit.
  */
 static int
-ath5k_beacon_setup(struct ath5k_softc *sc, struct ath5k_buf *bf,
-               struct ieee80211_tx_control *ctl)
+ath5k_beacon_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
 {
        struct sk_buff *skb = bf->skb;
+       struct  ieee80211_tx_info *info = (void*) skb->cb;
        struct ath5k_hw *ah = sc->ah;
        struct ath5k_desc *ds;
        int ret, antenna = 0;
@@ -2016,7 +2042,8 @@ ath5k_beacon_setup(struct ath5k_softc *sc, struct ath5k_buf *bf,
        ret = ah->ah_setup_tx_desc(ah, ds, skb->len,
                        ieee80211_get_hdrlen_from_skb(skb),
                        AR5K_PKT_TYPE_BEACON, (sc->power_level * 2),
-                       ctl->tx_rate->hw_value, 1, AR5K_TXKEYIX_INVALID,
+                       ieee80211_get_tx_rate(sc->hw, info)->hw_value,
+                       1, AR5K_TXKEYIX_INVALID,
                        antenna, flags, 0, 0);
        if (ret)
                goto err_unmap;
@@ -2108,7 +2135,7 @@ ath5k_beacon_send(struct ath5k_softc *sc)
  * beacon timer registers.
  *
  * This is called in a variety of situations, e.g. when a beacon is received,
- * when a HW merge has been detected, but also when an new IBSS is created or
+ * when a TSF update has been detected, but also when an new IBSS is created or
  * when we otherwise know we have to update the timers, but we keep it in this
  * function to have it all together in one place.
  */
@@ -2208,7 +2235,7 @@ ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf)
  * another AP to associate with.
  *
  * In IBSS mode we use a self-linked tx descriptor if possible. We enable SWBA
- * interrupts to detect HW merges only.
+ * interrupts to detect TSF updates only.
  *
  * AP mode is missing.
  */
@@ -2228,7 +2255,7 @@ ath5k_beacon_config(struct ath5k_softc *sc)
                 * hardware send the beacons automatically. We have to load it
                 * only once here.
                 * We use the SWBA interrupt only to keep track of the beacon
-                * timers in order to detect HW merges (automatic TSF updates).
+                * timers in order to detect automatic TSF updates.
                 */
                ath5k_beaconq_config(sc);
 
@@ -2297,7 +2324,8 @@ ath5k_init(struct ath5k_softc *sc)
         * Enable interrupts.
         */
        sc->imask = AR5K_INT_RX | AR5K_INT_TX | AR5K_INT_RXEOL |
-               AR5K_INT_RXORN | AR5K_INT_FATAL | AR5K_INT_GLOBAL;
+               AR5K_INT_RXORN | AR5K_INT_FATAL | AR5K_INT_GLOBAL |
+               AR5K_INT_MIB;
 
        ath5k_hw_set_intr(sc->ah, sc->imask);
        /* Set ack to be sent at low bit-rates */
@@ -2441,8 +2469,8 @@ ath5k_intr(int irq, void *dev_id)
                                *
                                * In IBSS mode we use this interrupt just to
                                * keep track of the next TBTT (target beacon
-                               * transmission time) in order to detect hardware
-                               * merges (TSF updates).
+                               * transmission time) in order to detect wether
+                               * automatic TSF updates happened.
                                */
                                if (sc->opmode == IEEE80211_IF_TYPE_IBSS) {
                                         /* XXX: only if VEOL suppported */
@@ -2477,7 +2505,11 @@ ath5k_intr(int irq, void *dev_id)
                        if (status & AR5K_INT_BMISS) {
                        }
                        if (status & AR5K_INT_MIB) {
-                               /* TODO */
+                               /*
+                                * These stats are also used for ANI i think
+                                * so how about updating them more often ?
+                                */
+                               ath5k_hw_update_mib_counters(ah, &sc->ll_stats);
                        }
                }
        } while (ath5k_hw_is_intr_pending(ah) && counter-- > 0);
@@ -2589,11 +2621,11 @@ ath5k_led_event(struct ath5k_softc *sc, int event)
 \********************/
 
 static int
-ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
-                       struct ieee80211_tx_control *ctl)
+ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 {
        struct ath5k_softc *sc = hw->priv;
        struct ath5k_buf *bf;
+       struct ieee80211_tx_info *info = (void*) skb->cb;
        unsigned long flags;
        int hdrlen;
        int pad;
@@ -2619,13 +2651,13 @@ ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
                memmove(skb->data, skb->data+pad, hdrlen);
        }
 
-       sc->led_txrate = ctl->tx_rate->hw_value;
+       sc->led_txrate = ieee80211_get_tx_rate(hw, info)->hw_value;
 
        spin_lock_irqsave(&sc->txbuflock, flags);
        if (list_empty(&sc->txbuf)) {
                ATH5K_ERR(sc, "no further txbuf available, dropping packet\n");
                spin_unlock_irqrestore(&sc->txbuflock, flags);
-               ieee80211_stop_queue(hw, ctl->queue);
+               ieee80211_stop_queue(hw, skb_get_queue_mapping(skb));
                return -1;
        }
        bf = list_first_entry(&sc->txbuf, struct ath5k_buf, list);
@@ -2637,7 +2669,7 @@ ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
 
        bf->skb = skb;
 
-       if (ath5k_txbuf_setup(sc, bf, ctl)) {
+       if (ath5k_txbuf_setup(sc, bf)) {
                bf->skb = NULL;
                spin_lock_irqsave(&sc->txbuflock, flags);
                list_add_tail(&bf->list, &sc->txbuf);
@@ -2859,9 +2891,9 @@ static void ath5k_configure_filter(struct ieee80211_hw *hw,
                        if (!mclist)
                                break;
                        /* calculate XOR of eight 6-bit values */
-                       val = LE_READ_4(mclist->dmi_addr + 0);
+                       val = get_unaligned_le32(mclist->dmi_addr + 0);
                        pos = (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val;
-                       val = LE_READ_4(mclist->dmi_addr + 3);
+                       val = get_unaligned_le32(mclist->dmi_addr + 3);
                        pos ^= (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val;
                        pos &= 0x3f;
                        mfilt[pos / 32] |= (1 << (pos % 32));
@@ -2970,6 +3002,10 @@ ath5k_get_stats(struct ieee80211_hw *hw,
                struct ieee80211_low_level_stats *stats)
 {
        struct ath5k_softc *sc = hw->priv;
+       struct ath5k_hw *ah = sc->ah;
+
+       /* Force update */
+       ath5k_hw_update_mib_counters(ah, &sc->ll_stats);
 
        memcpy(stats, &sc->ll_stats, sizeof(sc->ll_stats));
 
@@ -3011,8 +3047,7 @@ ath5k_reset_tsf(struct ieee80211_hw *hw)
 }
 
 static int
-ath5k_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
-                       struct ieee80211_tx_control *ctl)
+ath5k_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb)
 {
        struct ath5k_softc *sc = hw->priv;
        int ret;
@@ -3028,7 +3063,7 @@ ath5k_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
 
        ath5k_txbuf_free(sc, sc->bbuf);
        sc->bbuf->skb = skb;
-       ret = ath5k_beacon_setup(sc, sc->bbuf, ctl);
+       ret = ath5k_beacon_setup(sc, sc->bbuf);
        if (ret)
                sc->bbuf->skb = NULL;
        else
This page took 0.034294 seconds and 5 git commands to generate.