mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-23 04:34:11 +08:00
ath9k: get rid of tx_info_priv
This patch removes the need for separately allocated private tx info data in ath9k and brings the driver one small step closer to using the mac80211 rate control API properly. Signed-off-by: Felix Fietkau <nbd@openwrt.org> Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
parent
599bf6a4d6
commit
827e69bf67
@ -81,6 +81,7 @@ struct ath_buf {
|
||||
u16 bf_flags;
|
||||
struct ath_buf_state bf_state;
|
||||
dma_addr_t bf_dmacontext;
|
||||
struct ath_wiphy *aphy;
|
||||
};
|
||||
|
||||
struct ath_atx_tid {
|
||||
|
@ -257,14 +257,17 @@ static const struct file_operations fops_interrupt = {
|
||||
|
||||
void ath_debug_stat_rc(struct ath_softc *sc, struct sk_buff *skb)
|
||||
{
|
||||
struct ath_tx_info_priv *tx_info_priv = NULL;
|
||||
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
|
||||
struct ieee80211_tx_rate *rates = tx_info->status.rates;
|
||||
int final_ts_idx, idx;
|
||||
int final_ts_idx = 0, idx, i;
|
||||
struct ath_rc_stats *stats;
|
||||
|
||||
tx_info_priv = ATH_TX_INFO_PRIV(tx_info);
|
||||
final_ts_idx = tx_info_priv->tx.ts_rateindex;
|
||||
for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
|
||||
if (!rates[i].count)
|
||||
break;
|
||||
|
||||
final_ts_idx = i;
|
||||
}
|
||||
idx = rates[final_ts_idx].idx;
|
||||
stats = &sc->debug.stats.rcstats[idx];
|
||||
stats->success++;
|
||||
|
@ -859,12 +859,12 @@ static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,
|
||||
static bool ath_rc_update_per(struct ath_softc *sc,
|
||||
const struct ath_rate_table *rate_table,
|
||||
struct ath_rate_priv *ath_rc_priv,
|
||||
struct ath_tx_info_priv *tx_info_priv,
|
||||
struct ieee80211_tx_info *tx_info,
|
||||
int tx_rate, int xretries, int retries,
|
||||
u32 now_msec)
|
||||
{
|
||||
bool state_change = false;
|
||||
int count;
|
||||
int count, n_bad_frames;
|
||||
u8 last_per;
|
||||
static u32 nretry_to_per_lookup[10] = {
|
||||
100 * 0 / 1,
|
||||
@ -880,6 +880,7 @@ static bool ath_rc_update_per(struct ath_softc *sc,
|
||||
};
|
||||
|
||||
last_per = ath_rc_priv->per[tx_rate];
|
||||
n_bad_frames = tx_info->status.ampdu_len - tx_info->status.ampdu_ack_len;
|
||||
|
||||
if (xretries) {
|
||||
if (xretries == 1) {
|
||||
@ -907,7 +908,7 @@ static bool ath_rc_update_per(struct ath_softc *sc,
|
||||
if (retries >= count)
|
||||
retries = count - 1;
|
||||
|
||||
if (tx_info_priv->n_bad_frames) {
|
||||
if (n_bad_frames) {
|
||||
/* new_PER = 7/8*old_PER + 1/8*(currentPER)
|
||||
* Assuming that n_frames is not 0. The current PER
|
||||
* from the retries is 100 * retries / (retries+1),
|
||||
@ -920,14 +921,14 @@ static bool ath_rc_update_per(struct ath_softc *sc,
|
||||
* the above PER. The expression below is a
|
||||
* simplified version of the sum of these two terms.
|
||||
*/
|
||||
if (tx_info_priv->n_frames > 0) {
|
||||
int n_frames, n_bad_frames;
|
||||
if (tx_info->status.ampdu_len > 0) {
|
||||
int n_frames, n_bad_tries;
|
||||
u8 cur_per, new_per;
|
||||
|
||||
n_bad_frames = retries * tx_info_priv->n_frames +
|
||||
tx_info_priv->n_bad_frames;
|
||||
n_frames = tx_info_priv->n_frames * (retries + 1);
|
||||
cur_per = (100 * n_bad_frames / n_frames) >> 3;
|
||||
n_bad_tries = retries * tx_info->status.ampdu_len +
|
||||
n_bad_frames;
|
||||
n_frames = tx_info->status.ampdu_len * (retries + 1);
|
||||
cur_per = (100 * n_bad_tries / n_frames) >> 3;
|
||||
new_per = (u8)(last_per - (last_per >> 3) + cur_per);
|
||||
ath_rc_priv->per[tx_rate] = new_per;
|
||||
}
|
||||
@ -943,8 +944,7 @@ static bool ath_rc_update_per(struct ath_softc *sc,
|
||||
* this was a probe. Otherwise, ignore the probe.
|
||||
*/
|
||||
if (ath_rc_priv->probe_rate && ath_rc_priv->probe_rate == tx_rate) {
|
||||
if (retries > 0 || 2 * tx_info_priv->n_bad_frames >
|
||||
tx_info_priv->n_frames) {
|
||||
if (retries > 0 || 2 * n_bad_frames > tx_info->status.ampdu_len) {
|
||||
/*
|
||||
* Since we probed with just a single attempt,
|
||||
* any retries means the probe failed. Also,
|
||||
@ -1003,7 +1003,7 @@ static bool ath_rc_update_per(struct ath_softc *sc,
|
||||
|
||||
static void ath_rc_update_ht(struct ath_softc *sc,
|
||||
struct ath_rate_priv *ath_rc_priv,
|
||||
struct ath_tx_info_priv *tx_info_priv,
|
||||
struct ieee80211_tx_info *tx_info,
|
||||
int tx_rate, int xretries, int retries)
|
||||
{
|
||||
u32 now_msec = jiffies_to_msecs(jiffies);
|
||||
@ -1020,7 +1020,7 @@ static void ath_rc_update_ht(struct ath_softc *sc,
|
||||
|
||||
/* Update PER first */
|
||||
state_change = ath_rc_update_per(sc, rate_table, ath_rc_priv,
|
||||
tx_info_priv, tx_rate, xretries,
|
||||
tx_info, tx_rate, xretries,
|
||||
retries, now_msec);
|
||||
|
||||
/*
|
||||
@ -1098,7 +1098,6 @@ static void ath_rc_tx_status(struct ath_softc *sc,
|
||||
struct ieee80211_tx_info *tx_info,
|
||||
int final_ts_idx, int xretries, int long_retry)
|
||||
{
|
||||
struct ath_tx_info_priv *tx_info_priv = ATH_TX_INFO_PRIV(tx_info);
|
||||
const struct ath_rate_table *rate_table;
|
||||
struct ieee80211_tx_rate *rates = tx_info->status.rates;
|
||||
u8 flags;
|
||||
@ -1124,9 +1123,8 @@ static void ath_rc_tx_status(struct ath_softc *sc,
|
||||
return;
|
||||
|
||||
rix = ath_rc_get_rateindex(rate_table, &rates[i]);
|
||||
ath_rc_update_ht(sc, ath_rc_priv,
|
||||
tx_info_priv, rix,
|
||||
xretries ? 1 : 2,
|
||||
ath_rc_update_ht(sc, ath_rc_priv, tx_info,
|
||||
rix, xretries ? 1 : 2,
|
||||
rates[i].count);
|
||||
}
|
||||
}
|
||||
@ -1149,8 +1147,7 @@ static void ath_rc_tx_status(struct ath_softc *sc,
|
||||
return;
|
||||
|
||||
rix = ath_rc_get_rateindex(rate_table, &rates[i]);
|
||||
ath_rc_update_ht(sc, ath_rc_priv, tx_info_priv, rix,
|
||||
xretries, long_retry);
|
||||
ath_rc_update_ht(sc, ath_rc_priv, tx_info, rix, xretries, long_retry);
|
||||
}
|
||||
|
||||
static const
|
||||
@ -1301,23 +1298,30 @@ static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband,
|
||||
{
|
||||
struct ath_softc *sc = priv;
|
||||
struct ath_rate_priv *ath_rc_priv = priv_sta;
|
||||
struct ath_tx_info_priv *tx_info_priv = NULL;
|
||||
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
|
||||
struct ieee80211_hdr *hdr;
|
||||
int final_ts_idx, tx_status = 0, is_underrun = 0;
|
||||
int final_ts_idx = 0, tx_status = 0, is_underrun = 0;
|
||||
int long_retry = 0;
|
||||
__le16 fc;
|
||||
int i;
|
||||
|
||||
hdr = (struct ieee80211_hdr *)skb->data;
|
||||
fc = hdr->frame_control;
|
||||
tx_info_priv = ATH_TX_INFO_PRIV(tx_info);
|
||||
final_ts_idx = tx_info_priv->tx.ts_rateindex;
|
||||
for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
|
||||
struct ieee80211_tx_rate *rate = &tx_info->status.rates[i];
|
||||
if (!rate->count)
|
||||
break;
|
||||
|
||||
final_ts_idx = i;
|
||||
long_retry = rate->count - 1;
|
||||
}
|
||||
|
||||
if (!priv_sta || !ieee80211_is_data(fc) ||
|
||||
!tx_info_priv->update_rc)
|
||||
goto exit;
|
||||
!(tx_info->pad[0] & ATH_TX_INFO_UPDATE_RC))
|
||||
return;
|
||||
|
||||
if (tx_info_priv->tx.ts_status & ATH9K_TXERR_FILT)
|
||||
goto exit;
|
||||
if (tx_info->flags & IEEE80211_TX_STAT_TX_FILTERED)
|
||||
return;
|
||||
|
||||
/*
|
||||
* If underrun error is seen assume it as an excessive retry only
|
||||
@ -1325,20 +1329,17 @@ static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband,
|
||||
* Adjust the long retry as if the frame was tried hw->max_rate_tries
|
||||
* times. This affects how ratectrl updates PER for the failed rate.
|
||||
*/
|
||||
if (tx_info_priv->tx.ts_flags &
|
||||
(ATH9K_TX_DATA_UNDERRUN | ATH9K_TX_DELIM_UNDERRUN) &&
|
||||
((sc->sc_ah->tx_trig_level) >= ath_rc_priv->tx_triglevel_max)) {
|
||||
if ((tx_info->pad[0] & ATH_TX_INFO_UNDERRUN) &&
|
||||
(sc->sc_ah->tx_trig_level >= ath_rc_priv->tx_triglevel_max)) {
|
||||
tx_status = 1;
|
||||
is_underrun = 1;
|
||||
}
|
||||
|
||||
if ((tx_info_priv->tx.ts_status & ATH9K_TXERR_XRETRY) ||
|
||||
(tx_info_priv->tx.ts_status & ATH9K_TXERR_FIFO))
|
||||
if (tx_info->pad[0] & ATH_TX_INFO_XRETRY)
|
||||
tx_status = 1;
|
||||
|
||||
ath_rc_tx_status(sc, ath_rc_priv, tx_info, final_ts_idx, tx_status,
|
||||
(is_underrun) ? sc->hw->max_rate_tries :
|
||||
tx_info_priv->tx.ts_longretry);
|
||||
(is_underrun) ? sc->hw->max_rate_tries : long_retry);
|
||||
|
||||
/* Check if aggregation has to be enabled for this tid */
|
||||
if (conf_is_ht(&sc->hw->conf) &&
|
||||
@ -1357,8 +1358,6 @@ static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband,
|
||||
}
|
||||
|
||||
ath_debug_stat_rc(sc, skb);
|
||||
exit:
|
||||
kfree(tx_info_priv);
|
||||
}
|
||||
|
||||
static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband,
|
||||
|
@ -167,24 +167,18 @@ struct ath_rate_priv {
|
||||
struct ath_rate_softc *asc;
|
||||
};
|
||||
|
||||
#define ATH_TX_INFO_FRAME_TYPE_INTERNAL (1 << 0)
|
||||
#define ATH_TX_INFO_FRAME_TYPE_PAUSE (1 << 1)
|
||||
#define ATH_TX_INFO_UPDATE_RC (1 << 2)
|
||||
#define ATH_TX_INFO_XRETRY (1 << 3)
|
||||
#define ATH_TX_INFO_UNDERRUN (1 << 4)
|
||||
|
||||
enum ath9k_internal_frame_type {
|
||||
ATH9K_NOT_INTERNAL,
|
||||
ATH9K_INT_PAUSE,
|
||||
ATH9K_INT_UNPAUSE
|
||||
};
|
||||
|
||||
struct ath_tx_info_priv {
|
||||
struct ath_wiphy *aphy;
|
||||
struct ath_tx_status tx;
|
||||
int n_frames;
|
||||
int n_bad_frames;
|
||||
bool update_rc;
|
||||
enum ath9k_internal_frame_type frame_type;
|
||||
};
|
||||
|
||||
#define ATH_TX_INFO_PRIV(tx_info) \
|
||||
((struct ath_tx_info_priv *)((tx_info)->rate_driver_data[0]))
|
||||
|
||||
void ath_rate_attach(struct ath_softc *sc);
|
||||
u8 ath_rate_findrateix(struct ath_softc *sc, u8 dot11_rate);
|
||||
int ath_rate_control_register(void);
|
||||
|
@ -338,13 +338,11 @@ void ath9k_wiphy_chan_work(struct work_struct *work)
|
||||
void ath9k_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
|
||||
{
|
||||
struct ath_wiphy *aphy = hw->priv;
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
|
||||
struct ath_tx_info_priv *tx_info_priv = ATH_TX_INFO_PRIV(tx_info);
|
||||
|
||||
if (tx_info_priv && tx_info_priv->frame_type == ATH9K_INT_PAUSE &&
|
||||
if ((tx_info->pad[0] & ATH_TX_INFO_FRAME_TYPE_PAUSE) &&
|
||||
aphy->state == ATH_WIPHY_PAUSING) {
|
||||
if (!(info->flags & IEEE80211_TX_STAT_ACK)) {
|
||||
if (!(tx_info->flags & IEEE80211_TX_STAT_ACK)) {
|
||||
printk(KERN_DEBUG "ath9k: %s: no ACK for pause "
|
||||
"frame\n", wiphy_name(hw->wiphy));
|
||||
/*
|
||||
@ -363,9 +361,6 @@ void ath9k_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
|
||||
}
|
||||
}
|
||||
|
||||
kfree(tx_info_priv);
|
||||
tx_info->rate_driver_data[0] = NULL;
|
||||
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
|
||||
|
@ -251,6 +251,7 @@ static struct ath_buf* ath_clone_txbuf(struct ath_softc *sc, struct ath_buf *bf)
|
||||
|
||||
ATH_TXBUF_RESET(tbf);
|
||||
|
||||
tbf->aphy = bf->aphy;
|
||||
tbf->bf_mpdu = bf->bf_mpdu;
|
||||
tbf->bf_buf_addr = bf->bf_buf_addr;
|
||||
*(tbf->bf_desc) = *(bf->bf_desc);
|
||||
@ -270,7 +271,6 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
|
||||
struct ieee80211_hw *hw;
|
||||
struct ieee80211_hdr *hdr;
|
||||
struct ieee80211_tx_info *tx_info;
|
||||
struct ath_tx_info_priv *tx_info_priv;
|
||||
struct ath_atx_tid *tid = NULL;
|
||||
struct ath_buf *bf_next, *bf_last = bf->bf_lastbf;
|
||||
struct ath_desc *ds = bf_last->bf_desc;
|
||||
@ -284,8 +284,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
|
||||
hdr = (struct ieee80211_hdr *)skb->data;
|
||||
|
||||
tx_info = IEEE80211_SKB_CB(skb);
|
||||
tx_info_priv = (struct ath_tx_info_priv *) tx_info->rate_driver_data[0];
|
||||
hw = tx_info_priv->aphy->hw;
|
||||
hw = bf->aphy->hw;
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
@ -464,7 +463,6 @@ static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf,
|
||||
struct sk_buff *skb;
|
||||
struct ieee80211_tx_info *tx_info;
|
||||
struct ieee80211_tx_rate *rates;
|
||||
struct ath_tx_info_priv *tx_info_priv;
|
||||
u32 max_4ms_framelen, frmlen;
|
||||
u16 aggr_limit, legacy = 0;
|
||||
int i;
|
||||
@ -472,7 +470,6 @@ static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf,
|
||||
skb = bf->bf_mpdu;
|
||||
tx_info = IEEE80211_SKB_CB(skb);
|
||||
rates = tx_info->control.rates;
|
||||
tx_info_priv = (struct ath_tx_info_priv *)tx_info->rate_driver_data[0];
|
||||
|
||||
/*
|
||||
* Find the lowest frame length among the rate series that will have a
|
||||
@ -1560,21 +1557,26 @@ static int ath_tx_setup_buffer(struct ieee80211_hw *hw, struct ath_buf *bf,
|
||||
struct ath_softc *sc = aphy->sc;
|
||||
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
|
||||
struct ath_tx_info_priv *tx_info_priv;
|
||||
int hdrlen;
|
||||
__le16 fc;
|
||||
|
||||
tx_info_priv = kzalloc(sizeof(*tx_info_priv), GFP_ATOMIC);
|
||||
if (unlikely(!tx_info_priv))
|
||||
return -ENOMEM;
|
||||
tx_info->rate_driver_data[0] = tx_info_priv;
|
||||
tx_info_priv->aphy = aphy;
|
||||
tx_info_priv->frame_type = txctl->frame_type;
|
||||
tx_info->pad[0] = 0;
|
||||
switch (txctl->frame_type) {
|
||||
case ATH9K_NOT_INTERNAL:
|
||||
break;
|
||||
case ATH9K_INT_PAUSE:
|
||||
tx_info->pad[0] |= ATH_TX_INFO_FRAME_TYPE_PAUSE;
|
||||
/* fall through */
|
||||
case ATH9K_INT_UNPAUSE:
|
||||
tx_info->pad[0] |= ATH_TX_INFO_FRAME_TYPE_INTERNAL;
|
||||
break;
|
||||
}
|
||||
hdrlen = ieee80211_get_hdrlen_from_skb(skb);
|
||||
fc = hdr->frame_control;
|
||||
|
||||
ATH_TXBUF_RESET(bf);
|
||||
|
||||
bf->aphy = aphy;
|
||||
bf->bf_frmlen = skb->len + FCS_LEN - (hdrlen & 3);
|
||||
|
||||
if (conf_is_ht(&hw->conf) && !is_pae(skb))
|
||||
@ -1599,8 +1601,6 @@ static int ath_tx_setup_buffer(struct ieee80211_hw *hw, struct ath_buf *bf,
|
||||
skb->len, DMA_TO_DEVICE);
|
||||
if (unlikely(dma_mapping_error(sc->dev, bf->bf_dmacontext))) {
|
||||
bf->bf_mpdu = NULL;
|
||||
kfree(tx_info_priv);
|
||||
tx_info->rate_driver_data[0] = NULL;
|
||||
ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL,
|
||||
"dma_mapping_error() on TX\n");
|
||||
return -ENOMEM;
|
||||
@ -1781,27 +1781,17 @@ exit:
|
||||
/*****************/
|
||||
|
||||
static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
|
||||
int tx_flags)
|
||||
struct ath_wiphy *aphy, int tx_flags)
|
||||
{
|
||||
struct ieee80211_hw *hw = sc->hw;
|
||||
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
|
||||
struct ath_tx_info_priv *tx_info_priv = ATH_TX_INFO_PRIV(tx_info);
|
||||
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
|
||||
int hdrlen, padsize;
|
||||
int frame_type = ATH9K_NOT_INTERNAL;
|
||||
|
||||
ath_print(common, ATH_DBG_XMIT, "TX complete: skb: %p\n", skb);
|
||||
|
||||
if (tx_info_priv) {
|
||||
hw = tx_info_priv->aphy->hw;
|
||||
frame_type = tx_info_priv->frame_type;
|
||||
}
|
||||
|
||||
if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK ||
|
||||
tx_info->flags & IEEE80211_TX_STAT_TX_FILTERED) {
|
||||
kfree(tx_info_priv);
|
||||
tx_info->rate_driver_data[0] = NULL;
|
||||
}
|
||||
if (aphy)
|
||||
hw = aphy->hw;
|
||||
|
||||
if (tx_flags & ATH_TX_BAR)
|
||||
tx_info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK;
|
||||
@ -1833,10 +1823,10 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
|
||||
SC_OP_WAIT_FOR_TX_ACK));
|
||||
}
|
||||
|
||||
if (frame_type == ATH9K_NOT_INTERNAL)
|
||||
ieee80211_tx_status(hw, skb);
|
||||
else
|
||||
if (unlikely(tx_info->pad[0] & ATH_TX_INFO_FRAME_TYPE_INTERNAL))
|
||||
ath9k_tx_status(hw, skb);
|
||||
else
|
||||
ieee80211_tx_status(hw, skb);
|
||||
}
|
||||
|
||||
static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
|
||||
@ -1859,7 +1849,7 @@ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
|
||||
}
|
||||
|
||||
dma_unmap_single(sc->dev, bf->bf_dmacontext, skb->len, DMA_TO_DEVICE);
|
||||
ath_tx_complete(sc, skb, tx_flags);
|
||||
ath_tx_complete(sc, skb, bf->aphy, tx_flags);
|
||||
ath_debug_stat_tx(sc, txq, bf);
|
||||
|
||||
/*
|
||||
@ -1907,8 +1897,7 @@ static void ath_tx_rc_status(struct ath_buf *bf, struct ath_desc *ds,
|
||||
struct sk_buff *skb = bf->bf_mpdu;
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
|
||||
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
|
||||
struct ath_tx_info_priv *tx_info_priv = ATH_TX_INFO_PRIV(tx_info);
|
||||
struct ieee80211_hw *hw = tx_info_priv->aphy->hw;
|
||||
struct ieee80211_hw *hw = bf->aphy->hw;
|
||||
u8 i, tx_rateindex;
|
||||
|
||||
if (txok)
|
||||
@ -1917,17 +1906,22 @@ static void ath_tx_rc_status(struct ath_buf *bf, struct ath_desc *ds,
|
||||
tx_rateindex = ds->ds_txstat.ts_rateindex;
|
||||
WARN_ON(tx_rateindex >= hw->max_rates);
|
||||
|
||||
tx_info_priv->update_rc = update_rc;
|
||||
if (update_rc)
|
||||
tx_info->pad[0] |= ATH_TX_INFO_UPDATE_RC;
|
||||
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 &&
|
||||
(bf->bf_flags & ATH9K_TXDESC_NOACK) == 0 && update_rc) {
|
||||
if (ieee80211_is_data(hdr->frame_control)) {
|
||||
memcpy(&tx_info_priv->tx, &ds->ds_txstat,
|
||||
sizeof(tx_info_priv->tx));
|
||||
tx_info_priv->n_frames = bf->bf_nframes;
|
||||
tx_info_priv->n_bad_frames = nbad;
|
||||
if (ds->ds_txstat.ts_flags &
|
||||
(ATH9K_TX_DATA_UNDERRUN | ATH9K_TX_DELIM_UNDERRUN))
|
||||
tx_info->pad[0] |= ATH_TX_INFO_UNDERRUN;
|
||||
if ((ds->ds_txstat.ts_status & ATH9K_TXERR_XRETRY) ||
|
||||
(ds->ds_txstat.ts_status & ATH9K_TXERR_FIFO))
|
||||
tx_info->pad[0] |= ATH_TX_INFO_XRETRY;
|
||||
tx_info->status.ampdu_len = bf->bf_nframes;
|
||||
tx_info->status.ampdu_ack_len = bf->bf_nframes - nbad;
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user