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 *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
 152static inline
 153struct virtqueue *virtio_find_single_vq(struct virtio_device *vdev,
 154                                        vq_callback_t *c, const char *n)
 155{
 156        vq_callback_t *callbacks[] = { c };
 157        const char *names[] = { n };
 158        struct virtqueue *vq;
 159        int err = vdev->config->find_vqs(vdev, 1, &vq, callbacks, names);
 160        if (err < 0)
 161                return ERR_PTR(err);
 162        return vq;
 163}
 164
 165/**
 166 * virtio_device_ready - enable vq use in probe function
 167 * @vdev: the device
 168 *
 169 * Driver must call this to use vqs in the probe function.
 170 *
 171 * Note: vqs are enabled automatically after probe returns.
 172 */
 173static inline
 174void virtio_device_ready(struct virtio_device *dev)
 175{
 176        unsigned status = dev->config->get_status(dev);
 177
 178        BUG_ON(status & VIRTIO_CONFIG_S_DRIVER_OK);
 179        dev->config->set_status(dev, status | VIRTIO_CONFIG_S_DRIVER_OK);
 180}
 181
 182static inline
 183const char *virtio_bus_name(struct virtio_device *vdev)
 184{
 185        if (!vdev->config->bus_name)
 186                return "virtio";
 187        return vdev->config->bus_name(vdev);
 188}
 189
 190/**
 191 * virtqueue_set_affinity - setting affinity for a virtqueue
 192 * @vq: the virtqueue
 193 * @cpu: the cpu no.
 194 *
 195 * Pay attention the function are best-effort: the affinity hint may not be set
 196 * due to config support, irq type and sharing.
 197 *
 198 */
 199static inline
 200int virtqueue_set_affinity(struct virtqueue *vq, int cpu)
 201{
 202        struct virtio_device *vdev = vq->vdev;
 203        if (vdev->config->set_vq_affinity)
 204                return vdev->config->set_vq_affinity(vq, cpu);
 205        return 0;
 206}
 207
 208/* Memory accessors */
 209static inline u16 virtio16_to_cpu(struct virtio_device *vdev, __virtio16 val)
 210{
 211        return __virtio16_to_cpu(virtio_has_feature(vdev, VIRTIO_F_VERSION_1), val);
 212}
 213
 214static inline __virtio16 cpu_to_virtio16(struct virtio_device *vdev, u16 val)
 215{
 216        return __cpu_to_virtio16(virtio_has_feature(vdev, VIRTIO_F_VERSION_1), val);
 217}
 218
 219static inline u32 virtio32_to_cpu(struct virtio_device *vdev, __virtio32 val)
 220{
 221        return __virtio32_to_cpu(virtio_has_feature(vdev, VIRTIO_F_VERSION_1), val);
 222}
 223
 224static inline __virtio32 cpu_to_virtio32(struct virtio_device *vdev, u32 val)
 225{
 226        return __cpu_to_virtio32(virtio_has_feature(vdev, VIRTIO_F_VERSION_1), val);
 227}
 228
 229static inline u64 virtio64_to_cpu(struct virtio_device *vdev, __virtio64 val)
 230{
 231        return __virtio64_to_cpu(virtio_has_feature(vdev, VIRTIO_F_VERSION_1), val);
 232}
 233
 234static inline __virtio64 cpu_to_virtio64(struct virtio_device *vdev, u64 val)
 235{
 236        return __cpu_to_virtio64(virtio_has_feature(vdev, VIRTIO_F_VERSION_1), val);
 237}
 238
 239/* Config space accessors. */
 240#define virtio_cread(vdev, structname, member, ptr)                     \
 241        do {                                                            \
 242                /* Must match the member's type, and be integer */      \
 243                if (!typecheck(typeof((((structname*)0)->member)), *(ptr))) \
 244                        (*ptr) = 1;                                     \
 245                                                                        \
 246                switch (sizeof(*ptr)) {                                 \
 247                case 1:                                                 \
 248                        *(ptr) = virtio_cread8(vdev,                    \
 249                                               offsetof(structname, member)); \
 250                        break;                                          \
 251                case 2:                                                 \
 252                        *(ptr) = virtio_cread16(vdev,                   \
 253                                                offsetof(structname, member)); \
 254                        break;                                          \
 255                case 4:                                                 \
 256                        *(ptr) = virtio_cread32(vdev,                   \
 257                                                offsetof(structname, member)); \
 258                        break;                                          \
 259                case 8:                                                 \
 260                        *(ptr) = virtio_cread64(vdev,                   \
 261                                                offsetof(structname, member)); \
 262                        break;                                          \
 263                default:                                                \
 264                        BUG();                                          \
 265                }                                                       \
 266        } while(0)
 267
 268/* Config space accessors. */
 269#define virtio_cwrite(vdev, structname, member, ptr)                    \
 270        do {                                                            \
 271                /* Must match the member's type, and be integer */      \
 272                if (!typecheck(typeof((((structname*)0)->member)), *(ptr))) \
 273                        BUG_ON((*ptr) == 1);                            \
 274                                                                        \
 275                switch (sizeof(*ptr)) {                                 \
 276                case 1:                                                 \
 277                        virtio_cwrite8(vdev,                            \
 278                                       offsetof(structname, member),    \
 279                                       *(ptr));                         \
 280                        break;                                          \
 281                case 2:                                                 \
 282                        virtio_cwrite16(vdev,                           \
 283                                        offsetof(structname, member),   \
 284                                        *(ptr));                        \
 285                        break;                                          \
 286                case 4:                                                 \
 287                        virtio_cwrite32(vdev,                           \
 288                                        offsetof(structname, member),   \
 289                                        *(ptr));                        \
 290                        break;                                          \
 291                case 8:                                                 \
 292                        virtio_cwrite64(vdev,                           \
 293                                        offsetof(structname, member),   \
 294                                        *(ptr));                        \
 295                        break;                                          \
 296                default:                                                \
 297                        BUG();                                          \
 298                }                                                       \
 299        } while(0)
 300
 301static inline u8 virtio_cread8(struct virtio_device *vdev, unsigned int offset)
 302{
 303        u8 ret;
 304        vdev->config->get(vdev, offset, &ret, sizeof(ret));
 305        return ret;
 306}
 307
 308/* Read @count fields, @bytes each. */
 309static inline void __virtio_cread_many(struct virtio_device *vdev,
 310                                       unsigned int offset,
 311                                       void *buf, size_t count, size_t bytes)
 312{
 313        u32 old, gen = vdev->config->generation ?
 314                vdev->config->generation(vdev) : 0;
 315        int i;
 316
 317        do {
 318                old = gen;
 319
 320                for (i = 0; i < count; i++)
 321                        vdev->config->get(vdev, offset + bytes * i,
 322                                          buf + i * bytes, bytes);
 323
 324                gen = vdev->config->generation ?
 325                        vdev->config->generation(vdev) : 0;
 326        } while (gen != old);
 327}
 328
 329
 330static inline void virtio_cread_bytes(struct virtio_device *vdev,
 331                                      unsigned int offset,
 332                                      void *buf, size_t len)
 333{
 334        __virtio_cread_many(vdev, offset, buf, len, 1);
 335}
 336
 337static inline void virtio_cwrite8(struct virtio_device *vdev,
 338                                  unsigned int offset, u8 val)
 339{
 340        vdev->config->set(vdev, offset, &val, sizeof(val));
 341}
 342
 343static inline u16 virtio_cread16(struct virtio_device *vdev,
 344                                 unsigned int offset)
 345{
 346        u16 ret;
 347        vdev->config->get(vdev, offset, &ret, sizeof(ret));
 348        return virtio16_to_cpu(vdev, (__force __virtio16)ret);
 349}
 350
 351static inline void virtio_cwrite16(struct virtio_device *vdev,
 352                                   unsigned int offset, u16 val)
 353{
 354        val = (__force u16)cpu_to_virtio16(vdev, val);
 355        vdev->config->set(vdev, offset, &val, sizeof(val));
 356}
 357
 358static inline u32 virtio_cread32(struct virtio_device *vdev,
 359                                 unsigned int offset)
 360{
 361        u32 ret;
 362        vdev->config->get(vdev, offset, &ret, sizeof(ret));
 363        return virtio32_to_cpu(vdev, (__force __virtio32)ret);
 364}
 365
 366static inline void virtio_cwrite32(struct virtio_device *vdev,
 367                                   unsigned int offset, u32 val)
 368{
 369        val = (__force u32)cpu_to_virtio32(vdev, val);
 370        vdev->config->set(vdev, offset, &val, sizeof(val));
 371}
 372
 373static inline u64 virtio_cread64(struct virtio_device *vdev,
 374                                 unsigned int offset)
 375{
 376        u64 ret;
 377        vdev->config->get(vdev, offset, &ret, sizeof(ret));
 378        __virtio_cread_many(vdev, offset, &ret, 1, sizeof(ret));
 379        return virtio64_to_cpu(vdev, (__force __virtio64)ret);
 380}
 381
 382static inline void virtio_cwrite64(struct virtio_device *vdev,
 383                                   unsigned int offset, u64 val)
 384{
 385        val = (__force u64)cpu_to_virtio64(vdev, val);
 386        vdev->config->set(vdev, offset, &val, sizeof(val));
 387}
 388
 389/* Conditional config space accessors. */
 390#define virtio_cread_feature(vdev, fbit, structname, member, ptr)       \
 391        ({                                                              \
 392                int _r = 0;                                             \
 393                if (!virtio_has_feature(vdev, fbit))                    \
 394                        _r = -ENOENT;                                   \
 395                else                                                    \
 396                        virtio_cread((vdev), structname, member, ptr);  \
 397                _r;                                                     \
 398        })
 399
 400#endif /* _LINUX_VIRTIO_CONFIG_H */
 401