Message ID | 20220214081416.117695-7-xuanzhuo@linux.alibaba.com (mailing list archive) |
---|---|
State | Superseded |
Delegated to: | Netdev Maintainers |
Headers | show |
Series | virtio pci support VIRTIO_F_RING_RESET | expand |
On Mon, Feb 14, 2022 at 4:14 PM Xuan Zhuo <xuanzhuo@linux.alibaba.com> wrote: > > The purpose of this patch is to make vring packed support re-enable reset > vq. > > Based on whether the incoming vq passed by vring_setup_virtqueue() is > NULL or not, distinguish whether it is a normal create virtqueue or > re-enable a reset queue. > > When re-enable a reset queue, reuse the original callback, name, indirect. > > Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com> > --- > drivers/virtio/virtio_ring.c | 29 ++++++++++++++++++----------- > 1 file changed, 18 insertions(+), 11 deletions(-) > > diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c > index 4639e1643c78..20659f7ca582 100644 > --- a/drivers/virtio/virtio_ring.c > +++ b/drivers/virtio/virtio_ring.c > @@ -1683,7 +1683,8 @@ static struct virtqueue *vring_create_virtqueue_packed( > bool context, > bool (*notify)(struct virtqueue *), > void (*callback)(struct virtqueue *), > - const char *name) > + const char *name, > + struct virtqueue *_vq) > { > struct vring_virtqueue *vq; > struct vring_packed_desc *ring; > @@ -1713,13 +1714,20 @@ static struct virtqueue *vring_create_virtqueue_packed( > if (!device) > goto err_device; > > - vq = kmalloc(sizeof(*vq), GFP_KERNEL); > - if (!vq) > - goto err_vq; > + if (_vq) { > + vq = to_vvq(_vq); > + } else { > + vq = kmalloc(sizeof(*vq), GFP_KERNEL); > + if (!vq) > + goto err_vq; > + > + vq->vq.callback = callback; > + vq->vq.name = name; > + vq->indirect = virtio_has_feature(vdev, VIRTIO_RING_F_INDIRECT_DESC) && > + !context; > + } The code looks tricky. Except for the memory we don't even need to touch any of the other attributes. I'd suggest splitting out the vring allocation into a dedicated helper that could be called by both vring_create_queue_XXX and the enable() logic (and in the enable logic we don't even need to relocate if size is not changed). Thanks > > - vq->vq.callback = callback; > vq->vq.vdev = vdev; > - vq->vq.name = name; > vq->vq.num_free = num; > vq->vq.index = index; > vq->we_own_ring = true; > @@ -1736,8 +1744,6 @@ static struct virtqueue *vring_create_virtqueue_packed( > vq->last_add_time_valid = false; > #endif > > - vq->indirect = virtio_has_feature(vdev, VIRTIO_RING_F_INDIRECT_DESC) && > - !context; > vq->event = virtio_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX); > > if (virtio_has_feature(vdev, VIRTIO_F_ORDER_PLATFORM)) > @@ -1778,7 +1784,7 @@ static struct virtqueue *vring_create_virtqueue_packed( > goto err_desc_extra; > > /* No callback? Tell other side not to bother us. */ > - if (!callback) { > + if (!vq->vq.callback) { > vq->packed.event_flags_shadow = VRING_PACKED_EVENT_FLAG_DISABLE; > vq->packed.vring.driver->flags = > cpu_to_le16(vq->packed.event_flags_shadow); > @@ -1792,7 +1798,8 @@ static struct virtqueue *vring_create_virtqueue_packed( > err_desc_extra: > kfree(vq->packed.desc_state); > err_desc_state: > - kfree(vq); > + if (!_vq) > + kfree(vq); > err_vq: > vring_free_queue(vdev, event_size_in_bytes, device, device_event_dma_addr); > err_device: > @@ -2317,7 +2324,7 @@ struct virtqueue *vring_setup_virtqueue( > if (virtio_has_feature(vdev, VIRTIO_F_RING_PACKED)) > return vring_create_virtqueue_packed(index, num, vring_align, > vdev, weak_barriers, may_reduce_num, > - context, notify, callback, name); > + context, notify, callback, name, vq); > > return vring_create_virtqueue_split(index, num, vring_align, > vdev, weak_barriers, may_reduce_num, > -- > 2.31.0 >
diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c index 4639e1643c78..20659f7ca582 100644 --- a/drivers/virtio/virtio_ring.c +++ b/drivers/virtio/virtio_ring.c @@ -1683,7 +1683,8 @@ static struct virtqueue *vring_create_virtqueue_packed( bool context, bool (*notify)(struct virtqueue *), void (*callback)(struct virtqueue *), - const char *name) + const char *name, + struct virtqueue *_vq) { struct vring_virtqueue *vq; struct vring_packed_desc *ring; @@ -1713,13 +1714,20 @@ static struct virtqueue *vring_create_virtqueue_packed( if (!device) goto err_device; - vq = kmalloc(sizeof(*vq), GFP_KERNEL); - if (!vq) - goto err_vq; + if (_vq) { + vq = to_vvq(_vq); + } else { + vq = kmalloc(sizeof(*vq), GFP_KERNEL); + if (!vq) + goto err_vq; + + vq->vq.callback = callback; + vq->vq.name = name; + vq->indirect = virtio_has_feature(vdev, VIRTIO_RING_F_INDIRECT_DESC) && + !context; + } - vq->vq.callback = callback; vq->vq.vdev = vdev; - vq->vq.name = name; vq->vq.num_free = num; vq->vq.index = index; vq->we_own_ring = true; @@ -1736,8 +1744,6 @@ static struct virtqueue *vring_create_virtqueue_packed( vq->last_add_time_valid = false; #endif - vq->indirect = virtio_has_feature(vdev, VIRTIO_RING_F_INDIRECT_DESC) && - !context; vq->event = virtio_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX); if (virtio_has_feature(vdev, VIRTIO_F_ORDER_PLATFORM)) @@ -1778,7 +1784,7 @@ static struct virtqueue *vring_create_virtqueue_packed( goto err_desc_extra; /* No callback? Tell other side not to bother us. */ - if (!callback) { + if (!vq->vq.callback) { vq->packed.event_flags_shadow = VRING_PACKED_EVENT_FLAG_DISABLE; vq->packed.vring.driver->flags = cpu_to_le16(vq->packed.event_flags_shadow); @@ -1792,7 +1798,8 @@ static struct virtqueue *vring_create_virtqueue_packed( err_desc_extra: kfree(vq->packed.desc_state); err_desc_state: - kfree(vq); + if (!_vq) + kfree(vq); err_vq: vring_free_queue(vdev, event_size_in_bytes, device, device_event_dma_addr); err_device: @@ -2317,7 +2324,7 @@ struct virtqueue *vring_setup_virtqueue( if (virtio_has_feature(vdev, VIRTIO_F_RING_PACKED)) return vring_create_virtqueue_packed(index, num, vring_align, vdev, weak_barriers, may_reduce_num, - context, notify, callback, name); + context, notify, callback, name, vq); return vring_create_virtqueue_split(index, num, vring_align, vdev, weak_barriers, may_reduce_num,
The purpose of this patch is to make vring packed support re-enable reset vq. Based on whether the incoming vq passed by vring_setup_virtqueue() is NULL or not, distinguish whether it is a normal create virtqueue or re-enable a reset queue. When re-enable a reset queue, reuse the original callback, name, indirect. Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com> --- drivers/virtio/virtio_ring.c | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-)