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

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
...@@ -823,20 +823,24 @@ static void ath10k_pci_ce_send_done(struct ath10k_ce_pipe *ce_state) ...@@ -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 *ar = ce_state->ar;
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
struct ath10k_hif_cb *cb = &ar_pci->msg_callbacks_current; 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; u32 ce_data;
unsigned int nbytes; unsigned int nbytes;
unsigned int transfer_id; unsigned int transfer_id;
while (ath10k_ce_completed_send_next(ce_state, &transfer_context, __skb_queue_head_init(&list);
&ce_data, &nbytes, while (ath10k_ce_completed_send_next(ce_state, (void **)&skb, &ce_data,
&transfer_id) == 0) { &nbytes, &transfer_id) == 0) {
/* no need to call tx completion for NULL pointers */ /* no need to call tx completion for NULL pointers */
if (transfer_context == NULL) if (skb == NULL)
continue; 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. */ /* 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) ...@@ -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_pci_pipe *pipe_info = &ar_pci->pipe_info[ce_state->id];
struct ath10k_hif_cb *cb = &ar_pci->msg_callbacks_current; struct ath10k_hif_cb *cb = &ar_pci->msg_callbacks_current;
struct sk_buff *skb; struct sk_buff *skb;
struct sk_buff_head list;
void *transfer_context; void *transfer_context;
u32 ce_data; u32 ce_data;
unsigned int nbytes, max_nbytes; unsigned int nbytes, max_nbytes;
unsigned int transfer_id; unsigned int transfer_id;
unsigned int flags; unsigned int flags;
__skb_queue_head_init(&list);
while (ath10k_ce_completed_recv_next(ce_state, &transfer_context, while (ath10k_ce_completed_recv_next(ce_state, &transfer_context,
&ce_data, &nbytes, &transfer_id, &ce_data, &nbytes, &transfer_id,
&flags) == 0) { &flags) == 0) {
...@@ -869,7 +875,10 @@ static void ath10k_pci_ce_recv_data(struct ath10k_ce_pipe *ce_state) ...@@ -869,7 +875,10 @@ static void ath10k_pci_ce_recv_data(struct ath10k_ce_pipe *ce_state)
} }
skb_put(skb, nbytes); 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", ath10k_dbg(ar, ATH10K_DBG_PCI, "pci rx ce pipe %d len %d\n",
ce_state->id, skb->len); ce_state->id, skb->len);
ath10k_dbg_dump(ar, ATH10K_DBG_PCI_DUMP, NULL, "pci rx: ", ath10k_dbg_dump(ar, ATH10K_DBG_PCI_DUMP, NULL, "pci rx: ",
......
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