Linux: TransportRpmsg: Fix Mutex Deadlock Issue
[ipc/ipcdev.git] / linux / patches / 3.8.0 / omapl138 / 0001-Process-all-available-messages-in-virtqueue-callback.patch
1 From c93a879d9749295d8c56df7395e28fd446e6b9a7 Mon Sep 17 00:00:00 2001
2 From: Robert Tivy <rtivy@ti.com>
3 Date: Fri, 8 Mar 2013 10:17:04 -0800
4 Subject: [PATCH v8 1/7] Process all available messages in virtqueue callback
6 Change virtqueue callback function rpmsg_recv_done() to process all
7 available messages instead of just one message.
9 Signed-off-by: Robert Tivy <rtivy@ti.com>
10 ---
11  drivers/rpmsg/virtio_rpmsg_bus.c |   97 +++++++++++++++++++++++---------------
12  1 file changed, 58 insertions(+), 39 deletions(-)
14 diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c
15 index f1e3239..ae92ae7 100644
16 --- a/drivers/rpmsg/virtio_rpmsg_bus.c
17 +++ b/drivers/rpmsg/virtio_rpmsg_bus.c
18 @@ -782,7 +782,7 @@ out:
19  }
20  EXPORT_SYMBOL(rpmsg_send_offchannel_raw);
21  
22 -/* called when an rx buffer is used, and it's time to digest a message */
23 +/* called when an rx buffer is used, and it's time to digest a message(s) */
24  static void rpmsg_recv_done(struct virtqueue *rvq)
25  {
26         struct rpmsg_hdr *msg;
27 @@ -791,6 +791,7 @@ static void rpmsg_recv_done(struct virtqueue *rvq)
28         struct scatterlist sg;
29         struct virtproc_info *vrp = rvq->vdev->priv;
30         struct device *dev = &rvq->vdev->dev;
31 +       int added_buf = 0;
32         int err;
33  
34         msg = virtqueue_get_buf(rvq, &len);
35 @@ -799,60 +800,78 @@ static void rpmsg_recv_done(struct virtqueue *rvq)
36                 return;
37         }
38  
39 -       dev_dbg(dev, "From: 0x%x, To: 0x%x, Len: %d, Flags: %d, Reserved: %d\n",
40 +       while (msg) {
41 +               dev_dbg(dev, "From: 0x%x, To: 0x%x, Len: %d, Flags: %d, Reserved: %d\n",
42                                         msg->src, msg->dst, msg->len,
43                                         msg->flags, msg->reserved);
44 -       print_hex_dump(KERN_DEBUG, "rpmsg_virtio RX: ", DUMP_PREFIX_NONE, 16, 1,
45 +#ifdef DEBUG_VERBOSE
46 +               print_hex_dump(KERN_DEBUG, "rpmsg_virtio RX: ",
47 +                                       DUMP_PREFIX_NONE, 16, 1,
48                                         msg, sizeof(*msg) + msg->len, true);
49 +#endif
50  
51 -       /*
52 -        * We currently use fixed-sized buffers, so trivially sanitize
53 -        * the reported payload length.
54 -        */
55 -       if (len > RPMSG_BUF_SIZE ||
56 -               msg->len > (len - sizeof(struct rpmsg_hdr))) {
57 -               dev_warn(dev, "inbound msg too big: (%d, %d)\n", len, msg->len);
58 -               return;
59 -       }
60 +               /*
61 +                * We currently use fixed-sized buffers, so trivially sanitize
62 +                * the reported payload length.
63 +                */
64 +               if (len > RPMSG_BUF_SIZE ||
65 +                       msg->len > (len - sizeof(struct rpmsg_hdr))) {
66 +                       dev_warn(dev, "inbound msg too big: (%d, %d)\n",
67 +                                       len, msg->len);
68 +                       break;
69 +               }
70  
71 -       /* use the dst addr to fetch the callback of the appropriate user */
72 -       mutex_lock(&vrp->endpoints_lock);
73 +               /*
74 +                * Use the dst addr to fetch the callback of the appropriate
75 +                * user.
76 +                */
77 +               mutex_lock(&vrp->endpoints_lock);
78  
79 -       ept = idr_find(&vrp->endpoints, msg->dst);
80 +               ept = idr_find(&vrp->endpoints, msg->dst);
81  
82 -       /* let's make sure no one deallocates ept while we use it */
83 -       if (ept)
84 -               kref_get(&ept->refcount);
85 +               /* let's make sure no one deallocates ept while we use it */
86 +               if (ept)
87 +                       kref_get(&ept->refcount);
88  
89 -       mutex_unlock(&vrp->endpoints_lock);
90 +               mutex_unlock(&vrp->endpoints_lock);
91  
92 -       if (ept) {
93 -               /* make sure ept->cb doesn't go away while we use it */
94 -               mutex_lock(&ept->cb_lock);
95 +               if (ept) {
96 +                       /* make sure ept->cb doesn't go away while we use it */
97 +                       mutex_lock(&ept->cb_lock);
98  
99 -               if (ept->cb)
100 -                       ept->cb(ept->rpdev, msg->data, msg->len, ept->priv,
101 -                               msg->src);
102 +                       if (ept->cb)
103 +                               ept->cb(ept->rpdev, msg->data, msg->len,
104 +                                       ept->priv, msg->src);
105  
106 -               mutex_unlock(&ept->cb_lock);
107 +                       mutex_unlock(&ept->cb_lock);
108  
109 -               /* farewell, ept, we don't need you anymore */
110 -               kref_put(&ept->refcount, __ept_release);
111 -       } else
112 -               dev_warn(dev, "msg received with no recepient\n");
113 +                       /* farewell, ept, we don't need you anymore */
114 +                       kref_put(&ept->refcount, __ept_release);
115 +               } else
116 +                       dev_warn(dev, "msg received with no recepient\n");
117  
118 -       /* publish the real size of the buffer */
119 -       sg_init_one(&sg, msg, RPMSG_BUF_SIZE);
120 +               /* publish the real size of the buffer */
121 +               sg_init_one(&sg, msg, RPMSG_BUF_SIZE);
122  
123 -       /* add the buffer back to the remote processor's virtqueue */
124 -       err = virtqueue_add_buf(vrp->rvq, &sg, 0, 1, msg, GFP_KERNEL);
125 -       if (err < 0) {
126 -               dev_err(dev, "failed to add a virtqueue buffer: %d\n", err);
127 -               return;
128 +               /* add the buffer back to the remote processor's virtqueue */
129 +               err = virtqueue_add_buf(vrp->rvq, &sg, 0, 1, msg, GFP_KERNEL);
130 +               if (err < 0) {
131 +                       dev_err(dev, "failed to add a virtqueue buffer: %d\n",
132 +                                       err);
133 +                       break;
134 +               }
136 +               added_buf = 1;
138 +               msg = virtqueue_get_buf(rvq, &len);
139         }
140  
141 -       /* tell the remote processor we added another available rx buffer */
142 -       virtqueue_kick(vrp->rvq);
143 +       if (added_buf)
144 +               /*
145 +                * Tell the remote processor we added another available rx
146 +                * buffer.
147 +                */
148 +               virtqueue_kick(vrp->rvq);
149  }
150  
151  /*
152 -- 
153 1.7.9.4