linux/include/linux/virtio_config.h
<<
>>
Prefs
   1#ifndef _LINUX_VIRTIO_CONFIG_H
   2#define _LINUX_VIRTIO_CONFIG_H
   3
   4#include <linux/err.h>
   5#include <linux/bug.h>
   6#include <linux/virtio.h>
   7#include <linux/virtio_byteorder.h>
   8#include <uapi/linux/virtio_config.h>
   9
  10/**
  11 * virtio_config_ops - operations for configuring a virtio device
  12 * @get: read the value of a configuration field
  13 *      vdev: the virtio_device
  14 *      offset: the offset of the configuration field
  15 *      buf: the buffer to write the field value into.
  16 *      len: the length of the buffer
  17 * @set: write the value of a configuration field
  18 *      vdev: the virtio_device
  19 *      offset: the offset of the configuration field
  20 *      buf: the buffer to read the field value from.
  21 *      len: the length of the buffer
  22 * @generation: config generation counter
  23 *      vdev: the virtio_device
  24 *      Returns the config generation counter
  25 * @get_status: read the status byte
  26 *      vdev: the virtio_device
  27 *      Returns the status byte
  28 * @set_status: write the status byte
  29 *      vdev: the virtio_device
  30 *      status: the new status byte
  31 * @reset: reset the device
  32 *      vdev: the virtio device
  33 *      After this, status and feature negotiation must be done again
  34 *      Device must not be reset from its vq/config callbacks, or in
  35 *      parallel with being added/removed.
  36 * @find_vqs: find virtqueues and instantiate them.
  37 *      vdev: the virtio_device
  38 *      nvqs: the number of virtqueues to find
  39 *      vqs: on success, includes new virtqueues
  40 *      callbacks: array of callbacks, for each virtqueue
  41 *              include a NULL entry for vqs that do not need a callback
  42 *      names: array of virtqueue names (mainly for debugging)
  43 *              include a NULL entry for vqs unused by driver
  44 *      Returns 0 on success or error status
  45 * @del_vqs: free virtqueues found by find_vqs().
  46 * @get_features: get the array of feature bits for this device.
  47 *      vdev: the virtio_device
  48 *      Returns the first 32 feature bits (all we currently need).
  49 * @finalize_features: confirm what device features we'll be using.
  50 *      vdev: the virtio_device
  51 *      This gives the final feature bits for the device: it can change
  52 *      the dev->feature bits if it wants.
  53 *      Returns 0 on success or error status
  54 * @bus_name: return the bus name associated with the device
  55 *      vdev: the virtio_device
  56 *      This returns a pointer to the bus name a la pci_name from which
  57 *      the caller can then copy.
  58 * @set_vq_affinity: set the affinity for a virtqueue.
  59 */
  60typedef void vq_callback_t(struct virtqueue *);
  61struct virtio_config_ops {
  62        void (*get)(struct virtio_device *vdev, unsigned offset,
  63                    void *buf, unsigned len);
  64        void (*set)(struct virtio_device *vdev, unsigned offset,
  65                    const void *buf, unsigned len);
  66        u32 (*generation)(struct virtio_device *vdev);
  67        u8 (*get_status)(struct virtio_device *vdev);
  68        void (*set_status)(struct virtio_device *vdev, u8 status);
  69        void (*reset)(struct virtio_device *vdev);
  70        int (*find_vqs)(struct virtio_device *, unsigned nvqs,
  71                        struct virtqueue *vqs[],
  72                        vq_callback_t *callbacks[],
  73                        const char * const names[]);
  74        void (*del_vqs)(struct virtio_device *);
  75        u64 (*get_features)(struct virtio_device *vdev);
  76        int (*finalize_features)(struct virtio_device *vdev);
  77        const char *(*bus_name)(struct virtio_device *vdev);
  78        int (*set_vq_affinity)(struct virtqueue *vq, int cpu);
  79};
  80
  81/* If driver didn't advertise the feature, it will never appear. */
  82void virtio_check_driver_offered_feature(const struct virtio_device *vdev,
  83                                         unsigned int fbit);
  84
  85/**
  86 * __virtio_test_bit - helper to test feature bits. For use by transports.
  87 *                     Devices should normally use virtio_has_feature,
  88 *                     which includes more checks.
  89 * @vdev: the device
  90 * @fbit: the feature bit
  91 */
  92static inline bool __virtio_test_bit(const struct virtio_device *vdev,
  93                                     unsigned int fbit)
  94{
  95        /* Did you forget to fix assumptions on max features? */
  96        if (__builtin_constant_p(fbit))
  97                BUILD_BUG_ON(fbit >= 64);
  98        else
  99                BUG_ON(fbit >= 64);
 100
 101        return vdev->features & BIT_ULL(fbit);
 102}
 103
 104/**
 105 * __virtio_set_bit - helper to set feature bits. For use by transports.
 106 * @vdev: the device
 107 * @fbit: the feature bit
 108 */
 109static inline void __virtio_set_bit(struct virtio_device *vdev,
 110                                    unsigned int fbit)
 111{
 112        /* Did you forget to fix assumptions on max features? */
 113        if (__builtin_constant_p(fbit))
 114                BUILD_BUG_ON(fbit >= 64);
 115        else
 116                BUG_ON(fbit >= 64);
 117
 118        vdev->features |= BIT_ULL(fbit);
 119}
 120
 121/**
 122 * __virtio_clear_bit - helper to clear feature bits. For use by transports.
 123 * @vdev: the device
 124 * @fbit: the feature bit
 125 */
 126static inline void __virtio_clear_bit(struct virtio_device *vdev,
 127                                      unsigned int fbit)
 128{
 129        /* Did you forget to fix assumptions on max features? */
 130        if (__builtin_constant_p(fbit))
 131                BUILD_BUG_ON(fbit >= 64);
 132        else
 133                BUG_ON(fbit >= 64);
 134
 135        vdev->features &= ~BIT_ULL(fbit);
 136}
 137
 138/**
 139 * virtio_has_feature - helper to determine if this device has this feature.
 140 * @vdev: the device
 141 * @fbit: the feature bit
 142 */
 143static inline bool virtio_has_feature(const struct virtio_device *vdev,
 144                                      unsigned int fbit)
 145{
 146        if (fbit < VIRTIO_TRANSPORT_F_START)
 147                virtio_check_driver_offered_feature(vdev, fbit);
 148
 149        return __virtio_test_bit(vdev, fbit);
 150}
 151
 152/**
 153 * virtio_has_iommu_quirk - determine whether this device has the iommu quirk
 154 * @vdev: the device
 155 */
 156static inline bool virtio_has_iommu_quirk(const struct virtio_device *vdev)
 157{
 158        /*
 159         * Note the reverse polarity of the quirk feature (compared to most
 160         * other features), this is for compatibility with legacy systems.
 161         */
 162        return !virtio_has_feature(vdev, VIRTIO_F_IOMMU_PLATFORM);
 163}
 164
 165static inline
 166struct virtqueue *virtio_find_single_vq(struct virtio_device *vdev,
 167                                        vq_callback_t *c, const char *n)
 168{
 169        vq_callback_t *callbacks[] = { c };
 170        const char *names[] = { n };
 171        struct virtqueue *vq;
 172        int err = vdev->config->find_vqs(vdev, 1, &vq, callbacks, names);
 173        if (err < 0)
 174                return ERR_PTR(err);
 175        return vq;
 176}
 177
 178/**
 179 * virtio_device_ready - enable vq use in probe function
 180 * @vdev: the device
 181 *
 182 * Driver must call this to use vqs in the probe function.
 183 *
 184 * Note: vqs are enabled automatically after probe returns.
 185 */
 186static inline
 187void virtio_device_ready(struct virtio_device *dev)
 188{
 189        unsigned status = dev->config->get_status(dev);
 190
 191        BUG_ON(status & VIRTIO_CONFIG_S_DRIVER_OK);
 192        dev->config->set_status(dev, status | VIRTIO_CONFIG_S_DRIVER_OK);
 193}
 194
 195static inline
 196const char *virtio_bus_name(struct virtio_device *vdev)
 197{
 198        if (!vdev->config->bus_name)
 199                return "virtio";
 200        return vdev->config->bus_name(vdev);
 201}
 202
 203/**
 204 * virtqueue_set_affinity - setting affinity for a virtqueue
 205 * @vq: the virtqueue
 206 * @cpu: the cpu no.
 207 *
 208 * Pay attention the function are best-effort: the affinity hint may not be set
 209 * due to config support, irq type and sharing.
 210 *
 211 */
 212static inline
 213int virtqueue_set_affinity(struct virtqueue *vq, int cpu)
 214{
 215        struct virtio_device *vdev = vq->vdev;
 216        if (vdev->config->set_vq_affinity)
 217                return vdev->config->set_vq_affinity(vq, cpu);
 218        return 0;
 219}
 220
 221static inline bool virtio_is_little_endian(struct virtio_device *vdev)
 222{
 223        return virtio_has_feature(vdev, VIRTIO_F_VERSION_1) ||
 224                virtio_legacy_is_little_endian();
 225}
 226
 227/* Memory accessors */
 228static inline u16 virtio16_to_cpu(struct virtio_device *vdev, __virtio16 val)
 229{
 230        return __virtio16_to_cpu(virtio_is_little_endian(vdev), val);
 231}
 232
 233static inline __virtio16 cpu_to_virtio16(struct virtio_device *vdev, u16 val)
 234{
 235        return __cpu_to_virtio16(virtio_is_little_endian(vdev), val);
 236}
 237
 238static inline u32 virtio32_to_cpu(struct virtio_device *vdev, __virtio32 val)
 239{
 240        return __virtio32_to_cpu(virtio_is_little_endian(vdev), val);
 241}
 242
 243static inline __virtio32 cpu_to_virtio32(struct virtio_device *vdev, u32 val)
 244{
 245        return __cpu_to_virtio32(virtio_is_little_endian(vdev), val);
 246}
 247
 248static inline u64 virtio64_to_cpu(struct virtio_device *vdev, __virtio64 val)
 249{
 250        return __virtio64_to_cpu(virtio_is_little_endian(vdev), val);
 251}
 252
 253static inline __virtio64 cpu_to_virtio64(struct virtio_device *vdev, u64 val)
 254{
 255        return __cpu_to_virtio64(virtio_is_little_endian(vdev), val);
 256}
 257
 258/* Config space accessors. */
 259#define virtio_cread(vdev, structname, member, ptr)                     \
 260        do {                                                            \
 261                /* Must match the member's type, and be integer */      \
 262                if (!typecheck(typeof((((structname*)0)->member)), *(ptr))) \
 263                        (*ptr) = 1;                                     \
 264                                                                        \
 265                switch (sizeof(*ptr)) {                                 \
 266                case 1:                                                 \
 267                        *(ptr) = virtio_cread8(vdev,                    \
 268                                               offsetof(structname, member)); \
 269                        break;                                          \
 270                case 2:                                                 \
 271                        *(ptr) = virtio_cread16(vdev,                   \
 272                                                offsetof(structname, member)); \
 273                        break;                                          \
 274                case 4:                                                 \
 275                        *(ptr) = virtio_cread32(vdev,                   \
 276                                                offsetof(structname, member)); \
 277                        break;                                          \
 278                case 8:                                                 \
 279                        *(ptr) = virtio_cread64(vdev,                   \
 280                                                offsetof(structname, member)); \
 281                        break;                                          \
 282                default:                                                \
 283                        BUG();                                          \
 284                }                                                       \
 285        } while(0)
 286
 287/* Config space accessors. */
 288#define virtio_cwrite(vdev, structname, member, ptr)                    \
 289        do {                                                            \
 290                /* Must match the member's type, and be integer */      \
 291                if (!typecheck(typeof((((structname*)0)->member)), *(ptr))) \
 292                        BUG_ON((*ptr) == 1);                            \
 293                                                                        \
 294                switch (sizeof(*ptr)) {                                 \
 295                case 1:                                                 \
 296                        virtio_cwrite8(vdev,                            \
 297                                       offsetof(structname, member),    \
 298                                       *(ptr));                         \
 299                        break;                                          \
 300                case 2:                                                 \
 301                        virtio_cwrite16(vdev,                           \
 302                                        offsetof(structname, member),   \
 303                                        *(ptr));                        \
 304                        break;                                          \
 305                case 4:                                                 \
 306                        virtio_cwrite32(vdev,                           \
 307                                        offsetof(structname, member),   \
 308                                        *(ptr));                        \
 309                        break;                                          \
 310                case 8:                                                 \
 311                        virtio_cwrite64(vdev,                           \
 312                                        offsetof(structname, member),   \
 313                                        *(ptr));                        \
 314                        break;                                          \
 315                default:                                                \
 316                        BUG();                                          \
 317                }                                                       \
 318        } while(0)
 319
 320/* Read @count fields, @bytes each. */
 321static inline void __virtio_cread_many(struct virtio_device *vdev,
 322                                       unsigned int offset,
 323                                       void *buf, size_t count, size_t bytes)
 324{
 325        u32 old, gen = vdev->config->generation ?
 326                vdev->config->generation(vdev) : 0;
 327        int i;
 328
 329        do {
 330                old = gen;
 331
 332                for (i = 0; i < count; i++)
 333                        vdev->config->get(vdev, offset + bytes * i,
 334                                          buf + i * bytes, bytes);
 335
 336                gen = vdev->config->generation ?
 337                        vdev->config->generation(vdev) : 0;
 338        } while (gen != old);
 339}
 340
 341static inline void virtio_cread_bytes(struct virtio_device *vdev,
 342                                      unsigned int offset,
 343                                      void *buf, size_t len)
 344{
 345        __virtio_cread_many(vdev, offset, buf, len, 1);
 346}
 347
 348static inline u8 virtio_cread8(struct virtio_device *vdev, unsigned int offset)
 349{
 350        u8 ret;
 351        vdev->config->get(vdev, offset, &ret, sizeof(ret));
 352        return ret;
 353}
 354
 355static inline void virtio_cwrite8(struct virtio_device *vdev,
 356                                  unsigned int offset, u8 val)
 357{
 358        vdev->config->set(vdev, offset, &val, sizeof(val));
 359}
 360
 361static inline u16 virtio_cread16(struct virtio_device *vdev,
 362                                 unsigned int offset)
 363{
 364        u16 ret;
 365        vdev->config->get(vdev, offset, &ret, sizeof(ret));
 366        return virtio16_to_cpu(vdev, (__force __virtio16)ret);
 367}
 368
 369static inline void virtio_cwrite16(struct virtio_device *vdev,
 370                                   unsigned int offset, u16 val)
 371{
 372        val = (__force u16)cpu_to_virtio16(vdev, val);
 373        vdev->config->set(vdev, offset, &val, sizeof(val));
 374}
 375
 376static inline u32 virtio_cread32(struct virtio_device *vdev,
 377                                 unsigned int offset)
 378{
 379        u32 ret;
 380        vdev->config->get(vdev, offset, &ret, sizeof(ret));
 381        return virtio32_to_cpu(vdev, (__force __virtio32)ret);
 382}
 383
 384static inline void virtio_cwrite32(struct virtio_device *vdev,
 385                                   unsigned int offset, u32 val)
 386{
 387        val = (__force u32)cpu_to_virtio32(vdev, val);
 388        vdev->config->set(vdev, offset, &val, sizeof(val));
 389}
 390
 391static inline u64 virtio_cread64(struct virtio_device *vdev,
 392                                 unsigned int offset)
 393{
 394        u64 ret;
 395        __virtio_cread_many(vdev, offset, &ret, 1, sizeof(ret));
 396        return virtio64_to_cpu(vdev, (__force __virtio64)ret);
 397}
 398
 399static inline void virtio_cwrite64(struct virtio_device *vdev,
 400                                   unsigned int offset, u64 val)
 401{
 402        val = (__force u64)cpu_to_virtio64(vdev, val);
 403        vdev->config->set(vdev, offset, &val, sizeof(val));
 404}
 405
 406/* Conditional config space accessors. */
 407#define virtio_cread_feature(vdev, fbit, structname, member, ptr)       \
 408        ({                                                              \
 409                int _r = 0;                                             \
 410                if (!virtio_has_feature(vdev, fbit))                    \
 411                        _r = -ENOENT;                                   \
 412                else                                                    \
 413                        virtio_cread((vdev), structname, member, ptr);  \
 414                _r;                                                     \
 415        })
 416
 417#endif /* _LINUX_VIRTIO_CONFIG_H */
 418