Commit 2374b186 authored by Michal Kazior's avatar Michal Kazior Committed by Kalle Valo

ath10k: fix bmi exchange tx/rx race

It was possible for tx completion not to be
processed. In that case an old stack pointer was
left on copy engine tx ring. Next bmi exchange
would immediately pop it and use complete() on the
completion struct there causing corruption.

Make sure to wait for both tx and rx completions
properly.
Signed-off-by: default avatarMichal Kazior <michal.kazior@tieto.com>
Signed-off-by: default avatarKalle Valo <kvalo@qca.qualcomm.com>
parent a491a920
...@@ -1362,8 +1362,6 @@ static int ath10k_pci_hif_exchange_bmi_msg(struct ath10k *ar, ...@@ -1362,8 +1362,6 @@ static int ath10k_pci_hif_exchange_bmi_msg(struct ath10k *ar,
ath10k_ce_recv_buf_enqueue(ce_rx, &xfer, resp_paddr); ath10k_ce_recv_buf_enqueue(ce_rx, &xfer, resp_paddr);
} }
init_completion(&xfer.done);
ret = ath10k_ce_send(ce_tx, &xfer, req_paddr, req_len, -1, 0); ret = ath10k_ce_send(ce_tx, &xfer, req_paddr, req_len, -1, 0);
if (ret) if (ret)
goto err_resp; goto err_resp;
...@@ -1414,10 +1412,7 @@ static void ath10k_pci_bmi_send_done(struct ath10k_ce_pipe *ce_state) ...@@ -1414,10 +1412,7 @@ static void ath10k_pci_bmi_send_done(struct ath10k_ce_pipe *ce_state)
&nbytes, &transfer_id)) &nbytes, &transfer_id))
return; return;
if (xfer->wait_for_resp) xfer->tx_done = true;
return;
complete(&xfer->done);
} }
static void ath10k_pci_bmi_recv_data(struct ath10k_ce_pipe *ce_state) static void ath10k_pci_bmi_recv_data(struct ath10k_ce_pipe *ce_state)
...@@ -1438,7 +1433,7 @@ static void ath10k_pci_bmi_recv_data(struct ath10k_ce_pipe *ce_state) ...@@ -1438,7 +1433,7 @@ static void ath10k_pci_bmi_recv_data(struct ath10k_ce_pipe *ce_state)
} }
xfer->resp_len = nbytes; xfer->resp_len = nbytes;
complete(&xfer->done); xfer->rx_done = true;
} }
static int ath10k_pci_bmi_wait(struct ath10k_ce_pipe *tx_pipe, static int ath10k_pci_bmi_wait(struct ath10k_ce_pipe *tx_pipe,
...@@ -1451,7 +1446,7 @@ static int ath10k_pci_bmi_wait(struct ath10k_ce_pipe *tx_pipe, ...@@ -1451,7 +1446,7 @@ static int ath10k_pci_bmi_wait(struct ath10k_ce_pipe *tx_pipe,
ath10k_pci_bmi_send_done(tx_pipe); ath10k_pci_bmi_send_done(tx_pipe);
ath10k_pci_bmi_recv_data(rx_pipe); ath10k_pci_bmi_recv_data(rx_pipe);
if (completion_done(&xfer->done)) if (xfer->tx_done && (xfer->rx_done == xfer->wait_for_resp))
return 0; return 0;
schedule(); schedule();
......
...@@ -38,7 +38,8 @@ ...@@ -38,7 +38,8 @@
#define DIAG_TRANSFER_LIMIT 2048 #define DIAG_TRANSFER_LIMIT 2048
struct bmi_xfer { struct bmi_xfer {
struct completion done; bool tx_done;
bool rx_done;
bool wait_for_resp; bool wait_for_resp;
u32 resp_len; u32 resp_len;
}; };
......
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