| From 8a74ccfd3c914218400e29cf397e84cd4a15b949 Mon Sep 17 00:00:00 2001 |
| From: Sara Sharon <sara.sharon@intel.com> |
| Date: Wed, 30 Nov 2016 16:49:11 +0200 |
| Subject: [PATCH] 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: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c |
| index 46b52bf705fb..69f684b522be 100644 |
| --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c |
| +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c |
| @@ -786,12 +786,16 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm) |
| struct iwl_fw_error_dump_paging *paging; |
| struct page *pages = |
| mvm->fw_paging_db[i].fw_paging_block; |
| + dma_addr_t addr = mvm->fw_paging_db[i].fw_paging_phys; |
| |
| dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_PAGING); |
| dump_data->len = cpu_to_le32(sizeof(*paging) + |
| PAGING_BLOCK_SIZE); |
| paging = (void *)dump_data->data; |
| paging->index = cpu_to_le32(i); |
| + dma_sync_single_for_cpu(mvm->trans->dev, addr, |
| + PAGING_BLOCK_SIZE, |
| + DMA_BIDIRECTIONAL); |
| memcpy(paging->data, page_address(pages), |
| PAGING_BLOCK_SIZE); |
| 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 794c57486e02..1a32ec570cf0 100644 |
| --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c |
| +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c |
| @@ -223,6 +223,10 @@ static int iwl_fill_paging_mem(struct iwl_mvm *mvm, const struct fw_img *image) |
| memcpy(page_address(mvm->fw_paging_db[0].fw_paging_block), |
| image->sec[sec_idx].data, |
| mvm->fw_paging_db[0].fw_paging_size); |
| + dma_sync_single_for_device(mvm->trans->dev, |
| + mvm->fw_paging_db[0].fw_paging_phys, |
| + mvm->fw_paging_db[0].fw_paging_size, |
| + DMA_BIDIRECTIONAL); |
| |
| IWL_DEBUG_FW(mvm, |
| "Paging: copied %d CSS bytes to first block\n", |
| @@ -237,9 +241,16 @@ static int iwl_fill_paging_mem(struct iwl_mvm *mvm, const struct fw_img *image) |
| * loop stop at num_of_paging_blk since that last block is not full. |
| */ |
| for (idx = 1; idx < mvm->num_of_paging_blk; idx++) { |
| - memcpy(page_address(mvm->fw_paging_db[idx].fw_paging_block), |
| + struct iwl_fw_paging *block = &mvm->fw_paging_db[idx]; |
| + |
| + memcpy(page_address(block->fw_paging_block), |
| image->sec[sec_idx].data + offset, |
| - mvm->fw_paging_db[idx].fw_paging_size); |
| + block->fw_paging_size); |
| + dma_sync_single_for_device(mvm->trans->dev, |
| + block->fw_paging_phys, |
| + block->fw_paging_size, |
| + DMA_BIDIRECTIONAL); |
| + |
| |
| IWL_DEBUG_FW(mvm, |
| "Paging: copied %d paging bytes to block %d\n", |
| @@ -251,9 +262,15 @@ static int iwl_fill_paging_mem(struct iwl_mvm *mvm, const struct fw_img *image) |
| |
| /* copy the last paging block */ |
| if (mvm->num_of_pages_in_last_blk > 0) { |
| - memcpy(page_address(mvm->fw_paging_db[idx].fw_paging_block), |
| + struct iwl_fw_paging *block = &mvm->fw_paging_db[idx]; |
| + |
| + memcpy(page_address(block->fw_paging_block), |
| image->sec[sec_idx].data + offset, |
| FW_PAGING_SIZE * mvm->num_of_pages_in_last_blk); |
| + dma_sync_single_for_device(mvm->trans->dev, |
| + block->fw_paging_phys, |
| + block->fw_paging_size, |
| + DMA_BIDIRECTIONAL); |
| |
| IWL_DEBUG_FW(mvm, |
| "Paging: copied %d pages in the last block %d\n", |
| -- |
| 2.12.0 |
| |