X-Git-Url: http://pilppa.org/gitweb/gitweb.cgi?a=blobdiff_plain;f=include%2Flinux%2Fvirtio_config.h;h=f364bbf63c3413547738ae4028b399577bc76650;hb=36d926b94a9908937593e5669162305a071b9cc3;hp=bcc01888df78d52e19592a92bd8861b0f1f5f9c9;hpb=c7ffb6bb7a1b6fe5912a009d561733911769d32b;p=linux-2.6-omap-h63xx.git diff --git a/include/linux/virtio_config.h b/include/linux/virtio_config.h index bcc01888df7..f364bbf63c3 100644 --- a/include/linux/virtio_config.h +++ b/include/linux/virtio_config.h @@ -5,7 +5,7 @@ * store and access that space differently. */ #include -/* Status byte for guest to report progress, and synchronize config. */ +/* Status byte for guest to report progress, and synchronize features. */ /* We have seen device and processed generic fields (VIRTIO_CONFIG_F_VIRTIO) */ #define VIRTIO_CONFIG_S_ACKNOWLEDGE 1 /* We have found a driver for the device. */ @@ -15,97 +15,106 @@ /* We've given up on this device. */ #define VIRTIO_CONFIG_S_FAILED 0x80 -/* Feature byte (actually 7 bits availabe): */ -/* Requirements/features of the virtio implementation. */ -#define VIRTIO_CONFIG_F_VIRTIO 1 -/* Requirements/features of the virtqueue (may have more than one). */ -#define VIRTIO_CONFIG_F_VIRTQUEUE 2 +/* Do we get callbacks when the ring is completely used, even if we've + * suppressed them? */ +#define VIRTIO_F_NOTIFY_ON_EMPTY 24 #ifdef __KERNEL__ -struct virtio_device; +#include /** * virtio_config_ops - operations for configuring a virtio device - * @find: search for the next configuration field of the given type. + * @get: read the value of a configuration field * vdev: the virtio_device - * type: the feature type - * len: the (returned) length of the field if found. - * Returns a token if found, or NULL. Never returnes the same field twice - * (ie. it's used up). - * @get: read the value of a configuration field after find(). - * vdev: the virtio_device - * token: the token returned from find(). + * offset: the offset of the configuration field * buf: the buffer to write the field value into. - * len: the length of the buffer (given by find()). - * Note that contents are conventionally little-endian. - * @set: write the value of a configuration field after find(). + * len: the length of the buffer + * @set: write the value of a configuration field * vdev: the virtio_device - * token: the token returned from find(). + * offset: the offset of the configuration field * buf: the buffer to read the field value from. - * len: the length of the buffer (given by find()). - * Note that contents are conventionally little-endian. + * len: the length of the buffer * @get_status: read the status byte * vdev: the virtio_device * Returns the status byte * @set_status: write the status byte * vdev: the virtio_device * status: the new status byte - * @find_vq: find the first VIRTIO_CONFIG_F_VIRTQUEUE and create a virtqueue. + * @reset: reset the device + * vdev: the virtio device + * After this, status and feature negotiation must be done again + * @find_vq: find a virtqueue and instantiate it. * vdev: the virtio_device + * index: the 0-based virtqueue number in case there's more than one. * callback: the virqtueue callback - * Returns the new virtqueue or ERR_PTR(). + * Returns the new virtqueue or ERR_PTR() (eg. -ENOENT). * @del_vq: free a virtqueue found by find_vq(). + * @get_features: get the array of feature bits for this device. + * vdev: the virtio_device + * Returns the first 32 feature bits (all we currently need). + * @set_features: confirm what device features we'll be using. + * vdev: the virtio_device + * feature: the first 32 feature bits */ struct virtio_config_ops { - void *(*find)(struct virtio_device *vdev, u8 type, unsigned *len); - void (*get)(struct virtio_device *vdev, void *token, + void (*get)(struct virtio_device *vdev, unsigned offset, void *buf, unsigned len); - void (*set)(struct virtio_device *vdev, void *token, + void (*set)(struct virtio_device *vdev, unsigned offset, const void *buf, unsigned len); u8 (*get_status)(struct virtio_device *vdev); void (*set_status)(struct virtio_device *vdev, u8 status); + void (*reset)(struct virtio_device *vdev); struct virtqueue *(*find_vq)(struct virtio_device *vdev, - bool (*callback)(struct virtqueue *)); + unsigned index, + void (*callback)(struct virtqueue *)); void (*del_vq)(struct virtqueue *vq); + u32 (*get_features)(struct virtio_device *vdev); + void (*set_features)(struct virtio_device *vdev, u32 features); }; +/* If driver didn't advertise the feature, it will never appear. */ +void virtio_check_driver_offered_feature(const struct virtio_device *vdev, + unsigned int fbit); + /** - * virtio_config_val - get a single virtio config and mark it used. - * @config: the virtio config space - * @type: the type to search for. - * @val: a pointer to the value to fill in. - * - * Once used, the config type is marked with VIRTIO_CONFIG_F_USED so it can't - * be found again. This version does endian conversion. */ -#define virtio_config_val(vdev, type, v) ({ \ - int _err = __virtio_config_val((vdev),(type),(v),sizeof(*(v))); \ - \ - BUILD_BUG_ON(sizeof(*(v)) != 1 && sizeof(*(v)) != 2 \ - && sizeof(*(v)) != 4 && sizeof(*(v)) != 8); \ - if (!_err) { \ - switch (sizeof(*(v))) { \ - case 2: le16_to_cpus((__u16 *) v); break; \ - case 4: le32_to_cpus((__u32 *) v); break; \ - case 8: le64_to_cpus((__u64 *) v); break; \ - } \ - } \ - _err; \ -}) + * virtio_has_feature - helper to determine if this device has this feature. + * @vdev: the device + * @fbit: the feature bit + */ +static inline bool virtio_has_feature(const struct virtio_device *vdev, + unsigned int fbit) +{ + /* Did you forget to fix assumptions on max features? */ + if (__builtin_constant_p(fbit)) + BUILD_BUG_ON(fbit >= 32); -int __virtio_config_val(struct virtio_device *dev, - u8 type, void *val, size_t size); + virtio_check_driver_offered_feature(vdev, fbit); + return test_bit(fbit, vdev->features); +} /** - * virtio_use_bit - helper to use a feature bit in a bitfield value. - * @dev: the virtio device - * @token: the token as returned from vdev->config->find(). - * @len: the length of the field. - * @bitnum: the bit to test. + * virtio_config_val - look for a feature and get a virtio config entry. + * @vdev: the virtio device + * @fbit: the feature bit + * @offset: the type to search for. + * @val: a pointer to the value to fill in. * - * If handed a NULL token, it returns false, otherwise returns bit status. - * If it's one, it sets the mirroring acknowledgement bit. */ -int virtio_use_bit(struct virtio_device *vdev, - void *token, unsigned int len, unsigned int bitnum); + * The return value is -ENOENT if the feature doesn't exist. Otherwise + * the config value is copied into whatever is pointed to by v. */ +#define virtio_config_val(vdev, fbit, offset, v) \ + virtio_config_buf((vdev), (fbit), (offset), (v), sizeof(*v)) + +static inline int virtio_config_buf(struct virtio_device *vdev, + unsigned int fbit, + unsigned int offset, + void *buf, unsigned len) +{ + if (!virtio_has_feature(vdev, fbit)) + return -ENOENT; + + vdev->config->get(vdev, offset, buf, len); + return 0; +} #endif /* __KERNEL__ */ #endif /* _LINUX_VIRTIO_CONFIG_H */