diff options
Diffstat (limited to 'include/linux/virtio_config.h')
| -rw-r--r-- | include/linux/virtio_config.h | 85 | 
1 files changed, 48 insertions, 37 deletions
diff --git a/include/linux/virtio_config.h b/include/linux/virtio_config.h index d581b2914b3..f364bbf63c3 100644 --- a/include/linux/virtio_config.h +++ b/include/linux/virtio_config.h @@ -15,28 +15,25 @@  /* We've given up on this device. */  #define VIRTIO_CONFIG_S_FAILED		0x80 +/* 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 <linux/virtio.h>  /**   * virtio_config_ops - operations for configuring a virtio device - * @feature: search for a feature in this config - *	vdev: the virtio_device - *	bit: the feature bit - *	Returns true if the feature is supported.  Acknowledges the feature - *	so the host can see it.   * @get: read the value of a configuration field   *	vdev: the virtio_device   *	offset: the offset of the configuration field   *	buf: the buffer to write the field value into.   *	len: the length of the buffer - *	Note that contents are conventionally little-endian.   * @set: write the value of a configuration field   *	vdev: the virtio_device   *	offset: the offset of the configuration field   *	buf: the buffer to read the field value from.   *	len: the length of the buffer - *	Note that contents are conventionally little-endian.   * @get_status: read the status byte   *	vdev: the virtio_device   *	Returns the status byte @@ -52,10 +49,15 @@ struct virtio_device;   *	callback: the virqtueue callback   *	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  { -	bool (*feature)(struct virtio_device *vdev, unsigned bit);  	void (*get)(struct virtio_device *vdev, unsigned offset,  		    void *buf, unsigned len);  	void (*set)(struct virtio_device *vdev, unsigned offset, @@ -67,43 +69,52 @@ struct virtio_config_ops  				     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 - look for a feature and get a single virtio config. - * @vdev: the virtio device + * virtio_has_feature - helper to determine if this device has this feature. + * @vdev: the device   * @fbit: the feature bit - * @offset: the type to search for. - * @val: a pointer to the value to fill in. - * - * The return value is -ENOENT if the feature doesn't exist.  Otherwise - * the value is endian-corrected and returned in v. */ -#define virtio_config_val(vdev, fbit, offset, v) ({			\ -	int _err;							\ -	if ((vdev)->config->feature((vdev), (fbit))) {			\ -		__virtio_config_val((vdev), (offset), (v));		\ -		_err = 0;						\ -	} else								\ -		_err = -ENOENT;						\ -	_err;								\ -}) + */ +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); + +	virtio_check_driver_offered_feature(vdev, fbit); +	return test_bit(fbit, vdev->features); +}  /** - * __virtio_config_val - get a single virtio config without feature check. + * 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.   * - * The value is endian-corrected and returned in v. */ -#define __virtio_config_val(vdev, offset, v) do {			\ -	BUILD_BUG_ON(sizeof(*(v)) != 1 && sizeof(*(v)) != 2		\ -		     && sizeof(*(v)) != 4 && sizeof(*(v)) != 8);	\ -	(vdev)->config->get((vdev), (offset), (v), sizeof(*(v)));	\ -	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;			\ -	}								\ -} while(0) + * 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 */  |