Commit 0967e01e authored by Thomas Huehn's avatar Thomas Huehn Committed by John W. Linville

ath5k: make use of the new rate control API

This patch enabels ath5k to use the new rate table to lookup each
mrr rate and retry information per packet.
Signed-off-by: default avatarBenjamin Vahl <bvahl@net.t-labs.tu-berlin.de>
Signed-off-by: default avatarThomas Huehn <thomas@net.t-labs.tu-berlin.de>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent d3bcb7b2
...@@ -60,6 +60,7 @@ ...@@ -60,6 +60,7 @@
#include <asm/unaligned.h> #include <asm/unaligned.h>
#include <net/mac80211.h>
#include "base.h" #include "base.h"
#include "reg.h" #include "reg.h"
#include "debug.h" #include "debug.h"
...@@ -666,9 +667,46 @@ static enum ath5k_pkt_type get_hw_packet_type(struct sk_buff *skb) ...@@ -666,9 +667,46 @@ static enum ath5k_pkt_type get_hw_packet_type(struct sk_buff *skb)
return htype; return htype;
} }
static struct ieee80211_rate *
ath5k_get_rate(const struct ieee80211_hw *hw,
const struct ieee80211_tx_info *info,
struct ath5k_buf *bf, int idx)
{
/*
* convert a ieee80211_tx_rate RC-table entry to
* the respective ieee80211_rate struct
*/
if (bf->rates[idx].idx < 0) {
return NULL;
}
return &hw->wiphy->bands[info->band]->bitrates[ bf->rates[idx].idx ];
}
static u16
ath5k_get_rate_hw_value(const struct ieee80211_hw *hw,
const struct ieee80211_tx_info *info,
struct ath5k_buf *bf, int idx)
{
struct ieee80211_rate *rate;
u16 hw_rate;
u8 rc_flags;
rate = ath5k_get_rate(hw, info, bf, idx);
if (!rate)
return 0;
rc_flags = bf->rates[idx].flags;
hw_rate = (rc_flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) ?
rate->hw_value_short : rate->hw_value;
return hw_rate;
}
static int static int
ath5k_txbuf_setup(struct ath5k_hw *ah, struct ath5k_buf *bf, ath5k_txbuf_setup(struct ath5k_hw *ah, struct ath5k_buf *bf,
struct ath5k_txq *txq, int padsize) struct ath5k_txq *txq, int padsize,
struct ieee80211_tx_control *control)
{ {
struct ath5k_desc *ds = bf->desc; struct ath5k_desc *ds = bf->desc;
struct sk_buff *skb = bf->skb; struct sk_buff *skb = bf->skb;
...@@ -688,7 +726,11 @@ ath5k_txbuf_setup(struct ath5k_hw *ah, struct ath5k_buf *bf, ...@@ -688,7 +726,11 @@ ath5k_txbuf_setup(struct ath5k_hw *ah, struct ath5k_buf *bf,
bf->skbaddr = dma_map_single(ah->dev, skb->data, skb->len, bf->skbaddr = dma_map_single(ah->dev, skb->data, skb->len,
DMA_TO_DEVICE); DMA_TO_DEVICE);
rate = ieee80211_get_tx_rate(ah->hw, info); ieee80211_get_tx_rates(info->control.vif, (control) ? control->sta : NULL, skb, bf->rates,
ARRAY_SIZE(bf->rates));
rate = ath5k_get_rate(ah->hw, info, bf, 0);
if (!rate) { if (!rate) {
ret = -EINVAL; ret = -EINVAL;
goto err_unmap; goto err_unmap;
...@@ -698,8 +740,8 @@ ath5k_txbuf_setup(struct ath5k_hw *ah, struct ath5k_buf *bf, ...@@ -698,8 +740,8 @@ ath5k_txbuf_setup(struct ath5k_hw *ah, struct ath5k_buf *bf,
flags |= AR5K_TXDESC_NOACK; flags |= AR5K_TXDESC_NOACK;
rc_flags = info->control.rates[0].flags; rc_flags = info->control.rates[0].flags;
hw_rate = (rc_flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) ?
rate->hw_value_short : rate->hw_value; hw_rate = ath5k_get_rate_hw_value(ah->hw, info, bf, 0);
pktlen = skb->len; pktlen = skb->len;
...@@ -722,12 +764,13 @@ ath5k_txbuf_setup(struct ath5k_hw *ah, struct ath5k_buf *bf, ...@@ -722,12 +764,13 @@ ath5k_txbuf_setup(struct ath5k_hw *ah, struct ath5k_buf *bf,
duration = le16_to_cpu(ieee80211_ctstoself_duration(ah->hw, duration = le16_to_cpu(ieee80211_ctstoself_duration(ah->hw,
info->control.vif, pktlen, info)); info->control.vif, pktlen, info));
} }
ret = ah->ah_setup_tx_desc(ah, ds, pktlen, ret = ah->ah_setup_tx_desc(ah, ds, pktlen,
ieee80211_get_hdrlen_from_skb(skb), padsize, ieee80211_get_hdrlen_from_skb(skb), padsize,
get_hw_packet_type(skb), get_hw_packet_type(skb),
(ah->ah_txpower.txp_requested * 2), (ah->ah_txpower.txp_requested * 2),
hw_rate, hw_rate,
info->control.rates[0].count, keyidx, ah->ah_tx_ant, flags, bf->rates[0].count, keyidx, ah->ah_tx_ant, flags,
cts_rate, duration); cts_rate, duration);
if (ret) if (ret)
goto err_unmap; goto err_unmap;
...@@ -736,13 +779,15 @@ ath5k_txbuf_setup(struct ath5k_hw *ah, struct ath5k_buf *bf, ...@@ -736,13 +779,15 @@ ath5k_txbuf_setup(struct ath5k_hw *ah, struct ath5k_buf *bf,
if (ah->ah_capabilities.cap_has_mrr_support) { if (ah->ah_capabilities.cap_has_mrr_support) {
memset(mrr_rate, 0, sizeof(mrr_rate)); memset(mrr_rate, 0, sizeof(mrr_rate));
memset(mrr_tries, 0, sizeof(mrr_tries)); memset(mrr_tries, 0, sizeof(mrr_tries));
for (i = 0; i < 3; i++) { for (i = 0; i < 3; i++) {
rate = ieee80211_get_alt_retry_rate(ah->hw, info, i);
rate = ath5k_get_rate(ah->hw, info, bf, i);
if (!rate) if (!rate)
break; break;
mrr_rate[i] = rate->hw_value; mrr_rate[i] = ath5k_get_rate_hw_value(ah->hw, info, bf, i);
mrr_tries[i] = info->control.rates[i + 1].count; mrr_tries[i] = bf->rates[i].count;
} }
ath5k_hw_setup_mrr_tx_desc(ah, ds, ath5k_hw_setup_mrr_tx_desc(ah, ds,
...@@ -1515,7 +1560,7 @@ ath5k_tasklet_rx(unsigned long data) ...@@ -1515,7 +1560,7 @@ ath5k_tasklet_rx(unsigned long data)
void void
ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb, ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb,
struct ath5k_txq *txq) struct ath5k_txq *txq, struct ieee80211_tx_control *control)
{ {
struct ath5k_hw *ah = hw->priv; struct ath5k_hw *ah = hw->priv;
struct ath5k_buf *bf; struct ath5k_buf *bf;
...@@ -1555,7 +1600,7 @@ ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb, ...@@ -1555,7 +1600,7 @@ ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb,
bf->skb = skb; bf->skb = skb;
if (ath5k_txbuf_setup(ah, bf, txq, padsize)) { if (ath5k_txbuf_setup(ah, bf, txq, padsize, control)) {
bf->skb = NULL; bf->skb = NULL;
spin_lock_irqsave(&ah->txbuflock, flags); spin_lock_irqsave(&ah->txbuflock, flags);
list_add_tail(&bf->list, &ah->txbuf); list_add_tail(&bf->list, &ah->txbuf);
...@@ -1571,11 +1616,13 @@ ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb, ...@@ -1571,11 +1616,13 @@ ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb,
static void static void
ath5k_tx_frame_completed(struct ath5k_hw *ah, struct sk_buff *skb, ath5k_tx_frame_completed(struct ath5k_hw *ah, struct sk_buff *skb,
struct ath5k_txq *txq, struct ath5k_tx_status *ts) struct ath5k_txq *txq, struct ath5k_tx_status *ts,
struct ath5k_buf *bf)
{ {
struct ieee80211_tx_info *info; struct ieee80211_tx_info *info;
u8 tries[3]; u8 tries[3];
int i; int i;
int size = 0;
ah->stats.tx_all_count++; ah->stats.tx_all_count++;
ah->stats.tx_bytes_count += skb->len; ah->stats.tx_bytes_count += skb->len;
...@@ -1587,6 +1634,9 @@ ath5k_tx_frame_completed(struct ath5k_hw *ah, struct sk_buff *skb, ...@@ -1587,6 +1634,9 @@ ath5k_tx_frame_completed(struct ath5k_hw *ah, struct sk_buff *skb,
ieee80211_tx_info_clear_status(info); ieee80211_tx_info_clear_status(info);
size = min_t(int, sizeof(info->status.rates), sizeof(bf->rates));
memcpy(info->status.rates, bf->rates, size);
for (i = 0; i < ts->ts_final_idx; i++) { for (i = 0; i < ts->ts_final_idx; i++) {
struct ieee80211_tx_rate *r = struct ieee80211_tx_rate *r =
&info->status.rates[i]; &info->status.rates[i];
...@@ -1663,7 +1713,7 @@ ath5k_tx_processq(struct ath5k_hw *ah, struct ath5k_txq *txq) ...@@ -1663,7 +1713,7 @@ ath5k_tx_processq(struct ath5k_hw *ah, struct ath5k_txq *txq)
dma_unmap_single(ah->dev, bf->skbaddr, skb->len, dma_unmap_single(ah->dev, bf->skbaddr, skb->len,
DMA_TO_DEVICE); DMA_TO_DEVICE);
ath5k_tx_frame_completed(ah, skb, txq, &ts); ath5k_tx_frame_completed(ah, skb, txq, &ts, bf);
} }
/* /*
...@@ -1917,7 +1967,7 @@ ath5k_beacon_send(struct ath5k_hw *ah) ...@@ -1917,7 +1967,7 @@ ath5k_beacon_send(struct ath5k_hw *ah)
skb = ieee80211_get_buffered_bc(ah->hw, vif); skb = ieee80211_get_buffered_bc(ah->hw, vif);
while (skb) { while (skb) {
ath5k_tx_queue(ah->hw, skb, ah->cabq); ath5k_tx_queue(ah->hw, skb, ah->cabq, NULL);
if (ah->cabq->txq_len >= ah->cabq->txq_max) if (ah->cabq->txq_len >= ah->cabq->txq_max)
break; break;
...@@ -2442,7 +2492,8 @@ ath5k_init_ah(struct ath5k_hw *ah, const struct ath_bus_ops *bus_ops) ...@@ -2442,7 +2492,8 @@ ath5k_init_ah(struct ath5k_hw *ah, const struct ath_bus_ops *bus_ops)
IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_SIGNAL_DBM |
IEEE80211_HW_MFP_CAPABLE | IEEE80211_HW_MFP_CAPABLE |
IEEE80211_HW_REPORTS_TX_ACK_STATUS; IEEE80211_HW_REPORTS_TX_ACK_STATUS |
IEEE80211_HW_SUPPORTS_RC_TABLE;
hw->wiphy->interface_modes = hw->wiphy->interface_modes =
BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_AP) |
......
...@@ -47,6 +47,7 @@ struct ath5k_hw; ...@@ -47,6 +47,7 @@ struct ath5k_hw;
struct ath5k_txq; struct ath5k_txq;
struct ieee80211_channel; struct ieee80211_channel;
struct ath_bus_ops; struct ath_bus_ops;
struct ieee80211_tx_control;
enum nl80211_iftype; enum nl80211_iftype;
enum ath5k_srev_type { enum ath5k_srev_type {
...@@ -61,11 +62,12 @@ struct ath5k_srev_name { ...@@ -61,11 +62,12 @@ struct ath5k_srev_name {
}; };
struct ath5k_buf { struct ath5k_buf {
struct list_head list; struct list_head list;
struct ath5k_desc *desc; /* virtual addr of desc */ struct ath5k_desc *desc; /* virtual addr of desc */
dma_addr_t daddr; /* physical addr of desc */ dma_addr_t daddr; /* physical addr of desc */
struct sk_buff *skb; /* skbuff for buf */ struct sk_buff *skb; /* skbuff for buf */
dma_addr_t skbaddr;/* physical addr of skb data */ dma_addr_t skbaddr; /* physical addr of skb data */
struct ieee80211_tx_rate rates[4]; /* number of multi-rate stages */
}; };
struct ath5k_vif { struct ath5k_vif {
...@@ -103,7 +105,7 @@ int ath5k_chan_set(struct ath5k_hw *ah, struct ieee80211_channel *chan); ...@@ -103,7 +105,7 @@ int ath5k_chan_set(struct ath5k_hw *ah, struct ieee80211_channel *chan);
void ath5k_txbuf_free_skb(struct ath5k_hw *ah, struct ath5k_buf *bf); void ath5k_txbuf_free_skb(struct ath5k_hw *ah, struct ath5k_buf *bf);
void ath5k_rxbuf_free_skb(struct ath5k_hw *ah, struct ath5k_buf *bf); void ath5k_rxbuf_free_skb(struct ath5k_hw *ah, struct ath5k_buf *bf);
void ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb, void ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb,
struct ath5k_txq *txq); struct ath5k_txq *txq, struct ieee80211_tx_control *control);
const char *ath5k_chip_name(enum ath5k_srev_type type, u_int16_t val); const char *ath5k_chip_name(enum ath5k_srev_type type, u_int16_t val);
......
...@@ -66,7 +66,7 @@ ath5k_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control, ...@@ -66,7 +66,7 @@ ath5k_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control,
return; return;
} }
ath5k_tx_queue(hw, skb, &ah->txqs[qnum]); ath5k_tx_queue(hw, skb, &ah->txqs[qnum], control);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment