Commit 4d272f90 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull virtio fixes from Rusty Russell:
 "Not entirely surprising: the ongoing QEMU work on virtio 1.0 has
  revealed more minor issues with our virtio 1.0 drivers just introduced
  in the kernel.

  (I would normally use my fixes branch for this, but there were a batch
  of them...)"

* tag 'virtio-next-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux:
  virtio_mmio: fix access width for mmio
  uapi/virtio_scsi: allow overriding CDB/SENSE size
  virtio_mmio: generation support
  virtio_rpmsg: set DRIVER_OK before using device
  9p/trans_virtio: fix hot-unplug
  virtio-balloon: do not call blocking ops when !TASK_RUNNING
  virtio_blk: fix comment for virtio 1.0
  virtio_blk: typo fix
  virtio_balloon: set DRIVER_OK before using device
  virtio_console: avoid config access from irq
  virtio_console: init work unconditionally
parents 2fc67756 704a0b5f
...@@ -142,6 +142,7 @@ struct ports_device { ...@@ -142,6 +142,7 @@ struct ports_device {
* notification * notification
*/ */
struct work_struct control_work; struct work_struct control_work;
struct work_struct config_work;
struct list_head ports; struct list_head ports;
...@@ -1837,10 +1838,21 @@ static void config_intr(struct virtio_device *vdev) ...@@ -1837,10 +1838,21 @@ static void config_intr(struct virtio_device *vdev)
portdev = vdev->priv; portdev = vdev->priv;
if (!use_multiport(portdev))
schedule_work(&portdev->config_work);
}
static void config_work_handler(struct work_struct *work)
{
struct ports_device *portdev;
portdev = container_of(work, struct ports_device, control_work);
if (!use_multiport(portdev)) { if (!use_multiport(portdev)) {
struct virtio_device *vdev;
struct port *port; struct port *port;
u16 rows, cols; u16 rows, cols;
vdev = portdev->vdev;
virtio_cread(vdev, struct virtio_console_config, cols, &cols); virtio_cread(vdev, struct virtio_console_config, cols, &cols);
virtio_cread(vdev, struct virtio_console_config, rows, &rows); virtio_cread(vdev, struct virtio_console_config, rows, &rows);
...@@ -2040,12 +2052,14 @@ static int virtcons_probe(struct virtio_device *vdev) ...@@ -2040,12 +2052,14 @@ static int virtcons_probe(struct virtio_device *vdev)
virtio_device_ready(portdev->vdev); virtio_device_ready(portdev->vdev);
INIT_WORK(&portdev->config_work, &config_work_handler);
INIT_WORK(&portdev->control_work, &control_work_handler);
if (multiport) { if (multiport) {
unsigned int nr_added_bufs; unsigned int nr_added_bufs;
spin_lock_init(&portdev->c_ivq_lock); spin_lock_init(&portdev->c_ivq_lock);
spin_lock_init(&portdev->c_ovq_lock); spin_lock_init(&portdev->c_ovq_lock);
INIT_WORK(&portdev->control_work, &control_work_handler);
nr_added_bufs = fill_queue(portdev->c_ivq, nr_added_bufs = fill_queue(portdev->c_ivq,
&portdev->c_ivq_lock); &portdev->c_ivq_lock);
...@@ -2113,6 +2127,8 @@ static void virtcons_remove(struct virtio_device *vdev) ...@@ -2113,6 +2127,8 @@ static void virtcons_remove(struct virtio_device *vdev)
/* Finish up work that's lined up */ /* Finish up work that's lined up */
if (use_multiport(portdev)) if (use_multiport(portdev))
cancel_work_sync(&portdev->control_work); cancel_work_sync(&portdev->control_work);
else
cancel_work_sync(&portdev->config_work);
list_for_each_entry_safe(port, port2, &portdev->ports, list) list_for_each_entry_safe(port, port2, &portdev->ports, list)
unplug_port(port); unplug_port(port);
...@@ -2164,6 +2180,7 @@ static int virtcons_freeze(struct virtio_device *vdev) ...@@ -2164,6 +2180,7 @@ static int virtcons_freeze(struct virtio_device *vdev)
virtqueue_disable_cb(portdev->c_ivq); virtqueue_disable_cb(portdev->c_ivq);
cancel_work_sync(&portdev->control_work); cancel_work_sync(&portdev->control_work);
cancel_work_sync(&portdev->config_work);
/* /*
* Once more: if control_work_handler() was running, it would * Once more: if control_work_handler() was running, it would
* enable the cb as the last step. * enable the cb as the last step.
......
...@@ -951,6 +951,7 @@ static int rpmsg_probe(struct virtio_device *vdev) ...@@ -951,6 +951,7 @@ static int rpmsg_probe(struct virtio_device *vdev)
void *bufs_va; void *bufs_va;
int err = 0, i; int err = 0, i;
size_t total_buf_space; size_t total_buf_space;
bool notify;
vrp = kzalloc(sizeof(*vrp), GFP_KERNEL); vrp = kzalloc(sizeof(*vrp), GFP_KERNEL);
if (!vrp) if (!vrp)
...@@ -1030,8 +1031,22 @@ static int rpmsg_probe(struct virtio_device *vdev) ...@@ -1030,8 +1031,22 @@ static int rpmsg_probe(struct virtio_device *vdev)
} }
} }
/*
* Prepare to kick but don't notify yet - we can't do this before
* device is ready.
*/
notify = virtqueue_kick_prepare(vrp->rvq);
/* From this point on, we can notify and get callbacks. */
virtio_device_ready(vdev);
/* tell the remote processor it can start sending messages */ /* tell the remote processor it can start sending messages */
virtqueue_kick(vrp->rvq); /*
* this might be concurrent with callbacks, but we are only
* doing notify, not a full kick here, so that's ok.
*/
if (notify)
virtqueue_notify(vrp->rvq);
dev_info(&vdev->dev, "rpmsg host is online\n"); dev_info(&vdev->dev, "rpmsg host is online\n");
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/balloon_compaction.h> #include <linux/balloon_compaction.h>
#include <linux/oom.h> #include <linux/oom.h>
#include <linux/wait.h>
/* /*
* Balloon device works in 4K page units. So each page is pointed to by * Balloon device works in 4K page units. So each page is pointed to by
...@@ -334,17 +335,25 @@ static int virtballoon_oom_notify(struct notifier_block *self, ...@@ -334,17 +335,25 @@ static int virtballoon_oom_notify(struct notifier_block *self,
static int balloon(void *_vballoon) static int balloon(void *_vballoon)
{ {
struct virtio_balloon *vb = _vballoon; struct virtio_balloon *vb = _vballoon;
DEFINE_WAIT_FUNC(wait, woken_wake_function);
set_freezable(); set_freezable();
while (!kthread_should_stop()) { while (!kthread_should_stop()) {
s64 diff; s64 diff;
try_to_freeze(); try_to_freeze();
wait_event_interruptible(vb->config_change,
(diff = towards_target(vb)) != 0 add_wait_queue(&vb->config_change, &wait);
|| vb->need_stats_update for (;;) {
|| kthread_should_stop() if ((diff = towards_target(vb)) != 0 ||
|| freezing(current)); vb->need_stats_update ||
kthread_should_stop() ||
freezing(current))
break;
wait_woken(&wait, TASK_INTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT);
}
remove_wait_queue(&vb->config_change, &wait);
if (vb->need_stats_update) if (vb->need_stats_update)
stats_handle_request(vb); stats_handle_request(vb);
if (diff > 0) if (diff > 0)
...@@ -499,6 +508,8 @@ static int virtballoon_probe(struct virtio_device *vdev) ...@@ -499,6 +508,8 @@ static int virtballoon_probe(struct virtio_device *vdev)
if (err < 0) if (err < 0)
goto out_oom_notify; goto out_oom_notify;
virtio_device_ready(vdev);
vb->thread = kthread_run(balloon, vb, "vballoon"); vb->thread = kthread_run(balloon, vb, "vballoon");
if (IS_ERR(vb->thread)) { if (IS_ERR(vb->thread)) {
err = PTR_ERR(vb->thread); err = PTR_ERR(vb->thread);
......
...@@ -156,22 +156,95 @@ static void vm_get(struct virtio_device *vdev, unsigned offset, ...@@ -156,22 +156,95 @@ static void vm_get(struct virtio_device *vdev, unsigned offset,
void *buf, unsigned len) void *buf, unsigned len)
{ {
struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev); struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev);
void __iomem *base = vm_dev->base + VIRTIO_MMIO_CONFIG;
u8 b;
__le16 w;
__le32 l;
if (vm_dev->version == 1) {
u8 *ptr = buf; u8 *ptr = buf;
int i; int i;
for (i = 0; i < len; i++) for (i = 0; i < len; i++)
ptr[i] = readb(vm_dev->base + VIRTIO_MMIO_CONFIG + offset + i); ptr[i] = readb(base + offset + i);
return;
}
switch (len) {
case 1:
b = readb(base + offset);
memcpy(buf, &b, sizeof b);
break;
case 2:
w = cpu_to_le16(readw(base + offset));
memcpy(buf, &w, sizeof w);
break;
case 4:
l = cpu_to_le32(readl(base + offset));
memcpy(buf, &l, sizeof l);
break;
case 8:
l = cpu_to_le32(readl(base + offset));
memcpy(buf, &l, sizeof l);
l = cpu_to_le32(ioread32(base + offset + sizeof l));
memcpy(buf + sizeof l, &l, sizeof l);
break;
default:
BUG();
}
} }
static void vm_set(struct virtio_device *vdev, unsigned offset, static void vm_set(struct virtio_device *vdev, unsigned offset,
const void *buf, unsigned len) const void *buf, unsigned len)
{ {
struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev); struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev);
void __iomem *base = vm_dev->base + VIRTIO_MMIO_CONFIG;
u8 b;
__le16 w;
__le32 l;
if (vm_dev->version == 1) {
const u8 *ptr = buf; const u8 *ptr = buf;
int i; int i;
for (i = 0; i < len; i++) for (i = 0; i < len; i++)
writeb(ptr[i], vm_dev->base + VIRTIO_MMIO_CONFIG + offset + i); writeb(ptr[i], base + offset + i);
return;
}
switch (len) {
case 1:
memcpy(&b, buf, sizeof b);
writeb(b, base + offset);
break;
case 2:
memcpy(&w, buf, sizeof w);
writew(le16_to_cpu(w), base + offset);
break;
case 4:
memcpy(&l, buf, sizeof l);
writel(le32_to_cpu(l), base + offset);
break;
case 8:
memcpy(&l, buf, sizeof l);
writel(le32_to_cpu(l), base + offset);
memcpy(&l, buf + sizeof l, sizeof l);
writel(le32_to_cpu(l), base + offset + sizeof l);
break;
default:
BUG();
}
}
static u32 vm_generation(struct virtio_device *vdev)
{
struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev);
if (vm_dev->version == 1)
return 0;
else
return readl(vm_dev->base + VIRTIO_MMIO_CONFIG_GENERATION);
} }
static u8 vm_get_status(struct virtio_device *vdev) static u8 vm_get_status(struct virtio_device *vdev)
...@@ -440,6 +513,7 @@ static const char *vm_bus_name(struct virtio_device *vdev) ...@@ -440,6 +513,7 @@ static const char *vm_bus_name(struct virtio_device *vdev)
static const struct virtio_config_ops virtio_mmio_config_ops = { static const struct virtio_config_ops virtio_mmio_config_ops = {
.get = vm_get, .get = vm_get,
.set = vm_set, .set = vm_set,
.generation = vm_generation,
.get_status = vm_get_status, .get_status = vm_get_status,
.set_status = vm_set_status, .set_status = vm_set_status,
.reset = vm_reset, .reset = vm_reset,
......
...@@ -60,7 +60,7 @@ struct virtio_blk_config { ...@@ -60,7 +60,7 @@ struct virtio_blk_config {
__u32 size_max; __u32 size_max;
/* The maximum number of segments (if VIRTIO_BLK_F_SEG_MAX) */ /* The maximum number of segments (if VIRTIO_BLK_F_SEG_MAX) */
__u32 seg_max; __u32 seg_max;
/* geometry the device (if VIRTIO_BLK_F_GEOMETRY) */ /* geometry of the device (if VIRTIO_BLK_F_GEOMETRY) */
struct virtio_blk_geometry { struct virtio_blk_geometry {
__u16 cylinders; __u16 cylinders;
__u8 heads; __u8 heads;
...@@ -119,7 +119,11 @@ struct virtio_blk_config { ...@@ -119,7 +119,11 @@ struct virtio_blk_config {
#define VIRTIO_BLK_T_BARRIER 0x80000000 #define VIRTIO_BLK_T_BARRIER 0x80000000
#endif /* !VIRTIO_BLK_NO_LEGACY */ #endif /* !VIRTIO_BLK_NO_LEGACY */
/* This is the first element of the read scatter-gather list. */ /*
* This comes first in the read scatter-gather list.
* For legacy virtio, if VIRTIO_F_ANY_LAYOUT is not negotiated,
* this is the first element of the read scatter-gather list.
*/
struct virtio_blk_outhdr { struct virtio_blk_outhdr {
/* VIRTIO_BLK_T* */ /* VIRTIO_BLK_T* */
__virtio32 type; __virtio32 type;
......
...@@ -29,8 +29,16 @@ ...@@ -29,8 +29,16 @@
#include <linux/virtio_types.h> #include <linux/virtio_types.h>
#define VIRTIO_SCSI_CDB_SIZE 32 /* Default values of the CDB and sense data size configuration fields */
#define VIRTIO_SCSI_SENSE_SIZE 96 #define VIRTIO_SCSI_CDB_DEFAULT_SIZE 32
#define VIRTIO_SCSI_SENSE_DEFAULT_SIZE 96
#ifndef VIRTIO_SCSI_CDB_SIZE
#define VIRTIO_SCSI_CDB_SIZE VIRTIO_SCSI_CDB_DEFAULT_SIZE
#endif
#ifndef VIRTIO_SCSI_SENSE_SIZE
#define VIRTIO_SCSI_SENSE_SIZE VIRTIO_SCSI_SENSE_DEFAULT_SIZE
#endif
/* SCSI command request, followed by data-out */ /* SCSI command request, followed by data-out */
struct virtio_scsi_cmd_req { struct virtio_scsi_cmd_req {
......
...@@ -658,14 +658,30 @@ p9_virtio_create(struct p9_client *client, const char *devname, char *args) ...@@ -658,14 +658,30 @@ p9_virtio_create(struct p9_client *client, const char *devname, char *args)
static void p9_virtio_remove(struct virtio_device *vdev) static void p9_virtio_remove(struct virtio_device *vdev)
{ {
struct virtio_chan *chan = vdev->priv; struct virtio_chan *chan = vdev->priv;
unsigned long warning_time;
if (chan->inuse)
p9_virtio_close(chan->client);
vdev->config->del_vqs(vdev);
mutex_lock(&virtio_9p_lock); mutex_lock(&virtio_9p_lock);
/* Remove self from list so we don't get new users. */
list_del(&chan->chan_list); list_del(&chan->chan_list);
warning_time = jiffies;
/* Wait for existing users to close. */
while (chan->inuse) {
mutex_unlock(&virtio_9p_lock);
msleep(250);
if (time_after(jiffies, warning_time + 10 * HZ)) {
dev_emerg(&vdev->dev,
"p9_virtio_remove: waiting for device in use.\n");
warning_time = jiffies;
}
mutex_lock(&virtio_9p_lock);
}
mutex_unlock(&virtio_9p_lock); mutex_unlock(&virtio_9p_lock);
vdev->config->del_vqs(vdev);
sysfs_remove_file(&(vdev->dev.kobj), &dev_attr_mount_tag.attr); sysfs_remove_file(&(vdev->dev.kobj), &dev_attr_mount_tag.attr);
kobject_uevent(&(vdev->dev.kobj), KOBJ_CHANGE); kobject_uevent(&(vdev->dev.kobj), KOBJ_CHANGE);
kfree(chan->tag); kfree(chan->tag);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment