Commit c571573a authored by Emmanuel Grumbach's avatar Emmanuel Grumbach Committed by Johannes Berg

iwlwifi: pcie: prefer to load the firmware in one shot

Users complained about allocation failures, so we loaded
the firmware in small chunks (PAGE_SIZE). This makes the
firmware restart considerably slower.
So, always prefer to load it in one shot allocating a big
chunk of coherent, and use smaller chunks as a fallback
solution.

On my laptop, this reduces the fw loading time from 120ms
to 20ms.
Signed-off-by: default avatarEmmanuel Grumbach <emmanuel.grumbach@intel.com>
Reviewed-by: default avatarMoshe Island <moshe.island@intel.com>
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 7df15b1e
...@@ -405,20 +405,27 @@ static int iwl_pcie_load_section(struct iwl_trans *trans, u8 section_num, ...@@ -405,20 +405,27 @@ static int iwl_pcie_load_section(struct iwl_trans *trans, u8 section_num,
{ {
u8 *v_addr; u8 *v_addr;
dma_addr_t p_addr; dma_addr_t p_addr;
u32 offset; u32 offset, chunk_sz = section->len;
int ret = 0; int ret = 0;
IWL_DEBUG_FW(trans, "[%d] uCode section being loaded...\n", IWL_DEBUG_FW(trans, "[%d] uCode section being loaded...\n",
section_num); section_num);
v_addr = dma_alloc_coherent(trans->dev, PAGE_SIZE, &p_addr, GFP_KERNEL); v_addr = dma_alloc_coherent(trans->dev, chunk_sz, &p_addr,
if (!v_addr) GFP_KERNEL | __GFP_NOWARN);
return -ENOMEM; if (!v_addr) {
IWL_DEBUG_INFO(trans, "Falling back to small chunks of DMA\n");
chunk_sz = PAGE_SIZE;
v_addr = dma_alloc_coherent(trans->dev, chunk_sz,
&p_addr, GFP_KERNEL);
if (!v_addr)
return -ENOMEM;
}
for (offset = 0; offset < section->len; offset += PAGE_SIZE) { for (offset = 0; offset < section->len; offset += chunk_sz) {
u32 copy_size; u32 copy_size;
copy_size = min_t(u32, PAGE_SIZE, section->len - offset); copy_size = min_t(u32, chunk_sz, section->len - offset);
memcpy(v_addr, (u8 *)section->data + offset, copy_size); memcpy(v_addr, (u8 *)section->data + offset, copy_size);
ret = iwl_pcie_load_firmware_chunk(trans, ret = iwl_pcie_load_firmware_chunk(trans,
...@@ -432,7 +439,7 @@ static int iwl_pcie_load_section(struct iwl_trans *trans, u8 section_num, ...@@ -432,7 +439,7 @@ static int iwl_pcie_load_section(struct iwl_trans *trans, u8 section_num,
} }
} }
dma_free_coherent(trans->dev, PAGE_SIZE, v_addr, p_addr); dma_free_coherent(trans->dev, chunk_sz, v_addr, p_addr);
return ret; return ret;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment