Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1cb86d47 authored by Michal Kazior's avatar Michal Kazior Committed by Kalle Valo
Browse files

ath10k: prevent pci tx/rx starvation



In theory it was possible to starve the system if
a tx/rx handler could implicitly trigger more
tx/rx pci events.

Signed-off-by: default avatarMichal Kazior <michal.kazior@tieto.com>
Signed-off-by: default avatarKalle Valo <kvalo@qca.qualcomm.com>
parent d84a512d
Loading
Loading
Loading
Loading
+15 −6
Original line number Diff line number Diff line
@@ -823,20 +823,24 @@ static void ath10k_pci_ce_send_done(struct ath10k_ce_pipe *ce_state)
	struct ath10k *ar = ce_state->ar;
	struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
	struct ath10k_hif_cb *cb = &ar_pci->msg_callbacks_current;
	void *transfer_context;
	struct sk_buff_head list;
	struct sk_buff *skb;
	u32 ce_data;
	unsigned int nbytes;
	unsigned int transfer_id;

	while (ath10k_ce_completed_send_next(ce_state, &transfer_context,
					     &ce_data, &nbytes,
					     &transfer_id) == 0) {
	__skb_queue_head_init(&list);
	while (ath10k_ce_completed_send_next(ce_state, (void **)&skb, &ce_data,
					     &nbytes, &transfer_id) == 0) {
		/* no need to call tx completion for NULL pointers */
		if (transfer_context == NULL)
		if (skb == NULL)
			continue;

		cb->tx_completion(ar, transfer_context);
		__skb_queue_tail(&list, skb);
	}

	while ((skb = __skb_dequeue(&list)))
		cb->tx_completion(ar, skb);
}

/* Called by lower (CE) layer when data is received from the Target. */
@@ -847,12 +851,14 @@ static void ath10k_pci_ce_recv_data(struct ath10k_ce_pipe *ce_state)
	struct ath10k_pci_pipe *pipe_info =  &ar_pci->pipe_info[ce_state->id];
	struct ath10k_hif_cb *cb = &ar_pci->msg_callbacks_current;
	struct sk_buff *skb;
	struct sk_buff_head list;
	void *transfer_context;
	u32 ce_data;
	unsigned int nbytes, max_nbytes;
	unsigned int transfer_id;
	unsigned int flags;

	__skb_queue_head_init(&list);
	while (ath10k_ce_completed_recv_next(ce_state, &transfer_context,
					     &ce_data, &nbytes, &transfer_id,
					     &flags) == 0) {
@@ -869,7 +875,10 @@ static void ath10k_pci_ce_recv_data(struct ath10k_ce_pipe *ce_state)
		}

		skb_put(skb, nbytes);
		__skb_queue_tail(&list, skb);
	}

	while ((skb = __skb_dequeue(&list))) {
		ath10k_dbg(ar, ATH10K_DBG_PCI, "pci rx ce pipe %d len %d\n",
			   ce_state->id, skb->len);
		ath10k_dbg_dump(ar, ATH10K_DBG_PCI_DUMP, NULL, "pci rx: ",