This feature is mandatory in the 802.11n standard.
Signed-off-by: Christian Lamparter <chunkeey@googlemail.com>
menu "802.11 Firmware Features"
-config CARL9170FW_HANDLE_BACK_REQ
- def_bool y
- prompt "Handle BlockACK Requests in Firmware"
- ---help---
- Enables a firmware mechanism to answer incoming BlockACK requests.
- This feature is necessary to comply with 802.11n. So say Y,
- if you have plans to support this operation mode.
-
-config CARL9170FW_BACK_REQS_NUM
- default 4
- int
- prompt "Number of max. active BlockACK Request"
- depends on CARL9170FW_HANDLE_BACK_REQ
-
config CARL9170FW_CAB_QUEUE
def_bool y
prompt "Support software-based Content after Beacon Queue"
tx_status_tail_idx;
struct carl9170_tx_status tx_status_cache[CARL9170_TX_STATUS_NUM];
-#ifdef CONFIG_CARL9170FW_HANDLE_BACK_REQ
/* BA(R) Request Handler */
struct dma_desc *ba_desc;
struct carl9170_bar_ctx ba_cache[CONFIG_CARL9170FW_BACK_REQS_NUM];
unsigned int ba_desc_available,
ba_tail_idx,
ba_head_idx;
-#endif /* CONFIG_CARL9170FW_HANDLE_BACK_REQ */
} wlan;
struct {
#define CARL9170_INTF_NUM (1)
#endif /* CONFIG_CARL9170FW_VIFS_NUM */
+#define CONFIG_CARL9170FW_BACK_REQS_NUM 4
+
#if ((defined CONFIG_CARL9170FW_DEBUG) || \
(defined CONFIG_CARL9170FW_LOOPBACK))
#define CARL9170FW_UNUSABLE y
BUILD_BUG_ON(!CARL9170_TX_STATUS_NUM);
BUILD_BUG_ON(CARL9170_INTF_NUM < 1);
BUILD_BUG_ON(CARL9170_INTF_NUM >= AR9170_MAX_VIRTUAL_MAC);
-
-#ifdef CONFIG_CARL9170FW_HANDLE_BACK_REQ
- BUILD_BUG_ON(!CONFIG_CARL9170FW_BACK_REQS_NUM);
-#endif /* CONFIG_CARL9170FW_HANDLE_BACK_REQ */
}
#endif /* __CARL9170FW_CONFIG_H */
struct dma_desc *nextAddr; /* Next TD address */
} __packed __aligned(4);
-/* Up, Dn, 5x Tx, retry, Rx, [USB Int], (CAB), (BA) */
-#define AR9170_TERMINATOR_NUMBER_B 9
+/* Up, Dn, 5x Tx, retry, Rx, [USB Int], (CAB), FW */
+#define AR9170_TERMINATOR_NUMBER_B 10
#define AR9170_TERMINATOR_NUMBER_INT 1
#define AR9170_TERMINATOR_NUMBER_CAB 0
#endif /* CONFIG_CARL9170FW_CAB_QUEUE */
-#ifdef CONFIG_CARL9170FW_HANDLE_BACK_REQ
-#define AR9170_TERMINATOR_NUMBER_BA 1
-#else
-#define AR9170_TERMINATOR_NUMBER_BA 0
-#endif /* CONFIG_CARL9170FW_HANDLE_BACK_REQ */
#define AR9170_TERMINATOR_NUMBER (AR9170_TERMINATOR_NUMBER_B + \
AR9170_TERMINATOR_NUMBER_INT + \
- AR9170_TERMINATOR_NUMBER_CAB + \
- AR9170_TERMINATOR_NUMBER_BA)
+ AR9170_TERMINATOR_NUMBER_CAB)
#define AR9170_BLOCK_SIZE (256 + 64)
#define CARL9170_RSP_BUFFER_LEN AR9170_BLOCK_SIZE
struct carl9170_sram_reserved {
-#ifdef CONFIG_CARL9170FW_HANDLE_BACK_REQ
union {
uint32_t buf[CARL9170_BA_BUFFER_LEN / sizeof(uint32_t)];
struct carl9170_tx_ba_superframe ba;
} ba;
-#endif /* CONFIG_CARL9170FW_HANDLE_BACK_REQ */
+
union {
uint32_t buf[CARL9170_MAX_CMD_LEN / sizeof(uint32_t)];
struct carl9170_cmd cmd;
BUILD_BUG_ON(sizeof(mem) > AR9170_SRAM_SIZE);
-#ifdef CONFIG_CARL9170FW_HANDLE_BACK_REQ
BUILD_BUG_ON(offsetof(struct carl9170_sram_reserved, ba.buf) & (BLOCK_ALIGNMENT - 1));
-#endif /* CONFIG_CARL9170FW_HANDLE_BACK_REQ */
BUILD_BUG_ON(offsetof(struct carl9170_sram_reserved, cmd.buf) & (BLOCK_ALIGNMENT - 1));
BUILD_BUG_ON(offsetof(struct carl9170_sram_reserved, rsp.buf) & (BLOCK_ALIGNMENT - 1));
BUILD_BUG_ON(offsetof(struct carl9170_sram_reserved, bcn.buf) & (BLOCK_ALIGNMENT - 1));
fw.wlan.tx_retry.head = fw.wlan.tx_retry.terminator = &dma_mem.terminator[i++];
fw.wlan.rx_queue.head = fw.wlan.rx_queue.terminator = &dma_mem.terminator[i++];
fw.usb.int_desc = &dma_mem.terminator[i++];
+ fw.wlan.ba_desc = &dma_mem.terminator[i++];
#ifdef CONFIG_CARL9170FW_CAB_QUEUE
/* GCC bug ? */
#endif
#endif /* CONFIG_CARL9170FW_CAB_QUEUE */
-#ifdef CONFIG_CARL9170FW_HANDLE_BACK_REQ
- fw.wlan.ba_desc = &dma_mem.terminator[i++];
-#endif /* CONFIG_CARL9170FW_HANDLE_BACK_REQ */
-
BUILD_BUG_ON(AR9170_TERMINATOR_NUMBER != j);
DBG("Blocks:%d [tx:%d, rx:%d] Terminators:%d/%d\n",
/* rsp is now available for use */
fw.usb.int_desc_available = 1;
-#ifdef CONFIG_CARL9170FW_HANDLE_BACK_REQ
fw.wlan.ba_desc->status = AR9170_OWN_BITS_SW;
fw.wlan.ba_desc->ctrl = (AR9170_CTRL_LS_BIT | AR9170_CTRL_FS_BIT);
fw.wlan.ba_desc->dataSize = fw.wlan.ba_desc->totalLen =
memset(DESC_PAYLOAD(fw.wlan.ba_desc), 0, 128);
fw.wlan.ba_desc_available = 1;
-#endif /* CONFIG_CARL9170FW_HANDLE_BACK_REQ */
}
/*
FILL(otus, OTUS,
.feature_set = cpu_to_le32(BIT(CARL9170FW_DUMMY_FEATURE) |
BIT(CARL9170FW_USB_RESP_EP2) |
+ BIT(CARL9170FW_HANDLE_BACK_REQ) |
BIT(CARL9170FW_RX_FILTER) |
#ifdef CONFIG_CARL9170FW_USB_INIT_FIRMWARE
BIT(CARL9170FW_USB_INIT_FIRMWARE) |
#ifdef CONFIG_CARL9170FW_CAB_QUEUE
BIT(CARL9170FW_WLANTX_CAB) |
#endif /* CONFIG_CARL9170FW_CAB_QUEUE */
-#ifdef CONFIG_CARL9170FW_HANDLE_BACK_REQ
- BIT(CARL9170FW_HANDLE_BACK_REQ) |
-#endif /* CONFIG_CARL9170FW_HANDLE_BACK_REQ */
#ifdef CONFIG_CARL9170FW_UNUSABLE
BIT(CARL9170FW_UNUSABLE) |
#endif /* CONFIG_CARL9170FW_UNUSABLE */
unhide_super(desc);
-#ifdef CONFIG_CARL9170FW_HANDLE_BACK_REQ
if (unlikely(super == (void *) &dma_mem.reserved.ba)) {
fw.wlan.ba_desc = desc;
fw.wlan.ba_desc_available = 1;
return true;
}
-#endif /* CONFIG_CARL9170FW_HANDLE_BACK_REQ */
wlan_tx_complete(super, success);
wlan_trigger(BIT(super->s.queue));
}
-#ifdef CONFIG_CARL9170FW_HANDLE_BACK_REQ
static void wlan_send_buffered_ba(void)
{
struct carl9170_tx_ba_superframe *baf = &dma_mem.reserved.ba.ba;
ctx->phy = cpu_to_le32(0x2cc301);
}
}
-#endif /* CONFIG_CARL9170FW_HANDLE_BACK_REQ */
static void wlan_check_rx_overrun(void)
{
} else if (ieee80211_is_ctl(hdr->frame_control)) {
switch (le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_STYPE) {
case IEEE80211_STYPE_BACK_REQ:
-#ifdef CONFIG_CARL9170FW_HANDLE_BACK_REQ
handle_bar(desc, hdr, data_len, mac_err);
-#endif /* CONFIG_CARL9170FW_HANDLE_BACK_REQ */
/* fallthrough */
rx_filter |= CARL9170_RX_FILTER_CTL_BACKR;
break;
wlan_send_buffered_tx_status();
-#ifdef CONFIG_CARL9170FW_HANDLE_BACK_REQ
wlan_send_buffered_ba();
-#endif /* CONFIG_CARL9170FW_HANDLE_BACK_REQ */
}
void handle_wlan(void)