diff --git a/net/qrtr/qrtr.c b/net/qrtr/qrtr.c index 65470258f13b..efd61e10ff21 100644 --- a/net/qrtr/qrtr.c +++ b/net/qrtr/qrtr.c @@ -553,7 +553,8 @@ int qrtr_endpoint_post(struct qrtr_endpoint *ep, const void *data, size_t len) } if (cb->type == QRTR_TYPE_RESUME_TX) { - qrtr_tx_resume(node, skb); + skb_queue_tail(&node->rx_queue, skb); + schedule_work(&node->work); } else { ipc = qrtr_port_lookup(cb->dst_port); if (!ipc) @@ -598,6 +599,20 @@ static struct sk_buff *qrtr_alloc_ctrl_packet(struct qrtr_ctrl_pkt **pkt) return skb; } +/* Handle not atomic operations for a received packet. */ +static void qrtr_node_rx_work(struct work_struct *work) +{ + struct qrtr_node *node = container_of(work, struct qrtr_node, work); + struct sk_buff *skb; + + while ((skb = skb_dequeue(&node->rx_queue)) != NULL) { + struct qrtr_cb *cb = (struct qrtr_cb *)skb->cb; + + if (cb->type == QRTR_TYPE_RESUME_TX) + qrtr_tx_resume(node, skb); + } +} + /** * qrtr_endpoint_register() - register a new endpoint * @ep: endpoint to register @@ -617,6 +632,7 @@ int qrtr_endpoint_register(struct qrtr_endpoint *ep, unsigned int nid) if (!node) return -ENOMEM; + INIT_WORK(&node->work, qrtr_node_rx_work); kref_init(&node->ref); mutex_init(&node->ep_lock); skb_queue_head_init(&node->rx_queue);