diff options
Diffstat (limited to 'drivers/vhost/vhost.h')
| -rw-r--r-- | drivers/vhost/vhost.h | 55 | 
1 files changed, 37 insertions, 18 deletions
diff --git a/drivers/vhost/vhost.h b/drivers/vhost/vhost.h index 11ee13dba0f..afd77295971 100644 --- a/drivers/vhost/vhost.h +++ b/drivers/vhost/vhost.h @@ -5,13 +5,13 @@  #include <linux/vhost.h>  #include <linux/mm.h>  #include <linux/mutex.h> -#include <linux/workqueue.h>  #include <linux/poll.h>  #include <linux/file.h>  #include <linux/skbuff.h>  #include <linux/uio.h>  #include <linux/virtio_config.h>  #include <linux/virtio_ring.h> +#include <asm/atomic.h>  struct vhost_device; @@ -20,19 +20,31 @@ enum {  	VHOST_NET_MAX_SG = MAX_SKB_FRAGS + 2,  }; +struct vhost_work; +typedef void (*vhost_work_fn_t)(struct vhost_work *work); + +struct vhost_work { +	struct list_head	  node; +	vhost_work_fn_t		  fn; +	wait_queue_head_t	  done; +	int			  flushing; +	unsigned		  queue_seq; +	unsigned		  done_seq; +}; +  /* Poll a file (eventfd or socket) */  /* Note: there's nothing vhost specific about this structure. */  struct vhost_poll {  	poll_table                table;  	wait_queue_head_t        *wqh;  	wait_queue_t              wait; -	/* struct which will handle all actual work. */ -	struct work_struct        work; +	struct vhost_work	  work;  	unsigned long		  mask; +	struct vhost_dev	 *dev;  }; -void vhost_poll_init(struct vhost_poll *poll, work_func_t func, -		     unsigned long mask); +void vhost_poll_init(struct vhost_poll *poll, vhost_work_fn_t fn, +		     unsigned long mask, struct vhost_dev *dev);  void vhost_poll_start(struct vhost_poll *poll, struct file *file);  void vhost_poll_stop(struct vhost_poll *poll);  void vhost_poll_flush(struct vhost_poll *poll); @@ -63,7 +75,7 @@ struct vhost_virtqueue {  	struct vhost_poll poll;  	/* The routine to call when the Guest pings us, or timeout. */ -	work_func_t handle_kick; +	vhost_work_fn_t handle_kick;  	/* Last available index we saw. */  	u16 last_avail_idx; @@ -84,13 +96,15 @@ struct vhost_virtqueue {  	struct iovec indirect[VHOST_NET_MAX_SG];  	struct iovec iov[VHOST_NET_MAX_SG];  	struct iovec hdr[VHOST_NET_MAX_SG]; -	size_t hdr_size; +	size_t vhost_hlen; +	size_t sock_hlen; +	struct vring_used_elem heads[VHOST_NET_MAX_SG];  	/* We use a kind of RCU to access private pointer. -	 * All readers access it from workqueue, which makes it possible to -	 * flush the workqueue instead of synchronize_rcu. Therefore readers do +	 * All readers access it from worker, which makes it possible to +	 * flush the vhost_work instead of synchronize_rcu. Therefore readers do  	 * not need to call rcu_read_lock/rcu_read_unlock: the beginning of -	 * work item execution acts instead of rcu_read_lock() and the end of -	 * work item execution acts instead of rcu_read_lock(). +	 * vhost_work execution acts instead of rcu_read_lock() and the end of +	 * vhost_work execution acts instead of rcu_read_lock().  	 * Writers use virtqueue mutex. */  	void *private_data;  	/* Log write descriptors */ @@ -110,6 +124,9 @@ struct vhost_dev {  	int nvqs;  	struct file *log_file;  	struct eventfd_ctx *log_ctx; +	spinlock_t work_lock; +	struct list_head work_list; +	struct task_struct *worker;  };  long vhost_dev_init(struct vhost_dev *, struct vhost_virtqueue *vqs, int nvqs); @@ -124,21 +141,22 @@ int vhost_get_vq_desc(struct vhost_dev *, struct vhost_virtqueue *,  		      struct iovec iov[], unsigned int iov_count,  		      unsigned int *out_num, unsigned int *in_num,  		      struct vhost_log *log, unsigned int *log_num); -void vhost_discard_vq_desc(struct vhost_virtqueue *); +void vhost_discard_vq_desc(struct vhost_virtqueue *, int n);  int vhost_add_used(struct vhost_virtqueue *, unsigned int head, int len); -void vhost_signal(struct vhost_dev *, struct vhost_virtqueue *); +int vhost_add_used_n(struct vhost_virtqueue *, struct vring_used_elem *heads, +		     unsigned count);  void vhost_add_used_and_signal(struct vhost_dev *, struct vhost_virtqueue *, -			       unsigned int head, int len); +			       unsigned int id, int len); +void vhost_add_used_and_signal_n(struct vhost_dev *, struct vhost_virtqueue *, +			       struct vring_used_elem *heads, unsigned count); +void vhost_signal(struct vhost_dev *, struct vhost_virtqueue *);  void vhost_disable_notify(struct vhost_virtqueue *);  bool vhost_enable_notify(struct vhost_virtqueue *);  int vhost_log_write(struct vhost_virtqueue *vq, struct vhost_log *log,  		    unsigned int log_num, u64 len); -int vhost_init(void); -void vhost_cleanup(void); -  #define vq_err(vq, fmt, ...) do {                                  \  		pr_debug(pr_fmt(fmt), ##__VA_ARGS__);       \  		if ((vq)->error_ctx)                               \ @@ -149,7 +167,8 @@ enum {  	VHOST_FEATURES = (1 << VIRTIO_F_NOTIFY_ON_EMPTY) |  			 (1 << VIRTIO_RING_F_INDIRECT_DESC) |  			 (1 << VHOST_F_LOG_ALL) | -			 (1 << VHOST_NET_F_VIRTIO_NET_HDR), +			 (1 << VHOST_NET_F_VIRTIO_NET_HDR) | +			 (1 << VIRTIO_NET_F_MRG_RXBUF),  };  static inline int vhost_has_feature(struct vhost_dev *dev, int bit)  |