wlcore: Fix config firmware loading issues
authorTony Lindgren <tony@atomide.com>
Sat, 17 Sep 2016 16:06:32 +0000 (09:06 -0700)
committerKalle Valo <kvalo@codeaurora.org>
Mon, 26 Sep 2016 15:13:45 +0000 (18:13 +0300)
Booting multiple wl12xx and wl18xx devices using the same rootfs is
a pain. You currently have to symlink the right nvs file depending
on the wl12xx type.

For example, with wl1271-nvs.bin being a symlink to wl127x-nvs.bin
by default and trying to bring up a wl128x based device:

wlcore: ERROR nvs size is not as expected: 1113 != 912
wlcore: ERROR NVS file is needed during boot
wlcore: ERROR NVS file is needed during boot
wlcore: ERROR firmware boot failed despite 3 retries

Note that wl18xx uses a separate config firmware wl18xx-conf.bin
that can be generated with tools using the following two git repos:

git.ti.com/wilink8-wlan/18xx-ti-utils
git.ti.com/wilink8-wlan/wl18xx_fw

So let's not configure the nvs file for wl18xx as it's not needed
AFAIK. If it turns out that we also need the nvs file for wl18xx,
we can just add it to the config firmware data for wl18xx.

Let's fix the issue by using the chip specific config firmware
data, and make sure we produce understandable warnings if something
is missing.

Signed-off-by: Tony Lindgren <tony@atomide.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
drivers/net/wireless/ti/wlcore/boot.c
drivers/net/wireless/ti/wlcore/main.c
drivers/net/wireless/ti/wlcore/wlcore_i.h

index f75d3044411719ea10c63200534e25220aeeb311..f00509ea8aca1010dafd2e1e3c4165341dd91200 100644 (file)
@@ -282,6 +282,9 @@ EXPORT_SYMBOL_GPL(wlcore_boot_upload_firmware);
 
 int wlcore_boot_upload_nvs(struct wl1271 *wl)
 {
+       struct platform_device *pdev = wl->pdev;
+       struct wlcore_platdev_data *pdev_data = dev_get_platdata(&pdev->dev);
+       const char *nvs_name = "unknown";
        size_t nvs_len, burst_len;
        int i;
        u32 dest_addr, val;
@@ -293,6 +296,9 @@ int wlcore_boot_upload_nvs(struct wl1271 *wl)
                return -ENODEV;
        }
 
+       if (pdev_data && pdev_data->family)
+               nvs_name = pdev_data->family->nvs_name;
+
        if (wl->quirks & WLCORE_QUIRK_LEGACY_NVS) {
                struct wl1271_nvs_file *nvs =
                        (struct wl1271_nvs_file *)wl->nvs;
@@ -310,8 +316,9 @@ int wlcore_boot_upload_nvs(struct wl1271 *wl)
                if (wl->nvs_len != sizeof(struct wl1271_nvs_file) &&
                    (wl->nvs_len != WL1271_INI_LEGACY_NVS_FILE_SIZE ||
                     wl->enable_11a)) {
-                       wl1271_error("nvs size is not as expected: %zu != %zu",
-                               wl->nvs_len, sizeof(struct wl1271_nvs_file));
+                       wl1271_error("%s size is not as expected: %zu != %zu",
+                                    nvs_name, wl->nvs_len,
+                                    sizeof(struct wl1271_nvs_file));
                        kfree(wl->nvs);
                        wl->nvs = NULL;
                        wl->nvs_len = 0;
@@ -328,8 +335,8 @@ int wlcore_boot_upload_nvs(struct wl1271 *wl)
                        if (nvs->general_params.dual_mode_select)
                                wl->enable_11a = true;
                } else {
-                       wl1271_error("nvs size is not as expected: %zu != %zu",
-                                    wl->nvs_len,
+                       wl1271_error("%s size is not as expected: %zu != %zu",
+                                    nvs_name, wl->nvs_len,
                                     sizeof(struct wl128x_nvs_file));
                        kfree(wl->nvs);
                        wl->nvs = NULL;
index ef6c15b952cc8bcc91760b5011b8e41aafe6e94c..471521a0db7b6634e0f2c36ef8a168116c336f4f 100644 (file)
@@ -6413,9 +6413,12 @@ static void wlcore_nvs_cb(const struct firmware *fw, void *context)
                        goto out;
                }
                wl->nvs_len = fw->size;
-       } else {
+       } else if (pdev_data->family->nvs_name) {
                wl1271_debug(DEBUG_BOOT, "Could not get nvs file %s",
-                            WL12XX_NVS_NAME);
+                            pdev_data->family->nvs_name);
+               wl->nvs = NULL;
+               wl->nvs_len = 0;
+       } else {
                wl->nvs = NULL;
                wl->nvs_len = 0;
        }
@@ -6510,21 +6513,29 @@ out:
 
 int wlcore_probe(struct wl1271 *wl, struct platform_device *pdev)
 {
-       int ret;
+       struct wlcore_platdev_data *pdev_data = dev_get_platdata(&pdev->dev);
+       const char *nvs_name;
+       int ret = 0;
 
-       if (!wl->ops || !wl->ptable)
+       if (!wl->ops || !wl->ptable || !pdev_data)
                return -EINVAL;
 
        wl->dev = &pdev->dev;
        wl->pdev = pdev;
        platform_set_drvdata(pdev, wl);
 
-       ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
-                                     WL12XX_NVS_NAME, &pdev->dev, GFP_KERNEL,
-                                     wl, wlcore_nvs_cb);
-       if (ret < 0) {
-               wl1271_error("request_firmware_nowait failed: %d", ret);
-               complete_all(&wl->nvs_loading_complete);
+       if (pdev_data->family && pdev_data->family->nvs_name) {
+               nvs_name = pdev_data->family->nvs_name;
+               ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
+                                             nvs_name, &pdev->dev, GFP_KERNEL,
+                                             wl, wlcore_nvs_cb);
+               if (ret < 0) {
+                       wl1271_error("request_firmware_nowait failed for %s: %d",
+                                    nvs_name, ret);
+                       complete_all(&wl->nvs_loading_complete);
+               }
+       } else {
+               wlcore_nvs_cb(NULL, wl);
        }
 
        return ret;
@@ -6533,9 +6544,11 @@ EXPORT_SYMBOL_GPL(wlcore_probe);
 
 int wlcore_remove(struct platform_device *pdev)
 {
+       struct wlcore_platdev_data *pdev_data = dev_get_platdata(&pdev->dev);
        struct wl1271 *wl = platform_get_drvdata(pdev);
 
-       wait_for_completion(&wl->nvs_loading_complete);
+       if (pdev_data->family && pdev_data->family->nvs_name)
+               wait_for_completion(&wl->nvs_loading_complete);
        if (!wl->initialized)
                return 0;
 
@@ -6572,4 +6585,3 @@ MODULE_PARM_DESC(no_recovery, "Prevent HW recovery. FW will remain stuck.");
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>");
 MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>");
-MODULE_FIRMWARE(WL12XX_NVS_NAME);
index f68280db6e5eb43bf25a6499749a422d3425de37..e840985385fcef4379f683b209688e754e611333 100644 (file)
 #include "conf.h"
 #include "ini.h"
 
-/*
- * wl127x and wl128x are using the same NVS file name. However, the
- * ini parameters between them are different.  The driver validates
- * the correct NVS size in wl1271_boot_upload_nvs().
- */
-#define WL12XX_NVS_NAME "ti-connectivity/wl1271-nvs.bin"
-
 struct wilink_family_data {
        const char *name;
        const char *nvs_name;   /* wl12xx nvs file */