return ret;
}
+static unsigned int wl1271_get_fw_ver_quirks(struct wl1271 *wl)
+{
+ unsigned int quirks = 0;
+ unsigned int *fw_ver = wl->chip.fw_ver;
+
+ /* Only for wl127x */
+ if ((fw_ver[FW_VER_CHIP] == FW_VER_CHIP_WL127X) &&
+ /* Check STA version */
+ (((fw_ver[FW_VER_IF_TYPE] == FW_VER_IF_TYPE_STA) &&
+ (fw_ver[FW_VER_MINOR] < FW_VER_MINOR_1_SPARE_STA_MIN)) ||
+ /* Check AP version */
+ ((fw_ver[FW_VER_IF_TYPE] == FW_VER_IF_TYPE_AP) &&
+ (fw_ver[FW_VER_MINOR] < FW_VER_MINOR_1_SPARE_AP_MIN))))
+ quirks |= WL12XX_QUIRK_USE_2_SPARE_BLOCKS;
+
+ return quirks;
+}
+
int wl1271_plt_start(struct wl1271 *wl)
{
int retries = WL1271_BOOT_RETRIES;
wl->state = WL1271_STATE_PLT;
wl1271_notice("firmware booted in PLT mode (%s)",
wl->chip.fw_ver_str);
+
+ /* Check if any quirks are needed with older fw versions */
+ wl->quirks |= wl1271_get_fw_ver_quirks(wl);
goto out;
irq_disable:
strncpy(wiphy->fw_version, wl->chip.fw_ver_str,
sizeof(wiphy->fw_version));
+ /* Check if any quirks are needed with older fw versions */
+ wl->quirks |= wl1271_get_fw_ver_quirks(wl);
+
/*
* Now we know if 11a is supported (info from the NVS), so disable
* 11a channels if not supported
u32 len;
u32 total_blocks;
int id, ret = -EBUSY;
+ u32 spare_blocks;
+
+ if (unlikely(wl->quirks & WL12XX_QUIRK_USE_2_SPARE_BLOCKS))
+ spare_blocks = 2;
+ else
+ spare_blocks = 1;
if (buf_offset + total_len > WL1271_AGGR_BUFFER_SIZE)
return -EAGAIN;
len = total_len;
total_blocks = (len + TX_HW_BLOCK_SIZE - 1) / TX_HW_BLOCK_SIZE +
- TX_HW_BLOCK_SPARE;
+ spare_blocks;
if (total_blocks <= wl->tx_blocks_available) {
desc = (struct wl1271_tx_hw_descr *)skb_push(
if (wl->chip.id == CHIP_ID_1283_PG20) {
desc->wl128x_mem.total_mem_blocks = total_blocks;
} else {
- desc->wl127x_mem.extra_blocks = TX_HW_BLOCK_SPARE;
+ desc->wl127x_mem.extra_blocks = spare_blocks;
desc->wl127x_mem.total_mem_blocks = total_blocks;
}
#ifndef __TX_H__
#define __TX_H__
-#define TX_HW_BLOCK_SPARE 2
#define TX_HW_BLOCK_SIZE 252
#define TX_HW_MGMT_PKT_LIFETIME_TU 2000
struct wl1271;
-#define WL12XX_NUM_FW_VER 5
+enum {
+ FW_VER_CHIP,
+ FW_VER_IF_TYPE,
+ FW_VER_MAJOR,
+ FW_VER_SUBTYPE,
+ FW_VER_MINOR,
+
+ NUM_FW_VER
+};
+
+#define FW_VER_CHIP_WL127X 6
+#define FW_VER_CHIP_WL128X 7
+
+#define FW_VER_IF_TYPE_STA 1
+#define FW_VER_IF_TYPE_AP 2
+
+#define FW_VER_MINOR_1_SPARE_STA_MIN 58
+#define FW_VER_MINOR_1_SPARE_AP_MIN 47
-/* FIXME: I'm not sure about this structure name */
struct wl1271_chip {
u32 id;
char fw_ver_str[ETHTOOL_BUSINFO_LEN];
- unsigned int fw_ver[WL12XX_NUM_FW_VER];
+ unsigned int fw_ver[NUM_FW_VER];
};
struct wl1271_stats {
/* Each RX/TX transaction requires an end-of-transaction transfer */
#define WL12XX_QUIRK_END_OF_TRANSACTION BIT(0)
+/*
+ * Older firmwares use 2 spare TX blocks
+ * (for STA < 6.1.3.50.58 or for AP < 6.2.0.0.47)
+ */
+#define WL12XX_QUIRK_USE_2_SPARE_BLOCKS BIT(1)
+
#endif