From 3fcdab7066a31ae90ac2beba7d38e8e606374998 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Mon, 6 Feb 2012 12:47:54 +0200 Subject: [PATCH] wl12xx: Use a dedicated fw for PLT A special PLT firmware is used for calibration. Add multiple fw support by introducing a new fw_type member, representing the currently saved fw (the actual fw state can be determined by wl->state). Signed-off-by: Gery Kahn Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/debugfs.c | 2 +- drivers/net/wireless/wl12xx/main.c | 53 +++++++++++++++++--------- drivers/net/wireless/wl12xx/rx.c | 2 +- drivers/net/wireless/wl12xx/sdio.c | 2 + drivers/net/wireless/wl12xx/spi.c | 2 + drivers/net/wireless/wl12xx/testmode.c | 2 +- drivers/net/wireless/wl12xx/wl12xx.h | 11 +++++- 7 files changed, 52 insertions(+), 22 deletions(-) diff --git a/drivers/net/wireless/wl12xx/debugfs.c b/drivers/net/wireless/wl12xx/debugfs.c index 00dbe1595a7f..e1cf72765965 100644 --- a/drivers/net/wireless/wl12xx/debugfs.c +++ b/drivers/net/wireless/wl12xx/debugfs.c @@ -113,7 +113,7 @@ static void wl1271_debugfs_update_stats(struct wl1271 *wl) if (ret < 0) goto out; - if (wl->state == WL1271_STATE_ON && + if (wl->state == WL1271_STATE_ON && !wl->plt && time_after(jiffies, wl->stats.fw_stats_update + msecs_to_jiffies(WL1271_DEBUGFS_STATS_LIFETIME))) { wl1271_acx_statistics(wl, wl->stats.fw_stats); diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 723df48ed447..c10940703e8c 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -993,16 +993,29 @@ out: return IRQ_HANDLED; } -static int wl1271_fetch_firmware(struct wl1271 *wl) +static int wl12xx_fetch_firmware(struct wl1271 *wl, bool plt) { const struct firmware *fw; const char *fw_name; + enum wl12xx_fw_type fw_type; int ret; - if (wl->chip.id == CHIP_ID_1283_PG20) - fw_name = WL128X_FW_NAME; - else - fw_name = WL127X_FW_NAME; + if (plt) { + fw_type = WL12XX_FW_TYPE_PLT; + if (wl->chip.id == CHIP_ID_1283_PG20) + fw_name = WL128X_PLT_FW_NAME; + else + fw_name = WL127X_PLT_FW_NAME; + } else { + fw_type = WL12XX_FW_TYPE_NORMAL; + if (wl->chip.id == CHIP_ID_1283_PG20) + fw_name = WL128X_FW_NAME; + else + fw_name = WL127X_FW_NAME; + } + + if (wl->fw_type == fw_type) + return 0; wl1271_debug(DEBUG_BOOT, "booting firmware %s", fw_name); @@ -1021,6 +1034,7 @@ static int wl1271_fetch_firmware(struct wl1271 *wl) } vfree(wl->fw); + wl->fw_type = WL12XX_FW_TYPE_NONE; wl->fw_len = fw->size; wl->fw = vmalloc(wl->fw_len); @@ -1032,7 +1046,7 @@ static int wl1271_fetch_firmware(struct wl1271 *wl) memcpy(wl->fw, fw->data, wl->fw_len); ret = 0; - + wl->fw_type = fw_type; out: release_firmware(fw); @@ -1160,7 +1174,7 @@ static void wl1271_recovery_work(struct work_struct *work) mutex_lock(&wl->mutex); - if (wl->state != WL1271_STATE_ON) + if (wl->state != WL1271_STATE_ON || wl->plt) goto out_unlock; /* Avoid a recursive recovery */ @@ -1261,7 +1275,7 @@ out: return ret; } -static int wl1271_chip_wakeup(struct wl1271 *wl) +static int wl12xx_chip_wakeup(struct wl1271 *wl, bool plt) { int ret = 0; @@ -1316,11 +1330,9 @@ static int wl1271_chip_wakeup(struct wl1271 *wl) goto out; } - if (wl->fw == NULL) { - ret = wl1271_fetch_firmware(wl); - if (ret < 0) - goto out; - } + ret = wl12xx_fetch_firmware(wl, plt); + if (ret < 0) + goto out; /* No NVS from netlink, try to get it from the filesystem */ if (wl->nvs == NULL) { @@ -1352,7 +1364,7 @@ int wl1271_plt_start(struct wl1271 *wl) while (retries) { retries--; - ret = wl1271_chip_wakeup(wl); + ret = wl12xx_chip_wakeup(wl, true); if (ret < 0) goto power_off; @@ -1364,7 +1376,8 @@ int wl1271_plt_start(struct wl1271 *wl) if (ret < 0) goto irq_disable; - wl->state = WL1271_STATE_PLT; + wl->plt = true; + wl->state = WL1271_STATE_ON; wl1271_notice("firmware booted in PLT mode (%s)", wl->chip.fw_ver_str); @@ -1413,7 +1426,7 @@ int wl1271_plt_stop(struct wl1271 *wl) */ wl1271_disable_interrupts(wl); mutex_lock(&wl->mutex); - if (wl->state != WL1271_STATE_PLT) { + if (!wl->plt) { mutex_unlock(&wl->mutex); /* @@ -1440,6 +1453,7 @@ int wl1271_plt_stop(struct wl1271 *wl) wl1271_power_off(wl); wl->flags = 0; wl->state = WL1271_STATE_OFF; + wl->plt = false; wl->rx_counter = 0; mutex_unlock(&wl->mutex); @@ -1995,7 +2009,7 @@ static bool wl12xx_init_fw(struct wl1271 *wl) while (retries) { retries--; - ret = wl1271_chip_wakeup(wl); + ret = wl12xx_chip_wakeup(wl, false); if (ret < 0) goto power_off; @@ -2098,6 +2112,7 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, goto out; } + ret = wl12xx_init_vif_data(wl, vif); if (ret < 0) goto out; @@ -5009,7 +5024,7 @@ out: static void wl1271_unregister_hw(struct wl1271 *wl) { - if (wl->state == WL1271_STATE_PLT) + if (wl->plt) wl1271_plt_stop(wl); unregister_netdevice_notifier(&wl1271_dev_notifier); @@ -5186,6 +5201,7 @@ static struct ieee80211_hw *wl1271_alloc_hw(void) spin_lock_init(&wl->wl_lock); wl->state = WL1271_STATE_OFF; + wl->fw_type = WL12XX_FW_TYPE_NONE; mutex_init(&wl->mutex); /* Apply default driver configuration. */ @@ -5253,6 +5269,7 @@ static int wl1271_free_hw(struct wl1271 *wl) vfree(wl->fw); wl->fw = NULL; + wl->fw_type = WL12XX_FW_TYPE_NONE; kfree(wl->nvs); wl->nvs = NULL; diff --git a/drivers/net/wireless/wl12xx/rx.c b/drivers/net/wireless/wl12xx/rx.c index 4fbd2a722ffa..cfa6071704c5 100644 --- a/drivers/net/wireless/wl12xx/rx.c +++ b/drivers/net/wireless/wl12xx/rx.c @@ -113,7 +113,7 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length, * In PLT mode we seem to get frames and mac80211 warns about them, * workaround this by not retrieving them at all. */ - if (unlikely(wl->state == WL1271_STATE_PLT)) + if (unlikely(wl->plt)) return -EINVAL; /* the data read starts with the descriptor */ diff --git a/drivers/net/wireless/wl12xx/sdio.c b/drivers/net/wireless/wl12xx/sdio.c index ce3b9a99463e..1c0264ca021f 100644 --- a/drivers/net/wireless/wl12xx/sdio.c +++ b/drivers/net/wireless/wl12xx/sdio.c @@ -372,3 +372,5 @@ MODULE_AUTHOR("Luciano Coelho "); MODULE_AUTHOR("Juuso Oikarinen "); MODULE_FIRMWARE(WL127X_FW_NAME); MODULE_FIRMWARE(WL128X_FW_NAME); +MODULE_FIRMWARE(WL127X_PLT_FW_NAME); +MODULE_FIRMWARE(WL128X_PLT_FW_NAME); diff --git a/drivers/net/wireless/wl12xx/spi.c b/drivers/net/wireless/wl12xx/spi.c index 92caa7ce6053..5c2d4a0ef000 100644 --- a/drivers/net/wireless/wl12xx/spi.c +++ b/drivers/net/wireless/wl12xx/spi.c @@ -435,4 +435,6 @@ MODULE_AUTHOR("Luciano Coelho "); MODULE_AUTHOR("Juuso Oikarinen "); MODULE_FIRMWARE(WL127X_FW_NAME); MODULE_FIRMWARE(WL128X_FW_NAME); +MODULE_FIRMWARE(WL127X_PLT_FW_NAME); +MODULE_FIRMWARE(WL128X_PLT_FW_NAME); MODULE_ALIAS("spi:wl1271"); diff --git a/drivers/net/wireless/wl12xx/testmode.c b/drivers/net/wireless/wl12xx/testmode.c index b6b433e5562f..1e93bb9c0246 100644 --- a/drivers/net/wireless/wl12xx/testmode.c +++ b/drivers/net/wireless/wl12xx/testmode.c @@ -274,7 +274,7 @@ static int wl12xx_tm_cmd_get_mac(struct wl1271 *wl, struct nlattr *tb[]) mutex_lock(&wl->mutex); - if (wl->state != WL1271_STATE_PLT) { + if (!wl->plt) { ret = -EINVAL; goto out; } diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index 81af416d17da..9b48aa48cdca 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -37,6 +37,8 @@ #define WL127X_FW_NAME "ti-connectivity/wl127x-fw-4-sr.bin" #define WL128X_FW_NAME "ti-connectivity/wl128x-fw-4-sr.bin" +#define WL127X_PLT_FW_NAME "ti-connectivity/wl127x-fw-4-plt.bin" +#define WL128X_PLT_FW_NAME "ti-connectivity/wl128x-fw-4-plt.bin" /* * wl127x and wl128x are using the same NVS file name. However, the @@ -90,7 +92,12 @@ enum wl1271_state { WL1271_STATE_OFF, WL1271_STATE_ON, - WL1271_STATE_PLT, +}; + +enum wl12xx_fw_type { + WL12XX_FW_TYPE_NONE, + WL12XX_FW_TYPE_NORMAL, + WL12XX_FW_TYPE_PLT, }; enum wl1271_partition_type { @@ -294,6 +301,8 @@ struct wl1271 { spinlock_t wl_lock; enum wl1271_state state; + enum wl12xx_fw_type fw_type; + bool plt; struct mutex mutex; unsigned long flags; -- 2.30.2