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
5 void *(*alloc_pgt_page)(void *); /* allocate buf for page table */5 void *(*alloc_pgt_page)(void *); /* allocate buf for page table */
6 void *context; /* context for alloc_pgt_page */6 void *context; /* context for alloc_pgt_page */
7 unsigned long pmd_flag; /* page flag for PMD entry */7 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 */
9};9};
10 10
11int kernel_ident_mapping_init(struct x86_mapping_info *info, pgd_t *pgd_page,11int 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);
13 13
14#endif /* _ASM_X86_INIT_H */14#endif /* _ASM_X86_INIT_H */
arch/x86/mm/ident_map.c+11−8
@@ -3,15 +3,17 @@ · 2 unmodified lines
3 * included by both the compressed kernel and the regular kernel.3 * included by both the compressed kernel and the regular kernel.
4 */4 */
5 5
6static void ident_pmd_init(unsigned long pmd_flag, pmd_t *pmd_page,6static void ident_pmd_init(struct x86_mapping_info *info, pmd_t *pmd_page,
7 unsigned long addr, unsigned long end)7 unsigned long addr, unsigned long end)
8{8{
9 addr &= PMD_MASK;9 addr &= PMD_MASK;
10 for (; addr < end; addr += PMD_SIZE) {10 for (; addr < end; addr += PMD_SIZE) {
11 pmd_t *pmd = pmd_page + pmd_index(addr);11 pmd_t *pmd = pmd_page + pmd_index(addr);
12 12
13 if (!pmd_present(*pmd))13 if (pmd_present(*pmd))
14 set_pmd(pmd, __pmd(addr | pmd_flag));14 continue;
15
16 set_pmd(pmd, __pmd((addr - info->offset) | info->pmd_flag));
15 }17 }
16}18}
17 19
@@ -30,13 +32,13 @@ static int ident_pud_init(struct x86_mapping_info *info, pud_t *pud_page, · 12 unmodified lines
30 32
31 if (pud_present(*pud)) {33 if (pud_present(*pud)) {
32 pmd = pmd_offset(pud, 0);34 pmd = pmd_offset(pud, 0);
33 ident_pmd_init(info->pmd_flag, pmd, addr, next);35 ident_pmd_init(info, pmd, addr, next);
34 continue;36 continue;
35 }37 }
36 pmd = (pmd_t *)info->alloc_pgt_page(info->context);38 pmd = (pmd_t *)info->alloc_pgt_page(info->context);
37 if (!pmd)39 if (!pmd)
38 return -ENOMEM;40 return -ENOMEM;
39 ident_pmd_init(info->pmd_flag, pmd, addr, next);41 ident_pmd_init(info, pmd, addr, next);
40 set_pud(pud, __pud(__pa(pmd) | _KERNPG_TABLE));42 set_pud(pud, __pud(__pa(pmd) | _KERNPG_TABLE));
41 }43 }
42 44
@@ -44,14 +46,15 @@ static int ident_pud_init(struct x86_mapping_info *info, pud_t *pud_page, · 1 unmodified line
44}46}
45 47
46int kernel_ident_mapping_init(struct x86_mapping_info *info, pgd_t *pgd_page,48int 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)
48{50{
51 unsigned long addr = pstart + info->offset;
52 unsigned long end = pend + info->offset;
49 unsigned long next;53 unsigned long next;
50 int result;54 int result;
51 int off = info->kernel_mapping ? pgd_index(__PAGE_OFFSET) : 0;
52 55
53 for (; addr < end; addr = next) {56 for (; addr < end; addr = next) {
54 pgd_t *pgd = pgd_page + pgd_index(addr) + off;57 pgd_t *pgd = pgd_page + pgd_index(addr);
55 pud_t *pud;58 pud_t *pud;
56 59
57 next = (addr & PGDIR_MASK) + PGDIR_SIZE;60 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
87 struct x86_mapping_info info = {87 struct x86_mapping_info info = {
88 .alloc_pgt_page = alloc_pgt_page,88 .alloc_pgt_page = alloc_pgt_page,
89 .pmd_flag = __PAGE_KERNEL_LARGE_EXEC,89 .pmd_flag = __PAGE_KERNEL_LARGE_EXEC,
90 .kernel_mapping = true,90 .offset = __PAGE_OFFSET,
91 };91 };
92 unsigned long mstart, mend;92 unsigned long mstart, mend;
93 pgd_t *pgd;93 pgd_t *pgd;
drivers/cpufreq/powernv-cpufreq.c+20−1
@@ -145,11 +145,30 @@ static struct powernv_pstate_info { · 144 unmodified lines
145/* Use following macros for conversions between pstate_id and index */145/* Use following macros for conversions between pstate_id and index */
146static inline int idx_to_pstate(unsigned int i)146static inline int idx_to_pstate(unsigned int i)
147{147{
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
148 return powernv_freqs[i].driver_data;153 return powernv_freqs[i].driver_data;
149}154}
150 155
151static inline unsigned int pstate_to_idx(int pstate)156static inline unsigned int pstate_to_idx(int pstate)
152{157{
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 }
153 /*172 /*
154 * abs() is deliberately used so that is works with173 * abs() is deliberately used so that is works with
155 * both monotonically increasing and decreasing174 * both monotonically increasing and decreasing
@@ -593,7 +612,7 @@ void gpstate_timer_handler(unsigned long data) · 437 unmodified lines
593 } else {612 } else {
594 gpstate_idx = calc_global_pstate(gpstates->elapsed_time,613 gpstate_idx = calc_global_pstate(gpstates->elapsed_time,
595 gpstates->highest_lpstate_idx,614 gpstates->highest_lpstate_idx,
596 freq_data.pstate_id);615 gpstates->last_lpstate_idx);
597 }616 }
598 617
599 /*618 /*
kernel/power/hibernate.c+2−2
@@ -300,12 +300,12 @@ static int create_image(int platform_mode) · 299 unmodified lines
300 save_processor_state();300 save_processor_state();
301 trace_suspend_resume(TPS("machine_suspend"), PM_EVENT_HIBERNATE, true);301 trace_suspend_resume(TPS("machine_suspend"), PM_EVENT_HIBERNATE, true);
302 error = swsusp_arch_suspend();302 error = swsusp_arch_suspend();
303 /* Restore control flow magically appears here */
304 restore_processor_state();
303 trace_suspend_resume(TPS("machine_suspend"), PM_EVENT_HIBERNATE, false);305 trace_suspend_resume(TPS("machine_suspend"), PM_EVENT_HIBERNATE, false);
304 if (error)306 if (error)
305 printk(KERN_ERR "PM: Error %d creating hibernation image\n",307 printk(KERN_ERR "PM: Error %d creating hibernation image\n",
306 error);308 error);
307 /* Restore control flow magically appears here */
308 restore_processor_state();
309 if (!in_suspend)309 if (!in_suspend)
310 events_check_enabled = false;310 events_check_enabled = false;
311 311