Now, inside virtqueue_disable_and_recycle, the recycle() just has two parameters(vq, buf) after detach operate. But if we are in premapped mode, we may need to get some dma info when detach buf like virtqueue_get_buf_ctx_dma(). So we call recycle directly, this callback detaches bufs self. It should complete the work of detaching all the unused buffers. Signed-off-by: Xuan Zhuo <xuanzhuo@xxxxxxxxxxxxxxxxx> --- drivers/net/virtio/main.c | 31 ++++++++++++++++++++++--------- drivers/virtio/virtio_ring.c | 10 ++++------ include/linux/virtio.h | 4 ++-- 3 files changed, 28 insertions(+), 17 deletions(-) diff --git a/drivers/net/virtio/main.c b/drivers/net/virtio/main.c index 0037c0bda0c1..d81ee75142e0 100644 --- a/drivers/net/virtio/main.c +++ b/drivers/net/virtio/main.c @@ -149,8 +149,8 @@ struct virtio_net_common_hdr { }; }; -static void virtnet_rq_free_unused_buf(struct virtqueue *vq, void *buf); -static void virtnet_sq_free_unused_buf(struct virtqueue *vq, void *buf); +static void virtnet_rq_free_unused_bufs(struct virtqueue *vq); +static void virtnet_sq_free_unused_bufs(struct virtqueue *vq); static bool is_xdp_frame(void *ptr) { @@ -2197,7 +2197,7 @@ static int virtnet_rx_resize(struct virtnet_info *vi, if (running) napi_disable(&rq->napi); - err = virtqueue_resize(rq->vq, ring_num, virtnet_rq_free_unused_buf); + err = virtqueue_resize(rq->vq, ring_num, virtnet_rq_free_unused_bufs); if (err) netdev_err(vi->dev, "resize rx fail: rx queue index: %d err: %d\n", qindex, err); @@ -2236,7 +2236,7 @@ static int virtnet_tx_resize(struct virtnet_info *vi, __netif_tx_unlock_bh(txq); - err = virtqueue_resize(sq->vq, ring_num, virtnet_sq_free_unused_buf); + err = virtqueue_resize(sq->vq, ring_num, virtnet_sq_free_unused_bufs); if (err) netdev_err(vi->dev, "resize tx fail: tx queue index: %d err: %d\n", qindex, err); @@ -3850,22 +3850,35 @@ static void virtnet_rq_free_unused_buf(struct virtqueue *vq, void *buf) virtnet_rq_free_buf(vi, rq, buf); } -static void free_unused_bufs(struct virtnet_info *vi) +static void virtnet_sq_free_unused_bufs(struct virtqueue *vq) +{ + void *buf; + + while ((buf = virtqueue_detach_unused_buf(vq)) != NULL) + virtnet_sq_free_unused_buf(vq, buf); +} + +static void virtnet_rq_free_unused_bufs(struct virtqueue *vq) { void *buf; + + while ((buf = virtqueue_detach_unused_buf(vq)) != NULL) + virtnet_rq_free_unused_buf(vq, buf); +} + +static void free_unused_bufs(struct virtnet_info *vi) +{ int i; for (i = 0; i < vi->max_queue_pairs; i++) { struct virtqueue *vq = vi->sq[i].vq; - while ((buf = virtqueue_detach_unused_buf(vq)) != NULL) - virtnet_sq_free_unused_buf(vq, buf); + virtnet_sq_free_unused_bufs(vq); cond_resched(); } for (i = 0; i < vi->max_queue_pairs; i++) { struct virtqueue *vq = vi->rq[i].vq; - while ((buf = virtqueue_detach_unused_buf(vq)) != NULL) - virtnet_rq_free_unused_buf(vq, buf); + virtnet_rq_free_unused_bufs(vq); cond_resched(); } } diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c index 3bcf3e6067af..42d28bee1294 100644 --- a/drivers/virtio/virtio_ring.c +++ b/drivers/virtio/virtio_ring.c @@ -2194,11 +2194,10 @@ static int virtqueue_resize_packed(struct virtqueue *_vq, u32 num) } static int virtqueue_disable_and_recycle(struct virtqueue *_vq, - void (*recycle)(struct virtqueue *vq, void *buf)) + void (*recycle)(struct virtqueue *vq)) { struct vring_virtqueue *vq = to_vvq(_vq); struct virtio_device *vdev = vq->vq.vdev; - void *buf; int err; if (!vq->we_own_ring) @@ -2214,8 +2213,7 @@ static int virtqueue_disable_and_recycle(struct virtqueue *_vq, if (err) return err; - while ((buf = virtqueue_detach_unused_buf(_vq)) != NULL) - recycle(_vq, buf); + recycle(_vq); return 0; } @@ -2810,7 +2808,7 @@ EXPORT_SYMBOL_GPL(vring_create_virtqueue_dma); * */ int virtqueue_resize(struct virtqueue *_vq, u32 num, - void (*recycle)(struct virtqueue *vq, void *buf)) + void (*recycle)(struct virtqueue *vq)) { struct vring_virtqueue *vq = to_vvq(_vq); int err; @@ -2901,7 +2899,7 @@ EXPORT_SYMBOL_GPL(virtqueue_set_dma_premapped); * -EPERM: Operation not permitted */ int virtqueue_reset(struct virtqueue *_vq, - void (*recycle)(struct virtqueue *vq, void *buf)) + void (*recycle)(struct virtqueue *vq)) { struct vring_virtqueue *vq = to_vvq(_vq); int err; diff --git a/include/linux/virtio.h b/include/linux/virtio.h index 572aecec205b..7a5e9ea7d420 100644 --- a/include/linux/virtio.h +++ b/include/linux/virtio.h @@ -115,9 +115,9 @@ dma_addr_t virtqueue_get_avail_addr(const struct virtqueue *vq); dma_addr_t virtqueue_get_used_addr(const struct virtqueue *vq); int virtqueue_resize(struct virtqueue *vq, u32 num, - void (*recycle)(struct virtqueue *vq, void *buf)); + void (*recycle)(struct virtqueue *vq)); int virtqueue_reset(struct virtqueue *vq, - void (*recycle)(struct virtqueue *vq, void *buf)); + void (*recycle)(struct virtqueue *vq)); /** * struct virtio_device - representation of a device using virtio -- 2.32.0.3.g01195cf9f