Commit f51e146f authored by Yishai Hadas's avatar Yishai Hadas Committed by Alex Williamson

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: default avatarFeng Liu <feliu@nvidia.com>
Acked-by: default avatarMichael S. Tsirkin <mst@redhat.com>
Signed-off-by: default avatarYishai Hadas <yishaih@nvidia.com>
Link: https://lore.kernel.org/r/20231219093247.170936-6-yishaih@nvidia.comSigned-off-by: default avatarAlex Williamson <alex.williamson@redhat.com>
parent 388431b9
...@@ -60,6 +60,11 @@ config VIRTIO_PCI ...@@ -60,6 +60,11 @@ config VIRTIO_PCI
If unsure, say M. If unsure, say M.
config VIRTIO_PCI_ADMIN_LEGACY
bool
depends on VIRTIO_PCI && (X86 || COMPILE_TEST)
default y
config VIRTIO_PCI_LEGACY config VIRTIO_PCI_LEGACY
bool "Support for legacy virtio draft 0.9.X and older devices" bool "Support for legacy virtio draft 0.9.X and older devices"
default y default y
......
...@@ -47,6 +47,7 @@ struct virtio_pci_admin_vq { ...@@ -47,6 +47,7 @@ struct virtio_pci_admin_vq {
struct virtio_pci_vq_info info; struct virtio_pci_vq_info info;
/* serializing admin commands execution and virtqueue deletion */ /* serializing admin commands execution and virtqueue deletion */
struct mutex cmd_lock; struct mutex cmd_lock;
u64 supported_cmds;
/* Name of the admin queue: avq.$vq_index. */ /* Name of the admin queue: avq.$vq_index. */
char name[10]; char name[10];
u16 vq_index; u16 vq_index;
...@@ -155,6 +156,24 @@ static inline void virtio_pci_legacy_remove(struct virtio_pci_device *vp_dev) ...@@ -155,6 +156,24 @@ static inline void virtio_pci_legacy_remove(struct virtio_pci_device *vp_dev)
int virtio_pci_modern_probe(struct virtio_pci_device *); int virtio_pci_modern_probe(struct virtio_pci_device *);
void virtio_pci_modern_remove(struct virtio_pci_device *); void virtio_pci_modern_remove(struct virtio_pci_device *);
#define VIRTIO_LEGACY_ADMIN_CMD_BITMAP \
(BIT_ULL(VIRTIO_ADMIN_CMD_LEGACY_COMMON_CFG_WRITE) | \
BIT_ULL(VIRTIO_ADMIN_CMD_LEGACY_COMMON_CFG_READ) | \
BIT_ULL(VIRTIO_ADMIN_CMD_LEGACY_DEV_CFG_WRITE) | \
BIT_ULL(VIRTIO_ADMIN_CMD_LEGACY_DEV_CFG_READ) | \
BIT_ULL(VIRTIO_ADMIN_CMD_LEGACY_NOTIFY_INFO))
/* Unlike modern drivers which support hardware virtio devices, legacy drivers
* assume software-based devices: e.g. they don't use proper memory barriers
* on ARM, use big endian on PPC, etc. X86 drivers are mostly ok though, more
* or less by chance. For now, only support legacy IO on X86.
*/
#ifdef CONFIG_VIRTIO_PCI_ADMIN_LEGACY
#define VIRTIO_ADMIN_CMD_BITMAP VIRTIO_LEGACY_ADMIN_CMD_BITMAP
#else
#define VIRTIO_ADMIN_CMD_BITMAP 0
#endif
int vp_modern_admin_cmd_exec(struct virtio_device *vdev, int vp_modern_admin_cmd_exec(struct virtio_device *vdev,
struct virtio_admin_cmd *cmd); struct virtio_admin_cmd *cmd);
......
...@@ -39,6 +39,7 @@ static bool vp_is_avq(struct virtio_device *vdev, unsigned int index) ...@@ -39,6 +39,7 @@ static bool vp_is_avq(struct virtio_device *vdev, unsigned int index)
} }
static int virtqueue_exec_admin_cmd(struct virtio_pci_admin_vq *admin_vq, static int virtqueue_exec_admin_cmd(struct virtio_pci_admin_vq *admin_vq,
u16 opcode,
struct scatterlist **sgs, struct scatterlist **sgs,
unsigned int out_num, unsigned int out_num,
unsigned int in_num, unsigned int in_num,
...@@ -51,6 +52,11 @@ static int virtqueue_exec_admin_cmd(struct virtio_pci_admin_vq *admin_vq, ...@@ -51,6 +52,11 @@ static int virtqueue_exec_admin_cmd(struct virtio_pci_admin_vq *admin_vq,
if (!vq) if (!vq)
return -EIO; return -EIO;
if (opcode != VIRTIO_ADMIN_CMD_LIST_QUERY &&
opcode != VIRTIO_ADMIN_CMD_LIST_USE &&
!((1ULL << opcode) & admin_vq->supported_cmds))
return -EOPNOTSUPP;
ret = virtqueue_add_sgs(vq, sgs, out_num, in_num, data, GFP_KERNEL); ret = virtqueue_add_sgs(vq, sgs, out_num, in_num, data, GFP_KERNEL);
if (ret < 0) if (ret < 0)
return -EIO; return -EIO;
...@@ -117,8 +123,9 @@ int vp_modern_admin_cmd_exec(struct virtio_device *vdev, ...@@ -117,8 +123,9 @@ int vp_modern_admin_cmd_exec(struct virtio_device *vdev,
} }
mutex_lock(&vp_dev->admin_vq.cmd_lock); mutex_lock(&vp_dev->admin_vq.cmd_lock);
ret = virtqueue_exec_admin_cmd(&vp_dev->admin_vq, sgs, ret = virtqueue_exec_admin_cmd(&vp_dev->admin_vq,
out_num, in_num, sgs); le16_to_cpu(cmd->opcode),
sgs, out_num, in_num, sgs);
mutex_unlock(&vp_dev->admin_vq.cmd_lock); mutex_unlock(&vp_dev->admin_vq.cmd_lock);
if (ret) { if (ret) {
...@@ -142,6 +149,43 @@ int vp_modern_admin_cmd_exec(struct virtio_device *vdev, ...@@ -142,6 +149,43 @@ int vp_modern_admin_cmd_exec(struct virtio_device *vdev,
return ret; return ret;
} }
static void virtio_pci_admin_cmd_list_init(struct virtio_device *virtio_dev)
{
struct virtio_pci_device *vp_dev = to_vp_device(virtio_dev);
struct virtio_admin_cmd cmd = {};
struct scatterlist result_sg;
struct scatterlist data_sg;
__le64 *data;
int ret;
data = kzalloc(sizeof(*data), GFP_KERNEL);
if (!data)
return;
sg_init_one(&result_sg, data, sizeof(*data));
cmd.opcode = cpu_to_le16(VIRTIO_ADMIN_CMD_LIST_QUERY);
cmd.group_type = cpu_to_le16(VIRTIO_ADMIN_GROUP_TYPE_SRIOV);
cmd.result_sg = &result_sg;
ret = vp_modern_admin_cmd_exec(virtio_dev, &cmd);
if (ret)
goto end;
*data &= cpu_to_le64(VIRTIO_ADMIN_CMD_BITMAP);
sg_init_one(&data_sg, data, sizeof(*data));
cmd.opcode = cpu_to_le16(VIRTIO_ADMIN_CMD_LIST_USE);
cmd.data_sg = &data_sg;
cmd.result_sg = NULL;
ret = vp_modern_admin_cmd_exec(virtio_dev, &cmd);
if (ret)
goto end;
vp_dev->admin_vq.supported_cmds = le64_to_cpu(*data);
end:
kfree(data);
}
static void vp_modern_avq_activate(struct virtio_device *vdev) static void vp_modern_avq_activate(struct virtio_device *vdev)
{ {
struct virtio_pci_device *vp_dev = to_vp_device(vdev); struct virtio_pci_device *vp_dev = to_vp_device(vdev);
...@@ -151,6 +195,7 @@ static void vp_modern_avq_activate(struct virtio_device *vdev) ...@@ -151,6 +195,7 @@ static void vp_modern_avq_activate(struct virtio_device *vdev)
return; return;
__virtqueue_unbreak(admin_vq->info.vq); __virtqueue_unbreak(admin_vq->info.vq);
virtio_pci_admin_cmd_list_init(vdev);
} }
static void vp_modern_avq_deactivate(struct virtio_device *vdev) static void vp_modern_avq_deactivate(struct virtio_device *vdev)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment