anolis: virtio_ring: add split queue seq_printf interface

ANBZ: #19447

Provide ability for split virtqueue to show descriptors condition.
Pay attention to isolating concurrent access before call this function.

Signed-off-by: Ferry Meng <mengferry@linux.alibaba.com>
Acked-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
Reviewed-by: Jingbo Xu <jefflexu@linux.alibaba.com>
Reviewed-by: Joseph Qi <joseph.qi@linux.alibaba.com>
Link: https://gitee.com/anolis/cloud-kernel/pulls/4799
This commit is contained in:
Ferry Meng 2025-03-28 01:40:13 +08:00 committed by 小龙
parent a89d948c65
commit 13f314ec38
2 changed files with 99 additions and 0 deletions

View File

@ -14,6 +14,7 @@
#include <linux/moduleparam.h>
#include <xen/xen.h>
#include <linux/cc_platform.h>
#include <linux/seq_file.h>
static bool vring_force_dma_api;
@ -3461,4 +3462,101 @@ void virtqueue_dma_sync_single_range_for_device(struct virtqueue *_vq,
}
EXPORT_SYMBOL_GPL(virtqueue_dma_sync_single_range_for_device);
/**
* virtqueue_show_split_message - print split queue structure
* @_vq: the struct virtqueue we're talking about.
* @s: the struct seq_file
* Before calling this function, get lock to confirm that
* the virtqueue is not in use.
*/
void virtqueue_show_split_message(struct virtqueue *_vq, struct seq_file *s)
{
struct vring_virtqueue *vq = to_vvq(_vq);
struct vring_virtqueue_split *split = &vq->split;
u16 last_used_idx, used_idx, idx, idx_in_used_ring, flags;
struct vring_desc *desc;
int len, i;
last_used_idx = vq->last_used_idx;
used_idx = virtio16_to_cpu(vq->vq.vdev, split->vring.used->idx);
seq_printf(s, "Virtqueue %d (0x%px): num %d\n", _vq->index,
vq, split->vring.num);
seq_printf(s, "Descriptor Table: num_free %d, free_head %d\n",
_vq->num_free, vq->free_head);
seq_printf(s, "Available Ring: flags 0x%x, avail_idx %d\n",
split->avail_flags_shadow, split->vring.avail->idx);
seq_printf(s, "Used Ring: used %d, last_used_index %d\n",
used_idx, last_used_idx);
if (last_used_idx == used_idx)
goto out;
seq_puts(s, "---------- ---------------- -------\n");
seq_puts(s, "USED_INDEX DESC_TABLE_INDEX DRVDATA\n");
while (last_used_idx != used_idx) {
idx = last_used_idx & (split->vring.num - 1);
idx_in_used_ring = virtio32_to_cpu(vq->vq.vdev,
split->vring.used->ring[idx].id);
seq_printf(s, "%10d %16d 0x%px\n", idx, idx_in_used_ring,
split->desc_state[idx_in_used_ring].data);
last_used_idx++;
}
seq_puts(s, "---------- ---------------- -------\n");
last_used_idx = vq->last_used_idx;
while (last_used_idx != used_idx) {
idx = last_used_idx & (split->vring.num - 1);
idx_in_used_ring = virtio32_to_cpu(vq->vq.vdev,
split->vring.used->ring[idx].id);
if (!vq->indirect) {
seq_printf(s, "Direct desc[%d]\n", idx_in_used_ring);
i = idx_in_used_ring;
do {
desc = &split->vring.desc[i];
flags = virtio16_to_cpu(vq->vq.vdev, desc->flags);
seq_printf(s, " desc[%d] ", i);
seq_printf(s, "dma_addr=0x%-16llx ",
virtio64_to_cpu(vq->vq.vdev, desc->addr));
seq_printf(s, "flags=0x%-4x ", flags);
seq_printf(s, "len=%-8d ",
virtio32_to_cpu(vq->vq.vdev, desc->len));
seq_printf(s, "next=%-4d\n",
virtio16_to_cpu(vq->vq.vdev, desc->next));
i = desc->next;
} while (flags & VRING_DESC_F_NEXT);
} else {
desc = &split->vring.desc[idx_in_used_ring];
len = split->desc_extra[idx_in_used_ring].len;
seq_printf(s, "P{0x%px} desc[%d]", desc, idx_in_used_ring);
seq_printf(s, "dma_addr=0x%-16llx len=%-8d\n",
virtio64_to_cpu(vq->vq.vdev, desc[i].addr),
virtio32_to_cpu(vq->vq.vdev, desc[i].len));
/* print indir_descs */
desc = split->desc_state[idx_in_used_ring].indir_desc;
for (i = 0; i < len / sizeof(struct vring_desc); i++) {
seq_printf(s, " indir_desc[%d] ", i);
seq_printf(s, "dma_addr=0x%-16llx ",
virtio64_to_cpu(vq->vq.vdev, desc[i].addr));
seq_printf(s, "flags=0x%-4x ",
virtio16_to_cpu(vq->vq.vdev, desc[i].flags));
seq_printf(s, "len=%-8d ",
virtio32_to_cpu(vq->vq.vdev, desc[i].len));
seq_printf(s, "next=%-4d\n",
virtio16_to_cpu(vq->vq.vdev, desc[i].next));
}
}
last_used_idx++;
}
out:
seq_puts(s, "=======================================\n");
return;
}
EXPORT_SYMBOL_GPL(virtqueue_show_split_message);
MODULE_LICENSE("GPL");

View File

@ -242,4 +242,5 @@ void virtqueue_dma_sync_single_range_for_cpu(struct virtqueue *_vq, dma_addr_t a
void virtqueue_dma_sync_single_range_for_device(struct virtqueue *_vq, dma_addr_t addr,
unsigned long offset, size_t size,
enum dma_data_direction dir);
void virtqueue_show_split_message(struct virtqueue *_vq, struct seq_file *s);
#endif /* _LINUX_VIRTIO_H */