s390: Remove zfcpdump NR_CPUS dependency
authorMichael Holzheu <holzheu@linux.vnet.ibm.com>
Fri, 11 Oct 2013 08:29:23 +0000 (10:29 +0200)
committerMartin Schwidefsky <schwidefsky@de.ibm.com>
Thu, 24 Oct 2013 15:17:04 +0000 (17:17 +0200)
Currently zfpcdump can only collect registers for up to CONFIG_NR_CPUS
CPUss. This dependency is not necessary. So remove it by dynamically
allocating the save area array.

Signed-off-by: Michael Holzheu <holzheu@linux.vnet.ibm.com>
Reviewed-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
arch/s390/include/asm/ipl.h
arch/s390/include/asm/smp.h
arch/s390/kernel/crash_dump.c
arch/s390/kernel/smp.c
drivers/s390/char/zcore.c

index 2bd6cb897b90e86f129a6ae2b4eeca6bd495de95..ea7d9d6ab06e2b33ff3ae946b8d19928d04e963d 100644 (file)
@@ -7,6 +7,7 @@
 #ifndef _ASM_S390_IPL_H
 #define _ASM_S390_IPL_H
 
+#include <asm/lowcore.h>
 #include <asm/types.h>
 #include <asm/cio.h>
 #include <asm/setup.h>
@@ -88,6 +89,14 @@ extern u32 ipl_flags;
 extern u32 dump_prefix_page;
 extern unsigned int zfcpdump_prefix_array[];
 
+struct dump_save_areas {
+       struct save_area **areas;
+       int count;
+};
+
+extern struct dump_save_areas dump_save_areas;
+struct save_area *dump_save_area_create(int cpu);
+
 extern void do_reipl(void);
 extern void do_halt(void);
 extern void do_poff(void);
index b64f15c3b4cc739a13e76ec3c1287328315ecb74..ac9bed8e103fa741f85b3aecc64fcc9a18511c82 100644 (file)
@@ -14,7 +14,6 @@
 #define raw_smp_processor_id() (S390_lowcore.cpu_nr)
 
 extern struct mutex smp_cpu_state_mutex;
-extern struct save_area *zfcpdump_save_areas[NR_CPUS + 1];
 
 extern int __cpu_up(unsigned int cpu, struct task_struct *tidle);
 
index 3db6af0601a576c16ea112f1a83c4eebe9c642d7..f45b2ab0cb81ae425ce2d72c2de9b6fa4fa241a3 100644 (file)
 #define PTR_SUB(x, y) (((char *) (x)) - ((unsigned long) (y)))
 #define PTR_DIFF(x, y) ((unsigned long)(((char *) (x)) - ((unsigned long) (y))))
 
+struct dump_save_areas dump_save_areas;
+
+/*
+ * Allocate and add a save area for a CPU
+ */
+struct save_area *dump_save_area_create(int cpu)
+{
+       struct save_area **save_areas, *save_area;
+
+       save_area = kmalloc(sizeof(*save_area), GFP_KERNEL);
+       if (!save_area)
+               return NULL;
+       if (cpu + 1 > dump_save_areas.count) {
+               dump_save_areas.count = cpu + 1;
+               save_areas = krealloc(dump_save_areas.areas,
+                                     dump_save_areas.count * sizeof(void *),
+                                     GFP_KERNEL | __GFP_ZERO);
+               if (!save_areas) {
+                       kfree(save_area);
+                       return NULL;
+               }
+               dump_save_areas.areas = save_areas;
+       }
+       dump_save_areas.areas[cpu] = save_area;
+       return save_area;
+}
 
 /*
  * Return physical address for virtual address
@@ -450,8 +476,8 @@ static int get_cpu_cnt(void)
 {
        int i, cpus = 0;
 
-       for (i = 0; zfcpdump_save_areas[i]; i++) {
-               if (zfcpdump_save_areas[i]->pref_reg == 0)
+       for (i = 0; i < dump_save_areas.count; i++) {
+               if (dump_save_areas.areas[i]->pref_reg == 0)
                        continue;
                cpus++;
        }
@@ -522,8 +548,8 @@ static void *notes_init(Elf64_Phdr *phdr, void *ptr, u64 notes_offset)
 
        ptr = nt_prpsinfo(ptr);
 
-       for (i = 0; zfcpdump_save_areas[i]; i++) {
-               sa = zfcpdump_save_areas[i];
+       for (i = 0; i < dump_save_areas.count; i++) {
+               sa = dump_save_areas.areas[i];
                if (sa->pref_reg == 0)
                        continue;
                ptr = fill_cpu_elf_notes(ptr, sa);
index cca6cf6abacc16645eb18804d2f19705a5dbb6bd..739313db71e5e2431f32c59472cdaa89ccbae2ef 100644 (file)
@@ -533,9 +533,6 @@ EXPORT_SYMBOL(smp_ctl_clear_bit);
 
 #if defined(CONFIG_ZFCPDUMP) || defined(CONFIG_CRASH_DUMP)
 
-struct save_area *zfcpdump_save_areas[NR_CPUS + 1];
-EXPORT_SYMBOL_GPL(zfcpdump_save_areas);
-
 static void __init smp_get_save_area(int cpu, u16 address)
 {
        void *lc = pcpu_devices[0].lowcore;
@@ -546,15 +543,9 @@ static void __init smp_get_save_area(int cpu, u16 address)
        if (!OLDMEM_BASE && (address == boot_cpu_address ||
                             ipl_info.type != IPL_TYPE_FCP_DUMP))
                return;
-       if (cpu >= NR_CPUS) {
-               pr_warning("CPU %i exceeds the maximum %i and is excluded "
-                          "from the dump\n", cpu, NR_CPUS - 1);
-               return;
-       }
-       save_area = kmalloc(sizeof(struct save_area), GFP_KERNEL);
+       save_area = dump_save_area_create(cpu);
        if (!save_area)
                panic("could not allocate memory for save area\n");
-       zfcpdump_save_areas[cpu] = save_area;
 #ifdef CONFIG_CRASH_DUMP
        if (address == boot_cpu_address) {
                /* Copy the registers of the boot cpu. */
index 794820a123d0c83c07b1b2e546efc84c25daa14a..ffb1fcf0bf5bed9928f53e1205f8b6b01635f6b6 100644 (file)
@@ -151,7 +151,7 @@ static int __init init_cpu_info(enum arch_id arch)
 
        /* get info for boot cpu from lowcore, stored in the HSA */
 
-       sa = kmalloc(sizeof(*sa), GFP_KERNEL);
+       sa = dump_save_area_create(0);
        if (!sa)
                return -ENOMEM;
        if (memcpy_hsa_kernel(sa, sys_info.sa_base, sys_info.sa_size) < 0) {
@@ -159,7 +159,6 @@ static int __init init_cpu_info(enum arch_id arch)
                kfree(sa);
                return -EIO;
        }
-       zfcpdump_save_areas[0] = sa;
        return 0;
 }
 
@@ -246,24 +245,25 @@ static int copy_lc(void __user *buf, void *sa, int sa_off, int len)
 static int zcore_add_lc(char __user *buf, unsigned long start, size_t count)
 {
        unsigned long end;
-       int i = 0;
+       int i;
 
        if (count == 0)
                return 0;
 
        end = start + count;
-       while (zfcpdump_save_areas[i]) {
+       for (i = 0; i < dump_save_areas.count; i++) {
                unsigned long cp_start, cp_end; /* copy range */
                unsigned long sa_start, sa_end; /* save area range */
                unsigned long prefix;
                unsigned long sa_off, len, buf_off;
+               struct save_area *save_area = dump_save_areas.areas[i];
 
-               prefix = zfcpdump_save_areas[i]->pref_reg;
+               prefix = save_area->pref_reg;
                sa_start = prefix + sys_info.sa_base;
                sa_end = prefix + sys_info.sa_base + sys_info.sa_size;
 
                if ((end < sa_start) || (start > sa_end))
-                       goto next;
+                       continue;
                cp_start = max(start, sa_start);
                cp_end = min(end, sa_end);
 
@@ -272,10 +272,8 @@ static int zcore_add_lc(char __user *buf, unsigned long start, size_t count)
                len = cp_end - cp_start;
 
                TRACE("copy_lc for: %lx\n", start);
-               if (copy_lc(buf + buf_off, zfcpdump_save_areas[i], sa_off, len))
+               if (copy_lc(buf + buf_off, save_area, sa_off, len))
                        return -EFAULT;
-next:
-               i++;
        }
        return 0;
 }
@@ -637,8 +635,8 @@ static void __init zcore_header_init(int arch, struct zcore_header *hdr,
        hdr->num_pages = mem_size / PAGE_SIZE;
        hdr->tod = get_tod_clock();
        get_cpu_id(&hdr->cpu_id);
-       for (i = 0; zfcpdump_save_areas[i]; i++) {
-               prefix = zfcpdump_save_areas[i]->pref_reg;
+       for (i = 0; i < dump_save_areas.count; i++) {
+               prefix = dump_save_areas.areas[i]->pref_reg;
                hdr->real_cpu_cnt++;
                if (!prefix)
                        continue;