ACPI / x86: Increase override tables number limit

Current ACPI tables in initrd is limited to 10, that is too small.
64 should be good enough as we have 35 sigs and could have several
SSDT.

Two problems in current code prevent us from increasing limit:
 1. The cpio file info array is put in stack, as every element is 32
    bytes, could run out of stack if we have that array size to 64.
    We can move it out from stack, make it global and put it into the
    __initdata section.
 2. early_ioremap() only can remap 256k one time. Current code maps
    10 tables at a time. If we increased that limit, the whole size
    could be more than 256k, so early_ioremap() would fail with that.
    We can map chunks one by one during copying, instead of mapping
    all of them together.

Signed-off-by: Yinghai <yinghai@kernel.org>
Acked-by: Tejun Heo <tj@kernel.org>
Tested-by: Thomas Renninger <trenn@suse.de>
Reviewed-by: Tang Chen <tangchen@cn.fujitsu.com>
Tested-by: Tang Chen <tangchen@cn.fujitsu.com>
Acked-by: Toshi Kani <toshi.kani@hp.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
This commit is contained in:
Yinghai Lu 2013-09-06 19:08:00 -07:00 committed by Rafael J. Wysocki
parent 4a10c2ac2f
commit bee7f9c83e
2 changed files with 33 additions and 12 deletions

View File

@ -26,6 +26,7 @@
#include <acpi/pdc_intel.h> #include <acpi/pdc_intel.h>
#include <asm/numa.h> #include <asm/numa.h>
#include <asm/fixmap.h>
#include <asm/processor.h> #include <asm/processor.h>
#include <asm/mmu.h> #include <asm/mmu.h>
#include <asm/mpspec.h> #include <asm/mpspec.h>

View File

@ -569,8 +569,10 @@ static const char * const table_sigs[] = {
#define ACPI_HEADER_SIZE sizeof(struct acpi_table_header) #define ACPI_HEADER_SIZE sizeof(struct acpi_table_header)
/* Must not increase 10 or needs code modification below */ #define ACPI_OVERRIDE_TABLES 64
#define ACPI_OVERRIDE_TABLES 10 static struct cpio_data __initdata acpi_initrd_files[ACPI_OVERRIDE_TABLES];
#define MAP_CHUNK_SIZE (NR_FIX_BTMAPS << PAGE_SHIFT)
void __init acpi_initrd_override(void *data, size_t size) void __init acpi_initrd_override(void *data, size_t size)
{ {
@ -579,8 +581,6 @@ void __init acpi_initrd_override(void *data, size_t size)
struct acpi_table_header *table; struct acpi_table_header *table;
char cpio_path[32] = "kernel/firmware/acpi/"; char cpio_path[32] = "kernel/firmware/acpi/";
struct cpio_data file; struct cpio_data file;
struct cpio_data early_initrd_files[ACPI_OVERRIDE_TABLES];
char *p;
if (data == NULL || size == 0) if (data == NULL || size == 0)
return; return;
@ -625,8 +625,8 @@ void __init acpi_initrd_override(void *data, size_t size)
table->signature, cpio_path, file.name, table->length); table->signature, cpio_path, file.name, table->length);
all_tables_size += table->length; all_tables_size += table->length;
early_initrd_files[table_nr].data = file.data; acpi_initrd_files[table_nr].data = file.data;
early_initrd_files[table_nr].size = file.size; acpi_initrd_files[table_nr].size = file.size;
table_nr++; table_nr++;
} }
if (table_nr == 0) if (table_nr == 0)
@ -652,14 +652,34 @@ void __init acpi_initrd_override(void *data, size_t size)
memblock_reserve(acpi_tables_addr, all_tables_size); memblock_reserve(acpi_tables_addr, all_tables_size);
arch_reserve_mem_area(acpi_tables_addr, all_tables_size); arch_reserve_mem_area(acpi_tables_addr, all_tables_size);
p = early_ioremap(acpi_tables_addr, all_tables_size); /*
* early_ioremap only can remap 256k one time. If we map all
* tables one time, we will hit the limit. Need to map chunks
* one by one during copying the same as that in relocate_initrd().
*/
for (no = 0; no < table_nr; no++) { for (no = 0; no < table_nr; no++) {
memcpy(p + total_offset, early_initrd_files[no].data, unsigned char *src_p = acpi_initrd_files[no].data;
early_initrd_files[no].size); phys_addr_t size = acpi_initrd_files[no].size;
total_offset += early_initrd_files[no].size; phys_addr_t dest_addr = acpi_tables_addr + total_offset;
phys_addr_t slop, clen;
char *dest_p;
total_offset += size;
while (size) {
slop = dest_addr & ~PAGE_MASK;
clen = size;
if (clen > MAP_CHUNK_SIZE - slop)
clen = MAP_CHUNK_SIZE - slop;
dest_p = early_ioremap(dest_addr & PAGE_MASK,
clen + slop);
memcpy(dest_p + slop, src_p, clen);
early_iounmap(dest_p, clen + slop);
src_p += clen;
dest_addr += clen;
size -= clen;
}
} }
early_iounmap(p, all_tables_size);
} }
#endif /* CONFIG_ACPI_INITRD_TABLE_OVERRIDE */ #endif /* CONFIG_ACPI_INITRD_TABLE_OVERRIDE */