diff options
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/fw-api.h | 37 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/fw.c | 10 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/mvm.h | 5 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/nvm.c | 136 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/ops.c | 12 |
5 files changed, 38 insertions, 162 deletions
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api.h b/drivers/net/wireless/iwlwifi/mvm/fw-api.h index f8d7e88234e4..0e94d8b91956 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api.h | |||
@@ -278,38 +278,7 @@ enum { | |||
278 | NVM_ACCESS_TARGET_EEPROM = 2, | 278 | NVM_ACCESS_TARGET_EEPROM = 2, |
279 | }; | 279 | }; |
280 | 280 | ||
281 | /** | 281 | /* Section types for NVM_ACCESS_CMD */ |
282 | * struct iwl_nvm_access_cmd_ver1 - Request the device to send the NVM. | ||
283 | * @op_code: 0 - read, 1 - write. | ||
284 | * @target: NVM_ACCESS_TARGET_*. should be 0 for read. | ||
285 | * @cache_refresh: 0 - None, 1- NVM. | ||
286 | * @offset: offset in the nvm data. | ||
287 | * @length: of the chunk. | ||
288 | * @data: empty on read, the NVM chunk on write | ||
289 | */ | ||
290 | struct iwl_nvm_access_cmd_ver1 { | ||
291 | u8 op_code; | ||
292 | u8 target; | ||
293 | u8 cache_refresh; | ||
294 | u8 reserved; | ||
295 | __le16 offset; | ||
296 | __le16 length; | ||
297 | u8 data[]; | ||
298 | } __packed; /* NVM_ACCESS_CMD_API_S_VER_1 */ | ||
299 | |||
300 | /** | ||
301 | * struct iwl_nvm_access_resp_ver1 - response to NVM_ACCESS_CMD | ||
302 | * @offset: the offset in the nvm data | ||
303 | * @length: of the chunk | ||
304 | * @data: the nvm chunk on when NVM_ACCESS_CMD was read, nothing on write | ||
305 | */ | ||
306 | struct iwl_nvm_access_resp_ver1 { | ||
307 | __le16 offset; | ||
308 | __le16 length; | ||
309 | u8 data[]; | ||
310 | } __packed; /* NVM_ACCESS_CMD_RESP_API_S_VER_1 */ | ||
311 | |||
312 | /* Section types for NVM_ACCESS_CMD version 2 */ | ||
313 | enum { | 282 | enum { |
314 | NVM_SECTION_TYPE_HW = 0, | 283 | NVM_SECTION_TYPE_HW = 0, |
315 | NVM_SECTION_TYPE_SW, | 284 | NVM_SECTION_TYPE_SW, |
@@ -330,7 +299,7 @@ enum { | |||
330 | * @length: in bytes, to read/write | 299 | * @length: in bytes, to read/write |
331 | * @data: if write operation, the data to write. On read its empty | 300 | * @data: if write operation, the data to write. On read its empty |
332 | */ | 301 | */ |
333 | struct iwl_nvm_access_cmd_ver2 { | 302 | struct iwl_nvm_access_cmd { |
334 | u8 op_code; | 303 | u8 op_code; |
335 | u8 target; | 304 | u8 target; |
336 | __le16 type; | 305 | __le16 type; |
@@ -347,7 +316,7 @@ struct iwl_nvm_access_cmd_ver2 { | |||
347 | * @status: 0 for success, fail otherwise | 316 | * @status: 0 for success, fail otherwise |
348 | * @data: if read operation, the data returned. Empty on write. | 317 | * @data: if read operation, the data returned. Empty on write. |
349 | */ | 318 | */ |
350 | struct iwl_nvm_access_resp_ver2 { | 319 | struct iwl_nvm_access_resp { |
351 | __le16 offset; | 320 | __le16 offset; |
352 | __le16 length; | 321 | __le16 length; |
353 | __le16 type; | 322 | __le16 type; |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw.c b/drivers/net/wireless/iwlwifi/mvm/fw.c index 1006b3204e7b..d43e2a57d354 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/iwlwifi/mvm/fw.c | |||
@@ -330,12 +330,10 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm) | |||
330 | if (ret) | 330 | if (ret) |
331 | goto error; | 331 | goto error; |
332 | 332 | ||
333 | /* WkP doesn't have all calibrations, need to set default values */ | 333 | /* need to set default values */ |
334 | if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_7000) { | 334 | ret = iwl_set_default_calibrations(mvm); |
335 | ret = iwl_set_default_calibrations(mvm); | 335 | if (ret) |
336 | if (ret) | 336 | goto error; |
337 | goto error; | ||
338 | } | ||
339 | 337 | ||
340 | /* | 338 | /* |
341 | * Send phy configurations command to init uCode | 339 | * Send phy configurations command to init uCode |
diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h index 203eb85e03d3..d022e44e83a1 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h | |||
@@ -281,10 +281,7 @@ struct iwl_mvm { | |||
281 | atomic_t queue_stop_count[IWL_MAX_HW_QUEUES]; | 281 | atomic_t queue_stop_count[IWL_MAX_HW_QUEUES]; |
282 | 282 | ||
283 | struct iwl_nvm_data *nvm_data; | 283 | struct iwl_nvm_data *nvm_data; |
284 | /* eeprom blob for debugfs/testmode */ | 284 | /* NVM sections */ |
285 | u8 *eeprom_blob; | ||
286 | size_t eeprom_blob_size; | ||
287 | /* NVM sections for 7000 family */ | ||
288 | struct iwl_nvm_section nvm_sections[NVM_NUM_OF_SECTIONS]; | 285 | struct iwl_nvm_section nvm_sections[NVM_NUM_OF_SECTIONS]; |
289 | 286 | ||
290 | /* EEPROM MAC addresses */ | 287 | /* EEPROM MAC addresses */ |
diff --git a/drivers/net/wireless/iwlwifi/mvm/nvm.c b/drivers/net/wireless/iwlwifi/mvm/nvm.c index 93e3d0f174cc..b8ec02f89acc 100644 --- a/drivers/net/wireless/iwlwifi/mvm/nvm.c +++ b/drivers/net/wireless/iwlwifi/mvm/nvm.c | |||
@@ -77,26 +77,8 @@ static const int nvm_to_read[] = { | |||
77 | /* Default NVM size to read */ | 77 | /* Default NVM size to read */ |
78 | #define IWL_NVM_DEFAULT_CHUNK_SIZE (2*1024); | 78 | #define IWL_NVM_DEFAULT_CHUNK_SIZE (2*1024); |
79 | 79 | ||
80 | /* used to simplify the shared operations on NCM_ACCESS_CMD versions */ | 80 | static inline void iwl_nvm_fill_read(struct iwl_nvm_access_cmd *cmd, |
81 | union iwl_nvm_access_cmd { | 81 | u16 offset, u16 length, u16 section) |
82 | struct iwl_nvm_access_cmd_ver1 ver1; | ||
83 | struct iwl_nvm_access_cmd_ver2 ver2; | ||
84 | }; | ||
85 | union iwl_nvm_access_resp { | ||
86 | struct iwl_nvm_access_resp_ver1 ver1; | ||
87 | struct iwl_nvm_access_resp_ver2 ver2; | ||
88 | }; | ||
89 | |||
90 | static inline void iwl_nvm_fill_read_ver1(struct iwl_nvm_access_cmd_ver1 *cmd, | ||
91 | u16 offset, u16 length) | ||
92 | { | ||
93 | cmd->offset = cpu_to_le16(offset); | ||
94 | cmd->length = cpu_to_le16(length); | ||
95 | cmd->cache_refresh = 1; | ||
96 | } | ||
97 | |||
98 | static inline void iwl_nvm_fill_read_ver2(struct iwl_nvm_access_cmd_ver2 *cmd, | ||
99 | u16 offset, u16 length, u16 section) | ||
100 | { | 82 | { |
101 | cmd->offset = cpu_to_le16(offset); | 83 | cmd->offset = cpu_to_le16(offset); |
102 | cmd->length = cpu_to_le16(length); | 84 | cmd->length = cpu_to_le16(length); |
@@ -106,8 +88,8 @@ static inline void iwl_nvm_fill_read_ver2(struct iwl_nvm_access_cmd_ver2 *cmd, | |||
106 | static int iwl_nvm_read_chunk(struct iwl_mvm *mvm, u16 section, | 88 | static int iwl_nvm_read_chunk(struct iwl_mvm *mvm, u16 section, |
107 | u16 offset, u16 length, u8 *data) | 89 | u16 offset, u16 length, u8 *data) |
108 | { | 90 | { |
109 | union iwl_nvm_access_cmd nvm_access_cmd; | 91 | struct iwl_nvm_access_cmd nvm_access_cmd = {}; |
110 | union iwl_nvm_access_resp *nvm_resp; | 92 | struct iwl_nvm_access_resp *nvm_resp; |
111 | struct iwl_rx_packet *pkt; | 93 | struct iwl_rx_packet *pkt; |
112 | struct iwl_host_cmd cmd = { | 94 | struct iwl_host_cmd cmd = { |
113 | .id = NVM_ACCESS_CMD, | 95 | .id = NVM_ACCESS_CMD, |
@@ -117,18 +99,8 @@ static int iwl_nvm_read_chunk(struct iwl_mvm *mvm, u16 section, | |||
117 | int ret, bytes_read, offset_read; | 99 | int ret, bytes_read, offset_read; |
118 | u8 *resp_data; | 100 | u8 *resp_data; |
119 | 101 | ||
120 | memset(&nvm_access_cmd, 0, sizeof(nvm_access_cmd)); | 102 | iwl_nvm_fill_read(&nvm_access_cmd, offset, length, section); |
121 | 103 | cmd.len[0] = sizeof(struct iwl_nvm_access_cmd); | |
122 | /* TODO: not sure family should be the decider, maybe FW version? */ | ||
123 | if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_7000) { | ||
124 | iwl_nvm_fill_read_ver2(&(nvm_access_cmd.ver2), | ||
125 | offset, length, section); | ||
126 | cmd.len[0] = sizeof(struct iwl_nvm_access_cmd_ver2); | ||
127 | } else { | ||
128 | iwl_nvm_fill_read_ver1(&(nvm_access_cmd.ver1), | ||
129 | offset, length); | ||
130 | cmd.len[0] = sizeof(struct iwl_nvm_access_cmd_ver1); | ||
131 | } | ||
132 | 104 | ||
133 | ret = iwl_mvm_send_cmd(mvm, &cmd); | 105 | ret = iwl_mvm_send_cmd(mvm, &cmd); |
134 | if (ret) | 106 | if (ret) |
@@ -144,17 +116,10 @@ static int iwl_nvm_read_chunk(struct iwl_mvm *mvm, u16 section, | |||
144 | 116 | ||
145 | /* Extract NVM response */ | 117 | /* Extract NVM response */ |
146 | nvm_resp = (void *)pkt->data; | 118 | nvm_resp = (void *)pkt->data; |
147 | if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_7000) { | 119 | ret = le16_to_cpu(nvm_resp->status); |
148 | ret = le16_to_cpu(nvm_resp->ver2.status); | 120 | bytes_read = le16_to_cpu(nvm_resp->length); |
149 | bytes_read = le16_to_cpu(nvm_resp->ver2.length); | 121 | offset_read = le16_to_cpu(nvm_resp->offset); |
150 | offset_read = le16_to_cpu(nvm_resp->ver2.offset); | 122 | resp_data = nvm_resp->data; |
151 | resp_data = nvm_resp->ver2.data; | ||
152 | } else { | ||
153 | ret = le16_to_cpu(nvm_resp->ver1.length) <= 0; | ||
154 | bytes_read = le16_to_cpu(nvm_resp->ver1.length); | ||
155 | offset_read = le16_to_cpu(nvm_resp->ver1.offset); | ||
156 | resp_data = nvm_resp->ver1.data; | ||
157 | } | ||
158 | if (ret) { | 123 | if (ret) { |
159 | IWL_ERR(mvm, | 124 | IWL_ERR(mvm, |
160 | "NVM access command failed with status %d (device: %s)\n", | 125 | "NVM access command failed with status %d (device: %s)\n", |
@@ -194,17 +159,10 @@ static int iwl_nvm_read_section(struct iwl_mvm *mvm, u16 section, | |||
194 | { | 159 | { |
195 | u16 length, offset = 0; | 160 | u16 length, offset = 0; |
196 | int ret; | 161 | int ret; |
197 | bool old_eeprom = mvm->cfg->device_family != IWL_DEVICE_FAMILY_7000; | ||
198 | 162 | ||
199 | /* Set nvm section read length */ | 163 | /* Set nvm section read length */ |
200 | length = IWL_NVM_DEFAULT_CHUNK_SIZE; | 164 | length = IWL_NVM_DEFAULT_CHUNK_SIZE; |
201 | 165 | ||
202 | /* | ||
203 | * if length is greater than EEPROM size, truncate it because uCode | ||
204 | * doesn't check it by itself, and exit the loop when reached. | ||
205 | */ | ||
206 | if (old_eeprom && length > mvm->cfg->base_params->eeprom_size) | ||
207 | length = mvm->cfg->base_params->eeprom_size; | ||
208 | ret = length; | 166 | ret = length; |
209 | 167 | ||
210 | /* Read the NVM until exhausted (reading less than requested) */ | 168 | /* Read the NVM until exhausted (reading less than requested) */ |
@@ -217,8 +175,6 @@ static int iwl_nvm_read_section(struct iwl_mvm *mvm, u16 section, | |||
217 | return ret; | 175 | return ret; |
218 | } | 176 | } |
219 | offset += ret; | 177 | offset += ret; |
220 | if (old_eeprom && offset == mvm->cfg->base_params->eeprom_size) | ||
221 | break; | ||
222 | } | 178 | } |
223 | 179 | ||
224 | IWL_INFO(mvm, "NVM section %d read completed\n", section); | 180 | IWL_INFO(mvm, "NVM section %d read completed\n", section); |
@@ -252,63 +208,31 @@ int iwl_nvm_init(struct iwl_mvm *mvm) | |||
252 | int ret, i, section; | 208 | int ret, i, section; |
253 | u8 *nvm_buffer, *temp; | 209 | u8 *nvm_buffer, *temp; |
254 | 210 | ||
255 | if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_7000) { | 211 | /* TODO: find correct NVM max size for a section */ |
256 | /* TODO: find correct NVM max size for a section */ | 212 | nvm_buffer = kmalloc(mvm->cfg->base_params->eeprom_size, |
257 | nvm_buffer = kmalloc(mvm->cfg->base_params->eeprom_size, | 213 | GFP_KERNEL); |
258 | GFP_KERNEL); | 214 | if (!nvm_buffer) |
259 | if (!nvm_buffer) | 215 | return -ENOMEM; |
260 | return -ENOMEM; | 216 | for (i = 0; i < ARRAY_SIZE(nvm_to_read); i++) { |
261 | for (i = 0; i < ARRAY_SIZE(nvm_to_read); i++) { | 217 | section = nvm_to_read[i]; |
262 | section = nvm_to_read[i]; | 218 | /* we override the constness for initial read */ |
263 | /* we override the constness for initial read */ | 219 | ret = iwl_nvm_read_section(mvm, section, nvm_buffer); |
264 | ret = iwl_nvm_read_section(mvm, section, nvm_buffer); | ||
265 | if (ret < 0) | ||
266 | break; | ||
267 | temp = kmemdup(nvm_buffer, ret, GFP_KERNEL); | ||
268 | if (!temp) { | ||
269 | ret = -ENOMEM; | ||
270 | break; | ||
271 | } | ||
272 | mvm->nvm_sections[section].data = temp; | ||
273 | mvm->nvm_sections[section].length = ret; | ||
274 | } | ||
275 | kfree(nvm_buffer); | ||
276 | if (ret < 0) | 220 | if (ret < 0) |
277 | return ret; | 221 | break; |
278 | } else { | 222 | temp = kmemdup(nvm_buffer, ret, GFP_KERNEL); |
279 | /* allocate eeprom */ | 223 | if (!temp) { |
280 | mvm->eeprom_blob_size = mvm->cfg->base_params->eeprom_size; | 224 | ret = -ENOMEM; |
281 | IWL_DEBUG_EEPROM(mvm->trans->dev, "NVM size = %zd\n", | 225 | break; |
282 | mvm->eeprom_blob_size); | ||
283 | mvm->eeprom_blob = kzalloc(mvm->eeprom_blob_size, GFP_KERNEL); | ||
284 | if (!mvm->eeprom_blob) | ||
285 | return -ENOMEM; | ||
286 | |||
287 | ret = iwl_nvm_read_section(mvm, 0, mvm->eeprom_blob); | ||
288 | if (ret != mvm->eeprom_blob_size) { | ||
289 | IWL_ERR(mvm, "Read partial NVM %d/%zd\n", | ||
290 | ret, mvm->eeprom_blob_size); | ||
291 | kfree(mvm->eeprom_blob); | ||
292 | mvm->eeprom_blob = NULL; | ||
293 | return -EINVAL; | ||
294 | } | 226 | } |
227 | mvm->nvm_sections[section].data = temp; | ||
228 | mvm->nvm_sections[section].length = ret; | ||
295 | } | 229 | } |
230 | kfree(nvm_buffer); | ||
231 | if (ret < 0) | ||
232 | return ret; | ||
296 | 233 | ||
297 | ret = 0; | 234 | ret = 0; |
298 | if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_7000) | 235 | mvm->nvm_data = iwl_parse_nvm_sections(mvm); |
299 | mvm->nvm_data = iwl_parse_nvm_sections(mvm); | ||
300 | else | ||
301 | mvm->nvm_data = | ||
302 | iwl_parse_eeprom_data(mvm->trans->dev, | ||
303 | mvm->cfg, | ||
304 | mvm->eeprom_blob, | ||
305 | mvm->eeprom_blob_size); | ||
306 | |||
307 | if (!mvm->nvm_data) { | ||
308 | kfree(mvm->eeprom_blob); | ||
309 | mvm->eeprom_blob = NULL; | ||
310 | ret = -ENOMEM; | ||
311 | } | ||
312 | 236 | ||
313 | return ret; | 237 | return ret; |
314 | } | 238 | } |
diff --git a/drivers/net/wireless/iwlwifi/mvm/ops.c b/drivers/net/wireless/iwlwifi/mvm/ops.c index 828bdddd07e9..b490426294cc 100644 --- a/drivers/net/wireless/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/iwlwifi/mvm/ops.c | |||
@@ -319,16 +319,6 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, | |||
319 | }; | 319 | }; |
320 | int err, scan_size; | 320 | int err, scan_size; |
321 | 321 | ||
322 | switch (cfg->device_family) { | ||
323 | case IWL_DEVICE_FAMILY_6030: | ||
324 | case IWL_DEVICE_FAMILY_6005: | ||
325 | case IWL_DEVICE_FAMILY_7000: | ||
326 | break; | ||
327 | default: | ||
328 | IWL_ERR(trans, "Trying to load mvm on an unsupported device\n"); | ||
329 | return NULL; | ||
330 | } | ||
331 | |||
332 | /******************************** | 322 | /******************************** |
333 | * 1. Allocating and configuring HW data | 323 | * 1. Allocating and configuring HW data |
334 | ********************************/ | 324 | ********************************/ |
@@ -444,7 +434,6 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, | |||
444 | out_free: | 434 | out_free: |
445 | iwl_phy_db_free(mvm->phy_db); | 435 | iwl_phy_db_free(mvm->phy_db); |
446 | kfree(mvm->scan_cmd); | 436 | kfree(mvm->scan_cmd); |
447 | kfree(mvm->eeprom_blob); | ||
448 | iwl_trans_stop_hw(trans, true); | 437 | iwl_trans_stop_hw(trans, true); |
449 | ieee80211_free_hw(mvm->hw); | 438 | ieee80211_free_hw(mvm->hw); |
450 | return NULL; | 439 | return NULL; |
@@ -466,7 +455,6 @@ static void iwl_op_mode_mvm_stop(struct iwl_op_mode *op_mode) | |||
466 | iwl_phy_db_free(mvm->phy_db); | 455 | iwl_phy_db_free(mvm->phy_db); |
467 | mvm->phy_db = NULL; | 456 | mvm->phy_db = NULL; |
468 | 457 | ||
469 | kfree(mvm->eeprom_blob); | ||
470 | iwl_free_nvm_data(mvm->nvm_data); | 458 | iwl_free_nvm_data(mvm->nvm_data); |
471 | for (i = 0; i < NVM_NUM_OF_SECTIONS; i++) | 459 | for (i = 0; i < NVM_NUM_OF_SECTIONS; i++) |
472 | kfree(mvm->nvm_sections[i].data); | 460 | kfree(mvm->nvm_sections[i].data); |