diff options
author | David Spinadel <david.spinadel@intel.com> | 2012-03-10 16:00:14 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2012-03-12 14:22:09 -0400 |
commit | 6dfa8d019cd21d08634ceb65a3fb90d0648bd93b (patch) | |
tree | 04cb6b0be027598b782d8c91ab5ae681d3304d83 /drivers/net | |
parent | ed8c8365c4431eeb733def3dd314cf303e1b12ea (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')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-debugfs.c | 17 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-drv.c | 141 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-fw.h | 25 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-mac80211.c | 15 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-testmode.c | 21 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-trans-pcie.c | 32 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-ucode.c | 29 |
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 | } |
357 | static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf, | 350 | static 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 | ||
119 | static void iwl_free_fw_img(struct iwl_drv *drv, struct fw_img *img) | 119 | static 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 | ||
125 | static void iwl_dealloc_ucode(struct iwl_drv *drv) | 126 | static 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 | ||
132 | static int iwl_alloc_fw_desc(struct iwl_drv *drv, struct fw_desc *desc, | 133 | static 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 | */ | ||
196 | enum 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 | |||
206 | struct fw_img_parsing { | 193 | struct 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 | ||
681 | static 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 | |||
695 | static 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 | */ | ||
108 | enum 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 | |||
104 | struct iwl_ucode_capabilities { | 118 | struct 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 | ||
118 | struct fw_img { | 132 | struct 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 | */ |
954 | static int iwl_load_section(struct iwl_trans *trans, const char *name, | 954 | static 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] = { | |||
80 | static inline const struct fw_img * | 80 | static inline const struct fw_img * |
81 | iwl_get_ucode_image(struct iwl_priv *priv, enum iwl_ucode_type ucode_type) | 81 | iwl_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 | */ |
345 | static int iwl_verify_inst_sparse(struct iwl_priv *priv, | 338 | static 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 | ||
369 | static void iwl_print_mismatch_inst(struct iwl_priv *priv, | 362 | static 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) |