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

virtio-vdpa: add VIRTIO_F_NOTIFICATION_DATA feature support

Add VIRTIO_F_NOTIFICATION_DATA support for vDPA transport.
If this feature is negotiated, the driver passes extra data when kicking
a virtqueue.

A device that offers this feature needs to implement the
kick_vq_with_data callback.

kick_vq_with_data receives the vDPA device and data.
data includes:
16 bits vqn and 16 bits next available index for split virtqueues.
16 bits vqs, 15 least significant bits of next available index
and 1 bit next_wrap for packed virtqueues.

This patch follows a patch [1] by Viktor Prutyanov which adds support
for the MMIO, channel I/O and modern PCI transports.

Signed-off-by: Alvaro Karsz <alvaro.karsz@solid-run.com>
Message-Id: <20230413081855.36643-3-alvaro.karsz@solid-run.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Acked-by: Jason Wang <jasowang@redhat.com>

authored by

Alvaro Karsz and committed by
Michael S. Tsirkin
2c4e4a22 af8ececd

+30 -2
+21 -2
drivers/virtio/virtio_vdpa.c
··· 113 113 return true; 114 114 } 115 115 116 + static bool virtio_vdpa_notify_with_data(struct virtqueue *vq) 117 + { 118 + struct vdpa_device *vdpa = vd_get_vdpa(vq->vdev); 119 + const struct vdpa_config_ops *ops = vdpa->config; 120 + u32 data = vring_notification_data(vq); 121 + 122 + ops->kick_vq_with_data(vdpa, data); 123 + 124 + return true; 125 + } 126 + 116 127 static irqreturn_t virtio_vdpa_config_cb(void *private) 117 128 { 118 129 struct virtio_vdpa_device *vd_dev = private; ··· 150 139 struct device *dma_dev; 151 140 const struct vdpa_config_ops *ops = vdpa->config; 152 141 struct virtio_vdpa_vq_info *info; 142 + bool (*notify)(struct virtqueue *vq) = virtio_vdpa_notify; 153 143 struct vdpa_callback cb; 154 144 struct virtqueue *vq; 155 145 u64 desc_addr, driver_addr, device_addr; ··· 166 154 167 155 if (index >= vdpa->nvqs) 168 156 return ERR_PTR(-ENOENT); 157 + 158 + /* We cannot accept VIRTIO_F_NOTIFICATION_DATA without kick_vq_with_data */ 159 + if (__virtio_test_bit(vdev, VIRTIO_F_NOTIFICATION_DATA)) { 160 + if (ops->kick_vq_with_data) 161 + notify = virtio_vdpa_notify_with_data; 162 + else 163 + __virtio_clear_bit(vdev, VIRTIO_F_NOTIFICATION_DATA); 164 + } 169 165 170 166 /* Queue shouldn't already be set up. */ 171 167 if (ops->get_vq_ready(vdpa, index)) ··· 204 184 dma_dev = vdpa_get_dma_dev(vdpa); 205 185 vq = vring_create_virtqueue_dma(index, max_num, align, vdev, 206 186 true, may_reduce_num, ctx, 207 - virtio_vdpa_notify, callback, 208 - name, dma_dev); 187 + notify, callback, name, dma_dev); 209 188 if (!vq) { 210 189 err = -ENOMEM; 211 190 goto error_new_virtqueue;
+9
include/linux/vdpa.h
··· 149 149 * @kick_vq: Kick the virtqueue 150 150 * @vdev: vdpa device 151 151 * @idx: virtqueue index 152 + * @kick_vq_with_data: Kick the virtqueue and supply extra data 153 + * (only if VIRTIO_F_NOTIFICATION_DATA is negotiated) 154 + * @vdev: vdpa device 155 + * @data for split virtqueue: 156 + * 16 bits vqn and 16 bits next available index. 157 + * @data for packed virtqueue: 158 + * 16 bits vqn, 15 least significant bits of 159 + * next available index and 1 bit next_wrap. 152 160 * @set_vq_cb: Set the interrupt callback function for 153 161 * a virtqueue 154 162 * @vdev: vdpa device ··· 337 329 u64 device_area); 338 330 void (*set_vq_num)(struct vdpa_device *vdev, u16 idx, u32 num); 339 331 void (*kick_vq)(struct vdpa_device *vdev, u16 idx); 332 + void (*kick_vq_with_data)(struct vdpa_device *vdev, u32 data); 340 333 void (*set_vq_cb)(struct vdpa_device *vdev, u16 idx, 341 334 struct vdpa_callback *cb); 342 335 void (*set_vq_ready)(struct vdpa_device *vdev, u16 idx, bool ready);