]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blobdiff - include/linux/virtio_config.h
Merge tag 'x86-urgent-2020-08-30' of git://git.kernel.org/pub/scm/linux/kernel/git...
[mirror_ubuntu-jammy-kernel.git] / include / linux / virtio_config.h
index 441fd6dd42ab1bd949cf5c41a343ecc415d1d3c9..8fe857e27ef32a2aab464fb437e93f3e320a8726 100644 (file)
@@ -293,19 +293,7 @@ static inline __virtio64 cpu_to_virtio64(struct virtio_device *vdev, u64 val)
                __u8: (x), \
                __virtio16: virtio16_to_cpu((vdev), (x)), \
                __virtio32: virtio32_to_cpu((vdev), (x)), \
-               __virtio64: virtio64_to_cpu((vdev), (x)), \
-               /*
-                * Why define a default? checker can distinguish between
-                * e.g. __u16, __le16 and __virtio16, but GCC can't so
-                * attempts to define variants for both look like a duplicate
-                * variant to it.
-                */ \
-               default: _Generic((x), \
-                                __u8: (x), \
-                                __le16: virtio16_to_cpu((vdev), (__force __virtio16)(x)), \
-                                __le32: virtio32_to_cpu((vdev), (__force __virtio32)(x)), \
-                                __le64: virtio64_to_cpu((vdev), (__force __virtio64)(x)) \
-                                ) \
+               __virtio64: virtio64_to_cpu((vdev), (x)) \
                )
 
 #define cpu_to_virtio(vdev, x, m) \
@@ -313,19 +301,7 @@ static inline __virtio64 cpu_to_virtio64(struct virtio_device *vdev, u64 val)
                __u8: (x), \
                __virtio16: cpu_to_virtio16((vdev), (x)), \
                __virtio32: cpu_to_virtio32((vdev), (x)), \
-               __virtio64: cpu_to_virtio64((vdev), (x)), \
-               /*
-                * Why define a default? checker can distinguish between
-                * e.g. __u16, __le16 and __virtio16, but GCC can't so
-                * attempts to define variants for both look like a duplicate
-                * variant to it.
-                */ \
-               default: _Generic((m), \
-                                __u8: (x), \
-                                __le16: (__force __le16)cpu_to_virtio16((vdev), (x)), \
-                                __le32: (__force __le32)cpu_to_virtio32((vdev), (x)), \
-                                __le64: (__force __le64)cpu_to_virtio64((vdev), (x)) \
-                                ) \
+               __virtio64: cpu_to_virtio64((vdev), (x)) \
                )
 
 #define __virtio_native_type(structname, member) \
@@ -375,6 +351,70 @@ static inline __virtio64 cpu_to_virtio64(struct virtio_device *vdev, u64 val)
                                  sizeof(virtio_cwrite_v));             \
        } while(0)
 
+/*
+ * Nothing virtio-specific about these, but let's worry about generalizing
+ * these later.
+ */
+#define virtio_le_to_cpu(x) \
+       _Generic((x), \
+               __u8: (u8)(x), \
+                __le16: (u16)le16_to_cpu(x), \
+                __le32: (u32)le32_to_cpu(x), \
+                __le64: (u64)le64_to_cpu(x) \
+               )
+
+#define virtio_cpu_to_le(x, m) \
+       _Generic((m), \
+                __u8: (x), \
+                __le16: cpu_to_le16(x), \
+                __le32: cpu_to_le32(x), \
+                __le64: cpu_to_le64(x) \
+               )
+
+/* LE (e.g. modern) Config space accessors. */
+#define virtio_cread_le(vdev, structname, member, ptr)                 \
+       do {                                                            \
+               typeof(((structname*)0)->member) virtio_cread_v;        \
+                                                                       \
+               might_sleep();                                          \
+               /* Sanity check: must match the member's type */        \
+               typecheck(typeof(virtio_le_to_cpu(virtio_cread_v)), *(ptr)); \
+                                                                       \
+               switch (sizeof(virtio_cread_v)) {                       \
+               case 1:                                                 \
+               case 2:                                                 \
+               case 4:                                                 \
+                       vdev->config->get((vdev),                       \
+                                         offsetof(structname, member), \
+                                         &virtio_cread_v,              \
+                                         sizeof(virtio_cread_v));      \
+                       break;                                          \
+               default:                                                \
+                       __virtio_cread_many((vdev),                     \
+                                         offsetof(structname, member), \
+                                         &virtio_cread_v,              \
+                                         1,                            \
+                                         sizeof(virtio_cread_v));      \
+                       break;                                          \
+               }                                                       \
+               *(ptr) = virtio_le_to_cpu(virtio_cread_v);              \
+       } while(0)
+
+#define virtio_cwrite_le(vdev, structname, member, ptr)                        \
+       do {                                                            \
+               typeof(((structname*)0)->member) virtio_cwrite_v =      \
+                       virtio_cpu_to_le(*(ptr), ((structname*)0)->member); \
+                                                                       \
+               might_sleep();                                          \
+               /* Sanity check: must match the member's type */        \
+               typecheck(typeof(virtio_le_to_cpu(virtio_cwrite_v)), *(ptr)); \
+                                                                       \
+               vdev->config->set((vdev), offsetof(structname, member), \
+                                 &virtio_cwrite_v,                     \
+                                 sizeof(virtio_cwrite_v));             \
+       } while(0)
+
+
 /* Read @count fields, @bytes each. */
 static inline void __virtio_cread_many(struct virtio_device *vdev,
                                       unsigned int offset,
@@ -490,4 +530,14 @@ static inline void virtio_cwrite64(struct virtio_device *vdev,
                _r;                                                     \
        })
 
+/* Conditional config space accessors. */
+#define virtio_cread_le_feature(vdev, fbit, structname, member, ptr)   \
+       ({                                                              \
+               int _r = 0;                                             \
+               if (!virtio_has_feature(vdev, fbit))                    \
+                       _r = -ENOENT;                                   \
+               else                                                    \
+                       virtio_cread_le((vdev), structname, member, ptr); \
+               _r;                                                     \
+       })
 #endif /* _LINUX_VIRTIO_CONFIG_H */