From ffd2e8df8d138e7436e218e0a9d3447a18b888e6 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Fri, 1 Dec 2017 11:50:33 -0600 Subject: [PATCH] resource: Set type of "reserve=" user-specified resources When we reserve regions because the user specified a "reserve=" parameter, set the resource type to either IORESOURCE_IO (for regions below 0x10000) or IORESOURCE_MEM. The test for 0x10000 is just a heuristic; obviously there can be memory below 0x10000 as well. Improve documentation of the "reserve=" parameter. Signed-off-by: Bjorn Helgaas --- .../admin-guide/kernel-parameters.txt | 6 ++++- kernel/resource.c | 24 ++++++++++++++----- 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index 6571fbfdb2a1..78cdf6a637fc 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -3675,7 +3675,11 @@ [KNL, SMP] Set scheduler's default relax_domain_level. See Documentation/cgroup-v1/cpusets.txt. - reserve= [KNL,BUGS] Force the kernel to ignore some iomem area + reserve= [KNL,BUGS] Force kernel to ignore I/O ports or memory + Format: ,[,,,...] + Reserve I/O ports or memory so the kernel won't use + them. If is less than 0x10000, the region + is assumed to be I/O ports; otherwise it is memory. reservetop= [X86-32] Format: nn[KMG] diff --git a/kernel/resource.c b/kernel/resource.c index 54ba6de3757c..ba3252f7c319 100644 --- a/kernel/resource.c +++ b/kernel/resource.c @@ -1478,7 +1478,7 @@ void __devm_release_region(struct device *dev, struct resource *parent, EXPORT_SYMBOL(__devm_release_region); /* - * Called from init/main.c to reserve IO ports. + * Reserve I/O ports or memory based on "reserve=" kernel parameter. */ #define MAXRESERVE 4 static int __init reserve_setup(char *str) @@ -1489,26 +1489,38 @@ static int __init reserve_setup(char *str) for (;;) { unsigned int io_start, io_num; int x = reserved; + struct resource *parent; - if (get_option (&str, &io_start) != 2) + if (get_option(&str, &io_start) != 2) break; - if (get_option (&str, &io_num) == 0) + if (get_option(&str, &io_num) == 0) break; if (x < MAXRESERVE) { struct resource *res = reserve + x; + + /* + * If the region starts below 0x10000, we assume it's + * I/O port space; otherwise assume it's memory. + */ + if (io_start < 0x10000) { + res->flags = IORESOURCE_IO; + parent = &ioport_resource; + } else { + res->flags = IORESOURCE_MEM; + parent = &iomem_resource; + } res->name = "reserved"; res->start = io_start; res->end = io_start + io_num - 1; - res->flags = IORESOURCE_BUSY; + res->flags |= IORESOURCE_BUSY; res->desc = IORES_DESC_NONE; res->child = NULL; - if (request_resource(res->start >= 0x10000 ? &iomem_resource : &ioport_resource, res) == 0) + if (request_resource(parent, res) == 0) reserved = x+1; } } return 1; } - __setup("reserve=", reserve_setup); /*