ath10k: add diag_read() to hif ops
diag_read() is used for reading from firmware memory via the diagnose window. First user will be cal_data debugfs file. To serialise diagnostic window access and make it safe to use while firmware is running take ce_lock both in ath10k_pci_diag_write_mem() and ath10k_pci_diag_read_mem(). Because of that all the CE calls had to be changed to _nolock variants. Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
This commit is contained in:
@@ -443,12 +443,12 @@ int ath10k_ce_rx_post_buf(struct ath10k_ce_pipe *pipe, void *ctx, u32 paddr)
|
||||
* Guts of ath10k_ce_completed_recv_next.
|
||||
* The caller takes responsibility for any necessary locking.
|
||||
*/
|
||||
static int ath10k_ce_completed_recv_next_nolock(struct ath10k_ce_pipe *ce_state,
|
||||
void **per_transfer_contextp,
|
||||
u32 *bufferp,
|
||||
unsigned int *nbytesp,
|
||||
unsigned int *transfer_idp,
|
||||
unsigned int *flagsp)
|
||||
int ath10k_ce_completed_recv_next_nolock(struct ath10k_ce_pipe *ce_state,
|
||||
void **per_transfer_contextp,
|
||||
u32 *bufferp,
|
||||
unsigned int *nbytesp,
|
||||
unsigned int *transfer_idp,
|
||||
unsigned int *flagsp)
|
||||
{
|
||||
struct ath10k_ce_ring *dest_ring = ce_state->dest_ring;
|
||||
unsigned int nentries_mask = dest_ring->nentries_mask;
|
||||
@@ -576,11 +576,11 @@ int ath10k_ce_revoke_recv_next(struct ath10k_ce_pipe *ce_state,
|
||||
* Guts of ath10k_ce_completed_send_next.
|
||||
* The caller takes responsibility for any necessary locking.
|
||||
*/
|
||||
static int ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state,
|
||||
void **per_transfer_contextp,
|
||||
u32 *bufferp,
|
||||
unsigned int *nbytesp,
|
||||
unsigned int *transfer_idp)
|
||||
int ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state,
|
||||
void **per_transfer_contextp,
|
||||
u32 *bufferp,
|
||||
unsigned int *nbytesp,
|
||||
unsigned int *transfer_idp)
|
||||
{
|
||||
struct ath10k_ce_ring *src_ring = ce_state->src_ring;
|
||||
u32 ctrl_addr = ce_state->ctrl_addr;
|
||||
|
@@ -192,6 +192,12 @@ int ath10k_ce_completed_send_next(struct ath10k_ce_pipe *ce_state,
|
||||
unsigned int *nbytesp,
|
||||
unsigned int *transfer_idp);
|
||||
|
||||
int ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state,
|
||||
void **per_transfer_contextp,
|
||||
u32 *bufferp,
|
||||
unsigned int *nbytesp,
|
||||
unsigned int *transfer_idp);
|
||||
|
||||
/*==================CE Engine Initialization=======================*/
|
||||
|
||||
int ath10k_ce_init_pipe(struct ath10k *ar, unsigned int ce_id,
|
||||
@@ -213,6 +219,13 @@ int ath10k_ce_revoke_recv_next(struct ath10k_ce_pipe *ce_state,
|
||||
void **per_transfer_contextp,
|
||||
u32 *bufferp);
|
||||
|
||||
int ath10k_ce_completed_recv_next_nolock(struct ath10k_ce_pipe *ce_state,
|
||||
void **per_transfer_contextp,
|
||||
u32 *bufferp,
|
||||
unsigned int *nbytesp,
|
||||
unsigned int *transfer_idp,
|
||||
unsigned int *flagsp);
|
||||
|
||||
/*
|
||||
* Support clean shutdown by allowing the caller to cancel
|
||||
* pending sends. Target DMA must be stopped before using
|
||||
|
@@ -43,6 +43,10 @@ struct ath10k_hif_ops {
|
||||
int (*tx_sg)(struct ath10k *ar, u8 pipe_id,
|
||||
struct ath10k_hif_sg_item *items, int n_items);
|
||||
|
||||
/* read firmware memory through the diagnose interface */
|
||||
int (*diag_read)(struct ath10k *ar, u32 address, void *buf,
|
||||
size_t buf_len);
|
||||
|
||||
/*
|
||||
* API to handle HIF-specific BMI message exchanges, this API is
|
||||
* synchronous and only allowed to be called from a context that
|
||||
@@ -98,6 +102,12 @@ static inline int ath10k_hif_tx_sg(struct ath10k *ar, u8 pipe_id,
|
||||
return ar->hif.ops->tx_sg(ar, pipe_id, items, n_items);
|
||||
}
|
||||
|
||||
static inline int ath10k_hif_diag_read(struct ath10k *ar, u32 address, void *buf,
|
||||
size_t buf_len)
|
||||
{
|
||||
return ar->hif.ops->diag_read(ar, address, buf, buf_len);
|
||||
}
|
||||
|
||||
static inline int ath10k_hif_exchange_bmi_msg(struct ath10k *ar,
|
||||
void *request, u32 request_len,
|
||||
void *response, u32 *response_len)
|
||||
|
@@ -485,6 +485,8 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data,
|
||||
void *data_buf = NULL;
|
||||
int i;
|
||||
|
||||
spin_lock_bh(&ar_pci->ce_lock);
|
||||
|
||||
ce_diag = ar_pci->ce_diag;
|
||||
|
||||
/*
|
||||
@@ -511,7 +513,7 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data,
|
||||
nbytes = min_t(unsigned int, remaining_bytes,
|
||||
DIAG_TRANSFER_LIMIT);
|
||||
|
||||
ret = ath10k_ce_rx_post_buf(ce_diag, NULL, ce_data);
|
||||
ret = __ath10k_ce_rx_post_buf(ce_diag, NULL, ce_data);
|
||||
if (ret != 0)
|
||||
goto done;
|
||||
|
||||
@@ -527,15 +529,15 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data,
|
||||
address = TARG_CPU_SPACE_TO_CE_SPACE(ar, ar_pci->mem,
|
||||
address);
|
||||
|
||||
ret = ath10k_ce_send(ce_diag, NULL, (u32)address, nbytes, 0,
|
||||
0);
|
||||
ret = ath10k_ce_send_nolock(ce_diag, NULL, (u32)address, nbytes, 0,
|
||||
0);
|
||||
if (ret)
|
||||
goto done;
|
||||
|
||||
i = 0;
|
||||
while (ath10k_ce_completed_send_next(ce_diag, NULL, &buf,
|
||||
&completed_nbytes,
|
||||
&id) != 0) {
|
||||
while (ath10k_ce_completed_send_next_nolock(ce_diag, NULL, &buf,
|
||||
&completed_nbytes,
|
||||
&id) != 0) {
|
||||
mdelay(1);
|
||||
if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) {
|
||||
ret = -EBUSY;
|
||||
@@ -554,9 +556,9 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data,
|
||||
}
|
||||
|
||||
i = 0;
|
||||
while (ath10k_ce_completed_recv_next(ce_diag, NULL, &buf,
|
||||
&completed_nbytes,
|
||||
&id, &flags) != 0) {
|
||||
while (ath10k_ce_completed_recv_next_nolock(ce_diag, NULL, &buf,
|
||||
&completed_nbytes,
|
||||
&id, &flags) != 0) {
|
||||
mdelay(1);
|
||||
|
||||
if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) {
|
||||
@@ -591,6 +593,8 @@ done:
|
||||
dma_free_coherent(ar->dev, orig_nbytes, data_buf,
|
||||
ce_data_base);
|
||||
|
||||
spin_unlock_bh(&ar_pci->ce_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -648,6 +652,8 @@ static int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address,
|
||||
dma_addr_t ce_data_base = 0;
|
||||
int i;
|
||||
|
||||
spin_lock_bh(&ar_pci->ce_lock);
|
||||
|
||||
ce_diag = ar_pci->ce_diag;
|
||||
|
||||
/*
|
||||
@@ -688,7 +694,7 @@ static int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address,
|
||||
nbytes = min_t(int, remaining_bytes, DIAG_TRANSFER_LIMIT);
|
||||
|
||||
/* Set up to receive directly into Target(!) address */
|
||||
ret = ath10k_ce_rx_post_buf(ce_diag, NULL, address);
|
||||
ret = __ath10k_ce_rx_post_buf(ce_diag, NULL, address);
|
||||
if (ret != 0)
|
||||
goto done;
|
||||
|
||||
@@ -696,15 +702,15 @@ static int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address,
|
||||
* Request CE to send caller-supplied data that
|
||||
* was copied to bounce buffer to Target(!) address.
|
||||
*/
|
||||
ret = ath10k_ce_send(ce_diag, NULL, (u32)ce_data,
|
||||
nbytes, 0, 0);
|
||||
ret = ath10k_ce_send_nolock(ce_diag, NULL, (u32)ce_data,
|
||||
nbytes, 0, 0);
|
||||
if (ret != 0)
|
||||
goto done;
|
||||
|
||||
i = 0;
|
||||
while (ath10k_ce_completed_send_next(ce_diag, NULL, &buf,
|
||||
&completed_nbytes,
|
||||
&id) != 0) {
|
||||
while (ath10k_ce_completed_send_next_nolock(ce_diag, NULL, &buf,
|
||||
&completed_nbytes,
|
||||
&id) != 0) {
|
||||
mdelay(1);
|
||||
|
||||
if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) {
|
||||
@@ -724,9 +730,9 @@ static int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address,
|
||||
}
|
||||
|
||||
i = 0;
|
||||
while (ath10k_ce_completed_recv_next(ce_diag, NULL, &buf,
|
||||
&completed_nbytes,
|
||||
&id, &flags) != 0) {
|
||||
while (ath10k_ce_completed_recv_next_nolock(ce_diag, NULL, &buf,
|
||||
&completed_nbytes,
|
||||
&id, &flags) != 0) {
|
||||
mdelay(1);
|
||||
|
||||
if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) {
|
||||
@@ -760,6 +766,8 @@ done:
|
||||
ath10k_warn(ar, "failed to write diag value at 0x%x: %d\n",
|
||||
address, ret);
|
||||
|
||||
spin_unlock_bh(&ar_pci->ce_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -942,6 +950,12 @@ err:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int ath10k_pci_hif_diag_read(struct ath10k *ar, u32 address, void *buf,
|
||||
size_t buf_len)
|
||||
{
|
||||
return ath10k_pci_diag_read_mem(ar, address, buf, buf_len);
|
||||
}
|
||||
|
||||
static u16 ath10k_pci_hif_get_free_queue_number(struct ath10k *ar, u8 pipe)
|
||||
{
|
||||
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
|
||||
@@ -1927,6 +1941,7 @@ static int ath10k_pci_hif_resume(struct ath10k *ar)
|
||||
|
||||
static const struct ath10k_hif_ops ath10k_pci_hif_ops = {
|
||||
.tx_sg = ath10k_pci_hif_tx_sg,
|
||||
.diag_read = ath10k_pci_hif_diag_read,
|
||||
.exchange_bmi_msg = ath10k_pci_hif_exchange_bmi_msg,
|
||||
.start = ath10k_pci_hif_start,
|
||||
.stop = ath10k_pci_hif_stop,
|
||||
|
Reference in New Issue
Block a user