#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,
{ "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 },
/*
* 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);
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,
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)
{
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);
/* 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;
}
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;
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 */
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);
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)
ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON,
"beacon %llx mactime %llx (diff %lld) tsf now %llx\n",
- bc_tstamp, rxs->mactime,
- (rxs->mactime - bc_tstamp), tsf);
+ (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
if (bc_tstamp > rxs->mactime) {
ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON,
"fixing mactime from %llx to %llx\n",
- rxs->mactime, tsf);
+ (unsigned long long)rxs->mactime,
+ (unsigned long long)tsf);
rxs->mactime = tsf;
}
spin_lock(&sc->rxbuflock);
do {
+ rxs.flag = 0;
+
if (unlikely(list_empty(&sc->rxbuf))) {
ATH5K_WARN(sc, "empty rx buf pool\n");
break;
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 + rs.rs_rssi;
- /*
- * "signal" is actually displayed as Link Quality by iwconfig
- * we provide a percentage based on rssi (assuming max rssi 64)
- */
- rxs.signal = rs.rs_rssi * 100 / 64;
+ rxs.signal = rxs.noise + rs.rs_rssi;
+ rxs.qual = rs.rs_rssi * 100 / 64;
rxs.antenna = rs.rs_antenna;
rxs.rate_idx = ath5k_hw_to_driver_rix(sc, rs.rs_rate);
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);
}
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 = ts.ts_shortretry + ts.ts_longretry / 6;
+ info->status.retry_count = ts.ts_shortretry + ts.ts_longretry / 6;
if (unlikely(ts.ts_status)) {
sc->ll_stats.dot11ACKFailureCount++;
if (ts.ts_status & AR5K_TXERR_XRETRY)
- txs.excessive_retries = 1;
+ info->status.excessive_retries = 1;
else if (ts.ts_status & AR5K_TXERR_FILT)
- txs.flags |= IEEE80211_TX_STATUS_TX_FILTERED;
+ info->flags |= IEEE80211_TX_STAT_TX_FILTERED;
} else {
- txs.flags |= IEEE80211_TX_STATUS_ACK;
- txs.ack_signal = ts.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);
* 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;
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;
* 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 */
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);
\********************/
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;
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);
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);
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));
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));
}
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;
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