aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSara Sharon <sara.sharon@intel.com>2016-11-30 09:49:11 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-05-14 08:00:17 -0400
commit1fb264cf7d54d8ac69adb72aec26933c1a7b8895 (patch)
tree541dcf2f33cd7168cb8cdf152b867a3902d714bc
parent495f91630205b441ead5461580703575c18324ec (diff)
iwlwifi: mvm: synchronize firmware DMA paging memory
commit 4b70f07686d75d1eb5d956812cc810944e0b29b2 upstream. When driver needs to access the contents of a streaming DMA buffer without unmapping it it should call dma_sync_single_for_cpu(). Once the call has been made, the CPU "owns" the DMA buffer and can work with it as needed. Before the device accesses the buffer, however, ownership should be transferred back to it with dma_sync_single_for_device(). Both calls weren't performed by the driver, resulting with odd paging errors on some platforms. Fix it. Fixes: a6c4fb4441f4 ("iwlwifi: mvm: Add FW paging mechanism for the UMAC on PCI") Signed-off-by: Sara Sharon <sara.sharon@intel.com> Signed-off-by: Luca Coelho <luciano.coelho@intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c4
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/fw.c23
2 files changed, 24 insertions, 3 deletions
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c
index d89d0a1fd34e..700d244df34b 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c
@@ -784,12 +784,16 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
784 struct iwl_fw_error_dump_paging *paging; 784 struct iwl_fw_error_dump_paging *paging;
785 struct page *pages = 785 struct page *pages =
786 mvm->fw_paging_db[i].fw_paging_block; 786 mvm->fw_paging_db[i].fw_paging_block;
787 dma_addr_t addr = mvm->fw_paging_db[i].fw_paging_phys;
787 788
788 dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_PAGING); 789 dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_PAGING);
789 dump_data->len = cpu_to_le32(sizeof(*paging) + 790 dump_data->len = cpu_to_le32(sizeof(*paging) +
790 PAGING_BLOCK_SIZE); 791 PAGING_BLOCK_SIZE);
791 paging = (void *)dump_data->data; 792 paging = (void *)dump_data->data;
792 paging->index = cpu_to_le32(i); 793 paging->index = cpu_to_le32(i);
794 dma_sync_single_for_cpu(mvm->trans->dev, addr,
795 PAGING_BLOCK_SIZE,
796 DMA_BIDIRECTIONAL);
793 memcpy(paging->data, page_address(pages), 797 memcpy(paging->data, page_address(pages),
794 PAGING_BLOCK_SIZE); 798 PAGING_BLOCK_SIZE);
795 dump_data = iwl_fw_error_next_data(dump_data); 799 dump_data = iwl_fw_error_next_data(dump_data);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
index 872066317fa5..2ec3a91a0f6b 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
@@ -214,6 +214,10 @@ static int iwl_fill_paging_mem(struct iwl_mvm *mvm, const struct fw_img *image)
214 memcpy(page_address(mvm->fw_paging_db[0].fw_paging_block), 214 memcpy(page_address(mvm->fw_paging_db[0].fw_paging_block),
215 image->sec[sec_idx].data, 215 image->sec[sec_idx].data,
216 mvm->fw_paging_db[0].fw_paging_size); 216 mvm->fw_paging_db[0].fw_paging_size);
217 dma_sync_single_for_device(mvm->trans->dev,
218 mvm->fw_paging_db[0].fw_paging_phys,
219 mvm->fw_paging_db[0].fw_paging_size,
220 DMA_BIDIRECTIONAL);
217 221
218 IWL_DEBUG_FW(mvm, 222 IWL_DEBUG_FW(mvm,
219 "Paging: copied %d CSS bytes to first block\n", 223 "Paging: copied %d CSS bytes to first block\n",
@@ -228,9 +232,16 @@ static int iwl_fill_paging_mem(struct iwl_mvm *mvm, const struct fw_img *image)
228 * loop stop at num_of_paging_blk since that last block is not full. 232 * loop stop at num_of_paging_blk since that last block is not full.
229 */ 233 */
230 for (idx = 1; idx < mvm->num_of_paging_blk; idx++) { 234 for (idx = 1; idx < mvm->num_of_paging_blk; idx++) {
231 memcpy(page_address(mvm->fw_paging_db[idx].fw_paging_block), 235 struct iwl_fw_paging *block = &mvm->fw_paging_db[idx];
236
237 memcpy(page_address(block->fw_paging_block),
232 image->sec[sec_idx].data + offset, 238 image->sec[sec_idx].data + offset,
233 mvm->fw_paging_db[idx].fw_paging_size); 239 block->fw_paging_size);
240 dma_sync_single_for_device(mvm->trans->dev,
241 block->fw_paging_phys,
242 block->fw_paging_size,
243 DMA_BIDIRECTIONAL);
244
234 245
235 IWL_DEBUG_FW(mvm, 246 IWL_DEBUG_FW(mvm,
236 "Paging: copied %d paging bytes to block %d\n", 247 "Paging: copied %d paging bytes to block %d\n",
@@ -242,9 +253,15 @@ static int iwl_fill_paging_mem(struct iwl_mvm *mvm, const struct fw_img *image)
242 253
243 /* copy the last paging block */ 254 /* copy the last paging block */
244 if (mvm->num_of_pages_in_last_blk > 0) { 255 if (mvm->num_of_pages_in_last_blk > 0) {
245 memcpy(page_address(mvm->fw_paging_db[idx].fw_paging_block), 256 struct iwl_fw_paging *block = &mvm->fw_paging_db[idx];
257
258 memcpy(page_address(block->fw_paging_block),
246 image->sec[sec_idx].data + offset, 259 image->sec[sec_idx].data + offset,
247 FW_PAGING_SIZE * mvm->num_of_pages_in_last_blk); 260 FW_PAGING_SIZE * mvm->num_of_pages_in_last_blk);
261 dma_sync_single_for_device(mvm->trans->dev,
262 block->fw_paging_phys,
263 block->fw_paging_size,
264 DMA_BIDIRECTIONAL);
248 265
249 IWL_DEBUG_FW(mvm, 266 IWL_DEBUG_FW(mvm,
250 "Paging: copied %d pages in the last block %d\n", 267 "Paging: copied %d pages in the last block %d\n",