Skip to content

Commit f51e146

Browse files
yishaihAlex Williamson
authored andcommitted
virtio-pci: Initialize the supported admin commands
Initialize the supported admin commands upon activating the admin queue. The supported commands are saved as part of the admin queue context. Next patches in this series will expose APIs to use them. Reviewed-by: Feng Liu <feliu@nvidia.com> Acked-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Yishai Hadas <yishaih@nvidia.com> Link: https://lore.kernel.org/r/20231219093247.170936-6-yishaih@nvidia.com Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
1 parent 388431b commit f51e146

3 files changed

Lines changed: 71 additions & 2 deletions

File tree

drivers/virtio/Kconfig

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,11 @@ config VIRTIO_PCI
6060

6161
If unsure, say M.
6262

63+
config VIRTIO_PCI_ADMIN_LEGACY
64+
bool
65+
depends on VIRTIO_PCI && (X86 || COMPILE_TEST)
66+
default y
67+
6368
config VIRTIO_PCI_LEGACY
6469
bool "Support for legacy virtio draft 0.9.X and older devices"
6570
default y

drivers/virtio/virtio_pci_common.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ struct virtio_pci_admin_vq {
4747
struct virtio_pci_vq_info info;
4848
/* serializing admin commands execution and virtqueue deletion */
4949
struct mutex cmd_lock;
50+
u64 supported_cmds;
5051
/* Name of the admin queue: avq.$vq_index. */
5152
char name[10];
5253
u16 vq_index;
@@ -155,6 +156,24 @@ static inline void virtio_pci_legacy_remove(struct virtio_pci_device *vp_dev)
155156
int virtio_pci_modern_probe(struct virtio_pci_device *);
156157
void virtio_pci_modern_remove(struct virtio_pci_device *);
157158

159+
#define VIRTIO_LEGACY_ADMIN_CMD_BITMAP \
160+
(BIT_ULL(VIRTIO_ADMIN_CMD_LEGACY_COMMON_CFG_WRITE) | \
161+
BIT_ULL(VIRTIO_ADMIN_CMD_LEGACY_COMMON_CFG_READ) | \
162+
BIT_ULL(VIRTIO_ADMIN_CMD_LEGACY_DEV_CFG_WRITE) | \
163+
BIT_ULL(VIRTIO_ADMIN_CMD_LEGACY_DEV_CFG_READ) | \
164+
BIT_ULL(VIRTIO_ADMIN_CMD_LEGACY_NOTIFY_INFO))
165+
166+
/* Unlike modern drivers which support hardware virtio devices, legacy drivers
167+
* assume software-based devices: e.g. they don't use proper memory barriers
168+
* on ARM, use big endian on PPC, etc. X86 drivers are mostly ok though, more
169+
* or less by chance. For now, only support legacy IO on X86.
170+
*/
171+
#ifdef CONFIG_VIRTIO_PCI_ADMIN_LEGACY
172+
#define VIRTIO_ADMIN_CMD_BITMAP VIRTIO_LEGACY_ADMIN_CMD_BITMAP
173+
#else
174+
#define VIRTIO_ADMIN_CMD_BITMAP 0
175+
#endif
176+
158177
int vp_modern_admin_cmd_exec(struct virtio_device *vdev,
159178
struct virtio_admin_cmd *cmd);
160179

drivers/virtio/virtio_pci_modern.c

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ static bool vp_is_avq(struct virtio_device *vdev, unsigned int index)
3939
}
4040

4141
static int virtqueue_exec_admin_cmd(struct virtio_pci_admin_vq *admin_vq,
42+
u16 opcode,
4243
struct scatterlist **sgs,
4344
unsigned int out_num,
4445
unsigned int in_num,
@@ -51,6 +52,11 @@ static int virtqueue_exec_admin_cmd(struct virtio_pci_admin_vq *admin_vq,
5152
if (!vq)
5253
return -EIO;
5354

55+
if (opcode != VIRTIO_ADMIN_CMD_LIST_QUERY &&
56+
opcode != VIRTIO_ADMIN_CMD_LIST_USE &&
57+
!((1ULL << opcode) & admin_vq->supported_cmds))
58+
return -EOPNOTSUPP;
59+
5460
ret = virtqueue_add_sgs(vq, sgs, out_num, in_num, data, GFP_KERNEL);
5561
if (ret < 0)
5662
return -EIO;
@@ -117,8 +123,9 @@ int vp_modern_admin_cmd_exec(struct virtio_device *vdev,
117123
}
118124

119125
mutex_lock(&vp_dev->admin_vq.cmd_lock);
120-
ret = virtqueue_exec_admin_cmd(&vp_dev->admin_vq, sgs,
121-
out_num, in_num, sgs);
126+
ret = virtqueue_exec_admin_cmd(&vp_dev->admin_vq,
127+
le16_to_cpu(cmd->opcode),
128+
sgs, out_num, in_num, sgs);
122129
mutex_unlock(&vp_dev->admin_vq.cmd_lock);
123130

124131
if (ret) {
@@ -142,6 +149,43 @@ int vp_modern_admin_cmd_exec(struct virtio_device *vdev,
142149
return ret;
143150
}
144151

152+
static void virtio_pci_admin_cmd_list_init(struct virtio_device *virtio_dev)
153+
{
154+
struct virtio_pci_device *vp_dev = to_vp_device(virtio_dev);
155+
struct virtio_admin_cmd cmd = {};
156+
struct scatterlist result_sg;
157+
struct scatterlist data_sg;
158+
__le64 *data;
159+
int ret;
160+
161+
data = kzalloc(sizeof(*data), GFP_KERNEL);
162+
if (!data)
163+
return;
164+
165+
sg_init_one(&result_sg, data, sizeof(*data));
166+
cmd.opcode = cpu_to_le16(VIRTIO_ADMIN_CMD_LIST_QUERY);
167+
cmd.group_type = cpu_to_le16(VIRTIO_ADMIN_GROUP_TYPE_SRIOV);
168+
cmd.result_sg = &result_sg;
169+
170+
ret = vp_modern_admin_cmd_exec(virtio_dev, &cmd);
171+
if (ret)
172+
goto end;
173+
174+
*data &= cpu_to_le64(VIRTIO_ADMIN_CMD_BITMAP);
175+
sg_init_one(&data_sg, data, sizeof(*data));
176+
cmd.opcode = cpu_to_le16(VIRTIO_ADMIN_CMD_LIST_USE);
177+
cmd.data_sg = &data_sg;
178+
cmd.result_sg = NULL;
179+
180+
ret = vp_modern_admin_cmd_exec(virtio_dev, &cmd);
181+
if (ret)
182+
goto end;
183+
184+
vp_dev->admin_vq.supported_cmds = le64_to_cpu(*data);
185+
end:
186+
kfree(data);
187+
}
188+
145189
static void vp_modern_avq_activate(struct virtio_device *vdev)
146190
{
147191
struct virtio_pci_device *vp_dev = to_vp_device(vdev);
@@ -151,6 +195,7 @@ static void vp_modern_avq_activate(struct virtio_device *vdev)
151195
return;
152196

153197
__virtqueue_unbreak(admin_vq->info.vq);
198+
virtio_pci_admin_cmd_list_init(vdev);
154199
}
155200

156201
static void vp_modern_avq_deactivate(struct virtio_device *vdev)

0 commit comments

Comments
 (0)