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
 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
 208static inline bool virtio_is_little_endian(struct virtio_device *vdev)
 209{
 210        return virtio_has_feature(vdev, VIRTIO_F_VERSION_1) ||
 211                virtio_legacy_is_little_endian();
 212}
 213
 214/* Memory accessors */
 215static inline u16 virtio16_to_cpu(struct virtio_device *vdev, __virtio16 val)
 216{
 217        return __virtio16_to_cpu(virtio_is_little_endian(vdev), val);
 218}
 219
 220static inline __virtio16 cpu_to_virtio16(struct virtio_device *vdev, u16 val)
 221{
 222        return __cpu_to_virtio16(virtio_is_little_endian(vdev), val);
 223}
 224
 225static inline u32 virtio32_to_cpu(struct virtio_device *vdev, __virtio32 val)
 226{
 227        return __virtio32_to_cpu(virtio_is_little_endian(vdev), val);
 228}
 229
 230static inline __virtio32 cpu_to_virtio32(struct virtio_device *vdev, u32 val)
 231{
 232        return __cpu_to_virtio32(virtio_is_little_endian(vdev), val);
 233}
 234
 235static inline u64 virtio64_to_cpu(struct virtio_device *vdev, __virtio64 val)
 236{
 237        return __virtio64_to_cpu(virtio_is_little_endian(vdev), val);
 238}
 239
 240static inline __virtio64 cpu_to_virtio64(struct virtio_device *vdev, u64 val)
 241{
 242        return __cpu_to_virtio64(virtio_is_little_endian(vdev), val);
 243}
 244
 245/* Config space accessors. */
 246#define virtio_cread(vdev, structname, member, ptr)                     \
 247        do {                                                            \
 248                /* Must match the member's type, and be integer */      \
 249                if (!typecheck(typeof((((structname*)0)->member)), *(ptr))) \
 250                        (*ptr) = 1;                                     \
 251                                                                        \
 252                switch (sizeof(*ptr)) {                                 \
 253                case 1:                                                 \
 254                        *(ptr) = virtio_cread8(vdev,                    \
 255                                               offsetof(structname, member)); \
 256                        break;                                          \
 257                case 2:                                                 \
 258                        *(ptr) = virtio_cread16(vdev,                   \
 259                                                offsetof(structname, member)); \
 260                        break;                                          \
 261                case 4:                                                 \
 262                        *(ptr) = virtio_cread32(vdev,                   \
 263                                                offsetof(structname, member)); \
 264                        break;                                          \
 265                case 8:                                                 \
 266                        *(ptr) = virtio_cread64(vdev,                   \
 267                                                offsetof(structname, member)); \
 268                        break;                                          \
 269                default:                                                \
 270                        BUG();                                          \
 271                }                                                       \
 272        } while(0)
 273
 274/* Config space accessors. */
 275#define virtio_cwrite(vdev, structname, member, ptr)                    \
 276        do {                                                            \
 277                /* Must match the member's type, and be integer */      \
 278                if (!typecheck(typeof((((structname*)0)->member)), *(ptr))) \
 279                        BUG_ON((*ptr) == 1);                            \
 280                                                                        \
 281                switch (sizeof(*ptr)) {                                 \
 282                case 1:                                                 \
 283                        virtio_cwrite8(vdev,                            \
 284                                       offsetof(structname, member),    \
 285                                       *(ptr));                         \
 286                        break;                                          \
 287                case 2:                                                 \
 288                        virtio_cwrite16(vdev,                           \
 289                                        offsetof(structname, member),   \
 290                                        *(ptr));                        \
 291                        break;                                          \
 292                case 4:                                                 \
 293                        virtio_cwrite32(vdev,                           \
 294                                        offsetof(structname, member),   \
 295                                        *(ptr));                        \
 296                        break;                                          \
 297                case 8:                                                 \
 298                        virtio_cwrite64(vdev,                           \
 299                                        offsetof(structname, member),   \
 300                                        *(ptr));                        \
 301                        break;                                          \
 302                default:                                                \
 303                        BUG();                                          \
 304                }                                                       \
 305        } while(0)
 306
 307/* Read @count fields, @bytes each. */
 308static inline void __virtio_cread_many(struct virtio_device *vdev,
 309                                       unsigned int offset,
 310                                       void *buf, size_t count, size_t bytes)
 311{
 312        u32 old, gen = vdev->config->generation ?
 313                vdev->config->generation(vdev) : 0;
 314        int i;
 315
 316        do {
 317                old = gen;
 318
 319                for (i = 0; i < count; i++)
 320                        vdev->config->get(vdev, offset + bytes * i,
 321                                          buf + i * bytes, bytes);
 322
 323                gen = vdev->config->generation ?
 324                        vdev->config->generation(vdev) : 0;
 325        } while (gen != old);
 326}
 327
 328static inline void virtio_cread_bytes(struct virtio_device *vdev,
 329                                      unsigned int offset,
 330                                      void *buf, size_t len)
 331{
 332        __virtio_cread_many(vdev, offset, buf, len, 1);
 333}
 334
 335static inline u8 virtio_cread8(struct virtio_device *vdev, unsigned int offset)
 336{
 337        u8 ret;
 338        vdev->config->get(vdev, offset, &ret, sizeof(ret));
 339        return ret;
 340}
 341
 342static inline void virtio_cwrite8(struct virtio_device *vdev,
 343                                  unsigned int offset, u8 val)
 344{
 345        vdev->config->set(vdev, offset, &val, sizeof(val));
 346}
 347
 348static inline u16 virtio_cread16(struct virtio_device *vdev,
 349                                 unsigned int offset)
 350{
 351        u16 ret;
 352        vdev->config->get(vdev, offset, &ret, sizeof(ret));
 353        return virtio16_to_cpu(vdev, (__force __virtio16)ret);
 354}
 355
 356static inline void virtio_cwrite16(struct virtio_device *vdev,
 357                                   unsigned int offset, u16 val)
 358{
 359        val = (__force u16)cpu_to_virtio16(vdev, val);
 360        vdev->config->set(vdev, offset, &val, sizeof(val));
 361}
 362
 363static inline u32 virtio_cread32(struct virtio_device *vdev,
 364                                 unsigned int offset)
 365{
 366        u32 ret;
 367        vdev->config->get(vdev, offset, &ret, sizeof(ret));
 368        return virtio32_to_cpu(vdev, (__force __virtio32)ret);
 369}
 370
 371static inline void virtio_cwrite32(struct virtio_device *vdev,
 372                                   unsigned int offset, u32 val)
 373{
 374        val = (__force u32)cpu_to_virtio32(vdev, val);
 375        vdev->config->set(vdev, offset, &val, sizeof(val));
 376}
 377
 378static inline u64 virtio_cread64(struct virtio_device *vdev,
 379                                 unsigned int offset)
 380{
 381        u64 ret;
 382        __virtio_cread_many(vdev, offset, &ret, 1, sizeof(ret));
 383        return virtio64_to_cpu(vdev, (__force __virtio64)ret);
 384}
 385
 386static inline void virtio_cwrite64(struct virtio_device *vdev,
 387                                   unsigned int offset, u64 val)
 388{
 389        val = (__force u64)cpu_to_virtio64(vdev, val);
 390        vdev->config->set(vdev, offset, &val, sizeof(val));
 391}
 392
 393/* Conditional config space accessors. */
 394#define virtio_cread_feature(vdev, fbit, structname, member, ptr)       \
 395        ({                                                              \
 396                int _r = 0;                                             \
 397                if (!virtio_has_feature(vdev, fbit))                    \
 398                        _r = -ENOENT;                                   \
 399                else                                                    \
 400                        virtio_cread((vdev), structname, member, ptr);  \
 401                _r;                                                     \
 402        })
 403
 404#endif /* _LINUX_VIRTIO_CONFIG_H */
 405