diff options
author | Kalle Valo <kalle.valo@nokia.com> | 2009-11-17 11:48:45 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-11-18 17:09:20 -0500 |
commit | c74ddfd5ea9c0c67d0aae77eeb5b610188cb8bc4 (patch) | |
tree | 83b9b65950079b8c4d1ee1428009fa4832791fd8 /drivers | |
parent | d5da79ac1f5050cccaa68d814ccce292371f25fa (diff) |
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: Kalle Valo <kalle.valo@nokia.com>
Reviewed-by: Vidhya Govindan <vidhya.govindan@nokia.com>
Signed-off-by: Luciano Coelho <luciano.coelho@nokia.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/wireless/wl12xx/wl1251_boot.c | 27 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/wl1251_main.c | 5 |
2 files changed, 25 insertions, 7 deletions
diff --git a/drivers/net/wireless/wl12xx/wl1251_boot.c b/drivers/net/wireless/wl12xx/wl1251_boot.c index 452d748e42c6..8febf27ab28d 100644 --- a/drivers/net/wireless/wl12xx/wl1251_boot.c +++ b/drivers/net/wireless/wl12xx/wl1251_boot.c | |||
@@ -314,8 +314,8 @@ int wl1251_boot_run_firmware(struct wl1251 *wl) | |||
314 | static int wl1251_boot_upload_firmware(struct wl1251 *wl) | 314 | static int wl1251_boot_upload_firmware(struct wl1251 *wl) |
315 | { | 315 | { |
316 | int addr, chunk_num, partition_limit; | 316 | int addr, chunk_num, partition_limit; |
317 | size_t fw_data_len; | 317 | size_t fw_data_len, len; |
318 | u8 *p; | 318 | u8 *p, *buf; |
319 | 319 | ||
320 | /* whal_FwCtrl_LoadFwImageSm() */ | 320 | /* whal_FwCtrl_LoadFwImageSm() */ |
321 | 321 | ||
@@ -334,6 +334,12 @@ static int wl1251_boot_upload_firmware(struct wl1251 *wl) | |||
334 | return -EIO; | 334 | return -EIO; |
335 | } | 335 | } |
336 | 336 | ||
337 | buf = kmalloc(CHUNK_SIZE, GFP_KERNEL); | ||
338 | if (!buf) { | ||
339 | wl1251_error("allocation for firmware upload chunk failed"); | ||
340 | return -ENOMEM; | ||
341 | } | ||
342 | |||
337 | wl1251_set_partition(wl, WL1251_PART_DOWN_MEM_START, | 343 | wl1251_set_partition(wl, WL1251_PART_DOWN_MEM_START, |
338 | WL1251_PART_DOWN_MEM_SIZE, | 344 | WL1251_PART_DOWN_MEM_SIZE, |
339 | WL1251_PART_DOWN_REG_START, | 345 | WL1251_PART_DOWN_REG_START, |
@@ -364,7 +370,11 @@ static int wl1251_boot_upload_firmware(struct wl1251 *wl) | |||
364 | p = wl->fw + FW_HDR_SIZE + chunk_num * CHUNK_SIZE; | 370 | p = wl->fw + FW_HDR_SIZE + chunk_num * CHUNK_SIZE; |
365 | wl1251_debug(DEBUG_BOOT, "uploading fw chunk 0x%p to 0x%x", | 371 | wl1251_debug(DEBUG_BOOT, "uploading fw chunk 0x%p to 0x%x", |
366 | p, addr); | 372 | p, addr); |
367 | wl1251_mem_write(wl, addr, p, CHUNK_SIZE); | 373 | |
374 | /* need to copy the chunk for dma */ | ||
375 | len = CHUNK_SIZE; | ||
376 | memcpy(buf, p, len); | ||
377 | wl1251_mem_write(wl, addr, buf, len); | ||
368 | 378 | ||
369 | chunk_num++; | 379 | chunk_num++; |
370 | } | 380 | } |
@@ -372,9 +382,16 @@ static int wl1251_boot_upload_firmware(struct wl1251 *wl) | |||
372 | /* 10.4 upload the last chunk */ | 382 | /* 10.4 upload the last chunk */ |
373 | addr = WL1251_PART_DOWN_MEM_START + chunk_num * CHUNK_SIZE; | 383 | addr = WL1251_PART_DOWN_MEM_START + chunk_num * CHUNK_SIZE; |
374 | p = wl->fw + FW_HDR_SIZE + chunk_num * CHUNK_SIZE; | 384 | p = wl->fw + FW_HDR_SIZE + chunk_num * CHUNK_SIZE; |
385 | |||
386 | /* need to copy the chunk for dma */ | ||
387 | len = fw_data_len % CHUNK_SIZE; | ||
388 | memcpy(buf, p, len); | ||
389 | |||
375 | wl1251_debug(DEBUG_BOOT, "uploading fw last chunk (%zu B) 0x%p to 0x%x", | 390 | wl1251_debug(DEBUG_BOOT, "uploading fw last chunk (%zu B) 0x%p to 0x%x", |
376 | fw_data_len % CHUNK_SIZE, p, addr); | 391 | len, p, addr); |
377 | wl1251_mem_write(wl, addr, p, fw_data_len % CHUNK_SIZE); | 392 | wl1251_mem_write(wl, addr, buf, len); |
393 | |||
394 | kfree(buf); | ||
378 | 395 | ||
379 | return 0; | 396 | return 0; |
380 | } | 397 | } |
diff --git a/drivers/net/wireless/wl12xx/wl1251_main.c b/drivers/net/wireless/wl12xx/wl1251_main.c index b5e3bdb08448..1f4c238a3371 100644 --- a/drivers/net/wireless/wl12xx/wl1251_main.c +++ b/drivers/net/wireless/wl12xx/wl1251_main.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/irq.h> | 28 | #include <linux/irq.h> |
29 | #include <linux/crc32.h> | 29 | #include <linux/crc32.h> |
30 | #include <linux/etherdevice.h> | 30 | #include <linux/etherdevice.h> |
31 | #include <linux/vmalloc.h> | ||
31 | 32 | ||
32 | #include "wl1251.h" | 33 | #include "wl1251.h" |
33 | #include "wl12xx_80211.h" | 34 | #include "wl12xx_80211.h" |
@@ -83,7 +84,7 @@ static int wl1251_fetch_firmware(struct wl1251 *wl) | |||
83 | } | 84 | } |
84 | 85 | ||
85 | wl->fw_len = fw->size; | 86 | wl->fw_len = fw->size; |
86 | wl->fw = kmalloc(wl->fw_len, GFP_KERNEL); | 87 | wl->fw = vmalloc(wl->fw_len); |
87 | 88 | ||
88 | if (!wl->fw) { | 89 | if (!wl->fw) { |
89 | wl1251_error("could not allocate memory for the firmware"); | 90 | wl1251_error("could not allocate memory for the firmware"); |
@@ -1427,7 +1428,7 @@ int wl1251_free_hw(struct wl1251 *wl) | |||
1427 | 1428 | ||
1428 | kfree(wl->target_mem_map); | 1429 | kfree(wl->target_mem_map); |
1429 | kfree(wl->data_path); | 1430 | kfree(wl->data_path); |
1430 | kfree(wl->fw); | 1431 | vfree(wl->fw); |
1431 | wl->fw = NULL; | 1432 | wl->fw = NULL; |
1432 | kfree(wl->nvs); | 1433 | kfree(wl->nvs); |
1433 | wl->nvs = NULL; | 1434 | wl->nvs = NULL; |