aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl-drv.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2012-09-10 05:50:18 -0400
committerJohannes Berg <johannes.berg@intel.com>2012-09-10 13:14:30 -0400
commit83f84d7bd49f9e4deea0a77a76c9882673ee1f3c (patch)
treefb2f84fa74450f89cbb429a7457ff0e80ece35b7 /drivers/net/wireless/iwlwifi/iwl-drv.c
parent7439046d9747966bb805ca8bfd1086a876a4b8fd (diff)
iwlwifi: load firmware in chunks
Instead of allocating one big chunk of DMA-coherent memory for the firmware and keeping it around, only vmalloc() the firmware and copy it into a single page of DMA-coherent memory for the upload. The advantage is that we don't need DMA memory for the firmware image that is stored while the driver is operating, we only need it while uploading. This will make it easier for the driver to work if the system has fragmented memory. Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-drv.c')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-drv.c26
1 files changed, 14 insertions, 12 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-drv.c b/drivers/net/wireless/iwlwifi/iwl-drv.c
index 48d6d44c16d0..198634b75ed0 100644
--- a/drivers/net/wireless/iwlwifi/iwl-drv.c
+++ b/drivers/net/wireless/iwlwifi/iwl-drv.c
@@ -64,6 +64,7 @@
64#include <linux/dma-mapping.h> 64#include <linux/dma-mapping.h>
65#include <linux/firmware.h> 65#include <linux/firmware.h>
66#include <linux/module.h> 66#include <linux/module.h>
67#include <linux/vmalloc.h>
67 68
68#include "iwl-drv.h" 69#include "iwl-drv.h"
69#include "iwl-debug.h" 70#include "iwl-debug.h"
@@ -164,10 +165,8 @@ struct fw_sec {
164 165
165static void iwl_free_fw_desc(struct iwl_drv *drv, struct fw_desc *desc) 166static void iwl_free_fw_desc(struct iwl_drv *drv, struct fw_desc *desc)
166{ 167{
167 if (desc->v_addr) 168 vfree(desc->data);
168 dma_free_coherent(drv->trans->dev, desc->len, 169 desc->data = NULL;
169 desc->v_addr, desc->p_addr);
170 desc->v_addr = NULL;
171 desc->len = 0; 170 desc->len = 0;
172} 171}
173 172
@@ -186,21 +185,24 @@ static void iwl_dealloc_ucode(struct iwl_drv *drv)
186} 185}
187 186
188static int iwl_alloc_fw_desc(struct iwl_drv *drv, struct fw_desc *desc, 187static int iwl_alloc_fw_desc(struct iwl_drv *drv, struct fw_desc *desc,
189 struct fw_sec *sec) 188 struct fw_sec *sec)
190{ 189{
191 if (!sec || !sec->size) { 190 void *data;
192 desc->v_addr = NULL; 191
192 desc->data = NULL;
193
194 if (!sec || !sec->size)
193 return -EINVAL; 195 return -EINVAL;
194 }
195 196
196 desc->v_addr = dma_alloc_coherent(drv->trans->dev, sec->size, 197 data = vmalloc(sec->size);
197 &desc->p_addr, GFP_KERNEL); 198 if (!data)
198 if (!desc->v_addr)
199 return -ENOMEM; 199 return -ENOMEM;
200 200
201 desc->len = sec->size; 201 desc->len = sec->size;
202 desc->offset = sec->offset; 202 desc->offset = sec->offset;
203 memcpy(desc->v_addr, sec->data, sec->size); 203 memcpy(data, sec->data, desc->len);
204 desc->data = data;
205
204 return 0; 206 return 0;
205} 207}
206 208