diff options
Diffstat (limited to 'drivers/net/wireless/intel/iwlwifi/fw/paging.c')
-rw-r--r-- | drivers/net/wireless/intel/iwlwifi/fw/paging.c | 103 |
1 files changed, 12 insertions, 91 deletions
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/paging.c b/drivers/net/wireless/intel/iwlwifi/fw/paging.c index 1610722b8099..1fec8e3a6b35 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/paging.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/paging.c | |||
@@ -87,9 +87,6 @@ void iwl_free_fw_paging(struct iwl_fw_runtime *fwrt) | |||
87 | get_order(paging->fw_paging_size)); | 87 | get_order(paging->fw_paging_size)); |
88 | paging->fw_paging_block = NULL; | 88 | paging->fw_paging_block = NULL; |
89 | } | 89 | } |
90 | kfree(fwrt->trans->paging_download_buf); | ||
91 | fwrt->trans->paging_download_buf = NULL; | ||
92 | fwrt->trans->paging_db = NULL; | ||
93 | 90 | ||
94 | memset(fwrt->fw_paging_db, 0, sizeof(fwrt->fw_paging_db)); | 91 | memset(fwrt->fw_paging_db, 0, sizeof(fwrt->fw_paging_db)); |
95 | } | 92 | } |
@@ -100,13 +97,11 @@ static int iwl_alloc_fw_paging_mem(struct iwl_fw_runtime *fwrt, | |||
100 | { | 97 | { |
101 | struct page *block; | 98 | struct page *block; |
102 | dma_addr_t phys = 0; | 99 | dma_addr_t phys = 0; |
103 | int blk_idx, order, num_of_pages, size, dma_enabled; | 100 | int blk_idx, order, num_of_pages, size; |
104 | 101 | ||
105 | if (fwrt->fw_paging_db[0].fw_paging_block) | 102 | if (fwrt->fw_paging_db[0].fw_paging_block) |
106 | return 0; | 103 | return 0; |
107 | 104 | ||
108 | dma_enabled = is_device_dma_capable(fwrt->trans->dev); | ||
109 | |||
110 | /* ensure BLOCK_2_EXP_SIZE is power of 2 of PAGING_BLOCK_SIZE */ | 105 | /* ensure BLOCK_2_EXP_SIZE is power of 2 of PAGING_BLOCK_SIZE */ |
111 | BUILD_BUG_ON(BIT(BLOCK_2_EXP_SIZE) != PAGING_BLOCK_SIZE); | 106 | BUILD_BUG_ON(BIT(BLOCK_2_EXP_SIZE) != PAGING_BLOCK_SIZE); |
112 | 107 | ||
@@ -139,24 +134,18 @@ static int iwl_alloc_fw_paging_mem(struct iwl_fw_runtime *fwrt, | |||
139 | fwrt->fw_paging_db[blk_idx].fw_paging_block = block; | 134 | fwrt->fw_paging_db[blk_idx].fw_paging_block = block; |
140 | fwrt->fw_paging_db[blk_idx].fw_paging_size = size; | 135 | fwrt->fw_paging_db[blk_idx].fw_paging_size = size; |
141 | 136 | ||
142 | if (dma_enabled) { | 137 | phys = dma_map_page(fwrt->trans->dev, block, 0, |
143 | phys = dma_map_page(fwrt->trans->dev, block, 0, | 138 | PAGE_SIZE << order, |
144 | PAGE_SIZE << order, | 139 | DMA_BIDIRECTIONAL); |
145 | DMA_BIDIRECTIONAL); | 140 | if (dma_mapping_error(fwrt->trans->dev, phys)) { |
146 | if (dma_mapping_error(fwrt->trans->dev, phys)) { | 141 | /* |
147 | /* | 142 | * free the previous pages and the current one |
148 | * free the previous pages and the current one | 143 | * since we failed to map_page. |
149 | * since we failed to map_page. | 144 | */ |
150 | */ | 145 | iwl_free_fw_paging(fwrt); |
151 | iwl_free_fw_paging(fwrt); | 146 | return -ENOMEM; |
152 | return -ENOMEM; | ||
153 | } | ||
154 | fwrt->fw_paging_db[blk_idx].fw_paging_phys = phys; | ||
155 | } else { | ||
156 | fwrt->fw_paging_db[blk_idx].fw_paging_phys = | ||
157 | PAGING_ADDR_SIG | | ||
158 | blk_idx << BLOCK_2_EXP_SIZE; | ||
159 | } | 147 | } |
148 | fwrt->fw_paging_db[blk_idx].fw_paging_phys = phys; | ||
160 | 149 | ||
161 | if (!blk_idx) | 150 | if (!blk_idx) |
162 | IWL_DEBUG_FW(fwrt, | 151 | IWL_DEBUG_FW(fwrt, |
@@ -312,60 +301,6 @@ static int iwl_send_paging_cmd(struct iwl_fw_runtime *fwrt, | |||
312 | return iwl_trans_send_cmd(fwrt->trans, &hcmd); | 301 | return iwl_trans_send_cmd(fwrt->trans, &hcmd); |
313 | } | 302 | } |
314 | 303 | ||
315 | /* | ||
316 | * Send paging item cmd to FW in case CPU2 has paging image | ||
317 | */ | ||
318 | static int iwl_trans_get_paging_item(struct iwl_fw_runtime *fwrt) | ||
319 | { | ||
320 | int ret; | ||
321 | struct iwl_fw_get_item_cmd fw_get_item_cmd = { | ||
322 | .item_id = cpu_to_le32(IWL_FW_ITEM_ID_PAGING), | ||
323 | }; | ||
324 | struct iwl_fw_get_item_resp *item_resp; | ||
325 | struct iwl_host_cmd cmd = { | ||
326 | .id = iwl_cmd_id(FW_GET_ITEM_CMD, IWL_ALWAYS_LONG_GROUP, 0), | ||
327 | .flags = CMD_WANT_SKB | CMD_SEND_IN_RFKILL, | ||
328 | .data = { &fw_get_item_cmd, }, | ||
329 | .len = { sizeof(fw_get_item_cmd), }, | ||
330 | }; | ||
331 | |||
332 | ret = iwl_trans_send_cmd(fwrt->trans, &cmd); | ||
333 | if (ret) { | ||
334 | IWL_ERR(fwrt, | ||
335 | "Paging: Failed to send FW_GET_ITEM_CMD cmd (err = %d)\n", | ||
336 | ret); | ||
337 | return ret; | ||
338 | } | ||
339 | |||
340 | item_resp = (void *)((struct iwl_rx_packet *)cmd.resp_pkt)->data; | ||
341 | if (item_resp->item_id != cpu_to_le32(IWL_FW_ITEM_ID_PAGING)) { | ||
342 | IWL_ERR(fwrt, | ||
343 | "Paging: got wrong item in FW_GET_ITEM_CMD resp (item_id = %u)\n", | ||
344 | le32_to_cpu(item_resp->item_id)); | ||
345 | ret = -EIO; | ||
346 | goto exit; | ||
347 | } | ||
348 | |||
349 | /* Add an extra page for headers */ | ||
350 | fwrt->trans->paging_download_buf = kzalloc(PAGING_BLOCK_SIZE + | ||
351 | FW_PAGING_SIZE, | ||
352 | GFP_KERNEL); | ||
353 | if (!fwrt->trans->paging_download_buf) { | ||
354 | ret = -ENOMEM; | ||
355 | goto exit; | ||
356 | } | ||
357 | fwrt->trans->paging_req_addr = le32_to_cpu(item_resp->item_val); | ||
358 | fwrt->trans->paging_db = fwrt->fw_paging_db; | ||
359 | IWL_DEBUG_FW(fwrt, | ||
360 | "Paging: got paging request address (paging_req_addr 0x%08x)\n", | ||
361 | fwrt->trans->paging_req_addr); | ||
362 | |||
363 | exit: | ||
364 | iwl_free_resp(&cmd); | ||
365 | |||
366 | return ret; | ||
367 | } | ||
368 | |||
369 | int iwl_init_paging(struct iwl_fw_runtime *fwrt, enum iwl_ucode_type type) | 304 | int iwl_init_paging(struct iwl_fw_runtime *fwrt, enum iwl_ucode_type type) |
370 | { | 305 | { |
371 | const struct fw_img *fw = &fwrt->fw->img[type]; | 306 | const struct fw_img *fw = &fwrt->fw->img[type]; |
@@ -382,20 +317,6 @@ int iwl_init_paging(struct iwl_fw_runtime *fwrt, enum iwl_ucode_type type) | |||
382 | if (!fw->paging_mem_size) | 317 | if (!fw->paging_mem_size) |
383 | return 0; | 318 | return 0; |
384 | 319 | ||
385 | /* | ||
386 | * When dma is not enabled, the driver needs to copy / write | ||
387 | * the downloaded / uploaded page to / from the smem. | ||
388 | * This gets the location of the place were the pages are | ||
389 | * stored. | ||
390 | */ | ||
391 | if (!is_device_dma_capable(fwrt->trans->dev)) { | ||
392 | ret = iwl_trans_get_paging_item(fwrt); | ||
393 | if (ret) { | ||
394 | IWL_ERR(fwrt, "failed to get FW paging item\n"); | ||
395 | return ret; | ||
396 | } | ||
397 | } | ||
398 | |||
399 | ret = iwl_save_fw_paging(fwrt, fw); | 320 | ret = iwl_save_fw_paging(fwrt, fw); |
400 | if (ret) { | 321 | if (ret) { |
401 | IWL_ERR(fwrt, "failed to save the FW paging image\n"); | 322 | IWL_ERR(fwrt, "failed to save the FW paging image\n"); |