From 0b90d0622ad290b3717a13489b396af52aea9d2d Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Mon, 14 Oct 2013 18:11:51 +1030 Subject: virtio_config: introduce size-based accessors. This lets the us do endian conversion if necessary, and insulates the drivers from that change. Signed-off-by: Rusty Russell --- include/linux/virtio_config.h | 134 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 134 insertions(+) (limited to 'include') diff --git a/include/linux/virtio_config.h b/include/linux/virtio_config.h index 29b9104232b4..490a4bbd59a3 100644 --- a/include/linux/virtio_config.h +++ b/include/linux/virtio_config.h @@ -162,5 +162,139 @@ int virtqueue_set_affinity(struct virtqueue *vq, int cpu) return 0; } +/* Config space accessors. */ +#define virtio_cread(vdev, structname, member, ptr) \ + do { \ + /* Must match the member's type, and be integer */ \ + if (!typecheck(typeof((((structname*)0)->member)), *(ptr))) \ + (*ptr) = 1; \ + \ + switch (sizeof(*ptr)) { \ + case 1: \ + *(ptr) = virtio_cread8(vdev, \ + offsetof(structname, member)); \ + break; \ + case 2: \ + *(ptr) = virtio_cread16(vdev, \ + offsetof(structname, member)); \ + break; \ + case 4: \ + *(ptr) = virtio_cread32(vdev, \ + offsetof(structname, member)); \ + break; \ + case 8: \ + *(ptr) = virtio_cread64(vdev, \ + offsetof(structname, member)); \ + break; \ + default: \ + BUG(); \ + } \ + } while(0) + +/* Config space accessors. */ +#define virtio_cwrite(vdev, structname, member, ptr) \ + do { \ + /* Must match the member's type, and be integer */ \ + if (!typecheck(typeof((((structname*)0)->member)), *(ptr))) \ + BUG_ON((*ptr) == 1); \ + \ + switch (sizeof(*ptr)) { \ + case 1: \ + virtio_cwrite8(vdev, \ + offsetof(structname, member), \ + *(ptr)); \ + break; \ + case 2: \ + virtio_cwrite16(vdev, \ + offsetof(structname, member), \ + *(ptr)); \ + break; \ + case 4: \ + virtio_cwrite32(vdev, \ + offsetof(structname, member), \ + *(ptr)); \ + break; \ + case 8: \ + virtio_cwrite64(vdev, \ + offsetof(structname, member), \ + *(ptr)); \ + break; \ + default: \ + BUG(); \ + } \ + } while(0) + +static inline u8 virtio_cread8(struct virtio_device *vdev, unsigned int offset) +{ + u8 ret; + vdev->config->get(vdev, offset, &ret, sizeof(ret)); + return ret; +} + +static inline void virtio_cread_bytes(struct virtio_device *vdev, + unsigned int offset, + void *buf, size_t len) +{ + vdev->config->get(vdev, offset, buf, len); +} + +static inline void virtio_cwrite8(struct virtio_device *vdev, + unsigned int offset, u8 val) +{ + vdev->config->set(vdev, offset, &val, sizeof(val)); +} + +static inline u16 virtio_cread16(struct virtio_device *vdev, + unsigned int offset) +{ + u16 ret; + vdev->config->get(vdev, offset, &ret, sizeof(ret)); + return ret; +} + +static inline void virtio_cwrite16(struct virtio_device *vdev, + unsigned int offset, u16 val) +{ + vdev->config->set(vdev, offset, &val, sizeof(val)); +} + +static inline u32 virtio_cread32(struct virtio_device *vdev, + unsigned int offset) +{ + u32 ret; + vdev->config->get(vdev, offset, &ret, sizeof(ret)); + return ret; +} + +static inline void virtio_cwrite32(struct virtio_device *vdev, + unsigned int offset, u32 val) +{ + vdev->config->set(vdev, offset, &val, sizeof(val)); +} + +static inline u64 virtio_cread64(struct virtio_device *vdev, + unsigned int offset) +{ + u64 ret; + vdev->config->get(vdev, offset, &ret, sizeof(ret)); + return ret; +} + +static inline void virtio_cwrite64(struct virtio_device *vdev, + unsigned int offset, u64 val) +{ + vdev->config->set(vdev, offset, &val, sizeof(val)); +} + +/* Conditional config space accessors. */ +#define virtio_cread_feature(vdev, fbit, structname, member, ptr) \ + ({ \ + int _r = 0; \ + if (!virtio_has_feature(vdev, fbit)) \ + _r = -ENOENT; \ + else \ + virtio_cread((vdev), structname, member, ptr); \ + _r; \ + }) #endif /* _LINUX_VIRTIO_CONFIG_H */ -- cgit v1.2.3 From 630b54d33493d1f67e79b148b5e361c5bbd3f29d Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Mon, 14 Oct 2013 18:11:51 +1030 Subject: virtio_config: remove virtio_config_val The virtio_cread() functions should now be used. Signed-off-by: Rusty Russell --- include/linux/virtio_config.h | 27 --------------------------- 1 file changed, 27 deletions(-) (limited to 'include') diff --git a/include/linux/virtio_config.h b/include/linux/virtio_config.h index 490a4bbd59a3..e8f8f71e843c 100644 --- a/include/linux/virtio_config.h +++ b/include/linux/virtio_config.h @@ -96,33 +96,6 @@ static inline bool virtio_has_feature(const struct virtio_device *vdev, return test_bit(fbit, vdev->features); } -/** - * 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. - * @v: a pointer to the value to fill in. - * - * 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)) - -#define virtio_config_val_len(vdev, fbit, offset, v, len) \ - virtio_config_buf((vdev), (fbit), (offset), (v), (len)) - -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; -} - static inline struct virtqueue *virtio_find_single_vq(struct virtio_device *vdev, vq_callback_t *c, const char *n) -- cgit v1.2.3 From 46f9c2b925ac12e5ad8b8b7c90c71dacc9d5db37 Mon Sep 17 00:00:00 2001 From: Heinz Graalfs Date: Tue, 29 Oct 2013 09:38:50 +1030 Subject: virtio_ring: change host notification API Currently a host kick error is silently ignored and not reflected in the virtqueue of a particular virtio device. Changing the notify API for guest->host notification seems to be one prerequisite in order to be able to handle such errors in the context where the kick is triggered. This patch changes the notify API. The notify function must return a bool return value. It returns false if the host notification failed. Signed-off-by: Heinz Graalfs Signed-off-by: Rusty Russell --- include/linux/virtio_ring.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/virtio_ring.h b/include/linux/virtio_ring.h index b300787af8e0..67e06fe18c03 100644 --- a/include/linux/virtio_ring.h +++ b/include/linux/virtio_ring.h @@ -71,7 +71,7 @@ struct virtqueue *vring_new_virtqueue(unsigned int index, struct virtio_device *vdev, bool weak_barriers, void *pages, - void (*notify)(struct virtqueue *vq), + bool (*notify)(struct virtqueue *vq), void (*callback)(struct virtqueue *vq), const char *name); void vring_del_virtqueue(struct virtqueue *vq); -- cgit v1.2.3 From 5b1bf7cb673ade0ab5c75f200dce911d9fb91c21 Mon Sep 17 00:00:00 2001 From: Heinz Graalfs Date: Tue, 29 Oct 2013 09:39:48 +1030 Subject: virtio_ring: let virtqueue_{kick()/notify()} return a bool virtqueue_{kick()/notify()} should exploit the new host notification API. If the notify call returned with a negative value the host kick failed (e.g. a kick triggered after a device was hot-unplugged). In this case the virtqueue is set to 'broken' and false is returned, otherwise true. Signed-off-by: Heinz Graalfs Signed-off-by: Rusty Russell --- include/linux/virtio.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/linux/virtio.h b/include/linux/virtio.h index 36d36cc89329..9b4de15fcb2f 100644 --- a/include/linux/virtio.h +++ b/include/linux/virtio.h @@ -51,11 +51,11 @@ int virtqueue_add_sgs(struct virtqueue *vq, void *data, gfp_t gfp); -void virtqueue_kick(struct virtqueue *vq); +bool virtqueue_kick(struct virtqueue *vq); bool virtqueue_kick_prepare(struct virtqueue *vq); -void virtqueue_notify(struct virtqueue *vq); +bool virtqueue_notify(struct virtqueue *vq); void *virtqueue_get_buf(struct virtqueue *vq, unsigned int *len); -- cgit v1.2.3 From b3b32c94133621c9ba7e4c8f29ec7533f2f4d8ec Mon Sep 17 00:00:00 2001 From: Heinz Graalfs Date: Tue, 29 Oct 2013 09:40:19 +1030 Subject: virtio_ring: add new function virtqueue_is_broken() Add new function virtqueue_is_broken(). Callers of virtqueue_get_buf() should check for a broken queue. Signed-off-by: Heinz Graalfs Signed-off-by: Rusty Russell --- include/linux/virtio.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include') diff --git a/include/linux/virtio.h b/include/linux/virtio.h index 9b4de15fcb2f..e4abb84199be 100644 --- a/include/linux/virtio.h +++ b/include/linux/virtio.h @@ -73,6 +73,8 @@ void *virtqueue_detach_unused_buf(struct virtqueue *vq); unsigned int virtqueue_get_vring_size(struct virtqueue *vq); +bool virtqueue_is_broken(struct virtqueue *vq); + /** * virtio_device - representation of a device using virtio * @index: unique position on the virtio bus -- cgit v1.2.3