Skip to content

Commit

Permalink
Merge tag 'virtio-next-for-linus' of git://git.kernel.org/pub/scm/lin…
Browse files Browse the repository at this point in the history
…ux/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
  • Loading branch information
torvalds committed Nov 15, 2013
2 parents ce6513f + 2bf4fd3 commit b746f9c
Show file tree
Hide file tree
Showing 21 changed files with 310 additions and 166 deletions.
83 changes: 37 additions & 46 deletions drivers/block/virtio_blk.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -608,9 +606,9 @@ 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),
&writeback);
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);

Expand Down Expand Up @@ -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; )
Expand All @@ -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;
}
Expand Down Expand Up @@ -699,9 +692,9 @@ 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),
&sg_elems);
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. */
if (err || !sg_elems)
Expand Down Expand Up @@ -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) {
Expand All @@ -794,46 +786,45 @@ 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),
&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);
else
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),
&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),
&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),
&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),
&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);

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions drivers/char/hw_random/virtio-rng.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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
Expand Down
25 changes: 11 additions & 14 deletions drivers/char/virtio_console.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -2014,10 +2012,9 @@ 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),
&portdev->config.max_nr_ports) == 0) {
virtio_cread_feature(vdev, VIRTIO_CONSOLE_F_MULTIPORT,
struct virtio_console_config, max_nr_ports,
&portdev->config.max_nr_ports) == 0) {
multiport = true;
}

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down
3 changes: 2 additions & 1 deletion drivers/lguest/lguest_device.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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. */
Expand Down
6 changes: 4 additions & 2 deletions drivers/lguest/x86/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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
Expand Down
23 changes: 12 additions & 11 deletions drivers/net/caif/caif_virtio.c
Original file line number Diff line number Diff line change
Expand Up @@ -686,18 +686,19 @@ static int cfv_probe(struct virtio_device *vdev)
goto err;

/* Get the CAIF configuration from virtio config space, if available */
#define GET_VIRTIO_CONFIG_OPS(_v, _var, _f) \
((_v)->config->get(_v, offsetof(struct virtio_caif_transf_config, _f), \
&_var, \
FIELD_SIZEOF(struct virtio_caif_transf_config, _f)))

if (vdev->config->get) {
GET_VIRTIO_CONFIG_OPS(vdev, cfv->tx_hr, headroom);
GET_VIRTIO_CONFIG_OPS(vdev, cfv->rx_hr, headroom);
GET_VIRTIO_CONFIG_OPS(vdev, cfv->tx_tr, tailroom);
GET_VIRTIO_CONFIG_OPS(vdev, cfv->rx_tr, tailroom);
GET_VIRTIO_CONFIG_OPS(vdev, cfv->mtu, mtu);
GET_VIRTIO_CONFIG_OPS(vdev, cfv->mru, mtu);
virtio_cread(vdev, struct virtio_caif_transf_config, headroom,
&cfv->tx_hr);
virtio_cread(vdev, struct virtio_caif_transf_config, headroom,
&cfv->rx_hr);
virtio_cread(vdev, struct virtio_caif_transf_config, tailroom,
&cfv->tx_tr);
virtio_cread(vdev, struct virtio_caif_transf_config, tailroom,
&cfv->rx_tr);
virtio_cread(vdev, struct virtio_caif_transf_config, mtu,
&cfv->mtu);
virtio_cread(vdev, struct virtio_caif_transf_config, mtu,
&cfv->mru);
} else {
cfv->tx_hr = CFV_DEF_HEADROOM;
cfv->rx_hr = CFV_DEF_HEADROOM;
Expand Down
Loading

0 comments on commit b746f9c

Please sign in to comment.