Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

virtio_rpmsg: set DRIVER_OK before using device

virtio spec requires that all drivers set DRIVER_OK
before using devices. While rpmsg isn't yet
included in the virtio 1 spec, previous spec versions
also required this.

virtio rpmsg violates this rule: is calls kick
before setting DRIVER_OK.

The fix isn't trivial since simply calling virtio_device_ready earlier
would mean we might get an interrupt in parallel with adding buffers.

Instead, split kick out to prepare+notify calls. prepare before
virtio_device_ready - when we know we won't get interrupts. notify right
afterwards.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Acked-by: Ohad Ben-Cohen <ohad@wizery.com>
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>

authored by

Michael S. Tsirkin and committed by
Rusty Russell
71e4b8bf 8051a2a5

+16 -1
+16 -1
drivers/rpmsg/virtio_rpmsg_bus.c
··· 951 951 void *bufs_va; 952 952 int err = 0, i; 953 953 size_t total_buf_space; 954 + bool notify; 954 955 955 956 vrp = kzalloc(sizeof(*vrp), GFP_KERNEL); 956 957 if (!vrp) ··· 1031 1030 } 1032 1031 } 1033 1032 1033 + /* 1034 + * Prepare to kick but don't notify yet - we can't do this before 1035 + * device is ready. 1036 + */ 1037 + notify = virtqueue_kick_prepare(vrp->rvq); 1038 + 1039 + /* From this point on, we can notify and get callbacks. */ 1040 + virtio_device_ready(vdev); 1041 + 1034 1042 /* tell the remote processor it can start sending messages */ 1035 - virtqueue_kick(vrp->rvq); 1043 + /* 1044 + * this might be concurrent with callbacks, but we are only 1045 + * doing notify, not a full kick here, so that's ok. 1046 + */ 1047 + if (notify) 1048 + virtqueue_notify(vrp->rvq); 1036 1049 1037 1050 dev_info(&vdev->dev, "rpmsg host is online\n"); 1038 1051