diff options
author | Johannes Berg | 2008-10-21 12:40:02 +0200 |
---|---|---|
committer | John W. Linville | 2008-10-31 19:00:23 -0400 |
commit | e6a9854b05c1a6af1308fe2b8c68f35abf28a3ee (patch) | |
tree | 241f611f8194586ccabf61bacb060508773b9d05 /drivers/net | |
parent | cb121bad67a32cde37adc2729b7e18aa4fd3063e (diff) |
mac80211/drivers: rewrite the rate control API
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 <nbd@openwrt.org>
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net')
34 files changed, 427 insertions, 277 deletions
diff --git a/drivers/net/wireless/adm8211.c b/drivers/net/wireless/adm8211.c index 9a1e0c514c08..b96ebfe4ef3e 100644 --- a/drivers/net/wireless/adm8211.c +++ b/drivers/net/wireless/adm8211.c @@ -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; @@ -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; @@ -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); diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c index 44401f6f578d..3773d983ea66 100644 --- a/drivers/net/wireless/ath5k/base.c +++ b/drivers/net/wireless/ath5k/base.c @@ -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 */ @@ -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; @@ -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, @@ -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; diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index 32acaf7ff622..a7656a3ea1b0 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c @@ -457,12 +457,13 @@ 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) { @@ -470,17 +471,12 @@ void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, 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) diff --git a/drivers/net/wireless/ath9k/rc.c b/drivers/net/wireless/ath9k/rc.c index 9b2526030965..6afafeddeda2 100644 --- a/drivers/net/wireless/ath9k/rc.c +++ b/drivers/net/wireless/ath9k/rc.c @@ -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, @@ -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; @@ -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; } @@ -1966,8 +1964,10 @@ 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) @@ -1975,7 +1975,7 @@ static void ath_get_rate(void *priv, struct ieee80211_supported_band *sband, 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 */ diff --git a/drivers/net/wireless/ath9k/xmit.c b/drivers/net/wireless/ath9k/xmit.c index ba818cc2fb5c..9fa395418a6c 100644 --- a/drivers/net/wireless/ath9k/xmit.c +++ b/drivers/net/wireless/ath9k/xmit.c @@ -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; @@ -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) { @@ -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 */ @@ -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 && @@ -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 */ @@ -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])); @@ -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]; diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c index 098f886976f6..6d65a02b7052 100644 --- a/drivers/net/wireless/b43/dma.c +++ b/drivers/net/wireless/b43/dma.c @@ -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++; diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 9aeeb6553a91..2a599fb772d9 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -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); diff --git a/drivers/net/wireless/b43/pio.c b/drivers/net/wireless/b43/pio.c index 401591267592..1036bef8c4cc 100644 --- a/drivers/net/wireless/b43/pio.c +++ b/drivers/net/wireless/b43/pio.c @@ -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); diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c index 2fabcf8f0474..adba89b816d4 100644 --- a/drivers/net/wireless/b43/xmit.c +++ b/drivers/net/wireless/b43/xmit.c @@ -185,7 +185,7 @@ int b43_generate_txhdr(struct b43_wldev *dev, u8 *_txhdr, const unsigned char *fragment_data, unsigned int fragment_len, - const struct ieee80211_tx_info *info, + struct ieee80211_tx_info *info, u16 cookie) { struct b43_txhdr *txhdr = (struct b43_txhdr *)_txhdr; @@ -202,6 +202,7 @@ int b43_generate_txhdr(struct b43_wldev *dev, u16 phy_ctl = 0; u8 extra_ft = 0; struct ieee80211_rate *txrate; + struct ieee80211_tx_rate *rates; memset(txhdr, 0, sizeof(*txhdr)); @@ -291,7 +292,7 @@ int b43_generate_txhdr(struct b43_wldev *dev, phy_ctl |= B43_TXH_PHY_ENC_OFDM; else phy_ctl |= B43_TXH_PHY_ENC_CCK; - if (info->flags & IEEE80211_TX_CTL_SHORT_PREAMBLE) + if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) phy_ctl |= B43_TXH_PHY_SHORTPRMBL; switch (b43_ieee80211_antenna_sanitize(dev, info->antenna_sel_tx)) { @@ -314,6 +315,7 @@ int b43_generate_txhdr(struct b43_wldev *dev, B43_WARN_ON(1); } + rates = info->control.rates; /* MAC control */ if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) mac_ctl |= B43_TXH_MAC_ACK; @@ -324,12 +326,22 @@ int b43_generate_txhdr(struct b43_wldev *dev, mac_ctl |= B43_TXH_MAC_STMSDU; if (phy->type == B43_PHYTYPE_A) mac_ctl |= B43_TXH_MAC_5GHZ; - if (info->flags & IEEE80211_TX_CTL_LONG_RETRY_LIMIT) + + /* Overwrite rates[0].count to make the retry calculation + * in the tx status easier. need the actual retry limit to + * detect whether the fallback rate was used. + */ + if ((rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) || + (rates[0].count <= dev->wl->hw->conf.long_frame_max_tx_count)) { + rates[0].count = dev->wl->hw->conf.long_frame_max_tx_count; mac_ctl |= B43_TXH_MAC_LONGFRAME; + } else { + rates[0].count = dev->wl->hw->conf.short_frame_max_tx_count; + } /* Generate the RTS or CTS-to-self frame */ - if ((info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) || - (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT)) { + if ((rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) || + (rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)) { unsigned int len; struct ieee80211_hdr *hdr; int rts_rate, rts_rate_fb; @@ -344,7 +356,7 @@ int b43_generate_txhdr(struct b43_wldev *dev, rts_rate_fb = b43_calc_fallback_rate(rts_rate); rts_rate_fb_ofdm = b43_is_ofdm_rate(rts_rate_fb); - if (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) { + if (rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { struct ieee80211_cts *cts; if (b43_is_old_txhdr_format(dev)) { @@ -687,10 +699,18 @@ void b43_handle_txstatus(struct b43_wldev *dev, /* Fill out the mac80211 TXstatus report based on the b43-specific * txstatus report data. This returns a boolean whether the frame was * successfully transmitted. */ -bool b43_fill_txstatus_report(struct ieee80211_tx_info *report, +bool b43_fill_txstatus_report(struct b43_wldev *dev, + struct ieee80211_tx_info *report, const struct b43_txstatus *status) { bool frame_success = 1; + int retry_limit; + + /* preserve the confiured retry limit before clearing the status + * The xmit function has overwritten the rc's value with the actual + * retry limit done by the hardware */ + retry_limit = report->status.rates[0].count; + ieee80211_tx_info_clear_status(report); if (status->acked) { /* The frame was ACKed. */ @@ -700,14 +720,32 @@ bool b43_fill_txstatus_report(struct ieee80211_tx_info *report, if (!(report->flags & IEEE80211_TX_CTL_NO_ACK)) { /* ...but we expected an ACK. */ frame_success = 0; - report->status.excessive_retries = 1; } } if (status->frame_count == 0) { /* The frame was not transmitted at all. */ - report->status.retry_count = 0; - } else - report->status.retry_count = status->frame_count - 1; + report->status.rates[0].count = 0; + } else if (status->rts_count > dev->wl->hw->conf.short_frame_max_tx_count) { + /* + * If the short retries (RTS, not data frame) have exceeded + * the limit, the hw will not have tried the selected rate, + * but will have used the fallback rate instead. + * Don't let the rate control count attempts for the selected + * rate in this case, otherwise the statistics will be off. + */ + report->status.rates[0].count = 0; + report->status.rates[1].count = status->frame_count; + } else { + if (status->frame_count > retry_limit) { + report->status.rates[0].count = retry_limit; + report->status.rates[1].count = status->frame_count - + retry_limit; + + } else { + report->status.rates[0].count = status->frame_count; + report->status.rates[1].idx = -1; + } + } return frame_success; } diff --git a/drivers/net/wireless/b43/xmit.h b/drivers/net/wireless/b43/xmit.h index 0215faf47541..4fb2a190f7a7 100644 --- a/drivers/net/wireless/b43/xmit.h +++ b/drivers/net/wireless/b43/xmit.h @@ -178,7 +178,7 @@ int b43_generate_txhdr(struct b43_wldev *dev, u8 * txhdr, const unsigned char *fragment_data, unsigned int fragment_len, - const struct ieee80211_tx_info *txctl, u16 cookie); + struct ieee80211_tx_info *txctl, u16 cookie); /* Transmit Status */ struct b43_txstatus { @@ -294,7 +294,8 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr); void b43_handle_txstatus(struct b43_wldev *dev, const struct b43_txstatus *status); -bool b43_fill_txstatus_report(struct ieee80211_tx_info *report, +bool b43_fill_txstatus_report(struct b43_wldev *dev, + struct ieee80211_tx_info *report, const struct b43_txstatus *status); void b43_tx_suspend(struct b43_wldev *dev); diff --git a/drivers/net/wireless/b43legacy/dma.c b/drivers/net/wireless/b43legacy/dma.c index fb6819e40f38..308c2647f002 100644 --- a/drivers/net/wireless/b43legacy/dma.c +++ b/drivers/net/wireless/b43legacy/dma.c @@ -1411,6 +1411,7 @@ void b43legacy_dma_handle_txstatus(struct b43legacy_wldev *dev, struct b43legacy_dmaring *ring; struct b43legacy_dmadesc_generic *desc; struct b43legacy_dmadesc_meta *meta; + int retry_limit; int slot; ring = parse_cookie(dev, status->cookie, &slot); @@ -1437,25 +1438,42 @@ void b43legacy_dma_handle_txstatus(struct b43legacy_wldev *dev, struct ieee80211_tx_info *info; BUG_ON(!meta->skb); info = IEEE80211_SKB_CB(meta->skb); - /* Call back to inform the ieee80211 subsystem about the - * status of the transmission. - * Some fields of txstat are already filled in dma_tx(). - */ - memset(&info->status, 0, sizeof(info->status)); + /* preserve the confiured retry limit before clearing the status + * The xmit function has overwritten the rc's value with the actual + * retry limit done by the hardware */ + retry_limit = info->status.rates[0].count; + ieee80211_tx_info_clear_status(info); - if (status->acked) { + if (status->acked) info->flags |= IEEE80211_TX_STAT_ACK; + + if (status->rts_count > dev->wl->hw->conf.short_frame_max_tx_count) { + /* + * If the short retries (RTS, not data frame) have exceeded + * the limit, the hw will not have tried the selected rate, + * but will have used the fallback rate instead. + * Don't let the rate control count attempts for the selected + * rate in this case, otherwise the statistics will be off. + */ + info->status.rates[0].count = 0; + info->status.rates[1].count = status->frame_count; } else { - if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) - info->status.excessive_retries = 1; + if (status->frame_count > retry_limit) { + info->status.rates[0].count = retry_limit; + info->status.rates[1].count = status->frame_count - + retry_limit; + + } else { + info->status.rates[0].count = status->frame_count; + info->status.rates[1].idx = -1; + } } - if (status->frame_count == 0) { - /* The frame was not transmitted at all. */ - info->status.retry_count = 0; - } else - info->status.retry_count = status->frame_count - - 1; + + /* Call back to inform the ieee80211 subsystem about the + * status of the transmission. + * Some fields of txstat are already filled in dma_tx(). + */ ieee80211_tx_status_irqsafe(dev->wl->hw, meta->skb); /* skb is freed by ieee80211_tx_status_irqsafe() */ meta->skb = NULL; diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index 78e46365f69e..9edbdf9cb50f 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c @@ -3682,7 +3682,7 @@ static int b43legacy_wireless_init(struct ssb_device *dev) BIT(NL80211_IFTYPE_WDS) | BIT(NL80211_IFTYPE_ADHOC); hw->queues = 1; /* FIXME: hardware has more queues */ - 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); diff --git a/drivers/net/wireless/b43legacy/pio.c b/drivers/net/wireless/b43legacy/pio.c index a86c7647fa2d..746d5361bba0 100644 --- a/drivers/net/wireless/b43legacy/pio.c +++ b/drivers/net/wireless/b43legacy/pio.c @@ -491,6 +491,7 @@ void b43legacy_pio_handle_txstatus(struct b43legacy_wldev *dev, struct b43legacy_pioqueue *queue; struct b43legacy_pio_txpacket *packet; struct ieee80211_tx_info *info; + int retry_limit; queue = parse_cookie(dev, status->cookie, &packet); B43legacy_WARN_ON(!queue); @@ -503,11 +504,37 @@ void b43legacy_pio_handle_txstatus(struct b43legacy_wldev *dev, sizeof(struct b43legacy_txhdr_fw3)); info = IEEE80211_SKB_CB(packet->skb); - memset(&info->status, 0, sizeof(info->status)); + + /* preserve the confiured retry limit before clearing the status + * The xmit function has overwritten the rc's value with the actual + * retry limit done by the hardware */ + retry_limit = info->status.rates[0].count; + ieee80211_tx_info_clear_status(info); if (status->acked) info->flags |= IEEE80211_TX_STAT_ACK; - info->status.retry_count = status->frame_count - 1; + + if (status->rts_count > dev->wl->hw->conf.short_frame_max_tx_count) { + /* + * If the short retries (RTS, not data frame) have exceeded + * the limit, the hw will not have tried the selected rate, + * but will have used the fallback rate instead. + * Don't let the rate control count attempts for the selected + * rate in this case, otherwise the statistics will be off. + */ + info->status.rates[0].count = 0; + info->status.rates[1].count = status->frame_count; + } else { + if (status->frame_count > retry_limit) { + info->status.rates[0].count = retry_limit; + info->status.rates[1].count = status->frame_count - + retry_limit; + + } else { + info->status.rates[0].count = status->frame_count; + info->status.rates[1].idx = -1; + } + } ieee80211_tx_status_irqsafe(dev->wl->hw, packet->skb); packet->skb = NULL; diff --git a/drivers/net/wireless/b43legacy/xmit.c b/drivers/net/wireless/b43legacy/xmit.c index 65e833781608..12fca99f7578 100644 --- a/drivers/net/wireless/b43legacy/xmit.c +++ b/drivers/net/wireless/b43legacy/xmit.c @@ -188,7 +188,7 @@ static int generate_txhdr_fw3(struct b43legacy_wldev *dev, struct b43legacy_txhdr_fw3 *txhdr, const unsigned char *fragment_data, unsigned int fragment_len, - const struct ieee80211_tx_info *info, + struct ieee80211_tx_info *info, u16 cookie) { const struct ieee80211_hdr *wlhdr; @@ -201,6 +201,7 @@ static int generate_txhdr_fw3(struct b43legacy_wldev *dev, u32 mac_ctl = 0; u16 phy_ctl = 0; struct ieee80211_rate *tx_rate; + struct ieee80211_tx_rate *rates; wlhdr = (const struct ieee80211_hdr *)fragment_data; @@ -274,7 +275,7 @@ static int generate_txhdr_fw3(struct b43legacy_wldev *dev, /* PHY TX Control word */ if (rate_ofdm) phy_ctl |= B43legacy_TX4_PHY_OFDM; - if (dev->short_preamble) + if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) phy_ctl |= B43legacy_TX4_PHY_SHORTPRMBL; switch (info->antenna_sel_tx) { case 0: @@ -291,6 +292,7 @@ static int generate_txhdr_fw3(struct b43legacy_wldev *dev, } /* MAC control */ + rates = info->control.rates; if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) mac_ctl |= B43legacy_TX4_MAC_ACK; if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) @@ -299,12 +301,22 @@ static int generate_txhdr_fw3(struct b43legacy_wldev *dev, mac_ctl |= B43legacy_TX4_MAC_STMSDU; if (rate_fb_ofdm) mac_ctl |= B43legacy_TX4_MAC_FALLBACKOFDM; - if (info->flags & IEEE80211_TX_CTL_LONG_RETRY_LIMIT) + + /* Overwrite rates[0].count to make the retry calculation + * in the tx status easier. need the actual retry limit to + * detect whether the fallback rate was used. + */ + if ((rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) || + (rates[0].count <= dev->wl->hw->conf.long_frame_max_tx_count)) { + rates[0].count = dev->wl->hw->conf.long_frame_max_tx_count; mac_ctl |= B43legacy_TX4_MAC_LONGFRAME; + } else { + rates[0].count = dev->wl->hw->conf.short_frame_max_tx_count; + } /* Generate the RTS or CTS-to-self frame */ - if ((info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) || - (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT)) { + if ((rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) || + (rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)) { unsigned int len; struct ieee80211_hdr *hdr; int rts_rate; @@ -319,7 +331,7 @@ static int generate_txhdr_fw3(struct b43legacy_wldev *dev, if (rts_rate_fb_ofdm) mac_ctl |= B43legacy_TX4_MAC_CTSFALLBACKOFDM; - if (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) { + if (rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { ieee80211_ctstoself_get(dev->wl->hw, info->control.vif, fragment_data, @@ -362,7 +374,7 @@ int b43legacy_generate_txhdr(struct b43legacy_wldev *dev, u8 *txhdr, const unsigned char *fragment_data, unsigned int fragment_len, - const struct ieee80211_tx_info *info, + struct ieee80211_tx_info *info, u16 cookie) { return generate_txhdr_fw3(dev, (struct b43legacy_txhdr_fw3 *)txhdr, diff --git a/drivers/net/wireless/b43legacy/xmit.h b/drivers/net/wireless/b43legacy/xmit.h index e56777e0feab..62e09d02788f 100644 --- a/drivers/net/wireless/b43legacy/xmit.h +++ b/drivers/net/wireless/b43legacy/xmit.h @@ -80,7 +80,7 @@ int b43legacy_generate_txhdr(struct b43legacy_wldev *dev, u8 *txhdr, const unsigned char *fragment_data, unsigned int fragment_len, - const struct ieee80211_tx_info *info, + struct ieee80211_tx_info *info, u16 cookie); diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c index c25daec4f93d..f440ed0fe543 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c @@ -422,34 +422,6 @@ static void rs_free_sta(void *priv, struct ieee80211_sta *sta, } -/* - * get ieee prev rate from rate scale table. - * for A and B mode we need to overright prev - * value - */ -static int rs_adjust_next_rate(struct iwl3945_priv *priv, int rate) -{ - int next_rate = iwl3945_get_prev_ieee_rate(rate); - - switch (priv->band) { - case IEEE80211_BAND_5GHZ: - if (rate == IWL_RATE_12M_INDEX) - next_rate = IWL_RATE_9M_INDEX; - else if (rate == IWL_RATE_6M_INDEX) - next_rate = IWL_RATE_6M_INDEX; - break; -/* XXX cannot be invoked in current mac80211 so not a regression - case MODE_IEEE80211B: - if (rate == IWL_RATE_11M_INDEX_TABLE) - next_rate = IWL_RATE_5M_INDEX_TABLE; - break; - */ - default: - break; - } - - return next_rate; -} /** * rs_tx_status - Update rate control values based on Tx results * @@ -460,17 +432,21 @@ static void rs_tx_status(void *priv_rate, struct ieee80211_supported_band *sband struct ieee80211_sta *sta, void *priv_sta, struct sk_buff *skb) { - u8 retries, current_count; + u8 retries = 0, current_count; int scale_rate_index, first_index, last_index; unsigned long flags; struct iwl3945_priv *priv = (struct iwl3945_priv *)priv_rate; struct iwl3945_rs_sta *rs_sta = priv_sta; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + int i; IWL_DEBUG_RATE("enter\n"); - retries = info->status.retry_count; - first_index = sband->bitrates[info->tx_rate_idx].hw_value; + for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) + retries += info->status.rates[i].count; + retries--; + + first_index = sband->bitrates[info->status.rates[0].idx].hw_value; if ((first_index < 0) || (first_index >= IWL_RATE_COUNT)) { IWL_DEBUG_RATE("leave: Rate out of bounds: %d\n", first_index); return; @@ -502,7 +478,7 @@ static void rs_tx_status(void *priv_rate, struct ieee80211_supported_band *sband last_index = scale_rate_index; } else { current_count = priv->retry_rate; - last_index = rs_adjust_next_rate(priv, + last_index = iwl3945_rs_next_rate(priv, scale_rate_index); } @@ -518,7 +494,7 @@ static void rs_tx_status(void *priv_rate, struct ieee80211_supported_band *sband if (retries) scale_rate_index = - rs_adjust_next_rate(priv, scale_rate_index); + iwl3945_rs_next_rate(priv, scale_rate_index); } @@ -630,10 +606,11 @@ static u16 iwl3945_get_adjacent_rate(struct iwl3945_rs_sta *rs_sta, * rate table and must reference the driver allocated rate table * */ -static void rs_get_rate(void *priv_r, struct ieee80211_supported_band *sband, - struct ieee80211_sta *sta, void *priv_sta, - struct sk_buff *skb, struct rate_selection *sel) +static void rs_get_rate(void *priv_r, 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; u8 low = IWL_RATE_INVALID; u8 high = IWL_RATE_INVALID; u16 high_low; @@ -649,6 +626,7 @@ static void rs_get_rate(void *priv_r, struct ieee80211_supported_band *sband, struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; u16 fc, rate_mask; struct iwl3945_priv *priv = (struct iwl3945_priv *)priv_r; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); IWL_DEBUG_RATE("enter\n"); @@ -659,7 +637,7 @@ static void rs_get_rate(void *priv_r, struct ieee80211_supported_band *sband, is_multicast_ether_addr(hdr->addr1) || !sta || !priv_sta) { IWL_DEBUG_RATE("leave: No STA priv data to update!\n"); - sel->rate_idx = rate_lowest_index(sband, sta); + info->control.rates[0].idx = rate_lowest_index(sband, sta); return; } @@ -792,9 +770,10 @@ static void rs_get_rate(void *priv_r, struct ieee80211_supported_band *sband, rs_sta->last_txrate_idx = index; if (sband->band == IEEE80211_BAND_5GHZ) - sel->rate_idx = rs_sta->last_txrate_idx - IWL_FIRST_OFDM_RATE; + info->control.rates[0].idx = rs_sta->last_txrate_idx - + IWL_FIRST_OFDM_RATE; else - sel->rate_idx = rs_sta->last_txrate_idx; + info->control.rates[0].idx = rs_sta->last_txrate_idx; IWL_DEBUG_RATE("leave: %d\n", index); } diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 8a00245be51e..7afafb629706 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -261,6 +261,35 @@ static inline const char *iwl3945_get_tx_fail_reason(u32 status) } #endif +/* + * get ieee prev rate from rate scale table. + * for A and B mode we need to overright prev + * value + */ +int iwl3945_rs_next_rate(struct iwl3945_priv *priv, int rate) +{ + int next_rate = iwl3945_get_prev_ieee_rate(rate); + + switch (priv->band) { + case IEEE80211_BAND_5GHZ: + if (rate == IWL_RATE_12M_INDEX) + next_rate = IWL_RATE_9M_INDEX; + else if (rate == IWL_RATE_6M_INDEX) + next_rate = IWL_RATE_6M_INDEX; + break; +/* XXX cannot be invoked in current mac80211 so not a regression + case MODE_IEEE80211B: + if (rate == IWL_RATE_11M_INDEX_TABLE) + next_rate = IWL_RATE_5M_INDEX_TABLE; + break; + */ + default: + break; + } + + return next_rate; +} + /** * iwl3945_tx_queue_reclaim - Reclaim Tx queue entries already Tx'd @@ -308,6 +337,7 @@ static void iwl3945_rx_reply_tx(struct iwl3945_priv *priv, struct iwl3945_tx_resp *tx_resp = (void *)&pkt->u.raw[0]; u32 status = le32_to_cpu(tx_resp->status); int rate_idx; + int fail, i; if ((index >= txq->q.n_bd) || (iwl3945_x2_queue_used(&txq->q, index) == 0)) { IWL_ERROR("Read index for DMA queue txq_id (%d) index %d " @@ -318,9 +348,36 @@ static void iwl3945_rx_reply_tx(struct iwl3945_priv *priv, } info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb[0]); - memset(&info->status, 0, sizeof(info->status)); + ieee80211_tx_info_clear_status(info); + + /* Fill the MRR chain with some info about on-chip retransmissions */ + rate_idx = iwl3945_hwrate_to_plcp_idx(tx_resp->rate); + if (info->band == IEEE80211_BAND_5GHZ) + rate_idx -= IWL_FIRST_OFDM_RATE; + + fail = tx_resp->failure_frame; + for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { + int next = iwl3945_rs_next_rate(priv, rate_idx); + + info->status.rates[i].idx = rate_idx; + + /* + * Put remaining into the last count as best approximation + * of saying exactly what the hardware would have done... + */ + if ((rate_idx == next) || (i == IEEE80211_TX_MAX_RATES - 1)) { + info->status.rates[i].count = fail; + break; + } + + info->status.rates[i].count = priv->retry_rate; + fail -= priv->retry_rate; + rate_idx = next; + if (fail <= 0) + break; + } + info->status.rates[i].count++; /* add final attempt */ - info->status.retry_count = tx_resp->failure_frame; /* tx_status->rts_retry_count = tx_resp->failure_rts; */ info->flags |= ((status & TX_STATUS_MSK) == TX_STATUS_SUCCESS) ? IEEE80211_TX_STAT_ACK : 0; @@ -329,10 +386,6 @@ static void iwl3945_rx_reply_tx(struct iwl3945_priv *priv, txq_id, iwl3945_get_tx_fail_reason(status), status, tx_resp->rate, tx_resp->failure_frame); - rate_idx = iwl3945_hwrate_to_plcp_idx(tx_resp->rate); - if (info->band == IEEE80211_BAND_5GHZ) - rate_idx -= IWL_FIRST_OFDM_RATE; - info->tx_rate_idx = rate_idx; IWL_DEBUG_TX_REPLY("Tx queue reclaim %d\n", index); iwl3945_tx_queue_reclaim(priv, txq_id, index); diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index bdd32475b99c..592c5958723b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -954,6 +954,8 @@ static inline int is_channel_ibss(const struct iwl3945_channel_info *ch) extern const struct iwl3945_channel_info *iwl3945_get_channel_info( const struct iwl3945_priv *priv, enum ieee80211_band band, u16 channel); +extern int iwl3945_rs_next_rate(struct iwl3945_priv *priv, int rate); + /* Requires full declaration of iwl3945_priv before including */ #include "iwl-3945-io.h" diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 9838de5f4369..222c2baa95ca 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -619,10 +619,10 @@ static void iwl4965_gain_computation(struct iwl_priv *priv, static void iwl4965_rts_tx_cmd_flag(struct ieee80211_tx_info *info, __le32 *tx_flags) { - if (info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) { + if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) { *tx_flags |= TX_CMD_FLG_RTS_MSK; *tx_flags &= ~TX_CMD_FLG_CTS_MSK; - } else if (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) { + } else if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { *tx_flags &= ~TX_CMD_FLG_RTS_MSK; *tx_flags |= TX_CMD_FLG_CTS_MSK; } @@ -2070,7 +2070,7 @@ static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv, agg->frame_count, agg->start_idx, idx); info = IEEE80211_SKB_CB(priv->txq[txq_id].txb[idx].skb[0]); - info->status.retry_count = tx_resp->failure_frame; + info->status.rates[0].count = tx_resp->failure_frame + 1; info->flags &= ~IEEE80211_TX_CTL_AMPDU; info->flags |= iwl_is_tx_success(status)? IEEE80211_TX_STAT_ACK : 0; @@ -2227,7 +2227,7 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv, iwl_txq_check_empty(priv, sta_id, tid, txq_id); } } else { - info->status.retry_count = tx_resp->failure_frame; + info->status.rates[0].count = tx_resp->failure_frame + 1; info->flags |= iwl_is_tx_success(status) ? IEEE80211_TX_STAT_ACK : 0; iwl_hwrate_to_tx_control(priv, diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 56a3f0c84a1e..d5282fa65084 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -390,8 +390,8 @@ static void iwl5000_chain_noise_reset(struct iwl_priv *priv) static void iwl5000_rts_tx_cmd_flag(struct ieee80211_tx_info *info, __le32 *tx_flags) { - if ((info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) || - (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT)) + if ((info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) || + (info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)) *tx_flags |= TX_CMD_FLG_RTS_CTS_MSK; else *tx_flags &= ~TX_CMD_FLG_RTS_CTS_MSK; @@ -1154,7 +1154,7 @@ static int iwl5000_tx_status_reply_tx(struct iwl_priv *priv, agg->frame_count, agg->start_idx, idx); info = IEEE80211_SKB_CB(priv->txq[txq_id].txb[idx].skb[0]); - info->status.retry_count = tx_resp->failure_frame; + info->status.rates[0].count = tx_resp->failure_frame + 1; info->flags &= ~IEEE80211_TX_CTL_AMPDU; info->flags |= iwl_is_tx_success(status)? IEEE80211_TX_STAT_ACK : 0; @@ -1307,7 +1307,7 @@ static void iwl5000_rx_reply_tx(struct iwl_priv *priv, iwl_txq_check_empty(priv, sta_id, tid, txq_id); } } else { - info->status.retry_count = tx_resp->failure_frame; + info->status.rates[0].count = tx_resp->failure_frame + 1; info->flags = iwl_is_tx_success(status) ? IEEE80211_TX_STAT_ACK : 0; iwl_hwrate_to_tx_control(priv, diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index e10e0ca09ce9..f685e5d6c281 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -798,7 +798,7 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, !(info->flags & IEEE80211_TX_STAT_AMPDU)) return; - retries = info->status.retry_count; + retries = info->status.rates[0].count - 1; if (retries > 15) retries = 15; @@ -830,20 +830,15 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, if (priv->band == IEEE80211_BAND_5GHZ) rs_index -= IWL_FIRST_OFDM_RATE; - if ((info->tx_rate_idx < 0) || - (tbl_type.is_SGI ^ - !!(info->flags & IEEE80211_TX_CTL_SHORT_GI)) || - (tbl_type.is_fat ^ - !!(info->flags & IEEE80211_TX_CTL_40_MHZ_WIDTH)) || - (tbl_type.is_dup ^ - !!(info->flags & IEEE80211_TX_CTL_DUP_DATA)) || - (tbl_type.ant_type ^ info->antenna_sel_tx) || - (!!(tx_rate & RATE_MCS_HT_MSK) ^ - !!(info->flags & IEEE80211_TX_CTL_OFDM_HT)) || - (!!(tx_rate & RATE_MCS_GF_MSK) ^ - !!(info->flags & IEEE80211_TX_CTL_GREEN_FIELD)) || + if ((info->status.rates[0].idx < 0) || + (tbl_type.is_SGI != !!(info->status.rates[0].flags & IEEE80211_TX_RC_SHORT_GI)) || + (tbl_type.is_fat != !!(info->status.rates[0].flags & IEEE80211_TX_RC_40_MHZ_WIDTH)) || + (tbl_type.is_dup != !!(info->status.rates[0].flags & IEEE80211_TX_RC_DUP_DATA)) || + (tbl_type.ant_type != info->antenna_sel_tx) || + (!!(tx_rate & RATE_MCS_HT_MSK) != !!(info->status.rates[0].flags & IEEE80211_TX_RC_MCS)) || + (!!(tx_rate & RATE_MCS_GF_MSK) != !!(info->status.rates[0].flags & IEEE80211_TX_RC_GREEN_FIELD)) || (hw->wiphy->bands[priv->band]->bitrates[rs_index].bitrate != - hw->wiphy->bands[info->band]->bitrates[info->tx_rate_idx].bitrate)) { + hw->wiphy->bands[info->band]->bitrates[info->status.rates[0].idx].bitrate)) { IWL_DEBUG_RATE("initial rate does not match 0x%x\n", tx_rate); goto out; } @@ -2098,15 +2093,17 @@ static void rs_initialize_lq(struct iwl_priv *priv, return; } -static void rs_get_rate(void *priv_r, struct ieee80211_supported_band *sband, - struct ieee80211_sta *sta, void *priv_sta, - struct sk_buff *skb, struct rate_selection *sel) +static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta, + struct ieee80211_tx_rate_control *txrc) { int i; + struct sk_buff *skb = txrc->skb; + struct ieee80211_supported_band *sband = txrc->sband; struct iwl_priv *priv = (struct iwl_priv *)priv_r; struct ieee80211_conf *conf = &priv->hw->conf; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); __le16 fc; struct iwl_lq_sta *lq_sta; @@ -2117,7 +2114,7 @@ static void rs_get_rate(void *priv_r, struct ieee80211_supported_band *sband, fc = hdr->frame_control; if (!ieee80211_is_data(fc) || is_multicast_ether_addr(hdr->addr1) || !sta || !priv_sta) { - sel->rate_idx = rate_lowest_index(sband, sta); + info->control.rates[0].idx = rate_lowest_index(sband, sta); return; } @@ -2143,13 +2140,13 @@ static void rs_get_rate(void *priv_r, struct ieee80211_supported_band *sband, } if ((i < 0) || (i > IWL_RATE_COUNT)) { - sel->rate_idx = rate_lowest_index(sband, sta); + info->control.rates[0].idx = rate_lowest_index(sband, sta); return; } if (sband->band == IEEE80211_BAND_5GHZ) i -= IWL_FIRST_OFDM_RATE; - sel->rate_idx = i; + info->control.rates[0].idx = i; } static void *rs_alloc_sta(void *priv_rate, struct ieee80211_sta *sta, diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 10f5a0a233fe..2c4162e48140 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -88,26 +88,27 @@ EXPORT_SYMBOL(iwl_rates); * translate ucode response to mac80211 tx status control values */ void iwl_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags, - struct ieee80211_tx_info *control) + struct ieee80211_tx_info *info) { int rate_index; + struct ieee80211_tx_rate *r = &info->control.rates[0]; - control->antenna_sel_tx = + info->antenna_sel_tx = ((rate_n_flags & RATE_MCS_ANT_ABC_MSK) >> RATE_MCS_ANT_POS); if (rate_n_flags & RATE_MCS_HT_MSK) - control->flags |= IEEE80211_TX_CTL_OFDM_HT; + r->flags |= IEEE80211_TX_RC_MCS; if (rate_n_flags & RATE_MCS_GF_MSK) - control->flags |= IEEE80211_TX_CTL_GREEN_FIELD; + r->flags |= IEEE80211_TX_RC_GREEN_FIELD; if (rate_n_flags & RATE_MCS_FAT_MSK) - control->flags |= IEEE80211_TX_CTL_40_MHZ_WIDTH; + r->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH; if (rate_n_flags & RATE_MCS_DUP_MSK) - control->flags |= IEEE80211_TX_CTL_DUP_DATA; + r->flags |= IEEE80211_TX_RC_DUP_DATA; if (rate_n_flags & RATE_MCS_SGI_MSK) - control->flags |= IEEE80211_TX_CTL_SHORT_GI; + r->flags |= IEEE80211_TX_RC_SHORT_GI; rate_index = iwl_hwrate_to_plcp_idx(rate_n_flags); - if (control->band == IEEE80211_BAND_5GHZ) + if (info->band == IEEE80211_BAND_5GHZ) rate_index -= IWL_FIRST_OFDM_RATE; - control->tx_rate_idx = rate_index; + r->idx = rate_index; } EXPORT_SYMBOL(iwl_hwrate_to_tx_control); diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index b1464c71ea0a..2cd33b4e9e13 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -2395,6 +2395,7 @@ static void iwl3945_build_tx_cmd_basic(struct iwl3945_priv *priv, { __le16 fc = hdr->frame_control; __le32 tx_flags = cmd->cmd.tx.tx_flags; + u8 rc_flags = info->control.rates[0].flags; cmd->cmd.tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) { @@ -2421,10 +2422,10 @@ static void iwl3945_build_tx_cmd_basic(struct iwl3945_priv *priv, tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK; } - if (info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) { + if (rc_flags & IEEE80211_TX_RC_USE_RTS_CTS) { tx_flags |= TX_CMD_FLG_RTS_MSK; tx_flags &= ~TX_CMD_FLG_CTS_MSK; - } else if (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) { + } else if (rc_flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { tx_flags &= ~TX_CMD_FLG_RTS_MSK; tx_flags |= TX_CMD_FLG_CTS_MSK; } diff --git a/drivers/net/wireless/libertas_tf/main.c b/drivers/net/wireless/libertas_tf/main.c index 241ddcfa352e..d1fc305de5fe 100644 --- a/drivers/net/wireless/libertas_tf/main.c +++ b/drivers/net/wireless/libertas_tf/main.c @@ -592,14 +592,14 @@ EXPORT_SYMBOL_GPL(lbtf_remove_card); void lbtf_send_tx_feedback(struct lbtf_private *priv, u8 retrycnt, u8 fail) { struct ieee80211_tx_info *info = IEEE80211_SKB_CB(priv->tx_skb); - memset(&info->status, 0, sizeof(info->status)); + + ieee80211_tx_info_clear_status(info); /* * Commented out, otherwise we never go beyond 1Mbit/s using mac80211 * default pid rc algorithm. * * info->status.retry_count = MRVL_DEFAULT_RETRIES - retrycnt; */ - info->status.excessive_retries = fail ? 1 : 0; if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) && !fail) info->flags |= IEEE80211_TX_STAT_ACK; skb_pull(priv->tx_skb, sizeof(struct txpd)); diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index e2aeef8de707..c57652325286 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -209,7 +209,7 @@ static bool mac80211_hwsim_tx_frame(struct ieee80211_hw *hw, /* TODO: set mactime */ rx_status.freq = data->channel->center_freq; rx_status.band = data->channel->band; - rx_status.rate_idx = info->tx_rate_idx; + rx_status.rate_idx = info->control.rates[0].idx; /* TODO: simulate signal strength (and optional packet drop) */ /* Copy skb to all enabled radios that are on the current frequency */ @@ -269,13 +269,9 @@ static int mac80211_hwsim_tx(struct ieee80211_hw *hw, struct sk_buff *skb) if (txi->control.sta) hwsim_check_sta_magic(txi->control.sta); - memset(&txi->status, 0, sizeof(txi->status)); - if (!(txi->flags & IEEE80211_TX_CTL_NO_ACK)) { - if (ack) - txi->flags |= IEEE80211_TX_STAT_ACK; - else - txi->status.excessive_retries = 1; - } + ieee80211_tx_info_clear_status(txi); + if (!(txi->flags & IEEE80211_TX_CTL_NO_ACK) && ack) + txi->flags |= IEEE80211_TX_STAT_ACK; ieee80211_tx_status_irqsafe(hw, skb); return NETDEV_TX_OK; } diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c index 81a9756254fb..65be5eca2340 100644 --- a/drivers/net/wireless/p54/p54common.c +++ b/drivers/net/wireless/p54/p54common.c @@ -548,7 +548,7 @@ static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb) spin_lock_irqsave(&priv->tx_queue.lock, flags); while (entry != (struct sk_buff *)&priv->tx_queue) { struct ieee80211_tx_info *info = IEEE80211_SKB_CB(entry); - range = (void *)info->driver_data; + range = (void *)info->rate_driver_data; if (range->start_addr == addr) { struct p54_control_hdr *entry_hdr; struct p54_tx_control_allocdata *entry_data; @@ -559,7 +559,7 @@ static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb) struct memrecord *mr; ni = IEEE80211_SKB_CB(entry->next); - mr = (struct memrecord *)ni->driver_data; + mr = (struct memrecord *)ni->rate_driver_data; freed = mr->start_addr - last_addr; } else freed = priv->rx_end - last_addr; @@ -568,7 +568,7 @@ static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb) __skb_unlink(entry, &priv->tx_queue); spin_unlock_irqrestore(&priv->tx_queue.lock, flags); - memset(&info->status, 0, sizeof(info->status)); + ieee80211_tx_info_clear_status(info); entry_hdr = (struct p54_control_hdr *) entry->data; entry_data = (struct p54_tx_control_allocdata *) entry_hdr->data; if ((entry_hdr->magic1 & cpu_to_le16(0x4000)) != 0) @@ -578,10 +578,8 @@ static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb) if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) { if (!(payload->status & 0x01)) info->flags |= IEEE80211_TX_STAT_ACK; - else - info->status.excessive_retries = 1; } - info->status.retry_count = payload->retries - 1; + info->status.rates[0].count = payload->retries; info->status.ack_signal = p54_rssi_to_dbm(dev, le16_to_cpu(payload->ack_rssi)); skb_pull(entry, sizeof(*hdr) + pad + sizeof(*entry_data)); @@ -699,7 +697,7 @@ static void p54_assign_address(struct ieee80211_hw *dev, struct sk_buff *skb, while (left--) { u32 hole_size; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(entry); - struct memrecord *range = (void *)info->driver_data; + struct memrecord *range = (void *)info->rate_driver_data; hole_size = range->start_addr - last_addr; if (!target_skb && hole_size >= len) { target_skb = entry->prev; @@ -715,7 +713,7 @@ static void p54_assign_address(struct ieee80211_hw *dev, struct sk_buff *skb, largest_hole = max(largest_hole, priv->rx_end - last_addr - len); if (!skb_queue_empty(&priv->tx_queue)) { struct ieee80211_tx_info *info = IEEE80211_SKB_CB(target_skb); - struct memrecord *range = (void *)info->driver_data; + struct memrecord *range = (void *)info->rate_driver_data; target_addr = range->end_addr; } } else @@ -723,7 +721,7 @@ static void p54_assign_address(struct ieee80211_hw *dev, struct sk_buff *skb, if (skb) { struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct memrecord *range = (void *)info->driver_data; + struct memrecord *range = (void *)info->rate_driver_data; range->start_addr = target_addr; range->end_addr = target_addr + len; __skb_queue_after(&priv->tx_queue, target_skb, skb); @@ -806,6 +804,7 @@ static int p54_tx(struct ieee80211_hw *dev, struct sk_buff *skb) size_t padding, len; u8 rate; u8 cts_rate = 0x20; + u8 rc_flags; current_queue = &priv->tx_stats[skb_get_queue_mapping(skb) + 4]; if (unlikely(current_queue->len > current_queue->limit)) @@ -828,18 +827,19 @@ static int p54_tx(struct ieee80211_hw *dev, struct sk_buff *skb) hdr->magic1 = cpu_to_le16(0x0010); hdr->len = cpu_to_le16(len); hdr->type = (info->flags & IEEE80211_TX_CTL_NO_ACK) ? 0 : cpu_to_le16(1); - hdr->retry1 = hdr->retry2 = info->control.retry_limit; + hdr->retry1 = hdr->retry2 = info->control.rates[0].count; /* TODO: add support for alternate retry TX rates */ rate = ieee80211_get_tx_rate(dev, info)->hw_value; - if (info->flags & IEEE80211_TX_CTL_SHORT_PREAMBLE) { + rc_flags = info->control.rates[0].flags; + if (rc_flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) { rate |= 0x10; cts_rate |= 0x10; } - if (info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) { + if (rc_flags & IEEE80211_TX_RC_USE_RTS_CTS) { rate |= 0x40; cts_rate |= ieee80211_get_rts_cts_rate(dev, info)->hw_value; - } else if (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) { + } else if (rc_flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { rate |= 0x20; cts_rate |= ieee80211_get_rts_cts_rate(dev, info)->hw_value; } diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 697806cf94e2..e1feab8b6b02 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -498,7 +498,9 @@ void rt2x00lib_txdone(struct queue_entry *entry, { struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb); + struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); enum data_queue_qid qid = skb_get_queue_mapping(entry->skb); + u8 rate_idx, rate_flags; /* * Unmap the skb. @@ -528,14 +530,18 @@ void rt2x00lib_txdone(struct queue_entry *entry, rt2x00dev->link.qual.tx_failed += test_bit(TXDONE_FAILURE, &txdesc->flags); + rate_idx = skbdesc->tx_rate_idx; + rate_flags = skbdesc->tx_rate_flags; + /* * Initialize TX status */ memset(&tx_info->status, 0, sizeof(tx_info->status)); tx_info->status.ack_signal = 0; - tx_info->status.excessive_retries = - test_bit(TXDONE_EXCESSIVE_RETRY, &txdesc->flags); - tx_info->status.retry_count = txdesc->retry; + tx_info->status.rates[0].idx = rate_idx; + tx_info->status.rates[0].flags = rate_flags; + tx_info->status.rates[0].count = txdesc->retry + 1; + tx_info->status.rates[1].idx = -1; /* terminate */ if (!(tx_info->flags & IEEE80211_TX_CTL_NO_ACK)) { if (test_bit(TXDONE_SUCCESS, &txdesc->flags)) @@ -544,7 +550,7 @@ void rt2x00lib_txdone(struct queue_entry *entry, rt2x00dev->low_level_stats.dot11ACKFailureCount++; } - if (tx_info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) { + if (rate_flags & IEEE80211_TX_RC_USE_RTS_CTS) { if (test_bit(TXDONE_SUCCESS, &txdesc->flags)) rt2x00dev->low_level_stats.dot11RTSSuccessCount++; else if (test_bit(TXDONE_FAILURE, &txdesc->flags)) diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index 931183369f07..b32d59eafaa3 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -39,7 +39,7 @@ static int rt2x00mac_tx_rts_cts(struct rt2x00_dev *rt2x00dev, unsigned int data_length; int retval = 0; - if (tx_info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) + if (tx_info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) data_length = sizeof(struct ieee80211_cts); else data_length = sizeof(struct ieee80211_rts); @@ -64,11 +64,11 @@ static int rt2x00mac_tx_rts_cts(struct rt2x00_dev *rt2x00dev, */ memcpy(skb->cb, frag_skb->cb, sizeof(skb->cb)); rts_info = IEEE80211_SKB_CB(skb); - rts_info->flags &= ~IEEE80211_TX_CTL_USE_RTS_CTS; - rts_info->flags &= ~IEEE80211_TX_CTL_USE_CTS_PROTECT; + rts_info->control.rates[0].flags &= ~IEEE80211_TX_RC_USE_RTS_CTS; + rts_info->control.rates[0].flags &= ~IEEE80211_TX_RC_USE_CTS_PROTECT; rts_info->flags &= ~IEEE80211_TX_CTL_REQ_TX_STATUS; - if (tx_info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) + if (tx_info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) rts_info->flags |= IEEE80211_TX_CTL_NO_ACK; else rts_info->flags &= ~IEEE80211_TX_CTL_NO_ACK; @@ -84,7 +84,7 @@ static int rt2x00mac_tx_rts_cts(struct rt2x00_dev *rt2x00dev, data_length += rt2x00crypto_tx_overhead(tx_info); #endif /* CONFIG_RT2X00_LIB_CRYPTO */ - if (tx_info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) + if (tx_info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) ieee80211_ctstoself_get(rt2x00dev->hw, tx_info->control.vif, frag_skb->data, data_length, tx_info, (struct ieee80211_cts *)(skb->data)); @@ -146,8 +146,8 @@ int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) * inside the hardware. */ frame_control = le16_to_cpu(ieee80211hdr->frame_control); - if ((tx_info->flags & (IEEE80211_TX_CTL_USE_RTS_CTS | - IEEE80211_TX_CTL_USE_CTS_PROTECT)) && + if ((tx_info->control.rates[0].flags & (IEEE80211_TX_RC_USE_RTS_CTS | + IEEE80211_TX_RC_USE_CTS_PROTECT)) && !rt2x00dev->ops->hw->set_rts_threshold) { if (rt2x00queue_available(queue) <= 1) goto exit_fail; diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index 451d410ecdae..070786ebd076 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -230,8 +230,15 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry, /* * Determine retry information. */ - txdesc->retry_limit = tx_info->control.retry_limit; - if (tx_info->flags & IEEE80211_TX_CTL_LONG_RETRY_LIMIT) + txdesc->retry_limit = tx_info->control.rates[0].count - 1; + /* + * XXX: If at this point we knew whether the HW is going to use + * the RETRY_MODE bit or the retry_limit (currently all + * use the RETRY_MODE bit) we could do something like b43 + * does, set the RETRY_MODE bit when the RC algorithm is + * requesting more than the long retry limit. + */ + if (tx_info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) __set_bit(ENTRY_TXD_RETRY_MODE, &txdesc->flags); /* @@ -371,10 +378,12 @@ static void rt2x00queue_write_tx_descriptor(struct queue_entry *entry, int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb) { + struct ieee80211_tx_info *tx_info; struct queue_entry *entry = rt2x00queue_get_entry(queue, Q_INDEX); struct txentry_desc txdesc; struct skb_frame_desc *skbdesc; unsigned int iv_len = 0; + u8 rate_idx, rate_flags; if (unlikely(rt2x00queue_full(queue))) return -EINVAL; @@ -399,13 +408,18 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb) iv_len = IEEE80211_SKB_CB(skb)->control.hw_key->iv_len; /* - * All information is retreived from the skb->cb array, + * All information is retrieved from the skb->cb array, * now we should claim ownership of the driver part of that - * array. + * array, preserving the bitrate index and flags. */ + tx_info = IEEE80211_SKB_CB(skb); + rate_idx = tx_info->control.rates[0].idx; + rate_flags = tx_info->control.rates[0].flags; skbdesc = get_skb_frame_desc(entry->skb); memset(skbdesc, 0, sizeof(*skbdesc)); skbdesc->entry = entry; + skbdesc->tx_rate_idx = rate_idx; + skbdesc->tx_rate_flags = rate_flags; /* * When hardware encryption is supported, and this frame diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h index 9dbf04f0f04c..4d3c7246f9ae 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.h +++ b/drivers/net/wireless/rt2x00/rt2x00queue.h @@ -104,6 +104,8 @@ enum skb_frame_desc_flags { * * @flags: Frame flags, see &enum skb_frame_desc_flags. * @desc_len: Length of the frame descriptor. + * @tx_rate_idx: the index of the TX rate, used for TX status reporting + * @tx_rate_flags: the TX rate flags, used for TX status reporting * @desc: Pointer to descriptor part of the frame. * Note that this pointer could point to something outside * of the scope of the skb->data pointer. @@ -113,9 +115,12 @@ enum skb_frame_desc_flags { * @entry: The entry to which this sk buffer belongs. */ struct skb_frame_desc { - unsigned int flags; + u8 flags; + + u8 desc_len; + u8 tx_rate_idx; + u8 tx_rate_flags; - unsigned int desc_len; void *desc; __le32 iv; diff --git a/drivers/net/wireless/rtl8180_dev.c b/drivers/net/wireless/rtl8180_dev.c index e8d22393797f..6c226c024dd9 100644 --- a/drivers/net/wireless/rtl8180_dev.c +++ b/drivers/net/wireless/rtl8180_dev.c @@ -182,15 +182,13 @@ static void rtl8180_handle_tx(struct ieee80211_hw *dev, unsigned int prio) skb->len, PCI_DMA_TODEVICE); info = IEEE80211_SKB_CB(skb); - memset(&info->status, 0, sizeof(info->status)); + ieee80211_tx_info_clear_status(info); - if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) { - if (flags & RTL818X_TX_DESC_FLAG_TX_OK) - info->flags |= IEEE80211_TX_STAT_ACK; - else - info->status.excessive_retries = 1; - } - info->status.retry_count = flags & 0xFF; + if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) && + (flags & RTL818X_TX_DESC_FLAG_TX_OK)) + info->flags |= IEEE80211_TX_STAT_ACK; + + info->status.rates[0].count = (flags & 0xFF) + 1; ieee80211_tx_status_irqsafe(dev, skb); if (ring->entries - skb_queue_len(&ring->queue) == 2) @@ -243,6 +241,7 @@ static int rtl8180_tx(struct ieee80211_hw *dev, struct sk_buff *skb) unsigned int idx, prio; dma_addr_t mapping; u32 tx_flags; + u8 rc_flags; u16 plcp_len = 0; __le16 rts_duration = 0; @@ -261,15 +260,16 @@ static int rtl8180_tx(struct ieee80211_hw *dev, struct sk_buff *skb) tx_flags |= RTL818X_TX_DESC_FLAG_DMA | RTL818X_TX_DESC_FLAG_NO_ENC; - if (info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) { + rc_flags = info->control.rates[0].flags; + if (rc_flags & IEEE80211_TX_RC_USE_RTS_CTS) { tx_flags |= RTL818X_TX_DESC_FLAG_RTS; tx_flags |= ieee80211_get_rts_cts_rate(dev, info)->hw_value << 19; - } else if (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) { + } else if (rc_flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { tx_flags |= RTL818X_TX_DESC_FLAG_CTS; tx_flags |= ieee80211_get_rts_cts_rate(dev, info)->hw_value << 19; } - if (info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) + if (rc_flags & IEEE80211_TX_RC_USE_RTS_CTS) rts_duration = ieee80211_rts_duration(dev, priv->vif, skb->len, info); @@ -292,9 +292,9 @@ static int rtl8180_tx(struct ieee80211_hw *dev, struct sk_buff *skb) entry->plcp_len = cpu_to_le16(plcp_len); entry->tx_buf = cpu_to_le32(mapping); entry->frame_len = cpu_to_le32(skb->len); - entry->flags2 = info->control.retries[0].rate_idx >= 0 ? + entry->flags2 = info->control.rates[1].idx >= 0 ? ieee80211_get_alt_retry_rate(dev, info, 0)->bitrate << 4 : 0; - entry->retry_limit = info->control.retry_limit; + entry->retry_limit = info->control.rates[0].count; entry->flags = cpu_to_le32(tx_flags); __skb_queue_tail(&ring->queue, skb); if (ring->entries - skb_queue_len(&ring->queue) < 2) @@ -855,7 +855,7 @@ static int __devinit rtl8180_probe(struct pci_dev *pdev, priv = dev->priv; priv->pdev = pdev; - dev->max_altrates = 1; + dev->max_rates = 2; SET_IEEE80211_DEV(dev, &pdev->dev); pci_set_drvdata(pdev, dev); diff --git a/drivers/net/wireless/rtl8187_dev.c b/drivers/net/wireless/rtl8187_dev.c index cd839bcb6d78..6260ed8ce12b 100644 --- a/drivers/net/wireless/rtl8187_dev.c +++ b/drivers/net/wireless/rtl8187_dev.c @@ -160,13 +160,13 @@ static void rtl8187_tx_cb(struct urb *urb) { struct sk_buff *skb = (struct sk_buff *)urb->context; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct ieee80211_hw *hw = info->driver_data[0]; + struct ieee80211_hw *hw = info->rate_driver_data[0]; struct rtl8187_priv *priv = hw->priv; - usb_free_urb(info->driver_data[1]); + usb_free_urb(info->rate_driver_data[1]); skb_pull(skb, priv->is_rtl8187b ? sizeof(struct rtl8187b_tx_hdr) : sizeof(struct rtl8187_tx_hdr)); - memset(&info->status, 0, sizeof(info->status)); + ieee80211_tx_info_clear_status(info); info->flags |= IEEE80211_TX_STAT_ACK; ieee80211_tx_status_irqsafe(hw, skb); } @@ -194,12 +194,12 @@ static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb) flags |= ieee80211_get_tx_rate(dev, info)->hw_value << 24; if (ieee80211_has_morefrags(((struct ieee80211_hdr *)skb->data)->frame_control)) flags |= RTL818X_TX_DESC_FLAG_MOREFRAG; - if (info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) { + if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) { flags |= RTL818X_TX_DESC_FLAG_RTS; flags |= ieee80211_get_rts_cts_rate(dev, info)->hw_value << 19; rts_dur = ieee80211_rts_duration(dev, priv->vif, skb->len, info); - } else if (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) { + } else if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { flags |= RTL818X_TX_DESC_FLAG_CTS; flags |= ieee80211_get_rts_cts_rate(dev, info)->hw_value << 19; } @@ -210,7 +210,7 @@ static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb) hdr->flags = cpu_to_le32(flags); hdr->len = 0; hdr->rts_duration = rts_dur; - hdr->retry = cpu_to_le32(info->control.retry_limit << 8); + hdr->retry = cpu_to_le32((info->control.rates[0].count - 1) << 8); buf = hdr; ep = 2; @@ -228,7 +228,7 @@ static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb) memset(hdr, 0, sizeof(*hdr)); hdr->flags = cpu_to_le32(flags); hdr->rts_duration = rts_dur; - hdr->retry = cpu_to_le32(info->control.retry_limit << 8); + hdr->retry = cpu_to_le32((info->control.rates[0].count - 1) << 8); hdr->tx_duration = ieee80211_generic_frame_duration(dev, priv->vif, skb->len, txrate); @@ -240,8 +240,8 @@ static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb) ep = epmap[skb_get_queue_mapping(skb)]; } - info->driver_data[0] = dev; - info->driver_data[1] = urb; + info->rate_driver_data[0] = dev; + info->rate_driver_data[1] = urb; usb_fill_bulk_urb(urb, priv->udev, usb_sndbulkpipe(priv->udev, ep), buf, skb->len, rtl8187_tx_cb, skb); diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c index 6c3e21887fc8..2f0802b29c4b 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.c +++ b/drivers/net/wireless/zd1211rw/zd_mac.c @@ -296,15 +296,14 @@ static void zd_op_stop(struct ieee80211_hw *hw) * If no status information has been requested, the skb is freed. */ static void tx_status(struct ieee80211_hw *hw, struct sk_buff *skb, - u32 flags, int ackssi, bool success) + int ackssi, bool success) { struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - memset(&info->status, 0, sizeof(info->status)); + ieee80211_tx_info_clear_status(info); - if (!success) - info->status.excessive_retries = 1; - info->flags |= flags; + if (success) + info->flags |= IEEE80211_TX_STAT_ACK; info->status.ack_signal = ackssi; ieee80211_tx_status_irqsafe(hw, skb); } @@ -326,7 +325,7 @@ void zd_mac_tx_failed(struct ieee80211_hw *hw) if (skb == NULL) return; - tx_status(hw, skb, 0, 0, 0); + tx_status(hw, skb, 0, 0); } /** @@ -342,12 +341,12 @@ void zd_mac_tx_failed(struct ieee80211_hw *hw) void zd_mac_tx_to_dev(struct sk_buff *skb, int error) { struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct ieee80211_hw *hw = info->driver_data[0]; + struct ieee80211_hw *hw = info->rate_driver_data[0]; skb_pull(skb, sizeof(struct zd_ctrlset)); if (unlikely(error || (info->flags & IEEE80211_TX_CTL_NO_ACK))) { - tx_status(hw, skb, 0, 0, !error); + tx_status(hw, skb, 0, !error); } else { struct sk_buff_head *q = &zd_hw_mac(hw)->ack_wait_queue; @@ -406,7 +405,8 @@ static int zd_calc_tx_length_us(u8 *service, u8 zd_rate, u16 tx_length) } static void cs_set_control(struct zd_mac *mac, struct zd_ctrlset *cs, - struct ieee80211_hdr *header, u32 flags) + struct ieee80211_hdr *header, + struct ieee80211_tx_info *info) { /* * CONTROL TODO: @@ -417,7 +417,7 @@ static void cs_set_control(struct zd_mac *mac, struct zd_ctrlset *cs, cs->control = 0; /* First fragment */ - if (flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) + if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) cs->control |= ZD_CS_NEED_RANDOM_BACKOFF; /* Multicast */ @@ -428,10 +428,10 @@ static void cs_set_control(struct zd_mac *mac, struct zd_ctrlset *cs, if (ieee80211_is_pspoll(header->frame_control)) cs->control |= ZD_CS_PS_POLL_FRAME; - if (flags & IEEE80211_TX_CTL_USE_RTS_CTS) + if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) cs->control |= ZD_CS_RTS; - if (flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) + if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) cs->control |= ZD_CS_SELF_CTS; /* FIXME: Management frame? */ @@ -517,12 +517,12 @@ static int fill_ctrlset(struct zd_mac *mac, txrate = ieee80211_get_tx_rate(mac->hw, info); cs->modulation = txrate->hw_value; - if (info->flags & IEEE80211_TX_CTL_SHORT_PREAMBLE) + if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) cs->modulation = txrate->hw_value_short; cs->tx_length = cpu_to_le16(frag_len); - cs_set_control(mac, cs, hdr, info->flags); + cs_set_control(mac, cs, hdr, info); packet_length = frag_len + sizeof(struct zd_ctrlset) + 10; ZD_ASSERT(packet_length <= 0xffff); @@ -577,7 +577,7 @@ static int zd_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) if (r) return r; - info->driver_data[0] = hw; + info->rate_driver_data[0] = hw; r = zd_usb_tx(&mac->chip.usb, skb); if (r) @@ -618,7 +618,7 @@ static int filter_ack(struct ieee80211_hw *hw, struct ieee80211_hdr *rx_hdr, if (likely(!compare_ether_addr(tx_hdr->addr2, rx_hdr->addr1))) { __skb_unlink(skb, q); - tx_status(hw, skb, IEEE80211_TX_STAT_ACK, stats->signal, 1); + tx_status(hw, skb, stats->signal, 1); goto out; } } diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c index a60ae86bd5c9..d7a2f52e40cf 100644 --- a/drivers/net/wireless/zd1211rw/zd_usb.c +++ b/drivers/net/wireless/zd1211rw/zd_usb.c @@ -907,7 +907,7 @@ free_urb: * it might be freed by zd_mac_tx_to_dev or mac80211) */ info = IEEE80211_SKB_CB(skb); - usb = &zd_hw_mac(info->driver_data[0])->chip.usb; + usb = &zd_hw_mac(info->rate_driver_data[0])->chip.usb; zd_mac_tx_to_dev(skb, urb->status); free_tx_urb(usb, urb); tx_dec_submitted_urbs(usb); |