Commit 08fe9b40 authored by Michal Kazior's avatar Michal Kazior Committed by Kalle Valo

ath10k: prevent HTC from being used after stopping

It was possible to submit new HTC commands
after/while HTC stopped. This led to memory
corruption in some rare cases.
Signed-off-by: default avatarMichal Kazior <michal.kazior@tieto.com>
Signed-off-by: default avatarKalle Valo <kvalo@qca.qualcomm.com>
parent 278c4a85
...@@ -254,10 +254,14 @@ int ath10k_htc_send(struct ath10k_htc *htc, ...@@ -254,10 +254,14 @@ int ath10k_htc_send(struct ath10k_htc *htc,
return -ENOENT; return -ENOENT;
} }
skb_push(skb, sizeof(struct ath10k_htc_hdr));
spin_lock_bh(&htc->tx_lock); spin_lock_bh(&htc->tx_lock);
if (htc->stopped) {
spin_unlock_bh(&htc->tx_lock);
return -ESHUTDOWN;
}
__skb_queue_tail(&ep->tx_queue, skb); __skb_queue_tail(&ep->tx_queue, skb);
skb_push(skb, sizeof(struct ath10k_htc_hdr));
spin_unlock_bh(&htc->tx_lock); spin_unlock_bh(&htc->tx_lock);
queue_work(htc->ar->workqueue, &ep->send_work); queue_work(htc->ar->workqueue, &ep->send_work);
...@@ -270,23 +274,17 @@ static int ath10k_htc_tx_completion_handler(struct ath10k *ar, ...@@ -270,23 +274,17 @@ static int ath10k_htc_tx_completion_handler(struct ath10k *ar,
{ {
struct ath10k_htc *htc = &ar->htc; struct ath10k_htc *htc = &ar->htc;
struct ath10k_htc_ep *ep = &htc->endpoint[eid]; struct ath10k_htc_ep *ep = &htc->endpoint[eid];
bool stopping;
ath10k_htc_notify_tx_completion(ep, skb); ath10k_htc_notify_tx_completion(ep, skb);
/* the skb now belongs to the completion handler */ /* the skb now belongs to the completion handler */
/* note: when using TX credit flow, the re-checking of queues happens
* when credits flow back from the target. in the non-TX credit case,
* we recheck after the packet completes */
spin_lock_bh(&htc->tx_lock); spin_lock_bh(&htc->tx_lock);
stopping = htc->stopping; if (!ep->tx_credit_flow_enabled && !htc->stopped)
spin_unlock_bh(&htc->tx_lock);
if (!ep->tx_credit_flow_enabled && !stopping)
/*
* note: when using TX credit flow, the re-checking of
* queues happens when credits flow back from the target.
* in the non-TX credit case, we recheck after the packet
* completes
*/
queue_work(ar->workqueue, &ep->send_work); queue_work(ar->workqueue, &ep->send_work);
spin_unlock_bh(&htc->tx_lock);
return 0; return 0;
} }
...@@ -951,7 +949,7 @@ void ath10k_htc_stop(struct ath10k_htc *htc) ...@@ -951,7 +949,7 @@ void ath10k_htc_stop(struct ath10k_htc *htc)
struct ath10k_htc_ep *ep; struct ath10k_htc_ep *ep;
spin_lock_bh(&htc->tx_lock); spin_lock_bh(&htc->tx_lock);
htc->stopping = true; htc->stopped = true;
spin_unlock_bh(&htc->tx_lock); spin_unlock_bh(&htc->tx_lock);
for (i = ATH10K_HTC_EP_0; i < ATH10K_HTC_EP_COUNT; i++) { for (i = ATH10K_HTC_EP_0; i < ATH10K_HTC_EP_COUNT; i++) {
...@@ -972,6 +970,7 @@ int ath10k_htc_init(struct ath10k *ar) ...@@ -972,6 +970,7 @@ int ath10k_htc_init(struct ath10k *ar)
spin_lock_init(&htc->tx_lock); spin_lock_init(&htc->tx_lock);
htc->stopped = false;
ath10k_htc_reset_endpoint_states(htc); ath10k_htc_reset_endpoint_states(htc);
/* setup HIF layer callbacks */ /* setup HIF layer callbacks */
......
...@@ -335,7 +335,7 @@ struct ath10k_htc { ...@@ -335,7 +335,7 @@ struct ath10k_htc {
struct ath10k *ar; struct ath10k *ar;
struct ath10k_htc_ep endpoint[ATH10K_HTC_EP_COUNT]; struct ath10k_htc_ep endpoint[ATH10K_HTC_EP_COUNT];
/* protects endpoint and stopping fields */ /* protects endpoint and stopped fields */
spinlock_t tx_lock; spinlock_t tx_lock;
struct ath10k_htc_ops htc_ops; struct ath10k_htc_ops htc_ops;
...@@ -349,7 +349,7 @@ struct ath10k_htc { ...@@ -349,7 +349,7 @@ struct ath10k_htc {
struct ath10k_htc_svc_tx_credits service_tx_alloc[ATH10K_HTC_EP_COUNT]; struct ath10k_htc_svc_tx_credits service_tx_alloc[ATH10K_HTC_EP_COUNT];
int target_credit_size; int target_credit_size;
bool stopping; bool stopped;
}; };
int ath10k_htc_init(struct ath10k *ar); int ath10k_htc_init(struct ath10k *ar);
......
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