net: qrtr: Move resume-tx transmission to recvmsg
authorBjorn Andersson <bjorn.andersson@linaro.org>
Tue, 14 Jan 2020 07:56:59 +0000 (23:56 -0800)
committerDavid S. Miller <davem@davemloft.net>
Wed, 15 Jan 2020 02:36:26 +0000 (18:36 -0800)
The confirm-rx bit is used to implement a per port flow control, in
order to make sure that no messages are dropped due to resource
exhaustion. Move the resume-tx transmission to recvmsg to only confirm
messages as they are consumed by the application.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/qrtr/qrtr.c

index 3d24d45..60f73b4 100644 (file)
@@ -362,22 +362,11 @@ static void qrtr_port_put(struct qrtr_sock *ipc);
 static void qrtr_node_rx_work(struct work_struct *work)
 {
        struct qrtr_node *node = container_of(work, struct qrtr_node, work);
-       struct qrtr_ctrl_pkt *pkt;
-       struct sockaddr_qrtr dst;
-       struct sockaddr_qrtr src;
        struct sk_buff *skb;
 
        while ((skb = skb_dequeue(&node->rx_queue)) != NULL) {
                struct qrtr_sock *ipc;
-               struct qrtr_cb *cb;
-               int confirm;
-
-               cb = (struct qrtr_cb *)skb->cb;
-               src.sq_node = cb->src_node;
-               src.sq_port = cb->src_port;
-               dst.sq_node = cb->dst_node;
-               dst.sq_port = cb->dst_port;
-               confirm = !!cb->confirm_rx;
+               struct qrtr_cb *cb = (struct qrtr_cb *)skb->cb;
 
                qrtr_node_assign(node, cb->src_node);
 
@@ -390,20 +379,6 @@ static void qrtr_node_rx_work(struct work_struct *work)
 
                        qrtr_port_put(ipc);
                }
-
-               if (confirm) {
-                       skb = qrtr_alloc_ctrl_packet(&pkt);
-                       if (!skb)
-                               break;
-
-                       pkt->cmd = cpu_to_le32(QRTR_TYPE_RESUME_TX);
-                       pkt->client.node = cpu_to_le32(dst.sq_node);
-                       pkt->client.port = cpu_to_le32(dst.sq_port);
-
-                       if (qrtr_node_enqueue(node, skb, QRTR_TYPE_RESUME_TX,
-                                             &dst, &src))
-                               break;
-               }
        }
 }
 
@@ -816,6 +791,34 @@ out_node:
        return rc;
 }
 
+static int qrtr_send_resume_tx(struct qrtr_cb *cb)
+{
+       struct sockaddr_qrtr remote = { AF_QIPCRTR, cb->src_node, cb->src_port };
+       struct sockaddr_qrtr local = { AF_QIPCRTR, cb->dst_node, cb->dst_port };
+       struct qrtr_ctrl_pkt *pkt;
+       struct qrtr_node *node;
+       struct sk_buff *skb;
+       int ret;
+
+       node = qrtr_node_lookup(remote.sq_node);
+       if (!node)
+               return -EINVAL;
+
+       skb = qrtr_alloc_ctrl_packet(&pkt);
+       if (!skb)
+               return -ENOMEM;
+
+       pkt->cmd = cpu_to_le32(QRTR_TYPE_RESUME_TX);
+       pkt->client.node = cpu_to_le32(cb->dst_node);
+       pkt->client.port = cpu_to_le32(cb->dst_port);
+
+       ret = qrtr_node_enqueue(node, skb, QRTR_TYPE_RESUME_TX, &local, &remote);
+
+       qrtr_node_release(node);
+
+       return ret;
+}
+
 static int qrtr_recvmsg(struct socket *sock, struct msghdr *msg,
                        size_t size, int flags)
 {
@@ -838,6 +841,7 @@ static int qrtr_recvmsg(struct socket *sock, struct msghdr *msg,
                release_sock(sk);
                return rc;
        }
+       cb = (struct qrtr_cb *)skb->cb;
 
        copied = skb->len;
        if (copied > size) {
@@ -851,7 +855,6 @@ static int qrtr_recvmsg(struct socket *sock, struct msghdr *msg,
        rc = copied;
 
        if (addr) {
-               cb = (struct qrtr_cb *)skb->cb;
                addr->sq_family = AF_QIPCRTR;
                addr->sq_node = cb->src_node;
                addr->sq_port = cb->src_port;
@@ -859,6 +862,9 @@ static int qrtr_recvmsg(struct socket *sock, struct msghdr *msg,
        }
 
 out:
+       if (cb->confirm_rx)
+               qrtr_send_resume_tx(cb);
+
        skb_free_datagram(sk, skb);
        release_sock(sk);