In preparation to support VIRTIO_F_DMB, read the two registers a device uses to describe its Device Memory Buffer. Both are read-only le16 fields at the end of the common configuration structure. dmb_shm_id names the VIRTIO_PCI_CAP_SHARED_MEMORY_CFG capability that virtio_pci_find_shm_cap() has to find to map the region, and is valid once the feature is negotiated. dmb_mem_type describes the memory the region is made of: VIRTIO_DMB_MEM_TYPE_COHERENT means a write by either side becomes visible to the other with no cache maintenance by the driver. It is valid as soon as the device offers the feature, so a driver that does not support the value it reads can decline the offer instead of failing the device afterwards.
Add both fields, VIRTIO_PCI_COMMON_DMB_SHM_ID and VIRTIO_PCI_COMMON_DMB_MEM_TYPE for the offsets check_offsets() asserts them against, and vp_modern_get_dmb_shm_id() and vp_modern_get_dmb_mem_type() to read them. vp_modern_probe() capped the common cfg mapping at the end of admin_queue_num, exactly where dmb_shm_id starts, so extend it to the end of dmb_mem_type. vp_modern_map_capability() takes that as an upper bound, so a device with a shorter common cfg maps what it has and mdev->common_len records how much. Link: https://lore.kernel.org/virtio-comment/[email protected]/ Assisted-by: Kiro:claude-opus-5 checkpatch sparse Signed-off-by: Alexander Graf <[email protected]> --- drivers/virtio/virtio_pci_modern_dev.c | 47 +++++++++++++++++++++++++- include/linux/virtio_pci_modern.h | 2 ++ include/uapi/linux/virtio_pci.h | 19 +++++++++++ 3 files changed, 67 insertions(+), 1 deletion(-) diff --git a/drivers/virtio/virtio_pci_modern_dev.c b/drivers/virtio/virtio_pci_modern_dev.c index 413a8c353463..270c67fe58ff 100644 --- a/drivers/virtio/virtio_pci_modern_dev.c +++ b/drivers/virtio/virtio_pci_modern_dev.c @@ -211,6 +211,10 @@ static inline void check_offsets(void) offsetof(struct virtio_pci_modern_common_cfg, admin_queue_index)); BUILD_BUG_ON(VIRTIO_PCI_COMMON_ADM_Q_NUM != offsetof(struct virtio_pci_modern_common_cfg, admin_queue_num)); + BUILD_BUG_ON(VIRTIO_PCI_COMMON_DMB_SHM_ID != + offsetof(struct virtio_pci_modern_common_cfg, dmb_shm_id)); + BUILD_BUG_ON(VIRTIO_PCI_COMMON_DMB_MEM_TYPE != + offsetof(struct virtio_pci_modern_common_cfg, dmb_mem_type)); } /* @@ -300,7 +304,7 @@ int vp_modern_probe(struct virtio_pci_modern_device *mdev) mdev->common = vp_modern_map_capability(mdev, common, sizeof(struct virtio_pci_common_cfg), 4, 0, offsetofend(struct virtio_pci_modern_common_cfg, - admin_queue_num), + dmb_mem_type), &mdev->common_len, NULL); if (!mdev->common) goto err_map_common; @@ -752,6 +756,47 @@ u16 vp_modern_avq_index(struct virtio_pci_modern_device *mdev) } EXPORT_SYMBOL_GPL(vp_modern_avq_index); +/* + * vp_modern_get_dmb_shm_id - read the Device Memory Buffer shared memory id + * @mdev: the modern virtio-pci device + * + * The value identifies the VIRTIO_PCI_CAP_SHARED_MEMORY_CFG capability that + * describes the Device Memory Buffer region. Only valid once VIRTIO_F_DMB + * has been negotiated, and the caller has to have established that the common + * configuration structure is long enough to hold the field. + * + * Returns the shared memory id. + */ +u16 vp_modern_get_dmb_shm_id(struct virtio_pci_modern_device *mdev) +{ + struct virtio_pci_modern_common_cfg __iomem *cfg; + + cfg = (struct virtio_pci_modern_common_cfg __iomem *)mdev->common; + return vp_ioread16(&cfg->dmb_shm_id); +} +EXPORT_SYMBOL_GPL(vp_modern_get_dmb_shm_id); + +/* + * vp_modern_get_dmb_mem_type - read the Device Memory Buffer memory type + * @mdev: the modern virtio-pci device + * + * The value describes the memory the Device Memory Buffer region is made of. + * VIRTIO_DMB_MEM_TYPE_COHERENT means the region is cache coherent. Valid + * whenever the device offers VIRTIO_F_DMB, and the caller has to have + * established that the common configuration structure is long enough to hold + * the field. + * + * Returns the memory type. + */ +u16 vp_modern_get_dmb_mem_type(struct virtio_pci_modern_device *mdev) +{ + struct virtio_pci_modern_common_cfg __iomem *cfg; + + cfg = (struct virtio_pci_modern_common_cfg __iomem *)mdev->common; + return vp_ioread16(&cfg->dmb_mem_type); +} +EXPORT_SYMBOL_GPL(vp_modern_get_dmb_mem_type); + MODULE_VERSION("0.1"); MODULE_DESCRIPTION("Modern Virtio PCI Device"); MODULE_AUTHOR("Jason Wang <[email protected]>"); diff --git a/include/linux/virtio_pci_modern.h b/include/linux/virtio_pci_modern.h index 9a3f2fc53bd6..80643c895495 100644 --- a/include/linux/virtio_pci_modern.h +++ b/include/linux/virtio_pci_modern.h @@ -162,4 +162,6 @@ int vp_modern_get_queue_reset(struct virtio_pci_modern_device *mdev, u16 index); void vp_modern_set_queue_reset(struct virtio_pci_modern_device *mdev, u16 index); u16 vp_modern_avq_num(struct virtio_pci_modern_device *mdev); u16 vp_modern_avq_index(struct virtio_pci_modern_device *mdev); +u16 vp_modern_get_dmb_shm_id(struct virtio_pci_modern_device *mdev); +u16 vp_modern_get_dmb_mem_type(struct virtio_pci_modern_device *mdev); #endif diff --git a/include/uapi/linux/virtio_pci.h b/include/uapi/linux/virtio_pci.h index e732e3456e27..1bd2bb981dc9 100644 --- a/include/uapi/linux/virtio_pci.h +++ b/include/uapi/linux/virtio_pci.h @@ -193,6 +193,23 @@ struct virtio_pci_modern_common_cfg { __le16 admin_queue_index; /* read-only */ __le16 admin_queue_num; /* read-only */ + + /* + * Reports the shmid of the Device Memory Buffer region. Valid once + * VIRTIO_F_DMB has been negotiated. + */ + __le16 dmb_shm_id; /* read-only */ + + /* + * Reports the memory type of the Device Memory Buffer region. + * VIRTIO_DMB_MEM_TYPE_COHERENT means the region is cache coherent: a + * write by either side becomes visible to the other with no cache + * maintenance by the driver. Every other value is reserved, and a + * driver must not accept VIRTIO_F_DMB unless the value is one it + * supports. Valid whenever the device offers VIRTIO_F_DMB, so that a + * driver can read it before it accepts. + */ + __le16 dmb_mem_type; /* read-only */ }; /* Fields in VIRTIO_PCI_CAP_PCI_CFG: */ @@ -235,6 +252,8 @@ struct virtio_pci_cfg_cap { #define VIRTIO_PCI_COMMON_Q_RESET 58 #define VIRTIO_PCI_COMMON_ADM_Q_IDX 60 #define VIRTIO_PCI_COMMON_ADM_Q_NUM 62 +#define VIRTIO_PCI_COMMON_DMB_SHM_ID 64 +#define VIRTIO_PCI_COMMON_DMB_MEM_TYPE 66 #endif /* VIRTIO_PCI_NO_MODERN */

