wl1271: Use vmalloc to allocate memory for firmware
Juuso Oikarinen [Thu, 8 Oct 2009 18:56:32 +0000 (21:56 +0300)]
Use vmalloc to allocate memory for the firmware image, and use a smaller
linear buffer for the actual transfer of the firmware to the chipset.

This patch is an adaptation of a similar patch for wl1251 by Kalle Valo.

Signed-off-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>
Reviewed-by: Luciano Coelho <luciano.coelho@nokia.com>
Signed-off-by: Luciano Coelho <luciano.coelho@nokia.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>

drivers/net/wireless/wl12xx/wl1271_boot.c
drivers/net/wireless/wl12xx/wl1271_main.c

index 8228ef4..7640313 100644 (file)
@@ -94,7 +94,7 @@ static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf,
                                             size_t fw_data_len, u32 dest)
 {
        int addr, chunk_num, partition_limit;
-       u8 *p;
+       u8 *p, *chunk;
 
        /* whal_FwCtrl_LoadFwImageSm() */
 
@@ -103,12 +103,17 @@ static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf,
        wl1271_debug(DEBUG_BOOT, "fw_data_len %zd chunk_size %d",
                     fw_data_len, CHUNK_SIZE);
 
-
        if ((fw_data_len % 4) != 0) {
                wl1271_error("firmware length not multiple of four");
                return -EIO;
        }
 
+       chunk = kmalloc(CHUNK_SIZE, GFP_KERNEL);
+       if (!buf) {
+               wl1271_error("allocation for firmware upload chunk failed");
+               return -ENOMEM;
+       }
+
        wl1271_set_partition(wl, dest,
                             part_table[PART_DOWN].mem.size,
                             part_table[PART_DOWN].reg.start,
@@ -137,9 +142,10 @@ static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf,
                /* 10.3 upload the chunk */
                addr = dest + chunk_num * CHUNK_SIZE;
                p = buf + chunk_num * CHUNK_SIZE;
+               memcpy(chunk, p, CHUNK_SIZE);
                wl1271_debug(DEBUG_BOOT, "uploading fw chunk 0x%p to 0x%x",
                             p, addr);
-               wl1271_spi_mem_write(wl, addr, p, CHUNK_SIZE);
+               wl1271_spi_mem_write(wl, addr, chunk, CHUNK_SIZE);
 
                chunk_num++;
        }
@@ -147,10 +153,12 @@ static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf,
        /* 10.4 upload the last chunk */
        addr = dest + chunk_num * CHUNK_SIZE;
        p = buf + chunk_num * CHUNK_SIZE;
+       memcpy(chunk, p, fw_data_len % CHUNK_SIZE);
        wl1271_debug(DEBUG_BOOT, "uploading fw last chunk (%zd B) 0x%p to 0x%x",
                     fw_data_len % CHUNK_SIZE, p, addr);
-       wl1271_spi_mem_write(wl, addr, p, fw_data_len % CHUNK_SIZE);
+       wl1271_spi_mem_write(wl, addr, chunk, fw_data_len % CHUNK_SIZE);
 
+       kfree(chunk);
        return 0;
 }
 
index 09fe968..d22de23 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/spi/spi.h>
 #include <linux/crc32.h>
 #include <linux/etherdevice.h>
+#include <linux/vmalloc.h>
 #include <linux/spi/wl12xx.h>
 
 #include "wl1271.h"
@@ -231,7 +232,7 @@ static int wl1271_fetch_firmware(struct wl1271 *wl)
        }
 
        wl->fw_len = fw->size;
-       wl->fw = kmalloc(wl->fw_len, GFP_KERNEL);
+       wl->fw = vmalloc(wl->fw_len);
 
        if (!wl->fw) {
                wl1271_error("could not allocate memory for the firmware");
@@ -1484,7 +1485,7 @@ static int __devexit wl1271_remove(struct spi_device *spi)
        platform_device_unregister(&wl1271_device);
        free_irq(wl->irq, wl);
        kfree(wl->target_mem_map);
-       kfree(wl->fw);
+       vfree(wl->fw);
        wl->fw = NULL;
        kfree(wl->nvs);
        wl->nvs = NULL;