aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPawel Moll <pawel.moll@arm.com>2012-05-09 13:30:16 -0400
committerRusty Russell <rusty@rustcorp.com.au>2012-05-21 22:46:15 -0400
commit81a054ce0b469b66c88e9da6403082759c64bf73 (patch)
tree4736df1e0d7c7d9143a1e6dbbfe8947d8079f934
parentf65ca1dc6a8c81c6bd72297d4399ec5f4c1f3a01 (diff)
virtio-mmio: Devices parameter parsing
This patch adds an option to instantiate guest virtio-mmio devices basing on a kernel command line (or module) parameter, for example: virtio_mmio.devices=0x100@0x100b0000:48 Signed-off-by: Pawel Moll <pawel.moll@arm.com> Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
-rw-r--r--Documentation/kernel-parameters.txt17
-rw-r--r--drivers/virtio/Kconfig11
-rw-r--r--drivers/virtio/virtio_mmio.c163
3 files changed, 191 insertions, 0 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index c1601e5a8b71..8b350512f360 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -110,6 +110,7 @@ parameter is applicable:
110 USB USB support is enabled. 110 USB USB support is enabled.
111 USBHID USB Human Interface Device support is enabled. 111 USBHID USB Human Interface Device support is enabled.
112 V4L Video For Linux support is enabled. 112 V4L Video For Linux support is enabled.
113 VMMIO Driver for memory mapped virtio devices is enabled.
113 VGA The VGA console has been enabled. 114 VGA The VGA console has been enabled.
114 VT Virtual terminal support is enabled. 115 VT Virtual terminal support is enabled.
115 WDT Watchdog support is enabled. 116 WDT Watchdog support is enabled.
@@ -2847,6 +2848,22 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
2847 video= [FB] Frame buffer configuration 2848 video= [FB] Frame buffer configuration
2848 See Documentation/fb/modedb.txt. 2849 See Documentation/fb/modedb.txt.
2849 2850
2851 virtio_mmio.device=
2852 [VMMIO] Memory mapped virtio (platform) device.
2853
2854 <size>@<baseaddr>:<irq>[:<id>]
2855 where:
2856 <size> := size (can use standard suffixes
2857 like K, M and G)
2858 <baseaddr> := physical base address
2859 <irq> := interrupt number (as passed to
2860 request_irq())
2861 <id> := (optional) platform device id
2862 example:
2863 virtio_mmio.device=1K@0x100b0000:48:7
2864
2865 Can be used multiple times for multiple devices.
2866
2850 vga= [BOOT,X86-32] Select a particular video mode 2867 vga= [BOOT,X86-32] Select a particular video mode
2851 See Documentation/x86/boot.txt and 2868 See Documentation/x86/boot.txt and
2852 Documentation/svga.txt. 2869 Documentation/svga.txt.
diff --git a/drivers/virtio/Kconfig b/drivers/virtio/Kconfig
index 1a61939b85fc..f38b17a86c35 100644
--- a/drivers/virtio/Kconfig
+++ b/drivers/virtio/Kconfig
@@ -46,4 +46,15 @@ config VIRTIO_BALLOON
46 46
47 If unsure, say N. 47 If unsure, say N.
48 48
49config VIRTIO_MMIO_CMDLINE_DEVICES
50 bool "Memory mapped virtio devices parameter parsing"
51 depends on VIRTIO_MMIO
52 ---help---
53 Allow virtio-mmio devices instantiation via the kernel command line
54 or module parameters. Be aware that using incorrect parameters (base
55 address in particular) can crash your system - you have been warned.
56 See Documentation/kernel-parameters.txt for details.
57
58 If unsure, say 'N'.
59
49endmenu 60endmenu
diff --git a/drivers/virtio/virtio_mmio.c b/drivers/virtio/virtio_mmio.c
index 01d6dc250d5c..453db0c403d8 100644
--- a/drivers/virtio/virtio_mmio.c
+++ b/drivers/virtio/virtio_mmio.c
@@ -6,6 +6,50 @@
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.
8 * 8 *
9 * The guest device(s) may be instantiated in one of three equivalent ways:
10 *
11 * 1. Static platform device in board's code, eg.:
12 *
13 * static struct platform_device v2m_virtio_device = {
14 * .name = "virtio-mmio",
15 * .id = -1,
16 * .num_resources = 2,
17 * .resource = (struct resource []) {
18 * {
19 * .start = 0x1001e000,
20 * .end = 0x1001e0ff,
21 * .flags = IORESOURCE_MEM,
22 * }, {
23 * .start = 42 + 32,
24 * .end = 42 + 32,
25 * .flags = IORESOURCE_IRQ,
26 * },
27 * }
28 * };
29 *
30 * 2. Device Tree node, eg.:
31 *
32 * virtio_block@1e000 {
33 * compatible = "virtio,mmio";
34 * reg = <0x1e000 0x100>;
35 * interrupts = <42>;
36 * }
37 *
38 * 3. Kernel module (or command line) parameter. Can be used more than once -
39 * one device will be created for each one. Syntax:
40 *
41 * [virtio_mmio.]device=<size>@<baseaddr>:<irq>[:<id>]
42 * where:
43 * <size> := size (can use standard suffixes like K, M or G)
44 * <baseaddr> := physical base address
45 * <irq> := interrupt number (as passed to request_irq())
46 * <id> := (optional) platform device id
47 * eg.:
48 * virtio_mmio.device=0x100@0x100b0000:48 \
49 * virtio_mmio.device=1K@0x1001e000:74
50 *
51 *
52 *
9 * Registers layout (all 32-bit wide): 53 * Registers layout (all 32-bit wide):
10 * 54 *
11 * offset d. name description 55 * offset d. name description
@@ -42,6 +86,8 @@
42 * See the COPYING file in the top-level directory. 86 * See the COPYING file in the top-level directory.
43 */ 87 */
44 88
89#define pr_fmt(fmt) "virtio-mmio: " fmt
90
45#include <linux/highmem.h> 91#include <linux/highmem.h>
46#include <linux/interrupt.h> 92#include <linux/interrupt.h>
47#include <linux/io.h> 93#include <linux/io.h>
@@ -449,6 +495,122 @@ static int __devexit virtio_mmio_remove(struct platform_device *pdev)
449 495
450 496
451 497
498/* Devices list parameter */
499
500#if defined(CONFIG_VIRTIO_MMIO_CMDLINE_DEVICES)
501
502static struct device vm_cmdline_parent = {
503 .init_name = "virtio-mmio-cmdline",
504};
505
506static int vm_cmdline_parent_registered;
507static int vm_cmdline_id;
508
509static int vm_cmdline_set(const char *device,
510 const struct kernel_param *kp)
511{
512 int err;
513 struct resource resources[2] = {};
514 char *str;
515 long long int base;
516 int processed, consumed = 0;
517 struct platform_device *pdev;
518
519 resources[0].flags = IORESOURCE_MEM;
520 resources[1].flags = IORESOURCE_IRQ;
521
522 resources[0].end = memparse(device, &str) - 1;
523
524 processed = sscanf(str, "@%lli:%u%n:%d%n",
525 &base, &resources[1].start, &consumed,
526 &vm_cmdline_id, &consumed);
527
528 if (processed < 2 || processed > 3 || str[consumed])
529 return -EINVAL;
530
531 resources[0].start = base;
532 resources[0].end += base;
533 resources[1].end = resources[1].start;
534
535 if (!vm_cmdline_parent_registered) {
536 err = device_register(&vm_cmdline_parent);
537 if (err) {
538 pr_err("Failed to register parent device!\n");
539 return err;
540 }
541 vm_cmdline_parent_registered = 1;
542 }
543
544 pr_info("Registering device virtio-mmio.%d at 0x%llx-0x%llx, IRQ %d.\n",
545 vm_cmdline_id,
546 (unsigned long long)resources[0].start,
547 (unsigned long long)resources[0].end,
548 (int)resources[1].start);
549
550 pdev = platform_device_register_resndata(&vm_cmdline_parent,
551 "virtio-mmio", vm_cmdline_id++,
552 resources, ARRAY_SIZE(resources), NULL, 0);
553 if (IS_ERR(pdev))
554 return PTR_ERR(pdev);
555
556 return 0;
557}
558
559static int vm_cmdline_get_device(struct device *dev, void *data)
560{
561 char *buffer = data;
562 unsigned int len = strlen(buffer);
563 struct platform_device *pdev = to_platform_device(dev);
564
565 snprintf(buffer + len, PAGE_SIZE - len, "0x%llx@0x%llx:%llu:%d\n",
566 pdev->resource[0].end - pdev->resource[0].start + 1ULL,
567 (unsigned long long)pdev->resource[0].start,
568 (unsigned long long)pdev->resource[1].start,
569 pdev->id);
570 return 0;
571}
572
573static int vm_cmdline_get(char *buffer, const struct kernel_param *kp)
574{
575 buffer[0] = '\0';
576 device_for_each_child(&vm_cmdline_parent, buffer,
577 vm_cmdline_get_device);
578 return strlen(buffer) + 1;
579}
580
581static struct kernel_param_ops vm_cmdline_param_ops = {
582 .set = vm_cmdline_set,
583 .get = vm_cmdline_get,
584};
585
586device_param_cb(device, &vm_cmdline_param_ops, NULL, S_IRUSR);
587
588static int vm_unregister_cmdline_device(struct device *dev,
589 void *data)
590{
591 platform_device_unregister(to_platform_device(dev));
592
593 return 0;
594}
595
596static void vm_unregister_cmdline_devices(void)
597{
598 if (vm_cmdline_parent_registered) {
599 device_for_each_child(&vm_cmdline_parent, NULL,
600 vm_unregister_cmdline_device);
601 device_unregister(&vm_cmdline_parent);
602 vm_cmdline_parent_registered = 0;
603 }
604}
605
606#else
607
608static void vm_unregister_cmdline_devices(void)
609{
610}
611
612#endif
613
452/* Platform driver */ 614/* Platform driver */
453 615
454static struct of_device_id virtio_mmio_match[] = { 616static struct of_device_id virtio_mmio_match[] = {
@@ -475,6 +637,7 @@ static int __init virtio_mmio_init(void)
475static void __exit virtio_mmio_exit(void) 637static void __exit virtio_mmio_exit(void)
476{ 638{
477 platform_driver_unregister(&virtio_mmio_driver); 639 platform_driver_unregister(&virtio_mmio_driver);
640 vm_unregister_cmdline_devices();
478} 641}
479 642
480module_init(virtio_mmio_init); 643module_init(virtio_mmio_init);