You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
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>
This commit is contained in:
committed by
John W. Linville
parent
cb121bad67
commit
e6a9854b05
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 */
|
||||
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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++;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
/* 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;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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));
|
||||
|
||||
if (status->acked) {
|
||||
info->flags |= IEEE80211_TX_STAT_ACK;
|
||||
} else {
|
||||
if (!(info->flags & IEEE80211_TX_CTL_NO_ACK))
|
||||
info->status.excessive_retries = 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;
|
||||
ieee80211_tx_status_irqsafe(dev->wl->hw, meta->skb);
|
||||
/* skb is freed by ieee80211_tx_status_irqsafe() */
|
||||
meta->skb = NULL;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user