diff options
| -rw-r--r-- | drivers/char/virtio_console.c | 19 | ||||
| -rw-r--r-- | drivers/rpmsg/virtio_rpmsg_bus.c | 17 | ||||
| -rw-r--r-- | drivers/virtio/virtio_balloon.c | 21 | ||||
| -rw-r--r-- | drivers/virtio/virtio_mmio.c | 90 | ||||
| -rw-r--r-- | include/uapi/linux/virtio_blk.h | 8 | ||||
| -rw-r--r-- | include/uapi/linux/virtio_scsi.h | 12 | ||||
| -rw-r--r-- | net/9p/trans_virtio.c | 24 |
7 files changed, 168 insertions, 23 deletions
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index fae2dbbf5745..72d7028f779b 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c | |||
| @@ -142,6 +142,7 @@ struct ports_device { | |||
| 142 | * notification | 142 | * notification |
| 143 | */ | 143 | */ |
| 144 | struct work_struct control_work; | 144 | struct work_struct control_work; |
| 145 | struct work_struct config_work; | ||
| 145 | 146 | ||
| 146 | struct list_head ports; | 147 | struct list_head ports; |
| 147 | 148 | ||
| @@ -1837,10 +1838,21 @@ static void config_intr(struct virtio_device *vdev) | |||
| 1837 | 1838 | ||
| 1838 | portdev = vdev->priv; | 1839 | portdev = vdev->priv; |
| 1839 | 1840 | ||
| 1841 | if (!use_multiport(portdev)) | ||
| 1842 | schedule_work(&portdev->config_work); | ||
| 1843 | } | ||
| 1844 | |||
| 1845 | static void config_work_handler(struct work_struct *work) | ||
| 1846 | { | ||
| 1847 | struct ports_device *portdev; | ||
| 1848 | |||
| 1849 | portdev = container_of(work, struct ports_device, control_work); | ||
| 1840 | if (!use_multiport(portdev)) { | 1850 | if (!use_multiport(portdev)) { |
| 1851 | struct virtio_device *vdev; | ||
| 1841 | struct port *port; | 1852 | struct port *port; |
| 1842 | u16 rows, cols; | 1853 | u16 rows, cols; |
| 1843 | 1854 | ||
| 1855 | vdev = portdev->vdev; | ||
| 1844 | virtio_cread(vdev, struct virtio_console_config, cols, &cols); | 1856 | virtio_cread(vdev, struct virtio_console_config, cols, &cols); |
| 1845 | virtio_cread(vdev, struct virtio_console_config, rows, &rows); | 1857 | virtio_cread(vdev, struct virtio_console_config, rows, &rows); |
| 1846 | 1858 | ||
| @@ -2040,12 +2052,14 @@ static int virtcons_probe(struct virtio_device *vdev) | |||
| 2040 | 2052 | ||
| 2041 | virtio_device_ready(portdev->vdev); | 2053 | virtio_device_ready(portdev->vdev); |
| 2042 | 2054 | ||
| 2055 | INIT_WORK(&portdev->config_work, &config_work_handler); | ||
| 2056 | INIT_WORK(&portdev->control_work, &control_work_handler); | ||
| 2057 | |||
| 2043 | if (multiport) { | 2058 | if (multiport) { |
| 2044 | unsigned int nr_added_bufs; | 2059 | unsigned int nr_added_bufs; |
| 2045 | 2060 | ||
| 2046 | spin_lock_init(&portdev->c_ivq_lock); | 2061 | spin_lock_init(&portdev->c_ivq_lock); |
| 2047 | spin_lock_init(&portdev->c_ovq_lock); | 2062 | spin_lock_init(&portdev->c_ovq_lock); |
| 2048 | INIT_WORK(&portdev->control_work, &control_work_handler); | ||
| 2049 | 2063 | ||
| 2050 | nr_added_bufs = fill_queue(portdev->c_ivq, | 2064 | nr_added_bufs = fill_queue(portdev->c_ivq, |
| 2051 | &portdev->c_ivq_lock); | 2065 | &portdev->c_ivq_lock); |
| @@ -2113,6 +2127,8 @@ static void virtcons_remove(struct virtio_device *vdev) | |||
| 2113 | /* Finish up work that's lined up */ | 2127 | /* Finish up work that's lined up */ |
| 2114 | if (use_multiport(portdev)) | 2128 | if (use_multiport(portdev)) |
| 2115 | cancel_work_sync(&portdev->control_work); | 2129 | cancel_work_sync(&portdev->control_work); |
| 2130 | else | ||
| 2131 | cancel_work_sync(&portdev->config_work); | ||
| 2116 | 2132 | ||
| 2117 | list_for_each_entry_safe(port, port2, &portdev->ports, list) | 2133 | list_for_each_entry_safe(port, port2, &portdev->ports, list) |
| 2118 | unplug_port(port); | 2134 | unplug_port(port); |
| @@ -2164,6 +2180,7 @@ static int virtcons_freeze(struct virtio_device *vdev) | |||
| 2164 | 2180 | ||
| 2165 | virtqueue_disable_cb(portdev->c_ivq); | 2181 | virtqueue_disable_cb(portdev->c_ivq); |
| 2166 | cancel_work_sync(&portdev->control_work); | 2182 | cancel_work_sync(&portdev->control_work); |
| 2183 | cancel_work_sync(&portdev->config_work); | ||
| 2167 | /* | 2184 | /* |
| 2168 | * Once more: if control_work_handler() was running, it would | 2185 | * Once more: if control_work_handler() was running, it would |
| 2169 | * enable the cb as the last step. | 2186 | * enable the cb as the last step. |
diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c index 92f6af6da699..73354ee27877 100644 --- a/drivers/rpmsg/virtio_rpmsg_bus.c +++ b/drivers/rpmsg/virtio_rpmsg_bus.c | |||
| @@ -951,6 +951,7 @@ static int rpmsg_probe(struct virtio_device *vdev) | |||
| 951 | void *bufs_va; | 951 | void *bufs_va; |
| 952 | int err = 0, i; | 952 | int err = 0, i; |
| 953 | size_t total_buf_space; | 953 | size_t total_buf_space; |
| 954 | bool notify; | ||
| 954 | 955 | ||
| 955 | vrp = kzalloc(sizeof(*vrp), GFP_KERNEL); | 956 | vrp = kzalloc(sizeof(*vrp), GFP_KERNEL); |
| 956 | if (!vrp) | 957 | if (!vrp) |
| @@ -1030,8 +1031,22 @@ static int rpmsg_probe(struct virtio_device *vdev) | |||
| 1030 | } | 1031 | } |
| 1031 | } | 1032 | } |
| 1032 | 1033 | ||
| 1034 | /* | ||
| 1035 | * Prepare to kick but don't notify yet - we can't do this before | ||
| 1036 | * device is ready. | ||
| 1037 | */ | ||
| 1038 | notify = virtqueue_kick_prepare(vrp->rvq); | ||
| 1039 | |||
| 1040 | /* From this point on, we can notify and get callbacks. */ | ||
| 1041 | virtio_device_ready(vdev); | ||
| 1042 | |||
| 1033 | /* tell the remote processor it can start sending messages */ | 1043 | /* tell the remote processor it can start sending messages */ |
| 1034 | virtqueue_kick(vrp->rvq); | 1044 | /* |
| 1045 | * this might be concurrent with callbacks, but we are only | ||
| 1046 | * doing notify, not a full kick here, so that's ok. | ||
| 1047 | */ | ||
| 1048 | if (notify) | ||
| 1049 | virtqueue_notify(vrp->rvq); | ||
| 1035 | 1050 | ||
| 1036 | dev_info(&vdev->dev, "rpmsg host is online\n"); | 1051 | dev_info(&vdev->dev, "rpmsg host is online\n"); |
| 1037 | 1052 | ||
diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c index 0413157f3b49..6a356e344f82 100644 --- a/drivers/virtio/virtio_balloon.c +++ b/drivers/virtio/virtio_balloon.c | |||
| @@ -29,6 +29,7 @@ | |||
| 29 | #include <linux/module.h> | 29 | #include <linux/module.h> |
| 30 | #include <linux/balloon_compaction.h> | 30 | #include <linux/balloon_compaction.h> |
| 31 | #include <linux/oom.h> | 31 | #include <linux/oom.h> |
| 32 | #include <linux/wait.h> | ||
| 32 | 33 | ||
| 33 | /* | 34 | /* |
| 34 | * Balloon device works in 4K page units. So each page is pointed to by | 35 | * 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 | static int balloon(void *_vballoon) | 335 | static int balloon(void *_vballoon) |
| 335 | { | 336 | { |
| 336 | struct virtio_balloon *vb = _vballoon; | 337 | struct virtio_balloon *vb = _vballoon; |
| 338 | DEFINE_WAIT_FUNC(wait, woken_wake_function); | ||
| 337 | 339 | ||
| 338 | set_freezable(); | 340 | set_freezable(); |
| 339 | while (!kthread_should_stop()) { | 341 | while (!kthread_should_stop()) { |
| 340 | s64 diff; | 342 | s64 diff; |
| 341 | 343 | ||
| 342 | try_to_freeze(); | 344 | try_to_freeze(); |
| 343 | wait_event_interruptible(vb->config_change, | 345 | |
| 344 | (diff = towards_target(vb)) != 0 | 346 | add_wait_queue(&vb->config_change, &wait); |
| 345 | || vb->need_stats_update | 347 | for (;;) { |
| 346 | || kthread_should_stop() | 348 | if ((diff = towards_target(vb)) != 0 || |
| 347 | || freezing(current)); | 349 | vb->need_stats_update || |
| 350 | kthread_should_stop() || | ||
| 351 | freezing(current)) | ||
| 352 | break; | ||
| 353 | wait_woken(&wait, TASK_INTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT); | ||
| 354 | } | ||
| 355 | remove_wait_queue(&vb->config_change, &wait); | ||
| 356 | |||
| 348 | if (vb->need_stats_update) | 357 | if (vb->need_stats_update) |
| 349 | stats_handle_request(vb); | 358 | stats_handle_request(vb); |
| 350 | if (diff > 0) | 359 | if (diff > 0) |
| @@ -499,6 +508,8 @@ static int virtballoon_probe(struct virtio_device *vdev) | |||
| 499 | if (err < 0) | 508 | if (err < 0) |
| 500 | goto out_oom_notify; | 509 | goto out_oom_notify; |
| 501 | 510 | ||
| 511 | virtio_device_ready(vdev); | ||
| 512 | |||
| 502 | vb->thread = kthread_run(balloon, vb, "vballoon"); | 513 | vb->thread = kthread_run(balloon, vb, "vballoon"); |
| 503 | if (IS_ERR(vb->thread)) { | 514 | if (IS_ERR(vb->thread)) { |
| 504 | err = PTR_ERR(vb->thread); | 515 | err = PTR_ERR(vb->thread); |
diff --git a/drivers/virtio/virtio_mmio.c b/drivers/virtio/virtio_mmio.c index cad569890908..6010d7ec0a0f 100644 --- a/drivers/virtio/virtio_mmio.c +++ b/drivers/virtio/virtio_mmio.c | |||
| @@ -156,22 +156,95 @@ static void vm_get(struct virtio_device *vdev, unsigned offset, | |||
| 156 | void *buf, unsigned len) | 156 | void *buf, unsigned len) |
| 157 | { | 157 | { |
| 158 | struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev); | 158 | struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev); |
| 159 | u8 *ptr = buf; | 159 | void __iomem *base = vm_dev->base + VIRTIO_MMIO_CONFIG; |
| 160 | int i; | 160 | u8 b; |
| 161 | __le16 w; | ||
| 162 | __le32 l; | ||
| 161 | 163 | ||
| 162 | for (i = 0; i < len; i++) | 164 | if (vm_dev->version == 1) { |
| 163 | ptr[i] = readb(vm_dev->base + VIRTIO_MMIO_CONFIG + offset + i); | 165 | u8 *ptr = buf; |
| 166 | int i; | ||
| 167 | |||
| 168 | for (i = 0; i < len; i++) | ||
| 169 | ptr[i] = readb(base + offset + i); | ||
| 170 | return; | ||
| 171 | } | ||
| 172 | |||
| 173 | switch (len) { | ||
| 174 | case 1: | ||
| 175 | b = readb(base + offset); | ||
| 176 | memcpy(buf, &b, sizeof b); | ||
| 177 | break; | ||
| 178 | case 2: | ||
| 179 | w = cpu_to_le16(readw(base + offset)); | ||
| 180 | memcpy(buf, &w, sizeof w); | ||
| 181 | break; | ||
| 182 | case 4: | ||
| 183 | l = cpu_to_le32(readl(base + offset)); | ||
| 184 | memcpy(buf, &l, sizeof l); | ||
| 185 | break; | ||
| 186 | case 8: | ||
| 187 | l = cpu_to_le32(readl(base + offset)); | ||
| 188 | memcpy(buf, &l, sizeof l); | ||
| 189 | l = cpu_to_le32(ioread32(base + offset + sizeof l)); | ||
| 190 | memcpy(buf + sizeof l, &l, sizeof l); | ||
| 191 | break; | ||
| 192 | default: | ||
| 193 | BUG(); | ||
| 194 | } | ||
| 164 | } | 195 | } |
| 165 | 196 | ||
| 166 | static void vm_set(struct virtio_device *vdev, unsigned offset, | 197 | static void vm_set(struct virtio_device *vdev, unsigned offset, |
| 167 | const void *buf, unsigned len) | 198 | const void *buf, unsigned len) |
| 168 | { | 199 | { |
| 169 | struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev); | 200 | struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev); |
| 170 | const u8 *ptr = buf; | 201 | void __iomem *base = vm_dev->base + VIRTIO_MMIO_CONFIG; |
| 171 | int i; | 202 | u8 b; |
| 203 | __le16 w; | ||
| 204 | __le32 l; | ||
| 172 | 205 | ||
| 173 | for (i = 0; i < len; i++) | 206 | if (vm_dev->version == 1) { |
| 174 | writeb(ptr[i], vm_dev->base + VIRTIO_MMIO_CONFIG + offset + i); | 207 | const u8 *ptr = buf; |
| 208 | int i; | ||
| 209 | |||
| 210 | for (i = 0; i < len; i++) | ||
| 211 | writeb(ptr[i], base + offset + i); | ||
| 212 | |||
| 213 | return; | ||
| 214 | } | ||
| 215 | |||
| 216 | switch (len) { | ||
| 217 | case 1: | ||
| 218 | memcpy(&b, buf, sizeof b); | ||
| 219 | writeb(b, base + offset); | ||
| 220 | break; | ||
| 221 | case 2: | ||
| 222 | memcpy(&w, buf, sizeof w); | ||
| 223 | writew(le16_to_cpu(w), base + offset); | ||
| 224 | break; | ||
| 225 | case 4: | ||
| 226 | memcpy(&l, buf, sizeof l); | ||
| 227 | writel(le32_to_cpu(l), base + offset); | ||
| 228 | break; | ||
| 229 | case 8: | ||
| 230 | memcpy(&l, buf, sizeof l); | ||
| 231 | writel(le32_to_cpu(l), base + offset); | ||
| 232 | memcpy(&l, buf + sizeof l, sizeof l); | ||
| 233 | writel(le32_to_cpu(l), base + offset + sizeof l); | ||
| 234 | break; | ||
| 235 | default: | ||
| 236 | BUG(); | ||
| 237 | } | ||
| 238 | } | ||
| 239 | |||
| 240 | static u32 vm_generation(struct virtio_device *vdev) | ||
| 241 | { | ||
| 242 | struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev); | ||
| 243 | |||
| 244 | if (vm_dev->version == 1) | ||
| 245 | return 0; | ||
| 246 | else | ||
| 247 | return readl(vm_dev->base + VIRTIO_MMIO_CONFIG_GENERATION); | ||
| 175 | } | 248 | } |
| 176 | 249 | ||
| 177 | static u8 vm_get_status(struct virtio_device *vdev) | 250 | static u8 vm_get_status(struct virtio_device *vdev) |
| @@ -440,6 +513,7 @@ static const char *vm_bus_name(struct virtio_device *vdev) | |||
| 440 | static const struct virtio_config_ops virtio_mmio_config_ops = { | 513 | static const struct virtio_config_ops virtio_mmio_config_ops = { |
| 441 | .get = vm_get, | 514 | .get = vm_get, |
| 442 | .set = vm_set, | 515 | .set = vm_set, |
| 516 | .generation = vm_generation, | ||
| 443 | .get_status = vm_get_status, | 517 | .get_status = vm_get_status, |
| 444 | .set_status = vm_set_status, | 518 | .set_status = vm_set_status, |
| 445 | .reset = vm_reset, | 519 | .reset = vm_reset, |
diff --git a/include/uapi/linux/virtio_blk.h b/include/uapi/linux/virtio_blk.h index 3c53eec4ae22..19c66fcbab8a 100644 --- a/include/uapi/linux/virtio_blk.h +++ b/include/uapi/linux/virtio_blk.h | |||
| @@ -60,7 +60,7 @@ struct virtio_blk_config { | |||
| 60 | __u32 size_max; | 60 | __u32 size_max; |
| 61 | /* The maximum number of segments (if VIRTIO_BLK_F_SEG_MAX) */ | 61 | /* The maximum number of segments (if VIRTIO_BLK_F_SEG_MAX) */ |
| 62 | __u32 seg_max; | 62 | __u32 seg_max; |
| 63 | /* geometry the device (if VIRTIO_BLK_F_GEOMETRY) */ | 63 | /* geometry of the device (if VIRTIO_BLK_F_GEOMETRY) */ |
| 64 | struct virtio_blk_geometry { | 64 | struct virtio_blk_geometry { |
| 65 | __u16 cylinders; | 65 | __u16 cylinders; |
| 66 | __u8 heads; | 66 | __u8 heads; |
| @@ -119,7 +119,11 @@ struct virtio_blk_config { | |||
| 119 | #define VIRTIO_BLK_T_BARRIER 0x80000000 | 119 | #define VIRTIO_BLK_T_BARRIER 0x80000000 |
| 120 | #endif /* !VIRTIO_BLK_NO_LEGACY */ | 120 | #endif /* !VIRTIO_BLK_NO_LEGACY */ |
| 121 | 121 | ||
| 122 | /* This is the first element of the read scatter-gather list. */ | 122 | /* |
| 123 | * This comes first in the read scatter-gather list. | ||
| 124 | * For legacy virtio, if VIRTIO_F_ANY_LAYOUT is not negotiated, | ||
| 125 | * this is the first element of the read scatter-gather list. | ||
| 126 | */ | ||
| 123 | struct virtio_blk_outhdr { | 127 | struct virtio_blk_outhdr { |
| 124 | /* VIRTIO_BLK_T* */ | 128 | /* VIRTIO_BLK_T* */ |
| 125 | __virtio32 type; | 129 | __virtio32 type; |
diff --git a/include/uapi/linux/virtio_scsi.h b/include/uapi/linux/virtio_scsi.h index 42b9370771b0..cc18ef8825c0 100644 --- a/include/uapi/linux/virtio_scsi.h +++ b/include/uapi/linux/virtio_scsi.h | |||
| @@ -29,8 +29,16 @@ | |||
| 29 | 29 | ||
| 30 | #include <linux/virtio_types.h> | 30 | #include <linux/virtio_types.h> |
| 31 | 31 | ||
| 32 | #define VIRTIO_SCSI_CDB_SIZE 32 | 32 | /* Default values of the CDB and sense data size configuration fields */ |
| 33 | #define VIRTIO_SCSI_SENSE_SIZE 96 | 33 | #define VIRTIO_SCSI_CDB_DEFAULT_SIZE 32 |
| 34 | #define VIRTIO_SCSI_SENSE_DEFAULT_SIZE 96 | ||
| 35 | |||
| 36 | #ifndef VIRTIO_SCSI_CDB_SIZE | ||
| 37 | #define VIRTIO_SCSI_CDB_SIZE VIRTIO_SCSI_CDB_DEFAULT_SIZE | ||
| 38 | #endif | ||
| 39 | #ifndef VIRTIO_SCSI_SENSE_SIZE | ||
| 40 | #define VIRTIO_SCSI_SENSE_SIZE VIRTIO_SCSI_SENSE_DEFAULT_SIZE | ||
| 41 | #endif | ||
| 34 | 42 | ||
| 35 | /* SCSI command request, followed by data-out */ | 43 | /* SCSI command request, followed by data-out */ |
| 36 | struct virtio_scsi_cmd_req { | 44 | struct virtio_scsi_cmd_req { |
diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c index d8e376a5f0f1..36a1a739ad68 100644 --- a/net/9p/trans_virtio.c +++ b/net/9p/trans_virtio.c | |||
| @@ -658,14 +658,30 @@ p9_virtio_create(struct p9_client *client, const char *devname, char *args) | |||
| 658 | static void p9_virtio_remove(struct virtio_device *vdev) | 658 | static void p9_virtio_remove(struct virtio_device *vdev) |
| 659 | { | 659 | { |
| 660 | struct virtio_chan *chan = vdev->priv; | 660 | struct virtio_chan *chan = vdev->priv; |
| 661 | 661 | unsigned long warning_time; | |
| 662 | if (chan->inuse) | ||
| 663 | p9_virtio_close(chan->client); | ||
| 664 | vdev->config->del_vqs(vdev); | ||
| 665 | 662 | ||
| 666 | mutex_lock(&virtio_9p_lock); | 663 | mutex_lock(&virtio_9p_lock); |
| 664 | |||
| 665 | /* Remove self from list so we don't get new users. */ | ||
| 667 | list_del(&chan->chan_list); | 666 | list_del(&chan->chan_list); |
| 667 | warning_time = jiffies; | ||
| 668 | |||
| 669 | /* Wait for existing users to close. */ | ||
| 670 | while (chan->inuse) { | ||
| 671 | mutex_unlock(&virtio_9p_lock); | ||
| 672 | msleep(250); | ||
| 673 | if (time_after(jiffies, warning_time + 10 * HZ)) { | ||
| 674 | dev_emerg(&vdev->dev, | ||
| 675 | "p9_virtio_remove: waiting for device in use.\n"); | ||
| 676 | warning_time = jiffies; | ||
| 677 | } | ||
| 678 | mutex_lock(&virtio_9p_lock); | ||
| 679 | } | ||
| 680 | |||
| 668 | mutex_unlock(&virtio_9p_lock); | 681 | mutex_unlock(&virtio_9p_lock); |
| 682 | |||
| 683 | vdev->config->del_vqs(vdev); | ||
| 684 | |||
| 669 | sysfs_remove_file(&(vdev->dev.kobj), &dev_attr_mount_tag.attr); | 685 | sysfs_remove_file(&(vdev->dev.kobj), &dev_attr_mount_tag.attr); |
| 670 | kobject_uevent(&(vdev->dev.kobj), KOBJ_CHANGE); | 686 | kobject_uevent(&(vdev->dev.kobj), KOBJ_CHANGE); |
| 671 | kfree(chan->tag); | 687 | kfree(chan->tag); |
