/* update hangcheck */
fw.wlan.last_super_num[qidx] = 0;
+ /*
+ * Note:
+ * There could be a corner case when the TXFAIL is set
+ * even though the frame was properly ACKed by the peer:
+ * a BlockAckReq with the immediate policy will cause
+ * the receiving peer to produce a BlockACK unfortunately
+ * the MAC in this chip seems to be expecting a legacy
+ * ACK and marks the BAR as failed!
+ */
+
if (!!(desc->ctrl & AR9170_CTRL_FAIL)) {
txfail = !!(desc->ctrl & AR9170_CTRL_TXFAIL);
wlan_tx_complete(super, success);
+ if (ieee80211_is_back_req(super->f.data.i3e.frame_control)) {
+ fw.wlan.queued_bar--;
+ }
+
/* recycle freed descriptors */
dma_reclaim(&fw.pta.down_queue, desc);
down_trigger();
{
struct carl9170_tx_superframe *super = DESC_PAYLOAD(desc);
+ if (ieee80211_is_back_req(super->f.data.i3e.frame_control)) {
+ fw.wlan.queued_bar++;
+ }
+
/* initialize rate control struct */
super->s.rix = 0;
super->s.cnt = 1;
baf->s.queue = AR9170_TXQ_VO;
baf->f.hdr.length = sizeof(struct ieee80211_ba) + FCS_LEN;
- /* HW Duration / Backoff */
- baf->f.hdr.mac.backoff = 1;
- baf->f.hdr.mac.hw_duration = 1;
+ baf->f.hdr.mac.no_ack = 1;
- /* take the TX rate from the RX'd BAR */
- baf->f.hdr.phy.set = ctx->phy;
- baf->f.hdr.phy.tx_power = 29; /* 14.5 dBm */
+ baf->f.hdr.phy.modulation = 1; /* OFDM */
+ baf->f.hdr.phy.tx_power = 34; /* 17 dBm */
+ baf->f.hdr.phy.chains = 1;
+ baf->f.hdr.phy.mcs = AR9170_TXRX_PHY_RATE_OFDM_6M;
/* format outgoing BA */
- ba->frame_control = cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_NULLFUNC);
+ ba->frame_control = cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_BACK);
ba->duration = cpu_to_le16(0);
- memcpy(ba->ta, ctx->ta, 6);
- memcpy(ba->ra, ctx->ra, 6);
+
+ /* the BAR contains all necessary MACs. All we need is to swap them */
+ memcpy(ba->ra, ctx->ta, 6);
+ memcpy(ba->ta, ctx->ra, 6);
/*
* Unfortunately, we cannot look into the hardware's scoreboard.
memset(ba->bitmap, 0x0, sizeof(ba->bitmap));
/*
- * NB:
- * not entirely sure if this is 100% correct?!
+ * Both, the original firmare and ath9k set the NO ACK flag in
+ * the BA Ack Policy subfield.
*/
ba->control = ctx->control | cpu_to_le16(1);
ba->start_seq_num = ctx->start_seq_num;
return tmp;
}
-static void handle_bar(struct dma_desc *desc, struct ieee80211_hdr *hdr,
+static void handle_bar(struct dma_desc *desc __unused, struct ieee80211_hdr *hdr,
unsigned int len, unsigned int mac_err)
{
struct ieee80211_bar *bar;
ctx = wlan_get_bar_cache_buffer();
- /* Brilliant! The BAR provides all necessary MACs! */
- memcpy(ctx->ra, bar->ta, 6);
- memcpy(ctx->ta, bar->ra, 6);
-
- /*
- * NB:
- * not entirely sure if this is 100% correct to force the
- * imm ack bit or not...
- */
- ctx->control = bar->control | cpu_to_le16(1);
+ memcpy(ctx->ra, bar->ra, 6);
+ memcpy(ctx->ta, bar->ta, 6);
+ ctx->control = bar->control;
ctx->start_seq_num = bar->start_seq_num;
- ctx->phy = ar9170_rx_to_phy(desc);
- if (unlikely(!ctx->phy)) {
- /* provide a backup, in case ar9170_rx_to_phy fails */
- ctx->phy = cpu_to_le32(0x2cc301);
- }
}
static void wlan_check_rx_overrun(void)
switch (le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_STYPE) {
case IEEE80211_STYPE_BACK_REQ:
handle_bar(desc, hdr, data_len, mac_err);
- /* fallthrough */
rx_filter |= CARL9170_RX_FILTER_CTL_BACKR;
break;
case IEEE80211_STYPE_PSPOLL:
rx_filter |= CARL9170_RX_FILTER_CTL_PSPOLL;
break;
+ case IEEE80211_STYPE_BACK:
+ if (fw.wlan.queued_bar) {
+ /*
+ * Don't filter block acks when the application
+ * has queued BARs. This is because the firmware
+ * can't do the accouting and the application
+ * has to sort out if the BA belongs to any BARs.
+ */
+ break;
+ }
+ /* otherwise fall through */
default:
rx_filter |= CARL9170_RX_FILTER_CTL_OTHER;
break;