Commit 1e56d512 authored by Ashok Raj Nagarajan's avatar Ashok Raj Nagarajan Committed by Kalle Valo

ath10k: fix diag_read to collect data for larger memory

diag_read uses dma_alloc_coherent to allocate memory requested by the
caller. If this memory requested is larger, more than DIAG_TRANSFER_LIMIT
(2K), then it is likely that we may not get the requested memory and we
would fail.

To solve this, request dma_alloc_coherent for only DIAG_TRANSFER_LIMIT, and
reuse this buffer multiple times as needed to copy the data requested in
smaller chunks of size not more than DIAG_TRANSFER_LIMIT. Previously we
were reading into the caller's only after getting the complete requested
data.

Fixes: 68c03249 ('ath10k: convert pci_alloc_consistent() to dma_alloc_coherent()')
Signed-off-by: default avatarAshok Raj Nagarajan <arnagara@qti.qualcomm.com>
Signed-off-by: default avatarKalle Valo <kvalo@qca.qualcomm.com>
parent 8a0a36cf
...@@ -869,7 +869,7 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data, ...@@ -869,7 +869,7 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data,
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
int ret = 0; int ret = 0;
u32 *buf; u32 *buf;
unsigned int completed_nbytes, orig_nbytes, remaining_bytes; unsigned int completed_nbytes, alloc_nbytes, remaining_bytes;
struct ath10k_ce_pipe *ce_diag; struct ath10k_ce_pipe *ce_diag;
/* Host buffer address in CE space */ /* Host buffer address in CE space */
u32 ce_data; u32 ce_data;
...@@ -887,9 +887,10 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data, ...@@ -887,9 +887,10 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data,
* 1) 4-byte alignment * 1) 4-byte alignment
* 2) Buffer in DMA-able space * 2) Buffer in DMA-able space
*/ */
orig_nbytes = nbytes; alloc_nbytes = min_t(unsigned int, nbytes, DIAG_TRANSFER_LIMIT);
data_buf = (unsigned char *)dma_alloc_coherent(ar->dev, data_buf = (unsigned char *)dma_alloc_coherent(ar->dev,
orig_nbytes, alloc_nbytes,
&ce_data_base, &ce_data_base,
GFP_ATOMIC); GFP_ATOMIC);
...@@ -897,9 +898,9 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data, ...@@ -897,9 +898,9 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data,
ret = -ENOMEM; ret = -ENOMEM;
goto done; goto done;
} }
memset(data_buf, 0, orig_nbytes); memset(data_buf, 0, alloc_nbytes);
remaining_bytes = orig_nbytes; remaining_bytes = nbytes;
ce_data = ce_data_base; ce_data = ce_data_base;
while (remaining_bytes) { while (remaining_bytes) {
nbytes = min_t(unsigned int, remaining_bytes, nbytes = min_t(unsigned int, remaining_bytes,
...@@ -959,19 +960,22 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data, ...@@ -959,19 +960,22 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data,
} }
remaining_bytes -= nbytes; remaining_bytes -= nbytes;
if (ret) {
ath10k_warn(ar, "failed to read diag value at 0x%x: %d\n",
address, ret);
break;
}
memcpy(data, data_buf, nbytes);
address += nbytes; address += nbytes;
ce_data += nbytes; data += nbytes;
} }
done: done:
if (ret == 0)
memcpy(data, data_buf, orig_nbytes);
else
ath10k_warn(ar, "failed to read diag value at 0x%x: %d\n",
address, ret);
if (data_buf) if (data_buf)
dma_free_coherent(ar->dev, orig_nbytes, data_buf, dma_free_coherent(ar->dev, alloc_nbytes, data_buf,
ce_data_base); ce_data_base);
spin_unlock_bh(&ar_pci->ce_lock); spin_unlock_bh(&ar_pci->ce_lock);
......
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