History

Merge branches 'pm-sleep' and 'pm-cpufreq'

* pm-sleep: PM / hibernate: Restore processor state before using per-CPU variables x86/power/64: Always create temporary identity mapping correctly * pm-cpufreq: cpufreq: powernv: Fix crash in gpstate_timer_handler()

Rafael J. Wysocki committed 10 years ago

Commit 0aeeb3e3 parents 29b4817 62822e2 8e859465 files · +36 −14Browse files

Unified · Split

5 files
  1. arch/x86/include/asm/init.h +2 −2
  2. arch/x86/mm/ident_map.c +11 −8
  3. arch/x86/power/hibernate_64.c +1 −1
  4. drivers/cpufreq/powernv-cpufreq.c +20 −1
  5. kernel/power/hibernate.c +2 −2
arch/x86/include/asm/init.h+2−2
@@ -5,10 +5,10 @@ struct x86_mapping_info { · 4 unmodified lines
55 void *(*alloc_pgt_page)(void *); /* allocate buf for page table */
66 void *context; /* context for alloc_pgt_page */
77 unsigned long pmd_flag; /* page flag for PMD entry */
8− bool kernel_mapping; /* kernel mapping or ident mapping */
8+ unsigned long offset; /* ident mapping offset */
99 };
1010
1111 int kernel_ident_mapping_init(struct x86_mapping_info *info, pgd_t *pgd_page,
12− unsigned long addr, unsigned long end);
12+ unsigned long pstart, unsigned long pend);
1313
1414 #endif /* _ASM_X86_INIT_H */
arch/x86/mm/ident_map.c+11−8
@@ -3,15 +3,17 @@ · 2 unmodified lines
33 * included by both the compressed kernel and the regular kernel.
44 */
55
6−static void ident_pmd_init(unsigned long pmd_flag, pmd_t *pmd_page,
6+static void ident_pmd_init(struct x86_mapping_info *info, pmd_t *pmd_page,
77 unsigned long addr, unsigned long end)
88 {
99 addr &= PMD_MASK;
1010 for (; addr < end; addr += PMD_SIZE) {
1111 pmd_t *pmd = pmd_page + pmd_index(addr);
1212
13− if (!pmd_present(*pmd))
14− set_pmd(pmd, __pmd(addr | pmd_flag));
13+ if (pmd_present(*pmd))
14+ continue;
15+
16+ set_pmd(pmd, __pmd((addr - info->offset) | info->pmd_flag));
1517 }
1618 }
1719
@@ -30,13 +32,13 @@ static int ident_pud_init(struct x86_mapping_info *info, pud_t *pud_page, · 12 unmodified lines
3032
3133 if (pud_present(*pud)) {
3234 pmd = pmd_offset(pud, 0);
33− ident_pmd_init(info->pmd_flag, pmd, addr, next);
35+ ident_pmd_init(info, pmd, addr, next);
3436 continue;
3537 }
3638 pmd = (pmd_t *)info->alloc_pgt_page(info->context);
3739 if (!pmd)
3840 return -ENOMEM;
39− ident_pmd_init(info->pmd_flag, pmd, addr, next);
41+ ident_pmd_init(info, pmd, addr, next);
4042 set_pud(pud, __pud(__pa(pmd) | _KERNPG_TABLE));
4143 }
4244
@@ -44,14 +46,15 @@ static int ident_pud_init(struct x86_mapping_info *info, pud_t *pud_page, · 1 unmodified line
4446 }
4547
4648 int kernel_ident_mapping_init(struct x86_mapping_info *info, pgd_t *pgd_page,
47− unsigned long addr, unsigned long end)
49+ unsigned long pstart, unsigned long pend)
4850 {
51+ unsigned long addr = pstart + info->offset;
52+ unsigned long end = pend + info->offset;
4953 unsigned long next;
5054 int result;
51− int off = info->kernel_mapping ? pgd_index(__PAGE_OFFSET) : 0;
5255
5356 for (; addr < end; addr = next) {
54− pgd_t *pgd = pgd_page + pgd_index(addr) + off;
57+ pgd_t *pgd = pgd_page + pgd_index(addr);
5558 pud_t *pud;
5659
5760 next = (addr & PGDIR_MASK) + PGDIR_SIZE;
arch/x86/power/hibernate_64.c+1−1
@@ -87,7 +87,7 @@ static int set_up_temporary_mappings(void) · 86 unmodified lines
8787 struct x86_mapping_info info = {
8888 .alloc_pgt_page = alloc_pgt_page,
8989 .pmd_flag = __PAGE_KERNEL_LARGE_EXEC,
90− .kernel_mapping = true,
90+ .offset = __PAGE_OFFSET,
9191 };
9292 unsigned long mstart, mend;
9393 pgd_t *pgd;
drivers/cpufreq/powernv-cpufreq.c+20−1
@@ -145,11 +145,30 @@ static struct powernv_pstate_info { · 144 unmodified lines
145145 /* Use following macros for conversions between pstate_id and index */
146146 static inline int idx_to_pstate(unsigned int i)
147147 {
148+ if (unlikely(i >= powernv_pstate_info.nr_pstates)) {
149+ pr_warn_once("index %u is out of bound\n", i);
150+ return powernv_freqs[powernv_pstate_info.nominal].driver_data;
151+ }
152+
148153 return powernv_freqs[i].driver_data;
149154 }
150155
151156 static inline unsigned int pstate_to_idx(int pstate)
152157 {
158+ int min = powernv_freqs[powernv_pstate_info.min].driver_data;
159+ int max = powernv_freqs[powernv_pstate_info.max].driver_data;
160+
161+ if (min > 0) {
162+ if (unlikely((pstate < max) || (pstate > min))) {
163+ pr_warn_once("pstate %d is out of bound\n", pstate);
164+ return powernv_pstate_info.nominal;
165+ }
166+ } else {
167+ if (unlikely((pstate > max) || (pstate < min))) {
168+ pr_warn_once("pstate %d is out of bound\n", pstate);
169+ return powernv_pstate_info.nominal;
170+ }
171+ }
153172 /*
154173 * abs() is deliberately used so that is works with
155174 * both monotonically increasing and decreasing
@@ -593,7 +612,7 @@ void gpstate_timer_handler(unsigned long data) · 437 unmodified lines
593612 } else {
594613 gpstate_idx = calc_global_pstate(gpstates->elapsed_time,
595614 gpstates->highest_lpstate_idx,
596− freq_data.pstate_id);
615+ gpstates->last_lpstate_idx);
597616 }
598617
599618 /*
kernel/power/hibernate.c+2−2
@@ -300,12 +300,12 @@ static int create_image(int platform_mode) · 299 unmodified lines
300300 save_processor_state();
301301 trace_suspend_resume(TPS("machine_suspend"), PM_EVENT_HIBERNATE, true);
302302 error = swsusp_arch_suspend();
303+ /* Restore control flow magically appears here */
304+ restore_processor_state();
303305 trace_suspend_resume(TPS("machine_suspend"), PM_EVENT_HIBERNATE, false);
304306 if (error)
305307 printk(KERN_ERR "PM: Error %d creating hibernation image\n",
306308 error);
307− /* Restore control flow magically appears here */
308− restore_processor_state();
309309 if (!in_suspend)
310310 events_check_enabled = false;
311311