aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi
diff options
context:
space:
mode:
authorDavid Spinadel <david.spinadel@intel.com>2012-03-10 16:00:14 -0500
committerJohn W. Linville <linville@tuxdriver.com>2012-03-12 14:22:09 -0400
commit6dfa8d019cd21d08634ceb65a3fb90d0648bd93b (patch)
tree04cb6b0be027598b782d8c91ab5ae681d3304d83 /drivers/net/wireless/iwlwifi
parented8c8365c4431eeb733def3dd314cf303e1b12ea (diff)
iwlwifi: change struct iwl_fw
Change iwl_fw struct to hold an array of fw_img instead of three separated instances. Change fw_img to hold an array of fw_desc instead of two separate descriptors for instructions and data. Change load_given_ucode, load_section, verification functions etc. to support this structure. Signed-off-by: David Spinadel <david.spinadel@intel.com> Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-debugfs.c17
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-drv.c141
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-fw.h25
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-mac80211.c15
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-testmode.c21
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-trans-pcie.c32
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-ucode.c29
7 files changed, 139 insertions, 141 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
index 89cb9a7a3b56..b7b1c04f2fba 100644
--- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
@@ -230,6 +230,7 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file,
230 int pos = 0; 230 int pos = 0;
231 int sram; 231 int sram;
232 struct iwl_priv *priv = file->private_data; 232 struct iwl_priv *priv = file->private_data;
233 const struct fw_img *img;
233 size_t bufsz; 234 size_t bufsz;
234 235
235 /* default is to dump the entire data segment */ 236 /* default is to dump the entire data segment */
@@ -239,17 +240,8 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file,
239 IWL_ERR(priv, "No uCode has been loadded.\n"); 240 IWL_ERR(priv, "No uCode has been loadded.\n");
240 return -EINVAL; 241 return -EINVAL;
241 } 242 }
242 if (priv->shrd->ucode_type == IWL_UCODE_INIT) { 243 img = &priv->fw->img[priv->shrd->ucode_type];
243 priv->dbgfs_sram_len = priv->fw->ucode_init.data.len; 244 priv->dbgfs_sram_len = img->sec[IWL_UCODE_SECTION_DATA].len;
244 } else if (priv->shrd->ucode_type == IWL_UCODE_REGULAR) {
245 priv->dbgfs_sram_len = priv->fw->ucode_rt.data.len;
246 } else if (priv->shrd->ucode_type == IWL_UCODE_WOWLAN) {
247 priv->dbgfs_sram_len = priv->fw->ucode_wowlan.data.len;
248 } else {
249 IWL_ERR(priv, "Unsupported type of uCode loaded?"
250 " that shouldn't happen.\n");
251 return -EINVAL;
252 }
253 } 245 }
254 len = priv->dbgfs_sram_len; 246 len = priv->dbgfs_sram_len;
255 247
@@ -346,13 +338,14 @@ static ssize_t iwl_dbgfs_wowlan_sram_read(struct file *file,
346 size_t count, loff_t *ppos) 338 size_t count, loff_t *ppos)
347{ 339{
348 struct iwl_priv *priv = file->private_data; 340 struct iwl_priv *priv = file->private_data;
341 const struct fw_img *img = &priv->fw->img[IWL_UCODE_WOWLAN];
349 342
350 if (!priv->wowlan_sram) 343 if (!priv->wowlan_sram)
351 return -ENODATA; 344 return -ENODATA;
352 345
353 return simple_read_from_buffer(user_buf, count, ppos, 346 return simple_read_from_buffer(user_buf, count, ppos,
354 priv->wowlan_sram, 347 priv->wowlan_sram,
355 priv->fw->ucode_wowlan.data.len); 348 img->sec[IWL_UCODE_SECTION_DATA].len);
356} 349}
357static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf, 350static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf,
358 size_t count, loff_t *ppos) 351 size_t count, loff_t *ppos)
diff --git a/drivers/net/wireless/iwlwifi/iwl-drv.c b/drivers/net/wireless/iwlwifi/iwl-drv.c
index 19ccd36a55b3..54e09696fc9d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-drv.c
+++ b/drivers/net/wireless/iwlwifi/iwl-drv.c
@@ -118,15 +118,16 @@ static void iwl_free_fw_desc(struct iwl_drv *drv, struct fw_desc *desc)
118 118
119static void iwl_free_fw_img(struct iwl_drv *drv, struct fw_img *img) 119static void iwl_free_fw_img(struct iwl_drv *drv, struct fw_img *img)
120{ 120{
121 iwl_free_fw_desc(drv, &img->code); 121 int i;
122 iwl_free_fw_desc(drv, &img->data); 122 for (i = 0; i < IWL_UCODE_SECTION_MAX; i++)
123 iwl_free_fw_desc(drv, &img->sec[i]);
123} 124}
124 125
125static void iwl_dealloc_ucode(struct iwl_drv *drv) 126static void iwl_dealloc_ucode(struct iwl_drv *drv)
126{ 127{
127 iwl_free_fw_img(drv, &drv->fw.ucode_rt); 128 int i;
128 iwl_free_fw_img(drv, &drv->fw.ucode_init); 129 for (i = 0; i < IWL_UCODE_TYPE_MAX; i++)
129 iwl_free_fw_img(drv, &drv->fw.ucode_wowlan); 130 iwl_free_fw_img(drv, drv->fw.img + i);
130} 131}
131 132
132static int iwl_alloc_fw_desc(struct iwl_drv *drv, struct fw_desc *desc, 133static int iwl_alloc_fw_desc(struct iwl_drv *drv, struct fw_desc *desc,
@@ -189,22 +190,8 @@ static int iwl_request_firmware(struct iwl_drv *drv, bool first)
189 GFP_KERNEL, drv, iwl_ucode_callback); 190 GFP_KERNEL, drv, iwl_ucode_callback);
190} 191}
191 192
192/*
193 * enumeration of ucode section.
194 * This enumeration is used for legacy tlv style (before 16.0 uCode).
195 */
196enum iwl_ucode_sec {
197 IWL_UCODE_SECTION_INST,
198 IWL_UCODE_SECTION_DATA,
199};
200/*
201 * For 16.0 uCode and above, there is no differentiation between section,
202 * just an offset to the HW address.
203 */
204#define UCODE_SECTION_MAX 4
205
206struct fw_img_parsing { 193struct fw_img_parsing {
207 struct fw_sec sec[UCODE_SECTION_MAX]; 194 struct fw_sec sec[IWL_UCODE_SECTION_MAX];
208 int sec_counter; 195 int sec_counter;
209}; 196};
210 197
@@ -691,6 +678,71 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
691 return -EINVAL; 678 return -EINVAL;
692} 679}
693 680
681static int alloc_pci_desc(struct iwl_drv *drv,
682 struct iwl_firmware_pieces *pieces,
683 enum iwl_ucode_type type)
684{
685 int i;
686 for (i = 0;
687 i < IWL_UCODE_SECTION_MAX && get_sec_size(pieces, type, i);
688 i++)
689 if (iwl_alloc_fw_desc(drv, &(drv->fw.img[type].sec[i]),
690 get_sec(pieces, type, i)))
691 return -1;
692 return 0;
693}
694
695static int validate_sec_sizes(struct iwl_drv *drv,
696 struct iwl_firmware_pieces *pieces,
697 const struct iwl_cfg *cfg)
698{
699 IWL_DEBUG_INFO(drv, "f/w package hdr runtime inst size = %Zd\n",
700 get_sec_size(pieces, IWL_UCODE_REGULAR,
701 IWL_UCODE_SECTION_INST));
702 IWL_DEBUG_INFO(drv, "f/w package hdr runtime data size = %Zd\n",
703 get_sec_size(pieces, IWL_UCODE_REGULAR,
704 IWL_UCODE_SECTION_DATA));
705 IWL_DEBUG_INFO(drv, "f/w package hdr init inst size = %Zd\n",
706 get_sec_size(pieces, IWL_UCODE_INIT, IWL_UCODE_SECTION_INST));
707 IWL_DEBUG_INFO(drv, "f/w package hdr init data size = %Zd\n",
708 get_sec_size(pieces, IWL_UCODE_INIT, IWL_UCODE_SECTION_DATA));
709
710 /* Verify that uCode images will fit in card's SRAM. */
711 if (get_sec_size(pieces, IWL_UCODE_REGULAR, IWL_UCODE_SECTION_INST) >
712 cfg->max_inst_size) {
713 IWL_ERR(drv, "uCode instr len %Zd too large to fit in\n",
714 get_sec_size(pieces, IWL_UCODE_REGULAR,
715 IWL_UCODE_SECTION_INST));
716 return -1;
717 }
718
719 if (get_sec_size(pieces, IWL_UCODE_REGULAR, IWL_UCODE_SECTION_DATA) >
720 cfg->max_data_size) {
721 IWL_ERR(drv, "uCode data len %Zd too large to fit in\n",
722 get_sec_size(pieces, IWL_UCODE_REGULAR,
723 IWL_UCODE_SECTION_DATA));
724 return -1;
725 }
726
727 if (get_sec_size(pieces, IWL_UCODE_INIT, IWL_UCODE_SECTION_INST) >
728 cfg->max_inst_size) {
729 IWL_ERR(drv, "uCode init instr len %Zd too large to fit in\n",
730 get_sec_size(pieces, IWL_UCODE_INIT,
731 IWL_UCODE_SECTION_INST));
732 return -1;
733 }
734
735 if (get_sec_size(pieces, IWL_UCODE_INIT, IWL_UCODE_SECTION_DATA) >
736 cfg->max_data_size) {
737 IWL_ERR(drv, "uCode init data len %Zd too large to fit in\n",
738 get_sec_size(pieces, IWL_UCODE_REGULAR,
739 IWL_UCODE_SECTION_DATA));
740 return -1;
741 }
742 return 0;
743}
744
745
694/** 746/**
695 * iwl_ucode_callback - callback when firmware was loaded 747 * iwl_ucode_callback - callback when firmware was loaded
696 * 748 *
@@ -709,6 +761,7 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
709 unsigned int api_ok = cfg->ucode_api_ok; 761 unsigned int api_ok = cfg->ucode_api_ok;
710 const unsigned int api_min = cfg->ucode_api_min; 762 const unsigned int api_min = cfg->ucode_api_min;
711 u32 api_ver; 763 u32 api_ver;
764 int i;
712 765
713 fw->ucode_capa.max_probe_length = 200; 766 fw->ucode_capa.max_probe_length = 200;
714 fw->ucode_capa.standard_phy_calibration_size = 767 fw->ucode_capa.standard_phy_calibration_size =
@@ -817,59 +870,17 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
817 goto try_again; 870 goto try_again;
818 } 871 }
819 872
820 if (get_sec_size(&pieces, IWL_UCODE_INIT, IWL_UCODE_SECTION_INST) > 873 if (validate_sec_sizes(drv, &pieces, cfg))
821 cfg->max_inst_size) {
822 IWL_ERR(drv, "uCode init instr len %Zd too large to fit in\n",
823 get_sec_size(&pieces, IWL_UCODE_INIT,
824 IWL_UCODE_SECTION_INST));
825 goto try_again; 874 goto try_again;
826 }
827
828 if (get_sec_size(&pieces, IWL_UCODE_INIT, IWL_UCODE_SECTION_DATA) >
829 cfg->max_data_size) {
830 IWL_ERR(drv, "uCode init data len %Zd too large to fit in\n",
831 get_sec_size(&pieces, IWL_UCODE_REGULAR,
832 IWL_UCODE_SECTION_DATA));
833 goto try_again;
834 }
835 875
836 /* Allocate ucode buffers for card's bus-master loading ... */ 876 /* Allocate ucode buffers for card's bus-master loading ... */
837 877
838 /* Runtime instructions and 2 copies of data: 878 /* Runtime instructions and 2 copies of data:
839 * 1) unmodified from disk 879 * 1) unmodified from disk
840 * 2) backup cache for save/restore during power-downs */ 880 * 2) backup cache for save/restore during power-downs */
841 if (iwl_alloc_fw_desc(drv, &drv->fw.ucode_rt.code, 881 for (i = 0; i < IWL_UCODE_TYPE_MAX; i++)
842 get_sec(&pieces, IWL_UCODE_REGULAR, IWL_UCODE_SECTION_INST))) 882 if (alloc_pci_desc(drv, &pieces, i))
843 goto err_pci_alloc;
844 if (iwl_alloc_fw_desc(drv, &drv->fw.ucode_rt.data,
845 get_sec(&pieces, IWL_UCODE_REGULAR, IWL_UCODE_SECTION_DATA)))
846 goto err_pci_alloc;
847
848 /* Initialization instructions and data */
849 if (get_sec_size(&pieces, IWL_UCODE_INIT, IWL_UCODE_SECTION_INST) &&
850 get_sec_size(&pieces, IWL_UCODE_INIT, IWL_UCODE_SECTION_DATA)) {
851 if (iwl_alloc_fw_desc(drv, &drv->fw.ucode_init.code,
852 get_sec(&pieces, IWL_UCODE_INIT,
853 IWL_UCODE_SECTION_INST)))
854 goto err_pci_alloc;
855 if (iwl_alloc_fw_desc(drv, &drv->fw.ucode_init.data,
856 get_sec(&pieces, IWL_UCODE_INIT,
857 IWL_UCODE_SECTION_DATA)))
858 goto err_pci_alloc; 883 goto err_pci_alloc;
859 }
860
861 /* WoWLAN instructions and data */
862 if (get_sec_size(&pieces, IWL_UCODE_WOWLAN, IWL_UCODE_SECTION_INST) &&
863 get_sec_size(&pieces, IWL_UCODE_WOWLAN, IWL_UCODE_SECTION_DATA)) {
864 if (iwl_alloc_fw_desc(drv, &drv->fw.ucode_wowlan.code,
865 get_sec(&pieces, IWL_UCODE_WOWLAN,
866 IWL_UCODE_SECTION_INST)))
867 goto err_pci_alloc;
868 if (iwl_alloc_fw_desc(drv, &drv->fw.ucode_wowlan.data,
869 get_sec(&pieces, IWL_UCODE_WOWLAN,
870 IWL_UCODE_SECTION_DATA)))
871 goto err_pci_alloc;
872 }
873 884
874 /* Now that we can no longer fail, copy information */ 885 /* Now that we can no longer fail, copy information */
875 886
diff --git a/drivers/net/wireless/iwlwifi/iwl-fw.h b/drivers/net/wireless/iwlwifi/iwl-fw.h
index c99a7fd1d29a..5d634f3db929 100644
--- a/drivers/net/wireless/iwlwifi/iwl-fw.h
+++ b/drivers/net/wireless/iwlwifi/iwl-fw.h
@@ -101,6 +101,20 @@ enum iwl_ucode_type {
101 IWL_UCODE_TYPE_MAX, 101 IWL_UCODE_TYPE_MAX,
102}; 102};
103 103
104/*
105 * enumeration of ucode section.
106 * This enumeration is used for legacy tlv style (before 16.0 uCode).
107 */
108enum iwl_ucode_sec {
109 IWL_UCODE_SECTION_INST,
110 IWL_UCODE_SECTION_DATA,
111};
112/*
113 * For 16.0 uCode and above, there is no differentiation between sections,
114 * just an offset to the HW address.
115 */
116#define IWL_UCODE_SECTION_MAX 4
117
104struct iwl_ucode_capabilities { 118struct iwl_ucode_capabilities {
105 u32 max_probe_length; 119 u32 max_probe_length;
106 u32 standard_phy_calibration_size; 120 u32 standard_phy_calibration_size;
@@ -116,8 +130,7 @@ struct fw_desc {
116}; 130};
117 131
118struct fw_img { 132struct fw_img {
119 struct fw_desc code; /* firmware code image */ 133 struct fw_desc sec[IWL_UCODE_SECTION_MAX];
120 struct fw_desc data; /* firmware data image */
121}; 134};
122 135
123/* uCode version contains 4 values: Major/Minor/API/Serial */ 136/* uCode version contains 4 values: Major/Minor/API/Serial */
@@ -131,9 +144,7 @@ struct fw_img {
131 * 144 *
132 * @ucode_ver: ucode version from the ucode file 145 * @ucode_ver: ucode version from the ucode file
133 * @fw_version: firmware version string 146 * @fw_version: firmware version string
134 * @ucode_rt: run time ucode image 147 * @img: ucode image like ucode_rt, ucode_init, ucode_wowlan.
135 * @ucode_init: init ucode image
136 * @ucode_wowlan: wake on wireless ucode image (optional)
137 * @ucode_capa: capabilities parsed from the ucode file. 148 * @ucode_capa: capabilities parsed from the ucode file.
138 * @enhance_sensitivity_table: device can do enhanced sensitivity. 149 * @enhance_sensitivity_table: device can do enhanced sensitivity.
139 * @init_evtlog_ptr: event log offset for init ucode. 150 * @init_evtlog_ptr: event log offset for init ucode.
@@ -149,9 +160,7 @@ struct iwl_fw {
149 char fw_version[ETHTOOL_BUSINFO_LEN]; 160 char fw_version[ETHTOOL_BUSINFO_LEN];
150 161
151 /* ucode images */ 162 /* ucode images */
152 struct fw_img ucode_rt; 163 struct fw_img img[IWL_UCODE_TYPE_MAX];
153 struct fw_img ucode_init;
154 struct fw_img ucode_wowlan;
155 164
156 struct iwl_ucode_capabilities ucode_capa; 165 struct iwl_ucode_capabilities ucode_capa;
157 bool enhance_sensitivity_table; 166 bool enhance_sensitivity_table;
diff --git a/drivers/net/wireless/iwlwifi/iwl-mac80211.c b/drivers/net/wireless/iwlwifi/iwl-mac80211.c
index 9212ee3bef9b..b6805f8e9a01 100644
--- a/drivers/net/wireless/iwlwifi/iwl-mac80211.c
+++ b/drivers/net/wireless/iwlwifi/iwl-mac80211.c
@@ -196,7 +196,7 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv,
196 WIPHY_FLAG_DISABLE_BEACON_HINTS | 196 WIPHY_FLAG_DISABLE_BEACON_HINTS |
197 WIPHY_FLAG_IBSS_RSN; 197 WIPHY_FLAG_IBSS_RSN;
198 198
199 if (priv->fw->ucode_wowlan.code.len && 199 if (priv->fw->img[IWL_UCODE_WOWLAN].sec[0].len &&
200 trans(priv)->ops->wowlan_suspend && 200 trans(priv)->ops->wowlan_suspend &&
201 device_can_wakeup(trans(priv)->dev)) { 201 device_can_wakeup(trans(priv)->dev)) {
202 hw->wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT | 202 hw->wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT |
@@ -437,6 +437,7 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw)
437 unsigned long flags; 437 unsigned long flags;
438 u32 base, status = 0xffffffff; 438 u32 base, status = 0xffffffff;
439 int ret = -EIO; 439 int ret = -EIO;
440 const struct fw_img *img;
440 441
441 IWL_DEBUG_MAC80211(priv, "enter\n"); 442 IWL_DEBUG_MAC80211(priv, "enter\n");
442 mutex_lock(&priv->mutex); 443 mutex_lock(&priv->mutex);
@@ -457,16 +458,18 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw)
457 458
458#ifdef CONFIG_IWLWIFI_DEBUGFS 459#ifdef CONFIG_IWLWIFI_DEBUGFS
459 if (ret == 0) { 460 if (ret == 0) {
460 if (!priv->wowlan_sram) 461 img = &(priv->fw->img[IWL_UCODE_WOWLAN]);
462 if (!priv->wowlan_sram) {
461 priv->wowlan_sram = 463 priv->wowlan_sram =
462 kzalloc(priv->fw->ucode_wowlan.data.len, 464 kzalloc(img->sec[IWL_UCODE_SECTION_DATA].len,
463 GFP_KERNEL); 465 GFP_KERNEL);
466 }
464 467
465 if (priv->wowlan_sram) 468 if (priv->wowlan_sram)
466 _iwl_read_targ_mem_words( 469 _iwl_read_targ_mem_words(
467 trans(priv), 0x800000, 470 trans(priv), 0x800000,
468 priv->wowlan_sram, 471 priv->wowlan_sram,
469 priv->fw->ucode_wowlan.data.len / 4); 472 img->sec[IWL_UCODE_SECTION_DATA].len / 4);
470 } 473 }
471#endif 474#endif
472 } 475 }
diff --git a/drivers/net/wireless/iwlwifi/iwl-testmode.c b/drivers/net/wireless/iwlwifi/iwl-testmode.c
index c6c084f45b72..76f7f9251436 100644
--- a/drivers/net/wireless/iwlwifi/iwl-testmode.c
+++ b/drivers/net/wireless/iwlwifi/iwl-testmode.c
@@ -466,6 +466,7 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb)
466 unsigned char *rsp_data_ptr = NULL; 466 unsigned char *rsp_data_ptr = NULL;
467 int status = 0, rsp_data_len = 0; 467 int status = 0, rsp_data_len = 0;
468 u32 devid, inst_size = 0, data_size = 0; 468 u32 devid, inst_size = 0, data_size = 0;
469 const struct fw_img *img;
469 470
470 switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) { 471 switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) {
471 case IWL_TM_CMD_APP2DEV_GET_DEVICENAME: 472 case IWL_TM_CMD_APP2DEV_GET_DEVICENAME:
@@ -597,23 +598,9 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb)
597 IWL_ERR(priv, "No uCode has not been loaded\n"); 598 IWL_ERR(priv, "No uCode has not been loaded\n");
598 return -EINVAL; 599 return -EINVAL;
599 } else { 600 } else {
600 switch (priv->shrd->ucode_type) { 601 img = &priv->fw->img[priv->shrd->ucode_type];
601 case IWL_UCODE_REGULAR: 602 inst_size = img->sec[IWL_UCODE_SECTION_INST].len;
602 inst_size = priv->fw->ucode_rt.code.len; 603 data_size = img->sec[IWL_UCODE_SECTION_DATA].len;
603 data_size = priv->fw->ucode_rt.data.len;
604 break;
605 case IWL_UCODE_INIT:
606 inst_size = priv->fw->ucode_init.code.len;
607 data_size = priv->fw->ucode_init.data.len;
608 break;
609 case IWL_UCODE_WOWLAN:
610 inst_size = priv->fw->ucode_wowlan.code.len;
611 data_size = priv->fw->ucode_wowlan.data.len;
612 break;
613 default:
614 IWL_ERR(priv, "Unsupported uCode type\n");
615 break;
616 }
617 } 604 }
618 NLA_PUT_U32(skb, IWL_TM_ATTR_FW_TYPE, priv->shrd->ucode_type); 605 NLA_PUT_U32(skb, IWL_TM_ATTR_FW_TYPE, priv->shrd->ucode_type);
619 NLA_PUT_U32(skb, IWL_TM_ATTR_FW_INST_SIZE, inst_size); 606 NLA_PUT_U32(skb, IWL_TM_ATTR_FW_INST_SIZE, inst_size);
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c
index 0e8e31a53c7a..b4f796c82e1e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c
+++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c
@@ -951,12 +951,13 @@ static const u8 iwlagn_pan_ac_to_queue[] = {
951/* 951/*
952 * ucode 952 * ucode
953 */ 953 */
954static int iwl_load_section(struct iwl_trans *trans, const char *name, 954static int iwl_load_section(struct iwl_trans *trans, u8 section_num,
955 const struct fw_desc *image, u32 dst_addr) 955 const struct fw_desc *section)
956{ 956{
957 struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); 957 struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
958 dma_addr_t phy_addr = image->p_addr; 958 dma_addr_t phy_addr = section->p_addr;
959 u32 byte_cnt = image->len; 959 u32 byte_cnt = section->len;
960 u32 dst_addr = section->offset;
960 int ret; 961 int ret;
961 962
962 trans_pcie->ucode_write_complete = false; 963 trans_pcie->ucode_write_complete = false;
@@ -989,12 +990,13 @@ static int iwl_load_section(struct iwl_trans *trans, const char *name,
989 FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE | 990 FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE |
990 FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD); 991 FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD);
991 992
992 IWL_DEBUG_FW(trans, "%s uCode section being loaded...\n", name); 993 IWL_DEBUG_FW(trans, "[%d] uCode section being loaded...\n",
994 section_num);
993 ret = wait_event_timeout(trans_pcie->ucode_write_waitq, 995 ret = wait_event_timeout(trans_pcie->ucode_write_waitq,
994 trans_pcie->ucode_write_complete, 5 * HZ); 996 trans_pcie->ucode_write_complete, 5 * HZ);
995 if (!ret) { 997 if (!ret) {
996 IWL_ERR(trans, "Could not load the %s uCode section\n", 998 IWL_ERR(trans, "Could not load the [%d] uCode section\n",
997 name); 999 section_num);
998 return -ETIMEDOUT; 1000 return -ETIMEDOUT;
999 } 1001 }
1000 1002
@@ -1005,16 +1007,16 @@ static int iwl_load_given_ucode(struct iwl_trans *trans,
1005 const struct fw_img *image) 1007 const struct fw_img *image)
1006{ 1008{
1007 int ret = 0; 1009 int ret = 0;
1010 int i;
1008 1011
1009 ret = iwl_load_section(trans, "INST", &image->code, 1012 for (i = 0; i < IWL_UCODE_SECTION_MAX; i++) {
1010 IWLAGN_RTC_INST_LOWER_BOUND); 1013 if (!image->sec[i].p_addr)
1011 if (ret) 1014 break;
1012 return ret;
1013 1015
1014 ret = iwl_load_section(trans, "DATA", &image->data, 1016 ret = iwl_load_section(trans, i, &image->sec[i]);
1015 IWLAGN_RTC_DATA_LOWER_BOUND); 1017 if (ret)
1016 if (ret) 1018 return ret;
1017 return ret; 1019 }
1018 1020
1019 /* Remove all resets to allow NIC to operate */ 1021 /* Remove all resets to allow NIC to operate */
1020 iwl_write32(trans, CSR_RESET, 0); 1022 iwl_write32(trans, CSR_RESET, 0);
diff --git a/drivers/net/wireless/iwlwifi/iwl-ucode.c b/drivers/net/wireless/iwlwifi/iwl-ucode.c
index 0908880dd7ac..252828728837 100644
--- a/drivers/net/wireless/iwlwifi/iwl-ucode.c
+++ b/drivers/net/wireless/iwlwifi/iwl-ucode.c
@@ -80,17 +80,10 @@ static struct iwl_wimax_coex_event_entry cu_priorities[COEX_NUM_OF_EVENTS] = {
80static inline const struct fw_img * 80static inline const struct fw_img *
81iwl_get_ucode_image(struct iwl_priv *priv, enum iwl_ucode_type ucode_type) 81iwl_get_ucode_image(struct iwl_priv *priv, enum iwl_ucode_type ucode_type)
82{ 82{
83 switch (ucode_type) { 83 if (ucode_type >= IWL_UCODE_TYPE_MAX)
84 case IWL_UCODE_INIT: 84 return NULL;
85 return &priv->fw->ucode_init; 85
86 case IWL_UCODE_WOWLAN: 86 return &priv->fw->img[ucode_type];
87 return &priv->fw->ucode_wowlan;
88 case IWL_UCODE_REGULAR:
89 return &priv->fw->ucode_rt;
90 default:
91 break;
92 }
93 return NULL;
94} 87}
95 88
96/* 89/*
@@ -342,7 +335,7 @@ static int iwl_alive_notify(struct iwl_priv *priv)
342 * using sample data 100 bytes apart. If these sample points are good, 335 * using sample data 100 bytes apart. If these sample points are good,
343 * it's a pretty good bet that everything between them is good, too. 336 * it's a pretty good bet that everything between them is good, too.
344 */ 337 */
345static int iwl_verify_inst_sparse(struct iwl_priv *priv, 338static int iwl_verify_sec_sparse(struct iwl_priv *priv,
346 const struct fw_desc *fw_desc) 339 const struct fw_desc *fw_desc)
347{ 340{
348 __le32 *image = (__le32 *)fw_desc->v_addr; 341 __le32 *image = (__le32 *)fw_desc->v_addr;
@@ -357,7 +350,7 @@ static int iwl_verify_inst_sparse(struct iwl_priv *priv,
357 /* NOTE: Use the debugless read so we don't flood kernel log 350 /* NOTE: Use the debugless read so we don't flood kernel log
358 * if IWL_DL_IO is set */ 351 * if IWL_DL_IO is set */
359 iwl_write_direct32(trans(priv), HBUS_TARG_MEM_RADDR, 352 iwl_write_direct32(trans(priv), HBUS_TARG_MEM_RADDR,
360 i + IWLAGN_RTC_INST_LOWER_BOUND); 353 i + fw_desc->offset);
361 val = iwl_read32(trans(priv), HBUS_TARG_MEM_RDAT); 354 val = iwl_read32(trans(priv), HBUS_TARG_MEM_RDAT);
362 if (val != le32_to_cpu(*image)) 355 if (val != le32_to_cpu(*image))
363 return -EIO; 356 return -EIO;
@@ -366,7 +359,7 @@ static int iwl_verify_inst_sparse(struct iwl_priv *priv,
366 return 0; 359 return 0;
367} 360}
368 361
369static void iwl_print_mismatch_inst(struct iwl_priv *priv, 362static void iwl_print_mismatch_sec(struct iwl_priv *priv,
370 const struct fw_desc *fw_desc) 363 const struct fw_desc *fw_desc)
371{ 364{
372 __le32 *image = (__le32 *)fw_desc->v_addr; 365 __le32 *image = (__le32 *)fw_desc->v_addr;
@@ -378,7 +371,7 @@ static void iwl_print_mismatch_inst(struct iwl_priv *priv,
378 IWL_DEBUG_FW(priv, "ucode inst image size is %u\n", len); 371 IWL_DEBUG_FW(priv, "ucode inst image size is %u\n", len);
379 372
380 iwl_write_direct32(trans(priv), HBUS_TARG_MEM_RADDR, 373 iwl_write_direct32(trans(priv), HBUS_TARG_MEM_RADDR,
381 IWLAGN_RTC_INST_LOWER_BOUND); 374 fw_desc->offset);
382 375
383 for (offs = 0; 376 for (offs = 0;
384 offs < len && errors < 20; 377 offs < len && errors < 20;
@@ -408,14 +401,14 @@ static int iwl_verify_ucode(struct iwl_priv *priv,
408 return -EINVAL; 401 return -EINVAL;
409 } 402 }
410 403
411 if (!iwl_verify_inst_sparse(priv, &img->code)) { 404 if (!iwl_verify_sec_sparse(priv, &img->sec[IWL_UCODE_SECTION_INST])) {
412 IWL_DEBUG_FW(priv, "uCode is good in inst SRAM\n"); 405 IWL_DEBUG_FW(priv, "uCode is good in inst SRAM\n");
413 return 0; 406 return 0;
414 } 407 }
415 408
416 IWL_ERR(priv, "UCODE IMAGE IN INSTRUCTION SRAM NOT VALID!!\n"); 409 IWL_ERR(priv, "UCODE IMAGE IN INSTRUCTION SRAM NOT VALID!!\n");
417 410
418 iwl_print_mismatch_inst(priv, &img->code); 411 iwl_print_mismatch_sec(priv, &img->sec[IWL_UCODE_SECTION_INST]);
419 return -EIO; 412 return -EIO;
420} 413}
421 414
@@ -534,7 +527,7 @@ int iwl_run_init_ucode(struct iwl_priv *priv)
534 lockdep_assert_held(&priv->mutex); 527 lockdep_assert_held(&priv->mutex);
535 528
536 /* No init ucode required? Curious, but maybe ok */ 529 /* No init ucode required? Curious, but maybe ok */
537 if (!priv->fw->ucode_init.code.len) 530 if (!priv->fw->img[IWL_UCODE_INIT].sec[0].len)
538 return 0; 531 return 0;
539 532
540 if (priv->init_ucode_run) 533 if (priv->init_ucode_run)