iwlwifi: alloc memory dynamically also for DVM
authorSara Sharon <sara.sharon@intel.com>
Mon, 30 Jan 2017 10:34:32 +0000 (12:34 +0200)
committerKalle Valo <kvalo@codeaurora.org>
Tue, 31 Jan 2017 07:10:24 +0000 (09:10 +0200)
For old firmwares the memory wasn't allocated, resulting in panic.
Make it dynamically allocated as well. Allow any order of functions
call.

Fixes: eef187a7b8a1 ("iwlwifi: enlarge number of ucode sections")
Signed-off-by: Sara Sharon <sara.sharon@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
Tested-by: Kalle Valo <kvalo@codeaurora.org>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
drivers/net/wireless/intel/iwlwifi/iwl-drv.c

index 1d1af4b..d228215 100644 (file)
@@ -291,11 +291,33 @@ static struct fw_sec *get_sec(struct iwl_firmware_pieces *pieces,
        return &pieces->img[type].sec[sec];
 }
 
+static void alloc_sec_data(struct iwl_firmware_pieces *pieces,
+                          enum iwl_ucode_type type,
+                          int sec)
+{
+       struct fw_img_parsing *img = &pieces->img[type];
+       struct fw_sec *sec_memory;
+       int size = sec + 1;
+       size_t alloc_size = sizeof(*img->sec) * size;
+
+       if (img->sec && img->sec_counter >= size)
+               return;
+
+       sec_memory = krealloc(img->sec, alloc_size, GFP_KERNEL);
+       if (!sec_memory)
+               return;
+
+       img->sec = sec_memory;
+       img->sec_counter = size;
+}
+
 static void set_sec_data(struct iwl_firmware_pieces *pieces,
                         enum iwl_ucode_type type,
                         int sec,
                         const void *data)
 {
+       alloc_sec_data(pieces, type, sec);
+
        pieces->img[type].sec[sec].data = data;
 }
 
@@ -304,6 +326,8 @@ static void set_sec_size(struct iwl_firmware_pieces *pieces,
                         int sec,
                         size_t size)
 {
+       alloc_sec_data(pieces, type, sec);
+
        pieces->img[type].sec[sec].size = size;
 }
 
@@ -319,6 +343,8 @@ static void set_sec_offset(struct iwl_firmware_pieces *pieces,
                           int sec,
                           u32 offset)
 {
+       alloc_sec_data(pieces, type, sec);
+
        pieces->img[type].sec[sec].offset = offset;
 }