Skip to content

Commit

Permalink
mac80211/drivers: rewrite the rate control API
Browse files Browse the repository at this point in the history
So after the previous changes we were still unhappy with how
convoluted the API is and decided to make things simpler for
everybody. This completely changes the rate control API, now
taking into account 802.11n with MCS rates and more control,
most drivers don't support that though.

Signed-off-by: Felix Fietkau <[email protected]>
Signed-off-by: Johannes Berg <[email protected]>
Signed-off-by: John W. Linville <[email protected]>
  • Loading branch information
jmberg authored and linvjw committed Oct 31, 2008
1 parent cb121ba commit e6a9854
Show file tree
Hide file tree
Showing 47 changed files with 889 additions and 685 deletions.
21 changes: 11 additions & 10 deletions drivers/net/wireless/adm8211.c
Original file line number Diff line number Diff line change
Expand Up @@ -341,15 +341,14 @@ static void adm8211_interrupt_tci(struct ieee80211_hw *dev)
pci_unmap_single(priv->pdev, info->mapping,
info->skb->len, PCI_DMA_TODEVICE);

memset(&txi->status, 0, sizeof(txi->status));
ieee80211_tx_info_clear_status(txi);

skb_pull(skb, sizeof(struct adm8211_tx_hdr));
memcpy(skb_push(skb, info->hdrlen), skb->cb, info->hdrlen);
if (!(txi->flags & IEEE80211_TX_CTL_NO_ACK)) {
if (status & TDES0_STATUS_ES)
txi->status.excessive_retries = 1;
else
txi->flags |= IEEE80211_TX_STAT_ACK;
}
if (!(txi->flags & IEEE80211_TX_CTL_NO_ACK) &&
!(status & TDES0_STATUS_ES))
txi->flags |= IEEE80211_TX_STAT_ACK;

ieee80211_tx_status_irqsafe(dev, skb);

info->skb = NULL;
Expand Down Expand Up @@ -1691,8 +1690,10 @@ static int adm8211_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
struct ieee80211_hdr *hdr;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_rate *txrate = ieee80211_get_tx_rate(dev, info);
u8 rc_flags;

short_preamble = !!(txrate->flags & IEEE80211_TX_CTL_SHORT_PREAMBLE);
rc_flags = info->control.rates[0].flags;
short_preamble = !!(rc_flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE);
plcp_signal = txrate->bitrate;

hdr = (struct ieee80211_hdr *)skb->data;
Expand Down Expand Up @@ -1724,10 +1725,10 @@ static int adm8211_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
if (short_preamble)
txhdr->header_control |= cpu_to_le16(ADM8211_TXHDRCTL_SHORT_PREAMBLE);

if (info->flags & IEEE80211_TX_CTL_USE_RTS_CTS)
if (rc_flags & IEEE80211_TX_RC_USE_RTS_CTS)
txhdr->header_control |= cpu_to_le16(ADM8211_TXHDRCTL_ENABLE_RTS);

txhdr->retry_limit = info->control.retry_limit;
txhdr->retry_limit = info->control.rates[0].count;

adm8211_tx_raw(dev, skb, plcp_signal, hdrlen);

Expand Down
34 changes: 15 additions & 19 deletions drivers/net/wireless/ath5k/base.c
Original file line number Diff line number Diff line change
Expand Up @@ -541,8 +541,8 @@ ath5k_pci_probe(struct pci_dev *pdev,

/* set up multi-rate retry capabilities */
if (sc->ah->ah_version == AR5K_AR5212) {
hw->max_altrates = 3;
hw->max_altrate_tries = 11;
hw->max_rates = 4;
hw->max_rate_tries = 11;
}

/* Finish private driver data initialization */
Expand Down Expand Up @@ -1181,7 +1181,7 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
ieee80211_get_hdrlen_from_skb(skb), AR5K_PKT_TYPE_NORMAL,
(sc->power_level * 2),
ieee80211_get_tx_rate(sc->hw, info)->hw_value,
info->control.retry_limit, keyidx, 0, flags, 0, 0);
info->control.rates[0].count, keyidx, 0, flags, 0, 0);
if (ret)
goto err_unmap;

Expand All @@ -1193,7 +1193,7 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
break;

mrr_rate[i] = rate->hw_value;
mrr_tries[i] = info->control.retries[i].limit;
mrr_tries[i] = info->control.rates[i + 1].count;
}

ah->ah_setup_mrr_tx_desc(ah, ds,
Expand Down Expand Up @@ -1849,30 +1849,26 @@ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq)
pci_unmap_single(sc->pdev, bf->skbaddr, skb->len,
PCI_DMA_TODEVICE);

memset(&info->status, 0, sizeof(info->status));
info->tx_rate_idx = ath5k_hw_to_driver_rix(sc,
ts.ts_rate[ts.ts_final_idx]);
info->status.retry_count = ts.ts_longretry;

ieee80211_tx_info_clear_status(info);
for (i = 0; i < 4; i++) {
struct ieee80211_tx_altrate *r =
&info->status.retries[i];
struct ieee80211_tx_rate *r =
&info->status.rates[i];

if (ts.ts_rate[i]) {
r->rate_idx = ath5k_hw_to_driver_rix(sc, ts.ts_rate[i]);
r->limit = ts.ts_retry[i];
r->idx = ath5k_hw_to_driver_rix(sc, ts.ts_rate[i]);
r->count = ts.ts_retry[i];
} else {
r->rate_idx = -1;
r->limit = 0;
r->idx = -1;
r->count = 0;
}
}

info->status.excessive_retries = 0;
/* count the successful attempt as well */
info->status.rates[ts.ts_final_idx].count++;

if (unlikely(ts.ts_status)) {
sc->ll_stats.dot11ACKFailureCount++;
if (ts.ts_status & AR5K_TXERR_XRETRY)
info->status.excessive_retries = 1;
else if (ts.ts_status & AR5K_TXERR_FILT)
if (ts.ts_status & AR5K_TXERR_FILT)
info->flags |= IEEE80211_TX_STAT_TX_FILTERED;
} else {
info->flags |= IEEE80211_TX_STAT_ACK;
Expand Down
18 changes: 7 additions & 11 deletions drivers/net/wireless/ath9k/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -457,30 +457,26 @@ void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
DPRINTF(sc, ATH_DBG_XMIT,
"%s: TX complete: skb: %p\n", __func__, skb);

ieee80211_tx_info_clear_status(tx_info);
if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK ||
tx_info->flags & IEEE80211_TX_STAT_TX_FILTERED) {
/* free driver's private data area of tx_info */
if (tx_info->driver_data[0] != NULL)
kfree(tx_info->driver_data[0]);
tx_info->driver_data[0] = NULL;
/* free driver's private data area of tx_info, XXX: HACK! */
if (tx_info->control.vif != NULL)
kfree(tx_info->control.vif);
tx_info->control.vif = NULL;
}

if (tx_status->flags & ATH_TX_BAR) {
tx_info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK;
tx_status->flags &= ~ATH_TX_BAR;
}

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 {
if (!(tx_status->flags & (ATH_TX_ERROR | ATH_TX_XRETRY))) {
/* Frame was ACKed */
tx_info->flags |= IEEE80211_TX_STAT_ACK;
}

tx_info->status.retry_count = tx_status->retries;
tx_info->status.rates[0].count = tx_status->retries + 1;

ieee80211_tx_status(hw, skb);
if (an)
Expand Down
40 changes: 20 additions & 20 deletions drivers/net/wireless/ath9k/rc.c
Original file line number Diff line number Diff line change
Expand Up @@ -1864,24 +1864,21 @@ static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband,

hdr = (struct ieee80211_hdr *)skb->data;
fc = hdr->frame_control;
tx_info_priv = (struct ath_tx_info_priv *)tx_info->driver_data[0];
/* XXX: UGLY HACK!! */
tx_info_priv = (struct ath_tx_info_priv *)tx_info->control.vif;

spin_lock_bh(&sc->node_lock);
an = ath_node_find(sc, hdr->addr1);
spin_unlock_bh(&sc->node_lock);

if (!an || !priv_sta || !ieee80211_is_data(fc)) {
if (tx_info->driver_data[0] != NULL) {
kfree(tx_info->driver_data[0]);
tx_info->driver_data[0] = NULL;
}
if (tx_info_priv == NULL)
return;
}
if (tx_info->driver_data[0] != NULL) {

if (an && priv_sta && ieee80211_is_data(fc))
ath_rate_tx_complete(sc, an, priv_sta, tx_info_priv);
kfree(tx_info->driver_data[0]);
tx_info->driver_data[0] = NULL;
}

kfree(tx_info_priv);
tx_info->control.vif = NULL;
}

static void ath_tx_aggr_resp(struct ath_softc *sc,
Expand Down Expand Up @@ -1927,10 +1924,11 @@ static void ath_tx_aggr_resp(struct ath_softc *sc,
}
}

static void ath_get_rate(void *priv, struct ieee80211_supported_band *sband,
struct ieee80211_sta *sta, void *priv_sta,
struct sk_buff *skb, struct rate_selection *sel)
static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,
struct ieee80211_tx_rate_control *txrc)
{
struct ieee80211_supported_band *sband = txrc->sband;
struct sk_buff *skb = txrc->skb;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
struct ath_softc *sc = priv;
struct ieee80211_hw *hw = sc->hw;
Expand All @@ -1945,17 +1943,17 @@ static void ath_get_rate(void *priv, struct ieee80211_supported_band *sband,

DPRINTF(sc, ATH_DBG_RATE, "%s\n", __func__);

/* allocate driver private area of tx_info */
tx_info->driver_data[0] = kzalloc(sizeof(*tx_info_priv), GFP_ATOMIC);
ASSERT(tx_info->driver_data[0] != NULL);
tx_info_priv = (struct ath_tx_info_priv *)tx_info->driver_data[0];
/* allocate driver private area of tx_info, XXX: UGLY HACK! */
tx_info->control.vif = kzalloc(sizeof(*tx_info_priv), GFP_ATOMIC);
tx_info_priv = (struct ath_tx_info_priv *)tx_info->control.vif;
ASSERT(tx_info_priv != NULL);

lowest_idx = rate_lowest_index(sband, sta);
tx_info_priv->min_rate = (sband->bitrates[lowest_idx].bitrate * 2) / 10;
/* lowest rate for management and multicast/broadcast frames */
if (!ieee80211_is_data(fc) ||
is_multicast_ether_addr(hdr->addr1) || !sta) {
sel->rate_idx = lowest_idx;
tx_info->control.rates[0].idx = lowest_idx;
return;
}

Expand All @@ -1966,16 +1964,18 @@ static void ath_get_rate(void *priv, struct ieee80211_supported_band *sband,
tx_info_priv->rcs,
&is_probe,
false);
#if 0
if (is_probe)
sel->probe_idx = ath_rc_priv->tx_ratectrl.probe_rate;
#endif

/* Ratecontrol sometimes returns invalid rate index */
if (tx_info_priv->rcs[0].rix != 0xff)
ath_rc_priv->prev_data_rix = tx_info_priv->rcs[0].rix;
else
tx_info_priv->rcs[0].rix = ath_rc_priv->prev_data_rix;

sel->rate_idx = tx_info_priv->rcs[0].rix;
tx_info->control.rates[0].idx = tx_info_priv->rcs[0].rix;

/* Check if aggregation has to be enabled for this tid */

Expand Down
28 changes: 19 additions & 9 deletions drivers/net/wireless/ath9k/xmit.c
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,9 @@ static void fill_min_rates(struct sk_buff *skb, struct ath_tx_control *txctl)

hdr = (struct ieee80211_hdr *)skb->data;
fc = hdr->frame_control;
tx_info_priv = (struct ath_tx_info_priv *)tx_info->driver_data[0];

/* XXX: HACK! */
tx_info_priv = (struct ath_tx_info_priv *)tx_info->control.vif;

if (ieee80211_is_mgmt(fc) || ieee80211_is_ctl(fc)) {
txctl->use_minrate = 1;
Expand Down Expand Up @@ -288,13 +290,16 @@ static int ath_tx_prepare(struct ath_softc *sc,

if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK)
txctl->flags |= ATH9K_TXDESC_NOACK;
if (tx_info->flags & IEEE80211_TX_CTL_USE_RTS_CTS)

if (tx_info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS)
txctl->flags |= ATH9K_TXDESC_RTSENA;

/*
* Setup for rate calculations.
*/
tx_info_priv = (struct ath_tx_info_priv *)tx_info->driver_data[0];

/* XXX: HACK! */
tx_info_priv = (struct ath_tx_info_priv *)tx_info->control.vif;
rcs = tx_info_priv->rcs;

if (ieee80211_is_data(fc) && !txctl->use_minrate) {
Expand Down Expand Up @@ -855,7 +860,9 @@ static int ath_tx_send_normal(struct ath_softc *sc,

skb = (struct sk_buff *)bf->bf_mpdu;
tx_info = IEEE80211_SKB_CB(skb);
tx_info_priv = (struct ath_tx_info_priv *)tx_info->driver_data[0];

/* XXX: HACK! */
tx_info_priv = (struct ath_tx_info_priv *)tx_info->control.vif;
memcpy(bf->bf_rcs, tx_info_priv->rcs, 4 * sizeof(tx_info_priv->rcs[0]));

/* update starting sequence number for subsequent ADDBA request */
Expand Down Expand Up @@ -1249,8 +1256,9 @@ static int ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
}
skb = bf->bf_mpdu;
tx_info = IEEE80211_SKB_CB(skb);
tx_info_priv = (struct ath_tx_info_priv *)
tx_info->driver_data[0];

/* XXX: HACK! */
tx_info_priv = (struct ath_tx_info_priv *) tx_info->control.vif;
if (ds->ds_txstat.ts_status & ATH9K_TXERR_FILT)
tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED;
if ((ds->ds_txstat.ts_status & ATH9K_TXERR_FILT) == 0 &&
Expand Down Expand Up @@ -1431,7 +1439,8 @@ static int ath_tx_send_ampdu(struct ath_softc *sc,

skb = (struct sk_buff *)bf->bf_mpdu;
tx_info = IEEE80211_SKB_CB(skb);
tx_info_priv = (struct ath_tx_info_priv *)tx_info->driver_data[0];
/* XXX: HACK! */
tx_info_priv = (struct ath_tx_info_priv *)tx_info->control.vif;
memcpy(bf->bf_rcs, tx_info_priv->rcs, 4 * sizeof(tx_info_priv->rcs[0]));

/* Add sub-frame to BAW */
Expand Down Expand Up @@ -1466,7 +1475,7 @@ static u32 ath_lookup_rate(struct ath_softc *sc,
skb = (struct sk_buff *)bf->bf_mpdu;
tx_info = IEEE80211_SKB_CB(skb);
tx_info_priv = (struct ath_tx_info_priv *)
tx_info->driver_data[0];
tx_info->control.vif; /* XXX: HACK! */
memcpy(bf->bf_rcs,
tx_info_priv->rcs, 4 * sizeof(tx_info_priv->rcs[0]));

Expand Down Expand Up @@ -1927,7 +1936,8 @@ static int ath_tx_start_dma(struct ath_softc *sc,

bf->bf_flags = txctl->flags;
bf->bf_keytype = txctl->keytype;
tx_info_priv = (struct ath_tx_info_priv *)tx_info->driver_data[0];
/* XXX: HACK! */
tx_info_priv = (struct ath_tx_info_priv *)tx_info->control.vif;
rcs = tx_info_priv->rcs;
bf->bf_rcs[0] = rcs[0];
bf->bf_rcs[1] = rcs[1];
Expand Down
4 changes: 1 addition & 3 deletions drivers/net/wireless/b43/dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -1387,13 +1387,11 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,

info = IEEE80211_SKB_CB(meta->skb);

memset(&info->status, 0, sizeof(info->status));

/*
* Call back to inform the ieee80211 subsystem about
* the status of the transmission.
*/
frame_succeed = b43_fill_txstatus_report(info, status);
frame_succeed = b43_fill_txstatus_report(dev, info, status);
#ifdef CONFIG_B43_DEBUG
if (frame_succeed)
ring->nr_succeed_tx_packets++;
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/wireless/b43/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -4555,7 +4555,7 @@ static int b43_wireless_init(struct ssb_device *dev)
BIT(NL80211_IFTYPE_ADHOC);

hw->queues = b43_modparam_qos ? 4 : 1;
hw->max_altrates = 1;
hw->max_rates = 2;
SET_IEEE80211_DEV(hw, dev->dev);
if (is_valid_ether_addr(sprom->et1mac))
SET_IEEE80211_PERM_ADDR(hw, sprom->et1mac);
Expand Down
3 changes: 1 addition & 2 deletions drivers/net/wireless/b43/pio.c
Original file line number Diff line number Diff line change
Expand Up @@ -587,9 +587,8 @@ void b43_pio_handle_txstatus(struct b43_wldev *dev,
spin_lock(&q->lock); /* IRQs are already disabled. */

info = IEEE80211_SKB_CB(pack->skb);
memset(&info->status, 0, sizeof(info->status));

b43_fill_txstatus_report(info, status);
b43_fill_txstatus_report(dev, info, status);

total_len = pack->skb->len + b43_txhdr_size(dev);
total_len = roundup(total_len, 4);
Expand Down
Loading

0 comments on commit e6a9854

Please sign in to comment.