Autogenerated GPG tag for Rusty D1ADB8F1: 15EE 8D6C AB0E 7F0C F999 BFCB D920 0E6C D1AD B8F1
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.11 (GNU/Linux) iQIcBAABAgAGBQJPuv35AAoJENkgDmzRrbjxUx4P/0uc+0oNnZv11vYQsqHuhURa zMlsVdlXGVkvPqQiLY0QkrK5LcO6KiSnSk8vEnOYFIPjL4wNqL/4RRRLnTAJwmE+ lsrL9DblI8Ira/EZRv7d2L12QrP+F2ZGKOZr67uVxSaxH71fUqtiJ0jqA/I8AYH7 /V7+DgdIB1DD28Ya/JEFEUi41F08A6MU10hpaQWy9kXv09gCc9apgvH7/S3s9DaQ G640YWkoKZAx/OFBb8XFvpu9LqZcVl02Nl8goMZOKnMctC4iU3km7HeVjfwCgLjO AdA5spLMhDkS/xrpI0mSQ/wT0k0+sSYW5vEdW9N4XLZza0NgH9GfU4RtEuK85Slj 7bPviZOcpjtt0sGi4wXCaVjZyHROX6tyRvTMUAIj3D0oJglb5T9D3MCvQnadILb0 I0+7gk3d9rHqkO6CmjNaZG9IwR9NpFkbuolcFQuEaZoUMoKd2pYNQyxpbFGl+jCl 7ViFHAy+fydNqDoETKincld4A43KWxOV7jyEJd7hloKcCixsqI7ZdPS7X8amec72 a0hfNgMJzarZkTgo61Hair/d+vKGRJPgEdF1Yq76SDhYKD1TeWeDjmboctsiMjqe f5M4C6IdNJj9cDIlCxMk+3bX250oy7KG77v7Ux0/7nvtSWVa3yEMowD57hnn1But 0gNC8bjXDHRsho90rDRN =Kj9v -----END PGP SIGNATURE----- Merge tag 'virtio-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux-2.6-for-linus Pull virtio updates from Rusty Russell. * tag 'virtio-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux-2.6-for-linus: virtio: fix typo in comment virtio-mmio: Devices parameter parsing virtio_blk: Drop unused request tracking list virtio-blk: Fix hot-unplug race in remove method virtio: Use ida to allocate virtio index virtio: balloon: separate out common code between remove and freeze functions virtio: balloon: drop restore_common() 9p: disconnect channel when PCI device is removed virtio: update documentation to v0.9.5 of spec
This commit is contained in:
commit
99262a3daf
9 changed files with 1314 additions and 120 deletions
|
@ -110,6 +110,7 @@ parameter is applicable:
|
|||
USB USB support is enabled.
|
||||
USBHID USB Human Interface Device support is enabled.
|
||||
V4L Video For Linux support is enabled.
|
||||
VMMIO Driver for memory mapped virtio devices is enabled.
|
||||
VGA The VGA console has been enabled.
|
||||
VT Virtual terminal support is enabled.
|
||||
WDT Watchdog support is enabled.
|
||||
|
@ -2932,6 +2933,22 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
|
|||
video= [FB] Frame buffer configuration
|
||||
See Documentation/fb/modedb.txt.
|
||||
|
||||
virtio_mmio.device=
|
||||
[VMMIO] Memory mapped virtio (platform) device.
|
||||
|
||||
<size>@<baseaddr>:<irq>[:<id>]
|
||||
where:
|
||||
<size> := size (can use standard suffixes
|
||||
like K, M and G)
|
||||
<baseaddr> := physical base address
|
||||
<irq> := interrupt number (as passed to
|
||||
request_irq())
|
||||
<id> := (optional) platform device id
|
||||
example:
|
||||
virtio_mmio.device=1K@0x100b0000:48:7
|
||||
|
||||
Can be used multiple times for multiple devices.
|
||||
|
||||
vga= [BOOT,X86-32] Select a particular video mode
|
||||
See Documentation/x86/boot.txt and
|
||||
Documentation/svga.txt.
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -29,9 +29,6 @@ struct virtio_blk
|
|||
/* The disk structure for the kernel. */
|
||||
struct gendisk *disk;
|
||||
|
||||
/* Request tracking. */
|
||||
struct list_head reqs;
|
||||
|
||||
mempool_t *pool;
|
||||
|
||||
/* Process context for config space updates */
|
||||
|
@ -55,7 +52,6 @@ struct virtio_blk
|
|||
|
||||
struct virtblk_req
|
||||
{
|
||||
struct list_head list;
|
||||
struct request *req;
|
||||
struct virtio_blk_outhdr out_hdr;
|
||||
struct virtio_scsi_inhdr in_hdr;
|
||||
|
@ -99,7 +95,6 @@ static void blk_done(struct virtqueue *vq)
|
|||
}
|
||||
|
||||
__blk_end_request_all(vbr->req, error);
|
||||
list_del(&vbr->list);
|
||||
mempool_free(vbr, vblk->pool);
|
||||
}
|
||||
/* In case queue is stopped waiting for more buffers. */
|
||||
|
@ -184,7 +179,6 @@ static bool do_req(struct request_queue *q, struct virtio_blk *vblk,
|
|||
return false;
|
||||
}
|
||||
|
||||
list_add_tail(&vbr->list, &vblk->reqs);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -437,7 +431,6 @@ static int __devinit virtblk_probe(struct virtio_device *vdev)
|
|||
goto out_free_index;
|
||||
}
|
||||
|
||||
INIT_LIST_HEAD(&vblk->reqs);
|
||||
spin_lock_init(&vblk->lock);
|
||||
vblk->vdev = vdev;
|
||||
vblk->sg_elems = sg_elems;
|
||||
|
@ -583,21 +576,29 @@ static void __devexit virtblk_remove(struct virtio_device *vdev)
|
|||
{
|
||||
struct virtio_blk *vblk = vdev->priv;
|
||||
int index = vblk->index;
|
||||
struct virtblk_req *vbr;
|
||||
unsigned long flags;
|
||||
|
||||
/* Prevent config work handler from accessing the device. */
|
||||
mutex_lock(&vblk->config_lock);
|
||||
vblk->config_enable = false;
|
||||
mutex_unlock(&vblk->config_lock);
|
||||
|
||||
/* Nothing should be pending. */
|
||||
BUG_ON(!list_empty(&vblk->reqs));
|
||||
|
||||
/* Stop all the virtqueues. */
|
||||
vdev->config->reset(vdev);
|
||||
|
||||
flush_work(&vblk->config_work);
|
||||
|
||||
del_gendisk(vblk->disk);
|
||||
|
||||
/* Abort requests dispatched to driver. */
|
||||
spin_lock_irqsave(&vblk->lock, flags);
|
||||
while ((vbr = virtqueue_detach_unused_buf(vblk->vq))) {
|
||||
__blk_end_request_all(vbr->req, -EIO);
|
||||
mempool_free(vbr, vblk->pool);
|
||||
}
|
||||
spin_unlock_irqrestore(&vblk->lock, flags);
|
||||
|
||||
blk_cleanup_queue(vblk->disk->queue);
|
||||
put_disk(vblk->disk);
|
||||
mempool_destroy(vblk->pool);
|
||||
|
|
|
@ -46,4 +46,15 @@ config VIRTIO_BALLOON
|
|||
|
||||
If unsure, say N.
|
||||
|
||||
config VIRTIO_MMIO_CMDLINE_DEVICES
|
||||
bool "Memory mapped virtio devices parameter parsing"
|
||||
depends on VIRTIO_MMIO
|
||||
---help---
|
||||
Allow virtio-mmio devices instantiation via the kernel command line
|
||||
or module parameters. Be aware that using incorrect parameters (base
|
||||
address in particular) can crash your system - you have been warned.
|
||||
See Documentation/kernel-parameters.txt for details.
|
||||
|
||||
If unsure, say 'N'.
|
||||
|
||||
endmenu
|
||||
|
|
|
@ -2,9 +2,10 @@
|
|||
#include <linux/spinlock.h>
|
||||
#include <linux/virtio_config.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/idr.h>
|
||||
|
||||
/* Unique numbering for virtio devices. */
|
||||
static unsigned int dev_index;
|
||||
static DEFINE_IDA(virtio_index_ida);
|
||||
|
||||
static ssize_t device_show(struct device *_d,
|
||||
struct device_attribute *attr, char *buf)
|
||||
|
@ -193,7 +194,11 @@ int register_virtio_device(struct virtio_device *dev)
|
|||
dev->dev.bus = &virtio_bus;
|
||||
|
||||
/* Assign a unique device index and hence name. */
|
||||
dev->index = dev_index++;
|
||||
err = ida_simple_get(&virtio_index_ida, 0, 0, GFP_KERNEL);
|
||||
if (err < 0)
|
||||
goto out;
|
||||
|
||||
dev->index = err;
|
||||
dev_set_name(&dev->dev, "virtio%u", dev->index);
|
||||
|
||||
/* We always start by resetting the device, in case a previous
|
||||
|
@ -208,6 +213,7 @@ int register_virtio_device(struct virtio_device *dev)
|
|||
/* device_register() causes the bus infrastructure to look for a
|
||||
* matching driver. */
|
||||
err = device_register(&dev->dev);
|
||||
out:
|
||||
if (err)
|
||||
add_status(dev, VIRTIO_CONFIG_S_FAILED);
|
||||
return err;
|
||||
|
@ -217,6 +223,7 @@ EXPORT_SYMBOL_GPL(register_virtio_device);
|
|||
void unregister_virtio_device(struct virtio_device *dev)
|
||||
{
|
||||
device_unregister(&dev->dev);
|
||||
ida_simple_remove(&virtio_index_ida, dev->index);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(unregister_virtio_device);
|
||||
|
||||
|
|
|
@ -381,21 +381,25 @@ out:
|
|||
return err;
|
||||
}
|
||||
|
||||
static void __devexit virtballoon_remove(struct virtio_device *vdev)
|
||||
static void remove_common(struct virtio_balloon *vb)
|
||||
{
|
||||
struct virtio_balloon *vb = vdev->priv;
|
||||
|
||||
kthread_stop(vb->thread);
|
||||
|
||||
/* There might be pages left in the balloon: free them. */
|
||||
while (vb->num_pages)
|
||||
leak_balloon(vb, vb->num_pages);
|
||||
update_balloon_size(vb);
|
||||
|
||||
/* Now we reset the device so we can clean up the queues. */
|
||||
vdev->config->reset(vdev);
|
||||
vb->vdev->config->reset(vb->vdev);
|
||||
|
||||
vdev->config->del_vqs(vdev);
|
||||
vb->vdev->config->del_vqs(vb->vdev);
|
||||
}
|
||||
|
||||
static void __devexit virtballoon_remove(struct virtio_device *vdev)
|
||||
{
|
||||
struct virtio_balloon *vb = vdev->priv;
|
||||
|
||||
kthread_stop(vb->thread);
|
||||
remove_common(vb);
|
||||
kfree(vb);
|
||||
}
|
||||
|
||||
|
@ -409,17 +413,11 @@ static int virtballoon_freeze(struct virtio_device *vdev)
|
|||
* function is called.
|
||||
*/
|
||||
|
||||
while (vb->num_pages)
|
||||
leak_balloon(vb, vb->num_pages);
|
||||
update_balloon_size(vb);
|
||||
|
||||
/* Ensure we don't get any more requests from the host */
|
||||
vdev->config->reset(vdev);
|
||||
vdev->config->del_vqs(vdev);
|
||||
remove_common(vb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int restore_common(struct virtio_device *vdev)
|
||||
static int virtballoon_restore(struct virtio_device *vdev)
|
||||
{
|
||||
struct virtio_balloon *vb = vdev->priv;
|
||||
int ret;
|
||||
|
@ -432,11 +430,6 @@ static int restore_common(struct virtio_device *vdev)
|
|||
update_balloon_size(vb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int virtballoon_restore(struct virtio_device *vdev)
|
||||
{
|
||||
return restore_common(vdev);
|
||||
}
|
||||
#endif
|
||||
|
||||
static unsigned int features[] = {
|
||||
|
|
|
@ -6,6 +6,50 @@
|
|||
* This module allows virtio devices to be used over a virtual, memory mapped
|
||||
* platform device.
|
||||
*
|
||||
* The guest device(s) may be instantiated in one of three equivalent ways:
|
||||
*
|
||||
* 1. Static platform device in board's code, eg.:
|
||||
*
|
||||
* static struct platform_device v2m_virtio_device = {
|
||||
* .name = "virtio-mmio",
|
||||
* .id = -1,
|
||||
* .num_resources = 2,
|
||||
* .resource = (struct resource []) {
|
||||
* {
|
||||
* .start = 0x1001e000,
|
||||
* .end = 0x1001e0ff,
|
||||
* .flags = IORESOURCE_MEM,
|
||||
* }, {
|
||||
* .start = 42 + 32,
|
||||
* .end = 42 + 32,
|
||||
* .flags = IORESOURCE_IRQ,
|
||||
* },
|
||||
* }
|
||||
* };
|
||||
*
|
||||
* 2. Device Tree node, eg.:
|
||||
*
|
||||
* virtio_block@1e000 {
|
||||
* compatible = "virtio,mmio";
|
||||
* reg = <0x1e000 0x100>;
|
||||
* interrupts = <42>;
|
||||
* }
|
||||
*
|
||||
* 3. Kernel module (or command line) parameter. Can be used more than once -
|
||||
* one device will be created for each one. Syntax:
|
||||
*
|
||||
* [virtio_mmio.]device=<size>@<baseaddr>:<irq>[:<id>]
|
||||
* where:
|
||||
* <size> := size (can use standard suffixes like K, M or G)
|
||||
* <baseaddr> := physical base address
|
||||
* <irq> := interrupt number (as passed to request_irq())
|
||||
* <id> := (optional) platform device id
|
||||
* eg.:
|
||||
* virtio_mmio.device=0x100@0x100b0000:48 \
|
||||
* virtio_mmio.device=1K@0x1001e000:74
|
||||
*
|
||||
*
|
||||
*
|
||||
* Registers layout (all 32-bit wide):
|
||||
*
|
||||
* offset d. name description
|
||||
|
@ -42,6 +86,8 @@
|
|||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) "virtio-mmio: " fmt
|
||||
|
||||
#include <linux/highmem.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/io.h>
|
||||
|
@ -449,6 +495,122 @@ static int __devexit virtio_mmio_remove(struct platform_device *pdev)
|
|||
|
||||
|
||||
|
||||
/* Devices list parameter */
|
||||
|
||||
#if defined(CONFIG_VIRTIO_MMIO_CMDLINE_DEVICES)
|
||||
|
||||
static struct device vm_cmdline_parent = {
|
||||
.init_name = "virtio-mmio-cmdline",
|
||||
};
|
||||
|
||||
static int vm_cmdline_parent_registered;
|
||||
static int vm_cmdline_id;
|
||||
|
||||
static int vm_cmdline_set(const char *device,
|
||||
const struct kernel_param *kp)
|
||||
{
|
||||
int err;
|
||||
struct resource resources[2] = {};
|
||||
char *str;
|
||||
long long int base;
|
||||
int processed, consumed = 0;
|
||||
struct platform_device *pdev;
|
||||
|
||||
resources[0].flags = IORESOURCE_MEM;
|
||||
resources[1].flags = IORESOURCE_IRQ;
|
||||
|
||||
resources[0].end = memparse(device, &str) - 1;
|
||||
|
||||
processed = sscanf(str, "@%lli:%u%n:%d%n",
|
||||
&base, &resources[1].start, &consumed,
|
||||
&vm_cmdline_id, &consumed);
|
||||
|
||||
if (processed < 2 || processed > 3 || str[consumed])
|
||||
return -EINVAL;
|
||||
|
||||
resources[0].start = base;
|
||||
resources[0].end += base;
|
||||
resources[1].end = resources[1].start;
|
||||
|
||||
if (!vm_cmdline_parent_registered) {
|
||||
err = device_register(&vm_cmdline_parent);
|
||||
if (err) {
|
||||
pr_err("Failed to register parent device!\n");
|
||||
return err;
|
||||
}
|
||||
vm_cmdline_parent_registered = 1;
|
||||
}
|
||||
|
||||
pr_info("Registering device virtio-mmio.%d at 0x%llx-0x%llx, IRQ %d.\n",
|
||||
vm_cmdline_id,
|
||||
(unsigned long long)resources[0].start,
|
||||
(unsigned long long)resources[0].end,
|
||||
(int)resources[1].start);
|
||||
|
||||
pdev = platform_device_register_resndata(&vm_cmdline_parent,
|
||||
"virtio-mmio", vm_cmdline_id++,
|
||||
resources, ARRAY_SIZE(resources), NULL, 0);
|
||||
if (IS_ERR(pdev))
|
||||
return PTR_ERR(pdev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vm_cmdline_get_device(struct device *dev, void *data)
|
||||
{
|
||||
char *buffer = data;
|
||||
unsigned int len = strlen(buffer);
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
|
||||
snprintf(buffer + len, PAGE_SIZE - len, "0x%llx@0x%llx:%llu:%d\n",
|
||||
pdev->resource[0].end - pdev->resource[0].start + 1ULL,
|
||||
(unsigned long long)pdev->resource[0].start,
|
||||
(unsigned long long)pdev->resource[1].start,
|
||||
pdev->id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vm_cmdline_get(char *buffer, const struct kernel_param *kp)
|
||||
{
|
||||
buffer[0] = '\0';
|
||||
device_for_each_child(&vm_cmdline_parent, buffer,
|
||||
vm_cmdline_get_device);
|
||||
return strlen(buffer) + 1;
|
||||
}
|
||||
|
||||
static struct kernel_param_ops vm_cmdline_param_ops = {
|
||||
.set = vm_cmdline_set,
|
||||
.get = vm_cmdline_get,
|
||||
};
|
||||
|
||||
device_param_cb(device, &vm_cmdline_param_ops, NULL, S_IRUSR);
|
||||
|
||||
static int vm_unregister_cmdline_device(struct device *dev,
|
||||
void *data)
|
||||
{
|
||||
platform_device_unregister(to_platform_device(dev));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void vm_unregister_cmdline_devices(void)
|
||||
{
|
||||
if (vm_cmdline_parent_registered) {
|
||||
device_for_each_child(&vm_cmdline_parent, NULL,
|
||||
vm_unregister_cmdline_device);
|
||||
device_unregister(&vm_cmdline_parent);
|
||||
vm_cmdline_parent_registered = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static void vm_unregister_cmdline_devices(void)
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* Platform driver */
|
||||
|
||||
static struct of_device_id virtio_mmio_match[] = {
|
||||
|
@ -475,6 +637,7 @@ static int __init virtio_mmio_init(void)
|
|||
static void __exit virtio_mmio_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&virtio_mmio_driver);
|
||||
vm_unregister_cmdline_devices();
|
||||
}
|
||||
|
||||
module_init(virtio_mmio_init);
|
||||
|
|
|
@ -74,15 +74,6 @@
|
|||
* @set_status: write the status byte
|
||||
* vdev: the virtio_device
|
||||
* status: the new status byte
|
||||
* @request_vqs: request the specified number of virtqueues
|
||||
* vdev: the virtio_device
|
||||
* max_vqs: the max number of virtqueues we want
|
||||
* If supplied, must call before any virtqueues are instantiated.
|
||||
* To modify the max number of virtqueues after request_vqs has been
|
||||
* called, call free_vqs and then request_vqs with a new value.
|
||||
* @free_vqs: cleanup resources allocated by request_vqs
|
||||
* vdev: the virtio_device
|
||||
* If supplied, must call after all virtqueues have been deleted.
|
||||
* @reset: reset the device
|
||||
* vdev: the virtio device
|
||||
* After this, status and feature negotiation must be done again
|
||||
|
@ -156,7 +147,7 @@ static inline bool virtio_has_feature(const struct virtio_device *vdev,
|
|||
* @vdev: the virtio device
|
||||
* @fbit: the feature bit
|
||||
* @offset: the type to search for.
|
||||
* @val: a pointer to the value to fill in.
|
||||
* @v: a pointer to the value to fill in.
|
||||
*
|
||||
* The return value is -ENOENT if the feature doesn't exist. Otherwise
|
||||
* the config value is copied into whatever is pointed to by v. */
|
||||
|
|
|
@ -615,7 +615,8 @@ static void p9_virtio_remove(struct virtio_device *vdev)
|
|||
{
|
||||
struct virtio_chan *chan = vdev->priv;
|
||||
|
||||
BUG_ON(chan->inuse);
|
||||
if (chan->inuse)
|
||||
p9_virtio_close(chan->client);
|
||||
vdev->config->del_vqs(vdev);
|
||||
|
||||
mutex_lock(&virtio_9p_lock);
|
||||
|
|
Loading…
Reference in a new issue