aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/virtio
diff options
context:
space:
mode:
authorPawel Moll <pawel.moll@arm.com>2015-01-22 23:15:55 -0500
committerRusty Russell <rusty@rustcorp.com.au>2015-01-22 23:27:10 -0500
commit1862ee22ce2e28087299aebb6556a5cdc122d0ef (patch)
treef28c2d0aae6d7e9bde82b269d09da72d727f8522 /drivers/virtio
parent76545f066d2a85464a9f81de2e159b199cc2942b (diff)
virtio-mmio: Update the device to OASIS spec version
This patch add a support for second version of the virtio-mmio device, which follows OASIS "Virtual I/O Device (VIRTIO) Version 1.0" specification. Main changes: 1. The control register symbolic names use the new device/driver nomenclature rather than the old guest/host one. 2. The driver detect the device version (version 1 is the pre-OASIS spec, version 2 is compatible with fist revision of the OASIS spec) and drives the device accordingly. 3. New version uses direct addressing (64 bit address split into two low/high register) instead of the guest page size based one, and addresses each part of the queue (descriptors, available, used) separately. 4. The device activity is now explicitly triggered by writing to the "queue ready" register. 5. Whole 64 bit features are properly handled now (both ways). Signed-off-by: Pawel Moll <pawel.moll@arm.com> Acked-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Diffstat (limited to 'drivers/virtio')
-rw-r--r--drivers/virtio/virtio_mmio.c131
1 files changed, 81 insertions, 50 deletions
diff --git a/drivers/virtio/virtio_mmio.c b/drivers/virtio/virtio_mmio.c
index 00d115b22bd8..cad569890908 100644
--- a/drivers/virtio/virtio_mmio.c
+++ b/drivers/virtio/virtio_mmio.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * Virtio memory mapped device driver 2 * Virtio memory mapped device driver
3 * 3 *
4 * Copyright 2011, ARM Ltd. 4 * Copyright 2011-2014, ARM Ltd.
5 * 5 *
6 * This module allows virtio devices to be used over a virtual, memory mapped 6 * This module allows virtio devices to be used over a virtual, memory mapped
7 * platform device. 7 * platform device.
@@ -50,36 +50,6 @@
50 * 50 *
51 * 51 *
52 * 52 *
53 * Registers layout (all 32-bit wide):
54 *
55 * offset d. name description
56 * ------ -- ---------------- -----------------
57 *
58 * 0x000 R MagicValue Magic value "virt"
59 * 0x004 R Version Device version (current max. 1)
60 * 0x008 R DeviceID Virtio device ID
61 * 0x00c R VendorID Virtio vendor ID
62 *
63 * 0x010 R HostFeatures Features supported by the host
64 * 0x014 W HostFeaturesSel Set of host features to access via HostFeatures
65 *
66 * 0x020 W GuestFeatures Features activated by the guest
67 * 0x024 W GuestFeaturesSel Set of activated features to set via GuestFeatures
68 * 0x028 W GuestPageSize Size of guest's memory page in bytes
69 *
70 * 0x030 W QueueSel Queue selector
71 * 0x034 R QueueNumMax Maximum size of the currently selected queue
72 * 0x038 W QueueNum Queue size for the currently selected queue
73 * 0x03c W QueueAlign Used Ring alignment for the current queue
74 * 0x040 RW QueuePFN PFN for the currently selected queue
75 *
76 * 0x050 W QueueNotify Queue notifier
77 * 0x060 R InterruptStatus Interrupt status register
78 * 0x064 W InterruptACK Interrupt acknowledge register
79 * 0x070 RW Status Device status register
80 *
81 * 0x100+ RW Device-specific configuration space
82 *
83 * Based on Virtio PCI driver by Anthony Liguori, copyright IBM Corp. 2007 53 * Based on Virtio PCI driver by Anthony Liguori, copyright IBM Corp. 2007
84 * 54 *
85 * This work is licensed under the terms of the GNU GPL, version 2 or later. 55 * This work is licensed under the terms of the GNU GPL, version 2 or later.
@@ -145,11 +115,16 @@ struct virtio_mmio_vq_info {
145static u64 vm_get_features(struct virtio_device *vdev) 115static u64 vm_get_features(struct virtio_device *vdev)
146{ 116{
147 struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev); 117 struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev);
118 u64 features;
119
120 writel(1, vm_dev->base + VIRTIO_MMIO_DEVICE_FEATURES_SEL);
121 features = readl(vm_dev->base + VIRTIO_MMIO_DEVICE_FEATURES);
122 features <<= 32;
148 123
149 /* TODO: Features > 32 bits */ 124 writel(0, vm_dev->base + VIRTIO_MMIO_DEVICE_FEATURES_SEL);
150 writel(0, vm_dev->base + VIRTIO_MMIO_HOST_FEATURES_SEL); 125 features |= readl(vm_dev->base + VIRTIO_MMIO_DEVICE_FEATURES);
151 126
152 return readl(vm_dev->base + VIRTIO_MMIO_HOST_FEATURES); 127 return features;
153} 128}
154 129
155static int vm_finalize_features(struct virtio_device *vdev) 130static int vm_finalize_features(struct virtio_device *vdev)
@@ -159,11 +134,20 @@ static int vm_finalize_features(struct virtio_device *vdev)
159 /* Give virtio_ring a chance to accept features. */ 134 /* Give virtio_ring a chance to accept features. */
160 vring_transport_features(vdev); 135 vring_transport_features(vdev);
161 136
162 /* Make sure we don't have any features > 32 bits! */ 137 /* Make sure there is are no mixed devices */
163 BUG_ON((u32)vdev->features != vdev->features); 138 if (vm_dev->version == 2 &&
139 !__virtio_test_bit(vdev, VIRTIO_F_VERSION_1)) {
140 dev_err(&vdev->dev, "New virtio-mmio devices (version 2) must provide VIRTIO_F_VERSION_1 feature!\n");
141 return -EINVAL;
142 }
143
144 writel(1, vm_dev->base + VIRTIO_MMIO_DRIVER_FEATURES_SEL);
145 writel((u32)(vdev->features >> 32),
146 vm_dev->base + VIRTIO_MMIO_DRIVER_FEATURES);
164 147
165 writel(0, vm_dev->base + VIRTIO_MMIO_GUEST_FEATURES_SEL); 148 writel(0, vm_dev->base + VIRTIO_MMIO_DRIVER_FEATURES_SEL);
166 writel(vdev->features, vm_dev->base + VIRTIO_MMIO_GUEST_FEATURES); 149 writel((u32)vdev->features,
150 vm_dev->base + VIRTIO_MMIO_DRIVER_FEATURES);
167 151
168 return 0; 152 return 0;
169} 153}
@@ -275,7 +259,12 @@ static void vm_del_vq(struct virtqueue *vq)
275 259
276 /* Select and deactivate the queue */ 260 /* Select and deactivate the queue */
277 writel(index, vm_dev->base + VIRTIO_MMIO_QUEUE_SEL); 261 writel(index, vm_dev->base + VIRTIO_MMIO_QUEUE_SEL);
278 writel(0, vm_dev->base + VIRTIO_MMIO_QUEUE_PFN); 262 if (vm_dev->version == 1) {
263 writel(0, vm_dev->base + VIRTIO_MMIO_QUEUE_PFN);
264 } else {
265 writel(0, vm_dev->base + VIRTIO_MMIO_QUEUE_READY);
266 WARN_ON(readl(vm_dev->base + VIRTIO_MMIO_QUEUE_READY));
267 }
279 268
280 size = PAGE_ALIGN(vring_size(info->num, VIRTIO_MMIO_VRING_ALIGN)); 269 size = PAGE_ALIGN(vring_size(info->num, VIRTIO_MMIO_VRING_ALIGN));
281 free_pages_exact(info->queue, size); 270 free_pages_exact(info->queue, size);
@@ -312,7 +301,8 @@ static struct virtqueue *vm_setup_vq(struct virtio_device *vdev, unsigned index,
312 writel(index, vm_dev->base + VIRTIO_MMIO_QUEUE_SEL); 301 writel(index, vm_dev->base + VIRTIO_MMIO_QUEUE_SEL);
313 302
314 /* Queue shouldn't already be set up. */ 303 /* Queue shouldn't already be set up. */
315 if (readl(vm_dev->base + VIRTIO_MMIO_QUEUE_PFN)) { 304 if (readl(vm_dev->base + (vm_dev->version == 1 ?
305 VIRTIO_MMIO_QUEUE_PFN : VIRTIO_MMIO_QUEUE_READY))) {
316 err = -ENOENT; 306 err = -ENOENT;
317 goto error_available; 307 goto error_available;
318 } 308 }
@@ -356,13 +346,6 @@ static struct virtqueue *vm_setup_vq(struct virtio_device *vdev, unsigned index,
356 info->num /= 2; 346 info->num /= 2;
357 } 347 }
358 348
359 /* Activate the queue */
360 writel(info->num, vm_dev->base + VIRTIO_MMIO_QUEUE_NUM);
361 writel(VIRTIO_MMIO_VRING_ALIGN,
362 vm_dev->base + VIRTIO_MMIO_QUEUE_ALIGN);
363 writel(virt_to_phys(info->queue) >> PAGE_SHIFT,
364 vm_dev->base + VIRTIO_MMIO_QUEUE_PFN);
365
366 /* Create the vring */ 349 /* Create the vring */
367 vq = vring_new_virtqueue(index, info->num, VIRTIO_MMIO_VRING_ALIGN, vdev, 350 vq = vring_new_virtqueue(index, info->num, VIRTIO_MMIO_VRING_ALIGN, vdev,
368 true, info->queue, vm_notify, callback, name); 351 true, info->queue, vm_notify, callback, name);
@@ -371,6 +354,33 @@ static struct virtqueue *vm_setup_vq(struct virtio_device *vdev, unsigned index,
371 goto error_new_virtqueue; 354 goto error_new_virtqueue;
372 } 355 }
373 356
357 /* Activate the queue */
358 writel(info->num, vm_dev->base + VIRTIO_MMIO_QUEUE_NUM);
359 if (vm_dev->version == 1) {
360 writel(PAGE_SIZE, vm_dev->base + VIRTIO_MMIO_QUEUE_ALIGN);
361 writel(virt_to_phys(info->queue) >> PAGE_SHIFT,
362 vm_dev->base + VIRTIO_MMIO_QUEUE_PFN);
363 } else {
364 u64 addr;
365
366 addr = virt_to_phys(info->queue);
367 writel((u32)addr, vm_dev->base + VIRTIO_MMIO_QUEUE_DESC_LOW);
368 writel((u32)(addr >> 32),
369 vm_dev->base + VIRTIO_MMIO_QUEUE_DESC_HIGH);
370
371 addr = virt_to_phys(virtqueue_get_avail(vq));
372 writel((u32)addr, vm_dev->base + VIRTIO_MMIO_QUEUE_AVAIL_LOW);
373 writel((u32)(addr >> 32),
374 vm_dev->base + VIRTIO_MMIO_QUEUE_AVAIL_HIGH);
375
376 addr = virt_to_phys(virtqueue_get_used(vq));
377 writel((u32)addr, vm_dev->base + VIRTIO_MMIO_QUEUE_USED_LOW);
378 writel((u32)(addr >> 32),
379 vm_dev->base + VIRTIO_MMIO_QUEUE_USED_HIGH);
380
381 writel(1, vm_dev->base + VIRTIO_MMIO_QUEUE_READY);
382 }
383
374 vq->priv = info; 384 vq->priv = info;
375 info->vq = vq; 385 info->vq = vq;
376 386
@@ -381,7 +391,12 @@ static struct virtqueue *vm_setup_vq(struct virtio_device *vdev, unsigned index,
381 return vq; 391 return vq;
382 392
383error_new_virtqueue: 393error_new_virtqueue:
384 writel(0, vm_dev->base + VIRTIO_MMIO_QUEUE_PFN); 394 if (vm_dev->version == 1) {
395 writel(0, vm_dev->base + VIRTIO_MMIO_QUEUE_PFN);
396 } else {
397 writel(0, vm_dev->base + VIRTIO_MMIO_QUEUE_READY);
398 WARN_ON(readl(vm_dev->base + VIRTIO_MMIO_QUEUE_READY));
399 }
385 free_pages_exact(info->queue, size); 400 free_pages_exact(info->queue, size);
386error_alloc_pages: 401error_alloc_pages:
387 kfree(info); 402 kfree(info);
@@ -476,16 +491,32 @@ static int virtio_mmio_probe(struct platform_device *pdev)
476 491
477 /* Check device version */ 492 /* Check device version */
478 vm_dev->version = readl(vm_dev->base + VIRTIO_MMIO_VERSION); 493 vm_dev->version = readl(vm_dev->base + VIRTIO_MMIO_VERSION);
479 if (vm_dev->version != 1) { 494 if (vm_dev->version < 1 || vm_dev->version > 2) {
480 dev_err(&pdev->dev, "Version %ld not supported!\n", 495 dev_err(&pdev->dev, "Version %ld not supported!\n",
481 vm_dev->version); 496 vm_dev->version);
482 return -ENXIO; 497 return -ENXIO;
483 } 498 }
484 499
485 vm_dev->vdev.id.device = readl(vm_dev->base + VIRTIO_MMIO_DEVICE_ID); 500 vm_dev->vdev.id.device = readl(vm_dev->base + VIRTIO_MMIO_DEVICE_ID);
501 if (vm_dev->vdev.id.device == 0) {
502 /*
503 * virtio-mmio device with an ID 0 is a (dummy) placeholder
504 * with no function. End probing now with no error reported.
505 */
506 return -ENODEV;
507 }
486 vm_dev->vdev.id.vendor = readl(vm_dev->base + VIRTIO_MMIO_VENDOR_ID); 508 vm_dev->vdev.id.vendor = readl(vm_dev->base + VIRTIO_MMIO_VENDOR_ID);
487 509
488 writel(PAGE_SIZE, vm_dev->base + VIRTIO_MMIO_GUEST_PAGE_SIZE); 510 /* Reject legacy-only IDs for version 2 devices */
511 if (vm_dev->version == 2 &&
512 virtio_device_is_legacy_only(vm_dev->vdev.id)) {
513 dev_err(&pdev->dev, "Version 2 not supported for devices %u!\n",
514 vm_dev->vdev.id.device);
515 return -ENODEV;
516 }
517
518 if (vm_dev->version == 1)
519 writel(PAGE_SIZE, vm_dev->base + VIRTIO_MMIO_GUEST_PAGE_SIZE);
489 520
490 platform_set_drvdata(pdev, vm_dev); 521 platform_set_drvdata(pdev, vm_dev);
491 522