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 <uapi/linux/virtio_config.h>
   8
   9/**
  10 * virtio_config_ops - operations for configuring a virtio device
  11 * @get: read the value of a configuration field
  12 *      vdev: the virtio_device
  13 *      offset: the offset of the configuration field
  14 *      buf: the buffer to write the field value into.
  15 *      len: the length of the buffer
  16 * @set: write the value of a configuration field
  17 *      vdev: the virtio_device
  18 *      offset: the offset of the configuration field
  19 *      buf: the buffer to read the field value from.
  20 *      len: the length of the buffer
  21 * @get_status: read the status byte
  22 *      vdev: the virtio_device
  23 *      Returns the status byte
  24 * @set_status: write the status byte
  25 *      vdev: the virtio_device
  26 *      status: the new status byte
  27 * @reset: reset the device
  28 *      vdev: the virtio device
  29 *      After this, status and feature negotiation must be done again
  30 *      Device must not be reset from its vq/config callbacks, or in
  31 *      parallel with being added/removed.
  32 * @find_vqs: find virtqueues and instantiate them.
  33 *      vdev: the virtio_device
  34 *      nvqs: the number of virtqueues to find
  35 *      vqs: on success, includes new virtqueues
  36 *      callbacks: array of callbacks, for each virtqueue
  37 *              include a NULL entry for vqs that do not need a callback
  38 *      names: array of virtqueue names (mainly for debugging)
  39 *              include a NULL entry for vqs unused by driver
  40 *      Returns 0 on success or error status
  41 * @del_vqs: free virtqueues found by find_vqs().
  42 * @get_features: get the array of feature bits for this device.
  43 *      vdev: the virtio_device
  44 *      Returns the first 32 feature bits (all we currently need).
  45 * @finalize_features: confirm what device features we'll be using.
  46 *      vdev: the virtio_device
  47 *      This gives the final feature bits for the device: it can change
  48 *      the dev->feature bits if it wants.
  49 * @bus_name: return the bus name associated with the device
  50 *      vdev: the virtio_device
  51 *      This returns a pointer to the bus name a la pci_name from which
  52 *      the caller can then copy.
  53 * @set_vq_affinity: set the affinity for a virtqueue.
  54 */
  55typedef void vq_callback_t(struct virtqueue *);
  56struct virtio_config_ops {
  57        void (*get)(struct virtio_device *vdev, unsigned offset,
  58                    void *buf, unsigned len);
  59        void (*set)(struct virtio_device *vdev, unsigned offset,
  60                    const void *buf, unsigned len);
  61        u8 (*get_status)(struct virtio_device *vdev);
  62        void (*set_status)(struct virtio_device *vdev, u8 status);
  63        void (*reset)(struct virtio_device *vdev);
  64        int (*find_vqs)(struct virtio_device *, unsigned nvqs,
  65                        struct virtqueue *vqs[],
  66                        vq_callback_t *callbacks[],
  67                        const char *names[]);
  68        void (*del_vqs)(struct virtio_device *);
  69        u32 (*get_features)(struct virtio_device *vdev);
  70        void (*finalize_features)(struct virtio_device *vdev);
  71        const char *(*bus_name)(struct virtio_device *vdev);
  72        int (*set_vq_affinity)(struct virtqueue *vq, int cpu);
  73};
  74
  75/* If driver didn't advertise the feature, it will never appear. */
  76void virtio_check_driver_offered_feature(const struct virtio_device *vdev,
  77                                         unsigned int fbit);
  78
  79/**
  80 * virtio_has_feature - helper to determine if this device has this feature.
  81 * @vdev: the device
  82 * @fbit: the feature bit
  83 */
  84static inline bool virtio_has_feature(const struct virtio_device *vdev,
  85                                      unsigned int fbit)
  86{
  87        /* Did you forget to fix assumptions on max features? */
  88        if (__builtin_constant_p(fbit))
  89                BUILD_BUG_ON(fbit >= 32);
  90        else
  91                BUG_ON(fbit >= 32);
  92
  93        if (fbit < VIRTIO_TRANSPORT_F_START)
  94                virtio_check_driver_offered_feature(vdev, fbit);
  95
  96        return test_bit(fbit, vdev->features);
  97}
  98
  99static inline
 100struct virtqueue *virtio_find_single_vq(struct virtio_device *vdev,
 101                                        vq_callback_t *c, const char *n)
 102{
 103        vq_callback_t *callbacks[] = { c };
 104        const char *names[] = { n };
 105        struct virtqueue *vq;
 106        int err = vdev->config->find_vqs(vdev, 1, &vq, callbacks, names);
 107        if (err < 0)
 108                return ERR_PTR(err);
 109        return vq;
 110}
 111
 112static inline
 113const char *virtio_bus_name(struct virtio_device *vdev)
 114{
 115        if (!vdev->config->bus_name)
 116                return "virtio";
 117        return vdev->config->bus_name(vdev);
 118}
 119
 120/**
 121 * virtqueue_set_affinity - setting affinity for a virtqueue
 122 * @vq: the virtqueue
 123 * @cpu: the cpu no.
 124 *
 125 * Pay attention the function are best-effort: the affinity hint may not be set
 126 * due to config support, irq type and sharing.
 127 *
 128 */
 129static inline
 130int virtqueue_set_affinity(struct virtqueue *vq, int cpu)
 131{
 132        struct virtio_device *vdev = vq->vdev;
 133        if (vdev->config->set_vq_affinity)
 134                return vdev->config->set_vq_affinity(vq, cpu);
 135        return 0;
 136}
 137
 138/* Config space accessors. */
 139#define virtio_cread(vdev, structname, member, ptr)                     \
 140        do {                                                            \
 141                /* Must match the member's type, and be integer */      \
 142                if (!typecheck(typeof((((structname*)0)->member)), *(ptr))) \
 143                        (*ptr) = 1;                                     \
 144                                                                        \
 145                switch (sizeof(*ptr)) {                                 \
 146                case 1:                                                 \
 147                        *(ptr) = virtio_cread8(vdev,                    \
 148                                               offsetof(structname, member)); \
 149                        break;                                          \
 150                case 2:                                                 \
 151                        *(ptr) = virtio_cread16(vdev,                   \
 152                                                offsetof(structname, member)); \
 153                        break;                                          \
 154                case 4:                                                 \
 155                        *(ptr) = virtio_cread32(vdev,                   \
 156                                                offsetof(structname, member)); \
 157                        break;                                          \
 158                case 8:                                                 \
 159                        *(ptr) = virtio_cread64(vdev,                   \
 160                                                offsetof(structname, member)); \
 161                        break;                                          \
 162                default:                                                \
 163                        BUG();                                          \
 164                }                                                       \
 165        } while(0)
 166
 167/* Config space accessors. */
 168#define virtio_cwrite(vdev, structname, member, ptr)                    \
 169        do {                                                            \
 170                /* Must match the member's type, and be integer */      \
 171                if (!typecheck(typeof((((structname*)0)->member)), *(ptr))) \
 172                        BUG_ON((*ptr) == 1);                            \
 173                                                                        \
 174                switch (sizeof(*ptr)) {                                 \
 175                case 1:                                                 \
 176                        virtio_cwrite8(vdev,                            \
 177                                       offsetof(structname, member),    \
 178                                       *(ptr));                         \
 179                        break;                                          \
 180                case 2:                                                 \
 181                        virtio_cwrite16(vdev,                           \
 182                                        offsetof(structname, member),   \
 183                                        *(ptr));                        \
 184                        break;                                          \
 185                case 4:                                                 \
 186                        virtio_cwrite32(vdev,                           \
 187                                        offsetof(structname, member),   \
 188                                        *(ptr));                        \
 189                        break;                                          \
 190                case 8:                                                 \
 191                        virtio_cwrite64(vdev,                           \
 192                                        offsetof(structname, member),   \
 193                                        *(ptr));                        \
 194                        break;                                          \
 195                default:                                                \
 196                        BUG();                                          \
 197                }                                                       \
 198        } while(0)
 199
 200static inline u8 virtio_cread8(struct virtio_device *vdev, unsigned int offset)
 201{
 202        u8 ret;
 203        vdev->config->get(vdev, offset, &ret, sizeof(ret));
 204        return ret;
 205}
 206
 207static inline void virtio_cread_bytes(struct virtio_device *vdev,
 208                                      unsigned int offset,
 209                                      void *buf, size_t len)
 210{
 211        vdev->config->get(vdev, offset, buf, len);
 212}
 213
 214static inline void virtio_cwrite8(struct virtio_device *vdev,
 215                                  unsigned int offset, u8 val)
 216{
 217        vdev->config->set(vdev, offset, &val, sizeof(val));
 218}
 219
 220static inline u16 virtio_cread16(struct virtio_device *vdev,
 221                                 unsigned int offset)
 222{
 223        u16 ret;
 224        vdev->config->get(vdev, offset, &ret, sizeof(ret));
 225        return ret;
 226}
 227
 228static inline void virtio_cwrite16(struct virtio_device *vdev,
 229                                   unsigned int offset, u16 val)
 230{
 231        vdev->config->set(vdev, offset, &val, sizeof(val));
 232}
 233
 234static inline u32 virtio_cread32(struct virtio_device *vdev,
 235                                 unsigned int offset)
 236{
 237        u32 ret;
 238        vdev->config->get(vdev, offset, &ret, sizeof(ret));
 239        return ret;
 240}
 241
 242static inline void virtio_cwrite32(struct virtio_device *vdev,
 243                                   unsigned int offset, u32 val)
 244{
 245        vdev->config->set(vdev, offset, &val, sizeof(val));
 246}
 247
 248static inline u64 virtio_cread64(struct virtio_device *vdev,
 249                                 unsigned int offset)
 250{
 251        u64 ret;
 252        vdev->config->get(vdev, offset, &ret, sizeof(ret));
 253        return ret;
 254}
 255
 256static inline void virtio_cwrite64(struct virtio_device *vdev,
 257                                   unsigned int offset, u64 val)
 258{
 259        vdev->config->set(vdev, offset, &val, sizeof(val));
 260}
 261
 262/* Conditional config space accessors. */
 263#define virtio_cread_feature(vdev, fbit, structname, member, ptr)       \
 264        ({                                                              \
 265                int _r = 0;                                             \
 266                if (!virtio_has_feature(vdev, fbit))                    \
 267                        _r = -ENOENT;                                   \
 268                else                                                    \
 269                        virtio_cread((vdev), structname, member, ptr);  \
 270                _r;                                                     \
 271        })
 272
 273#endif /* _LINUX_VIRTIO_CONFIG_H */
 274