Skip to content

Commit

Permalink
ath11k: Reuse the available memory after firmware reload
Browse files Browse the repository at this point in the history
Ath11k allocates memory when firmware requests memory in QMI.
Coldboot calibration and firmware recovery uses firmware reload.
On firmware reload, firmware sends memory request again. If Ath11k
allocates memory on first firmware boot, reuse the available
memory. Also check if the segment type and size is same
on the next firmware boot. Reuse if segment type/size is
same as previous firmware boot else free the segment and
allocate the segment with size/type.

Tested-on: QCN9074 hw1.0 PCI WLAN.HK.2.6.0.1-00752-QCAHKSWPL_SILICONZ-1

Signed-off-by: Anilkumar Kolli <quic_akolli@quicinc.com>
Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com>
Link: https://lore.kernel.org/r/20220506141448.10340-1-quic_akolli@quicinc.com
  • Loading branch information
Anilkumar Kolli authored and kvalo committed May 10, 2022
1 parent 4255a07 commit 5962f37
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 4 deletions.
1 change: 0 additions & 1 deletion drivers/net/wireless/ath/ath11k/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -1777,7 +1777,6 @@ static void ath11k_core_reset(struct work_struct *work)
ATH11K_RECOVER_START_TIMEOUT_HZ);

ath11k_hif_power_down(ab);
ath11k_qmi_free_resource(ab);
ath11k_hif_power_up(ab);

ath11k_dbg(ab, ATH11K_DBG_BOOT, "reset started\n");
Expand Down
24 changes: 21 additions & 3 deletions drivers/net/wireless/ath/ath11k/qmi.c
Original file line number Diff line number Diff line change
Expand Up @@ -1970,6 +1970,21 @@ static int ath11k_qmi_alloc_target_mem_chunk(struct ath11k_base *ab)

for (i = 0; i < ab->qmi.mem_seg_count; i++) {
chunk = &ab->qmi.target_mem[i];

/* Firmware reloads in coldboot/firmware recovery.
* in such case, no need to allocate memory for FW again.
*/
if (chunk->vaddr) {
if (chunk->prev_type == chunk->type ||
chunk->prev_size == chunk->size)
continue;

/* cannot reuse the existing chunk */
dma_free_coherent(ab->dev, chunk->size,
chunk->vaddr, chunk->paddr);
chunk->vaddr = NULL;
}

chunk->vaddr = dma_alloc_coherent(ab->dev,
chunk->size,
&chunk->paddr,
Expand All @@ -1990,6 +2005,8 @@ static int ath11k_qmi_alloc_target_mem_chunk(struct ath11k_base *ab)
chunk->type);
return -EINVAL;
}
chunk->prev_type = chunk->type;
chunk->prev_size = chunk->size;
}

return 0;
Expand Down Expand Up @@ -2466,9 +2483,6 @@ static int ath11k_qmi_m3_load(struct ath11k_base *ab)
char path[100];
int ret;

if (m3_mem->vaddr || m3_mem->size)
return 0;

fw = ath11k_core_firmware_request(ab, ATH11K_M3_FILE);
if (IS_ERR(fw)) {
ret = PTR_ERR(fw);
Expand All @@ -2478,6 +2492,9 @@ static int ath11k_qmi_m3_load(struct ath11k_base *ab)
return ret;
}

if (m3_mem->vaddr || m3_mem->size)
goto skip_m3_alloc;

m3_mem->vaddr = dma_alloc_coherent(ab->dev,
fw->size, &m3_mem->paddr,
GFP_KERNEL);
Expand All @@ -2488,6 +2505,7 @@ static int ath11k_qmi_m3_load(struct ath11k_base *ab)
return -ENOMEM;
}

skip_m3_alloc:
memcpy(m3_mem->vaddr, fw->data, fw->size);
m3_mem->size = fw->size;
release_firmware(fw);
Expand Down
2 changes: 2 additions & 0 deletions drivers/net/wireless/ath/ath11k/qmi.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@ struct ath11k_qmi_event_msg {
struct target_mem_chunk {
u32 size;
u32 type;
u32 prev_size;
u32 prev_type;
dma_addr_t paddr;
u32 *vaddr;
void __iomem *iaddr;
Expand Down

0 comments on commit 5962f37

Please sign in to comment.