Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b746f9c7 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'virtio-next-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux

Pull virtio updates from Rusty Russell:
 "Nothing really exciting: some groundwork for changing virtio endian,
  and some robustness fixes for broken virtio devices, plus minor
  tweaks"

* tag 'virtio-next-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux:
  virtio_scsi: verify if queue is broken after virtqueue_get_buf()
  x86, asmlinkage, lguest: Pass in globals into assembler statement
  virtio: mmio: fix signature checking for BE guests
  virtio_ring: adapt to notify() returning bool
  virtio_net: verify if queue is broken after virtqueue_get_buf()
  virtio_console: verify if queue is broken after virtqueue_get_buf()
  virtio_blk: verify if queue is broken after virtqueue_get_buf()
  virtio_ring: add new function virtqueue_is_broken()
  virtio_test: verify if virtqueue_kick() succeeded
  virtio_net: verify if virtqueue_kick() succeeded
  virtio_ring: let virtqueue_{kick()/notify()} return a bool
  virtio_ring: change host notification API
  virtio_config: remove virtio_config_val
  virtio: use size-based config accessors.
  virtio_config: introduce size-based accessors.
  virtio_ring: plug kmemleak false positive.
  virtio: pm: use CONFIG_PM_SLEEP instead of CONFIG_PM
parents ce6513f7 2bf4fd31
Loading
Loading
Loading
Loading
+37 −46
Original line number Diff line number Diff line
@@ -292,6 +292,8 @@ static void virtblk_done(struct virtqueue *vq)
				req_done = true;
			}
		}
		if (unlikely(virtqueue_is_broken(vq)))
			break;
	} while (!virtqueue_enable_cb(vq));
	/* In case queue is stopped waiting for more buffers. */
	if (req_done)
@@ -456,18 +458,15 @@ static int virtblk_ioctl(struct block_device *bdev, fmode_t mode,
static int virtblk_getgeo(struct block_device *bd, struct hd_geometry *geo)
{
	struct virtio_blk *vblk = bd->bd_disk->private_data;
	struct virtio_blk_geometry vgeo;
	int err;

	/* see if the host passed in geometry config */
	err = virtio_config_val(vblk->vdev, VIRTIO_BLK_F_GEOMETRY,
				offsetof(struct virtio_blk_config, geometry),
				&vgeo);

	if (!err) {
		geo->heads = vgeo.heads;
		geo->sectors = vgeo.sectors;
		geo->cylinders = vgeo.cylinders;
	if (virtio_has_feature(vblk->vdev, VIRTIO_BLK_F_GEOMETRY)) {
		virtio_cread(vblk->vdev, struct virtio_blk_config,
			     geometry.cylinders, &geo->cylinders);
		virtio_cread(vblk->vdev, struct virtio_blk_config,
			     geometry.heads, &geo->heads);
		virtio_cread(vblk->vdev, struct virtio_blk_config,
			     geometry.sectors, &geo->sectors);
	} else {
		/* some standard values, similar to sd */
		geo->heads = 1 << 6;
@@ -529,8 +528,7 @@ static void virtblk_config_changed_work(struct work_struct *work)
		goto done;

	/* Host must always specify the capacity. */
	vdev->config->get(vdev, offsetof(struct virtio_blk_config, capacity),
			  &capacity, sizeof(capacity));
	virtio_cread(vdev, struct virtio_blk_config, capacity, &capacity);

	/* If capacity is too big, truncate with warning. */
	if ((sector_t)capacity != capacity) {
@@ -608,8 +606,8 @@ static int virtblk_get_cache_mode(struct virtio_device *vdev)
	u8 writeback;
	int err;

	err = virtio_config_val(vdev, VIRTIO_BLK_F_CONFIG_WCE,
				offsetof(struct virtio_blk_config, wce),
	err = virtio_cread_feature(vdev, VIRTIO_BLK_F_CONFIG_WCE,
				   struct virtio_blk_config, wce,
				   &writeback);
	if (err)
		writeback = virtio_has_feature(vdev, VIRTIO_BLK_F_WCE);
@@ -642,7 +640,6 @@ virtblk_cache_type_store(struct device *dev, struct device_attribute *attr,
	struct virtio_blk *vblk = disk->private_data;
	struct virtio_device *vdev = vblk->vdev;
	int i;
	u8 writeback;

	BUG_ON(!virtio_has_feature(vblk->vdev, VIRTIO_BLK_F_CONFIG_WCE));
	for (i = ARRAY_SIZE(virtblk_cache_types); --i >= 0; )
@@ -652,11 +649,7 @@ virtblk_cache_type_store(struct device *dev, struct device_attribute *attr,
	if (i < 0)
		return -EINVAL;

	writeback = i;
	vdev->config->set(vdev,
			  offsetof(struct virtio_blk_config, wce),
			  &writeback, sizeof(writeback));

	virtio_cwrite8(vdev, offsetof(struct virtio_blk_config, wce), i);
	virtblk_update_cache_mode(vdev);
	return count;
}
@@ -699,8 +692,8 @@ static int virtblk_probe(struct virtio_device *vdev)
	index = err;

	/* We need to know how many segments before we allocate. */
	err = virtio_config_val(vdev, VIRTIO_BLK_F_SEG_MAX,
				offsetof(struct virtio_blk_config, seg_max),
	err = virtio_cread_feature(vdev, VIRTIO_BLK_F_SEG_MAX,
				   struct virtio_blk_config, seg_max,
				   &sg_elems);

	/* We need at least one SG element, whatever they say. */
@@ -772,8 +765,7 @@ static int virtblk_probe(struct virtio_device *vdev)
		set_disk_ro(vblk->disk, 1);

	/* Host must always specify the capacity. */
	vdev->config->get(vdev, offsetof(struct virtio_blk_config, capacity),
			  &cap, sizeof(cap));
	virtio_cread(vdev, struct virtio_blk_config, capacity, &cap);

	/* If capacity is too big, truncate with warning. */
	if ((sector_t)cap != cap) {
@@ -794,17 +786,16 @@ static int virtblk_probe(struct virtio_device *vdev)

	/* Host can optionally specify maximum segment size and number of
	 * segments. */
	err = virtio_config_val(vdev, VIRTIO_BLK_F_SIZE_MAX,
				offsetof(struct virtio_blk_config, size_max),
				&v);
	err = virtio_cread_feature(vdev, VIRTIO_BLK_F_SIZE_MAX,
				   struct virtio_blk_config, size_max, &v);
	if (!err)
		blk_queue_max_segment_size(q, v);
	else
		blk_queue_max_segment_size(q, -1U);

	/* Host can optionally specify the block size of the device */
	err = virtio_config_val(vdev, VIRTIO_BLK_F_BLK_SIZE,
				offsetof(struct virtio_blk_config, blk_size),
	err = virtio_cread_feature(vdev, VIRTIO_BLK_F_BLK_SIZE,
				   struct virtio_blk_config, blk_size,
				   &blk_size);
	if (!err)
		blk_queue_logical_block_size(q, blk_size);
@@ -812,27 +803,27 @@ static int virtblk_probe(struct virtio_device *vdev)
		blk_size = queue_logical_block_size(q);

	/* Use topology information if available */
	err = virtio_config_val(vdev, VIRTIO_BLK_F_TOPOLOGY,
			offsetof(struct virtio_blk_config, physical_block_exp),
	err = virtio_cread_feature(vdev, VIRTIO_BLK_F_TOPOLOGY,
				   struct virtio_blk_config, physical_block_exp,
				   &physical_block_exp);
	if (!err && physical_block_exp)
		blk_queue_physical_block_size(q,
				blk_size * (1 << physical_block_exp));

	err = virtio_config_val(vdev, VIRTIO_BLK_F_TOPOLOGY,
			offsetof(struct virtio_blk_config, alignment_offset),
	err = virtio_cread_feature(vdev, VIRTIO_BLK_F_TOPOLOGY,
				   struct virtio_blk_config, alignment_offset,
				   &alignment_offset);
	if (!err && alignment_offset)
		blk_queue_alignment_offset(q, blk_size * alignment_offset);

	err = virtio_config_val(vdev, VIRTIO_BLK_F_TOPOLOGY,
			offsetof(struct virtio_blk_config, min_io_size),
	err = virtio_cread_feature(vdev, VIRTIO_BLK_F_TOPOLOGY,
				   struct virtio_blk_config, min_io_size,
				   &min_io_size);
	if (!err && min_io_size)
		blk_queue_io_min(q, blk_size * min_io_size);

	err = virtio_config_val(vdev, VIRTIO_BLK_F_TOPOLOGY,
			offsetof(struct virtio_blk_config, opt_io_size),
	err = virtio_cread_feature(vdev, VIRTIO_BLK_F_TOPOLOGY,
				   struct virtio_blk_config, opt_io_size,
				   &opt_io_size);
	if (!err && opt_io_size)
		blk_queue_io_opt(q, blk_size * opt_io_size);
@@ -899,7 +890,7 @@ static void virtblk_remove(struct virtio_device *vdev)
		ida_simple_remove(&vd_index_ida, index);
}

#ifdef CONFIG_PM
#ifdef CONFIG_PM_SLEEP
static int virtblk_freeze(struct virtio_device *vdev)
{
	struct virtio_blk *vblk = vdev->priv;
@@ -959,7 +950,7 @@ static struct virtio_driver virtio_blk = {
	.probe			= virtblk_probe,
	.remove			= virtblk_remove,
	.config_changed		= virtblk_config_changed,
#ifdef CONFIG_PM
#ifdef CONFIG_PM_SLEEP
	.freeze			= virtblk_freeze,
	.restore		= virtblk_restore,
#endif
+2 −2
Original line number Diff line number Diff line
@@ -133,7 +133,7 @@ static void virtrng_remove(struct virtio_device *vdev)
	remove_common(vdev);
}

#ifdef CONFIG_PM
#ifdef CONFIG_PM_SLEEP
static int virtrng_freeze(struct virtio_device *vdev)
{
	remove_common(vdev);
@@ -157,7 +157,7 @@ static struct virtio_driver virtio_rng_driver = {
	.id_table =	id_table,
	.probe =	virtrng_probe,
	.remove =	virtrng_remove,
#ifdef CONFIG_PM
#ifdef CONFIG_PM_SLEEP
	.freeze =	virtrng_freeze,
	.restore =	virtrng_restore,
#endif
+11 −14
Original line number Diff line number Diff line
@@ -577,7 +577,8 @@ static ssize_t __send_control_msg(struct ports_device *portdev, u32 port_id,
	spin_lock(&portdev->c_ovq_lock);
	if (virtqueue_add_outbuf(vq, sg, 1, &cpkt, GFP_ATOMIC) == 0) {
		virtqueue_kick(vq);
		while (!virtqueue_get_buf(vq, &len))
		while (!virtqueue_get_buf(vq, &len)
			&& !virtqueue_is_broken(vq))
			cpu_relax();
	}
	spin_unlock(&portdev->c_ovq_lock);
@@ -650,7 +651,8 @@ static ssize_t __send_to_port(struct port *port, struct scatterlist *sg,
	 * we need to kmalloc a GFP_ATOMIC buffer each time the
	 * console driver writes something out.
	 */
	while (!virtqueue_get_buf(out_vq, &len))
	while (!virtqueue_get_buf(out_vq, &len)
		&& !virtqueue_is_broken(out_vq))
		cpu_relax();
done:
	spin_unlock_irqrestore(&port->outvq_lock, flags);
@@ -1837,12 +1839,8 @@ static void config_intr(struct virtio_device *vdev)
		struct port *port;
		u16 rows, cols;

		vdev->config->get(vdev,
				  offsetof(struct virtio_console_config, cols),
				  &cols, sizeof(u16));
		vdev->config->get(vdev,
				  offsetof(struct virtio_console_config, rows),
				  &rows, sizeof(u16));
		virtio_cread(vdev, struct virtio_console_config, cols, &cols);
		virtio_cread(vdev, struct virtio_console_config, rows, &rows);

		port = find_port_by_id(portdev, 0);
		set_console_size(port, rows, cols);
@@ -2014,9 +2012,8 @@ static int virtcons_probe(struct virtio_device *vdev)

	/* Don't test MULTIPORT at all if we're rproc: not a valid feature! */
	if (!is_rproc_serial(vdev) &&
	    virtio_config_val(vdev, VIRTIO_CONSOLE_F_MULTIPORT,
				  offsetof(struct virtio_console_config,
					   max_nr_ports),
	    virtio_cread_feature(vdev, VIRTIO_CONSOLE_F_MULTIPORT,
				 struct virtio_console_config, max_nr_ports,
				 &portdev->config.max_nr_ports) == 0) {
		multiport = true;
	}
@@ -2142,7 +2139,7 @@ static struct virtio_device_id rproc_serial_id_table[] = {
static unsigned int rproc_serial_features[] = {
};

#ifdef CONFIG_PM
#ifdef CONFIG_PM_SLEEP
static int virtcons_freeze(struct virtio_device *vdev)
{
	struct ports_device *portdev;
@@ -2220,7 +2217,7 @@ static struct virtio_driver virtio_console = {
	.probe =	virtcons_probe,
	.remove =	virtcons_remove,
	.config_changed = config_intr,
#ifdef CONFIG_PM
#ifdef CONFIG_PM_SLEEP
	.freeze =	virtcons_freeze,
	.restore =	virtcons_restore,
#endif
+2 −1
Original line number Diff line number Diff line
@@ -229,7 +229,7 @@ struct lguest_vq_info {
 * make a hypercall.  We hand the physical address of the virtqueue so the Host
 * knows which virtqueue we're talking about.
 */
static void lg_notify(struct virtqueue *vq)
static bool lg_notify(struct virtqueue *vq)
{
	/*
	 * We store our virtqueue information in the "priv" pointer of the
@@ -238,6 +238,7 @@ static void lg_notify(struct virtqueue *vq)
	struct lguest_vq_info *lvq = vq->priv;

	hcall(LHCALL_NOTIFY, lvq->config.pfn << PAGE_SHIFT, 0, 0, 0);
	return true;
}

/* An extern declaration inside a C file is bad form.  Don't do it. */
+4 −2
Original line number Diff line number Diff line
@@ -157,7 +157,7 @@ static void run_guest_once(struct lg_cpu *cpu, struct lguest_pages *pages)
	 * stack, then the address of this call.  This stack layout happens to
	 * exactly match the stack layout created by an interrupt...
	 */
	asm volatile("pushf; lcall *lguest_entry"
	asm volatile("pushf; lcall *%4"
		     /*
		      * This is how we tell GCC that %eax ("a") and %ebx ("b")
		      * are changed by this routine.  The "=" means output.
@@ -169,7 +169,9 @@ static void run_guest_once(struct lg_cpu *cpu, struct lguest_pages *pages)
		      * physical address of the Guest's top-level page
		      * directory.
		      */
		     : "0"(pages), "1"(__pa(cpu->lg->pgdirs[cpu->cpu_pgd].pgdir))
		     : "0"(pages), 
		       "1"(__pa(cpu->lg->pgdirs[cpu->cpu_pgd].pgdir)),
		       "m"(lguest_entry)
		     /*
		      * We tell gcc that all these registers could change,
		      * which means we don't have to save and restore them in
Loading