@@ -587,21 +587,27 @@ static int rpmsg_send_offchannel_raw(struct rpmsg_device *rpdev,
/* no free buffer ? wait for one (but bail after 15 seconds) */
while (!msg) {
/* enable "tx-complete" interrupts, if not already enabled */
rpmsg_upref_sleepers(vrp);
- /*
- * sleep until a free buffer is available or 15 secs elapse.
- * the timeout period is not configurable because there's
- * little point in asking drivers to specify that.
- * if later this happens to be required, it'd be easy to add.
- */
- err = wait_event_interruptible_timeout(vrp->sendq,
- (msg = get_a_tx_buf(vrp)),
- msecs_to_jiffies(15000));
+ /* make sure to retry to grab tx buffer before we start waiting */
+ msg = get_a_tx_buf(vrp);
+ if (msg) {
+ err = 0;
+ } else {
+ /*
+ * sleep until a free buffer is available or 15 secs elapse.
+ * the timeout period is not configurable because there's
+ * little point in asking drivers to specify that.
+ * if later this happens to be required, it'd be easy to add.
+ */
+ err = wait_event_interruptible_timeout(vrp->sendq,
+ (msg = get_a_tx_buf(vrp)),
+ msecs_to_jiffies(15000));
+ }
/* disable "tx-complete" interrupts if we're the last sleeper */
rpmsg_downref_sleepers(vrp);
/* timeout ? */
if (!err) {
When we cannot get a tx buffer (`get_a_tx_buf`) `rpmsg_upref_sleepers` enables tx-complete interrupt. However if the interrupt is executed after `get_a_tx_buf` and before `rpmsg_upref_sleepers` we may miss the tx-complete interrupt and sleep for the full 15 seconds. To avoid this race condition, we re-try once before we really start to sleep. Signed-off-by: Tim Blechmann <tim@klingt.org> --- drivers/rpmsg/virtio_rpmsg_bus.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-)