Commit c74ddfd5 authored by Kalle Valo's avatar Kalle Valo Committed by John W. Linville

wl1251: allocate space for firmware with vmalloc()

Earlier firmware was stored to a memory area allocated with kmalloc()
but finding a a contiguous area of memory long enough for the firmware is
very difficult in certain cases. better to allocate the memory for firmware
with vmalloc() instead and use a small buffer for DMA transfers.

Thanks to Eero Tamminen for the idea.
Signed-off-by: default avatarKalle Valo <kalle.valo@nokia.com>
Reviewed-by: default avatarVidhya Govindan <vidhya.govindan@nokia.com>
Signed-off-by: default avatarLuciano Coelho <luciano.coelho@nokia.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent d5da79ac
...@@ -314,8 +314,8 @@ int wl1251_boot_run_firmware(struct wl1251 *wl) ...@@ -314,8 +314,8 @@ int wl1251_boot_run_firmware(struct wl1251 *wl)
static int wl1251_boot_upload_firmware(struct wl1251 *wl) static int wl1251_boot_upload_firmware(struct wl1251 *wl)
{ {
int addr, chunk_num, partition_limit; int addr, chunk_num, partition_limit;
size_t fw_data_len; size_t fw_data_len, len;
u8 *p; u8 *p, *buf;
/* whal_FwCtrl_LoadFwImageSm() */ /* whal_FwCtrl_LoadFwImageSm() */
...@@ -334,6 +334,12 @@ static int wl1251_boot_upload_firmware(struct wl1251 *wl) ...@@ -334,6 +334,12 @@ static int wl1251_boot_upload_firmware(struct wl1251 *wl)
return -EIO; return -EIO;
} }
buf = kmalloc(CHUNK_SIZE, GFP_KERNEL);
if (!buf) {
wl1251_error("allocation for firmware upload chunk failed");
return -ENOMEM;
}
wl1251_set_partition(wl, WL1251_PART_DOWN_MEM_START, wl1251_set_partition(wl, WL1251_PART_DOWN_MEM_START,
WL1251_PART_DOWN_MEM_SIZE, WL1251_PART_DOWN_MEM_SIZE,
WL1251_PART_DOWN_REG_START, WL1251_PART_DOWN_REG_START,
...@@ -364,7 +370,11 @@ static int wl1251_boot_upload_firmware(struct wl1251 *wl) ...@@ -364,7 +370,11 @@ static int wl1251_boot_upload_firmware(struct wl1251 *wl)
p = wl->fw + FW_HDR_SIZE + chunk_num * CHUNK_SIZE; p = wl->fw + FW_HDR_SIZE + chunk_num * CHUNK_SIZE;
wl1251_debug(DEBUG_BOOT, "uploading fw chunk 0x%p to 0x%x", wl1251_debug(DEBUG_BOOT, "uploading fw chunk 0x%p to 0x%x",
p, addr); p, addr);
wl1251_mem_write(wl, addr, p, CHUNK_SIZE);
/* need to copy the chunk for dma */
len = CHUNK_SIZE;
memcpy(buf, p, len);
wl1251_mem_write(wl, addr, buf, len);
chunk_num++; chunk_num++;
} }
...@@ -372,9 +382,16 @@ static int wl1251_boot_upload_firmware(struct wl1251 *wl) ...@@ -372,9 +382,16 @@ static int wl1251_boot_upload_firmware(struct wl1251 *wl)
/* 10.4 upload the last chunk */ /* 10.4 upload the last chunk */
addr = WL1251_PART_DOWN_MEM_START + chunk_num * CHUNK_SIZE; addr = WL1251_PART_DOWN_MEM_START + chunk_num * CHUNK_SIZE;
p = wl->fw + FW_HDR_SIZE + chunk_num * CHUNK_SIZE; p = wl->fw + FW_HDR_SIZE + chunk_num * CHUNK_SIZE;
/* need to copy the chunk for dma */
len = fw_data_len % CHUNK_SIZE;
memcpy(buf, p, len);
wl1251_debug(DEBUG_BOOT, "uploading fw last chunk (%zu B) 0x%p to 0x%x", wl1251_debug(DEBUG_BOOT, "uploading fw last chunk (%zu B) 0x%p to 0x%x",
fw_data_len % CHUNK_SIZE, p, addr); len, p, addr);
wl1251_mem_write(wl, addr, p, fw_data_len % CHUNK_SIZE); wl1251_mem_write(wl, addr, buf, len);
kfree(buf);
return 0; return 0;
} }
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/crc32.h> #include <linux/crc32.h>
#include <linux/etherdevice.h> #include <linux/etherdevice.h>
#include <linux/vmalloc.h>
#include "wl1251.h" #include "wl1251.h"
#include "wl12xx_80211.h" #include "wl12xx_80211.h"
...@@ -83,7 +84,7 @@ static int wl1251_fetch_firmware(struct wl1251 *wl) ...@@ -83,7 +84,7 @@ static int wl1251_fetch_firmware(struct wl1251 *wl)
} }
wl->fw_len = fw->size; wl->fw_len = fw->size;
wl->fw = kmalloc(wl->fw_len, GFP_KERNEL); wl->fw = vmalloc(wl->fw_len);
if (!wl->fw) { if (!wl->fw) {
wl1251_error("could not allocate memory for the firmware"); wl1251_error("could not allocate memory for the firmware");
...@@ -1427,7 +1428,7 @@ int wl1251_free_hw(struct wl1251 *wl) ...@@ -1427,7 +1428,7 @@ int wl1251_free_hw(struct wl1251 *wl)
kfree(wl->target_mem_map); kfree(wl->target_mem_map);
kfree(wl->data_path); kfree(wl->data_path);
kfree(wl->fw); vfree(wl->fw);
wl->fw = NULL; wl->fw = NULL;
kfree(wl->nvs); kfree(wl->nvs);
wl->nvs = NULL; wl->nvs = NULL;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment