diff options
144 files changed, 2160 insertions, 1248 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 560ecce38ff5..f1bc3dc6b369 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -4292,10 +4292,7 @@ S: Maintained | |||
4292 | F: net/sched/sch_netem.c | 4292 | F: net/sched/sch_netem.c |
4293 | 4293 | ||
4294 | NETERION 10GbE DRIVERS (s2io/vxge) | 4294 | NETERION 10GbE DRIVERS (s2io/vxge) |
4295 | M: Ramkrishna Vepa <ramkrishna.vepa@exar.com> | 4295 | M: Jon Mason <jdmason@kudzu.us> |
4296 | M: Sivakumar Subramani <sivakumar.subramani@exar.com> | ||
4297 | M: Sreenivasa Honnur <sreenivasa.honnur@exar.com> | ||
4298 | M: Jon Mason <jon.mason@exar.com> | ||
4299 | L: netdev@vger.kernel.org | 4296 | L: netdev@vger.kernel.org |
4300 | W: http://trac.neterion.com/cgi-bin/trac.cgi/wiki/Linux?Anonymous | 4297 | W: http://trac.neterion.com/cgi-bin/trac.cgi/wiki/Linux?Anonymous |
4301 | W: http://trac.neterion.com/cgi-bin/trac.cgi/wiki/X3100Linux?Anonymous | 4298 | W: http://trac.neterion.com/cgi-bin/trac.cgi/wiki/X3100Linux?Anonymous |
@@ -1,7 +1,7 @@ | |||
1 | VERSION = 2 | 1 | VERSION = 2 |
2 | PATCHLEVEL = 6 | 2 | PATCHLEVEL = 6 |
3 | SUBLEVEL = 38 | 3 | SUBLEVEL = 38 |
4 | EXTRAVERSION = -rc8 | 4 | EXTRAVERSION = |
5 | NAME = Flesh-Eating Bats with Fangs | 5 | NAME = Flesh-Eating Bats with Fangs |
6 | 6 | ||
7 | # *DOCUMENTATION* | 7 | # *DOCUMENTATION* |
diff --git a/arch/ia64/include/asm/xen/hypercall.h b/arch/ia64/include/asm/xen/hypercall.h index 96fc62366aa4..ed28bcd5bb85 100644 --- a/arch/ia64/include/asm/xen/hypercall.h +++ b/arch/ia64/include/asm/xen/hypercall.h | |||
@@ -107,7 +107,7 @@ extern unsigned long __hypercall(unsigned long a1, unsigned long a2, | |||
107 | static inline int | 107 | static inline int |
108 | xencomm_arch_hypercall_sched_op(int cmd, struct xencomm_handle *arg) | 108 | xencomm_arch_hypercall_sched_op(int cmd, struct xencomm_handle *arg) |
109 | { | 109 | { |
110 | return _hypercall2(int, sched_op_new, cmd, arg); | 110 | return _hypercall2(int, sched_op, cmd, arg); |
111 | } | 111 | } |
112 | 112 | ||
113 | static inline long | 113 | static inline long |
diff --git a/arch/ia64/xen/suspend.c b/arch/ia64/xen/suspend.c index fd66b048c6fa..419c8620945a 100644 --- a/arch/ia64/xen/suspend.c +++ b/arch/ia64/xen/suspend.c | |||
@@ -37,19 +37,14 @@ xen_mm_unpin_all(void) | |||
37 | /* nothing */ | 37 | /* nothing */ |
38 | } | 38 | } |
39 | 39 | ||
40 | void xen_pre_device_suspend(void) | ||
41 | { | ||
42 | /* nothing */ | ||
43 | } | ||
44 | |||
45 | void | 40 | void |
46 | xen_pre_suspend() | 41 | xen_arch_pre_suspend() |
47 | { | 42 | { |
48 | /* nothing */ | 43 | /* nothing */ |
49 | } | 44 | } |
50 | 45 | ||
51 | void | 46 | void |
52 | xen_post_suspend(int suspend_cancelled) | 47 | xen_arch_post_suspend(int suspend_cancelled) |
53 | { | 48 | { |
54 | if (suspend_cancelled) | 49 | if (suspend_cancelled) |
55 | return; | 50 | return; |
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index f5ecc0566bc2..d88983516e26 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig | |||
@@ -4,6 +4,7 @@ config MIPS | |||
4 | select HAVE_GENERIC_DMA_COHERENT | 4 | select HAVE_GENERIC_DMA_COHERENT |
5 | select HAVE_IDE | 5 | select HAVE_IDE |
6 | select HAVE_OPROFILE | 6 | select HAVE_OPROFILE |
7 | select HAVE_IRQ_WORK | ||
7 | select HAVE_PERF_EVENTS | 8 | select HAVE_PERF_EVENTS |
8 | select PERF_USE_VMALLOC | 9 | select PERF_USE_VMALLOC |
9 | select HAVE_ARCH_KGDB | 10 | select HAVE_ARCH_KGDB |
@@ -208,6 +209,7 @@ config MACH_JZ4740 | |||
208 | select ARCH_REQUIRE_GPIOLIB | 209 | select ARCH_REQUIRE_GPIOLIB |
209 | select SYS_HAS_EARLY_PRINTK | 210 | select SYS_HAS_EARLY_PRINTK |
210 | select HAVE_PWM | 211 | select HAVE_PWM |
212 | select HAVE_CLK | ||
211 | 213 | ||
212 | config LASAT | 214 | config LASAT |
213 | bool "LASAT Networks platforms" | 215 | bool "LASAT Networks platforms" |
@@ -333,6 +335,8 @@ config PNX8550_STB810 | |||
333 | config PMC_MSP | 335 | config PMC_MSP |
334 | bool "PMC-Sierra MSP chipsets" | 336 | bool "PMC-Sierra MSP chipsets" |
335 | depends on EXPERIMENTAL | 337 | depends on EXPERIMENTAL |
338 | select CEVT_R4K | ||
339 | select CSRC_R4K | ||
336 | select DMA_NONCOHERENT | 340 | select DMA_NONCOHERENT |
337 | select SWAP_IO_SPACE | 341 | select SWAP_IO_SPACE |
338 | select NO_EXCEPT_FILL | 342 | select NO_EXCEPT_FILL |
diff --git a/arch/mips/alchemy/mtx-1/board_setup.c b/arch/mips/alchemy/mtx-1/board_setup.c index 6398fa95905c..40b84b991191 100644 --- a/arch/mips/alchemy/mtx-1/board_setup.c +++ b/arch/mips/alchemy/mtx-1/board_setup.c | |||
@@ -54,8 +54,8 @@ int mtx1_pci_idsel(unsigned int devsel, int assert); | |||
54 | 54 | ||
55 | static void mtx1_reset(char *c) | 55 | static void mtx1_reset(char *c) |
56 | { | 56 | { |
57 | /* Hit BCSR.SYSTEM_CONTROL[SW_RST] */ | 57 | /* Jump to the reset vector */ |
58 | au_writel(0x00000000, 0xAE00001C); | 58 | __asm__ __volatile__("jr\t%0"::"r"(0xbfc00000)); |
59 | } | 59 | } |
60 | 60 | ||
61 | static void mtx1_power_off(void) | 61 | static void mtx1_power_off(void) |
diff --git a/arch/mips/alchemy/mtx-1/platform.c b/arch/mips/alchemy/mtx-1/platform.c index e30e42add697..956f946218c5 100644 --- a/arch/mips/alchemy/mtx-1/platform.c +++ b/arch/mips/alchemy/mtx-1/platform.c | |||
@@ -28,6 +28,8 @@ | |||
28 | #include <linux/mtd/physmap.h> | 28 | #include <linux/mtd/physmap.h> |
29 | #include <mtd/mtd-abi.h> | 29 | #include <mtd/mtd-abi.h> |
30 | 30 | ||
31 | #include <asm/mach-au1x00/au1xxx_eth.h> | ||
32 | |||
31 | static struct gpio_keys_button mtx1_gpio_button[] = { | 33 | static struct gpio_keys_button mtx1_gpio_button[] = { |
32 | { | 34 | { |
33 | .gpio = 207, | 35 | .gpio = 207, |
@@ -140,10 +142,17 @@ static struct __initdata platform_device * mtx1_devs[] = { | |||
140 | &mtx1_mtd, | 142 | &mtx1_mtd, |
141 | }; | 143 | }; |
142 | 144 | ||
145 | static struct au1000_eth_platform_data mtx1_au1000_eth0_pdata = { | ||
146 | .phy_search_highest_addr = 1, | ||
147 | .phy1_search_mac0 = 1, | ||
148 | }; | ||
149 | |||
143 | static int __init mtx1_register_devices(void) | 150 | static int __init mtx1_register_devices(void) |
144 | { | 151 | { |
145 | int rc; | 152 | int rc; |
146 | 153 | ||
154 | au1xxx_override_eth_cfg(0, &mtx1_au1000_eth0_pdata); | ||
155 | |||
147 | rc = gpio_request(mtx1_gpio_button[0].gpio, | 156 | rc = gpio_request(mtx1_gpio_button[0].gpio, |
148 | mtx1_gpio_button[0].desc); | 157 | mtx1_gpio_button[0].desc); |
149 | if (rc < 0) { | 158 | if (rc < 0) { |
diff --git a/arch/mips/alchemy/xxs1500/board_setup.c b/arch/mips/alchemy/xxs1500/board_setup.c index b43c918925d3..80c521e5290d 100644 --- a/arch/mips/alchemy/xxs1500/board_setup.c +++ b/arch/mips/alchemy/xxs1500/board_setup.c | |||
@@ -36,8 +36,8 @@ | |||
36 | 36 | ||
37 | static void xxs1500_reset(char *c) | 37 | static void xxs1500_reset(char *c) |
38 | { | 38 | { |
39 | /* Hit BCSR.SYSTEM_CONTROL[SW_RST] */ | 39 | /* Jump to the reset vector */ |
40 | au_writel(0x00000000, 0xAE00001C); | 40 | __asm__ __volatile__("jr\t%0"::"r"(0xbfc00000)); |
41 | } | 41 | } |
42 | 42 | ||
43 | static void xxs1500_power_off(void) | 43 | static void xxs1500_power_off(void) |
diff --git a/arch/mips/include/asm/perf_event.h b/arch/mips/include/asm/perf_event.h index e00007cf8162..d0c77496c728 100644 --- a/arch/mips/include/asm/perf_event.h +++ b/arch/mips/include/asm/perf_event.h | |||
@@ -11,15 +11,5 @@ | |||
11 | 11 | ||
12 | #ifndef __MIPS_PERF_EVENT_H__ | 12 | #ifndef __MIPS_PERF_EVENT_H__ |
13 | #define __MIPS_PERF_EVENT_H__ | 13 | #define __MIPS_PERF_EVENT_H__ |
14 | 14 | /* Leave it empty here. The file is required by linux/perf_event.h */ | |
15 | /* | ||
16 | * MIPS performance counters do not raise NMI upon overflow, a regular | ||
17 | * interrupt will be signaled. Hence we can do the pending perf event | ||
18 | * work at the tail of the irq handler. | ||
19 | */ | ||
20 | static inline void | ||
21 | set_perf_event_pending(void) | ||
22 | { | ||
23 | } | ||
24 | |||
25 | #endif /* __MIPS_PERF_EVENT_H__ */ | 15 | #endif /* __MIPS_PERF_EVENT_H__ */ |
diff --git a/arch/mips/kernel/ftrace.c b/arch/mips/kernel/ftrace.c index 5a84a1f11231..94ca2b018af7 100644 --- a/arch/mips/kernel/ftrace.c +++ b/arch/mips/kernel/ftrace.c | |||
@@ -17,29 +17,13 @@ | |||
17 | #include <asm/cacheflush.h> | 17 | #include <asm/cacheflush.h> |
18 | #include <asm/uasm.h> | 18 | #include <asm/uasm.h> |
19 | 19 | ||
20 | /* | 20 | #include <asm-generic/sections.h> |
21 | * If the Instruction Pointer is in module space (0xc0000000), return true; | ||
22 | * otherwise, it is in kernel space (0x80000000), return false. | ||
23 | * | ||
24 | * FIXME: This will not work when the kernel space and module space are the | ||
25 | * same. If they are the same, we need to modify scripts/recordmcount.pl, | ||
26 | * ftrace_make_nop/call() and the other related parts to ensure the | ||
27 | * enabling/disabling of the calling site to _mcount is right for both kernel | ||
28 | * and module. | ||
29 | */ | ||
30 | |||
31 | static inline int in_module(unsigned long ip) | ||
32 | { | ||
33 | return ip & 0x40000000; | ||
34 | } | ||
35 | 21 | ||
36 | #ifdef CONFIG_DYNAMIC_FTRACE | 22 | #ifdef CONFIG_DYNAMIC_FTRACE |
37 | 23 | ||
38 | #define JAL 0x0c000000 /* jump & link: ip --> ra, jump to target */ | 24 | #define JAL 0x0c000000 /* jump & link: ip --> ra, jump to target */ |
39 | #define ADDR_MASK 0x03ffffff /* op_code|addr : 31...26|25 ....0 */ | 25 | #define ADDR_MASK 0x03ffffff /* op_code|addr : 31...26|25 ....0 */ |
40 | 26 | ||
41 | #define INSN_B_1F_4 0x10000004 /* b 1f; offset = 4 */ | ||
42 | #define INSN_B_1F_5 0x10000005 /* b 1f; offset = 5 */ | ||
43 | #define INSN_NOP 0x00000000 /* nop */ | 27 | #define INSN_NOP 0x00000000 /* nop */ |
44 | #define INSN_JAL(addr) \ | 28 | #define INSN_JAL(addr) \ |
45 | ((unsigned int)(JAL | (((addr) >> 2) & ADDR_MASK))) | 29 | ((unsigned int)(JAL | (((addr) >> 2) & ADDR_MASK))) |
@@ -69,6 +53,20 @@ static inline void ftrace_dyn_arch_init_insns(void) | |||
69 | #endif | 53 | #endif |
70 | } | 54 | } |
71 | 55 | ||
56 | /* | ||
57 | * Check if the address is in kernel space | ||
58 | * | ||
59 | * Clone core_kernel_text() from kernel/extable.c, but doesn't call | ||
60 | * init_kernel_text() for Ftrace doesn't trace functions in init sections. | ||
61 | */ | ||
62 | static inline int in_kernel_space(unsigned long ip) | ||
63 | { | ||
64 | if (ip >= (unsigned long)_stext && | ||
65 | ip <= (unsigned long)_etext) | ||
66 | return 1; | ||
67 | return 0; | ||
68 | } | ||
69 | |||
72 | static int ftrace_modify_code(unsigned long ip, unsigned int new_code) | 70 | static int ftrace_modify_code(unsigned long ip, unsigned int new_code) |
73 | { | 71 | { |
74 | int faulted; | 72 | int faulted; |
@@ -84,6 +82,42 @@ static int ftrace_modify_code(unsigned long ip, unsigned int new_code) | |||
84 | return 0; | 82 | return 0; |
85 | } | 83 | } |
86 | 84 | ||
85 | /* | ||
86 | * The details about the calling site of mcount on MIPS | ||
87 | * | ||
88 | * 1. For kernel: | ||
89 | * | ||
90 | * move at, ra | ||
91 | * jal _mcount --> nop | ||
92 | * | ||
93 | * 2. For modules: | ||
94 | * | ||
95 | * 2.1 For KBUILD_MCOUNT_RA_ADDRESS and CONFIG_32BIT | ||
96 | * | ||
97 | * lui v1, hi_16bit_of_mcount --> b 1f (0x10000005) | ||
98 | * addiu v1, v1, low_16bit_of_mcount | ||
99 | * move at, ra | ||
100 | * move $12, ra_address | ||
101 | * jalr v1 | ||
102 | * sub sp, sp, 8 | ||
103 | * 1: offset = 5 instructions | ||
104 | * 2.2 For the Other situations | ||
105 | * | ||
106 | * lui v1, hi_16bit_of_mcount --> b 1f (0x10000004) | ||
107 | * addiu v1, v1, low_16bit_of_mcount | ||
108 | * move at, ra | ||
109 | * jalr v1 | ||
110 | * nop | move $12, ra_address | sub sp, sp, 8 | ||
111 | * 1: offset = 4 instructions | ||
112 | */ | ||
113 | |||
114 | #if defined(KBUILD_MCOUNT_RA_ADDRESS) && defined(CONFIG_32BIT) | ||
115 | #define MCOUNT_OFFSET_INSNS 5 | ||
116 | #else | ||
117 | #define MCOUNT_OFFSET_INSNS 4 | ||
118 | #endif | ||
119 | #define INSN_B_1F (0x10000000 | MCOUNT_OFFSET_INSNS) | ||
120 | |||
87 | int ftrace_make_nop(struct module *mod, | 121 | int ftrace_make_nop(struct module *mod, |
88 | struct dyn_ftrace *rec, unsigned long addr) | 122 | struct dyn_ftrace *rec, unsigned long addr) |
89 | { | 123 | { |
@@ -91,39 +125,11 @@ int ftrace_make_nop(struct module *mod, | |||
91 | unsigned long ip = rec->ip; | 125 | unsigned long ip = rec->ip; |
92 | 126 | ||
93 | /* | 127 | /* |
94 | * We have compiled module with -mlong-calls, but compiled the kernel | 128 | * If ip is in kernel space, no long call, otherwise, long call is |
95 | * without it, we need to cope with them respectively. | 129 | * needed. |
96 | */ | 130 | */ |
97 | if (in_module(ip)) { | 131 | new = in_kernel_space(ip) ? INSN_NOP : INSN_B_1F; |
98 | #if defined(KBUILD_MCOUNT_RA_ADDRESS) && defined(CONFIG_32BIT) | 132 | |
99 | /* | ||
100 | * lui v1, hi_16bit_of_mcount --> b 1f (0x10000005) | ||
101 | * addiu v1, v1, low_16bit_of_mcount | ||
102 | * move at, ra | ||
103 | * move $12, ra_address | ||
104 | * jalr v1 | ||
105 | * sub sp, sp, 8 | ||
106 | * 1: offset = 5 instructions | ||
107 | */ | ||
108 | new = INSN_B_1F_5; | ||
109 | #else | ||
110 | /* | ||
111 | * lui v1, hi_16bit_of_mcount --> b 1f (0x10000004) | ||
112 | * addiu v1, v1, low_16bit_of_mcount | ||
113 | * move at, ra | ||
114 | * jalr v1 | ||
115 | * nop | move $12, ra_address | sub sp, sp, 8 | ||
116 | * 1: offset = 4 instructions | ||
117 | */ | ||
118 | new = INSN_B_1F_4; | ||
119 | #endif | ||
120 | } else { | ||
121 | /* | ||
122 | * move at, ra | ||
123 | * jal _mcount --> nop | ||
124 | */ | ||
125 | new = INSN_NOP; | ||
126 | } | ||
127 | return ftrace_modify_code(ip, new); | 133 | return ftrace_modify_code(ip, new); |
128 | } | 134 | } |
129 | 135 | ||
@@ -132,8 +138,8 @@ int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) | |||
132 | unsigned int new; | 138 | unsigned int new; |
133 | unsigned long ip = rec->ip; | 139 | unsigned long ip = rec->ip; |
134 | 140 | ||
135 | /* ip, module: 0xc0000000, kernel: 0x80000000 */ | 141 | new = in_kernel_space(ip) ? insn_jal_ftrace_caller : |
136 | new = in_module(ip) ? insn_lui_v1_hi16_mcount : insn_jal_ftrace_caller; | 142 | insn_lui_v1_hi16_mcount; |
137 | 143 | ||
138 | return ftrace_modify_code(ip, new); | 144 | return ftrace_modify_code(ip, new); |
139 | } | 145 | } |
@@ -190,29 +196,25 @@ int ftrace_disable_ftrace_graph_caller(void) | |||
190 | #define S_R_SP (0xafb0 << 16) /* s{d,w} R, offset(sp) */ | 196 | #define S_R_SP (0xafb0 << 16) /* s{d,w} R, offset(sp) */ |
191 | #define OFFSET_MASK 0xffff /* stack offset range: 0 ~ PT_SIZE */ | 197 | #define OFFSET_MASK 0xffff /* stack offset range: 0 ~ PT_SIZE */ |
192 | 198 | ||
193 | unsigned long ftrace_get_parent_addr(unsigned long self_addr, | 199 | unsigned long ftrace_get_parent_ra_addr(unsigned long self_ra, unsigned long |
194 | unsigned long parent, | 200 | old_parent_ra, unsigned long parent_ra_addr, unsigned long fp) |
195 | unsigned long parent_addr, | ||
196 | unsigned long fp) | ||
197 | { | 201 | { |
198 | unsigned long sp, ip, ra; | 202 | unsigned long sp, ip, tmp; |
199 | unsigned int code; | 203 | unsigned int code; |
200 | int faulted; | 204 | int faulted; |
201 | 205 | ||
202 | /* | 206 | /* |
203 | * For module, move the ip from calling site of mcount to the | 207 | * For module, move the ip from the return address after the |
204 | * instruction "lui v1, hi_16bit_of_mcount"(offset is 20), but for | 208 | * instruction "lui v1, hi_16bit_of_mcount"(offset is 24), but for |
205 | * kernel, move to the instruction "move ra, at"(offset is 12) | 209 | * kernel, move after the instruction "move ra, at"(offset is 16) |
206 | */ | 210 | */ |
207 | ip = self_addr - (in_module(self_addr) ? 20 : 12); | 211 | ip = self_ra - (in_kernel_space(self_ra) ? 16 : 24); |
208 | 212 | ||
209 | /* | 213 | /* |
210 | * search the text until finding the non-store instruction or "s{d,w} | 214 | * search the text until finding the non-store instruction or "s{d,w} |
211 | * ra, offset(sp)" instruction | 215 | * ra, offset(sp)" instruction |
212 | */ | 216 | */ |
213 | do { | 217 | do { |
214 | ip -= 4; | ||
215 | |||
216 | /* get the code at "ip": code = *(unsigned int *)ip; */ | 218 | /* get the code at "ip": code = *(unsigned int *)ip; */ |
217 | safe_load_code(code, ip, faulted); | 219 | safe_load_code(code, ip, faulted); |
218 | 220 | ||
@@ -224,18 +226,20 @@ unsigned long ftrace_get_parent_addr(unsigned long self_addr, | |||
224 | * store the ra on the stack | 226 | * store the ra on the stack |
225 | */ | 227 | */ |
226 | if ((code & S_R_SP) != S_R_SP) | 228 | if ((code & S_R_SP) != S_R_SP) |
227 | return parent_addr; | 229 | return parent_ra_addr; |
228 | 230 | ||
229 | } while (((code & S_RA_SP) != S_RA_SP)); | 231 | /* Move to the next instruction */ |
232 | ip -= 4; | ||
233 | } while ((code & S_RA_SP) != S_RA_SP); | ||
230 | 234 | ||
231 | sp = fp + (code & OFFSET_MASK); | 235 | sp = fp + (code & OFFSET_MASK); |
232 | 236 | ||
233 | /* ra = *(unsigned long *)sp; */ | 237 | /* tmp = *(unsigned long *)sp; */ |
234 | safe_load_stack(ra, sp, faulted); | 238 | safe_load_stack(tmp, sp, faulted); |
235 | if (unlikely(faulted)) | 239 | if (unlikely(faulted)) |
236 | return 0; | 240 | return 0; |
237 | 241 | ||
238 | if (ra == parent) | 242 | if (tmp == old_parent_ra) |
239 | return sp; | 243 | return sp; |
240 | return 0; | 244 | return 0; |
241 | } | 245 | } |
@@ -246,21 +250,21 @@ unsigned long ftrace_get_parent_addr(unsigned long self_addr, | |||
246 | * Hook the return address and push it in the stack of return addrs | 250 | * Hook the return address and push it in the stack of return addrs |
247 | * in current thread info. | 251 | * in current thread info. |
248 | */ | 252 | */ |
249 | void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr, | 253 | void prepare_ftrace_return(unsigned long *parent_ra_addr, unsigned long self_ra, |
250 | unsigned long fp) | 254 | unsigned long fp) |
251 | { | 255 | { |
252 | unsigned long old; | 256 | unsigned long old_parent_ra; |
253 | struct ftrace_graph_ent trace; | 257 | struct ftrace_graph_ent trace; |
254 | unsigned long return_hooker = (unsigned long) | 258 | unsigned long return_hooker = (unsigned long) |
255 | &return_to_handler; | 259 | &return_to_handler; |
256 | int faulted; | 260 | int faulted, insns; |
257 | 261 | ||
258 | if (unlikely(atomic_read(¤t->tracing_graph_pause))) | 262 | if (unlikely(atomic_read(¤t->tracing_graph_pause))) |
259 | return; | 263 | return; |
260 | 264 | ||
261 | /* | 265 | /* |
262 | * "parent" is the stack address saved the return address of the caller | 266 | * "parent_ra_addr" is the stack address saved the return address of |
263 | * of _mcount. | 267 | * the caller of _mcount. |
264 | * | 268 | * |
265 | * if the gcc < 4.5, a leaf function does not save the return address | 269 | * if the gcc < 4.5, a leaf function does not save the return address |
266 | * in the stack address, so, we "emulate" one in _mcount's stack space, | 270 | * in the stack address, so, we "emulate" one in _mcount's stack space, |
@@ -275,37 +279,44 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr, | |||
275 | * do it in ftrace_graph_caller of mcount.S. | 279 | * do it in ftrace_graph_caller of mcount.S. |
276 | */ | 280 | */ |
277 | 281 | ||
278 | /* old = *parent; */ | 282 | /* old_parent_ra = *parent_ra_addr; */ |
279 | safe_load_stack(old, parent, faulted); | 283 | safe_load_stack(old_parent_ra, parent_ra_addr, faulted); |
280 | if (unlikely(faulted)) | 284 | if (unlikely(faulted)) |
281 | goto out; | 285 | goto out; |
282 | #ifndef KBUILD_MCOUNT_RA_ADDRESS | 286 | #ifndef KBUILD_MCOUNT_RA_ADDRESS |
283 | parent = (unsigned long *)ftrace_get_parent_addr(self_addr, old, | 287 | parent_ra_addr = (unsigned long *)ftrace_get_parent_ra_addr(self_ra, |
284 | (unsigned long)parent, fp); | 288 | old_parent_ra, (unsigned long)parent_ra_addr, fp); |
285 | /* | 289 | /* |
286 | * If fails when getting the stack address of the non-leaf function's | 290 | * If fails when getting the stack address of the non-leaf function's |
287 | * ra, stop function graph tracer and return | 291 | * ra, stop function graph tracer and return |
288 | */ | 292 | */ |
289 | if (parent == 0) | 293 | if (parent_ra_addr == 0) |
290 | goto out; | 294 | goto out; |
291 | #endif | 295 | #endif |
292 | /* *parent = return_hooker; */ | 296 | /* *parent_ra_addr = return_hooker; */ |
293 | safe_store_stack(return_hooker, parent, faulted); | 297 | safe_store_stack(return_hooker, parent_ra_addr, faulted); |
294 | if (unlikely(faulted)) | 298 | if (unlikely(faulted)) |
295 | goto out; | 299 | goto out; |
296 | 300 | ||
297 | if (ftrace_push_return_trace(old, self_addr, &trace.depth, fp) == | 301 | if (ftrace_push_return_trace(old_parent_ra, self_ra, &trace.depth, fp) |
298 | -EBUSY) { | 302 | == -EBUSY) { |
299 | *parent = old; | 303 | *parent_ra_addr = old_parent_ra; |
300 | return; | 304 | return; |
301 | } | 305 | } |
302 | 306 | ||
303 | trace.func = self_addr; | 307 | /* |
308 | * Get the recorded ip of the current mcount calling site in the | ||
309 | * __mcount_loc section, which will be used to filter the function | ||
310 | * entries configured through the tracing/set_graph_function interface. | ||
311 | */ | ||
312 | |||
313 | insns = in_kernel_space(self_ra) ? 2 : MCOUNT_OFFSET_INSNS + 1; | ||
314 | trace.func = self_ra - (MCOUNT_INSN_SIZE * insns); | ||
304 | 315 | ||
305 | /* Only trace if the calling function expects to */ | 316 | /* Only trace if the calling function expects to */ |
306 | if (!ftrace_graph_entry(&trace)) { | 317 | if (!ftrace_graph_entry(&trace)) { |
307 | current->curr_ret_stack--; | 318 | current->curr_ret_stack--; |
308 | *parent = old; | 319 | *parent_ra_addr = old_parent_ra; |
309 | } | 320 | } |
310 | return; | 321 | return; |
311 | out: | 322 | out: |
diff --git a/arch/mips/kernel/perf_event.c b/arch/mips/kernel/perf_event.c index 2b7f3f703b83..a8244854d3dc 100644 --- a/arch/mips/kernel/perf_event.c +++ b/arch/mips/kernel/perf_event.c | |||
@@ -161,41 +161,6 @@ mipspmu_event_set_period(struct perf_event *event, | |||
161 | return ret; | 161 | return ret; |
162 | } | 162 | } |
163 | 163 | ||
164 | static int mipspmu_enable(struct perf_event *event) | ||
165 | { | ||
166 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); | ||
167 | struct hw_perf_event *hwc = &event->hw; | ||
168 | int idx; | ||
169 | int err = 0; | ||
170 | |||
171 | /* To look for a free counter for this event. */ | ||
172 | idx = mipspmu->alloc_counter(cpuc, hwc); | ||
173 | if (idx < 0) { | ||
174 | err = idx; | ||
175 | goto out; | ||
176 | } | ||
177 | |||
178 | /* | ||
179 | * If there is an event in the counter we are going to use then | ||
180 | * make sure it is disabled. | ||
181 | */ | ||
182 | event->hw.idx = idx; | ||
183 | mipspmu->disable_event(idx); | ||
184 | cpuc->events[idx] = event; | ||
185 | |||
186 | /* Set the period for the event. */ | ||
187 | mipspmu_event_set_period(event, hwc, idx); | ||
188 | |||
189 | /* Enable the event. */ | ||
190 | mipspmu->enable_event(hwc, idx); | ||
191 | |||
192 | /* Propagate our changes to the userspace mapping. */ | ||
193 | perf_event_update_userpage(event); | ||
194 | |||
195 | out: | ||
196 | return err; | ||
197 | } | ||
198 | |||
199 | static void mipspmu_event_update(struct perf_event *event, | 164 | static void mipspmu_event_update(struct perf_event *event, |
200 | struct hw_perf_event *hwc, | 165 | struct hw_perf_event *hwc, |
201 | int idx) | 166 | int idx) |
@@ -204,7 +169,7 @@ static void mipspmu_event_update(struct perf_event *event, | |||
204 | unsigned long flags; | 169 | unsigned long flags; |
205 | int shift = 64 - TOTAL_BITS; | 170 | int shift = 64 - TOTAL_BITS; |
206 | s64 prev_raw_count, new_raw_count; | 171 | s64 prev_raw_count, new_raw_count; |
207 | s64 delta; | 172 | u64 delta; |
208 | 173 | ||
209 | again: | 174 | again: |
210 | prev_raw_count = local64_read(&hwc->prev_count); | 175 | prev_raw_count = local64_read(&hwc->prev_count); |
@@ -231,32 +196,90 @@ again: | |||
231 | return; | 196 | return; |
232 | } | 197 | } |
233 | 198 | ||
234 | static void mipspmu_disable(struct perf_event *event) | 199 | static void mipspmu_start(struct perf_event *event, int flags) |
200 | { | ||
201 | struct hw_perf_event *hwc = &event->hw; | ||
202 | |||
203 | if (!mipspmu) | ||
204 | return; | ||
205 | |||
206 | if (flags & PERF_EF_RELOAD) | ||
207 | WARN_ON_ONCE(!(hwc->state & PERF_HES_UPTODATE)); | ||
208 | |||
209 | hwc->state = 0; | ||
210 | |||
211 | /* Set the period for the event. */ | ||
212 | mipspmu_event_set_period(event, hwc, hwc->idx); | ||
213 | |||
214 | /* Enable the event. */ | ||
215 | mipspmu->enable_event(hwc, hwc->idx); | ||
216 | } | ||
217 | |||
218 | static void mipspmu_stop(struct perf_event *event, int flags) | ||
219 | { | ||
220 | struct hw_perf_event *hwc = &event->hw; | ||
221 | |||
222 | if (!mipspmu) | ||
223 | return; | ||
224 | |||
225 | if (!(hwc->state & PERF_HES_STOPPED)) { | ||
226 | /* We are working on a local event. */ | ||
227 | mipspmu->disable_event(hwc->idx); | ||
228 | barrier(); | ||
229 | mipspmu_event_update(event, hwc, hwc->idx); | ||
230 | hwc->state |= PERF_HES_STOPPED | PERF_HES_UPTODATE; | ||
231 | } | ||
232 | } | ||
233 | |||
234 | static int mipspmu_add(struct perf_event *event, int flags) | ||
235 | { | 235 | { |
236 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); | 236 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); |
237 | struct hw_perf_event *hwc = &event->hw; | 237 | struct hw_perf_event *hwc = &event->hw; |
238 | int idx = hwc->idx; | 238 | int idx; |
239 | int err = 0; | ||
239 | 240 | ||
241 | perf_pmu_disable(event->pmu); | ||
240 | 242 | ||
241 | WARN_ON(idx < 0 || idx >= mipspmu->num_counters); | 243 | /* To look for a free counter for this event. */ |
244 | idx = mipspmu->alloc_counter(cpuc, hwc); | ||
245 | if (idx < 0) { | ||
246 | err = idx; | ||
247 | goto out; | ||
248 | } | ||
242 | 249 | ||
243 | /* We are working on a local event. */ | 250 | /* |
251 | * If there is an event in the counter we are going to use then | ||
252 | * make sure it is disabled. | ||
253 | */ | ||
254 | event->hw.idx = idx; | ||
244 | mipspmu->disable_event(idx); | 255 | mipspmu->disable_event(idx); |
256 | cpuc->events[idx] = event; | ||
245 | 257 | ||
246 | barrier(); | 258 | hwc->state = PERF_HES_STOPPED | PERF_HES_UPTODATE; |
247 | 259 | if (flags & PERF_EF_START) | |
248 | mipspmu_event_update(event, hwc, idx); | 260 | mipspmu_start(event, PERF_EF_RELOAD); |
249 | cpuc->events[idx] = NULL; | ||
250 | clear_bit(idx, cpuc->used_mask); | ||
251 | 261 | ||
262 | /* Propagate our changes to the userspace mapping. */ | ||
252 | perf_event_update_userpage(event); | 263 | perf_event_update_userpage(event); |
264 | |||
265 | out: | ||
266 | perf_pmu_enable(event->pmu); | ||
267 | return err; | ||
253 | } | 268 | } |
254 | 269 | ||
255 | static void mipspmu_unthrottle(struct perf_event *event) | 270 | static void mipspmu_del(struct perf_event *event, int flags) |
256 | { | 271 | { |
272 | struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); | ||
257 | struct hw_perf_event *hwc = &event->hw; | 273 | struct hw_perf_event *hwc = &event->hw; |
274 | int idx = hwc->idx; | ||
258 | 275 | ||
259 | mipspmu->enable_event(hwc, hwc->idx); | 276 | WARN_ON(idx < 0 || idx >= mipspmu->num_counters); |
277 | |||
278 | mipspmu_stop(event, PERF_EF_UPDATE); | ||
279 | cpuc->events[idx] = NULL; | ||
280 | clear_bit(idx, cpuc->used_mask); | ||
281 | |||
282 | perf_event_update_userpage(event); | ||
260 | } | 283 | } |
261 | 284 | ||
262 | static void mipspmu_read(struct perf_event *event) | 285 | static void mipspmu_read(struct perf_event *event) |
@@ -270,12 +293,17 @@ static void mipspmu_read(struct perf_event *event) | |||
270 | mipspmu_event_update(event, hwc, hwc->idx); | 293 | mipspmu_event_update(event, hwc, hwc->idx); |
271 | } | 294 | } |
272 | 295 | ||
273 | static struct pmu pmu = { | 296 | static void mipspmu_enable(struct pmu *pmu) |
274 | .enable = mipspmu_enable, | 297 | { |
275 | .disable = mipspmu_disable, | 298 | if (mipspmu) |
276 | .unthrottle = mipspmu_unthrottle, | 299 | mipspmu->start(); |
277 | .read = mipspmu_read, | 300 | } |
278 | }; | 301 | |
302 | static void mipspmu_disable(struct pmu *pmu) | ||
303 | { | ||
304 | if (mipspmu) | ||
305 | mipspmu->stop(); | ||
306 | } | ||
279 | 307 | ||
280 | static atomic_t active_events = ATOMIC_INIT(0); | 308 | static atomic_t active_events = ATOMIC_INIT(0); |
281 | static DEFINE_MUTEX(pmu_reserve_mutex); | 309 | static DEFINE_MUTEX(pmu_reserve_mutex); |
@@ -318,6 +346,82 @@ static void mipspmu_free_irq(void) | |||
318 | perf_irq = save_perf_irq; | 346 | perf_irq = save_perf_irq; |
319 | } | 347 | } |
320 | 348 | ||
349 | /* | ||
350 | * mipsxx/rm9000/loongson2 have different performance counters, they have | ||
351 | * specific low-level init routines. | ||
352 | */ | ||
353 | static void reset_counters(void *arg); | ||
354 | static int __hw_perf_event_init(struct perf_event *event); | ||
355 | |||
356 | static void hw_perf_event_destroy(struct perf_event *event) | ||
357 | { | ||
358 | if (atomic_dec_and_mutex_lock(&active_events, | ||
359 | &pmu_reserve_mutex)) { | ||
360 | /* | ||
361 | * We must not call the destroy function with interrupts | ||
362 | * disabled. | ||
363 | */ | ||
364 | on_each_cpu(reset_counters, | ||
365 | (void *)(long)mipspmu->num_counters, 1); | ||
366 | mipspmu_free_irq(); | ||
367 | mutex_unlock(&pmu_reserve_mutex); | ||
368 | } | ||
369 | } | ||
370 | |||
371 | static int mipspmu_event_init(struct perf_event *event) | ||
372 | { | ||
373 | int err = 0; | ||
374 | |||
375 | switch (event->attr.type) { | ||
376 | case PERF_TYPE_RAW: | ||
377 | case PERF_TYPE_HARDWARE: | ||
378 | case PERF_TYPE_HW_CACHE: | ||
379 | break; | ||
380 | |||
381 | default: | ||
382 | return -ENOENT; | ||
383 | } | ||
384 | |||
385 | if (!mipspmu || event->cpu >= nr_cpumask_bits || | ||
386 | (event->cpu >= 0 && !cpu_online(event->cpu))) | ||
387 | return -ENODEV; | ||
388 | |||
389 | if (!atomic_inc_not_zero(&active_events)) { | ||
390 | if (atomic_read(&active_events) > MIPS_MAX_HWEVENTS) { | ||
391 | atomic_dec(&active_events); | ||
392 | return -ENOSPC; | ||
393 | } | ||
394 | |||
395 | mutex_lock(&pmu_reserve_mutex); | ||
396 | if (atomic_read(&active_events) == 0) | ||
397 | err = mipspmu_get_irq(); | ||
398 | |||
399 | if (!err) | ||
400 | atomic_inc(&active_events); | ||
401 | mutex_unlock(&pmu_reserve_mutex); | ||
402 | } | ||
403 | |||
404 | if (err) | ||
405 | return err; | ||
406 | |||
407 | err = __hw_perf_event_init(event); | ||
408 | if (err) | ||
409 | hw_perf_event_destroy(event); | ||
410 | |||
411 | return err; | ||
412 | } | ||
413 | |||
414 | static struct pmu pmu = { | ||
415 | .pmu_enable = mipspmu_enable, | ||
416 | .pmu_disable = mipspmu_disable, | ||
417 | .event_init = mipspmu_event_init, | ||
418 | .add = mipspmu_add, | ||
419 | .del = mipspmu_del, | ||
420 | .start = mipspmu_start, | ||
421 | .stop = mipspmu_stop, | ||
422 | .read = mipspmu_read, | ||
423 | }; | ||
424 | |||
321 | static inline unsigned int | 425 | static inline unsigned int |
322 | mipspmu_perf_event_encode(const struct mips_perf_event *pev) | 426 | mipspmu_perf_event_encode(const struct mips_perf_event *pev) |
323 | { | 427 | { |
@@ -382,8 +486,9 @@ static int validate_event(struct cpu_hw_events *cpuc, | |||
382 | { | 486 | { |
383 | struct hw_perf_event fake_hwc = event->hw; | 487 | struct hw_perf_event fake_hwc = event->hw; |
384 | 488 | ||
385 | if (event->pmu && event->pmu != &pmu) | 489 | /* Allow mixed event group. So return 1 to pass validation. */ |
386 | return 0; | 490 | if (event->pmu != &pmu || event->state <= PERF_EVENT_STATE_OFF) |
491 | return 1; | ||
387 | 492 | ||
388 | return mipspmu->alloc_counter(cpuc, &fake_hwc) >= 0; | 493 | return mipspmu->alloc_counter(cpuc, &fake_hwc) >= 0; |
389 | } | 494 | } |
@@ -409,73 +514,6 @@ static int validate_group(struct perf_event *event) | |||
409 | return 0; | 514 | return 0; |
410 | } | 515 | } |
411 | 516 | ||
412 | /* | ||
413 | * mipsxx/rm9000/loongson2 have different performance counters, they have | ||
414 | * specific low-level init routines. | ||
415 | */ | ||
416 | static void reset_counters(void *arg); | ||
417 | static int __hw_perf_event_init(struct perf_event *event); | ||
418 | |||
419 | static void hw_perf_event_destroy(struct perf_event *event) | ||
420 | { | ||
421 | if (atomic_dec_and_mutex_lock(&active_events, | ||
422 | &pmu_reserve_mutex)) { | ||
423 | /* | ||
424 | * We must not call the destroy function with interrupts | ||
425 | * disabled. | ||
426 | */ | ||
427 | on_each_cpu(reset_counters, | ||
428 | (void *)(long)mipspmu->num_counters, 1); | ||
429 | mipspmu_free_irq(); | ||
430 | mutex_unlock(&pmu_reserve_mutex); | ||
431 | } | ||
432 | } | ||
433 | |||
434 | const struct pmu *hw_perf_event_init(struct perf_event *event) | ||
435 | { | ||
436 | int err = 0; | ||
437 | |||
438 | if (!mipspmu || event->cpu >= nr_cpumask_bits || | ||
439 | (event->cpu >= 0 && !cpu_online(event->cpu))) | ||
440 | return ERR_PTR(-ENODEV); | ||
441 | |||
442 | if (!atomic_inc_not_zero(&active_events)) { | ||
443 | if (atomic_read(&active_events) > MIPS_MAX_HWEVENTS) { | ||
444 | atomic_dec(&active_events); | ||
445 | return ERR_PTR(-ENOSPC); | ||
446 | } | ||
447 | |||
448 | mutex_lock(&pmu_reserve_mutex); | ||
449 | if (atomic_read(&active_events) == 0) | ||
450 | err = mipspmu_get_irq(); | ||
451 | |||
452 | if (!err) | ||
453 | atomic_inc(&active_events); | ||
454 | mutex_unlock(&pmu_reserve_mutex); | ||
455 | } | ||
456 | |||
457 | if (err) | ||
458 | return ERR_PTR(err); | ||
459 | |||
460 | err = __hw_perf_event_init(event); | ||
461 | if (err) | ||
462 | hw_perf_event_destroy(event); | ||
463 | |||
464 | return err ? ERR_PTR(err) : &pmu; | ||
465 | } | ||
466 | |||
467 | void hw_perf_enable(void) | ||
468 | { | ||
469 | if (mipspmu) | ||
470 | mipspmu->start(); | ||
471 | } | ||
472 | |||
473 | void hw_perf_disable(void) | ||
474 | { | ||
475 | if (mipspmu) | ||
476 | mipspmu->stop(); | ||
477 | } | ||
478 | |||
479 | /* This is needed by specific irq handlers in perf_event_*.c */ | 517 | /* This is needed by specific irq handlers in perf_event_*.c */ |
480 | static void | 518 | static void |
481 | handle_associated_event(struct cpu_hw_events *cpuc, | 519 | handle_associated_event(struct cpu_hw_events *cpuc, |
@@ -496,21 +534,13 @@ handle_associated_event(struct cpu_hw_events *cpuc, | |||
496 | #include "perf_event_mipsxx.c" | 534 | #include "perf_event_mipsxx.c" |
497 | 535 | ||
498 | /* Callchain handling code. */ | 536 | /* Callchain handling code. */ |
499 | static inline void | ||
500 | callchain_store(struct perf_callchain_entry *entry, | ||
501 | u64 ip) | ||
502 | { | ||
503 | if (entry->nr < PERF_MAX_STACK_DEPTH) | ||
504 | entry->ip[entry->nr++] = ip; | ||
505 | } | ||
506 | 537 | ||
507 | /* | 538 | /* |
508 | * Leave userspace callchain empty for now. When we find a way to trace | 539 | * Leave userspace callchain empty for now. When we find a way to trace |
509 | * the user stack callchains, we add here. | 540 | * the user stack callchains, we add here. |
510 | */ | 541 | */ |
511 | static void | 542 | void perf_callchain_user(struct perf_callchain_entry *entry, |
512 | perf_callchain_user(struct pt_regs *regs, | 543 | struct pt_regs *regs) |
513 | struct perf_callchain_entry *entry) | ||
514 | { | 544 | { |
515 | } | 545 | } |
516 | 546 | ||
@@ -523,23 +553,21 @@ static void save_raw_perf_callchain(struct perf_callchain_entry *entry, | |||
523 | while (!kstack_end(sp)) { | 553 | while (!kstack_end(sp)) { |
524 | addr = *sp++; | 554 | addr = *sp++; |
525 | if (__kernel_text_address(addr)) { | 555 | if (__kernel_text_address(addr)) { |
526 | callchain_store(entry, addr); | 556 | perf_callchain_store(entry, addr); |
527 | if (entry->nr >= PERF_MAX_STACK_DEPTH) | 557 | if (entry->nr >= PERF_MAX_STACK_DEPTH) |
528 | break; | 558 | break; |
529 | } | 559 | } |
530 | } | 560 | } |
531 | } | 561 | } |
532 | 562 | ||
533 | static void | 563 | void perf_callchain_kernel(struct perf_callchain_entry *entry, |
534 | perf_callchain_kernel(struct pt_regs *regs, | 564 | struct pt_regs *regs) |
535 | struct perf_callchain_entry *entry) | ||
536 | { | 565 | { |
537 | unsigned long sp = regs->regs[29]; | 566 | unsigned long sp = regs->regs[29]; |
538 | #ifdef CONFIG_KALLSYMS | 567 | #ifdef CONFIG_KALLSYMS |
539 | unsigned long ra = regs->regs[31]; | 568 | unsigned long ra = regs->regs[31]; |
540 | unsigned long pc = regs->cp0_epc; | 569 | unsigned long pc = regs->cp0_epc; |
541 | 570 | ||
542 | callchain_store(entry, PERF_CONTEXT_KERNEL); | ||
543 | if (raw_show_trace || !__kernel_text_address(pc)) { | 571 | if (raw_show_trace || !__kernel_text_address(pc)) { |
544 | unsigned long stack_page = | 572 | unsigned long stack_page = |
545 | (unsigned long)task_stack_page(current); | 573 | (unsigned long)task_stack_page(current); |
@@ -549,53 +577,12 @@ perf_callchain_kernel(struct pt_regs *regs, | |||
549 | return; | 577 | return; |
550 | } | 578 | } |
551 | do { | 579 | do { |
552 | callchain_store(entry, pc); | 580 | perf_callchain_store(entry, pc); |
553 | if (entry->nr >= PERF_MAX_STACK_DEPTH) | 581 | if (entry->nr >= PERF_MAX_STACK_DEPTH) |
554 | break; | 582 | break; |
555 | pc = unwind_stack(current, &sp, pc, &ra); | 583 | pc = unwind_stack(current, &sp, pc, &ra); |
556 | } while (pc); | 584 | } while (pc); |
557 | #else | 585 | #else |
558 | callchain_store(entry, PERF_CONTEXT_KERNEL); | ||
559 | save_raw_perf_callchain(entry, sp); | 586 | save_raw_perf_callchain(entry, sp); |
560 | #endif | 587 | #endif |
561 | } | 588 | } |
562 | |||
563 | static void | ||
564 | perf_do_callchain(struct pt_regs *regs, | ||
565 | struct perf_callchain_entry *entry) | ||
566 | { | ||
567 | int is_user; | ||
568 | |||
569 | if (!regs) | ||
570 | return; | ||
571 | |||
572 | is_user = user_mode(regs); | ||
573 | |||
574 | if (!current || !current->pid) | ||
575 | return; | ||
576 | |||
577 | if (is_user && current->state != TASK_RUNNING) | ||
578 | return; | ||
579 | |||
580 | if (!is_user) { | ||
581 | perf_callchain_kernel(regs, entry); | ||
582 | if (current->mm) | ||
583 | regs = task_pt_regs(current); | ||
584 | else | ||
585 | regs = NULL; | ||
586 | } | ||
587 | if (regs) | ||
588 | perf_callchain_user(regs, entry); | ||
589 | } | ||
590 | |||
591 | static DEFINE_PER_CPU(struct perf_callchain_entry, pmc_irq_entry); | ||
592 | |||
593 | struct perf_callchain_entry * | ||
594 | perf_callchain(struct pt_regs *regs) | ||
595 | { | ||
596 | struct perf_callchain_entry *entry = &__get_cpu_var(pmc_irq_entry); | ||
597 | |||
598 | entry->nr = 0; | ||
599 | perf_do_callchain(regs, entry); | ||
600 | return entry; | ||
601 | } | ||
diff --git a/arch/mips/kernel/perf_event_mipsxx.c b/arch/mips/kernel/perf_event_mipsxx.c index 183e0d226669..d9a7db78ed62 100644 --- a/arch/mips/kernel/perf_event_mipsxx.c +++ b/arch/mips/kernel/perf_event_mipsxx.c | |||
@@ -696,7 +696,7 @@ static int mipsxx_pmu_handle_shared_irq(void) | |||
696 | * interrupt, not NMI. | 696 | * interrupt, not NMI. |
697 | */ | 697 | */ |
698 | if (handled == IRQ_HANDLED) | 698 | if (handled == IRQ_HANDLED) |
699 | perf_event_do_pending(); | 699 | irq_work_run(); |
700 | 700 | ||
701 | #ifdef CONFIG_MIPS_MT_SMP | 701 | #ifdef CONFIG_MIPS_MT_SMP |
702 | read_unlock(&pmuint_rwlock); | 702 | read_unlock(&pmuint_rwlock); |
@@ -1045,6 +1045,8 @@ init_hw_perf_events(void) | |||
1045 | "CPU, irq %d%s\n", mipspmu->name, counters, irq, | 1045 | "CPU, irq %d%s\n", mipspmu->name, counters, irq, |
1046 | irq < 0 ? " (share with timer interrupt)" : ""); | 1046 | irq < 0 ? " (share with timer interrupt)" : ""); |
1047 | 1047 | ||
1048 | perf_pmu_register(&pmu, "cpu", PERF_TYPE_RAW); | ||
1049 | |||
1048 | return 0; | 1050 | return 0; |
1049 | } | 1051 | } |
1050 | early_initcall(init_hw_perf_events); | 1052 | early_initcall(init_hw_perf_events); |
diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c index 5922342bca39..dbbe0ce48d89 100644 --- a/arch/mips/kernel/signal.c +++ b/arch/mips/kernel/signal.c | |||
@@ -84,7 +84,7 @@ static int protected_save_fp_context(struct sigcontext __user *sc) | |||
84 | 84 | ||
85 | static int protected_restore_fp_context(struct sigcontext __user *sc) | 85 | static int protected_restore_fp_context(struct sigcontext __user *sc) |
86 | { | 86 | { |
87 | int err, tmp; | 87 | int err, tmp __maybe_unused; |
88 | while (1) { | 88 | while (1) { |
89 | lock_fpu_owner(); | 89 | lock_fpu_owner(); |
90 | own_fpu_inatomic(0); | 90 | own_fpu_inatomic(0); |
diff --git a/arch/mips/kernel/signal32.c b/arch/mips/kernel/signal32.c index a0ed0e052b2e..aae986613795 100644 --- a/arch/mips/kernel/signal32.c +++ b/arch/mips/kernel/signal32.c | |||
@@ -115,7 +115,7 @@ static int protected_save_fp_context32(struct sigcontext32 __user *sc) | |||
115 | 115 | ||
116 | static int protected_restore_fp_context32(struct sigcontext32 __user *sc) | 116 | static int protected_restore_fp_context32(struct sigcontext32 __user *sc) |
117 | { | 117 | { |
118 | int err, tmp; | 118 | int err, tmp __maybe_unused; |
119 | while (1) { | 119 | while (1) { |
120 | lock_fpu_owner(); | 120 | lock_fpu_owner(); |
121 | own_fpu_inatomic(0); | 121 | own_fpu_inatomic(0); |
diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c index 383aeb95cb49..32a256101082 100644 --- a/arch/mips/kernel/smp.c +++ b/arch/mips/kernel/smp.c | |||
@@ -193,6 +193,22 @@ void __devinit smp_prepare_boot_cpu(void) | |||
193 | */ | 193 | */ |
194 | static struct task_struct *cpu_idle_thread[NR_CPUS]; | 194 | static struct task_struct *cpu_idle_thread[NR_CPUS]; |
195 | 195 | ||
196 | struct create_idle { | ||
197 | struct work_struct work; | ||
198 | struct task_struct *idle; | ||
199 | struct completion done; | ||
200 | int cpu; | ||
201 | }; | ||
202 | |||
203 | static void __cpuinit do_fork_idle(struct work_struct *work) | ||
204 | { | ||
205 | struct create_idle *c_idle = | ||
206 | container_of(work, struct create_idle, work); | ||
207 | |||
208 | c_idle->idle = fork_idle(c_idle->cpu); | ||
209 | complete(&c_idle->done); | ||
210 | } | ||
211 | |||
196 | int __cpuinit __cpu_up(unsigned int cpu) | 212 | int __cpuinit __cpu_up(unsigned int cpu) |
197 | { | 213 | { |
198 | struct task_struct *idle; | 214 | struct task_struct *idle; |
@@ -203,8 +219,19 @@ int __cpuinit __cpu_up(unsigned int cpu) | |||
203 | * Linux can schedule processes on this slave. | 219 | * Linux can schedule processes on this slave. |
204 | */ | 220 | */ |
205 | if (!cpu_idle_thread[cpu]) { | 221 | if (!cpu_idle_thread[cpu]) { |
206 | idle = fork_idle(cpu); | 222 | /* |
207 | cpu_idle_thread[cpu] = idle; | 223 | * Schedule work item to avoid forking user task |
224 | * Ported from arch/x86/kernel/smpboot.c | ||
225 | */ | ||
226 | struct create_idle c_idle = { | ||
227 | .cpu = cpu, | ||
228 | .done = COMPLETION_INITIALIZER_ONSTACK(c_idle.done), | ||
229 | }; | ||
230 | |||
231 | INIT_WORK_ONSTACK(&c_idle.work, do_fork_idle); | ||
232 | schedule_work(&c_idle.work); | ||
233 | wait_for_completion(&c_idle.done); | ||
234 | idle = cpu_idle_thread[cpu] = c_idle.idle; | ||
208 | 235 | ||
209 | if (IS_ERR(idle)) | 236 | if (IS_ERR(idle)) |
210 | panic(KERN_ERR "Fork failed for CPU %d", cpu); | 237 | panic(KERN_ERR "Fork failed for CPU %d", cpu); |
diff --git a/arch/mips/kernel/syscall.c b/arch/mips/kernel/syscall.c index 1dc6edff45e0..58beabf50b3c 100644 --- a/arch/mips/kernel/syscall.c +++ b/arch/mips/kernel/syscall.c | |||
@@ -383,12 +383,11 @@ save_static_function(sys_sysmips); | |||
383 | static int __used noinline | 383 | static int __used noinline |
384 | _sys_sysmips(nabi_no_regargs struct pt_regs regs) | 384 | _sys_sysmips(nabi_no_regargs struct pt_regs regs) |
385 | { | 385 | { |
386 | long cmd, arg1, arg2, arg3; | 386 | long cmd, arg1, arg2; |
387 | 387 | ||
388 | cmd = regs.regs[4]; | 388 | cmd = regs.regs[4]; |
389 | arg1 = regs.regs[5]; | 389 | arg1 = regs.regs[5]; |
390 | arg2 = regs.regs[6]; | 390 | arg2 = regs.regs[6]; |
391 | arg3 = regs.regs[7]; | ||
392 | 391 | ||
393 | switch (cmd) { | 392 | switch (cmd) { |
394 | case MIPS_ATOMIC_SET: | 393 | case MIPS_ATOMIC_SET: |
@@ -405,7 +404,7 @@ _sys_sysmips(nabi_no_regargs struct pt_regs regs) | |||
405 | if (arg1 & 2) | 404 | if (arg1 & 2) |
406 | set_thread_flag(TIF_LOGADE); | 405 | set_thread_flag(TIF_LOGADE); |
407 | else | 406 | else |
408 | clear_thread_flag(TIF_FIXADE); | 407 | clear_thread_flag(TIF_LOGADE); |
409 | 408 | ||
410 | return 0; | 409 | return 0; |
411 | 410 | ||
diff --git a/arch/mips/kernel/vpe.c b/arch/mips/kernel/vpe.c index 6a1fdfef8fde..ab52b7cf3b6b 100644 --- a/arch/mips/kernel/vpe.c +++ b/arch/mips/kernel/vpe.c | |||
@@ -148,9 +148,9 @@ struct { | |||
148 | spinlock_t tc_list_lock; | 148 | spinlock_t tc_list_lock; |
149 | struct list_head tc_list; /* Thread contexts */ | 149 | struct list_head tc_list; /* Thread contexts */ |
150 | } vpecontrol = { | 150 | } vpecontrol = { |
151 | .vpe_list_lock = SPIN_LOCK_UNLOCKED, | 151 | .vpe_list_lock = __SPIN_LOCK_UNLOCKED(vpe_list_lock), |
152 | .vpe_list = LIST_HEAD_INIT(vpecontrol.vpe_list), | 152 | .vpe_list = LIST_HEAD_INIT(vpecontrol.vpe_list), |
153 | .tc_list_lock = SPIN_LOCK_UNLOCKED, | 153 | .tc_list_lock = __SPIN_LOCK_UNLOCKED(tc_list_lock), |
154 | .tc_list = LIST_HEAD_INIT(vpecontrol.tc_list) | 154 | .tc_list = LIST_HEAD_INIT(vpecontrol.tc_list) |
155 | }; | 155 | }; |
156 | 156 | ||
diff --git a/arch/mips/loongson/Kconfig b/arch/mips/loongson/Kconfig index 6e1b77fec7ea..aca93eed8779 100644 --- a/arch/mips/loongson/Kconfig +++ b/arch/mips/loongson/Kconfig | |||
@@ -1,6 +1,7 @@ | |||
1 | if MACH_LOONGSON | ||
2 | |||
1 | choice | 3 | choice |
2 | prompt "Machine Type" | 4 | prompt "Machine Type" |
3 | depends on MACH_LOONGSON | ||
4 | 5 | ||
5 | config LEMOTE_FULOONG2E | 6 | config LEMOTE_FULOONG2E |
6 | bool "Lemote Fuloong(2e) mini-PC" | 7 | bool "Lemote Fuloong(2e) mini-PC" |
@@ -87,3 +88,5 @@ config LOONGSON_UART_BASE | |||
87 | config LOONGSON_MC146818 | 88 | config LOONGSON_MC146818 |
88 | bool | 89 | bool |
89 | default n | 90 | default n |
91 | |||
92 | endif # MACH_LOONGSON | ||
diff --git a/arch/mips/loongson/common/cmdline.c b/arch/mips/loongson/common/cmdline.c index 1a06defc4f7f..353e1d2e41a5 100644 --- a/arch/mips/loongson/common/cmdline.c +++ b/arch/mips/loongson/common/cmdline.c | |||
@@ -44,10 +44,5 @@ void __init prom_init_cmdline(void) | |||
44 | strcat(arcs_cmdline, " "); | 44 | strcat(arcs_cmdline, " "); |
45 | } | 45 | } |
46 | 46 | ||
47 | if ((strstr(arcs_cmdline, "console=")) == NULL) | ||
48 | strcat(arcs_cmdline, " console=ttyS0,115200"); | ||
49 | if ((strstr(arcs_cmdline, "root=")) == NULL) | ||
50 | strcat(arcs_cmdline, " root=/dev/hda1"); | ||
51 | |||
52 | prom_init_machtype(); | 47 | prom_init_machtype(); |
53 | } | 48 | } |
diff --git a/arch/mips/loongson/common/machtype.c b/arch/mips/loongson/common/machtype.c index 81fbe6b73f91..2efd5d9dee27 100644 --- a/arch/mips/loongson/common/machtype.c +++ b/arch/mips/loongson/common/machtype.c | |||
@@ -41,7 +41,7 @@ void __weak __init mach_prom_init_machtype(void) | |||
41 | 41 | ||
42 | void __init prom_init_machtype(void) | 42 | void __init prom_init_machtype(void) |
43 | { | 43 | { |
44 | char *p, str[MACHTYPE_LEN]; | 44 | char *p, str[MACHTYPE_LEN + 1]; |
45 | int machtype = MACH_LEMOTE_FL2E; | 45 | int machtype = MACH_LEMOTE_FL2E; |
46 | 46 | ||
47 | mips_machtype = LOONGSON_MACHTYPE; | 47 | mips_machtype = LOONGSON_MACHTYPE; |
@@ -53,6 +53,7 @@ void __init prom_init_machtype(void) | |||
53 | } | 53 | } |
54 | p += strlen("machtype="); | 54 | p += strlen("machtype="); |
55 | strncpy(str, p, MACHTYPE_LEN); | 55 | strncpy(str, p, MACHTYPE_LEN); |
56 | str[MACHTYPE_LEN] = '\0'; | ||
56 | p = strstr(str, " "); | 57 | p = strstr(str, " "); |
57 | if (p) | 58 | if (p) |
58 | *p = '\0'; | 59 | *p = '\0'; |
diff --git a/arch/mips/math-emu/ieee754int.h b/arch/mips/math-emu/ieee754int.h index 2701d9500959..2a7d43f4f161 100644 --- a/arch/mips/math-emu/ieee754int.h +++ b/arch/mips/math-emu/ieee754int.h | |||
@@ -70,7 +70,7 @@ | |||
70 | 70 | ||
71 | 71 | ||
72 | #define COMPXSP \ | 72 | #define COMPXSP \ |
73 | unsigned xm; int xe; int xs; int xc | 73 | unsigned xm; int xe; int xs __maybe_unused; int xc |
74 | 74 | ||
75 | #define COMPYSP \ | 75 | #define COMPYSP \ |
76 | unsigned ym; int ye; int ys; int yc | 76 | unsigned ym; int ye; int ys; int yc |
@@ -104,7 +104,7 @@ | |||
104 | 104 | ||
105 | 105 | ||
106 | #define COMPXDP \ | 106 | #define COMPXDP \ |
107 | u64 xm; int xe; int xs; int xc | 107 | u64 xm; int xe; int xs __maybe_unused; int xc |
108 | 108 | ||
109 | #define COMPYDP \ | 109 | #define COMPYDP \ |
110 | u64 ym; int ye; int ys; int yc | 110 | u64 ym; int ye; int ys; int yc |
diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c index 2efcbd24c82f..279599e9a779 100644 --- a/arch/mips/mm/init.c +++ b/arch/mips/mm/init.c | |||
@@ -324,7 +324,7 @@ int page_is_ram(unsigned long pagenr) | |||
324 | void __init paging_init(void) | 324 | void __init paging_init(void) |
325 | { | 325 | { |
326 | unsigned long max_zone_pfns[MAX_NR_ZONES]; | 326 | unsigned long max_zone_pfns[MAX_NR_ZONES]; |
327 | unsigned long lastpfn; | 327 | unsigned long lastpfn __maybe_unused; |
328 | 328 | ||
329 | pagetable_init(); | 329 | pagetable_init(); |
330 | 330 | ||
diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c index 083d3412d0bc..04f9e17db9d0 100644 --- a/arch/mips/mm/tlbex.c +++ b/arch/mips/mm/tlbex.c | |||
@@ -109,6 +109,8 @@ static bool scratchpad_available(void) | |||
109 | static int scratchpad_offset(int i) | 109 | static int scratchpad_offset(int i) |
110 | { | 110 | { |
111 | BUG(); | 111 | BUG(); |
112 | /* Really unreachable, but evidently some GCC want this. */ | ||
113 | return 0; | ||
112 | } | 114 | } |
113 | #endif | 115 | #endif |
114 | /* | 116 | /* |
diff --git a/arch/mips/pci/ops-pmcmsp.c b/arch/mips/pci/ops-pmcmsp.c index b7c03d80c88c..68798f869c0f 100644 --- a/arch/mips/pci/ops-pmcmsp.c +++ b/arch/mips/pci/ops-pmcmsp.c | |||
@@ -308,7 +308,7 @@ static struct resource pci_mem_resource = { | |||
308 | * RETURNS: PCIBIOS_SUCCESSFUL - success | 308 | * RETURNS: PCIBIOS_SUCCESSFUL - success |
309 | * | 309 | * |
310 | ****************************************************************************/ | 310 | ****************************************************************************/ |
311 | static int bpci_interrupt(int irq, void *dev_id) | 311 | static irqreturn_t bpci_interrupt(int irq, void *dev_id) |
312 | { | 312 | { |
313 | struct msp_pci_regs *preg = (void *)PCI_BASE_REG; | 313 | struct msp_pci_regs *preg = (void *)PCI_BASE_REG; |
314 | unsigned int stat = preg->if_status; | 314 | unsigned int stat = preg->if_status; |
@@ -326,7 +326,7 @@ static int bpci_interrupt(int irq, void *dev_id) | |||
326 | /* write to clear all asserted interrupts */ | 326 | /* write to clear all asserted interrupts */ |
327 | preg->if_status = stat; | 327 | preg->if_status = stat; |
328 | 328 | ||
329 | return PCIBIOS_SUCCESSFUL; | 329 | return IRQ_HANDLED; |
330 | } | 330 | } |
331 | 331 | ||
332 | /***************************************************************************** | 332 | /***************************************************************************** |
diff --git a/arch/mips/pmc-sierra/Kconfig b/arch/mips/pmc-sierra/Kconfig index c139988bb85d..8d798497c614 100644 --- a/arch/mips/pmc-sierra/Kconfig +++ b/arch/mips/pmc-sierra/Kconfig | |||
@@ -4,15 +4,11 @@ choice | |||
4 | 4 | ||
5 | config PMC_MSP4200_EVAL | 5 | config PMC_MSP4200_EVAL |
6 | bool "PMC-Sierra MSP4200 Eval Board" | 6 | bool "PMC-Sierra MSP4200 Eval Board" |
7 | select CEVT_R4K | ||
8 | select CSRC_R4K | ||
9 | select IRQ_MSP_SLP | 7 | select IRQ_MSP_SLP |
10 | select HW_HAS_PCI | 8 | select HW_HAS_PCI |
11 | 9 | ||
12 | config PMC_MSP4200_GW | 10 | config PMC_MSP4200_GW |
13 | bool "PMC-Sierra MSP4200 VoIP Gateway" | 11 | bool "PMC-Sierra MSP4200 VoIP Gateway" |
14 | select CEVT_R4K | ||
15 | select CSRC_R4K | ||
16 | select IRQ_MSP_SLP | 12 | select IRQ_MSP_SLP |
17 | select HW_HAS_PCI | 13 | select HW_HAS_PCI |
18 | 14 | ||
diff --git a/arch/mips/pmc-sierra/msp71xx/msp_time.c b/arch/mips/pmc-sierra/msp71xx/msp_time.c index cca64e15f57f..01df84ce31e2 100644 --- a/arch/mips/pmc-sierra/msp71xx/msp_time.c +++ b/arch/mips/pmc-sierra/msp71xx/msp_time.c | |||
@@ -81,7 +81,7 @@ void __init plat_time_init(void) | |||
81 | mips_hpt_frequency = cpu_rate/2; | 81 | mips_hpt_frequency = cpu_rate/2; |
82 | } | 82 | } |
83 | 83 | ||
84 | unsigned int __init get_c0_compare_int(void) | 84 | unsigned int __cpuinit get_c0_compare_int(void) |
85 | { | 85 | { |
86 | return MSP_INT_VPE0_TIMER; | 86 | return MSP_INT_VPE0_TIMER; |
87 | } | 87 | } |
diff --git a/arch/mn10300/include/asm/atomic.h b/arch/mn10300/include/asm/atomic.h index 92d2f9298e38..9d773a639513 100644 --- a/arch/mn10300/include/asm/atomic.h +++ b/arch/mn10300/include/asm/atomic.h | |||
@@ -139,7 +139,7 @@ static inline unsigned long __cmpxchg(volatile unsigned long *m, | |||
139 | * Atomically reads the value of @v. Note that the guaranteed | 139 | * Atomically reads the value of @v. Note that the guaranteed |
140 | * useful range of an atomic_t is only 24 bits. | 140 | * useful range of an atomic_t is only 24 bits. |
141 | */ | 141 | */ |
142 | #define atomic_read(v) ((v)->counter) | 142 | #define atomic_read(v) (ACCESS_ONCE((v)->counter)) |
143 | 143 | ||
144 | /** | 144 | /** |
145 | * atomic_set - set atomic variable | 145 | * atomic_set - set atomic variable |
diff --git a/arch/mn10300/include/asm/uaccess.h b/arch/mn10300/include/asm/uaccess.h index 679dee0bbd08..3d6e60dad9d9 100644 --- a/arch/mn10300/include/asm/uaccess.h +++ b/arch/mn10300/include/asm/uaccess.h | |||
@@ -160,9 +160,10 @@ struct __large_struct { unsigned long buf[100]; }; | |||
160 | 160 | ||
161 | #define __get_user_check(x, ptr, size) \ | 161 | #define __get_user_check(x, ptr, size) \ |
162 | ({ \ | 162 | ({ \ |
163 | const __typeof__(ptr) __guc_ptr = (ptr); \ | ||
163 | int _e; \ | 164 | int _e; \ |
164 | if (likely(__access_ok((unsigned long) (ptr), (size)))) \ | 165 | if (likely(__access_ok((unsigned long) __guc_ptr, (size)))) \ |
165 | _e = __get_user_nocheck((x), (ptr), (size)); \ | 166 | _e = __get_user_nocheck((x), __guc_ptr, (size)); \ |
166 | else { \ | 167 | else { \ |
167 | _e = -EFAULT; \ | 168 | _e = -EFAULT; \ |
168 | (x) = (__typeof__(x))0; \ | 169 | (x) = (__typeof__(x))0; \ |
diff --git a/arch/mn10300/mm/cache-inv-icache.c b/arch/mn10300/mm/cache-inv-icache.c index a8933a60b2d4..a6b63dde603d 100644 --- a/arch/mn10300/mm/cache-inv-icache.c +++ b/arch/mn10300/mm/cache-inv-icache.c | |||
@@ -69,7 +69,7 @@ static void flush_icache_page_range(unsigned long start, unsigned long end) | |||
69 | 69 | ||
70 | /* invalidate the icache coverage on that region */ | 70 | /* invalidate the icache coverage on that region */ |
71 | mn10300_local_icache_inv_range2(addr + off, size); | 71 | mn10300_local_icache_inv_range2(addr + off, size); |
72 | smp_cache_call(SMP_ICACHE_INV_FLUSH_RANGE, start, end); | 72 | smp_cache_call(SMP_ICACHE_INV_RANGE, start, end); |
73 | } | 73 | } |
74 | 74 | ||
75 | /** | 75 | /** |
@@ -101,7 +101,7 @@ void flush_icache_range(unsigned long start, unsigned long end) | |||
101 | * directly */ | 101 | * directly */ |
102 | start_page = (start >= 0x80000000UL) ? start : 0x80000000UL; | 102 | start_page = (start >= 0x80000000UL) ? start : 0x80000000UL; |
103 | mn10300_icache_inv_range(start_page, end); | 103 | mn10300_icache_inv_range(start_page, end); |
104 | smp_cache_call(SMP_ICACHE_INV_FLUSH_RANGE, start, end); | 104 | smp_cache_call(SMP_ICACHE_INV_RANGE, start, end); |
105 | if (start_page == start) | 105 | if (start_page == start) |
106 | goto done; | 106 | goto done; |
107 | end = start_page; | 107 | end = start_page; |
diff --git a/arch/x86/include/asm/ce4100.h b/arch/x86/include/asm/ce4100.h new file mode 100644 index 000000000000..e656ad8c0a2e --- /dev/null +++ b/arch/x86/include/asm/ce4100.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #ifndef _ASM_CE4100_H_ | ||
2 | #define _ASM_CE4100_H_ | ||
3 | |||
4 | int ce4100_pci_init(void); | ||
5 | |||
6 | #endif | ||
diff --git a/arch/x86/include/asm/xen/hypercall.h b/arch/x86/include/asm/xen/hypercall.h index a3c28ae4025b..8508bfe52296 100644 --- a/arch/x86/include/asm/xen/hypercall.h +++ b/arch/x86/include/asm/xen/hypercall.h | |||
@@ -287,7 +287,7 @@ HYPERVISOR_fpu_taskswitch(int set) | |||
287 | static inline int | 287 | static inline int |
288 | HYPERVISOR_sched_op(int cmd, void *arg) | 288 | HYPERVISOR_sched_op(int cmd, void *arg) |
289 | { | 289 | { |
290 | return _hypercall2(int, sched_op_new, cmd, arg); | 290 | return _hypercall2(int, sched_op, cmd, arg); |
291 | } | 291 | } |
292 | 292 | ||
293 | static inline long | 293 | static inline long |
@@ -422,10 +422,17 @@ HYPERVISOR_set_segment_base(int reg, unsigned long value) | |||
422 | #endif | 422 | #endif |
423 | 423 | ||
424 | static inline int | 424 | static inline int |
425 | HYPERVISOR_suspend(unsigned long srec) | 425 | HYPERVISOR_suspend(unsigned long start_info_mfn) |
426 | { | 426 | { |
427 | return _hypercall3(int, sched_op, SCHEDOP_shutdown, | 427 | struct sched_shutdown r = { .reason = SHUTDOWN_suspend }; |
428 | SHUTDOWN_suspend, srec); | 428 | |
429 | /* | ||
430 | * For a PV guest the tools require that the start_info mfn be | ||
431 | * present in rdx/edx when the hypercall is made. Per the | ||
432 | * hypercall calling convention this is the third hypercall | ||
433 | * argument, which is start_info_mfn here. | ||
434 | */ | ||
435 | return _hypercall3(int, sched_op, SCHEDOP_shutdown, &r, start_info_mfn); | ||
429 | } | 436 | } |
430 | 437 | ||
431 | static inline int | 438 | static inline int |
diff --git a/arch/x86/include/asm/xen/page.h b/arch/x86/include/asm/xen/page.h index f25bdf238a33..c61934fbf22a 100644 --- a/arch/x86/include/asm/xen/page.h +++ b/arch/x86/include/asm/xen/page.h | |||
@@ -29,8 +29,10 @@ typedef struct xpaddr { | |||
29 | 29 | ||
30 | /**** MACHINE <-> PHYSICAL CONVERSION MACROS ****/ | 30 | /**** MACHINE <-> PHYSICAL CONVERSION MACROS ****/ |
31 | #define INVALID_P2M_ENTRY (~0UL) | 31 | #define INVALID_P2M_ENTRY (~0UL) |
32 | #define FOREIGN_FRAME_BIT (1UL<<31) | 32 | #define FOREIGN_FRAME_BIT (1UL<<(BITS_PER_LONG-1)) |
33 | #define IDENTITY_FRAME_BIT (1UL<<(BITS_PER_LONG-2)) | ||
33 | #define FOREIGN_FRAME(m) ((m) | FOREIGN_FRAME_BIT) | 34 | #define FOREIGN_FRAME(m) ((m) | FOREIGN_FRAME_BIT) |
35 | #define IDENTITY_FRAME(m) ((m) | IDENTITY_FRAME_BIT) | ||
34 | 36 | ||
35 | /* Maximum amount of memory we can handle in a domain in pages */ | 37 | /* Maximum amount of memory we can handle in a domain in pages */ |
36 | #define MAX_DOMAIN_PAGES \ | 38 | #define MAX_DOMAIN_PAGES \ |
@@ -41,12 +43,18 @@ extern unsigned int machine_to_phys_order; | |||
41 | 43 | ||
42 | extern unsigned long get_phys_to_machine(unsigned long pfn); | 44 | extern unsigned long get_phys_to_machine(unsigned long pfn); |
43 | extern bool set_phys_to_machine(unsigned long pfn, unsigned long mfn); | 45 | extern bool set_phys_to_machine(unsigned long pfn, unsigned long mfn); |
46 | extern bool __set_phys_to_machine(unsigned long pfn, unsigned long mfn); | ||
47 | extern unsigned long set_phys_range_identity(unsigned long pfn_s, | ||
48 | unsigned long pfn_e); | ||
44 | 49 | ||
45 | extern int m2p_add_override(unsigned long mfn, struct page *page); | 50 | extern int m2p_add_override(unsigned long mfn, struct page *page); |
46 | extern int m2p_remove_override(struct page *page); | 51 | extern int m2p_remove_override(struct page *page); |
47 | extern struct page *m2p_find_override(unsigned long mfn); | 52 | extern struct page *m2p_find_override(unsigned long mfn); |
48 | extern unsigned long m2p_find_override_pfn(unsigned long mfn, unsigned long pfn); | 53 | extern unsigned long m2p_find_override_pfn(unsigned long mfn, unsigned long pfn); |
49 | 54 | ||
55 | #ifdef CONFIG_XEN_DEBUG_FS | ||
56 | extern int p2m_dump_show(struct seq_file *m, void *v); | ||
57 | #endif | ||
50 | static inline unsigned long pfn_to_mfn(unsigned long pfn) | 58 | static inline unsigned long pfn_to_mfn(unsigned long pfn) |
51 | { | 59 | { |
52 | unsigned long mfn; | 60 | unsigned long mfn; |
@@ -57,7 +65,7 @@ static inline unsigned long pfn_to_mfn(unsigned long pfn) | |||
57 | mfn = get_phys_to_machine(pfn); | 65 | mfn = get_phys_to_machine(pfn); |
58 | 66 | ||
59 | if (mfn != INVALID_P2M_ENTRY) | 67 | if (mfn != INVALID_P2M_ENTRY) |
60 | mfn &= ~FOREIGN_FRAME_BIT; | 68 | mfn &= ~(FOREIGN_FRAME_BIT | IDENTITY_FRAME_BIT); |
61 | 69 | ||
62 | return mfn; | 70 | return mfn; |
63 | } | 71 | } |
@@ -73,25 +81,44 @@ static inline int phys_to_machine_mapping_valid(unsigned long pfn) | |||
73 | static inline unsigned long mfn_to_pfn(unsigned long mfn) | 81 | static inline unsigned long mfn_to_pfn(unsigned long mfn) |
74 | { | 82 | { |
75 | unsigned long pfn; | 83 | unsigned long pfn; |
84 | int ret = 0; | ||
76 | 85 | ||
77 | if (xen_feature(XENFEAT_auto_translated_physmap)) | 86 | if (xen_feature(XENFEAT_auto_translated_physmap)) |
78 | return mfn; | 87 | return mfn; |
79 | 88 | ||
89 | if (unlikely((mfn >> machine_to_phys_order) != 0)) { | ||
90 | pfn = ~0; | ||
91 | goto try_override; | ||
92 | } | ||
80 | pfn = 0; | 93 | pfn = 0; |
81 | /* | 94 | /* |
82 | * The array access can fail (e.g., device space beyond end of RAM). | 95 | * The array access can fail (e.g., device space beyond end of RAM). |
83 | * In such cases it doesn't matter what we return (we return garbage), | 96 | * In such cases it doesn't matter what we return (we return garbage), |
84 | * but we must handle the fault without crashing! | 97 | * but we must handle the fault without crashing! |
85 | */ | 98 | */ |
86 | __get_user(pfn, &machine_to_phys_mapping[mfn]); | 99 | ret = __get_user(pfn, &machine_to_phys_mapping[mfn]); |
87 | 100 | try_override: | |
88 | /* | 101 | /* ret might be < 0 if there are no entries in the m2p for mfn */ |
89 | * If this appears to be a foreign mfn (because the pfn | 102 | if (ret < 0) |
90 | * doesn't map back to the mfn), then check the local override | 103 | pfn = ~0; |
91 | * table to see if there's a better pfn to use. | 104 | else if (get_phys_to_machine(pfn) != mfn) |
105 | /* | ||
106 | * If this appears to be a foreign mfn (because the pfn | ||
107 | * doesn't map back to the mfn), then check the local override | ||
108 | * table to see if there's a better pfn to use. | ||
109 | * | ||
110 | * m2p_find_override_pfn returns ~0 if it doesn't find anything. | ||
111 | */ | ||
112 | pfn = m2p_find_override_pfn(mfn, ~0); | ||
113 | |||
114 | /* | ||
115 | * pfn is ~0 if there are no entries in the m2p for mfn or if the | ||
116 | * entry doesn't map back to the mfn and m2p_override doesn't have a | ||
117 | * valid entry for it. | ||
92 | */ | 118 | */ |
93 | if (get_phys_to_machine(pfn) != mfn) | 119 | if (pfn == ~0 && |
94 | pfn = m2p_find_override_pfn(mfn, pfn); | 120 | get_phys_to_machine(mfn) == IDENTITY_FRAME(mfn)) |
121 | pfn = mfn; | ||
95 | 122 | ||
96 | return pfn; | 123 | return pfn; |
97 | } | 124 | } |
diff --git a/arch/x86/include/asm/xen/pci.h b/arch/x86/include/asm/xen/pci.h index 2329b3eaf8d3..aa8620989162 100644 --- a/arch/x86/include/asm/xen/pci.h +++ b/arch/x86/include/asm/xen/pci.h | |||
@@ -27,16 +27,16 @@ static inline void __init xen_setup_pirqs(void) | |||
27 | * its own functions. | 27 | * its own functions. |
28 | */ | 28 | */ |
29 | struct xen_pci_frontend_ops { | 29 | struct xen_pci_frontend_ops { |
30 | int (*enable_msi)(struct pci_dev *dev, int **vectors); | 30 | int (*enable_msi)(struct pci_dev *dev, int vectors[]); |
31 | void (*disable_msi)(struct pci_dev *dev); | 31 | void (*disable_msi)(struct pci_dev *dev); |
32 | int (*enable_msix)(struct pci_dev *dev, int **vectors, int nvec); | 32 | int (*enable_msix)(struct pci_dev *dev, int vectors[], int nvec); |
33 | void (*disable_msix)(struct pci_dev *dev); | 33 | void (*disable_msix)(struct pci_dev *dev); |
34 | }; | 34 | }; |
35 | 35 | ||
36 | extern struct xen_pci_frontend_ops *xen_pci_frontend; | 36 | extern struct xen_pci_frontend_ops *xen_pci_frontend; |
37 | 37 | ||
38 | static inline int xen_pci_frontend_enable_msi(struct pci_dev *dev, | 38 | static inline int xen_pci_frontend_enable_msi(struct pci_dev *dev, |
39 | int **vectors) | 39 | int vectors[]) |
40 | { | 40 | { |
41 | if (xen_pci_frontend && xen_pci_frontend->enable_msi) | 41 | if (xen_pci_frontend && xen_pci_frontend->enable_msi) |
42 | return xen_pci_frontend->enable_msi(dev, vectors); | 42 | return xen_pci_frontend->enable_msi(dev, vectors); |
@@ -48,7 +48,7 @@ static inline void xen_pci_frontend_disable_msi(struct pci_dev *dev) | |||
48 | xen_pci_frontend->disable_msi(dev); | 48 | xen_pci_frontend->disable_msi(dev); |
49 | } | 49 | } |
50 | static inline int xen_pci_frontend_enable_msix(struct pci_dev *dev, | 50 | static inline int xen_pci_frontend_enable_msix(struct pci_dev *dev, |
51 | int **vectors, int nvec) | 51 | int vectors[], int nvec) |
52 | { | 52 | { |
53 | if (xen_pci_frontend && xen_pci_frontend->enable_msix) | 53 | if (xen_pci_frontend && xen_pci_frontend->enable_msix) |
54 | return xen_pci_frontend->enable_msix(dev, vectors, nvec); | 54 | return xen_pci_frontend->enable_msix(dev, vectors, nvec); |
diff --git a/arch/x86/kernel/check.c b/arch/x86/kernel/check.c index 13a389179514..452932d34730 100644 --- a/arch/x86/kernel/check.c +++ b/arch/x86/kernel/check.c | |||
@@ -106,8 +106,8 @@ void __init setup_bios_corruption_check(void) | |||
106 | addr += size; | 106 | addr += size; |
107 | } | 107 | } |
108 | 108 | ||
109 | printk(KERN_INFO "Scanning %d areas for low memory corruption\n", | 109 | if (num_scan_areas) |
110 | num_scan_areas); | 110 | printk(KERN_INFO "Scanning %d areas for low memory corruption\n", num_scan_areas); |
111 | } | 111 | } |
112 | 112 | ||
113 | 113 | ||
@@ -143,12 +143,12 @@ static void check_corruption(struct work_struct *dummy) | |||
143 | { | 143 | { |
144 | check_for_bios_corruption(); | 144 | check_for_bios_corruption(); |
145 | schedule_delayed_work(&bios_check_work, | 145 | schedule_delayed_work(&bios_check_work, |
146 | round_jiffies_relative(corruption_check_period*HZ)); | 146 | round_jiffies_relative(corruption_check_period*HZ)); |
147 | } | 147 | } |
148 | 148 | ||
149 | static int start_periodic_check_for_corruption(void) | 149 | static int start_periodic_check_for_corruption(void) |
150 | { | 150 | { |
151 | if (!memory_corruption_check || corruption_check_period == 0) | 151 | if (!num_scan_areas || !memory_corruption_check || corruption_check_period == 0) |
152 | return 0; | 152 | return 0; |
153 | 153 | ||
154 | printk(KERN_INFO "Scanning for low memory corruption every %d seconds\n", | 154 | printk(KERN_INFO "Scanning for low memory corruption every %d seconds\n", |
diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c index 7d90ceb882a4..20e3f8702d1e 100644 --- a/arch/x86/mm/fault.c +++ b/arch/x86/mm/fault.c | |||
@@ -229,15 +229,14 @@ void vmalloc_sync_all(void) | |||
229 | for (address = VMALLOC_START & PMD_MASK; | 229 | for (address = VMALLOC_START & PMD_MASK; |
230 | address >= TASK_SIZE && address < FIXADDR_TOP; | 230 | address >= TASK_SIZE && address < FIXADDR_TOP; |
231 | address += PMD_SIZE) { | 231 | address += PMD_SIZE) { |
232 | |||
233 | unsigned long flags; | ||
234 | struct page *page; | 232 | struct page *page; |
235 | 233 | ||
236 | spin_lock_irqsave(&pgd_lock, flags); | 234 | spin_lock(&pgd_lock); |
237 | list_for_each_entry(page, &pgd_list, lru) { | 235 | list_for_each_entry(page, &pgd_list, lru) { |
238 | spinlock_t *pgt_lock; | 236 | spinlock_t *pgt_lock; |
239 | pmd_t *ret; | 237 | pmd_t *ret; |
240 | 238 | ||
239 | /* the pgt_lock only for Xen */ | ||
241 | pgt_lock = &pgd_page_get_mm(page)->page_table_lock; | 240 | pgt_lock = &pgd_page_get_mm(page)->page_table_lock; |
242 | 241 | ||
243 | spin_lock(pgt_lock); | 242 | spin_lock(pgt_lock); |
@@ -247,7 +246,7 @@ void vmalloc_sync_all(void) | |||
247 | if (!ret) | 246 | if (!ret) |
248 | break; | 247 | break; |
249 | } | 248 | } |
250 | spin_unlock_irqrestore(&pgd_lock, flags); | 249 | spin_unlock(&pgd_lock); |
251 | } | 250 | } |
252 | } | 251 | } |
253 | 252 | ||
@@ -828,6 +827,13 @@ mm_fault_error(struct pt_regs *regs, unsigned long error_code, | |||
828 | unsigned long address, unsigned int fault) | 827 | unsigned long address, unsigned int fault) |
829 | { | 828 | { |
830 | if (fault & VM_FAULT_OOM) { | 829 | if (fault & VM_FAULT_OOM) { |
830 | /* Kernel mode? Handle exceptions or die: */ | ||
831 | if (!(error_code & PF_USER)) { | ||
832 | up_read(¤t->mm->mmap_sem); | ||
833 | no_context(regs, error_code, address); | ||
834 | return; | ||
835 | } | ||
836 | |||
831 | out_of_memory(regs, error_code, address); | 837 | out_of_memory(regs, error_code, address); |
832 | } else { | 838 | } else { |
833 | if (fault & (VM_FAULT_SIGBUS|VM_FAULT_HWPOISON| | 839 | if (fault & (VM_FAULT_SIGBUS|VM_FAULT_HWPOISON| |
diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c index 71a59296af80..c14a5422e152 100644 --- a/arch/x86/mm/init_64.c +++ b/arch/x86/mm/init_64.c | |||
@@ -105,18 +105,18 @@ void sync_global_pgds(unsigned long start, unsigned long end) | |||
105 | 105 | ||
106 | for (address = start; address <= end; address += PGDIR_SIZE) { | 106 | for (address = start; address <= end; address += PGDIR_SIZE) { |
107 | const pgd_t *pgd_ref = pgd_offset_k(address); | 107 | const pgd_t *pgd_ref = pgd_offset_k(address); |
108 | unsigned long flags; | ||
109 | struct page *page; | 108 | struct page *page; |
110 | 109 | ||
111 | if (pgd_none(*pgd_ref)) | 110 | if (pgd_none(*pgd_ref)) |
112 | continue; | 111 | continue; |
113 | 112 | ||
114 | spin_lock_irqsave(&pgd_lock, flags); | 113 | spin_lock(&pgd_lock); |
115 | list_for_each_entry(page, &pgd_list, lru) { | 114 | list_for_each_entry(page, &pgd_list, lru) { |
116 | pgd_t *pgd; | 115 | pgd_t *pgd; |
117 | spinlock_t *pgt_lock; | 116 | spinlock_t *pgt_lock; |
118 | 117 | ||
119 | pgd = (pgd_t *)page_address(page) + pgd_index(address); | 118 | pgd = (pgd_t *)page_address(page) + pgd_index(address); |
119 | /* the pgt_lock only for Xen */ | ||
120 | pgt_lock = &pgd_page_get_mm(page)->page_table_lock; | 120 | pgt_lock = &pgd_page_get_mm(page)->page_table_lock; |
121 | spin_lock(pgt_lock); | 121 | spin_lock(pgt_lock); |
122 | 122 | ||
@@ -128,7 +128,7 @@ void sync_global_pgds(unsigned long start, unsigned long end) | |||
128 | 128 | ||
129 | spin_unlock(pgt_lock); | 129 | spin_unlock(pgt_lock); |
130 | } | 130 | } |
131 | spin_unlock_irqrestore(&pgd_lock, flags); | 131 | spin_unlock(&pgd_lock); |
132 | } | 132 | } |
133 | } | 133 | } |
134 | 134 | ||
diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c index d343b3c81f3c..90825f2eb0f4 100644 --- a/arch/x86/mm/pageattr.c +++ b/arch/x86/mm/pageattr.c | |||
@@ -57,12 +57,10 @@ static unsigned long direct_pages_count[PG_LEVEL_NUM]; | |||
57 | 57 | ||
58 | void update_page_count(int level, unsigned long pages) | 58 | void update_page_count(int level, unsigned long pages) |
59 | { | 59 | { |
60 | unsigned long flags; | ||
61 | |||
62 | /* Protect against CPA */ | 60 | /* Protect against CPA */ |
63 | spin_lock_irqsave(&pgd_lock, flags); | 61 | spin_lock(&pgd_lock); |
64 | direct_pages_count[level] += pages; | 62 | direct_pages_count[level] += pages; |
65 | spin_unlock_irqrestore(&pgd_lock, flags); | 63 | spin_unlock(&pgd_lock); |
66 | } | 64 | } |
67 | 65 | ||
68 | static void split_page_count(int level) | 66 | static void split_page_count(int level) |
@@ -394,7 +392,7 @@ static int | |||
394 | try_preserve_large_page(pte_t *kpte, unsigned long address, | 392 | try_preserve_large_page(pte_t *kpte, unsigned long address, |
395 | struct cpa_data *cpa) | 393 | struct cpa_data *cpa) |
396 | { | 394 | { |
397 | unsigned long nextpage_addr, numpages, pmask, psize, flags, addr, pfn; | 395 | unsigned long nextpage_addr, numpages, pmask, psize, addr, pfn; |
398 | pte_t new_pte, old_pte, *tmp; | 396 | pte_t new_pte, old_pte, *tmp; |
399 | pgprot_t old_prot, new_prot, req_prot; | 397 | pgprot_t old_prot, new_prot, req_prot; |
400 | int i, do_split = 1; | 398 | int i, do_split = 1; |
@@ -403,7 +401,7 @@ try_preserve_large_page(pte_t *kpte, unsigned long address, | |||
403 | if (cpa->force_split) | 401 | if (cpa->force_split) |
404 | return 1; | 402 | return 1; |
405 | 403 | ||
406 | spin_lock_irqsave(&pgd_lock, flags); | 404 | spin_lock(&pgd_lock); |
407 | /* | 405 | /* |
408 | * Check for races, another CPU might have split this page | 406 | * Check for races, another CPU might have split this page |
409 | * up already: | 407 | * up already: |
@@ -498,14 +496,14 @@ try_preserve_large_page(pte_t *kpte, unsigned long address, | |||
498 | } | 496 | } |
499 | 497 | ||
500 | out_unlock: | 498 | out_unlock: |
501 | spin_unlock_irqrestore(&pgd_lock, flags); | 499 | spin_unlock(&pgd_lock); |
502 | 500 | ||
503 | return do_split; | 501 | return do_split; |
504 | } | 502 | } |
505 | 503 | ||
506 | static int split_large_page(pte_t *kpte, unsigned long address) | 504 | static int split_large_page(pte_t *kpte, unsigned long address) |
507 | { | 505 | { |
508 | unsigned long flags, pfn, pfninc = 1; | 506 | unsigned long pfn, pfninc = 1; |
509 | unsigned int i, level; | 507 | unsigned int i, level; |
510 | pte_t *pbase, *tmp; | 508 | pte_t *pbase, *tmp; |
511 | pgprot_t ref_prot; | 509 | pgprot_t ref_prot; |
@@ -519,7 +517,7 @@ static int split_large_page(pte_t *kpte, unsigned long address) | |||
519 | if (!base) | 517 | if (!base) |
520 | return -ENOMEM; | 518 | return -ENOMEM; |
521 | 519 | ||
522 | spin_lock_irqsave(&pgd_lock, flags); | 520 | spin_lock(&pgd_lock); |
523 | /* | 521 | /* |
524 | * Check for races, another CPU might have split this page | 522 | * Check for races, another CPU might have split this page |
525 | * up for us already: | 523 | * up for us already: |
@@ -591,7 +589,7 @@ out_unlock: | |||
591 | */ | 589 | */ |
592 | if (base) | 590 | if (base) |
593 | __free_page(base); | 591 | __free_page(base); |
594 | spin_unlock_irqrestore(&pgd_lock, flags); | 592 | spin_unlock(&pgd_lock); |
595 | 593 | ||
596 | return 0; | 594 | return 0; |
597 | } | 595 | } |
diff --git a/arch/x86/mm/pgtable.c b/arch/x86/mm/pgtable.c index 500242d3c96d..0113d19c8aa6 100644 --- a/arch/x86/mm/pgtable.c +++ b/arch/x86/mm/pgtable.c | |||
@@ -121,14 +121,12 @@ static void pgd_ctor(struct mm_struct *mm, pgd_t *pgd) | |||
121 | 121 | ||
122 | static void pgd_dtor(pgd_t *pgd) | 122 | static void pgd_dtor(pgd_t *pgd) |
123 | { | 123 | { |
124 | unsigned long flags; /* can be called from interrupt context */ | ||
125 | |||
126 | if (SHARED_KERNEL_PMD) | 124 | if (SHARED_KERNEL_PMD) |
127 | return; | 125 | return; |
128 | 126 | ||
129 | spin_lock_irqsave(&pgd_lock, flags); | 127 | spin_lock(&pgd_lock); |
130 | pgd_list_del(pgd); | 128 | pgd_list_del(pgd); |
131 | spin_unlock_irqrestore(&pgd_lock, flags); | 129 | spin_unlock(&pgd_lock); |
132 | } | 130 | } |
133 | 131 | ||
134 | /* | 132 | /* |
@@ -260,7 +258,6 @@ pgd_t *pgd_alloc(struct mm_struct *mm) | |||
260 | { | 258 | { |
261 | pgd_t *pgd; | 259 | pgd_t *pgd; |
262 | pmd_t *pmds[PREALLOCATED_PMDS]; | 260 | pmd_t *pmds[PREALLOCATED_PMDS]; |
263 | unsigned long flags; | ||
264 | 261 | ||
265 | pgd = (pgd_t *)__get_free_page(PGALLOC_GFP); | 262 | pgd = (pgd_t *)__get_free_page(PGALLOC_GFP); |
266 | 263 | ||
@@ -280,12 +277,12 @@ pgd_t *pgd_alloc(struct mm_struct *mm) | |||
280 | * respect to anything walking the pgd_list, so that they | 277 | * respect to anything walking the pgd_list, so that they |
281 | * never see a partially populated pgd. | 278 | * never see a partially populated pgd. |
282 | */ | 279 | */ |
283 | spin_lock_irqsave(&pgd_lock, flags); | 280 | spin_lock(&pgd_lock); |
284 | 281 | ||
285 | pgd_ctor(mm, pgd); | 282 | pgd_ctor(mm, pgd); |
286 | pgd_prepopulate_pmd(mm, pgd, pmds); | 283 | pgd_prepopulate_pmd(mm, pgd, pmds); |
287 | 284 | ||
288 | spin_unlock_irqrestore(&pgd_lock, flags); | 285 | spin_unlock(&pgd_lock); |
289 | 286 | ||
290 | return pgd; | 287 | return pgd; |
291 | 288 | ||
diff --git a/arch/x86/pci/ce4100.c b/arch/x86/pci/ce4100.c index 85b68ef5e809..9260b3eb18d4 100644 --- a/arch/x86/pci/ce4100.c +++ b/arch/x86/pci/ce4100.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include <linux/pci.h> | 34 | #include <linux/pci.h> |
35 | #include <linux/init.h> | 35 | #include <linux/init.h> |
36 | 36 | ||
37 | #include <asm/ce4100.h> | ||
37 | #include <asm/pci_x86.h> | 38 | #include <asm/pci_x86.h> |
38 | 39 | ||
39 | struct sim_reg { | 40 | struct sim_reg { |
@@ -306,10 +307,10 @@ struct pci_raw_ops ce4100_pci_conf = { | |||
306 | .write = ce4100_conf_write, | 307 | .write = ce4100_conf_write, |
307 | }; | 308 | }; |
308 | 309 | ||
309 | static int __init ce4100_pci_init(void) | 310 | int __init ce4100_pci_init(void) |
310 | { | 311 | { |
311 | init_sim_regs(); | 312 | init_sim_regs(); |
312 | raw_pci_ops = &ce4100_pci_conf; | 313 | raw_pci_ops = &ce4100_pci_conf; |
313 | return 0; | 314 | /* Indicate caller that it should invoke pci_legacy_init() */ |
315 | return 1; | ||
314 | } | 316 | } |
315 | subsys_initcall(ce4100_pci_init); | ||
diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c index 25cd4a07d09f..8c4085a95ef1 100644 --- a/arch/x86/pci/xen.c +++ b/arch/x86/pci/xen.c | |||
@@ -20,7 +20,8 @@ | |||
20 | #include <asm/xen/pci.h> | 20 | #include <asm/xen/pci.h> |
21 | 21 | ||
22 | #ifdef CONFIG_ACPI | 22 | #ifdef CONFIG_ACPI |
23 | static int xen_hvm_register_pirq(u32 gsi, int triggering) | 23 | static int acpi_register_gsi_xen_hvm(struct device *dev, u32 gsi, |
24 | int trigger, int polarity) | ||
24 | { | 25 | { |
25 | int rc, irq; | 26 | int rc, irq; |
26 | struct physdev_map_pirq map_irq; | 27 | struct physdev_map_pirq map_irq; |
@@ -41,7 +42,7 @@ static int xen_hvm_register_pirq(u32 gsi, int triggering) | |||
41 | return -1; | 42 | return -1; |
42 | } | 43 | } |
43 | 44 | ||
44 | if (triggering == ACPI_EDGE_SENSITIVE) { | 45 | if (trigger == ACPI_EDGE_SENSITIVE) { |
45 | shareable = 0; | 46 | shareable = 0; |
46 | name = "ioapic-edge"; | 47 | name = "ioapic-edge"; |
47 | } else { | 48 | } else { |
@@ -55,12 +56,6 @@ static int xen_hvm_register_pirq(u32 gsi, int triggering) | |||
55 | 56 | ||
56 | return irq; | 57 | return irq; |
57 | } | 58 | } |
58 | |||
59 | static int acpi_register_gsi_xen_hvm(struct device *dev, u32 gsi, | ||
60 | int trigger, int polarity) | ||
61 | { | ||
62 | return xen_hvm_register_pirq(gsi, trigger); | ||
63 | } | ||
64 | #endif | 59 | #endif |
65 | 60 | ||
66 | #if defined(CONFIG_PCI_MSI) | 61 | #if defined(CONFIG_PCI_MSI) |
@@ -91,7 +86,7 @@ static void xen_msi_compose_msg(struct pci_dev *pdev, unsigned int pirq, | |||
91 | 86 | ||
92 | static int xen_hvm_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) | 87 | static int xen_hvm_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) |
93 | { | 88 | { |
94 | int irq, pirq, ret = 0; | 89 | int irq, pirq; |
95 | struct msi_desc *msidesc; | 90 | struct msi_desc *msidesc; |
96 | struct msi_msg msg; | 91 | struct msi_msg msg; |
97 | 92 | ||
@@ -99,39 +94,32 @@ static int xen_hvm_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) | |||
99 | __read_msi_msg(msidesc, &msg); | 94 | __read_msi_msg(msidesc, &msg); |
100 | pirq = MSI_ADDR_EXT_DEST_ID(msg.address_hi) | | 95 | pirq = MSI_ADDR_EXT_DEST_ID(msg.address_hi) | |
101 | ((msg.address_lo >> MSI_ADDR_DEST_ID_SHIFT) & 0xff); | 96 | ((msg.address_lo >> MSI_ADDR_DEST_ID_SHIFT) & 0xff); |
102 | if (xen_irq_from_pirq(pirq) >= 0 && msg.data == XEN_PIRQ_MSI_DATA) { | 97 | if (msg.data != XEN_PIRQ_MSI_DATA || |
103 | xen_allocate_pirq_msi((type == PCI_CAP_ID_MSIX) ? | 98 | xen_irq_from_pirq(pirq) < 0) { |
104 | "msi-x" : "msi", &irq, &pirq, XEN_ALLOC_IRQ); | 99 | pirq = xen_allocate_pirq_msi(dev, msidesc); |
105 | if (irq < 0) | 100 | if (pirq < 0) |
106 | goto error; | 101 | goto error; |
107 | ret = set_irq_msi(irq, msidesc); | 102 | xen_msi_compose_msg(dev, pirq, &msg); |
108 | if (ret < 0) | 103 | __write_msi_msg(msidesc, &msg); |
109 | goto error_while; | 104 | dev_dbg(&dev->dev, "xen: msi bound to pirq=%d\n", pirq); |
110 | printk(KERN_DEBUG "xen: msi already setup: msi --> irq=%d" | 105 | } else { |
111 | " pirq=%d\n", irq, pirq); | 106 | dev_dbg(&dev->dev, |
112 | return 0; | 107 | "xen: msi already bound to pirq=%d\n", pirq); |
113 | } | 108 | } |
114 | xen_allocate_pirq_msi((type == PCI_CAP_ID_MSIX) ? | 109 | irq = xen_bind_pirq_msi_to_irq(dev, msidesc, pirq, 0, |
115 | "msi-x" : "msi", &irq, &pirq, (XEN_ALLOC_IRQ | XEN_ALLOC_PIRQ)); | 110 | (type == PCI_CAP_ID_MSIX) ? |
116 | if (irq < 0 || pirq < 0) | 111 | "msi-x" : "msi"); |
112 | if (irq < 0) | ||
117 | goto error; | 113 | goto error; |
118 | printk(KERN_DEBUG "xen: msi --> irq=%d, pirq=%d\n", irq, pirq); | 114 | dev_dbg(&dev->dev, |
119 | xen_msi_compose_msg(dev, pirq, &msg); | 115 | "xen: msi --> pirq=%d --> irq=%d\n", pirq, irq); |
120 | ret = set_irq_msi(irq, msidesc); | ||
121 | if (ret < 0) | ||
122 | goto error_while; | ||
123 | write_msi_msg(irq, &msg); | ||
124 | } | 116 | } |
125 | return 0; | 117 | return 0; |
126 | 118 | ||
127 | error_while: | ||
128 | unbind_from_irqhandler(irq, NULL); | ||
129 | error: | 119 | error: |
130 | if (ret == -ENODEV) | 120 | dev_err(&dev->dev, |
131 | dev_err(&dev->dev, "Xen PCI frontend has not registered" \ | 121 | "Xen PCI frontend has not registered MSI/MSI-X support!\n"); |
132 | " MSI/MSI-X support!\n"); | 122 | return -ENODEV; |
133 | |||
134 | return ret; | ||
135 | } | 123 | } |
136 | 124 | ||
137 | /* | 125 | /* |
@@ -150,35 +138,26 @@ static int xen_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) | |||
150 | return -ENOMEM; | 138 | return -ENOMEM; |
151 | 139 | ||
152 | if (type == PCI_CAP_ID_MSIX) | 140 | if (type == PCI_CAP_ID_MSIX) |
153 | ret = xen_pci_frontend_enable_msix(dev, &v, nvec); | 141 | ret = xen_pci_frontend_enable_msix(dev, v, nvec); |
154 | else | 142 | else |
155 | ret = xen_pci_frontend_enable_msi(dev, &v); | 143 | ret = xen_pci_frontend_enable_msi(dev, v); |
156 | if (ret) | 144 | if (ret) |
157 | goto error; | 145 | goto error; |
158 | i = 0; | 146 | i = 0; |
159 | list_for_each_entry(msidesc, &dev->msi_list, list) { | 147 | list_for_each_entry(msidesc, &dev->msi_list, list) { |
160 | irq = xen_allocate_pirq(v[i], 0, /* not sharable */ | 148 | irq = xen_bind_pirq_msi_to_irq(dev, msidesc, v[i], 0, |
161 | (type == PCI_CAP_ID_MSIX) ? | 149 | (type == PCI_CAP_ID_MSIX) ? |
162 | "pcifront-msi-x" : "pcifront-msi"); | 150 | "pcifront-msi-x" : |
163 | if (irq < 0) { | 151 | "pcifront-msi"); |
164 | ret = -1; | 152 | if (irq < 0) |
165 | goto free; | 153 | goto free; |
166 | } | ||
167 | |||
168 | ret = set_irq_msi(irq, msidesc); | ||
169 | if (ret) | ||
170 | goto error_while; | ||
171 | i++; | 154 | i++; |
172 | } | 155 | } |
173 | kfree(v); | 156 | kfree(v); |
174 | return 0; | 157 | return 0; |
175 | 158 | ||
176 | error_while: | ||
177 | unbind_from_irqhandler(irq, NULL); | ||
178 | error: | 159 | error: |
179 | if (ret == -ENODEV) | 160 | dev_err(&dev->dev, "Xen PCI frontend has not registered MSI/MSI-X support!\n"); |
180 | dev_err(&dev->dev, "Xen PCI frontend has not registered" \ | ||
181 | " MSI/MSI-X support!\n"); | ||
182 | free: | 161 | free: |
183 | kfree(v); | 162 | kfree(v); |
184 | return ret; | 163 | return ret; |
@@ -193,6 +172,9 @@ static void xen_teardown_msi_irqs(struct pci_dev *dev) | |||
193 | xen_pci_frontend_disable_msix(dev); | 172 | xen_pci_frontend_disable_msix(dev); |
194 | else | 173 | else |
195 | xen_pci_frontend_disable_msi(dev); | 174 | xen_pci_frontend_disable_msi(dev); |
175 | |||
176 | /* Free the IRQ's and the msidesc using the generic code. */ | ||
177 | default_teardown_msi_irqs(dev); | ||
196 | } | 178 | } |
197 | 179 | ||
198 | static void xen_teardown_msi_irq(unsigned int irq) | 180 | static void xen_teardown_msi_irq(unsigned int irq) |
@@ -200,47 +182,82 @@ static void xen_teardown_msi_irq(unsigned int irq) | |||
200 | xen_destroy_irq(irq); | 182 | xen_destroy_irq(irq); |
201 | } | 183 | } |
202 | 184 | ||
185 | #ifdef CONFIG_XEN_DOM0 | ||
203 | static int xen_initdom_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) | 186 | static int xen_initdom_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) |
204 | { | 187 | { |
205 | int irq, ret; | 188 | int ret = 0; |
206 | struct msi_desc *msidesc; | 189 | struct msi_desc *msidesc; |
207 | 190 | ||
208 | list_for_each_entry(msidesc, &dev->msi_list, list) { | 191 | list_for_each_entry(msidesc, &dev->msi_list, list) { |
209 | irq = xen_create_msi_irq(dev, msidesc, type); | 192 | struct physdev_map_pirq map_irq; |
210 | if (irq < 0) | ||
211 | return -1; | ||
212 | 193 | ||
213 | ret = set_irq_msi(irq, msidesc); | 194 | memset(&map_irq, 0, sizeof(map_irq)); |
214 | if (ret) | 195 | map_irq.domid = DOMID_SELF; |
215 | goto error; | 196 | map_irq.type = MAP_PIRQ_TYPE_MSI; |
216 | } | 197 | map_irq.index = -1; |
217 | return 0; | 198 | map_irq.pirq = -1; |
199 | map_irq.bus = dev->bus->number; | ||
200 | map_irq.devfn = dev->devfn; | ||
218 | 201 | ||
219 | error: | 202 | if (type == PCI_CAP_ID_MSIX) { |
220 | xen_destroy_irq(irq); | 203 | int pos; |
204 | u32 table_offset, bir; | ||
205 | |||
206 | pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); | ||
207 | |||
208 | pci_read_config_dword(dev, pos + PCI_MSIX_TABLE, | ||
209 | &table_offset); | ||
210 | bir = (u8)(table_offset & PCI_MSIX_FLAGS_BIRMASK); | ||
211 | |||
212 | map_irq.table_base = pci_resource_start(dev, bir); | ||
213 | map_irq.entry_nr = msidesc->msi_attrib.entry_nr; | ||
214 | } | ||
215 | |||
216 | ret = HYPERVISOR_physdev_op(PHYSDEVOP_map_pirq, &map_irq); | ||
217 | if (ret) { | ||
218 | dev_warn(&dev->dev, "xen map irq failed %d\n", ret); | ||
219 | goto out; | ||
220 | } | ||
221 | |||
222 | ret = xen_bind_pirq_msi_to_irq(dev, msidesc, | ||
223 | map_irq.pirq, map_irq.index, | ||
224 | (type == PCI_CAP_ID_MSIX) ? | ||
225 | "msi-x" : "msi"); | ||
226 | if (ret < 0) | ||
227 | goto out; | ||
228 | } | ||
229 | ret = 0; | ||
230 | out: | ||
221 | return ret; | 231 | return ret; |
222 | } | 232 | } |
223 | #endif | 233 | #endif |
234 | #endif | ||
224 | 235 | ||
225 | static int xen_pcifront_enable_irq(struct pci_dev *dev) | 236 | static int xen_pcifront_enable_irq(struct pci_dev *dev) |
226 | { | 237 | { |
227 | int rc; | 238 | int rc; |
228 | int share = 1; | 239 | int share = 1; |
240 | u8 gsi; | ||
229 | 241 | ||
230 | dev_info(&dev->dev, "Xen PCI enabling IRQ: %d\n", dev->irq); | 242 | rc = pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &gsi); |
231 | 243 | if (rc < 0) { | |
232 | if (dev->irq < 0) | 244 | dev_warn(&dev->dev, "Xen PCI: failed to read interrupt line: %d\n", |
233 | return -EINVAL; | 245 | rc); |
246 | return rc; | ||
247 | } | ||
234 | 248 | ||
235 | if (dev->irq < NR_IRQS_LEGACY) | 249 | if (gsi < NR_IRQS_LEGACY) |
236 | share = 0; | 250 | share = 0; |
237 | 251 | ||
238 | rc = xen_allocate_pirq(dev->irq, share, "pcifront"); | 252 | rc = xen_allocate_pirq(gsi, share, "pcifront"); |
239 | if (rc < 0) { | 253 | if (rc < 0) { |
240 | dev_warn(&dev->dev, "Xen PCI IRQ: %d, failed to register:%d\n", | 254 | dev_warn(&dev->dev, "Xen PCI: failed to register GSI%d: %d\n", |
241 | dev->irq, rc); | 255 | gsi, rc); |
242 | return rc; | 256 | return rc; |
243 | } | 257 | } |
258 | |||
259 | dev->irq = rc; | ||
260 | dev_info(&dev->dev, "Xen PCI mapped GSI%d to IRQ%d\n", gsi, dev->irq); | ||
244 | return 0; | 261 | return 0; |
245 | } | 262 | } |
246 | 263 | ||
diff --git a/arch/x86/platform/ce4100/ce4100.c b/arch/x86/platform/ce4100/ce4100.c index d2c0d51a7178..cd6f184c3b3f 100644 --- a/arch/x86/platform/ce4100/ce4100.c +++ b/arch/x86/platform/ce4100/ce4100.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/serial_reg.h> | 15 | #include <linux/serial_reg.h> |
16 | #include <linux/serial_8250.h> | 16 | #include <linux/serial_8250.h> |
17 | 17 | ||
18 | #include <asm/ce4100.h> | ||
18 | #include <asm/setup.h> | 19 | #include <asm/setup.h> |
19 | #include <asm/io.h> | 20 | #include <asm/io.h> |
20 | 21 | ||
@@ -129,4 +130,5 @@ void __init x86_ce4100_early_setup(void) | |||
129 | x86_init.resources.probe_roms = x86_init_noop; | 130 | x86_init.resources.probe_roms = x86_init_noop; |
130 | x86_init.mpparse.get_smp_config = x86_init_uint_noop; | 131 | x86_init.mpparse.get_smp_config = x86_init_uint_noop; |
131 | x86_init.mpparse.find_smp_config = sdv_find_smp_config; | 132 | x86_init.mpparse.find_smp_config = sdv_find_smp_config; |
133 | x86_init.pci.init = ce4100_pci_init; | ||
132 | } | 134 | } |
diff --git a/arch/x86/xen/Kconfig b/arch/x86/xen/Kconfig index 5b54892e4bc3..e4343fe488ed 100644 --- a/arch/x86/xen/Kconfig +++ b/arch/x86/xen/Kconfig | |||
@@ -48,3 +48,11 @@ config XEN_DEBUG_FS | |||
48 | help | 48 | help |
49 | Enable statistics output and various tuning options in debugfs. | 49 | Enable statistics output and various tuning options in debugfs. |
50 | Enabling this option may incur a significant performance overhead. | 50 | Enabling this option may incur a significant performance overhead. |
51 | |||
52 | config XEN_DEBUG | ||
53 | bool "Enable Xen debug checks" | ||
54 | depends on XEN | ||
55 | default n | ||
56 | help | ||
57 | Enable various WARN_ON checks in the Xen MMU code. | ||
58 | Enabling this option WILL incur a significant performance overhead. | ||
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index 50542efe45fb..49dbd78ec3cb 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c | |||
@@ -1284,15 +1284,14 @@ static int init_hvm_pv_info(int *major, int *minor) | |||
1284 | 1284 | ||
1285 | xen_setup_features(); | 1285 | xen_setup_features(); |
1286 | 1286 | ||
1287 | pv_info = xen_info; | 1287 | pv_info.name = "Xen HVM"; |
1288 | pv_info.kernel_rpl = 0; | ||
1289 | 1288 | ||
1290 | xen_domain_type = XEN_HVM_DOMAIN; | 1289 | xen_domain_type = XEN_HVM_DOMAIN; |
1291 | 1290 | ||
1292 | return 0; | 1291 | return 0; |
1293 | } | 1292 | } |
1294 | 1293 | ||
1295 | void xen_hvm_init_shared_info(void) | 1294 | void __ref xen_hvm_init_shared_info(void) |
1296 | { | 1295 | { |
1297 | int cpu; | 1296 | int cpu; |
1298 | struct xen_add_to_physmap xatp; | 1297 | struct xen_add_to_physmap xatp; |
@@ -1331,6 +1330,8 @@ static int __cpuinit xen_hvm_cpu_notify(struct notifier_block *self, | |||
1331 | switch (action) { | 1330 | switch (action) { |
1332 | case CPU_UP_PREPARE: | 1331 | case CPU_UP_PREPARE: |
1333 | per_cpu(xen_vcpu, cpu) = &HYPERVISOR_shared_info->vcpu_info[cpu]; | 1332 | per_cpu(xen_vcpu, cpu) = &HYPERVISOR_shared_info->vcpu_info[cpu]; |
1333 | if (xen_have_vector_callback) | ||
1334 | xen_init_lock_cpu(cpu); | ||
1334 | break; | 1335 | break; |
1335 | default: | 1336 | default: |
1336 | break; | 1337 | break; |
@@ -1355,6 +1356,7 @@ static void __init xen_hvm_guest_init(void) | |||
1355 | 1356 | ||
1356 | if (xen_feature(XENFEAT_hvm_callback_vector)) | 1357 | if (xen_feature(XENFEAT_hvm_callback_vector)) |
1357 | xen_have_vector_callback = 1; | 1358 | xen_have_vector_callback = 1; |
1359 | xen_hvm_smp_init(); | ||
1358 | register_cpu_notifier(&xen_hvm_cpu_notifier); | 1360 | register_cpu_notifier(&xen_hvm_cpu_notifier); |
1359 | xen_unplug_emulated_devices(); | 1361 | xen_unplug_emulated_devices(); |
1360 | have_vcpu_info_placement = 0; | 1362 | have_vcpu_info_placement = 0; |
diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c index 5e92b61ad574..832765c0fb8c 100644 --- a/arch/x86/xen/mmu.c +++ b/arch/x86/xen/mmu.c | |||
@@ -46,6 +46,7 @@ | |||
46 | #include <linux/module.h> | 46 | #include <linux/module.h> |
47 | #include <linux/gfp.h> | 47 | #include <linux/gfp.h> |
48 | #include <linux/memblock.h> | 48 | #include <linux/memblock.h> |
49 | #include <linux/seq_file.h> | ||
49 | 50 | ||
50 | #include <asm/pgtable.h> | 51 | #include <asm/pgtable.h> |
51 | #include <asm/tlbflush.h> | 52 | #include <asm/tlbflush.h> |
@@ -416,8 +417,12 @@ static pteval_t pte_pfn_to_mfn(pteval_t val) | |||
416 | if (val & _PAGE_PRESENT) { | 417 | if (val & _PAGE_PRESENT) { |
417 | unsigned long pfn = (val & PTE_PFN_MASK) >> PAGE_SHIFT; | 418 | unsigned long pfn = (val & PTE_PFN_MASK) >> PAGE_SHIFT; |
418 | pteval_t flags = val & PTE_FLAGS_MASK; | 419 | pteval_t flags = val & PTE_FLAGS_MASK; |
419 | unsigned long mfn = pfn_to_mfn(pfn); | 420 | unsigned long mfn; |
420 | 421 | ||
422 | if (!xen_feature(XENFEAT_auto_translated_physmap)) | ||
423 | mfn = get_phys_to_machine(pfn); | ||
424 | else | ||
425 | mfn = pfn; | ||
421 | /* | 426 | /* |
422 | * If there's no mfn for the pfn, then just create an | 427 | * If there's no mfn for the pfn, then just create an |
423 | * empty non-present pte. Unfortunately this loses | 428 | * empty non-present pte. Unfortunately this loses |
@@ -427,8 +432,18 @@ static pteval_t pte_pfn_to_mfn(pteval_t val) | |||
427 | if (unlikely(mfn == INVALID_P2M_ENTRY)) { | 432 | if (unlikely(mfn == INVALID_P2M_ENTRY)) { |
428 | mfn = 0; | 433 | mfn = 0; |
429 | flags = 0; | 434 | flags = 0; |
435 | } else { | ||
436 | /* | ||
437 | * Paramount to do this test _after_ the | ||
438 | * INVALID_P2M_ENTRY as INVALID_P2M_ENTRY & | ||
439 | * IDENTITY_FRAME_BIT resolves to true. | ||
440 | */ | ||
441 | mfn &= ~FOREIGN_FRAME_BIT; | ||
442 | if (mfn & IDENTITY_FRAME_BIT) { | ||
443 | mfn &= ~IDENTITY_FRAME_BIT; | ||
444 | flags |= _PAGE_IOMAP; | ||
445 | } | ||
430 | } | 446 | } |
431 | |||
432 | val = ((pteval_t)mfn << PAGE_SHIFT) | flags; | 447 | val = ((pteval_t)mfn << PAGE_SHIFT) | flags; |
433 | } | 448 | } |
434 | 449 | ||
@@ -532,6 +547,41 @@ pte_t xen_make_pte(pteval_t pte) | |||
532 | } | 547 | } |
533 | PV_CALLEE_SAVE_REGS_THUNK(xen_make_pte); | 548 | PV_CALLEE_SAVE_REGS_THUNK(xen_make_pte); |
534 | 549 | ||
550 | #ifdef CONFIG_XEN_DEBUG | ||
551 | pte_t xen_make_pte_debug(pteval_t pte) | ||
552 | { | ||
553 | phys_addr_t addr = (pte & PTE_PFN_MASK); | ||
554 | phys_addr_t other_addr; | ||
555 | bool io_page = false; | ||
556 | pte_t _pte; | ||
557 | |||
558 | if (pte & _PAGE_IOMAP) | ||
559 | io_page = true; | ||
560 | |||
561 | _pte = xen_make_pte(pte); | ||
562 | |||
563 | if (!addr) | ||
564 | return _pte; | ||
565 | |||
566 | if (io_page && | ||
567 | (xen_initial_domain() || addr >= ISA_END_ADDRESS)) { | ||
568 | other_addr = pfn_to_mfn(addr >> PAGE_SHIFT) << PAGE_SHIFT; | ||
569 | WARN(addr != other_addr, | ||
570 | "0x%lx is using VM_IO, but it is 0x%lx!\n", | ||
571 | (unsigned long)addr, (unsigned long)other_addr); | ||
572 | } else { | ||
573 | pteval_t iomap_set = (_pte.pte & PTE_FLAGS_MASK) & _PAGE_IOMAP; | ||
574 | other_addr = (_pte.pte & PTE_PFN_MASK); | ||
575 | WARN((addr == other_addr) && (!io_page) && (!iomap_set), | ||
576 | "0x%lx is missing VM_IO (and wasn't fixed)!\n", | ||
577 | (unsigned long)addr); | ||
578 | } | ||
579 | |||
580 | return _pte; | ||
581 | } | ||
582 | PV_CALLEE_SAVE_REGS_THUNK(xen_make_pte_debug); | ||
583 | #endif | ||
584 | |||
535 | pgd_t xen_make_pgd(pgdval_t pgd) | 585 | pgd_t xen_make_pgd(pgdval_t pgd) |
536 | { | 586 | { |
537 | pgd = pte_pfn_to_mfn(pgd); | 587 | pgd = pte_pfn_to_mfn(pgd); |
@@ -986,10 +1036,9 @@ static void xen_pgd_pin(struct mm_struct *mm) | |||
986 | */ | 1036 | */ |
987 | void xen_mm_pin_all(void) | 1037 | void xen_mm_pin_all(void) |
988 | { | 1038 | { |
989 | unsigned long flags; | ||
990 | struct page *page; | 1039 | struct page *page; |
991 | 1040 | ||
992 | spin_lock_irqsave(&pgd_lock, flags); | 1041 | spin_lock(&pgd_lock); |
993 | 1042 | ||
994 | list_for_each_entry(page, &pgd_list, lru) { | 1043 | list_for_each_entry(page, &pgd_list, lru) { |
995 | if (!PagePinned(page)) { | 1044 | if (!PagePinned(page)) { |
@@ -998,7 +1047,7 @@ void xen_mm_pin_all(void) | |||
998 | } | 1047 | } |
999 | } | 1048 | } |
1000 | 1049 | ||
1001 | spin_unlock_irqrestore(&pgd_lock, flags); | 1050 | spin_unlock(&pgd_lock); |
1002 | } | 1051 | } |
1003 | 1052 | ||
1004 | /* | 1053 | /* |
@@ -1099,10 +1148,9 @@ static void xen_pgd_unpin(struct mm_struct *mm) | |||
1099 | */ | 1148 | */ |
1100 | void xen_mm_unpin_all(void) | 1149 | void xen_mm_unpin_all(void) |
1101 | { | 1150 | { |
1102 | unsigned long flags; | ||
1103 | struct page *page; | 1151 | struct page *page; |
1104 | 1152 | ||
1105 | spin_lock_irqsave(&pgd_lock, flags); | 1153 | spin_lock(&pgd_lock); |
1106 | 1154 | ||
1107 | list_for_each_entry(page, &pgd_list, lru) { | 1155 | list_for_each_entry(page, &pgd_list, lru) { |
1108 | if (PageSavePinned(page)) { | 1156 | if (PageSavePinned(page)) { |
@@ -1112,7 +1160,7 @@ void xen_mm_unpin_all(void) | |||
1112 | } | 1160 | } |
1113 | } | 1161 | } |
1114 | 1162 | ||
1115 | spin_unlock_irqrestore(&pgd_lock, flags); | 1163 | spin_unlock(&pgd_lock); |
1116 | } | 1164 | } |
1117 | 1165 | ||
1118 | void xen_activate_mm(struct mm_struct *prev, struct mm_struct *next) | 1166 | void xen_activate_mm(struct mm_struct *prev, struct mm_struct *next) |
@@ -1942,6 +1990,9 @@ __init void xen_ident_map_ISA(void) | |||
1942 | 1990 | ||
1943 | static __init void xen_post_allocator_init(void) | 1991 | static __init void xen_post_allocator_init(void) |
1944 | { | 1992 | { |
1993 | #ifdef CONFIG_XEN_DEBUG | ||
1994 | pv_mmu_ops.make_pte = PV_CALLEE_SAVE(xen_make_pte_debug); | ||
1995 | #endif | ||
1945 | pv_mmu_ops.set_pte = xen_set_pte; | 1996 | pv_mmu_ops.set_pte = xen_set_pte; |
1946 | pv_mmu_ops.set_pmd = xen_set_pmd; | 1997 | pv_mmu_ops.set_pmd = xen_set_pmd; |
1947 | pv_mmu_ops.set_pud = xen_set_pud; | 1998 | pv_mmu_ops.set_pud = xen_set_pud; |
@@ -2074,7 +2125,7 @@ static void xen_zap_pfn_range(unsigned long vaddr, unsigned int order, | |||
2074 | in_frames[i] = virt_to_mfn(vaddr); | 2125 | in_frames[i] = virt_to_mfn(vaddr); |
2075 | 2126 | ||
2076 | MULTI_update_va_mapping(mcs.mc, vaddr, VOID_PTE, 0); | 2127 | MULTI_update_va_mapping(mcs.mc, vaddr, VOID_PTE, 0); |
2077 | set_phys_to_machine(virt_to_pfn(vaddr), INVALID_P2M_ENTRY); | 2128 | __set_phys_to_machine(virt_to_pfn(vaddr), INVALID_P2M_ENTRY); |
2078 | 2129 | ||
2079 | if (out_frames) | 2130 | if (out_frames) |
2080 | out_frames[i] = virt_to_pfn(vaddr); | 2131 | out_frames[i] = virt_to_pfn(vaddr); |
@@ -2353,6 +2404,18 @@ EXPORT_SYMBOL_GPL(xen_remap_domain_mfn_range); | |||
2353 | 2404 | ||
2354 | #ifdef CONFIG_XEN_DEBUG_FS | 2405 | #ifdef CONFIG_XEN_DEBUG_FS |
2355 | 2406 | ||
2407 | static int p2m_dump_open(struct inode *inode, struct file *filp) | ||
2408 | { | ||
2409 | return single_open(filp, p2m_dump_show, NULL); | ||
2410 | } | ||
2411 | |||
2412 | static const struct file_operations p2m_dump_fops = { | ||
2413 | .open = p2m_dump_open, | ||
2414 | .read = seq_read, | ||
2415 | .llseek = seq_lseek, | ||
2416 | .release = single_release, | ||
2417 | }; | ||
2418 | |||
2356 | static struct dentry *d_mmu_debug; | 2419 | static struct dentry *d_mmu_debug; |
2357 | 2420 | ||
2358 | static int __init xen_mmu_debugfs(void) | 2421 | static int __init xen_mmu_debugfs(void) |
@@ -2408,6 +2471,7 @@ static int __init xen_mmu_debugfs(void) | |||
2408 | debugfs_create_u32("prot_commit_batched", 0444, d_mmu_debug, | 2471 | debugfs_create_u32("prot_commit_batched", 0444, d_mmu_debug, |
2409 | &mmu_stats.prot_commit_batched); | 2472 | &mmu_stats.prot_commit_batched); |
2410 | 2473 | ||
2474 | debugfs_create_file("p2m", 0600, d_mmu_debug, NULL, &p2m_dump_fops); | ||
2411 | return 0; | 2475 | return 0; |
2412 | } | 2476 | } |
2413 | fs_initcall(xen_mmu_debugfs); | 2477 | fs_initcall(xen_mmu_debugfs); |
diff --git a/arch/x86/xen/p2m.c b/arch/x86/xen/p2m.c index fd12d7ce7ff9..215a3ce61068 100644 --- a/arch/x86/xen/p2m.c +++ b/arch/x86/xen/p2m.c | |||
@@ -23,6 +23,129 @@ | |||
23 | * P2M_PER_PAGE depends on the architecture, as a mfn is always | 23 | * P2M_PER_PAGE depends on the architecture, as a mfn is always |
24 | * unsigned long (8 bytes on 64-bit, 4 bytes on 32), leading to | 24 | * unsigned long (8 bytes on 64-bit, 4 bytes on 32), leading to |
25 | * 512 and 1024 entries respectively. | 25 | * 512 and 1024 entries respectively. |
26 | * | ||
27 | * In short, these structures contain the Machine Frame Number (MFN) of the PFN. | ||
28 | * | ||
29 | * However not all entries are filled with MFNs. Specifically for all other | ||
30 | * leaf entries, or for the top root, or middle one, for which there is a void | ||
31 | * entry, we assume it is "missing". So (for example) | ||
32 | * pfn_to_mfn(0x90909090)=INVALID_P2M_ENTRY. | ||
33 | * | ||
34 | * We also have the possibility of setting 1-1 mappings on certain regions, so | ||
35 | * that: | ||
36 | * pfn_to_mfn(0xc0000)=0xc0000 | ||
37 | * | ||
38 | * The benefit of this is, that we can assume for non-RAM regions (think | ||
39 | * PCI BARs, or ACPI spaces), we can create mappings easily b/c we | ||
40 | * get the PFN value to match the MFN. | ||
41 | * | ||
42 | * For this to work efficiently we have one new page p2m_identity and | ||
43 | * allocate (via reserved_brk) any other pages we need to cover the sides | ||
44 | * (1GB or 4MB boundary violations). All entries in p2m_identity are set to | ||
45 | * INVALID_P2M_ENTRY type (Xen toolstack only recognizes that and MFNs, | ||
46 | * no other fancy value). | ||
47 | * | ||
48 | * On lookup we spot that the entry points to p2m_identity and return the | ||
49 | * identity value instead of dereferencing and returning INVALID_P2M_ENTRY. | ||
50 | * If the entry points to an allocated page, we just proceed as before and | ||
51 | * return the PFN. If the PFN has IDENTITY_FRAME_BIT set we unmask that in | ||
52 | * appropriate functions (pfn_to_mfn). | ||
53 | * | ||
54 | * The reason for having the IDENTITY_FRAME_BIT instead of just returning the | ||
55 | * PFN is that we could find ourselves where pfn_to_mfn(pfn)==pfn for a | ||
56 | * non-identity pfn. To protect ourselves against we elect to set (and get) the | ||
57 | * IDENTITY_FRAME_BIT on all identity mapped PFNs. | ||
58 | * | ||
59 | * This simplistic diagram is used to explain the more subtle piece of code. | ||
60 | * There is also a digram of the P2M at the end that can help. | ||
61 | * Imagine your E820 looking as so: | ||
62 | * | ||
63 | * 1GB 2GB | ||
64 | * /-------------------+---------\/----\ /----------\ /---+-----\ | ||
65 | * | System RAM | Sys RAM ||ACPI| | reserved | | Sys RAM | | ||
66 | * \-------------------+---------/\----/ \----------/ \---+-----/ | ||
67 | * ^- 1029MB ^- 2001MB | ||
68 | * | ||
69 | * [1029MB = 263424 (0x40500), 2001MB = 512256 (0x7D100), | ||
70 | * 2048MB = 524288 (0x80000)] | ||
71 | * | ||
72 | * And dom0_mem=max:3GB,1GB is passed in to the guest, meaning memory past 1GB | ||
73 | * is actually not present (would have to kick the balloon driver to put it in). | ||
74 | * | ||
75 | * When we are told to set the PFNs for identity mapping (see patch: "xen/setup: | ||
76 | * Set identity mapping for non-RAM E820 and E820 gaps.") we pass in the start | ||
77 | * of the PFN and the end PFN (263424 and 512256 respectively). The first step | ||
78 | * is to reserve_brk a top leaf page if the p2m[1] is missing. The top leaf page | ||
79 | * covers 512^2 of page estate (1GB) and in case the start or end PFN is not | ||
80 | * aligned on 512^2*PAGE_SIZE (1GB) we loop on aligned 1GB PFNs from start pfn | ||
81 | * to end pfn. We reserve_brk top leaf pages if they are missing (means they | ||
82 | * point to p2m_mid_missing). | ||
83 | * | ||
84 | * With the E820 example above, 263424 is not 1GB aligned so we allocate a | ||
85 | * reserve_brk page which will cover the PFNs estate from 0x40000 to 0x80000. | ||
86 | * Each entry in the allocate page is "missing" (points to p2m_missing). | ||
87 | * | ||
88 | * Next stage is to determine if we need to do a more granular boundary check | ||
89 | * on the 4MB (or 2MB depending on architecture) off the start and end pfn's. | ||
90 | * We check if the start pfn and end pfn violate that boundary check, and if | ||
91 | * so reserve_brk a middle (p2m[x][y]) leaf page. This way we have a much finer | ||
92 | * granularity of setting which PFNs are missing and which ones are identity. | ||
93 | * In our example 263424 and 512256 both fail the check so we reserve_brk two | ||
94 | * pages. Populate them with INVALID_P2M_ENTRY (so they both have "missing" | ||
95 | * values) and assign them to p2m[1][2] and p2m[1][488] respectively. | ||
96 | * | ||
97 | * At this point we would at minimum reserve_brk one page, but could be up to | ||
98 | * three. Each call to set_phys_range_identity has at maximum a three page | ||
99 | * cost. If we were to query the P2M at this stage, all those entries from | ||
100 | * start PFN through end PFN (so 1029MB -> 2001MB) would return | ||
101 | * INVALID_P2M_ENTRY ("missing"). | ||
102 | * | ||
103 | * The next step is to walk from the start pfn to the end pfn setting | ||
104 | * the IDENTITY_FRAME_BIT on each PFN. This is done in set_phys_range_identity. | ||
105 | * If we find that the middle leaf is pointing to p2m_missing we can swap it | ||
106 | * over to p2m_identity - this way covering 4MB (or 2MB) PFN space. At this | ||
107 | * point we do not need to worry about boundary aligment (so no need to | ||
108 | * reserve_brk a middle page, figure out which PFNs are "missing" and which | ||
109 | * ones are identity), as that has been done earlier. If we find that the | ||
110 | * middle leaf is not occupied by p2m_identity or p2m_missing, we dereference | ||
111 | * that page (which covers 512 PFNs) and set the appropriate PFN with | ||
112 | * IDENTITY_FRAME_BIT. In our example 263424 and 512256 end up there, and we | ||
113 | * set from p2m[1][2][256->511] and p2m[1][488][0->256] with | ||
114 | * IDENTITY_FRAME_BIT set. | ||
115 | * | ||
116 | * All other regions that are void (or not filled) either point to p2m_missing | ||
117 | * (considered missing) or have the default value of INVALID_P2M_ENTRY (also | ||
118 | * considered missing). In our case, p2m[1][2][0->255] and p2m[1][488][257->511] | ||
119 | * contain the INVALID_P2M_ENTRY value and are considered "missing." | ||
120 | * | ||
121 | * This is what the p2m ends up looking (for the E820 above) with this | ||
122 | * fabulous drawing: | ||
123 | * | ||
124 | * p2m /--------------\ | ||
125 | * /-----\ | &mfn_list[0],| /-----------------\ | ||
126 | * | 0 |------>| &mfn_list[1],| /---------------\ | ~0, ~0, .. | | ||
127 | * |-----| | ..., ~0, ~0 | | ~0, ~0, [x]---+----->| IDENTITY [@256] | | ||
128 | * | 1 |---\ \--------------/ | [p2m_identity]+\ | IDENTITY [@257] | | ||
129 | * |-----| \ | [p2m_identity]+\\ | .... | | ||
130 | * | 2 |--\ \-------------------->| ... | \\ \----------------/ | ||
131 | * |-----| \ \---------------/ \\ | ||
132 | * | 3 |\ \ \\ p2m_identity | ||
133 | * |-----| \ \-------------------->/---------------\ /-----------------\ | ||
134 | * | .. +->+ | [p2m_identity]+-->| ~0, ~0, ~0, ... | | ||
135 | * \-----/ / | [p2m_identity]+-->| ..., ~0 | | ||
136 | * / /---------------\ | .... | \-----------------/ | ||
137 | * / | IDENTITY[@0] | /-+-[x], ~0, ~0.. | | ||
138 | * / | IDENTITY[@256]|<----/ \---------------/ | ||
139 | * / | ~0, ~0, .... | | ||
140 | * | \---------------/ | ||
141 | * | | ||
142 | * p2m_missing p2m_missing | ||
143 | * /------------------\ /------------\ | ||
144 | * | [p2m_mid_missing]+---->| ~0, ~0, ~0 | | ||
145 | * | [p2m_mid_missing]+---->| ..., ~0 | | ||
146 | * \------------------/ \------------/ | ||
147 | * | ||
148 | * where ~0 is INVALID_P2M_ENTRY. IDENTITY is (PFN | IDENTITY_BIT) | ||
26 | */ | 149 | */ |
27 | 150 | ||
28 | #include <linux/init.h> | 151 | #include <linux/init.h> |
@@ -30,6 +153,7 @@ | |||
30 | #include <linux/list.h> | 153 | #include <linux/list.h> |
31 | #include <linux/hash.h> | 154 | #include <linux/hash.h> |
32 | #include <linux/sched.h> | 155 | #include <linux/sched.h> |
156 | #include <linux/seq_file.h> | ||
33 | 157 | ||
34 | #include <asm/cache.h> | 158 | #include <asm/cache.h> |
35 | #include <asm/setup.h> | 159 | #include <asm/setup.h> |
@@ -59,9 +183,15 @@ static RESERVE_BRK_ARRAY(unsigned long **, p2m_top, P2M_TOP_PER_PAGE); | |||
59 | static RESERVE_BRK_ARRAY(unsigned long, p2m_top_mfn, P2M_TOP_PER_PAGE); | 183 | static RESERVE_BRK_ARRAY(unsigned long, p2m_top_mfn, P2M_TOP_PER_PAGE); |
60 | static RESERVE_BRK_ARRAY(unsigned long *, p2m_top_mfn_p, P2M_TOP_PER_PAGE); | 184 | static RESERVE_BRK_ARRAY(unsigned long *, p2m_top_mfn_p, P2M_TOP_PER_PAGE); |
61 | 185 | ||
186 | static RESERVE_BRK_ARRAY(unsigned long, p2m_identity, P2M_PER_PAGE); | ||
187 | |||
62 | RESERVE_BRK(p2m_mid, PAGE_SIZE * (MAX_DOMAIN_PAGES / (P2M_PER_PAGE * P2M_MID_PER_PAGE))); | 188 | RESERVE_BRK(p2m_mid, PAGE_SIZE * (MAX_DOMAIN_PAGES / (P2M_PER_PAGE * P2M_MID_PER_PAGE))); |
63 | RESERVE_BRK(p2m_mid_mfn, PAGE_SIZE * (MAX_DOMAIN_PAGES / (P2M_PER_PAGE * P2M_MID_PER_PAGE))); | 189 | RESERVE_BRK(p2m_mid_mfn, PAGE_SIZE * (MAX_DOMAIN_PAGES / (P2M_PER_PAGE * P2M_MID_PER_PAGE))); |
64 | 190 | ||
191 | /* We might hit two boundary violations at the start and end, at max each | ||
192 | * boundary violation will require three middle nodes. */ | ||
193 | RESERVE_BRK(p2m_mid_identity, PAGE_SIZE * 2 * 3); | ||
194 | |||
65 | static inline unsigned p2m_top_index(unsigned long pfn) | 195 | static inline unsigned p2m_top_index(unsigned long pfn) |
66 | { | 196 | { |
67 | BUG_ON(pfn >= MAX_P2M_PFN); | 197 | BUG_ON(pfn >= MAX_P2M_PFN); |
@@ -136,7 +266,7 @@ static void p2m_init(unsigned long *p2m) | |||
136 | * - After resume we're called from within stop_machine, but the mfn | 266 | * - After resume we're called from within stop_machine, but the mfn |
137 | * tree should alreay be completely allocated. | 267 | * tree should alreay be completely allocated. |
138 | */ | 268 | */ |
139 | void xen_build_mfn_list_list(void) | 269 | void __ref xen_build_mfn_list_list(void) |
140 | { | 270 | { |
141 | unsigned long pfn; | 271 | unsigned long pfn; |
142 | 272 | ||
@@ -221,6 +351,9 @@ void __init xen_build_dynamic_phys_to_machine(void) | |||
221 | p2m_top = extend_brk(PAGE_SIZE, PAGE_SIZE); | 351 | p2m_top = extend_brk(PAGE_SIZE, PAGE_SIZE); |
222 | p2m_top_init(p2m_top); | 352 | p2m_top_init(p2m_top); |
223 | 353 | ||
354 | p2m_identity = extend_brk(PAGE_SIZE, PAGE_SIZE); | ||
355 | p2m_init(p2m_identity); | ||
356 | |||
224 | /* | 357 | /* |
225 | * The domain builder gives us a pre-constructed p2m array in | 358 | * The domain builder gives us a pre-constructed p2m array in |
226 | * mfn_list for all the pages initially given to us, so we just | 359 | * mfn_list for all the pages initially given to us, so we just |
@@ -266,6 +399,14 @@ unsigned long get_phys_to_machine(unsigned long pfn) | |||
266 | mididx = p2m_mid_index(pfn); | 399 | mididx = p2m_mid_index(pfn); |
267 | idx = p2m_index(pfn); | 400 | idx = p2m_index(pfn); |
268 | 401 | ||
402 | /* | ||
403 | * The INVALID_P2M_ENTRY is filled in both p2m_*identity | ||
404 | * and in p2m_*missing, so returning the INVALID_P2M_ENTRY | ||
405 | * would be wrong. | ||
406 | */ | ||
407 | if (p2m_top[topidx][mididx] == p2m_identity) | ||
408 | return IDENTITY_FRAME(pfn); | ||
409 | |||
269 | return p2m_top[topidx][mididx][idx]; | 410 | return p2m_top[topidx][mididx][idx]; |
270 | } | 411 | } |
271 | EXPORT_SYMBOL_GPL(get_phys_to_machine); | 412 | EXPORT_SYMBOL_GPL(get_phys_to_machine); |
@@ -335,9 +476,11 @@ static bool alloc_p2m(unsigned long pfn) | |||
335 | p2m_top_mfn_p[topidx] = mid_mfn; | 476 | p2m_top_mfn_p[topidx] = mid_mfn; |
336 | } | 477 | } |
337 | 478 | ||
338 | if (p2m_top[topidx][mididx] == p2m_missing) { | 479 | if (p2m_top[topidx][mididx] == p2m_identity || |
480 | p2m_top[topidx][mididx] == p2m_missing) { | ||
339 | /* p2m leaf page is missing */ | 481 | /* p2m leaf page is missing */ |
340 | unsigned long *p2m; | 482 | unsigned long *p2m; |
483 | unsigned long *p2m_orig = p2m_top[topidx][mididx]; | ||
341 | 484 | ||
342 | p2m = alloc_p2m_page(); | 485 | p2m = alloc_p2m_page(); |
343 | if (!p2m) | 486 | if (!p2m) |
@@ -345,7 +488,7 @@ static bool alloc_p2m(unsigned long pfn) | |||
345 | 488 | ||
346 | p2m_init(p2m); | 489 | p2m_init(p2m); |
347 | 490 | ||
348 | if (cmpxchg(&mid[mididx], p2m_missing, p2m) != p2m_missing) | 491 | if (cmpxchg(&mid[mididx], p2m_orig, p2m) != p2m_orig) |
349 | free_p2m_page(p2m); | 492 | free_p2m_page(p2m); |
350 | else | 493 | else |
351 | mid_mfn[mididx] = virt_to_mfn(p2m); | 494 | mid_mfn[mididx] = virt_to_mfn(p2m); |
@@ -354,11 +497,91 @@ static bool alloc_p2m(unsigned long pfn) | |||
354 | return true; | 497 | return true; |
355 | } | 498 | } |
356 | 499 | ||
500 | bool __early_alloc_p2m(unsigned long pfn) | ||
501 | { | ||
502 | unsigned topidx, mididx, idx; | ||
503 | |||
504 | topidx = p2m_top_index(pfn); | ||
505 | mididx = p2m_mid_index(pfn); | ||
506 | idx = p2m_index(pfn); | ||
507 | |||
508 | /* Pfff.. No boundary cross-over, lets get out. */ | ||
509 | if (!idx) | ||
510 | return false; | ||
511 | |||
512 | WARN(p2m_top[topidx][mididx] == p2m_identity, | ||
513 | "P2M[%d][%d] == IDENTITY, should be MISSING (or alloced)!\n", | ||
514 | topidx, mididx); | ||
515 | |||
516 | /* | ||
517 | * Could be done by xen_build_dynamic_phys_to_machine.. | ||
518 | */ | ||
519 | if (p2m_top[topidx][mididx] != p2m_missing) | ||
520 | return false; | ||
521 | |||
522 | /* Boundary cross-over for the edges: */ | ||
523 | if (idx) { | ||
524 | unsigned long *p2m = extend_brk(PAGE_SIZE, PAGE_SIZE); | ||
525 | |||
526 | p2m_init(p2m); | ||
527 | |||
528 | p2m_top[topidx][mididx] = p2m; | ||
529 | |||
530 | } | ||
531 | return idx != 0; | ||
532 | } | ||
533 | unsigned long set_phys_range_identity(unsigned long pfn_s, | ||
534 | unsigned long pfn_e) | ||
535 | { | ||
536 | unsigned long pfn; | ||
537 | |||
538 | if (unlikely(pfn_s >= MAX_P2M_PFN || pfn_e >= MAX_P2M_PFN)) | ||
539 | return 0; | ||
540 | |||
541 | if (unlikely(xen_feature(XENFEAT_auto_translated_physmap))) | ||
542 | return pfn_e - pfn_s; | ||
543 | |||
544 | if (pfn_s > pfn_e) | ||
545 | return 0; | ||
546 | |||
547 | for (pfn = (pfn_s & ~(P2M_MID_PER_PAGE * P2M_PER_PAGE - 1)); | ||
548 | pfn < ALIGN(pfn_e, (P2M_MID_PER_PAGE * P2M_PER_PAGE)); | ||
549 | pfn += P2M_MID_PER_PAGE * P2M_PER_PAGE) | ||
550 | { | ||
551 | unsigned topidx = p2m_top_index(pfn); | ||
552 | if (p2m_top[topidx] == p2m_mid_missing) { | ||
553 | unsigned long **mid = extend_brk(PAGE_SIZE, PAGE_SIZE); | ||
554 | |||
555 | p2m_mid_init(mid); | ||
556 | |||
557 | p2m_top[topidx] = mid; | ||
558 | } | ||
559 | } | ||
560 | |||
561 | __early_alloc_p2m(pfn_s); | ||
562 | __early_alloc_p2m(pfn_e); | ||
563 | |||
564 | for (pfn = pfn_s; pfn < pfn_e; pfn++) | ||
565 | if (!__set_phys_to_machine(pfn, IDENTITY_FRAME(pfn))) | ||
566 | break; | ||
567 | |||
568 | if (!WARN((pfn - pfn_s) != (pfn_e - pfn_s), | ||
569 | "Identity mapping failed. We are %ld short of 1-1 mappings!\n", | ||
570 | (pfn_e - pfn_s) - (pfn - pfn_s))) | ||
571 | printk(KERN_DEBUG "1-1 mapping on %lx->%lx\n", pfn_s, pfn); | ||
572 | |||
573 | return pfn - pfn_s; | ||
574 | } | ||
575 | |||
357 | /* Try to install p2m mapping; fail if intermediate bits missing */ | 576 | /* Try to install p2m mapping; fail if intermediate bits missing */ |
358 | bool __set_phys_to_machine(unsigned long pfn, unsigned long mfn) | 577 | bool __set_phys_to_machine(unsigned long pfn, unsigned long mfn) |
359 | { | 578 | { |
360 | unsigned topidx, mididx, idx; | 579 | unsigned topidx, mididx, idx; |
361 | 580 | ||
581 | if (unlikely(xen_feature(XENFEAT_auto_translated_physmap))) { | ||
582 | BUG_ON(pfn != mfn && mfn != INVALID_P2M_ENTRY); | ||
583 | return true; | ||
584 | } | ||
362 | if (unlikely(pfn >= MAX_P2M_PFN)) { | 585 | if (unlikely(pfn >= MAX_P2M_PFN)) { |
363 | BUG_ON(mfn != INVALID_P2M_ENTRY); | 586 | BUG_ON(mfn != INVALID_P2M_ENTRY); |
364 | return true; | 587 | return true; |
@@ -368,6 +591,21 @@ bool __set_phys_to_machine(unsigned long pfn, unsigned long mfn) | |||
368 | mididx = p2m_mid_index(pfn); | 591 | mididx = p2m_mid_index(pfn); |
369 | idx = p2m_index(pfn); | 592 | idx = p2m_index(pfn); |
370 | 593 | ||
594 | /* For sparse holes were the p2m leaf has real PFN along with | ||
595 | * PCI holes, stick in the PFN as the MFN value. | ||
596 | */ | ||
597 | if (mfn != INVALID_P2M_ENTRY && (mfn & IDENTITY_FRAME_BIT)) { | ||
598 | if (p2m_top[topidx][mididx] == p2m_identity) | ||
599 | return true; | ||
600 | |||
601 | /* Swap over from MISSING to IDENTITY if needed. */ | ||
602 | if (p2m_top[topidx][mididx] == p2m_missing) { | ||
603 | WARN_ON(cmpxchg(&p2m_top[topidx][mididx], p2m_missing, | ||
604 | p2m_identity) != p2m_missing); | ||
605 | return true; | ||
606 | } | ||
607 | } | ||
608 | |||
371 | if (p2m_top[topidx][mididx] == p2m_missing) | 609 | if (p2m_top[topidx][mididx] == p2m_missing) |
372 | return mfn == INVALID_P2M_ENTRY; | 610 | return mfn == INVALID_P2M_ENTRY; |
373 | 611 | ||
@@ -378,11 +616,6 @@ bool __set_phys_to_machine(unsigned long pfn, unsigned long mfn) | |||
378 | 616 | ||
379 | bool set_phys_to_machine(unsigned long pfn, unsigned long mfn) | 617 | bool set_phys_to_machine(unsigned long pfn, unsigned long mfn) |
380 | { | 618 | { |
381 | if (unlikely(xen_feature(XENFEAT_auto_translated_physmap))) { | ||
382 | BUG_ON(pfn != mfn && mfn != INVALID_P2M_ENTRY); | ||
383 | return true; | ||
384 | } | ||
385 | |||
386 | if (unlikely(!__set_phys_to_machine(pfn, mfn))) { | 619 | if (unlikely(!__set_phys_to_machine(pfn, mfn))) { |
387 | if (!alloc_p2m(pfn)) | 620 | if (!alloc_p2m(pfn)) |
388 | return false; | 621 | return false; |
@@ -421,7 +654,7 @@ int m2p_add_override(unsigned long mfn, struct page *page) | |||
421 | { | 654 | { |
422 | unsigned long flags; | 655 | unsigned long flags; |
423 | unsigned long pfn; | 656 | unsigned long pfn; |
424 | unsigned long address; | 657 | unsigned long uninitialized_var(address); |
425 | unsigned level; | 658 | unsigned level; |
426 | pte_t *ptep = NULL; | 659 | pte_t *ptep = NULL; |
427 | 660 | ||
@@ -455,7 +688,7 @@ int m2p_remove_override(struct page *page) | |||
455 | unsigned long flags; | 688 | unsigned long flags; |
456 | unsigned long mfn; | 689 | unsigned long mfn; |
457 | unsigned long pfn; | 690 | unsigned long pfn; |
458 | unsigned long address; | 691 | unsigned long uninitialized_var(address); |
459 | unsigned level; | 692 | unsigned level; |
460 | pte_t *ptep = NULL; | 693 | pte_t *ptep = NULL; |
461 | 694 | ||
@@ -520,3 +753,80 @@ unsigned long m2p_find_override_pfn(unsigned long mfn, unsigned long pfn) | |||
520 | return ret; | 753 | return ret; |
521 | } | 754 | } |
522 | EXPORT_SYMBOL_GPL(m2p_find_override_pfn); | 755 | EXPORT_SYMBOL_GPL(m2p_find_override_pfn); |
756 | |||
757 | #ifdef CONFIG_XEN_DEBUG_FS | ||
758 | |||
759 | int p2m_dump_show(struct seq_file *m, void *v) | ||
760 | { | ||
761 | static const char * const level_name[] = { "top", "middle", | ||
762 | "entry", "abnormal" }; | ||
763 | static const char * const type_name[] = { "identity", "missing", | ||
764 | "pfn", "abnormal"}; | ||
765 | #define TYPE_IDENTITY 0 | ||
766 | #define TYPE_MISSING 1 | ||
767 | #define TYPE_PFN 2 | ||
768 | #define TYPE_UNKNOWN 3 | ||
769 | unsigned long pfn, prev_pfn_type = 0, prev_pfn_level = 0; | ||
770 | unsigned int uninitialized_var(prev_level); | ||
771 | unsigned int uninitialized_var(prev_type); | ||
772 | |||
773 | if (!p2m_top) | ||
774 | return 0; | ||
775 | |||
776 | for (pfn = 0; pfn < MAX_DOMAIN_PAGES; pfn++) { | ||
777 | unsigned topidx = p2m_top_index(pfn); | ||
778 | unsigned mididx = p2m_mid_index(pfn); | ||
779 | unsigned idx = p2m_index(pfn); | ||
780 | unsigned lvl, type; | ||
781 | |||
782 | lvl = 4; | ||
783 | type = TYPE_UNKNOWN; | ||
784 | if (p2m_top[topidx] == p2m_mid_missing) { | ||
785 | lvl = 0; type = TYPE_MISSING; | ||
786 | } else if (p2m_top[topidx] == NULL) { | ||
787 | lvl = 0; type = TYPE_UNKNOWN; | ||
788 | } else if (p2m_top[topidx][mididx] == NULL) { | ||
789 | lvl = 1; type = TYPE_UNKNOWN; | ||
790 | } else if (p2m_top[topidx][mididx] == p2m_identity) { | ||
791 | lvl = 1; type = TYPE_IDENTITY; | ||
792 | } else if (p2m_top[topidx][mididx] == p2m_missing) { | ||
793 | lvl = 1; type = TYPE_MISSING; | ||
794 | } else if (p2m_top[topidx][mididx][idx] == 0) { | ||
795 | lvl = 2; type = TYPE_UNKNOWN; | ||
796 | } else if (p2m_top[topidx][mididx][idx] == IDENTITY_FRAME(pfn)) { | ||
797 | lvl = 2; type = TYPE_IDENTITY; | ||
798 | } else if (p2m_top[topidx][mididx][idx] == INVALID_P2M_ENTRY) { | ||
799 | lvl = 2; type = TYPE_MISSING; | ||
800 | } else if (p2m_top[topidx][mididx][idx] == pfn) { | ||
801 | lvl = 2; type = TYPE_PFN; | ||
802 | } else if (p2m_top[topidx][mididx][idx] != pfn) { | ||
803 | lvl = 2; type = TYPE_PFN; | ||
804 | } | ||
805 | if (pfn == 0) { | ||
806 | prev_level = lvl; | ||
807 | prev_type = type; | ||
808 | } | ||
809 | if (pfn == MAX_DOMAIN_PAGES-1) { | ||
810 | lvl = 3; | ||
811 | type = TYPE_UNKNOWN; | ||
812 | } | ||
813 | if (prev_type != type) { | ||
814 | seq_printf(m, " [0x%lx->0x%lx] %s\n", | ||
815 | prev_pfn_type, pfn, type_name[prev_type]); | ||
816 | prev_pfn_type = pfn; | ||
817 | prev_type = type; | ||
818 | } | ||
819 | if (prev_level != lvl) { | ||
820 | seq_printf(m, " [0x%lx->0x%lx] level %s\n", | ||
821 | prev_pfn_level, pfn, level_name[prev_level]); | ||
822 | prev_pfn_level = pfn; | ||
823 | prev_level = lvl; | ||
824 | } | ||
825 | } | ||
826 | return 0; | ||
827 | #undef TYPE_IDENTITY | ||
828 | #undef TYPE_MISSING | ||
829 | #undef TYPE_PFN | ||
830 | #undef TYPE_UNKNOWN | ||
831 | } | ||
832 | #endif | ||
diff --git a/arch/x86/xen/setup.c b/arch/x86/xen/setup.c index a8a66a50d446..fa0269a99377 100644 --- a/arch/x86/xen/setup.c +++ b/arch/x86/xen/setup.c | |||
@@ -52,6 +52,8 @@ phys_addr_t xen_extra_mem_start, xen_extra_mem_size; | |||
52 | 52 | ||
53 | static __init void xen_add_extra_mem(unsigned long pages) | 53 | static __init void xen_add_extra_mem(unsigned long pages) |
54 | { | 54 | { |
55 | unsigned long pfn; | ||
56 | |||
55 | u64 size = (u64)pages * PAGE_SIZE; | 57 | u64 size = (u64)pages * PAGE_SIZE; |
56 | u64 extra_start = xen_extra_mem_start + xen_extra_mem_size; | 58 | u64 extra_start = xen_extra_mem_start + xen_extra_mem_size; |
57 | 59 | ||
@@ -66,6 +68,9 @@ static __init void xen_add_extra_mem(unsigned long pages) | |||
66 | xen_extra_mem_size += size; | 68 | xen_extra_mem_size += size; |
67 | 69 | ||
68 | xen_max_p2m_pfn = PFN_DOWN(extra_start + size); | 70 | xen_max_p2m_pfn = PFN_DOWN(extra_start + size); |
71 | |||
72 | for (pfn = PFN_DOWN(extra_start); pfn <= xen_max_p2m_pfn; pfn++) | ||
73 | __set_phys_to_machine(pfn, INVALID_P2M_ENTRY); | ||
69 | } | 74 | } |
70 | 75 | ||
71 | static unsigned long __init xen_release_chunk(phys_addr_t start_addr, | 76 | static unsigned long __init xen_release_chunk(phys_addr_t start_addr, |
@@ -104,7 +109,7 @@ static unsigned long __init xen_release_chunk(phys_addr_t start_addr, | |||
104 | WARN(ret != 1, "Failed to release memory %lx-%lx err=%d\n", | 109 | WARN(ret != 1, "Failed to release memory %lx-%lx err=%d\n", |
105 | start, end, ret); | 110 | start, end, ret); |
106 | if (ret == 1) { | 111 | if (ret == 1) { |
107 | set_phys_to_machine(pfn, INVALID_P2M_ENTRY); | 112 | __set_phys_to_machine(pfn, INVALID_P2M_ENTRY); |
108 | len++; | 113 | len++; |
109 | } | 114 | } |
110 | } | 115 | } |
@@ -138,12 +143,55 @@ static unsigned long __init xen_return_unused_memory(unsigned long max_pfn, | |||
138 | return released; | 143 | return released; |
139 | } | 144 | } |
140 | 145 | ||
146 | static unsigned long __init xen_set_identity(const struct e820entry *list, | ||
147 | ssize_t map_size) | ||
148 | { | ||
149 | phys_addr_t last = xen_initial_domain() ? 0 : ISA_END_ADDRESS; | ||
150 | phys_addr_t start_pci = last; | ||
151 | const struct e820entry *entry; | ||
152 | unsigned long identity = 0; | ||
153 | int i; | ||
154 | |||
155 | for (i = 0, entry = list; i < map_size; i++, entry++) { | ||
156 | phys_addr_t start = entry->addr; | ||
157 | phys_addr_t end = start + entry->size; | ||
158 | |||
159 | if (start < last) | ||
160 | start = last; | ||
161 | |||
162 | if (end <= start) | ||
163 | continue; | ||
164 | |||
165 | /* Skip over the 1MB region. */ | ||
166 | if (last > end) | ||
167 | continue; | ||
168 | |||
169 | if (entry->type == E820_RAM) { | ||
170 | if (start > start_pci) | ||
171 | identity += set_phys_range_identity( | ||
172 | PFN_UP(start_pci), PFN_DOWN(start)); | ||
173 | |||
174 | /* Without saving 'last' we would gooble RAM too | ||
175 | * at the end of the loop. */ | ||
176 | last = end; | ||
177 | start_pci = end; | ||
178 | continue; | ||
179 | } | ||
180 | start_pci = min(start, start_pci); | ||
181 | last = end; | ||
182 | } | ||
183 | if (last > start_pci) | ||
184 | identity += set_phys_range_identity( | ||
185 | PFN_UP(start_pci), PFN_DOWN(last)); | ||
186 | return identity; | ||
187 | } | ||
141 | /** | 188 | /** |
142 | * machine_specific_memory_setup - Hook for machine specific memory setup. | 189 | * machine_specific_memory_setup - Hook for machine specific memory setup. |
143 | **/ | 190 | **/ |
144 | char * __init xen_memory_setup(void) | 191 | char * __init xen_memory_setup(void) |
145 | { | 192 | { |
146 | static struct e820entry map[E820MAX] __initdata; | 193 | static struct e820entry map[E820MAX] __initdata; |
194 | static struct e820entry map_raw[E820MAX] __initdata; | ||
147 | 195 | ||
148 | unsigned long max_pfn = xen_start_info->nr_pages; | 196 | unsigned long max_pfn = xen_start_info->nr_pages; |
149 | unsigned long long mem_end; | 197 | unsigned long long mem_end; |
@@ -151,6 +199,7 @@ char * __init xen_memory_setup(void) | |||
151 | struct xen_memory_map memmap; | 199 | struct xen_memory_map memmap; |
152 | unsigned long extra_pages = 0; | 200 | unsigned long extra_pages = 0; |
153 | unsigned long extra_limit; | 201 | unsigned long extra_limit; |
202 | unsigned long identity_pages = 0; | ||
154 | int i; | 203 | int i; |
155 | int op; | 204 | int op; |
156 | 205 | ||
@@ -176,6 +225,7 @@ char * __init xen_memory_setup(void) | |||
176 | } | 225 | } |
177 | BUG_ON(rc); | 226 | BUG_ON(rc); |
178 | 227 | ||
228 | memcpy(map_raw, map, sizeof(map)); | ||
179 | e820.nr_map = 0; | 229 | e820.nr_map = 0; |
180 | xen_extra_mem_start = mem_end; | 230 | xen_extra_mem_start = mem_end; |
181 | for (i = 0; i < memmap.nr_entries; i++) { | 231 | for (i = 0; i < memmap.nr_entries; i++) { |
@@ -194,6 +244,15 @@ char * __init xen_memory_setup(void) | |||
194 | end -= delta; | 244 | end -= delta; |
195 | 245 | ||
196 | extra_pages += PFN_DOWN(delta); | 246 | extra_pages += PFN_DOWN(delta); |
247 | /* | ||
248 | * Set RAM below 4GB that is not for us to be unusable. | ||
249 | * This prevents "System RAM" address space from being | ||
250 | * used as potential resource for I/O address (happens | ||
251 | * when 'allocate_resource' is called). | ||
252 | */ | ||
253 | if (delta && | ||
254 | (xen_initial_domain() && end < 0x100000000ULL)) | ||
255 | e820_add_region(end, delta, E820_UNUSABLE); | ||
197 | } | 256 | } |
198 | 257 | ||
199 | if (map[i].size > 0 && end > xen_extra_mem_start) | 258 | if (map[i].size > 0 && end > xen_extra_mem_start) |
@@ -251,6 +310,13 @@ char * __init xen_memory_setup(void) | |||
251 | 310 | ||
252 | xen_add_extra_mem(extra_pages); | 311 | xen_add_extra_mem(extra_pages); |
253 | 312 | ||
313 | /* | ||
314 | * Set P2M for all non-RAM pages and E820 gaps to be identity | ||
315 | * type PFNs. We supply it with the non-sanitized version | ||
316 | * of the E820. | ||
317 | */ | ||
318 | identity_pages = xen_set_identity(map_raw, memmap.nr_entries); | ||
319 | printk(KERN_INFO "Set %ld page(s) to 1-1 mapping.\n", identity_pages); | ||
254 | return "Xen"; | 320 | return "Xen"; |
255 | } | 321 | } |
256 | 322 | ||
diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c index 72a4c7959045..30612441ed99 100644 --- a/arch/x86/xen/smp.c +++ b/arch/x86/xen/smp.c | |||
@@ -509,3 +509,41 @@ void __init xen_smp_init(void) | |||
509 | xen_fill_possible_map(); | 509 | xen_fill_possible_map(); |
510 | xen_init_spinlocks(); | 510 | xen_init_spinlocks(); |
511 | } | 511 | } |
512 | |||
513 | static void __init xen_hvm_smp_prepare_cpus(unsigned int max_cpus) | ||
514 | { | ||
515 | native_smp_prepare_cpus(max_cpus); | ||
516 | WARN_ON(xen_smp_intr_init(0)); | ||
517 | |||
518 | if (!xen_have_vector_callback) | ||
519 | return; | ||
520 | xen_init_lock_cpu(0); | ||
521 | xen_init_spinlocks(); | ||
522 | } | ||
523 | |||
524 | static int __cpuinit xen_hvm_cpu_up(unsigned int cpu) | ||
525 | { | ||
526 | int rc; | ||
527 | rc = native_cpu_up(cpu); | ||
528 | WARN_ON (xen_smp_intr_init(cpu)); | ||
529 | return rc; | ||
530 | } | ||
531 | |||
532 | static void xen_hvm_cpu_die(unsigned int cpu) | ||
533 | { | ||
534 | unbind_from_irqhandler(per_cpu(xen_resched_irq, cpu), NULL); | ||
535 | unbind_from_irqhandler(per_cpu(xen_callfunc_irq, cpu), NULL); | ||
536 | unbind_from_irqhandler(per_cpu(xen_debug_irq, cpu), NULL); | ||
537 | unbind_from_irqhandler(per_cpu(xen_callfuncsingle_irq, cpu), NULL); | ||
538 | native_cpu_die(cpu); | ||
539 | } | ||
540 | |||
541 | void __init xen_hvm_smp_init(void) | ||
542 | { | ||
543 | smp_ops.smp_prepare_cpus = xen_hvm_smp_prepare_cpus; | ||
544 | smp_ops.smp_send_reschedule = xen_smp_send_reschedule; | ||
545 | smp_ops.cpu_up = xen_hvm_cpu_up; | ||
546 | smp_ops.cpu_die = xen_hvm_cpu_die; | ||
547 | smp_ops.send_call_func_ipi = xen_smp_send_call_function_ipi; | ||
548 | smp_ops.send_call_func_single_ipi = xen_smp_send_call_function_single_ipi; | ||
549 | } | ||
diff --git a/arch/x86/xen/suspend.c b/arch/x86/xen/suspend.c index 9bbd63a129b5..45329c8c226e 100644 --- a/arch/x86/xen/suspend.c +++ b/arch/x86/xen/suspend.c | |||
@@ -12,7 +12,7 @@ | |||
12 | #include "xen-ops.h" | 12 | #include "xen-ops.h" |
13 | #include "mmu.h" | 13 | #include "mmu.h" |
14 | 14 | ||
15 | void xen_pre_suspend(void) | 15 | void xen_arch_pre_suspend(void) |
16 | { | 16 | { |
17 | xen_start_info->store_mfn = mfn_to_pfn(xen_start_info->store_mfn); | 17 | xen_start_info->store_mfn = mfn_to_pfn(xen_start_info->store_mfn); |
18 | xen_start_info->console.domU.mfn = | 18 | xen_start_info->console.domU.mfn = |
@@ -26,8 +26,9 @@ void xen_pre_suspend(void) | |||
26 | BUG(); | 26 | BUG(); |
27 | } | 27 | } |
28 | 28 | ||
29 | void xen_hvm_post_suspend(int suspend_cancelled) | 29 | void xen_arch_hvm_post_suspend(int suspend_cancelled) |
30 | { | 30 | { |
31 | #ifdef CONFIG_XEN_PVHVM | ||
31 | int cpu; | 32 | int cpu; |
32 | xen_hvm_init_shared_info(); | 33 | xen_hvm_init_shared_info(); |
33 | xen_callback_vector(); | 34 | xen_callback_vector(); |
@@ -37,9 +38,10 @@ void xen_hvm_post_suspend(int suspend_cancelled) | |||
37 | xen_setup_runstate_info(cpu); | 38 | xen_setup_runstate_info(cpu); |
38 | } | 39 | } |
39 | } | 40 | } |
41 | #endif | ||
40 | } | 42 | } |
41 | 43 | ||
42 | void xen_post_suspend(int suspend_cancelled) | 44 | void xen_arch_post_suspend(int suspend_cancelled) |
43 | { | 45 | { |
44 | xen_build_mfn_list_list(); | 46 | xen_build_mfn_list_list(); |
45 | 47 | ||
diff --git a/arch/x86/xen/time.c b/arch/x86/xen/time.c index 067759e3d6a5..2e2d370a47b1 100644 --- a/arch/x86/xen/time.c +++ b/arch/x86/xen/time.c | |||
@@ -397,7 +397,9 @@ void xen_setup_timer(int cpu) | |||
397 | name = "<timer kasprintf failed>"; | 397 | name = "<timer kasprintf failed>"; |
398 | 398 | ||
399 | irq = bind_virq_to_irqhandler(VIRQ_TIMER, cpu, xen_timer_interrupt, | 399 | irq = bind_virq_to_irqhandler(VIRQ_TIMER, cpu, xen_timer_interrupt, |
400 | IRQF_DISABLED|IRQF_PERCPU|IRQF_NOBALANCING|IRQF_TIMER, | 400 | IRQF_DISABLED|IRQF_PERCPU| |
401 | IRQF_NOBALANCING|IRQF_TIMER| | ||
402 | IRQF_FORCE_RESUME, | ||
401 | name, NULL); | 403 | name, NULL); |
402 | 404 | ||
403 | evt = &per_cpu(xen_clock_events, cpu); | 405 | evt = &per_cpu(xen_clock_events, cpu); |
diff --git a/arch/x86/xen/xen-ops.h b/arch/x86/xen/xen-ops.h index 9d41bf985757..3112f55638c4 100644 --- a/arch/x86/xen/xen-ops.h +++ b/arch/x86/xen/xen-ops.h | |||
@@ -64,10 +64,12 @@ void xen_setup_vcpu_info_placement(void); | |||
64 | 64 | ||
65 | #ifdef CONFIG_SMP | 65 | #ifdef CONFIG_SMP |
66 | void xen_smp_init(void); | 66 | void xen_smp_init(void); |
67 | void __init xen_hvm_smp_init(void); | ||
67 | 68 | ||
68 | extern cpumask_var_t xen_cpu_initialized_map; | 69 | extern cpumask_var_t xen_cpu_initialized_map; |
69 | #else | 70 | #else |
70 | static inline void xen_smp_init(void) {} | 71 | static inline void xen_smp_init(void) {} |
72 | static inline void xen_hvm_smp_init(void) {} | ||
71 | #endif | 73 | #endif |
72 | 74 | ||
73 | #ifdef CONFIG_PARAVIRT_SPINLOCKS | 75 | #ifdef CONFIG_PARAVIRT_SPINLOCKS |
diff --git a/block/blk-lib.c b/block/blk-lib.c index eec78becb355..bd3e8df4d5e2 100644 --- a/block/blk-lib.c +++ b/block/blk-lib.c | |||
@@ -109,7 +109,6 @@ struct bio_batch | |||
109 | atomic_t done; | 109 | atomic_t done; |
110 | unsigned long flags; | 110 | unsigned long flags; |
111 | struct completion *wait; | 111 | struct completion *wait; |
112 | bio_end_io_t *end_io; | ||
113 | }; | 112 | }; |
114 | 113 | ||
115 | static void bio_batch_end_io(struct bio *bio, int err) | 114 | static void bio_batch_end_io(struct bio *bio, int err) |
@@ -122,12 +121,9 @@ static void bio_batch_end_io(struct bio *bio, int err) | |||
122 | else | 121 | else |
123 | clear_bit(BIO_UPTODATE, &bb->flags); | 122 | clear_bit(BIO_UPTODATE, &bb->flags); |
124 | } | 123 | } |
125 | if (bb) { | 124 | if (bb) |
126 | if (bb->end_io) | 125 | if (atomic_dec_and_test(&bb->done)) |
127 | bb->end_io(bio, err); | 126 | complete(bb->wait); |
128 | atomic_inc(&bb->done); | ||
129 | complete(bb->wait); | ||
130 | } | ||
131 | bio_put(bio); | 127 | bio_put(bio); |
132 | } | 128 | } |
133 | 129 | ||
@@ -150,13 +146,12 @@ int blkdev_issue_zeroout(struct block_device *bdev, sector_t sector, | |||
150 | int ret; | 146 | int ret; |
151 | struct bio *bio; | 147 | struct bio *bio; |
152 | struct bio_batch bb; | 148 | struct bio_batch bb; |
153 | unsigned int sz, issued = 0; | 149 | unsigned int sz; |
154 | DECLARE_COMPLETION_ONSTACK(wait); | 150 | DECLARE_COMPLETION_ONSTACK(wait); |
155 | 151 | ||
156 | atomic_set(&bb.done, 0); | 152 | atomic_set(&bb.done, 1); |
157 | bb.flags = 1 << BIO_UPTODATE; | 153 | bb.flags = 1 << BIO_UPTODATE; |
158 | bb.wait = &wait; | 154 | bb.wait = &wait; |
159 | bb.end_io = NULL; | ||
160 | 155 | ||
161 | submit: | 156 | submit: |
162 | ret = 0; | 157 | ret = 0; |
@@ -185,12 +180,12 @@ submit: | |||
185 | break; | 180 | break; |
186 | } | 181 | } |
187 | ret = 0; | 182 | ret = 0; |
188 | issued++; | 183 | atomic_inc(&bb.done); |
189 | submit_bio(WRITE, bio); | 184 | submit_bio(WRITE, bio); |
190 | } | 185 | } |
191 | 186 | ||
192 | /* Wait for bios in-flight */ | 187 | /* Wait for bios in-flight */ |
193 | while (issued != atomic_read(&bb.done)) | 188 | if (!atomic_dec_and_test(&bb.done)) |
194 | wait_for_completion(&wait); | 189 | wait_for_completion(&wait); |
195 | 190 | ||
196 | if (!test_bit(BIO_UPTODATE, &bb.flags)) | 191 | if (!test_bit(BIO_UPTODATE, &bb.flags)) |
diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c index d7aa39e349a6..9cb8668ff5f4 100644 --- a/drivers/block/xen-blkfront.c +++ b/drivers/block/xen-blkfront.c | |||
@@ -120,6 +120,10 @@ static DEFINE_SPINLOCK(minor_lock); | |||
120 | #define EXTENDED (1<<EXT_SHIFT) | 120 | #define EXTENDED (1<<EXT_SHIFT) |
121 | #define VDEV_IS_EXTENDED(dev) ((dev)&(EXTENDED)) | 121 | #define VDEV_IS_EXTENDED(dev) ((dev)&(EXTENDED)) |
122 | #define BLKIF_MINOR_EXT(dev) ((dev)&(~EXTENDED)) | 122 | #define BLKIF_MINOR_EXT(dev) ((dev)&(~EXTENDED)) |
123 | #define EMULATED_HD_DISK_MINOR_OFFSET (0) | ||
124 | #define EMULATED_HD_DISK_NAME_OFFSET (EMULATED_HD_DISK_MINOR_OFFSET / 256) | ||
125 | #define EMULATED_SD_DISK_MINOR_OFFSET (EMULATED_HD_DISK_MINOR_OFFSET + (4 * 16)) | ||
126 | #define EMULATED_SD_DISK_NAME_OFFSET (EMULATED_HD_DISK_NAME_OFFSET + 4) | ||
123 | 127 | ||
124 | #define DEV_NAME "xvd" /* name in /dev */ | 128 | #define DEV_NAME "xvd" /* name in /dev */ |
125 | 129 | ||
@@ -281,7 +285,7 @@ static int blkif_queue_request(struct request *req) | |||
281 | info->shadow[id].request = req; | 285 | info->shadow[id].request = req; |
282 | 286 | ||
283 | ring_req->id = id; | 287 | ring_req->id = id; |
284 | ring_req->sector_number = (blkif_sector_t)blk_rq_pos(req); | 288 | ring_req->u.rw.sector_number = (blkif_sector_t)blk_rq_pos(req); |
285 | ring_req->handle = info->handle; | 289 | ring_req->handle = info->handle; |
286 | 290 | ||
287 | ring_req->operation = rq_data_dir(req) ? | 291 | ring_req->operation = rq_data_dir(req) ? |
@@ -317,7 +321,7 @@ static int blkif_queue_request(struct request *req) | |||
317 | rq_data_dir(req) ); | 321 | rq_data_dir(req) ); |
318 | 322 | ||
319 | info->shadow[id].frame[i] = mfn_to_pfn(buffer_mfn); | 323 | info->shadow[id].frame[i] = mfn_to_pfn(buffer_mfn); |
320 | ring_req->seg[i] = | 324 | ring_req->u.rw.seg[i] = |
321 | (struct blkif_request_segment) { | 325 | (struct blkif_request_segment) { |
322 | .gref = ref, | 326 | .gref = ref, |
323 | .first_sect = fsect, | 327 | .first_sect = fsect, |
@@ -434,6 +438,65 @@ static void xlvbd_flush(struct blkfront_info *info) | |||
434 | info->feature_flush ? "enabled" : "disabled"); | 438 | info->feature_flush ? "enabled" : "disabled"); |
435 | } | 439 | } |
436 | 440 | ||
441 | static int xen_translate_vdev(int vdevice, int *minor, unsigned int *offset) | ||
442 | { | ||
443 | int major; | ||
444 | major = BLKIF_MAJOR(vdevice); | ||
445 | *minor = BLKIF_MINOR(vdevice); | ||
446 | switch (major) { | ||
447 | case XEN_IDE0_MAJOR: | ||
448 | *offset = (*minor / 64) + EMULATED_HD_DISK_NAME_OFFSET; | ||
449 | *minor = ((*minor / 64) * PARTS_PER_DISK) + | ||
450 | EMULATED_HD_DISK_MINOR_OFFSET; | ||
451 | break; | ||
452 | case XEN_IDE1_MAJOR: | ||
453 | *offset = (*minor / 64) + 2 + EMULATED_HD_DISK_NAME_OFFSET; | ||
454 | *minor = (((*minor / 64) + 2) * PARTS_PER_DISK) + | ||
455 | EMULATED_HD_DISK_MINOR_OFFSET; | ||
456 | break; | ||
457 | case XEN_SCSI_DISK0_MAJOR: | ||
458 | *offset = (*minor / PARTS_PER_DISK) + EMULATED_SD_DISK_NAME_OFFSET; | ||
459 | *minor = *minor + EMULATED_SD_DISK_MINOR_OFFSET; | ||
460 | break; | ||
461 | case XEN_SCSI_DISK1_MAJOR: | ||
462 | case XEN_SCSI_DISK2_MAJOR: | ||
463 | case XEN_SCSI_DISK3_MAJOR: | ||
464 | case XEN_SCSI_DISK4_MAJOR: | ||
465 | case XEN_SCSI_DISK5_MAJOR: | ||
466 | case XEN_SCSI_DISK6_MAJOR: | ||
467 | case XEN_SCSI_DISK7_MAJOR: | ||
468 | *offset = (*minor / PARTS_PER_DISK) + | ||
469 | ((major - XEN_SCSI_DISK1_MAJOR + 1) * 16) + | ||
470 | EMULATED_SD_DISK_NAME_OFFSET; | ||
471 | *minor = *minor + | ||
472 | ((major - XEN_SCSI_DISK1_MAJOR + 1) * 16 * PARTS_PER_DISK) + | ||
473 | EMULATED_SD_DISK_MINOR_OFFSET; | ||
474 | break; | ||
475 | case XEN_SCSI_DISK8_MAJOR: | ||
476 | case XEN_SCSI_DISK9_MAJOR: | ||
477 | case XEN_SCSI_DISK10_MAJOR: | ||
478 | case XEN_SCSI_DISK11_MAJOR: | ||
479 | case XEN_SCSI_DISK12_MAJOR: | ||
480 | case XEN_SCSI_DISK13_MAJOR: | ||
481 | case XEN_SCSI_DISK14_MAJOR: | ||
482 | case XEN_SCSI_DISK15_MAJOR: | ||
483 | *offset = (*minor / PARTS_PER_DISK) + | ||
484 | ((major - XEN_SCSI_DISK8_MAJOR + 8) * 16) + | ||
485 | EMULATED_SD_DISK_NAME_OFFSET; | ||
486 | *minor = *minor + | ||
487 | ((major - XEN_SCSI_DISK8_MAJOR + 8) * 16 * PARTS_PER_DISK) + | ||
488 | EMULATED_SD_DISK_MINOR_OFFSET; | ||
489 | break; | ||
490 | case XENVBD_MAJOR: | ||
491 | *offset = *minor / PARTS_PER_DISK; | ||
492 | break; | ||
493 | default: | ||
494 | printk(KERN_WARNING "blkfront: your disk configuration is " | ||
495 | "incorrect, please use an xvd device instead\n"); | ||
496 | return -ENODEV; | ||
497 | } | ||
498 | return 0; | ||
499 | } | ||
437 | 500 | ||
438 | static int xlvbd_alloc_gendisk(blkif_sector_t capacity, | 501 | static int xlvbd_alloc_gendisk(blkif_sector_t capacity, |
439 | struct blkfront_info *info, | 502 | struct blkfront_info *info, |
@@ -441,7 +504,7 @@ static int xlvbd_alloc_gendisk(blkif_sector_t capacity, | |||
441 | { | 504 | { |
442 | struct gendisk *gd; | 505 | struct gendisk *gd; |
443 | int nr_minors = 1; | 506 | int nr_minors = 1; |
444 | int err = -ENODEV; | 507 | int err; |
445 | unsigned int offset; | 508 | unsigned int offset; |
446 | int minor; | 509 | int minor; |
447 | int nr_parts; | 510 | int nr_parts; |
@@ -456,12 +519,20 @@ static int xlvbd_alloc_gendisk(blkif_sector_t capacity, | |||
456 | } | 519 | } |
457 | 520 | ||
458 | if (!VDEV_IS_EXTENDED(info->vdevice)) { | 521 | if (!VDEV_IS_EXTENDED(info->vdevice)) { |
459 | minor = BLKIF_MINOR(info->vdevice); | 522 | err = xen_translate_vdev(info->vdevice, &minor, &offset); |
460 | nr_parts = PARTS_PER_DISK; | 523 | if (err) |
524 | return err; | ||
525 | nr_parts = PARTS_PER_DISK; | ||
461 | } else { | 526 | } else { |
462 | minor = BLKIF_MINOR_EXT(info->vdevice); | 527 | minor = BLKIF_MINOR_EXT(info->vdevice); |
463 | nr_parts = PARTS_PER_EXT_DISK; | 528 | nr_parts = PARTS_PER_EXT_DISK; |
529 | offset = minor / nr_parts; | ||
530 | if (xen_hvm_domain() && offset <= EMULATED_HD_DISK_NAME_OFFSET + 4) | ||
531 | printk(KERN_WARNING "blkfront: vdevice 0x%x might conflict with " | ||
532 | "emulated IDE disks,\n\t choose an xvd device name" | ||
533 | "from xvde on\n", info->vdevice); | ||
464 | } | 534 | } |
535 | err = -ENODEV; | ||
465 | 536 | ||
466 | if ((minor % nr_parts) == 0) | 537 | if ((minor % nr_parts) == 0) |
467 | nr_minors = nr_parts; | 538 | nr_minors = nr_parts; |
@@ -475,8 +546,6 @@ static int xlvbd_alloc_gendisk(blkif_sector_t capacity, | |||
475 | if (gd == NULL) | 546 | if (gd == NULL) |
476 | goto release; | 547 | goto release; |
477 | 548 | ||
478 | offset = minor / nr_parts; | ||
479 | |||
480 | if (nr_minors > 1) { | 549 | if (nr_minors > 1) { |
481 | if (offset < 26) | 550 | if (offset < 26) |
482 | sprintf(gd->disk_name, "%s%c", DEV_NAME, 'a' + offset); | 551 | sprintf(gd->disk_name, "%s%c", DEV_NAME, 'a' + offset); |
@@ -615,7 +684,7 @@ static void blkif_completion(struct blk_shadow *s) | |||
615 | { | 684 | { |
616 | int i; | 685 | int i; |
617 | for (i = 0; i < s->req.nr_segments; i++) | 686 | for (i = 0; i < s->req.nr_segments; i++) |
618 | gnttab_end_foreign_access(s->req.seg[i].gref, 0, 0UL); | 687 | gnttab_end_foreign_access(s->req.u.rw.seg[i].gref, 0, 0UL); |
619 | } | 688 | } |
620 | 689 | ||
621 | static irqreturn_t blkif_interrupt(int irq, void *dev_id) | 690 | static irqreturn_t blkif_interrupt(int irq, void *dev_id) |
@@ -932,7 +1001,7 @@ static int blkif_recover(struct blkfront_info *info) | |||
932 | /* Rewrite any grant references invalidated by susp/resume. */ | 1001 | /* Rewrite any grant references invalidated by susp/resume. */ |
933 | for (j = 0; j < req->nr_segments; j++) | 1002 | for (j = 0; j < req->nr_segments; j++) |
934 | gnttab_grant_foreign_access_ref( | 1003 | gnttab_grant_foreign_access_ref( |
935 | req->seg[j].gref, | 1004 | req->u.rw.seg[j].gref, |
936 | info->xbdev->otherend_id, | 1005 | info->xbdev->otherend_id, |
937 | pfn_to_mfn(info->shadow[req->id].frame[j]), | 1006 | pfn_to_mfn(info->shadow[req->id].frame[j]), |
938 | rq_data_dir(info->shadow[req->id].request)); | 1007 | rq_data_dir(info->shadow[req->id].request)); |
diff --git a/drivers/gpio/ml_ioh_gpio.c b/drivers/gpio/ml_ioh_gpio.c index cead8e6ff345..7f6f01a4b145 100644 --- a/drivers/gpio/ml_ioh_gpio.c +++ b/drivers/gpio/ml_ioh_gpio.c | |||
@@ -326,6 +326,7 @@ static DEFINE_PCI_DEVICE_TABLE(ioh_gpio_pcidev_id) = { | |||
326 | { PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x802E) }, | 326 | { PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x802E) }, |
327 | { 0, } | 327 | { 0, } |
328 | }; | 328 | }; |
329 | MODULE_DEVICE_TABLE(pci, ioh_gpio_pcidev_id); | ||
329 | 330 | ||
330 | static struct pci_driver ioh_gpio_driver = { | 331 | static struct pci_driver ioh_gpio_driver = { |
331 | .name = "ml_ioh_gpio", | 332 | .name = "ml_ioh_gpio", |
diff --git a/drivers/gpio/pch_gpio.c b/drivers/gpio/pch_gpio.c index 0eba0a75c804..2c6af8705103 100644 --- a/drivers/gpio/pch_gpio.c +++ b/drivers/gpio/pch_gpio.c | |||
@@ -286,6 +286,7 @@ static DEFINE_PCI_DEVICE_TABLE(pch_gpio_pcidev_id) = { | |||
286 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x8803) }, | 286 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x8803) }, |
287 | { 0, } | 287 | { 0, } |
288 | }; | 288 | }; |
289 | MODULE_DEVICE_TABLE(pci, pch_gpio_pcidev_id); | ||
289 | 290 | ||
290 | static struct pci_driver pch_gpio_driver = { | 291 | static struct pci_driver pch_gpio_driver = { |
291 | .name = "pch_gpio", | 292 | .name = "pch_gpio", |
diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index d270b3ff896b..6140ea1de45a 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c | |||
@@ -2194,7 +2194,6 @@ int evergreen_mc_init(struct radeon_device *rdev) | |||
2194 | rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE) * 1024 * 1024; | 2194 | rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE) * 1024 * 1024; |
2195 | } | 2195 | } |
2196 | rdev->mc.visible_vram_size = rdev->mc.aper_size; | 2196 | rdev->mc.visible_vram_size = rdev->mc.aper_size; |
2197 | rdev->mc.active_vram_size = rdev->mc.visible_vram_size; | ||
2198 | r700_vram_gtt_location(rdev, &rdev->mc); | 2197 | r700_vram_gtt_location(rdev, &rdev->mc); |
2199 | radeon_update_bandwidth_info(rdev); | 2198 | radeon_update_bandwidth_info(rdev); |
2200 | 2199 | ||
@@ -2934,7 +2933,7 @@ static int evergreen_startup(struct radeon_device *rdev) | |||
2934 | /* XXX: ontario has problems blitting to gart at the moment */ | 2933 | /* XXX: ontario has problems blitting to gart at the moment */ |
2935 | if (rdev->family == CHIP_PALM) { | 2934 | if (rdev->family == CHIP_PALM) { |
2936 | rdev->asic->copy = NULL; | 2935 | rdev->asic->copy = NULL; |
2937 | rdev->mc.active_vram_size = rdev->mc.visible_vram_size; | 2936 | radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size); |
2938 | } | 2937 | } |
2939 | 2938 | ||
2940 | /* allocate wb buffer */ | 2939 | /* allocate wb buffer */ |
diff --git a/drivers/gpu/drm/radeon/evergreen_blit_kms.c b/drivers/gpu/drm/radeon/evergreen_blit_kms.c index 2adfb03f479b..2be698e78ff2 100644 --- a/drivers/gpu/drm/radeon/evergreen_blit_kms.c +++ b/drivers/gpu/drm/radeon/evergreen_blit_kms.c | |||
@@ -623,7 +623,7 @@ done: | |||
623 | dev_err(rdev->dev, "(%d) pin blit object failed\n", r); | 623 | dev_err(rdev->dev, "(%d) pin blit object failed\n", r); |
624 | return r; | 624 | return r; |
625 | } | 625 | } |
626 | rdev->mc.active_vram_size = rdev->mc.real_vram_size; | 626 | radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size); |
627 | return 0; | 627 | return 0; |
628 | } | 628 | } |
629 | 629 | ||
@@ -631,7 +631,7 @@ void evergreen_blit_fini(struct radeon_device *rdev) | |||
631 | { | 631 | { |
632 | int r; | 632 | int r; |
633 | 633 | ||
634 | rdev->mc.active_vram_size = rdev->mc.visible_vram_size; | 634 | radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size); |
635 | if (rdev->r600_blit.shader_obj == NULL) | 635 | if (rdev->r600_blit.shader_obj == NULL) |
636 | return; | 636 | return; |
637 | /* If we can't reserve the bo, unref should be enough to destroy | 637 | /* If we can't reserve the bo, unref should be enough to destroy |
diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index 93fa735c8c1a..e372f9e1e5ce 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c | |||
@@ -70,23 +70,6 @@ MODULE_FIRMWARE(FIRMWARE_R520); | |||
70 | 70 | ||
71 | void r100_pre_page_flip(struct radeon_device *rdev, int crtc) | 71 | void r100_pre_page_flip(struct radeon_device *rdev, int crtc) |
72 | { | 72 | { |
73 | struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc]; | ||
74 | u32 tmp; | ||
75 | |||
76 | /* make sure flip is at vb rather than hb */ | ||
77 | tmp = RREG32(RADEON_CRTC_OFFSET_CNTL + radeon_crtc->crtc_offset); | ||
78 | tmp &= ~RADEON_CRTC_OFFSET_FLIP_CNTL; | ||
79 | /* make sure pending bit is asserted */ | ||
80 | tmp |= RADEON_CRTC_GUI_TRIG_OFFSET_LEFT_EN; | ||
81 | WREG32(RADEON_CRTC_OFFSET_CNTL + radeon_crtc->crtc_offset, tmp); | ||
82 | |||
83 | /* set pageflip to happen as late as possible in the vblank interval. | ||
84 | * same field for crtc1/2 | ||
85 | */ | ||
86 | tmp = RREG32(RADEON_CRTC_GEN_CNTL); | ||
87 | tmp &= ~RADEON_CRTC_VSTAT_MODE_MASK; | ||
88 | WREG32(RADEON_CRTC_GEN_CNTL, tmp); | ||
89 | |||
90 | /* enable the pflip int */ | 73 | /* enable the pflip int */ |
91 | radeon_irq_kms_pflip_irq_get(rdev, crtc); | 74 | radeon_irq_kms_pflip_irq_get(rdev, crtc); |
92 | } | 75 | } |
@@ -1041,7 +1024,7 @@ int r100_cp_init(struct radeon_device *rdev, unsigned ring_size) | |||
1041 | return r; | 1024 | return r; |
1042 | } | 1025 | } |
1043 | rdev->cp.ready = true; | 1026 | rdev->cp.ready = true; |
1044 | rdev->mc.active_vram_size = rdev->mc.real_vram_size; | 1027 | radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size); |
1045 | return 0; | 1028 | return 0; |
1046 | } | 1029 | } |
1047 | 1030 | ||
@@ -1059,7 +1042,7 @@ void r100_cp_fini(struct radeon_device *rdev) | |||
1059 | void r100_cp_disable(struct radeon_device *rdev) | 1042 | void r100_cp_disable(struct radeon_device *rdev) |
1060 | { | 1043 | { |
1061 | /* Disable ring */ | 1044 | /* Disable ring */ |
1062 | rdev->mc.active_vram_size = rdev->mc.visible_vram_size; | 1045 | radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size); |
1063 | rdev->cp.ready = false; | 1046 | rdev->cp.ready = false; |
1064 | WREG32(RADEON_CP_CSQ_MODE, 0); | 1047 | WREG32(RADEON_CP_CSQ_MODE, 0); |
1065 | WREG32(RADEON_CP_CSQ_CNTL, 0); | 1048 | WREG32(RADEON_CP_CSQ_CNTL, 0); |
@@ -2329,7 +2312,6 @@ void r100_vram_init_sizes(struct radeon_device *rdev) | |||
2329 | /* FIXME we don't use the second aperture yet when we could use it */ | 2312 | /* FIXME we don't use the second aperture yet when we could use it */ |
2330 | if (rdev->mc.visible_vram_size > rdev->mc.aper_size) | 2313 | if (rdev->mc.visible_vram_size > rdev->mc.aper_size) |
2331 | rdev->mc.visible_vram_size = rdev->mc.aper_size; | 2314 | rdev->mc.visible_vram_size = rdev->mc.aper_size; |
2332 | rdev->mc.active_vram_size = rdev->mc.visible_vram_size; | ||
2333 | config_aper_size = RREG32(RADEON_CONFIG_APER_SIZE); | 2315 | config_aper_size = RREG32(RADEON_CONFIG_APER_SIZE); |
2334 | if (rdev->flags & RADEON_IS_IGP) { | 2316 | if (rdev->flags & RADEON_IS_IGP) { |
2335 | uint32_t tom; | 2317 | uint32_t tom; |
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index de88624d5f87..9b3fad23b76c 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c | |||
@@ -1255,7 +1255,6 @@ int r600_mc_init(struct radeon_device *rdev) | |||
1255 | rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE); | 1255 | rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE); |
1256 | rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE); | 1256 | rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE); |
1257 | rdev->mc.visible_vram_size = rdev->mc.aper_size; | 1257 | rdev->mc.visible_vram_size = rdev->mc.aper_size; |
1258 | rdev->mc.active_vram_size = rdev->mc.visible_vram_size; | ||
1259 | r600_vram_gtt_location(rdev, &rdev->mc); | 1258 | r600_vram_gtt_location(rdev, &rdev->mc); |
1260 | 1259 | ||
1261 | if (rdev->flags & RADEON_IS_IGP) { | 1260 | if (rdev->flags & RADEON_IS_IGP) { |
@@ -1937,7 +1936,7 @@ void r600_pciep_wreg(struct radeon_device *rdev, u32 reg, u32 v) | |||
1937 | */ | 1936 | */ |
1938 | void r600_cp_stop(struct radeon_device *rdev) | 1937 | void r600_cp_stop(struct radeon_device *rdev) |
1939 | { | 1938 | { |
1940 | rdev->mc.active_vram_size = rdev->mc.visible_vram_size; | 1939 | radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size); |
1941 | WREG32(R_0086D8_CP_ME_CNTL, S_0086D8_CP_ME_HALT(1)); | 1940 | WREG32(R_0086D8_CP_ME_CNTL, S_0086D8_CP_ME_HALT(1)); |
1942 | WREG32(SCRATCH_UMSK, 0); | 1941 | WREG32(SCRATCH_UMSK, 0); |
1943 | } | 1942 | } |
diff --git a/drivers/gpu/drm/radeon/r600_blit_kms.c b/drivers/gpu/drm/radeon/r600_blit_kms.c index 41f7aafc97c4..df68d91e8190 100644 --- a/drivers/gpu/drm/radeon/r600_blit_kms.c +++ b/drivers/gpu/drm/radeon/r600_blit_kms.c | |||
@@ -558,7 +558,7 @@ done: | |||
558 | dev_err(rdev->dev, "(%d) pin blit object failed\n", r); | 558 | dev_err(rdev->dev, "(%d) pin blit object failed\n", r); |
559 | return r; | 559 | return r; |
560 | } | 560 | } |
561 | rdev->mc.active_vram_size = rdev->mc.real_vram_size; | 561 | radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size); |
562 | return 0; | 562 | return 0; |
563 | } | 563 | } |
564 | 564 | ||
@@ -566,7 +566,7 @@ void r600_blit_fini(struct radeon_device *rdev) | |||
566 | { | 566 | { |
567 | int r; | 567 | int r; |
568 | 568 | ||
569 | rdev->mc.active_vram_size = rdev->mc.visible_vram_size; | 569 | radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size); |
570 | if (rdev->r600_blit.shader_obj == NULL) | 570 | if (rdev->r600_blit.shader_obj == NULL) |
571 | return; | 571 | return; |
572 | /* If we can't reserve the bo, unref should be enough to destroy | 572 | /* If we can't reserve the bo, unref should be enough to destroy |
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 56c48b67ef3d..6b3429495118 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h | |||
@@ -345,7 +345,6 @@ struct radeon_mc { | |||
345 | * about vram size near mc fb location */ | 345 | * about vram size near mc fb location */ |
346 | u64 mc_vram_size; | 346 | u64 mc_vram_size; |
347 | u64 visible_vram_size; | 347 | u64 visible_vram_size; |
348 | u64 active_vram_size; | ||
349 | u64 gtt_size; | 348 | u64 gtt_size; |
350 | u64 gtt_start; | 349 | u64 gtt_start; |
351 | u64 gtt_end; | 350 | u64 gtt_end; |
@@ -1448,6 +1447,7 @@ extern void radeon_vram_location(struct radeon_device *rdev, struct radeon_mc *m | |||
1448 | extern void radeon_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc); | 1447 | extern void radeon_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc); |
1449 | extern int radeon_resume_kms(struct drm_device *dev); | 1448 | extern int radeon_resume_kms(struct drm_device *dev); |
1450 | extern int radeon_suspend_kms(struct drm_device *dev, pm_message_t state); | 1449 | extern int radeon_suspend_kms(struct drm_device *dev, pm_message_t state); |
1450 | extern void radeon_ttm_set_active_vram_size(struct radeon_device *rdev, u64 size); | ||
1451 | 1451 | ||
1452 | /* r600, rv610, rv630, rv620, rv635, rv670, rs780, rs880 */ | 1452 | /* r600, rv610, rv630, rv620, rv635, rv670, rs780, rs880 */ |
1453 | extern bool r600_card_posted(struct radeon_device *rdev); | 1453 | extern bool r600_card_posted(struct radeon_device *rdev); |
diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c index e75d63b8e21d..793c5e6026ad 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.c +++ b/drivers/gpu/drm/radeon/radeon_asic.c | |||
@@ -834,6 +834,9 @@ static struct radeon_asic sumo_asic = { | |||
834 | .pm_finish = &evergreen_pm_finish, | 834 | .pm_finish = &evergreen_pm_finish, |
835 | .pm_init_profile = &rs780_pm_init_profile, | 835 | .pm_init_profile = &rs780_pm_init_profile, |
836 | .pm_get_dynpm_state = &r600_pm_get_dynpm_state, | 836 | .pm_get_dynpm_state = &r600_pm_get_dynpm_state, |
837 | .pre_page_flip = &evergreen_pre_page_flip, | ||
838 | .page_flip = &evergreen_page_flip, | ||
839 | .post_page_flip = &evergreen_post_page_flip, | ||
837 | }; | 840 | }; |
838 | 841 | ||
839 | static struct radeon_asic btc_asic = { | 842 | static struct radeon_asic btc_asic = { |
diff --git a/drivers/gpu/drm/radeon/radeon_gem.c b/drivers/gpu/drm/radeon/radeon_gem.c index df95eb83dac6..1fe95dfe48c9 100644 --- a/drivers/gpu/drm/radeon/radeon_gem.c +++ b/drivers/gpu/drm/radeon/radeon_gem.c | |||
@@ -156,9 +156,12 @@ int radeon_gem_info_ioctl(struct drm_device *dev, void *data, | |||
156 | { | 156 | { |
157 | struct radeon_device *rdev = dev->dev_private; | 157 | struct radeon_device *rdev = dev->dev_private; |
158 | struct drm_radeon_gem_info *args = data; | 158 | struct drm_radeon_gem_info *args = data; |
159 | struct ttm_mem_type_manager *man; | ||
160 | |||
161 | man = &rdev->mman.bdev.man[TTM_PL_VRAM]; | ||
159 | 162 | ||
160 | args->vram_size = rdev->mc.real_vram_size; | 163 | args->vram_size = rdev->mc.real_vram_size; |
161 | args->vram_visible = rdev->mc.real_vram_size; | 164 | args->vram_visible = (u64)man->size << PAGE_SHIFT; |
162 | if (rdev->stollen_vga_memory) | 165 | if (rdev->stollen_vga_memory) |
163 | args->vram_visible -= radeon_bo_size(rdev->stollen_vga_memory); | 166 | args->vram_visible -= radeon_bo_size(rdev->stollen_vga_memory); |
164 | args->vram_visible -= radeon_fbdev_total_size(rdev); | 167 | args->vram_visible -= radeon_fbdev_total_size(rdev); |
diff --git a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c index cf0638c3b7c7..78968b738e88 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c | |||
@@ -443,7 +443,7 @@ int radeon_crtc_do_set_base(struct drm_crtc *crtc, | |||
443 | (target_fb->bits_per_pixel * 8)); | 443 | (target_fb->bits_per_pixel * 8)); |
444 | crtc_pitch |= crtc_pitch << 16; | 444 | crtc_pitch |= crtc_pitch << 16; |
445 | 445 | ||
446 | 446 | crtc_offset_cntl |= RADEON_CRTC_GUI_TRIG_OFFSET_LEFT_EN; | |
447 | if (tiling_flags & RADEON_TILING_MACRO) { | 447 | if (tiling_flags & RADEON_TILING_MACRO) { |
448 | if (ASIC_IS_R300(rdev)) | 448 | if (ASIC_IS_R300(rdev)) |
449 | crtc_offset_cntl |= (R300_CRTC_X_Y_MODE_EN | | 449 | crtc_offset_cntl |= (R300_CRTC_X_Y_MODE_EN | |
@@ -502,6 +502,7 @@ int radeon_crtc_do_set_base(struct drm_crtc *crtc, | |||
502 | gen_cntl_val = RREG32(gen_cntl_reg); | 502 | gen_cntl_val = RREG32(gen_cntl_reg); |
503 | gen_cntl_val &= ~(0xf << 8); | 503 | gen_cntl_val &= ~(0xf << 8); |
504 | gen_cntl_val |= (format << 8); | 504 | gen_cntl_val |= (format << 8); |
505 | gen_cntl_val &= ~RADEON_CRTC_VSTAT_MODE_MASK; | ||
505 | WREG32(gen_cntl_reg, gen_cntl_val); | 506 | WREG32(gen_cntl_reg, gen_cntl_val); |
506 | 507 | ||
507 | crtc_offset = (u32)base; | 508 | crtc_offset = (u32)base; |
diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index e5b2cf10cbf4..8389b4c63d12 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c | |||
@@ -589,6 +589,20 @@ void radeon_ttm_fini(struct radeon_device *rdev) | |||
589 | DRM_INFO("radeon: ttm finalized\n"); | 589 | DRM_INFO("radeon: ttm finalized\n"); |
590 | } | 590 | } |
591 | 591 | ||
592 | /* this should only be called at bootup or when userspace | ||
593 | * isn't running */ | ||
594 | void radeon_ttm_set_active_vram_size(struct radeon_device *rdev, u64 size) | ||
595 | { | ||
596 | struct ttm_mem_type_manager *man; | ||
597 | |||
598 | if (!rdev->mman.initialized) | ||
599 | return; | ||
600 | |||
601 | man = &rdev->mman.bdev.man[TTM_PL_VRAM]; | ||
602 | /* this just adjusts TTM size idea, which sets lpfn to the correct value */ | ||
603 | man->size = size >> PAGE_SHIFT; | ||
604 | } | ||
605 | |||
592 | static struct vm_operations_struct radeon_ttm_vm_ops; | 606 | static struct vm_operations_struct radeon_ttm_vm_ops; |
593 | static const struct vm_operations_struct *ttm_vm_ops = NULL; | 607 | static const struct vm_operations_struct *ttm_vm_ops = NULL; |
594 | 608 | ||
diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c index 5afe294ed51f..8af4679db23e 100644 --- a/drivers/gpu/drm/radeon/rs600.c +++ b/drivers/gpu/drm/radeon/rs600.c | |||
@@ -751,7 +751,6 @@ void rs600_mc_init(struct radeon_device *rdev) | |||
751 | rdev->mc.real_vram_size = RREG32(RADEON_CONFIG_MEMSIZE); | 751 | rdev->mc.real_vram_size = RREG32(RADEON_CONFIG_MEMSIZE); |
752 | rdev->mc.mc_vram_size = rdev->mc.real_vram_size; | 752 | rdev->mc.mc_vram_size = rdev->mc.real_vram_size; |
753 | rdev->mc.visible_vram_size = rdev->mc.aper_size; | 753 | rdev->mc.visible_vram_size = rdev->mc.aper_size; |
754 | rdev->mc.active_vram_size = rdev->mc.visible_vram_size; | ||
755 | rdev->mc.igp_sideport_enabled = radeon_atombios_sideport_present(rdev); | 754 | rdev->mc.igp_sideport_enabled = radeon_atombios_sideport_present(rdev); |
756 | base = RREG32_MC(R_000004_MC_FB_LOCATION); | 755 | base = RREG32_MC(R_000004_MC_FB_LOCATION); |
757 | base = G_000004_MC_FB_START(base) << 16; | 756 | base = G_000004_MC_FB_START(base) << 16; |
diff --git a/drivers/gpu/drm/radeon/rs690.c b/drivers/gpu/drm/radeon/rs690.c index 6638c8e4c81b..66c949b7c18c 100644 --- a/drivers/gpu/drm/radeon/rs690.c +++ b/drivers/gpu/drm/radeon/rs690.c | |||
@@ -157,7 +157,6 @@ void rs690_mc_init(struct radeon_device *rdev) | |||
157 | rdev->mc.aper_base = pci_resource_start(rdev->pdev, 0); | 157 | rdev->mc.aper_base = pci_resource_start(rdev->pdev, 0); |
158 | rdev->mc.aper_size = pci_resource_len(rdev->pdev, 0); | 158 | rdev->mc.aper_size = pci_resource_len(rdev->pdev, 0); |
159 | rdev->mc.visible_vram_size = rdev->mc.aper_size; | 159 | rdev->mc.visible_vram_size = rdev->mc.aper_size; |
160 | rdev->mc.active_vram_size = rdev->mc.visible_vram_size; | ||
161 | base = RREG32_MC(R_000100_MCCFG_FB_LOCATION); | 160 | base = RREG32_MC(R_000100_MCCFG_FB_LOCATION); |
162 | base = G_000100_MC_FB_START(base) << 16; | 161 | base = G_000100_MC_FB_START(base) << 16; |
163 | rdev->mc.igp_sideport_enabled = radeon_atombios_sideport_present(rdev); | 162 | rdev->mc.igp_sideport_enabled = radeon_atombios_sideport_present(rdev); |
diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c index d8ba67690656..714ad45757d0 100644 --- a/drivers/gpu/drm/radeon/rv770.c +++ b/drivers/gpu/drm/radeon/rv770.c | |||
@@ -307,7 +307,7 @@ static void rv770_mc_program(struct radeon_device *rdev) | |||
307 | */ | 307 | */ |
308 | void r700_cp_stop(struct radeon_device *rdev) | 308 | void r700_cp_stop(struct radeon_device *rdev) |
309 | { | 309 | { |
310 | rdev->mc.active_vram_size = rdev->mc.visible_vram_size; | 310 | radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size); |
311 | WREG32(CP_ME_CNTL, (CP_ME_HALT | CP_PFP_HALT)); | 311 | WREG32(CP_ME_CNTL, (CP_ME_HALT | CP_PFP_HALT)); |
312 | WREG32(SCRATCH_UMSK, 0); | 312 | WREG32(SCRATCH_UMSK, 0); |
313 | } | 313 | } |
@@ -1123,7 +1123,6 @@ int rv770_mc_init(struct radeon_device *rdev) | |||
1123 | rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE); | 1123 | rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE); |
1124 | rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE); | 1124 | rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE); |
1125 | rdev->mc.visible_vram_size = rdev->mc.aper_size; | 1125 | rdev->mc.visible_vram_size = rdev->mc.aper_size; |
1126 | rdev->mc.active_vram_size = rdev->mc.visible_vram_size; | ||
1127 | r700_vram_gtt_location(rdev, &rdev->mc); | 1126 | r700_vram_gtt_location(rdev, &rdev->mc); |
1128 | radeon_update_bandwidth_info(rdev); | 1127 | radeon_update_bandwidth_info(rdev); |
1129 | 1128 | ||
diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c index 3f49dd376f02..6e06019015a5 100644 --- a/drivers/hwmon/f71882fg.c +++ b/drivers/hwmon/f71882fg.c | |||
@@ -37,7 +37,7 @@ | |||
37 | #define SIO_F71858FG_LD_HWM 0x02 /* Hardware monitor logical device */ | 37 | #define SIO_F71858FG_LD_HWM 0x02 /* Hardware monitor logical device */ |
38 | #define SIO_F71882FG_LD_HWM 0x04 /* Hardware monitor logical device */ | 38 | #define SIO_F71882FG_LD_HWM 0x04 /* Hardware monitor logical device */ |
39 | #define SIO_UNLOCK_KEY 0x87 /* Key to enable Super-I/O */ | 39 | #define SIO_UNLOCK_KEY 0x87 /* Key to enable Super-I/O */ |
40 | #define SIO_LOCK_KEY 0xAA /* Key to diasble Super-I/O */ | 40 | #define SIO_LOCK_KEY 0xAA /* Key to disable Super-I/O */ |
41 | 41 | ||
42 | #define SIO_REG_LDSEL 0x07 /* Logical device select */ | 42 | #define SIO_REG_LDSEL 0x07 /* Logical device select */ |
43 | #define SIO_REG_DEVID 0x20 /* Device ID (2 bytes) */ | 43 | #define SIO_REG_DEVID 0x20 /* Device ID (2 bytes) */ |
@@ -2111,7 +2111,6 @@ static int f71882fg_remove(struct platform_device *pdev) | |||
2111 | int nr_fans = (data->type == f71882fg) ? 4 : 3; | 2111 | int nr_fans = (data->type == f71882fg) ? 4 : 3; |
2112 | u8 start_reg = f71882fg_read8(data, F71882FG_REG_START); | 2112 | u8 start_reg = f71882fg_read8(data, F71882FG_REG_START); |
2113 | 2113 | ||
2114 | platform_set_drvdata(pdev, NULL); | ||
2115 | if (data->hwmon_dev) | 2114 | if (data->hwmon_dev) |
2116 | hwmon_device_unregister(data->hwmon_dev); | 2115 | hwmon_device_unregister(data->hwmon_dev); |
2117 | 2116 | ||
@@ -2178,6 +2177,7 @@ static int f71882fg_remove(struct platform_device *pdev) | |||
2178 | } | 2177 | } |
2179 | } | 2178 | } |
2180 | 2179 | ||
2180 | platform_set_drvdata(pdev, NULL); | ||
2181 | kfree(data); | 2181 | kfree(data); |
2182 | 2182 | ||
2183 | return 0; | 2183 | return 0; |
diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c index a8c3e1c9b02a..4aaa88f8ab5f 100644 --- a/drivers/mtd/chips/cfi_cmdset_0001.c +++ b/drivers/mtd/chips/cfi_cmdset_0001.c | |||
@@ -1230,10 +1230,32 @@ static int inval_cache_and_wait_for_operation( | |||
1230 | sleep_time = chip_op_time / 2; | 1230 | sleep_time = chip_op_time / 2; |
1231 | 1231 | ||
1232 | for (;;) { | 1232 | for (;;) { |
1233 | if (chip->state != chip_state) { | ||
1234 | /* Someone's suspended the operation: sleep */ | ||
1235 | DECLARE_WAITQUEUE(wait, current); | ||
1236 | set_current_state(TASK_UNINTERRUPTIBLE); | ||
1237 | add_wait_queue(&chip->wq, &wait); | ||
1238 | mutex_unlock(&chip->mutex); | ||
1239 | schedule(); | ||
1240 | remove_wait_queue(&chip->wq, &wait); | ||
1241 | mutex_lock(&chip->mutex); | ||
1242 | continue; | ||
1243 | } | ||
1244 | |||
1233 | status = map_read(map, cmd_adr); | 1245 | status = map_read(map, cmd_adr); |
1234 | if (map_word_andequal(map, status, status_OK, status_OK)) | 1246 | if (map_word_andequal(map, status, status_OK, status_OK)) |
1235 | break; | 1247 | break; |
1236 | 1248 | ||
1249 | if (chip->erase_suspended && chip_state == FL_ERASING) { | ||
1250 | /* Erase suspend occured while sleep: reset timeout */ | ||
1251 | timeo = reset_timeo; | ||
1252 | chip->erase_suspended = 0; | ||
1253 | } | ||
1254 | if (chip->write_suspended && chip_state == FL_WRITING) { | ||
1255 | /* Write suspend occured while sleep: reset timeout */ | ||
1256 | timeo = reset_timeo; | ||
1257 | chip->write_suspended = 0; | ||
1258 | } | ||
1237 | if (!timeo) { | 1259 | if (!timeo) { |
1238 | map_write(map, CMD(0x70), cmd_adr); | 1260 | map_write(map, CMD(0x70), cmd_adr); |
1239 | chip->state = FL_STATUS; | 1261 | chip->state = FL_STATUS; |
@@ -1257,27 +1279,6 @@ static int inval_cache_and_wait_for_operation( | |||
1257 | timeo--; | 1279 | timeo--; |
1258 | } | 1280 | } |
1259 | mutex_lock(&chip->mutex); | 1281 | mutex_lock(&chip->mutex); |
1260 | |||
1261 | while (chip->state != chip_state) { | ||
1262 | /* Someone's suspended the operation: sleep */ | ||
1263 | DECLARE_WAITQUEUE(wait, current); | ||
1264 | set_current_state(TASK_UNINTERRUPTIBLE); | ||
1265 | add_wait_queue(&chip->wq, &wait); | ||
1266 | mutex_unlock(&chip->mutex); | ||
1267 | schedule(); | ||
1268 | remove_wait_queue(&chip->wq, &wait); | ||
1269 | mutex_lock(&chip->mutex); | ||
1270 | } | ||
1271 | if (chip->erase_suspended && chip_state == FL_ERASING) { | ||
1272 | /* Erase suspend occured while sleep: reset timeout */ | ||
1273 | timeo = reset_timeo; | ||
1274 | chip->erase_suspended = 0; | ||
1275 | } | ||
1276 | if (chip->write_suspended && chip_state == FL_WRITING) { | ||
1277 | /* Write suspend occured while sleep: reset timeout */ | ||
1278 | timeo = reset_timeo; | ||
1279 | chip->write_suspended = 0; | ||
1280 | } | ||
1281 | } | 1282 | } |
1282 | 1283 | ||
1283 | /* Done and happy. */ | 1284 | /* Done and happy. */ |
diff --git a/drivers/mtd/chips/jedec_probe.c b/drivers/mtd/chips/jedec_probe.c index d72a5fb2d041..4e1be51cc122 100644 --- a/drivers/mtd/chips/jedec_probe.c +++ b/drivers/mtd/chips/jedec_probe.c | |||
@@ -1935,14 +1935,14 @@ static void jedec_reset(u32 base, struct map_info *map, struct cfi_private *cfi) | |||
1935 | } | 1935 | } |
1936 | 1936 | ||
1937 | 1937 | ||
1938 | static int cfi_jedec_setup(struct cfi_private *p_cfi, int index) | 1938 | static int cfi_jedec_setup(struct map_info *map, struct cfi_private *cfi, int index) |
1939 | { | 1939 | { |
1940 | int i,num_erase_regions; | 1940 | int i,num_erase_regions; |
1941 | uint8_t uaddr; | 1941 | uint8_t uaddr; |
1942 | 1942 | ||
1943 | if (! (jedec_table[index].devtypes & p_cfi->device_type)) { | 1943 | if (!(jedec_table[index].devtypes & cfi->device_type)) { |
1944 | DEBUG(MTD_DEBUG_LEVEL1, "Rejecting potential %s with incompatible %d-bit device type\n", | 1944 | DEBUG(MTD_DEBUG_LEVEL1, "Rejecting potential %s with incompatible %d-bit device type\n", |
1945 | jedec_table[index].name, 4 * (1<<p_cfi->device_type)); | 1945 | jedec_table[index].name, 4 * (1<<cfi->device_type)); |
1946 | return 0; | 1946 | return 0; |
1947 | } | 1947 | } |
1948 | 1948 | ||
@@ -1950,27 +1950,28 @@ static int cfi_jedec_setup(struct cfi_private *p_cfi, int index) | |||
1950 | 1950 | ||
1951 | num_erase_regions = jedec_table[index].nr_regions; | 1951 | num_erase_regions = jedec_table[index].nr_regions; |
1952 | 1952 | ||
1953 | p_cfi->cfiq = kmalloc(sizeof(struct cfi_ident) + num_erase_regions * 4, GFP_KERNEL); | 1953 | cfi->cfiq = kmalloc(sizeof(struct cfi_ident) + num_erase_regions * 4, GFP_KERNEL); |
1954 | if (!p_cfi->cfiq) { | 1954 | if (!cfi->cfiq) { |
1955 | //xx printk(KERN_WARNING "%s: kmalloc failed for CFI ident structure\n", map->name); | 1955 | //xx printk(KERN_WARNING "%s: kmalloc failed for CFI ident structure\n", map->name); |
1956 | return 0; | 1956 | return 0; |
1957 | } | 1957 | } |
1958 | 1958 | ||
1959 | memset(p_cfi->cfiq,0,sizeof(struct cfi_ident)); | 1959 | memset(cfi->cfiq, 0, sizeof(struct cfi_ident)); |
1960 | 1960 | ||
1961 | p_cfi->cfiq->P_ID = jedec_table[index].cmd_set; | 1961 | cfi->cfiq->P_ID = jedec_table[index].cmd_set; |
1962 | p_cfi->cfiq->NumEraseRegions = jedec_table[index].nr_regions; | 1962 | cfi->cfiq->NumEraseRegions = jedec_table[index].nr_regions; |
1963 | p_cfi->cfiq->DevSize = jedec_table[index].dev_size; | 1963 | cfi->cfiq->DevSize = jedec_table[index].dev_size; |
1964 | p_cfi->cfi_mode = CFI_MODE_JEDEC; | 1964 | cfi->cfi_mode = CFI_MODE_JEDEC; |
1965 | cfi->sector_erase_cmd = CMD(0x30); | ||
1965 | 1966 | ||
1966 | for (i=0; i<num_erase_regions; i++){ | 1967 | for (i=0; i<num_erase_regions; i++){ |
1967 | p_cfi->cfiq->EraseRegionInfo[i] = jedec_table[index].regions[i]; | 1968 | cfi->cfiq->EraseRegionInfo[i] = jedec_table[index].regions[i]; |
1968 | } | 1969 | } |
1969 | p_cfi->cmdset_priv = NULL; | 1970 | cfi->cmdset_priv = NULL; |
1970 | 1971 | ||
1971 | /* This may be redundant for some cases, but it doesn't hurt */ | 1972 | /* This may be redundant for some cases, but it doesn't hurt */ |
1972 | p_cfi->mfr = jedec_table[index].mfr_id; | 1973 | cfi->mfr = jedec_table[index].mfr_id; |
1973 | p_cfi->id = jedec_table[index].dev_id; | 1974 | cfi->id = jedec_table[index].dev_id; |
1974 | 1975 | ||
1975 | uaddr = jedec_table[index].uaddr; | 1976 | uaddr = jedec_table[index].uaddr; |
1976 | 1977 | ||
@@ -1978,8 +1979,8 @@ static int cfi_jedec_setup(struct cfi_private *p_cfi, int index) | |||
1978 | our brains explode when we see the datasheets talking about address | 1979 | our brains explode when we see the datasheets talking about address |
1979 | lines numbered from A-1 to A18. The CFI table has unlock addresses | 1980 | lines numbered from A-1 to A18. The CFI table has unlock addresses |
1980 | in device-words according to the mode the device is connected in */ | 1981 | in device-words according to the mode the device is connected in */ |
1981 | p_cfi->addr_unlock1 = unlock_addrs[uaddr].addr1 / p_cfi->device_type; | 1982 | cfi->addr_unlock1 = unlock_addrs[uaddr].addr1 / cfi->device_type; |
1982 | p_cfi->addr_unlock2 = unlock_addrs[uaddr].addr2 / p_cfi->device_type; | 1983 | cfi->addr_unlock2 = unlock_addrs[uaddr].addr2 / cfi->device_type; |
1983 | 1984 | ||
1984 | return 1; /* ok */ | 1985 | return 1; /* ok */ |
1985 | } | 1986 | } |
@@ -2175,7 +2176,7 @@ static int jedec_probe_chip(struct map_info *map, __u32 base, | |||
2175 | "MTD %s(): matched device 0x%x,0x%x unlock_addrs: 0x%.4x 0x%.4x\n", | 2176 | "MTD %s(): matched device 0x%x,0x%x unlock_addrs: 0x%.4x 0x%.4x\n", |
2176 | __func__, cfi->mfr, cfi->id, | 2177 | __func__, cfi->mfr, cfi->id, |
2177 | cfi->addr_unlock1, cfi->addr_unlock2 ); | 2178 | cfi->addr_unlock1, cfi->addr_unlock2 ); |
2178 | if (!cfi_jedec_setup(cfi, i)) | 2179 | if (!cfi_jedec_setup(map, cfi, i)) |
2179 | return 0; | 2180 | return 0; |
2180 | goto ok_out; | 2181 | goto ok_out; |
2181 | } | 2182 | } |
diff --git a/drivers/mtd/maps/amd76xrom.c b/drivers/mtd/maps/amd76xrom.c index 77d64ce19e9f..92de7e3a49a5 100644 --- a/drivers/mtd/maps/amd76xrom.c +++ b/drivers/mtd/maps/amd76xrom.c | |||
@@ -151,6 +151,7 @@ static int __devinit amd76xrom_init_one (struct pci_dev *pdev, | |||
151 | printk(KERN_ERR MOD_NAME | 151 | printk(KERN_ERR MOD_NAME |
152 | " %s(): Unable to register resource %pR - kernel bug?\n", | 152 | " %s(): Unable to register resource %pR - kernel bug?\n", |
153 | __func__, &window->rsrc); | 153 | __func__, &window->rsrc); |
154 | return -EBUSY; | ||
154 | } | 155 | } |
155 | 156 | ||
156 | 157 | ||
diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c index cb20c67995d8..e0a2373bf0e2 100644 --- a/drivers/mtd/mtd_blkdevs.c +++ b/drivers/mtd/mtd_blkdevs.c | |||
@@ -413,7 +413,6 @@ error3: | |||
413 | error2: | 413 | error2: |
414 | list_del(&new->list); | 414 | list_del(&new->list); |
415 | error1: | 415 | error1: |
416 | kfree(new); | ||
417 | return ret; | 416 | return ret; |
418 | } | 417 | } |
419 | 418 | ||
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c index 15682ec8530e..28af71c61834 100644 --- a/drivers/mtd/nand/omap2.c +++ b/drivers/mtd/nand/omap2.c | |||
@@ -968,6 +968,6 @@ static void __exit omap_nand_exit(void) | |||
968 | module_init(omap_nand_init); | 968 | module_init(omap_nand_init); |
969 | module_exit(omap_nand_exit); | 969 | module_exit(omap_nand_exit); |
970 | 970 | ||
971 | MODULE_ALIAS(DRIVER_NAME); | 971 | MODULE_ALIAS("platform:" DRIVER_NAME); |
972 | MODULE_LICENSE("GPL"); | 972 | MODULE_LICENSE("GPL"); |
973 | MODULE_DESCRIPTION("Glue layer for NAND flash on TI OMAP boards"); | 973 | MODULE_DESCRIPTION("Glue layer for NAND flash on TI OMAP boards"); |
diff --git a/drivers/mtd/onenand/generic.c b/drivers/mtd/onenand/generic.c index e78914938c5c..ac08750748a3 100644 --- a/drivers/mtd/onenand/generic.c +++ b/drivers/mtd/onenand/generic.c | |||
@@ -131,7 +131,7 @@ static struct platform_driver generic_onenand_driver = { | |||
131 | .remove = __devexit_p(generic_onenand_remove), | 131 | .remove = __devexit_p(generic_onenand_remove), |
132 | }; | 132 | }; |
133 | 133 | ||
134 | MODULE_ALIAS(DRIVER_NAME); | 134 | MODULE_ALIAS("platform:" DRIVER_NAME); |
135 | 135 | ||
136 | static int __init generic_onenand_init(void) | 136 | static int __init generic_onenand_init(void) |
137 | { | 137 | { |
diff --git a/drivers/mtd/onenand/omap2.c b/drivers/mtd/onenand/omap2.c index ac31f461cc1c..c849cacf4b2f 100644 --- a/drivers/mtd/onenand/omap2.c +++ b/drivers/mtd/onenand/omap2.c | |||
@@ -860,7 +860,7 @@ static void __exit omap2_onenand_exit(void) | |||
860 | module_init(omap2_onenand_init); | 860 | module_init(omap2_onenand_init); |
861 | module_exit(omap2_onenand_exit); | 861 | module_exit(omap2_onenand_exit); |
862 | 862 | ||
863 | MODULE_ALIAS(DRIVER_NAME); | 863 | MODULE_ALIAS("platform:" DRIVER_NAME); |
864 | MODULE_LICENSE("GPL"); | 864 | MODULE_LICENSE("GPL"); |
865 | MODULE_AUTHOR("Jarkko Lavinen <jarkko.lavinen@nokia.com>"); | 865 | MODULE_AUTHOR("Jarkko Lavinen <jarkko.lavinen@nokia.com>"); |
866 | MODULE_DESCRIPTION("Glue layer for OneNAND flash on OMAP2 / OMAP3"); | 866 | MODULE_DESCRIPTION("Glue layer for OneNAND flash on OMAP2 / OMAP3"); |
diff --git a/drivers/net/ariadne.c b/drivers/net/ariadne.c index 39214e512452..7ca0eded2561 100644 --- a/drivers/net/ariadne.c +++ b/drivers/net/ariadne.c | |||
@@ -425,11 +425,6 @@ static irqreturn_t ariadne_interrupt(int irq, void *data) | |||
425 | int csr0, boguscnt; | 425 | int csr0, boguscnt; |
426 | int handled = 0; | 426 | int handled = 0; |
427 | 427 | ||
428 | if (dev == NULL) { | ||
429 | printk(KERN_WARNING "ariadne_interrupt(): irq for unknown device.\n"); | ||
430 | return IRQ_NONE; | ||
431 | } | ||
432 | |||
433 | lance->RAP = CSR0; /* PCnet-ISA Controller Status */ | 428 | lance->RAP = CSR0; /* PCnet-ISA Controller Status */ |
434 | 429 | ||
435 | if (!(lance->RDP & INTR)) /* Check if any interrupt has been */ | 430 | if (!(lance->RDP & INTR)) /* Check if any interrupt has been */ |
diff --git a/drivers/net/bnx2x/bnx2x.h b/drivers/net/bnx2x/bnx2x.h index 7897d114b290..8849699c66c4 100644 --- a/drivers/net/bnx2x/bnx2x.h +++ b/drivers/net/bnx2x/bnx2x.h | |||
@@ -1211,6 +1211,7 @@ struct bnx2x { | |||
1211 | /* DCBX Negotation results */ | 1211 | /* DCBX Negotation results */ |
1212 | struct dcbx_features dcbx_local_feat; | 1212 | struct dcbx_features dcbx_local_feat; |
1213 | u32 dcbx_error; | 1213 | u32 dcbx_error; |
1214 | u32 pending_max; | ||
1214 | }; | 1215 | }; |
1215 | 1216 | ||
1216 | /** | 1217 | /** |
@@ -1616,8 +1617,8 @@ static inline u32 reg_poll(struct bnx2x *bp, u32 reg, u32 expected, int ms, | |||
1616 | /* CMNG constants, as derived from system spec calculations */ | 1617 | /* CMNG constants, as derived from system spec calculations */ |
1617 | /* default MIN rate in case VNIC min rate is configured to zero - 100Mbps */ | 1618 | /* default MIN rate in case VNIC min rate is configured to zero - 100Mbps */ |
1618 | #define DEF_MIN_RATE 100 | 1619 | #define DEF_MIN_RATE 100 |
1619 | /* resolution of the rate shaping timer - 100 usec */ | 1620 | /* resolution of the rate shaping timer - 400 usec */ |
1620 | #define RS_PERIODIC_TIMEOUT_USEC 100 | 1621 | #define RS_PERIODIC_TIMEOUT_USEC 400 |
1621 | /* number of bytes in single QM arbitration cycle - | 1622 | /* number of bytes in single QM arbitration cycle - |
1622 | * coefficient for calculating the fairness timer */ | 1623 | * coefficient for calculating the fairness timer */ |
1623 | #define QM_ARB_BYTES 160000 | 1624 | #define QM_ARB_BYTES 160000 |
diff --git a/drivers/net/bnx2x/bnx2x_cmn.c b/drivers/net/bnx2x/bnx2x_cmn.c index 93798129061b..a71b32940533 100644 --- a/drivers/net/bnx2x/bnx2x_cmn.c +++ b/drivers/net/bnx2x/bnx2x_cmn.c | |||
@@ -996,6 +996,23 @@ void bnx2x_free_skbs(struct bnx2x *bp) | |||
996 | bnx2x_free_rx_skbs(bp); | 996 | bnx2x_free_rx_skbs(bp); |
997 | } | 997 | } |
998 | 998 | ||
999 | void bnx2x_update_max_mf_config(struct bnx2x *bp, u32 value) | ||
1000 | { | ||
1001 | /* load old values */ | ||
1002 | u32 mf_cfg = bp->mf_config[BP_VN(bp)]; | ||
1003 | |||
1004 | if (value != bnx2x_extract_max_cfg(bp, mf_cfg)) { | ||
1005 | /* leave all but MAX value */ | ||
1006 | mf_cfg &= ~FUNC_MF_CFG_MAX_BW_MASK; | ||
1007 | |||
1008 | /* set new MAX value */ | ||
1009 | mf_cfg |= (value << FUNC_MF_CFG_MAX_BW_SHIFT) | ||
1010 | & FUNC_MF_CFG_MAX_BW_MASK; | ||
1011 | |||
1012 | bnx2x_fw_command(bp, DRV_MSG_CODE_SET_MF_BW, mf_cfg); | ||
1013 | } | ||
1014 | } | ||
1015 | |||
999 | static void bnx2x_free_msix_irqs(struct bnx2x *bp) | 1016 | static void bnx2x_free_msix_irqs(struct bnx2x *bp) |
1000 | { | 1017 | { |
1001 | int i, offset = 1; | 1018 | int i, offset = 1; |
@@ -1464,6 +1481,11 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode) | |||
1464 | 1481 | ||
1465 | bnx2x_set_eth_mac(bp, 1); | 1482 | bnx2x_set_eth_mac(bp, 1); |
1466 | 1483 | ||
1484 | if (bp->pending_max) { | ||
1485 | bnx2x_update_max_mf_config(bp, bp->pending_max); | ||
1486 | bp->pending_max = 0; | ||
1487 | } | ||
1488 | |||
1467 | if (bp->port.pmf) | 1489 | if (bp->port.pmf) |
1468 | bnx2x_initial_phy_init(bp, load_mode); | 1490 | bnx2x_initial_phy_init(bp, load_mode); |
1469 | 1491 | ||
diff --git a/drivers/net/bnx2x/bnx2x_cmn.h b/drivers/net/bnx2x/bnx2x_cmn.h index 326ba44b3ded..85ea7f26b51f 100644 --- a/drivers/net/bnx2x/bnx2x_cmn.h +++ b/drivers/net/bnx2x/bnx2x_cmn.h | |||
@@ -341,6 +341,15 @@ void bnx2x_dcbx_init(struct bnx2x *bp); | |||
341 | */ | 341 | */ |
342 | int bnx2x_set_power_state(struct bnx2x *bp, pci_power_t state); | 342 | int bnx2x_set_power_state(struct bnx2x *bp, pci_power_t state); |
343 | 343 | ||
344 | /** | ||
345 | * Updates MAX part of MF configuration in HW | ||
346 | * (if required) | ||
347 | * | ||
348 | * @param bp | ||
349 | * @param value | ||
350 | */ | ||
351 | void bnx2x_update_max_mf_config(struct bnx2x *bp, u32 value); | ||
352 | |||
344 | /* dev_close main block */ | 353 | /* dev_close main block */ |
345 | int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode); | 354 | int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode); |
346 | 355 | ||
diff --git a/drivers/net/bnx2x/bnx2x_ethtool.c b/drivers/net/bnx2x/bnx2x_ethtool.c index ef2919987a10..7e92f9d0dcfd 100644 --- a/drivers/net/bnx2x/bnx2x_ethtool.c +++ b/drivers/net/bnx2x/bnx2x_ethtool.c | |||
@@ -238,7 +238,7 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) | |||
238 | speed |= (cmd->speed_hi << 16); | 238 | speed |= (cmd->speed_hi << 16); |
239 | 239 | ||
240 | if (IS_MF_SI(bp)) { | 240 | if (IS_MF_SI(bp)) { |
241 | u32 param = 0, part; | 241 | u32 part; |
242 | u32 line_speed = bp->link_vars.line_speed; | 242 | u32 line_speed = bp->link_vars.line_speed; |
243 | 243 | ||
244 | /* use 10G if no link detected */ | 244 | /* use 10G if no link detected */ |
@@ -251,24 +251,22 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) | |||
251 | REQ_BC_VER_4_SET_MF_BW); | 251 | REQ_BC_VER_4_SET_MF_BW); |
252 | return -EINVAL; | 252 | return -EINVAL; |
253 | } | 253 | } |
254 | |||
254 | part = (speed * 100) / line_speed; | 255 | part = (speed * 100) / line_speed; |
256 | |||
255 | if (line_speed < speed || !part) { | 257 | if (line_speed < speed || !part) { |
256 | BNX2X_DEV_INFO("Speed setting should be in a range " | 258 | BNX2X_DEV_INFO("Speed setting should be in a range " |
257 | "from 1%% to 100%% " | 259 | "from 1%% to 100%% " |
258 | "of actual line speed\n"); | 260 | "of actual line speed\n"); |
259 | return -EINVAL; | 261 | return -EINVAL; |
260 | } | 262 | } |
261 | /* load old values */ | ||
262 | param = bp->mf_config[BP_VN(bp)]; | ||
263 | 263 | ||
264 | /* leave only MIN value */ | 264 | if (bp->state != BNX2X_STATE_OPEN) |
265 | param &= FUNC_MF_CFG_MIN_BW_MASK; | 265 | /* store value for following "load" */ |
266 | 266 | bp->pending_max = part; | |
267 | /* set new MAX value */ | 267 | else |
268 | param |= (part << FUNC_MF_CFG_MAX_BW_SHIFT) | 268 | bnx2x_update_max_mf_config(bp, part); |
269 | & FUNC_MF_CFG_MAX_BW_MASK; | ||
270 | 269 | ||
271 | bnx2x_fw_command(bp, DRV_MSG_CODE_SET_MF_BW, param); | ||
272 | return 0; | 270 | return 0; |
273 | } | 271 | } |
274 | 272 | ||
diff --git a/drivers/net/bnx2x/bnx2x_main.c b/drivers/net/bnx2x/bnx2x_main.c index 032ae184b605..aa032339e321 100644 --- a/drivers/net/bnx2x/bnx2x_main.c +++ b/drivers/net/bnx2x/bnx2x_main.c | |||
@@ -2092,8 +2092,9 @@ static void bnx2x_cmng_fns_init(struct bnx2x *bp, u8 read_cfg, u8 cmng_type) | |||
2092 | bnx2x_calc_vn_weight_sum(bp); | 2092 | bnx2x_calc_vn_weight_sum(bp); |
2093 | 2093 | ||
2094 | /* calculate and set min-max rate for each vn */ | 2094 | /* calculate and set min-max rate for each vn */ |
2095 | for (vn = VN_0; vn < E1HVN_MAX; vn++) | 2095 | if (bp->port.pmf) |
2096 | bnx2x_init_vn_minmax(bp, vn); | 2096 | for (vn = VN_0; vn < E1HVN_MAX; vn++) |
2097 | bnx2x_init_vn_minmax(bp, vn); | ||
2097 | 2098 | ||
2098 | /* always enable rate shaping and fairness */ | 2099 | /* always enable rate shaping and fairness */ |
2099 | bp->cmng.flags.cmng_enables |= | 2100 | bp->cmng.flags.cmng_enables |= |
@@ -2162,13 +2163,6 @@ static void bnx2x_link_attn(struct bnx2x *bp) | |||
2162 | bnx2x_stats_handle(bp, STATS_EVENT_LINK_UP); | 2163 | bnx2x_stats_handle(bp, STATS_EVENT_LINK_UP); |
2163 | } | 2164 | } |
2164 | 2165 | ||
2165 | /* indicate link status only if link status actually changed */ | ||
2166 | if (prev_link_status != bp->link_vars.link_status) | ||
2167 | bnx2x_link_report(bp); | ||
2168 | |||
2169 | if (IS_MF(bp)) | ||
2170 | bnx2x_link_sync_notify(bp); | ||
2171 | |||
2172 | if (bp->link_vars.link_up && bp->link_vars.line_speed) { | 2166 | if (bp->link_vars.link_up && bp->link_vars.line_speed) { |
2173 | int cmng_fns = bnx2x_get_cmng_fns_mode(bp); | 2167 | int cmng_fns = bnx2x_get_cmng_fns_mode(bp); |
2174 | 2168 | ||
@@ -2180,6 +2174,13 @@ static void bnx2x_link_attn(struct bnx2x *bp) | |||
2180 | DP(NETIF_MSG_IFUP, | 2174 | DP(NETIF_MSG_IFUP, |
2181 | "single function mode without fairness\n"); | 2175 | "single function mode without fairness\n"); |
2182 | } | 2176 | } |
2177 | |||
2178 | if (IS_MF(bp)) | ||
2179 | bnx2x_link_sync_notify(bp); | ||
2180 | |||
2181 | /* indicate link status only if link status actually changed */ | ||
2182 | if (prev_link_status != bp->link_vars.link_status) | ||
2183 | bnx2x_link_report(bp); | ||
2183 | } | 2184 | } |
2184 | 2185 | ||
2185 | void bnx2x__link_status_update(struct bnx2x *bp) | 2186 | void bnx2x__link_status_update(struct bnx2x *bp) |
diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c index 1024ae158227..a5d5d0b5b155 100644 --- a/drivers/net/bonding/bond_3ad.c +++ b/drivers/net/bonding/bond_3ad.c | |||
@@ -281,23 +281,23 @@ static inline int __check_agg_selection_timer(struct port *port) | |||
281 | } | 281 | } |
282 | 282 | ||
283 | /** | 283 | /** |
284 | * __get_rx_machine_lock - lock the port's RX machine | 284 | * __get_state_machine_lock - lock the port's state machines |
285 | * @port: the port we're looking at | 285 | * @port: the port we're looking at |
286 | * | 286 | * |
287 | */ | 287 | */ |
288 | static inline void __get_rx_machine_lock(struct port *port) | 288 | static inline void __get_state_machine_lock(struct port *port) |
289 | { | 289 | { |
290 | spin_lock_bh(&(SLAVE_AD_INFO(port->slave).rx_machine_lock)); | 290 | spin_lock_bh(&(SLAVE_AD_INFO(port->slave).state_machine_lock)); |
291 | } | 291 | } |
292 | 292 | ||
293 | /** | 293 | /** |
294 | * __release_rx_machine_lock - unlock the port's RX machine | 294 | * __release_state_machine_lock - unlock the port's state machines |
295 | * @port: the port we're looking at | 295 | * @port: the port we're looking at |
296 | * | 296 | * |
297 | */ | 297 | */ |
298 | static inline void __release_rx_machine_lock(struct port *port) | 298 | static inline void __release_state_machine_lock(struct port *port) |
299 | { | 299 | { |
300 | spin_unlock_bh(&(SLAVE_AD_INFO(port->slave).rx_machine_lock)); | 300 | spin_unlock_bh(&(SLAVE_AD_INFO(port->slave).state_machine_lock)); |
301 | } | 301 | } |
302 | 302 | ||
303 | /** | 303 | /** |
@@ -388,14 +388,14 @@ static u8 __get_duplex(struct port *port) | |||
388 | } | 388 | } |
389 | 389 | ||
390 | /** | 390 | /** |
391 | * __initialize_port_locks - initialize a port's RX machine spinlock | 391 | * __initialize_port_locks - initialize a port's STATE machine spinlock |
392 | * @port: the port we're looking at | 392 | * @port: the port we're looking at |
393 | * | 393 | * |
394 | */ | 394 | */ |
395 | static inline void __initialize_port_locks(struct port *port) | 395 | static inline void __initialize_port_locks(struct port *port) |
396 | { | 396 | { |
397 | // make sure it isn't called twice | 397 | // make sure it isn't called twice |
398 | spin_lock_init(&(SLAVE_AD_INFO(port->slave).rx_machine_lock)); | 398 | spin_lock_init(&(SLAVE_AD_INFO(port->slave).state_machine_lock)); |
399 | } | 399 | } |
400 | 400 | ||
401 | //conversions | 401 | //conversions |
@@ -1025,9 +1025,6 @@ static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port) | |||
1025 | { | 1025 | { |
1026 | rx_states_t last_state; | 1026 | rx_states_t last_state; |
1027 | 1027 | ||
1028 | // Lock to prevent 2 instances of this function to run simultaneously(rx interrupt and periodic machine callback) | ||
1029 | __get_rx_machine_lock(port); | ||
1030 | |||
1031 | // keep current State Machine state to compare later if it was changed | 1028 | // keep current State Machine state to compare later if it was changed |
1032 | last_state = port->sm_rx_state; | 1029 | last_state = port->sm_rx_state; |
1033 | 1030 | ||
@@ -1133,7 +1130,6 @@ static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port) | |||
1133 | pr_err("%s: An illegal loopback occurred on adapter (%s).\n" | 1130 | pr_err("%s: An illegal loopback occurred on adapter (%s).\n" |
1134 | "Check the configuration to verify that all adapters are connected to 802.3ad compliant switch ports\n", | 1131 | "Check the configuration to verify that all adapters are connected to 802.3ad compliant switch ports\n", |
1135 | port->slave->dev->master->name, port->slave->dev->name); | 1132 | port->slave->dev->master->name, port->slave->dev->name); |
1136 | __release_rx_machine_lock(port); | ||
1137 | return; | 1133 | return; |
1138 | } | 1134 | } |
1139 | __update_selected(lacpdu, port); | 1135 | __update_selected(lacpdu, port); |
@@ -1153,7 +1149,6 @@ static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port) | |||
1153 | break; | 1149 | break; |
1154 | } | 1150 | } |
1155 | } | 1151 | } |
1156 | __release_rx_machine_lock(port); | ||
1157 | } | 1152 | } |
1158 | 1153 | ||
1159 | /** | 1154 | /** |
@@ -2155,6 +2150,12 @@ void bond_3ad_state_machine_handler(struct work_struct *work) | |||
2155 | goto re_arm; | 2150 | goto re_arm; |
2156 | } | 2151 | } |
2157 | 2152 | ||
2153 | /* Lock around state machines to protect data accessed | ||
2154 | * by all (e.g., port->sm_vars). ad_rx_machine may run | ||
2155 | * concurrently due to incoming LACPDU. | ||
2156 | */ | ||
2157 | __get_state_machine_lock(port); | ||
2158 | |||
2158 | ad_rx_machine(NULL, port); | 2159 | ad_rx_machine(NULL, port); |
2159 | ad_periodic_machine(port); | 2160 | ad_periodic_machine(port); |
2160 | ad_port_selection_logic(port); | 2161 | ad_port_selection_logic(port); |
@@ -2164,6 +2165,8 @@ void bond_3ad_state_machine_handler(struct work_struct *work) | |||
2164 | // turn off the BEGIN bit, since we already handled it | 2165 | // turn off the BEGIN bit, since we already handled it |
2165 | if (port->sm_vars & AD_PORT_BEGIN) | 2166 | if (port->sm_vars & AD_PORT_BEGIN) |
2166 | port->sm_vars &= ~AD_PORT_BEGIN; | 2167 | port->sm_vars &= ~AD_PORT_BEGIN; |
2168 | |||
2169 | __release_state_machine_lock(port); | ||
2167 | } | 2170 | } |
2168 | 2171 | ||
2169 | re_arm: | 2172 | re_arm: |
@@ -2200,7 +2203,10 @@ static void bond_3ad_rx_indication(struct lacpdu *lacpdu, struct slave *slave, u | |||
2200 | case AD_TYPE_LACPDU: | 2203 | case AD_TYPE_LACPDU: |
2201 | pr_debug("Received LACPDU on port %d\n", | 2204 | pr_debug("Received LACPDU on port %d\n", |
2202 | port->actor_port_number); | 2205 | port->actor_port_number); |
2206 | /* Protect against concurrent state machines */ | ||
2207 | __get_state_machine_lock(port); | ||
2203 | ad_rx_machine(lacpdu, port); | 2208 | ad_rx_machine(lacpdu, port); |
2209 | __release_state_machine_lock(port); | ||
2204 | break; | 2210 | break; |
2205 | 2211 | ||
2206 | case AD_TYPE_MARKER: | 2212 | case AD_TYPE_MARKER: |
diff --git a/drivers/net/bonding/bond_3ad.h b/drivers/net/bonding/bond_3ad.h index 2c46a154f2c6..b28baff70864 100644 --- a/drivers/net/bonding/bond_3ad.h +++ b/drivers/net/bonding/bond_3ad.h | |||
@@ -264,7 +264,8 @@ struct ad_bond_info { | |||
264 | struct ad_slave_info { | 264 | struct ad_slave_info { |
265 | struct aggregator aggregator; // 802.3ad aggregator structure | 265 | struct aggregator aggregator; // 802.3ad aggregator structure |
266 | struct port port; // 802.3ad port structure | 266 | struct port port; // 802.3ad port structure |
267 | spinlock_t rx_machine_lock; // To avoid race condition between callback and receive interrupt | 267 | spinlock_t state_machine_lock; /* mutex state machines vs. |
268 | incoming LACPDU */ | ||
268 | u16 id; | 269 | u16 id; |
269 | }; | 270 | }; |
270 | 271 | ||
diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c index 5933621ac3ff..fc27a9926d9e 100644 --- a/drivers/net/macvtap.c +++ b/drivers/net/macvtap.c | |||
@@ -528,8 +528,9 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, | |||
528 | vnet_hdr_len = q->vnet_hdr_sz; | 528 | vnet_hdr_len = q->vnet_hdr_sz; |
529 | 529 | ||
530 | err = -EINVAL; | 530 | err = -EINVAL; |
531 | if ((len -= vnet_hdr_len) < 0) | 531 | if (len < vnet_hdr_len) |
532 | goto err; | 532 | goto err; |
533 | len -= vnet_hdr_len; | ||
533 | 534 | ||
534 | err = memcpy_fromiovecend((void *)&vnet_hdr, iv, 0, | 535 | err = memcpy_fromiovecend((void *)&vnet_hdr, iv, 0, |
535 | sizeof(vnet_hdr)); | 536 | sizeof(vnet_hdr)); |
diff --git a/drivers/net/r6040.c b/drivers/net/r6040.c index 27e6f6d43cac..e3ebd90ae651 100644 --- a/drivers/net/r6040.c +++ b/drivers/net/r6040.c | |||
@@ -49,8 +49,8 @@ | |||
49 | #include <asm/processor.h> | 49 | #include <asm/processor.h> |
50 | 50 | ||
51 | #define DRV_NAME "r6040" | 51 | #define DRV_NAME "r6040" |
52 | #define DRV_VERSION "0.26" | 52 | #define DRV_VERSION "0.27" |
53 | #define DRV_RELDATE "30May2010" | 53 | #define DRV_RELDATE "23Feb2011" |
54 | 54 | ||
55 | /* PHY CHIP Address */ | 55 | /* PHY CHIP Address */ |
56 | #define PHY1_ADDR 1 /* For MAC1 */ | 56 | #define PHY1_ADDR 1 /* For MAC1 */ |
@@ -69,6 +69,8 @@ | |||
69 | 69 | ||
70 | /* MAC registers */ | 70 | /* MAC registers */ |
71 | #define MCR0 0x00 /* Control register 0 */ | 71 | #define MCR0 0x00 /* Control register 0 */ |
72 | #define MCR0_PROMISC 0x0020 /* Promiscuous mode */ | ||
73 | #define MCR0_HASH_EN 0x0100 /* Enable multicast hash table function */ | ||
72 | #define MCR1 0x04 /* Control register 1 */ | 74 | #define MCR1 0x04 /* Control register 1 */ |
73 | #define MAC_RST 0x0001 /* Reset the MAC */ | 75 | #define MAC_RST 0x0001 /* Reset the MAC */ |
74 | #define MBCR 0x08 /* Bus control */ | 76 | #define MBCR 0x08 /* Bus control */ |
@@ -851,77 +853,92 @@ static void r6040_multicast_list(struct net_device *dev) | |||
851 | { | 853 | { |
852 | struct r6040_private *lp = netdev_priv(dev); | 854 | struct r6040_private *lp = netdev_priv(dev); |
853 | void __iomem *ioaddr = lp->base; | 855 | void __iomem *ioaddr = lp->base; |
854 | u16 *adrp; | ||
855 | u16 reg; | ||
856 | unsigned long flags; | 856 | unsigned long flags; |
857 | struct netdev_hw_addr *ha; | 857 | struct netdev_hw_addr *ha; |
858 | int i; | 858 | int i; |
859 | u16 *adrp; | ||
860 | u16 hash_table[4] = { 0 }; | ||
861 | |||
862 | spin_lock_irqsave(&lp->lock, flags); | ||
859 | 863 | ||
860 | /* MAC Address */ | 864 | /* Keep our MAC Address */ |
861 | adrp = (u16 *)dev->dev_addr; | 865 | adrp = (u16 *)dev->dev_addr; |
862 | iowrite16(adrp[0], ioaddr + MID_0L); | 866 | iowrite16(adrp[0], ioaddr + MID_0L); |
863 | iowrite16(adrp[1], ioaddr + MID_0M); | 867 | iowrite16(adrp[1], ioaddr + MID_0M); |
864 | iowrite16(adrp[2], ioaddr + MID_0H); | 868 | iowrite16(adrp[2], ioaddr + MID_0H); |
865 | 869 | ||
866 | /* Promiscous Mode */ | ||
867 | spin_lock_irqsave(&lp->lock, flags); | ||
868 | |||
869 | /* Clear AMCP & PROM bits */ | 870 | /* Clear AMCP & PROM bits */ |
870 | reg = ioread16(ioaddr) & ~0x0120; | 871 | lp->mcr0 = ioread16(ioaddr + MCR0) & ~(MCR0_PROMISC | MCR0_HASH_EN); |
871 | if (dev->flags & IFF_PROMISC) { | ||
872 | reg |= 0x0020; | ||
873 | lp->mcr0 |= 0x0020; | ||
874 | } | ||
875 | /* Too many multicast addresses | ||
876 | * accept all traffic */ | ||
877 | else if ((netdev_mc_count(dev) > MCAST_MAX) || | ||
878 | (dev->flags & IFF_ALLMULTI)) | ||
879 | reg |= 0x0020; | ||
880 | 872 | ||
881 | iowrite16(reg, ioaddr); | 873 | /* Promiscuous mode */ |
882 | spin_unlock_irqrestore(&lp->lock, flags); | 874 | if (dev->flags & IFF_PROMISC) |
875 | lp->mcr0 |= MCR0_PROMISC; | ||
883 | 876 | ||
884 | /* Build the hash table */ | 877 | /* Enable multicast hash table function to |
885 | if (netdev_mc_count(dev) > MCAST_MAX) { | 878 | * receive all multicast packets. */ |
886 | u16 hash_table[4]; | 879 | else if (dev->flags & IFF_ALLMULTI) { |
887 | u32 crc; | 880 | lp->mcr0 |= MCR0_HASH_EN; |
888 | 881 | ||
889 | for (i = 0; i < 4; i++) | 882 | for (i = 0; i < MCAST_MAX ; i++) { |
890 | hash_table[i] = 0; | 883 | iowrite16(0, ioaddr + MID_1L + 8 * i); |
884 | iowrite16(0, ioaddr + MID_1M + 8 * i); | ||
885 | iowrite16(0, ioaddr + MID_1H + 8 * i); | ||
886 | } | ||
891 | 887 | ||
888 | for (i = 0; i < 4; i++) | ||
889 | hash_table[i] = 0xffff; | ||
890 | } | ||
891 | /* Use internal multicast address registers if the number of | ||
892 | * multicast addresses is not greater than MCAST_MAX. */ | ||
893 | else if (netdev_mc_count(dev) <= MCAST_MAX) { | ||
894 | i = 0; | ||
892 | netdev_for_each_mc_addr(ha, dev) { | 895 | netdev_for_each_mc_addr(ha, dev) { |
893 | char *addrs = ha->addr; | 896 | u16 *adrp = (u16 *) ha->addr; |
897 | iowrite16(adrp[0], ioaddr + MID_1L + 8 * i); | ||
898 | iowrite16(adrp[1], ioaddr + MID_1M + 8 * i); | ||
899 | iowrite16(adrp[2], ioaddr + MID_1H + 8 * i); | ||
900 | i++; | ||
901 | } | ||
902 | while (i < MCAST_MAX) { | ||
903 | iowrite16(0, ioaddr + MID_1L + 8 * i); | ||
904 | iowrite16(0, ioaddr + MID_1M + 8 * i); | ||
905 | iowrite16(0, ioaddr + MID_1H + 8 * i); | ||
906 | i++; | ||
907 | } | ||
908 | } | ||
909 | /* Otherwise, Enable multicast hash table function. */ | ||
910 | else { | ||
911 | u32 crc; | ||
894 | 912 | ||
895 | if (!(*addrs & 1)) | 913 | lp->mcr0 |= MCR0_HASH_EN; |
896 | continue; | 914 | |
915 | for (i = 0; i < MCAST_MAX ; i++) { | ||
916 | iowrite16(0, ioaddr + MID_1L + 8 * i); | ||
917 | iowrite16(0, ioaddr + MID_1M + 8 * i); | ||
918 | iowrite16(0, ioaddr + MID_1H + 8 * i); | ||
919 | } | ||
897 | 920 | ||
898 | crc = ether_crc_le(6, addrs); | 921 | /* Build multicast hash table */ |
922 | netdev_for_each_mc_addr(ha, dev) { | ||
923 | u8 *addrs = ha->addr; | ||
924 | |||
925 | crc = ether_crc(ETH_ALEN, addrs); | ||
899 | crc >>= 26; | 926 | crc >>= 26; |
900 | hash_table[crc >> 4] |= 1 << (15 - (crc & 0xf)); | 927 | hash_table[crc >> 4] |= 1 << (crc & 0xf); |
901 | } | 928 | } |
902 | /* Fill the MAC hash tables with their values */ | 929 | } |
930 | |||
931 | iowrite16(lp->mcr0, ioaddr + MCR0); | ||
932 | |||
933 | /* Fill the MAC hash tables with their values */ | ||
934 | if (lp->mcr0 && MCR0_HASH_EN) { | ||
903 | iowrite16(hash_table[0], ioaddr + MAR0); | 935 | iowrite16(hash_table[0], ioaddr + MAR0); |
904 | iowrite16(hash_table[1], ioaddr + MAR1); | 936 | iowrite16(hash_table[1], ioaddr + MAR1); |
905 | iowrite16(hash_table[2], ioaddr + MAR2); | 937 | iowrite16(hash_table[2], ioaddr + MAR2); |
906 | iowrite16(hash_table[3], ioaddr + MAR3); | 938 | iowrite16(hash_table[3], ioaddr + MAR3); |
907 | } | 939 | } |
908 | /* Multicast Address 1~4 case */ | 940 | |
909 | i = 0; | 941 | spin_unlock_irqrestore(&lp->lock, flags); |
910 | netdev_for_each_mc_addr(ha, dev) { | ||
911 | if (i >= MCAST_MAX) | ||
912 | break; | ||
913 | adrp = (u16 *) ha->addr; | ||
914 | iowrite16(adrp[0], ioaddr + MID_1L + 8 * i); | ||
915 | iowrite16(adrp[1], ioaddr + MID_1M + 8 * i); | ||
916 | iowrite16(adrp[2], ioaddr + MID_1H + 8 * i); | ||
917 | i++; | ||
918 | } | ||
919 | while (i < MCAST_MAX) { | ||
920 | iowrite16(0xffff, ioaddr + MID_1L + 8 * i); | ||
921 | iowrite16(0xffff, ioaddr + MID_1M + 8 * i); | ||
922 | iowrite16(0xffff, ioaddr + MID_1H + 8 * i); | ||
923 | i++; | ||
924 | } | ||
925 | } | 942 | } |
926 | 943 | ||
927 | static void netdev_get_drvinfo(struct net_device *dev, | 944 | static void netdev_get_drvinfo(struct net_device *dev, |
diff --git a/drivers/net/smsc911x.c b/drivers/net/smsc911x.c index 64bfdae5956f..d70bde95460b 100644 --- a/drivers/net/smsc911x.c +++ b/drivers/net/smsc911x.c | |||
@@ -1178,6 +1178,11 @@ static int smsc911x_open(struct net_device *dev) | |||
1178 | smsc911x_reg_write(pdata, HW_CFG, 0x00050000); | 1178 | smsc911x_reg_write(pdata, HW_CFG, 0x00050000); |
1179 | smsc911x_reg_write(pdata, AFC_CFG, 0x006E3740); | 1179 | smsc911x_reg_write(pdata, AFC_CFG, 0x006E3740); |
1180 | 1180 | ||
1181 | /* Increase the legal frame size of VLAN tagged frames to 1522 bytes */ | ||
1182 | spin_lock_irq(&pdata->mac_lock); | ||
1183 | smsc911x_mac_write(pdata, VLAN1, ETH_P_8021Q); | ||
1184 | spin_unlock_irq(&pdata->mac_lock); | ||
1185 | |||
1181 | /* Make sure EEPROM has finished loading before setting GPIO_CFG */ | 1186 | /* Make sure EEPROM has finished loading before setting GPIO_CFG */ |
1182 | timeout = 50; | 1187 | timeout = 50; |
1183 | while ((smsc911x_reg_read(pdata, E2P_CMD) & E2P_CMD_EPC_BUSY_) && | 1188 | while ((smsc911x_reg_read(pdata, E2P_CMD) & E2P_CMD_EPC_BUSY_) && |
diff --git a/drivers/pci/xen-pcifront.c b/drivers/pci/xen-pcifront.c index 3a5a6fcc0ead..492b7d807fe8 100644 --- a/drivers/pci/xen-pcifront.c +++ b/drivers/pci/xen-pcifront.c | |||
@@ -243,7 +243,7 @@ struct pci_ops pcifront_bus_ops = { | |||
243 | 243 | ||
244 | #ifdef CONFIG_PCI_MSI | 244 | #ifdef CONFIG_PCI_MSI |
245 | static int pci_frontend_enable_msix(struct pci_dev *dev, | 245 | static int pci_frontend_enable_msix(struct pci_dev *dev, |
246 | int **vector, int nvec) | 246 | int vector[], int nvec) |
247 | { | 247 | { |
248 | int err; | 248 | int err; |
249 | int i; | 249 | int i; |
@@ -277,18 +277,24 @@ static int pci_frontend_enable_msix(struct pci_dev *dev, | |||
277 | if (likely(!err)) { | 277 | if (likely(!err)) { |
278 | if (likely(!op.value)) { | 278 | if (likely(!op.value)) { |
279 | /* we get the result */ | 279 | /* we get the result */ |
280 | for (i = 0; i < nvec; i++) | 280 | for (i = 0; i < nvec; i++) { |
281 | *(*vector+i) = op.msix_entries[i].vector; | 281 | if (op.msix_entries[i].vector <= 0) { |
282 | return 0; | 282 | dev_warn(&dev->dev, "MSI-X entry %d is invalid: %d!\n", |
283 | i, op.msix_entries[i].vector); | ||
284 | err = -EINVAL; | ||
285 | vector[i] = -1; | ||
286 | continue; | ||
287 | } | ||
288 | vector[i] = op.msix_entries[i].vector; | ||
289 | } | ||
283 | } else { | 290 | } else { |
284 | printk(KERN_DEBUG "enable msix get value %x\n", | 291 | printk(KERN_DEBUG "enable msix get value %x\n", |
285 | op.value); | 292 | op.value); |
286 | return op.value; | ||
287 | } | 293 | } |
288 | } else { | 294 | } else { |
289 | dev_err(&dev->dev, "enable msix get err %x\n", err); | 295 | dev_err(&dev->dev, "enable msix get err %x\n", err); |
290 | return err; | ||
291 | } | 296 | } |
297 | return err; | ||
292 | } | 298 | } |
293 | 299 | ||
294 | static void pci_frontend_disable_msix(struct pci_dev *dev) | 300 | static void pci_frontend_disable_msix(struct pci_dev *dev) |
@@ -310,7 +316,7 @@ static void pci_frontend_disable_msix(struct pci_dev *dev) | |||
310 | dev_err(&dev->dev, "pci_disable_msix get err %x\n", err); | 316 | dev_err(&dev->dev, "pci_disable_msix get err %x\n", err); |
311 | } | 317 | } |
312 | 318 | ||
313 | static int pci_frontend_enable_msi(struct pci_dev *dev, int **vector) | 319 | static int pci_frontend_enable_msi(struct pci_dev *dev, int vector[]) |
314 | { | 320 | { |
315 | int err; | 321 | int err; |
316 | struct xen_pci_op op = { | 322 | struct xen_pci_op op = { |
@@ -324,7 +330,13 @@ static int pci_frontend_enable_msi(struct pci_dev *dev, int **vector) | |||
324 | 330 | ||
325 | err = do_pci_op(pdev, &op); | 331 | err = do_pci_op(pdev, &op); |
326 | if (likely(!err)) { | 332 | if (likely(!err)) { |
327 | *(*vector) = op.value; | 333 | vector[0] = op.value; |
334 | if (op.value <= 0) { | ||
335 | dev_warn(&dev->dev, "MSI entry is invalid: %d!\n", | ||
336 | op.value); | ||
337 | err = -EINVAL; | ||
338 | vector[0] = -1; | ||
339 | } | ||
328 | } else { | 340 | } else { |
329 | dev_err(&dev->dev, "pci frontend enable msi failed for dev " | 341 | dev_err(&dev->dev, "pci frontend enable msi failed for dev " |
330 | "%x:%x\n", op.bus, op.devfn); | 342 | "%x:%x\n", op.bus, op.devfn); |
@@ -733,8 +745,7 @@ static void free_pdev(struct pcifront_device *pdev) | |||
733 | 745 | ||
734 | pcifront_free_roots(pdev); | 746 | pcifront_free_roots(pdev); |
735 | 747 | ||
736 | /*For PCIE_AER error handling job*/ | 748 | cancel_work_sync(&pdev->op_work); |
737 | flush_scheduled_work(); | ||
738 | 749 | ||
739 | if (pdev->irq >= 0) | 750 | if (pdev->irq >= 0) |
740 | unbind_from_irqhandler(pdev->irq, pdev); | 751 | unbind_from_irqhandler(pdev->irq, pdev); |
diff --git a/drivers/target/target_core_tmr.c b/drivers/target/target_core_tmr.c index 158cecbec718..4a109835e420 100644 --- a/drivers/target/target_core_tmr.c +++ b/drivers/target/target_core_tmr.c | |||
@@ -282,6 +282,9 @@ int core_tmr_lun_reset( | |||
282 | 282 | ||
283 | atomic_set(&task->task_active, 0); | 283 | atomic_set(&task->task_active, 0); |
284 | atomic_set(&task->task_stop, 0); | 284 | atomic_set(&task->task_stop, 0); |
285 | } else { | ||
286 | if (atomic_read(&task->task_execute_queue) != 0) | ||
287 | transport_remove_task_from_execute_queue(task, dev); | ||
285 | } | 288 | } |
286 | __transport_stop_task_timer(task, &flags); | 289 | __transport_stop_task_timer(task, &flags); |
287 | 290 | ||
@@ -301,6 +304,7 @@ int core_tmr_lun_reset( | |||
301 | DEBUG_LR("LUN_RESET: got t_transport_active = 1 for" | 304 | DEBUG_LR("LUN_RESET: got t_transport_active = 1 for" |
302 | " task: %p, t_fe_count: %d dev: %p\n", task, | 305 | " task: %p, t_fe_count: %d dev: %p\n", task, |
303 | fe_count, dev); | 306 | fe_count, dev); |
307 | atomic_set(&T_TASK(cmd)->t_transport_aborted, 1); | ||
304 | spin_unlock_irqrestore(&T_TASK(cmd)->t_state_lock, | 308 | spin_unlock_irqrestore(&T_TASK(cmd)->t_state_lock, |
305 | flags); | 309 | flags); |
306 | core_tmr_handle_tas_abort(tmr_nacl, cmd, tas, fe_count); | 310 | core_tmr_handle_tas_abort(tmr_nacl, cmd, tas, fe_count); |
@@ -310,6 +314,7 @@ int core_tmr_lun_reset( | |||
310 | } | 314 | } |
311 | DEBUG_LR("LUN_RESET: Got t_transport_active = 0 for task: %p," | 315 | DEBUG_LR("LUN_RESET: Got t_transport_active = 0 for task: %p," |
312 | " t_fe_count: %d dev: %p\n", task, fe_count, dev); | 316 | " t_fe_count: %d dev: %p\n", task, fe_count, dev); |
317 | atomic_set(&T_TASK(cmd)->t_transport_aborted, 1); | ||
313 | spin_unlock_irqrestore(&T_TASK(cmd)->t_state_lock, flags); | 318 | spin_unlock_irqrestore(&T_TASK(cmd)->t_state_lock, flags); |
314 | core_tmr_handle_tas_abort(tmr_nacl, cmd, tas, fe_count); | 319 | core_tmr_handle_tas_abort(tmr_nacl, cmd, tas, fe_count); |
315 | 320 | ||
diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 236e22d8cfae..4bbf6c147f89 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c | |||
@@ -1207,7 +1207,7 @@ transport_get_task_from_execute_queue(struct se_device *dev) | |||
1207 | * | 1207 | * |
1208 | * | 1208 | * |
1209 | */ | 1209 | */ |
1210 | static void transport_remove_task_from_execute_queue( | 1210 | void transport_remove_task_from_execute_queue( |
1211 | struct se_task *task, | 1211 | struct se_task *task, |
1212 | struct se_device *dev) | 1212 | struct se_device *dev) |
1213 | { | 1213 | { |
@@ -5549,7 +5549,8 @@ static void transport_generic_wait_for_tasks( | |||
5549 | 5549 | ||
5550 | atomic_set(&T_TASK(cmd)->transport_lun_stop, 0); | 5550 | atomic_set(&T_TASK(cmd)->transport_lun_stop, 0); |
5551 | } | 5551 | } |
5552 | if (!atomic_read(&T_TASK(cmd)->t_transport_active)) | 5552 | if (!atomic_read(&T_TASK(cmd)->t_transport_active) || |
5553 | atomic_read(&T_TASK(cmd)->t_transport_aborted)) | ||
5553 | goto remove; | 5554 | goto remove; |
5554 | 5555 | ||
5555 | atomic_set(&T_TASK(cmd)->t_transport_stop, 1); | 5556 | atomic_set(&T_TASK(cmd)->t_transport_stop, 1); |
@@ -5956,6 +5957,9 @@ static void transport_processing_shutdown(struct se_device *dev) | |||
5956 | 5957 | ||
5957 | atomic_set(&task->task_active, 0); | 5958 | atomic_set(&task->task_active, 0); |
5958 | atomic_set(&task->task_stop, 0); | 5959 | atomic_set(&task->task_stop, 0); |
5960 | } else { | ||
5961 | if (atomic_read(&task->task_execute_queue) != 0) | ||
5962 | transport_remove_task_from_execute_queue(task, dev); | ||
5959 | } | 5963 | } |
5960 | __transport_stop_task_timer(task, &flags); | 5964 | __transport_stop_task_timer(task, &flags); |
5961 | 5965 | ||
diff --git a/drivers/watchdog/cpwd.c b/drivers/watchdog/cpwd.c index eca855a55c0d..3de4ba0260a5 100644 --- a/drivers/watchdog/cpwd.c +++ b/drivers/watchdog/cpwd.c | |||
@@ -646,7 +646,7 @@ static int __devexit cpwd_remove(struct platform_device *op) | |||
646 | struct cpwd *p = dev_get_drvdata(&op->dev); | 646 | struct cpwd *p = dev_get_drvdata(&op->dev); |
647 | int i; | 647 | int i; |
648 | 648 | ||
649 | for (i = 0; i < 4; i++) { | 649 | for (i = 0; i < WD_NUMDEVS; i++) { |
650 | misc_deregister(&p->devs[i].misc); | 650 | misc_deregister(&p->devs[i].misc); |
651 | 651 | ||
652 | if (!p->enabled) { | 652 | if (!p->enabled) { |
diff --git a/drivers/watchdog/hpwdt.c b/drivers/watchdog/hpwdt.c index 24b966d5061a..204a5603c4ae 100644 --- a/drivers/watchdog/hpwdt.c +++ b/drivers/watchdog/hpwdt.c | |||
@@ -710,7 +710,7 @@ static int __devinit hpwdt_init_nmi_decoding(struct pci_dev *dev) | |||
710 | return 0; | 710 | return 0; |
711 | } | 711 | } |
712 | 712 | ||
713 | static void __devexit hpwdt_exit_nmi_decoding(void) | 713 | static void hpwdt_exit_nmi_decoding(void) |
714 | { | 714 | { |
715 | unregister_die_notifier(&die_notifier); | 715 | unregister_die_notifier(&die_notifier); |
716 | if (cru_rom_addr) | 716 | if (cru_rom_addr) |
@@ -726,7 +726,7 @@ static int __devinit hpwdt_init_nmi_decoding(struct pci_dev *dev) | |||
726 | return 0; | 726 | return 0; |
727 | } | 727 | } |
728 | 728 | ||
729 | static void __devexit hpwdt_exit_nmi_decoding(void) | 729 | static void hpwdt_exit_nmi_decoding(void) |
730 | { | 730 | { |
731 | } | 731 | } |
732 | #endif /* CONFIG_HPWDT_NMI_DECODING */ | 732 | #endif /* CONFIG_HPWDT_NMI_DECODING */ |
diff --git a/drivers/watchdog/sch311x_wdt.c b/drivers/watchdog/sch311x_wdt.c index 0461858e07d0..b61ab1c54293 100644 --- a/drivers/watchdog/sch311x_wdt.c +++ b/drivers/watchdog/sch311x_wdt.c | |||
@@ -508,7 +508,7 @@ static int __init sch311x_detect(int sio_config_port, unsigned short *addr) | |||
508 | sch311x_sio_outb(sio_config_port, 0x07, 0x0a); | 508 | sch311x_sio_outb(sio_config_port, 0x07, 0x0a); |
509 | 509 | ||
510 | /* Check if Logical Device Register is currently active */ | 510 | /* Check if Logical Device Register is currently active */ |
511 | if (sch311x_sio_inb(sio_config_port, 0x30) && 0x01 == 0) | 511 | if ((sch311x_sio_inb(sio_config_port, 0x30) & 0x01) == 0) |
512 | printk(KERN_INFO PFX "Seems that LDN 0x0a is not active...\n"); | 512 | printk(KERN_INFO PFX "Seems that LDN 0x0a is not active...\n"); |
513 | 513 | ||
514 | /* Get the base address of the runtime registers */ | 514 | /* Get the base address of the runtime registers */ |
diff --git a/drivers/watchdog/w83697ug_wdt.c b/drivers/watchdog/w83697ug_wdt.c index a6c12dec91a1..df2a64dc9672 100644 --- a/drivers/watchdog/w83697ug_wdt.c +++ b/drivers/watchdog/w83697ug_wdt.c | |||
@@ -109,7 +109,7 @@ static int w83697ug_select_wd_register(void) | |||
109 | outb_p(0x08, WDT_EFDR); /* select logical device 8 (GPIO2) */ | 109 | outb_p(0x08, WDT_EFDR); /* select logical device 8 (GPIO2) */ |
110 | outb_p(0x30, WDT_EFER); /* select CR30 */ | 110 | outb_p(0x30, WDT_EFER); /* select CR30 */ |
111 | c = inb_p(WDT_EFDR); | 111 | c = inb_p(WDT_EFDR); |
112 | outb_p(c || 0x01, WDT_EFDR); /* set bit 0 to activate GPIO2 */ | 112 | outb_p(c | 0x01, WDT_EFDR); /* set bit 0 to activate GPIO2 */ |
113 | 113 | ||
114 | return 0; | 114 | return 0; |
115 | } | 115 | } |
diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c index 43f9f02c7db0..718050ace08f 100644 --- a/drivers/xen/balloon.c +++ b/drivers/xen/balloon.c | |||
@@ -232,7 +232,7 @@ static int increase_reservation(unsigned long nr_pages) | |||
232 | set_phys_to_machine(pfn, frame_list[i]); | 232 | set_phys_to_machine(pfn, frame_list[i]); |
233 | 233 | ||
234 | /* Link back into the page tables if not highmem. */ | 234 | /* Link back into the page tables if not highmem. */ |
235 | if (pfn < max_low_pfn) { | 235 | if (!xen_hvm_domain() && pfn < max_low_pfn) { |
236 | int ret; | 236 | int ret; |
237 | ret = HYPERVISOR_update_va_mapping( | 237 | ret = HYPERVISOR_update_va_mapping( |
238 | (unsigned long)__va(pfn << PAGE_SHIFT), | 238 | (unsigned long)__va(pfn << PAGE_SHIFT), |
@@ -280,7 +280,7 @@ static int decrease_reservation(unsigned long nr_pages) | |||
280 | 280 | ||
281 | scrub_page(page); | 281 | scrub_page(page); |
282 | 282 | ||
283 | if (!PageHighMem(page)) { | 283 | if (!xen_hvm_domain() && !PageHighMem(page)) { |
284 | ret = HYPERVISOR_update_va_mapping( | 284 | ret = HYPERVISOR_update_va_mapping( |
285 | (unsigned long)__va(pfn << PAGE_SHIFT), | 285 | (unsigned long)__va(pfn << PAGE_SHIFT), |
286 | __pte_ma(0), 0); | 286 | __pte_ma(0), 0); |
@@ -296,7 +296,7 @@ static int decrease_reservation(unsigned long nr_pages) | |||
296 | /* No more mappings: invalidate P2M and add to balloon. */ | 296 | /* No more mappings: invalidate P2M and add to balloon. */ |
297 | for (i = 0; i < nr_pages; i++) { | 297 | for (i = 0; i < nr_pages; i++) { |
298 | pfn = mfn_to_pfn(frame_list[i]); | 298 | pfn = mfn_to_pfn(frame_list[i]); |
299 | set_phys_to_machine(pfn, INVALID_P2M_ENTRY); | 299 | __set_phys_to_machine(pfn, INVALID_P2M_ENTRY); |
300 | balloon_append(pfn_to_page(pfn)); | 300 | balloon_append(pfn_to_page(pfn)); |
301 | } | 301 | } |
302 | 302 | ||
@@ -392,15 +392,19 @@ static struct notifier_block xenstore_notifier; | |||
392 | 392 | ||
393 | static int __init balloon_init(void) | 393 | static int __init balloon_init(void) |
394 | { | 394 | { |
395 | unsigned long pfn, extra_pfn_end; | 395 | unsigned long pfn, nr_pages, extra_pfn_end; |
396 | struct page *page; | 396 | struct page *page; |
397 | 397 | ||
398 | if (!xen_pv_domain()) | 398 | if (!xen_domain()) |
399 | return -ENODEV; | 399 | return -ENODEV; |
400 | 400 | ||
401 | pr_info("xen_balloon: Initialising balloon driver.\n"); | 401 | pr_info("xen_balloon: Initialising balloon driver.\n"); |
402 | 402 | ||
403 | balloon_stats.current_pages = min(xen_start_info->nr_pages, max_pfn); | 403 | if (xen_pv_domain()) |
404 | nr_pages = xen_start_info->nr_pages; | ||
405 | else | ||
406 | nr_pages = max_pfn; | ||
407 | balloon_stats.current_pages = min(nr_pages, max_pfn); | ||
404 | balloon_stats.target_pages = balloon_stats.current_pages; | 408 | balloon_stats.target_pages = balloon_stats.current_pages; |
405 | balloon_stats.balloon_low = 0; | 409 | balloon_stats.balloon_low = 0; |
406 | balloon_stats.balloon_high = 0; | 410 | balloon_stats.balloon_high = 0; |
diff --git a/drivers/xen/events.c b/drivers/xen/events.c index 74681478100a..149fa875e396 100644 --- a/drivers/xen/events.c +++ b/drivers/xen/events.c | |||
@@ -114,7 +114,7 @@ struct cpu_evtchn_s { | |||
114 | static __initdata struct cpu_evtchn_s init_evtchn_mask = { | 114 | static __initdata struct cpu_evtchn_s init_evtchn_mask = { |
115 | .bits[0 ... (NR_EVENT_CHANNELS/BITS_PER_LONG)-1] = ~0ul, | 115 | .bits[0 ... (NR_EVENT_CHANNELS/BITS_PER_LONG)-1] = ~0ul, |
116 | }; | 116 | }; |
117 | static struct cpu_evtchn_s *cpu_evtchn_mask_p = &init_evtchn_mask; | 117 | static struct cpu_evtchn_s __refdata *cpu_evtchn_mask_p = &init_evtchn_mask; |
118 | 118 | ||
119 | static inline unsigned long *cpu_evtchn_mask(int cpu) | 119 | static inline unsigned long *cpu_evtchn_mask(int cpu) |
120 | { | 120 | { |
@@ -277,7 +277,7 @@ static void bind_evtchn_to_cpu(unsigned int chn, unsigned int cpu) | |||
277 | 277 | ||
278 | BUG_ON(irq == -1); | 278 | BUG_ON(irq == -1); |
279 | #ifdef CONFIG_SMP | 279 | #ifdef CONFIG_SMP |
280 | cpumask_copy(irq_to_desc(irq)->affinity, cpumask_of(cpu)); | 280 | cpumask_copy(irq_to_desc(irq)->irq_data.affinity, cpumask_of(cpu)); |
281 | #endif | 281 | #endif |
282 | 282 | ||
283 | clear_bit(chn, cpu_evtchn_mask(cpu_from_irq(irq))); | 283 | clear_bit(chn, cpu_evtchn_mask(cpu_from_irq(irq))); |
@@ -294,7 +294,7 @@ static void init_evtchn_cpu_bindings(void) | |||
294 | 294 | ||
295 | /* By default all event channels notify CPU#0. */ | 295 | /* By default all event channels notify CPU#0. */ |
296 | for_each_irq_desc(i, desc) { | 296 | for_each_irq_desc(i, desc) { |
297 | cpumask_copy(desc->affinity, cpumask_of(0)); | 297 | cpumask_copy(desc->irq_data.affinity, cpumask_of(0)); |
298 | } | 298 | } |
299 | #endif | 299 | #endif |
300 | 300 | ||
@@ -376,81 +376,69 @@ static void unmask_evtchn(int port) | |||
376 | put_cpu(); | 376 | put_cpu(); |
377 | } | 377 | } |
378 | 378 | ||
379 | static int get_nr_hw_irqs(void) | 379 | static int xen_allocate_irq_dynamic(void) |
380 | { | 380 | { |
381 | int ret = 1; | 381 | int first = 0; |
382 | int irq; | ||
382 | 383 | ||
383 | #ifdef CONFIG_X86_IO_APIC | 384 | #ifdef CONFIG_X86_IO_APIC |
384 | ret = get_nr_irqs_gsi(); | 385 | /* |
386 | * For an HVM guest or domain 0 which see "real" (emulated or | ||
387 | * actual repectively) GSIs we allocate dynamic IRQs | ||
388 | * e.g. those corresponding to event channels or MSIs | ||
389 | * etc. from the range above those "real" GSIs to avoid | ||
390 | * collisions. | ||
391 | */ | ||
392 | if (xen_initial_domain() || xen_hvm_domain()) | ||
393 | first = get_nr_irqs_gsi(); | ||
385 | #endif | 394 | #endif |
386 | 395 | ||
387 | return ret; | 396 | retry: |
388 | } | 397 | irq = irq_alloc_desc_from(first, -1); |
389 | 398 | ||
390 | static int find_unbound_pirq(int type) | 399 | if (irq == -ENOMEM && first > NR_IRQS_LEGACY) { |
391 | { | 400 | printk(KERN_ERR "Out of dynamic IRQ space and eating into GSI space. You should increase nr_irqs\n"); |
392 | int rc, i; | 401 | first = max(NR_IRQS_LEGACY, first - NR_IRQS_LEGACY); |
393 | struct physdev_get_free_pirq op_get_free_pirq; | 402 | goto retry; |
394 | op_get_free_pirq.type = type; | 403 | } |
395 | 404 | ||
396 | rc = HYPERVISOR_physdev_op(PHYSDEVOP_get_free_pirq, &op_get_free_pirq); | 405 | if (irq < 0) |
397 | if (!rc) | 406 | panic("No available IRQ to bind to: increase nr_irqs!\n"); |
398 | return op_get_free_pirq.pirq; | ||
399 | 407 | ||
400 | for (i = 0; i < nr_irqs; i++) { | 408 | return irq; |
401 | if (pirq_to_irq[i] < 0) | ||
402 | return i; | ||
403 | } | ||
404 | return -1; | ||
405 | } | 409 | } |
406 | 410 | ||
407 | static int find_unbound_irq(void) | 411 | static int xen_allocate_irq_gsi(unsigned gsi) |
408 | { | 412 | { |
409 | struct irq_data *data; | 413 | int irq; |
410 | int irq, res; | ||
411 | int bottom = get_nr_hw_irqs(); | ||
412 | int top = nr_irqs-1; | ||
413 | |||
414 | if (bottom == nr_irqs) | ||
415 | goto no_irqs; | ||
416 | 414 | ||
417 | /* This loop starts from the top of IRQ space and goes down. | 415 | /* |
418 | * We need this b/c if we have a PCI device in a Xen PV guest | 416 | * A PV guest has no concept of a GSI (since it has no ACPI |
419 | * we do not have an IO-APIC (though the backend might have them) | 417 | * nor access to/knowledge of the physical APICs). Therefore |
420 | * mapped in. To not have a collision of physical IRQs with the Xen | 418 | * all IRQs are dynamically allocated from the entire IRQ |
421 | * event channels start at the top of the IRQ space for virtual IRQs. | 419 | * space. |
422 | */ | 420 | */ |
423 | for (irq = top; irq > bottom; irq--) { | 421 | if (xen_pv_domain() && !xen_initial_domain()) |
424 | data = irq_get_irq_data(irq); | 422 | return xen_allocate_irq_dynamic(); |
425 | /* only 15->0 have init'd desc; handle irq > 16 */ | ||
426 | if (!data) | ||
427 | break; | ||
428 | if (data->chip == &no_irq_chip) | ||
429 | break; | ||
430 | if (data->chip != &xen_dynamic_chip) | ||
431 | continue; | ||
432 | if (irq_info[irq].type == IRQT_UNBOUND) | ||
433 | return irq; | ||
434 | } | ||
435 | |||
436 | if (irq == bottom) | ||
437 | goto no_irqs; | ||
438 | 423 | ||
439 | res = irq_alloc_desc_at(irq, -1); | 424 | /* Legacy IRQ descriptors are already allocated by the arch. */ |
425 | if (gsi < NR_IRQS_LEGACY) | ||
426 | return gsi; | ||
440 | 427 | ||
441 | if (WARN_ON(res != irq)) | 428 | irq = irq_alloc_desc_at(gsi, -1); |
442 | return -1; | 429 | if (irq < 0) |
430 | panic("Unable to allocate to IRQ%d (%d)\n", gsi, irq); | ||
443 | 431 | ||
444 | return irq; | 432 | return irq; |
445 | |||
446 | no_irqs: | ||
447 | panic("No available IRQ to bind to: increase nr_irqs!\n"); | ||
448 | } | 433 | } |
449 | 434 | ||
450 | static bool identity_mapped_irq(unsigned irq) | 435 | static void xen_free_irq(unsigned irq) |
451 | { | 436 | { |
452 | /* identity map all the hardware irqs */ | 437 | /* Legacy IRQ descriptors are managed by the arch. */ |
453 | return irq < get_nr_hw_irqs(); | 438 | if (irq < NR_IRQS_LEGACY) |
439 | return; | ||
440 | |||
441 | irq_free_desc(irq); | ||
454 | } | 442 | } |
455 | 443 | ||
456 | static void pirq_unmask_notify(int irq) | 444 | static void pirq_unmask_notify(int irq) |
@@ -486,7 +474,7 @@ static bool probing_irq(int irq) | |||
486 | return desc && desc->action == NULL; | 474 | return desc && desc->action == NULL; |
487 | } | 475 | } |
488 | 476 | ||
489 | static unsigned int startup_pirq(unsigned int irq) | 477 | static unsigned int __startup_pirq(unsigned int irq) |
490 | { | 478 | { |
491 | struct evtchn_bind_pirq bind_pirq; | 479 | struct evtchn_bind_pirq bind_pirq; |
492 | struct irq_info *info = info_for_irq(irq); | 480 | struct irq_info *info = info_for_irq(irq); |
@@ -524,9 +512,15 @@ out: | |||
524 | return 0; | 512 | return 0; |
525 | } | 513 | } |
526 | 514 | ||
527 | static void shutdown_pirq(unsigned int irq) | 515 | static unsigned int startup_pirq(struct irq_data *data) |
516 | { | ||
517 | return __startup_pirq(data->irq); | ||
518 | } | ||
519 | |||
520 | static void shutdown_pirq(struct irq_data *data) | ||
528 | { | 521 | { |
529 | struct evtchn_close close; | 522 | struct evtchn_close close; |
523 | unsigned int irq = data->irq; | ||
530 | struct irq_info *info = info_for_irq(irq); | 524 | struct irq_info *info = info_for_irq(irq); |
531 | int evtchn = evtchn_from_irq(irq); | 525 | int evtchn = evtchn_from_irq(irq); |
532 | 526 | ||
@@ -546,20 +540,20 @@ static void shutdown_pirq(unsigned int irq) | |||
546 | info->evtchn = 0; | 540 | info->evtchn = 0; |
547 | } | 541 | } |
548 | 542 | ||
549 | static void enable_pirq(unsigned int irq) | 543 | static void enable_pirq(struct irq_data *data) |
550 | { | 544 | { |
551 | startup_pirq(irq); | 545 | startup_pirq(data); |
552 | } | 546 | } |
553 | 547 | ||
554 | static void disable_pirq(unsigned int irq) | 548 | static void disable_pirq(struct irq_data *data) |
555 | { | 549 | { |
556 | } | 550 | } |
557 | 551 | ||
558 | static void ack_pirq(unsigned int irq) | 552 | static void ack_pirq(struct irq_data *data) |
559 | { | 553 | { |
560 | int evtchn = evtchn_from_irq(irq); | 554 | int evtchn = evtchn_from_irq(data->irq); |
561 | 555 | ||
562 | move_native_irq(irq); | 556 | move_native_irq(data->irq); |
563 | 557 | ||
564 | if (VALID_EVTCHN(evtchn)) { | 558 | if (VALID_EVTCHN(evtchn)) { |
565 | mask_evtchn(evtchn); | 559 | mask_evtchn(evtchn); |
@@ -567,23 +561,6 @@ static void ack_pirq(unsigned int irq) | |||
567 | } | 561 | } |
568 | } | 562 | } |
569 | 563 | ||
570 | static void end_pirq(unsigned int irq) | ||
571 | { | ||
572 | int evtchn = evtchn_from_irq(irq); | ||
573 | struct irq_desc *desc = irq_to_desc(irq); | ||
574 | |||
575 | if (WARN_ON(!desc)) | ||
576 | return; | ||
577 | |||
578 | if ((desc->status & (IRQ_DISABLED|IRQ_PENDING)) == | ||
579 | (IRQ_DISABLED|IRQ_PENDING)) { | ||
580 | shutdown_pirq(irq); | ||
581 | } else if (VALID_EVTCHN(evtchn)) { | ||
582 | unmask_evtchn(evtchn); | ||
583 | pirq_unmask_notify(irq); | ||
584 | } | ||
585 | } | ||
586 | |||
587 | static int find_irq_by_gsi(unsigned gsi) | 564 | static int find_irq_by_gsi(unsigned gsi) |
588 | { | 565 | { |
589 | int irq; | 566 | int irq; |
@@ -638,14 +615,7 @@ int xen_map_pirq_gsi(unsigned pirq, unsigned gsi, int shareable, char *name) | |||
638 | goto out; /* XXX need refcount? */ | 615 | goto out; /* XXX need refcount? */ |
639 | } | 616 | } |
640 | 617 | ||
641 | /* If we are a PV guest, we don't have GSIs (no ACPI passed). Therefore | 618 | irq = xen_allocate_irq_gsi(gsi); |
642 | * we are using the !xen_initial_domain() to drop in the function.*/ | ||
643 | if (identity_mapped_irq(gsi) || (!xen_initial_domain() && | ||
644 | xen_pv_domain())) { | ||
645 | irq = gsi; | ||
646 | irq_alloc_desc_at(irq, -1); | ||
647 | } else | ||
648 | irq = find_unbound_irq(); | ||
649 | 619 | ||
650 | set_irq_chip_and_handler_name(irq, &xen_pirq_chip, | 620 | set_irq_chip_and_handler_name(irq, &xen_pirq_chip, |
651 | handle_level_irq, name); | 621 | handle_level_irq, name); |
@@ -658,7 +628,7 @@ int xen_map_pirq_gsi(unsigned pirq, unsigned gsi, int shareable, char *name) | |||
658 | * this in the priv domain. */ | 628 | * this in the priv domain. */ |
659 | if (xen_initial_domain() && | 629 | if (xen_initial_domain() && |
660 | HYPERVISOR_physdev_op(PHYSDEVOP_alloc_irq_vector, &irq_op)) { | 630 | HYPERVISOR_physdev_op(PHYSDEVOP_alloc_irq_vector, &irq_op)) { |
661 | irq_free_desc(irq); | 631 | xen_free_irq(irq); |
662 | irq = -ENOSPC; | 632 | irq = -ENOSPC; |
663 | goto out; | 633 | goto out; |
664 | } | 634 | } |
@@ -674,87 +644,46 @@ out: | |||
674 | } | 644 | } |
675 | 645 | ||
676 | #ifdef CONFIG_PCI_MSI | 646 | #ifdef CONFIG_PCI_MSI |
677 | #include <linux/msi.h> | 647 | int xen_allocate_pirq_msi(struct pci_dev *dev, struct msi_desc *msidesc) |
678 | #include "../pci/msi.h" | ||
679 | |||
680 | void xen_allocate_pirq_msi(char *name, int *irq, int *pirq, int alloc) | ||
681 | { | 648 | { |
682 | spin_lock(&irq_mapping_update_lock); | 649 | int rc; |
683 | 650 | struct physdev_get_free_pirq op_get_free_pirq; | |
684 | if (alloc & XEN_ALLOC_IRQ) { | ||
685 | *irq = find_unbound_irq(); | ||
686 | if (*irq == -1) | ||
687 | goto out; | ||
688 | } | ||
689 | |||
690 | if (alloc & XEN_ALLOC_PIRQ) { | ||
691 | *pirq = find_unbound_pirq(MAP_PIRQ_TYPE_MSI); | ||
692 | if (*pirq == -1) | ||
693 | goto out; | ||
694 | } | ||
695 | 651 | ||
696 | set_irq_chip_and_handler_name(*irq, &xen_pirq_chip, | 652 | op_get_free_pirq.type = MAP_PIRQ_TYPE_MSI; |
697 | handle_level_irq, name); | 653 | rc = HYPERVISOR_physdev_op(PHYSDEVOP_get_free_pirq, &op_get_free_pirq); |
698 | 654 | ||
699 | irq_info[*irq] = mk_pirq_info(0, *pirq, 0, 0); | 655 | WARN_ONCE(rc == -ENOSYS, |
700 | pirq_to_irq[*pirq] = *irq; | 656 | "hypervisor does not support the PHYSDEVOP_get_free_pirq interface\n"); |
701 | 657 | ||
702 | out: | 658 | return rc ? -1 : op_get_free_pirq.pirq; |
703 | spin_unlock(&irq_mapping_update_lock); | ||
704 | } | 659 | } |
705 | 660 | ||
706 | int xen_create_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc, int type) | 661 | int xen_bind_pirq_msi_to_irq(struct pci_dev *dev, struct msi_desc *msidesc, |
662 | int pirq, int vector, const char *name) | ||
707 | { | 663 | { |
708 | int irq = -1; | 664 | int irq, ret; |
709 | struct physdev_map_pirq map_irq; | ||
710 | int rc; | ||
711 | int pos; | ||
712 | u32 table_offset, bir; | ||
713 | |||
714 | memset(&map_irq, 0, sizeof(map_irq)); | ||
715 | map_irq.domid = DOMID_SELF; | ||
716 | map_irq.type = MAP_PIRQ_TYPE_MSI; | ||
717 | map_irq.index = -1; | ||
718 | map_irq.pirq = -1; | ||
719 | map_irq.bus = dev->bus->number; | ||
720 | map_irq.devfn = dev->devfn; | ||
721 | |||
722 | if (type == PCI_CAP_ID_MSIX) { | ||
723 | pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); | ||
724 | |||
725 | pci_read_config_dword(dev, msix_table_offset_reg(pos), | ||
726 | &table_offset); | ||
727 | bir = (u8)(table_offset & PCI_MSIX_FLAGS_BIRMASK); | ||
728 | |||
729 | map_irq.table_base = pci_resource_start(dev, bir); | ||
730 | map_irq.entry_nr = msidesc->msi_attrib.entry_nr; | ||
731 | } | ||
732 | 665 | ||
733 | spin_lock(&irq_mapping_update_lock); | 666 | spin_lock(&irq_mapping_update_lock); |
734 | 667 | ||
735 | irq = find_unbound_irq(); | 668 | irq = xen_allocate_irq_dynamic(); |
736 | |||
737 | if (irq == -1) | 669 | if (irq == -1) |
738 | goto out; | 670 | goto out; |
739 | 671 | ||
740 | rc = HYPERVISOR_physdev_op(PHYSDEVOP_map_pirq, &map_irq); | ||
741 | if (rc) { | ||
742 | printk(KERN_WARNING "xen map irq failed %d\n", rc); | ||
743 | |||
744 | irq_free_desc(irq); | ||
745 | |||
746 | irq = -1; | ||
747 | goto out; | ||
748 | } | ||
749 | irq_info[irq] = mk_pirq_info(0, map_irq.pirq, 0, map_irq.index); | ||
750 | |||
751 | set_irq_chip_and_handler_name(irq, &xen_pirq_chip, | 672 | set_irq_chip_and_handler_name(irq, &xen_pirq_chip, |
752 | handle_level_irq, | 673 | handle_level_irq, name); |
753 | (type == PCI_CAP_ID_MSIX) ? "msi-x":"msi"); | ||
754 | 674 | ||
675 | irq_info[irq] = mk_pirq_info(0, pirq, 0, vector); | ||
676 | pirq_to_irq[pirq] = irq; | ||
677 | ret = set_irq_msi(irq, msidesc); | ||
678 | if (ret < 0) | ||
679 | goto error_irq; | ||
755 | out: | 680 | out: |
756 | spin_unlock(&irq_mapping_update_lock); | 681 | spin_unlock(&irq_mapping_update_lock); |
757 | return irq; | 682 | return irq; |
683 | error_irq: | ||
684 | spin_unlock(&irq_mapping_update_lock); | ||
685 | xen_free_irq(irq); | ||
686 | return -1; | ||
758 | } | 687 | } |
759 | #endif | 688 | #endif |
760 | 689 | ||
@@ -779,11 +708,12 @@ int xen_destroy_irq(int irq) | |||
779 | printk(KERN_WARNING "unmap irq failed %d\n", rc); | 708 | printk(KERN_WARNING "unmap irq failed %d\n", rc); |
780 | goto out; | 709 | goto out; |
781 | } | 710 | } |
782 | pirq_to_irq[info->u.pirq.pirq] = -1; | ||
783 | } | 711 | } |
712 | pirq_to_irq[info->u.pirq.pirq] = -1; | ||
713 | |||
784 | irq_info[irq] = mk_unbound_info(); | 714 | irq_info[irq] = mk_unbound_info(); |
785 | 715 | ||
786 | irq_free_desc(irq); | 716 | xen_free_irq(irq); |
787 | 717 | ||
788 | out: | 718 | out: |
789 | spin_unlock(&irq_mapping_update_lock); | 719 | spin_unlock(&irq_mapping_update_lock); |
@@ -814,7 +744,7 @@ int bind_evtchn_to_irq(unsigned int evtchn) | |||
814 | irq = evtchn_to_irq[evtchn]; | 744 | irq = evtchn_to_irq[evtchn]; |
815 | 745 | ||
816 | if (irq == -1) { | 746 | if (irq == -1) { |
817 | irq = find_unbound_irq(); | 747 | irq = xen_allocate_irq_dynamic(); |
818 | 748 | ||
819 | set_irq_chip_and_handler_name(irq, &xen_dynamic_chip, | 749 | set_irq_chip_and_handler_name(irq, &xen_dynamic_chip, |
820 | handle_fasteoi_irq, "event"); | 750 | handle_fasteoi_irq, "event"); |
@@ -839,7 +769,7 @@ static int bind_ipi_to_irq(unsigned int ipi, unsigned int cpu) | |||
839 | irq = per_cpu(ipi_to_irq, cpu)[ipi]; | 769 | irq = per_cpu(ipi_to_irq, cpu)[ipi]; |
840 | 770 | ||
841 | if (irq == -1) { | 771 | if (irq == -1) { |
842 | irq = find_unbound_irq(); | 772 | irq = xen_allocate_irq_dynamic(); |
843 | if (irq < 0) | 773 | if (irq < 0) |
844 | goto out; | 774 | goto out; |
845 | 775 | ||
@@ -875,7 +805,7 @@ int bind_virq_to_irq(unsigned int virq, unsigned int cpu) | |||
875 | irq = per_cpu(virq_to_irq, cpu)[virq]; | 805 | irq = per_cpu(virq_to_irq, cpu)[virq]; |
876 | 806 | ||
877 | if (irq == -1) { | 807 | if (irq == -1) { |
878 | irq = find_unbound_irq(); | 808 | irq = xen_allocate_irq_dynamic(); |
879 | 809 | ||
880 | set_irq_chip_and_handler_name(irq, &xen_percpu_chip, | 810 | set_irq_chip_and_handler_name(irq, &xen_percpu_chip, |
881 | handle_percpu_irq, "virq"); | 811 | handle_percpu_irq, "virq"); |
@@ -934,7 +864,7 @@ static void unbind_from_irq(unsigned int irq) | |||
934 | if (irq_info[irq].type != IRQT_UNBOUND) { | 864 | if (irq_info[irq].type != IRQT_UNBOUND) { |
935 | irq_info[irq] = mk_unbound_info(); | 865 | irq_info[irq] = mk_unbound_info(); |
936 | 866 | ||
937 | irq_free_desc(irq); | 867 | xen_free_irq(irq); |
938 | } | 868 | } |
939 | 869 | ||
940 | spin_unlock(&irq_mapping_update_lock); | 870 | spin_unlock(&irq_mapping_update_lock); |
@@ -990,7 +920,7 @@ int bind_ipi_to_irqhandler(enum ipi_vector ipi, | |||
990 | if (irq < 0) | 920 | if (irq < 0) |
991 | return irq; | 921 | return irq; |
992 | 922 | ||
993 | irqflags |= IRQF_NO_SUSPEND; | 923 | irqflags |= IRQF_NO_SUSPEND | IRQF_FORCE_RESUME; |
994 | retval = request_irq(irq, handler, irqflags, devname, dev_id); | 924 | retval = request_irq(irq, handler, irqflags, devname, dev_id); |
995 | if (retval != 0) { | 925 | if (retval != 0) { |
996 | unbind_from_irq(irq); | 926 | unbind_from_irq(irq); |
@@ -1234,11 +1164,12 @@ static int rebind_irq_to_cpu(unsigned irq, unsigned tcpu) | |||
1234 | return 0; | 1164 | return 0; |
1235 | } | 1165 | } |
1236 | 1166 | ||
1237 | static int set_affinity_irq(unsigned irq, const struct cpumask *dest) | 1167 | static int set_affinity_irq(struct irq_data *data, const struct cpumask *dest, |
1168 | bool force) | ||
1238 | { | 1169 | { |
1239 | unsigned tcpu = cpumask_first(dest); | 1170 | unsigned tcpu = cpumask_first(dest); |
1240 | 1171 | ||
1241 | return rebind_irq_to_cpu(irq, tcpu); | 1172 | return rebind_irq_to_cpu(data->irq, tcpu); |
1242 | } | 1173 | } |
1243 | 1174 | ||
1244 | int resend_irq_on_evtchn(unsigned int irq) | 1175 | int resend_irq_on_evtchn(unsigned int irq) |
@@ -1257,35 +1188,35 @@ int resend_irq_on_evtchn(unsigned int irq) | |||
1257 | return 1; | 1188 | return 1; |
1258 | } | 1189 | } |
1259 | 1190 | ||
1260 | static void enable_dynirq(unsigned int irq) | 1191 | static void enable_dynirq(struct irq_data *data) |
1261 | { | 1192 | { |
1262 | int evtchn = evtchn_from_irq(irq); | 1193 | int evtchn = evtchn_from_irq(data->irq); |
1263 | 1194 | ||
1264 | if (VALID_EVTCHN(evtchn)) | 1195 | if (VALID_EVTCHN(evtchn)) |
1265 | unmask_evtchn(evtchn); | 1196 | unmask_evtchn(evtchn); |
1266 | } | 1197 | } |
1267 | 1198 | ||
1268 | static void disable_dynirq(unsigned int irq) | 1199 | static void disable_dynirq(struct irq_data *data) |
1269 | { | 1200 | { |
1270 | int evtchn = evtchn_from_irq(irq); | 1201 | int evtchn = evtchn_from_irq(data->irq); |
1271 | 1202 | ||
1272 | if (VALID_EVTCHN(evtchn)) | 1203 | if (VALID_EVTCHN(evtchn)) |
1273 | mask_evtchn(evtchn); | 1204 | mask_evtchn(evtchn); |
1274 | } | 1205 | } |
1275 | 1206 | ||
1276 | static void ack_dynirq(unsigned int irq) | 1207 | static void ack_dynirq(struct irq_data *data) |
1277 | { | 1208 | { |
1278 | int evtchn = evtchn_from_irq(irq); | 1209 | int evtchn = evtchn_from_irq(data->irq); |
1279 | 1210 | ||
1280 | move_masked_irq(irq); | 1211 | move_masked_irq(data->irq); |
1281 | 1212 | ||
1282 | if (VALID_EVTCHN(evtchn)) | 1213 | if (VALID_EVTCHN(evtchn)) |
1283 | unmask_evtchn(evtchn); | 1214 | unmask_evtchn(evtchn); |
1284 | } | 1215 | } |
1285 | 1216 | ||
1286 | static int retrigger_dynirq(unsigned int irq) | 1217 | static int retrigger_dynirq(struct irq_data *data) |
1287 | { | 1218 | { |
1288 | int evtchn = evtchn_from_irq(irq); | 1219 | int evtchn = evtchn_from_irq(data->irq); |
1289 | struct shared_info *sh = HYPERVISOR_shared_info; | 1220 | struct shared_info *sh = HYPERVISOR_shared_info; |
1290 | int ret = 0; | 1221 | int ret = 0; |
1291 | 1222 | ||
@@ -1334,7 +1265,7 @@ static void restore_cpu_pirqs(void) | |||
1334 | 1265 | ||
1335 | printk(KERN_DEBUG "xen: --> irq=%d, pirq=%d\n", irq, map_irq.pirq); | 1266 | printk(KERN_DEBUG "xen: --> irq=%d, pirq=%d\n", irq, map_irq.pirq); |
1336 | 1267 | ||
1337 | startup_pirq(irq); | 1268 | __startup_pirq(irq); |
1338 | } | 1269 | } |
1339 | } | 1270 | } |
1340 | 1271 | ||
@@ -1445,7 +1376,6 @@ void xen_poll_irq(int irq) | |||
1445 | void xen_irq_resume(void) | 1376 | void xen_irq_resume(void) |
1446 | { | 1377 | { |
1447 | unsigned int cpu, irq, evtchn; | 1378 | unsigned int cpu, irq, evtchn; |
1448 | struct irq_desc *desc; | ||
1449 | 1379 | ||
1450 | init_evtchn_cpu_bindings(); | 1380 | init_evtchn_cpu_bindings(); |
1451 | 1381 | ||
@@ -1465,66 +1395,48 @@ void xen_irq_resume(void) | |||
1465 | restore_cpu_ipis(cpu); | 1395 | restore_cpu_ipis(cpu); |
1466 | } | 1396 | } |
1467 | 1397 | ||
1468 | /* | ||
1469 | * Unmask any IRQF_NO_SUSPEND IRQs which are enabled. These | ||
1470 | * are not handled by the IRQ core. | ||
1471 | */ | ||
1472 | for_each_irq_desc(irq, desc) { | ||
1473 | if (!desc->action || !(desc->action->flags & IRQF_NO_SUSPEND)) | ||
1474 | continue; | ||
1475 | if (desc->status & IRQ_DISABLED) | ||
1476 | continue; | ||
1477 | |||
1478 | evtchn = evtchn_from_irq(irq); | ||
1479 | if (evtchn == -1) | ||
1480 | continue; | ||
1481 | |||
1482 | unmask_evtchn(evtchn); | ||
1483 | } | ||
1484 | |||
1485 | restore_cpu_pirqs(); | 1398 | restore_cpu_pirqs(); |
1486 | } | 1399 | } |
1487 | 1400 | ||
1488 | static struct irq_chip xen_dynamic_chip __read_mostly = { | 1401 | static struct irq_chip xen_dynamic_chip __read_mostly = { |
1489 | .name = "xen-dyn", | 1402 | .name = "xen-dyn", |
1490 | 1403 | ||
1491 | .disable = disable_dynirq, | 1404 | .irq_disable = disable_dynirq, |
1492 | .mask = disable_dynirq, | 1405 | .irq_mask = disable_dynirq, |
1493 | .unmask = enable_dynirq, | 1406 | .irq_unmask = enable_dynirq, |
1494 | 1407 | ||
1495 | .eoi = ack_dynirq, | 1408 | .irq_eoi = ack_dynirq, |
1496 | .set_affinity = set_affinity_irq, | 1409 | .irq_set_affinity = set_affinity_irq, |
1497 | .retrigger = retrigger_dynirq, | 1410 | .irq_retrigger = retrigger_dynirq, |
1498 | }; | 1411 | }; |
1499 | 1412 | ||
1500 | static struct irq_chip xen_pirq_chip __read_mostly = { | 1413 | static struct irq_chip xen_pirq_chip __read_mostly = { |
1501 | .name = "xen-pirq", | 1414 | .name = "xen-pirq", |
1502 | 1415 | ||
1503 | .startup = startup_pirq, | 1416 | .irq_startup = startup_pirq, |
1504 | .shutdown = shutdown_pirq, | 1417 | .irq_shutdown = shutdown_pirq, |
1505 | 1418 | ||
1506 | .enable = enable_pirq, | 1419 | .irq_enable = enable_pirq, |
1507 | .unmask = enable_pirq, | 1420 | .irq_unmask = enable_pirq, |
1508 | 1421 | ||
1509 | .disable = disable_pirq, | 1422 | .irq_disable = disable_pirq, |
1510 | .mask = disable_pirq, | 1423 | .irq_mask = disable_pirq, |
1511 | 1424 | ||
1512 | .ack = ack_pirq, | 1425 | .irq_ack = ack_pirq, |
1513 | .end = end_pirq, | ||
1514 | 1426 | ||
1515 | .set_affinity = set_affinity_irq, | 1427 | .irq_set_affinity = set_affinity_irq, |
1516 | 1428 | ||
1517 | .retrigger = retrigger_dynirq, | 1429 | .irq_retrigger = retrigger_dynirq, |
1518 | }; | 1430 | }; |
1519 | 1431 | ||
1520 | static struct irq_chip xen_percpu_chip __read_mostly = { | 1432 | static struct irq_chip xen_percpu_chip __read_mostly = { |
1521 | .name = "xen-percpu", | 1433 | .name = "xen-percpu", |
1522 | 1434 | ||
1523 | .disable = disable_dynirq, | 1435 | .irq_disable = disable_dynirq, |
1524 | .mask = disable_dynirq, | 1436 | .irq_mask = disable_dynirq, |
1525 | .unmask = enable_dynirq, | 1437 | .irq_unmask = enable_dynirq, |
1526 | 1438 | ||
1527 | .ack = ack_dynirq, | 1439 | .irq_ack = ack_dynirq, |
1528 | }; | 1440 | }; |
1529 | 1441 | ||
1530 | int xen_set_callback_via(uint64_t via) | 1442 | int xen_set_callback_via(uint64_t via) |
diff --git a/drivers/xen/manage.c b/drivers/xen/manage.c index 24177272bcb8..ebb292859b59 100644 --- a/drivers/xen/manage.c +++ b/drivers/xen/manage.c | |||
@@ -34,42 +34,38 @@ enum shutdown_state { | |||
34 | /* Ignore multiple shutdown requests. */ | 34 | /* Ignore multiple shutdown requests. */ |
35 | static enum shutdown_state shutting_down = SHUTDOWN_INVALID; | 35 | static enum shutdown_state shutting_down = SHUTDOWN_INVALID; |
36 | 36 | ||
37 | #ifdef CONFIG_PM_SLEEP | 37 | struct suspend_info { |
38 | static int xen_hvm_suspend(void *data) | 38 | int cancelled; |
39 | { | 39 | unsigned long arg; /* extra hypercall argument */ |
40 | int err; | 40 | void (*pre)(void); |
41 | struct sched_shutdown r = { .reason = SHUTDOWN_suspend }; | 41 | void (*post)(int cancelled); |
42 | int *cancelled = data; | 42 | }; |
43 | |||
44 | BUG_ON(!irqs_disabled()); | ||
45 | |||
46 | err = sysdev_suspend(PMSG_SUSPEND); | ||
47 | if (err) { | ||
48 | printk(KERN_ERR "xen_hvm_suspend: sysdev_suspend failed: %d\n", | ||
49 | err); | ||
50 | return err; | ||
51 | } | ||
52 | |||
53 | *cancelled = HYPERVISOR_sched_op(SCHEDOP_shutdown, &r); | ||
54 | 43 | ||
55 | xen_hvm_post_suspend(*cancelled); | 44 | static void xen_hvm_post_suspend(int cancelled) |
45 | { | ||
46 | xen_arch_hvm_post_suspend(cancelled); | ||
56 | gnttab_resume(); | 47 | gnttab_resume(); |
48 | } | ||
57 | 49 | ||
58 | if (!*cancelled) { | 50 | static void xen_pre_suspend(void) |
59 | xen_irq_resume(); | 51 | { |
60 | xen_console_resume(); | 52 | xen_mm_pin_all(); |
61 | xen_timer_resume(); | 53 | gnttab_suspend(); |
62 | } | 54 | xen_arch_pre_suspend(); |
63 | 55 | } | |
64 | sysdev_resume(); | ||
65 | 56 | ||
66 | return 0; | 57 | static void xen_post_suspend(int cancelled) |
58 | { | ||
59 | xen_arch_post_suspend(cancelled); | ||
60 | gnttab_resume(); | ||
61 | xen_mm_unpin_all(); | ||
67 | } | 62 | } |
68 | 63 | ||
64 | #ifdef CONFIG_PM_SLEEP | ||
69 | static int xen_suspend(void *data) | 65 | static int xen_suspend(void *data) |
70 | { | 66 | { |
67 | struct suspend_info *si = data; | ||
71 | int err; | 68 | int err; |
72 | int *cancelled = data; | ||
73 | 69 | ||
74 | BUG_ON(!irqs_disabled()); | 70 | BUG_ON(!irqs_disabled()); |
75 | 71 | ||
@@ -80,22 +76,20 @@ static int xen_suspend(void *data) | |||
80 | return err; | 76 | return err; |
81 | } | 77 | } |
82 | 78 | ||
83 | xen_mm_pin_all(); | 79 | if (si->pre) |
84 | gnttab_suspend(); | 80 | si->pre(); |
85 | xen_pre_suspend(); | ||
86 | 81 | ||
87 | /* | 82 | /* |
88 | * This hypercall returns 1 if suspend was cancelled | 83 | * This hypercall returns 1 if suspend was cancelled |
89 | * or the domain was merely checkpointed, and 0 if it | 84 | * or the domain was merely checkpointed, and 0 if it |
90 | * is resuming in a new domain. | 85 | * is resuming in a new domain. |
91 | */ | 86 | */ |
92 | *cancelled = HYPERVISOR_suspend(virt_to_mfn(xen_start_info)); | 87 | si->cancelled = HYPERVISOR_suspend(si->arg); |
93 | 88 | ||
94 | xen_post_suspend(*cancelled); | 89 | if (si->post) |
95 | gnttab_resume(); | 90 | si->post(si->cancelled); |
96 | xen_mm_unpin_all(); | ||
97 | 91 | ||
98 | if (!*cancelled) { | 92 | if (!si->cancelled) { |
99 | xen_irq_resume(); | 93 | xen_irq_resume(); |
100 | xen_console_resume(); | 94 | xen_console_resume(); |
101 | xen_timer_resume(); | 95 | xen_timer_resume(); |
@@ -109,7 +103,7 @@ static int xen_suspend(void *data) | |||
109 | static void do_suspend(void) | 103 | static void do_suspend(void) |
110 | { | 104 | { |
111 | int err; | 105 | int err; |
112 | int cancelled = 1; | 106 | struct suspend_info si; |
113 | 107 | ||
114 | shutting_down = SHUTDOWN_SUSPEND; | 108 | shutting_down = SHUTDOWN_SUSPEND; |
115 | 109 | ||
@@ -139,20 +133,29 @@ static void do_suspend(void) | |||
139 | goto out_resume; | 133 | goto out_resume; |
140 | } | 134 | } |
141 | 135 | ||
142 | if (xen_hvm_domain()) | 136 | si.cancelled = 1; |
143 | err = stop_machine(xen_hvm_suspend, &cancelled, cpumask_of(0)); | 137 | |
144 | else | 138 | if (xen_hvm_domain()) { |
145 | err = stop_machine(xen_suspend, &cancelled, cpumask_of(0)); | 139 | si.arg = 0UL; |
140 | si.pre = NULL; | ||
141 | si.post = &xen_hvm_post_suspend; | ||
142 | } else { | ||
143 | si.arg = virt_to_mfn(xen_start_info); | ||
144 | si.pre = &xen_pre_suspend; | ||
145 | si.post = &xen_post_suspend; | ||
146 | } | ||
147 | |||
148 | err = stop_machine(xen_suspend, &si, cpumask_of(0)); | ||
146 | 149 | ||
147 | dpm_resume_noirq(PMSG_RESUME); | 150 | dpm_resume_noirq(PMSG_RESUME); |
148 | 151 | ||
149 | if (err) { | 152 | if (err) { |
150 | printk(KERN_ERR "failed to start xen_suspend: %d\n", err); | 153 | printk(KERN_ERR "failed to start xen_suspend: %d\n", err); |
151 | cancelled = 1; | 154 | si.cancelled = 1; |
152 | } | 155 | } |
153 | 156 | ||
154 | out_resume: | 157 | out_resume: |
155 | if (!cancelled) { | 158 | if (!si.cancelled) { |
156 | xen_arch_resume(); | 159 | xen_arch_resume(); |
157 | xs_resume(); | 160 | xs_resume(); |
158 | } else | 161 | } else |
@@ -172,12 +175,39 @@ out: | |||
172 | } | 175 | } |
173 | #endif /* CONFIG_PM_SLEEP */ | 176 | #endif /* CONFIG_PM_SLEEP */ |
174 | 177 | ||
178 | struct shutdown_handler { | ||
179 | const char *command; | ||
180 | void (*cb)(void); | ||
181 | }; | ||
182 | |||
183 | static void do_poweroff(void) | ||
184 | { | ||
185 | shutting_down = SHUTDOWN_POWEROFF; | ||
186 | orderly_poweroff(false); | ||
187 | } | ||
188 | |||
189 | static void do_reboot(void) | ||
190 | { | ||
191 | shutting_down = SHUTDOWN_POWEROFF; /* ? */ | ||
192 | ctrl_alt_del(); | ||
193 | } | ||
194 | |||
175 | static void shutdown_handler(struct xenbus_watch *watch, | 195 | static void shutdown_handler(struct xenbus_watch *watch, |
176 | const char **vec, unsigned int len) | 196 | const char **vec, unsigned int len) |
177 | { | 197 | { |
178 | char *str; | 198 | char *str; |
179 | struct xenbus_transaction xbt; | 199 | struct xenbus_transaction xbt; |
180 | int err; | 200 | int err; |
201 | static struct shutdown_handler handlers[] = { | ||
202 | { "poweroff", do_poweroff }, | ||
203 | { "halt", do_poweroff }, | ||
204 | { "reboot", do_reboot }, | ||
205 | #ifdef CONFIG_PM_SLEEP | ||
206 | { "suspend", do_suspend }, | ||
207 | #endif | ||
208 | {NULL, NULL}, | ||
209 | }; | ||
210 | static struct shutdown_handler *handler; | ||
181 | 211 | ||
182 | if (shutting_down != SHUTDOWN_INVALID) | 212 | if (shutting_down != SHUTDOWN_INVALID) |
183 | return; | 213 | return; |
@@ -194,7 +224,14 @@ static void shutdown_handler(struct xenbus_watch *watch, | |||
194 | return; | 224 | return; |
195 | } | 225 | } |
196 | 226 | ||
197 | xenbus_write(xbt, "control", "shutdown", ""); | 227 | for (handler = &handlers[0]; handler->command; handler++) { |
228 | if (strcmp(str, handler->command) == 0) | ||
229 | break; | ||
230 | } | ||
231 | |||
232 | /* Only acknowledge commands which we are prepared to handle. */ | ||
233 | if (handler->cb) | ||
234 | xenbus_write(xbt, "control", "shutdown", ""); | ||
198 | 235 | ||
199 | err = xenbus_transaction_end(xbt, 0); | 236 | err = xenbus_transaction_end(xbt, 0); |
200 | if (err == -EAGAIN) { | 237 | if (err == -EAGAIN) { |
@@ -202,17 +239,8 @@ static void shutdown_handler(struct xenbus_watch *watch, | |||
202 | goto again; | 239 | goto again; |
203 | } | 240 | } |
204 | 241 | ||
205 | if (strcmp(str, "poweroff") == 0 || | 242 | if (handler->cb) { |
206 | strcmp(str, "halt") == 0) { | 243 | handler->cb(); |
207 | shutting_down = SHUTDOWN_POWEROFF; | ||
208 | orderly_poweroff(false); | ||
209 | } else if (strcmp(str, "reboot") == 0) { | ||
210 | shutting_down = SHUTDOWN_POWEROFF; /* ? */ | ||
211 | ctrl_alt_del(); | ||
212 | #ifdef CONFIG_PM_SLEEP | ||
213 | } else if (strcmp(str, "suspend") == 0) { | ||
214 | do_suspend(); | ||
215 | #endif | ||
216 | } else { | 244 | } else { |
217 | printk(KERN_INFO "Ignoring shutdown request: %s\n", str); | 245 | printk(KERN_INFO "Ignoring shutdown request: %s\n", str); |
218 | shutting_down = SHUTDOWN_INVALID; | 246 | shutting_down = SHUTDOWN_INVALID; |
@@ -291,27 +319,18 @@ static int shutdown_event(struct notifier_block *notifier, | |||
291 | return NOTIFY_DONE; | 319 | return NOTIFY_DONE; |
292 | } | 320 | } |
293 | 321 | ||
294 | static int __init __setup_shutdown_event(void) | ||
295 | { | ||
296 | /* Delay initialization in the PV on HVM case */ | ||
297 | if (xen_hvm_domain()) | ||
298 | return 0; | ||
299 | |||
300 | if (!xen_pv_domain()) | ||
301 | return -ENODEV; | ||
302 | |||
303 | return xen_setup_shutdown_event(); | ||
304 | } | ||
305 | |||
306 | int xen_setup_shutdown_event(void) | 322 | int xen_setup_shutdown_event(void) |
307 | { | 323 | { |
308 | static struct notifier_block xenstore_notifier = { | 324 | static struct notifier_block xenstore_notifier = { |
309 | .notifier_call = shutdown_event | 325 | .notifier_call = shutdown_event |
310 | }; | 326 | }; |
327 | |||
328 | if (!xen_domain()) | ||
329 | return -ENODEV; | ||
311 | register_xenstore_notifier(&xenstore_notifier); | 330 | register_xenstore_notifier(&xenstore_notifier); |
312 | 331 | ||
313 | return 0; | 332 | return 0; |
314 | } | 333 | } |
315 | EXPORT_SYMBOL_GPL(xen_setup_shutdown_event); | 334 | EXPORT_SYMBOL_GPL(xen_setup_shutdown_event); |
316 | 335 | ||
317 | subsys_initcall(__setup_shutdown_event); | 336 | subsys_initcall(xen_setup_shutdown_event); |
diff --git a/drivers/xen/platform-pci.c b/drivers/xen/platform-pci.c index afbe041f42c5..319dd0a94d51 100644 --- a/drivers/xen/platform-pci.c +++ b/drivers/xen/platform-pci.c | |||
@@ -156,9 +156,6 @@ static int __devinit platform_pci_init(struct pci_dev *pdev, | |||
156 | if (ret) | 156 | if (ret) |
157 | goto out; | 157 | goto out; |
158 | xenbus_probe(NULL); | 158 | xenbus_probe(NULL); |
159 | ret = xen_setup_shutdown_event(); | ||
160 | if (ret) | ||
161 | goto out; | ||
162 | return 0; | 159 | return 0; |
163 | 160 | ||
164 | out: | 161 | out: |
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 6f820fa23df4..7f78cc78fdd0 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
@@ -729,6 +729,15 @@ struct btrfs_space_info { | |||
729 | u64 disk_total; /* total bytes on disk, takes mirrors into | 729 | u64 disk_total; /* total bytes on disk, takes mirrors into |
730 | account */ | 730 | account */ |
731 | 731 | ||
732 | /* | ||
733 | * we bump reservation progress every time we decrement | ||
734 | * bytes_reserved. This way people waiting for reservations | ||
735 | * know something good has happened and they can check | ||
736 | * for progress. The number here isn't to be trusted, it | ||
737 | * just shows reclaim activity | ||
738 | */ | ||
739 | unsigned long reservation_progress; | ||
740 | |||
732 | int full; /* indicates that we cannot allocate any more | 741 | int full; /* indicates that we cannot allocate any more |
733 | chunks for this space */ | 742 | chunks for this space */ |
734 | int force_alloc; /* set if we need to force a chunk alloc for | 743 | int force_alloc; /* set if we need to force a chunk alloc for |
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 588ff9849873..7b3089b5c2df 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -3342,15 +3342,16 @@ static int shrink_delalloc(struct btrfs_trans_handle *trans, | |||
3342 | u64 max_reclaim; | 3342 | u64 max_reclaim; |
3343 | u64 reclaimed = 0; | 3343 | u64 reclaimed = 0; |
3344 | long time_left; | 3344 | long time_left; |
3345 | int pause = 1; | ||
3346 | int nr_pages = (2 * 1024 * 1024) >> PAGE_CACHE_SHIFT; | 3345 | int nr_pages = (2 * 1024 * 1024) >> PAGE_CACHE_SHIFT; |
3347 | int loops = 0; | 3346 | int loops = 0; |
3347 | unsigned long progress; | ||
3348 | 3348 | ||
3349 | block_rsv = &root->fs_info->delalloc_block_rsv; | 3349 | block_rsv = &root->fs_info->delalloc_block_rsv; |
3350 | space_info = block_rsv->space_info; | 3350 | space_info = block_rsv->space_info; |
3351 | 3351 | ||
3352 | smp_mb(); | 3352 | smp_mb(); |
3353 | reserved = space_info->bytes_reserved; | 3353 | reserved = space_info->bytes_reserved; |
3354 | progress = space_info->reservation_progress; | ||
3354 | 3355 | ||
3355 | if (reserved == 0) | 3356 | if (reserved == 0) |
3356 | return 0; | 3357 | return 0; |
@@ -3365,31 +3366,36 @@ static int shrink_delalloc(struct btrfs_trans_handle *trans, | |||
3365 | writeback_inodes_sb_nr_if_idle(root->fs_info->sb, nr_pages); | 3366 | writeback_inodes_sb_nr_if_idle(root->fs_info->sb, nr_pages); |
3366 | 3367 | ||
3367 | spin_lock(&space_info->lock); | 3368 | spin_lock(&space_info->lock); |
3368 | if (reserved > space_info->bytes_reserved) { | 3369 | if (reserved > space_info->bytes_reserved) |
3369 | loops = 0; | ||
3370 | reclaimed += reserved - space_info->bytes_reserved; | 3370 | reclaimed += reserved - space_info->bytes_reserved; |
3371 | } else { | ||
3372 | loops++; | ||
3373 | } | ||
3374 | reserved = space_info->bytes_reserved; | 3371 | reserved = space_info->bytes_reserved; |
3375 | spin_unlock(&space_info->lock); | 3372 | spin_unlock(&space_info->lock); |
3376 | 3373 | ||
3374 | loops++; | ||
3375 | |||
3377 | if (reserved == 0 || reclaimed >= max_reclaim) | 3376 | if (reserved == 0 || reclaimed >= max_reclaim) |
3378 | break; | 3377 | break; |
3379 | 3378 | ||
3380 | if (trans && trans->transaction->blocked) | 3379 | if (trans && trans->transaction->blocked) |
3381 | return -EAGAIN; | 3380 | return -EAGAIN; |
3382 | 3381 | ||
3383 | __set_current_state(TASK_INTERRUPTIBLE); | 3382 | time_left = schedule_timeout_interruptible(1); |
3384 | time_left = schedule_timeout(pause); | ||
3385 | 3383 | ||
3386 | /* We were interrupted, exit */ | 3384 | /* We were interrupted, exit */ |
3387 | if (time_left) | 3385 | if (time_left) |
3388 | break; | 3386 | break; |
3389 | 3387 | ||
3390 | pause <<= 1; | 3388 | /* we've kicked the IO a few times, if anything has been freed, |
3391 | if (pause > HZ / 10) | 3389 | * exit. There is no sense in looping here for a long time |
3392 | pause = HZ / 10; | 3390 | * when we really need to commit the transaction, or there are |
3391 | * just too many writers without enough free space | ||
3392 | */ | ||
3393 | |||
3394 | if (loops > 3) { | ||
3395 | smp_mb(); | ||
3396 | if (progress != space_info->reservation_progress) | ||
3397 | break; | ||
3398 | } | ||
3393 | 3399 | ||
3394 | } | 3400 | } |
3395 | return reclaimed >= to_reclaim; | 3401 | return reclaimed >= to_reclaim; |
@@ -3612,6 +3618,7 @@ void block_rsv_release_bytes(struct btrfs_block_rsv *block_rsv, | |||
3612 | if (num_bytes) { | 3618 | if (num_bytes) { |
3613 | spin_lock(&space_info->lock); | 3619 | spin_lock(&space_info->lock); |
3614 | space_info->bytes_reserved -= num_bytes; | 3620 | space_info->bytes_reserved -= num_bytes; |
3621 | space_info->reservation_progress++; | ||
3615 | spin_unlock(&space_info->lock); | 3622 | spin_unlock(&space_info->lock); |
3616 | } | 3623 | } |
3617 | } | 3624 | } |
@@ -3844,6 +3851,7 @@ static void update_global_block_rsv(struct btrfs_fs_info *fs_info) | |||
3844 | if (block_rsv->reserved >= block_rsv->size) { | 3851 | if (block_rsv->reserved >= block_rsv->size) { |
3845 | num_bytes = block_rsv->reserved - block_rsv->size; | 3852 | num_bytes = block_rsv->reserved - block_rsv->size; |
3846 | sinfo->bytes_reserved -= num_bytes; | 3853 | sinfo->bytes_reserved -= num_bytes; |
3854 | sinfo->reservation_progress++; | ||
3847 | block_rsv->reserved = block_rsv->size; | 3855 | block_rsv->reserved = block_rsv->size; |
3848 | block_rsv->full = 1; | 3856 | block_rsv->full = 1; |
3849 | } | 3857 | } |
@@ -4005,7 +4013,6 @@ int btrfs_delalloc_reserve_metadata(struct inode *inode, u64 num_bytes) | |||
4005 | to_reserve = 0; | 4013 | to_reserve = 0; |
4006 | } | 4014 | } |
4007 | spin_unlock(&BTRFS_I(inode)->accounting_lock); | 4015 | spin_unlock(&BTRFS_I(inode)->accounting_lock); |
4008 | |||
4009 | to_reserve += calc_csum_metadata_size(inode, num_bytes); | 4016 | to_reserve += calc_csum_metadata_size(inode, num_bytes); |
4010 | ret = reserve_metadata_bytes(NULL, root, block_rsv, to_reserve, 1); | 4017 | ret = reserve_metadata_bytes(NULL, root, block_rsv, to_reserve, 1); |
4011 | if (ret) | 4018 | if (ret) |
@@ -4133,6 +4140,7 @@ static int update_block_group(struct btrfs_trans_handle *trans, | |||
4133 | btrfs_set_block_group_used(&cache->item, old_val); | 4140 | btrfs_set_block_group_used(&cache->item, old_val); |
4134 | cache->reserved -= num_bytes; | 4141 | cache->reserved -= num_bytes; |
4135 | cache->space_info->bytes_reserved -= num_bytes; | 4142 | cache->space_info->bytes_reserved -= num_bytes; |
4143 | cache->space_info->reservation_progress++; | ||
4136 | cache->space_info->bytes_used += num_bytes; | 4144 | cache->space_info->bytes_used += num_bytes; |
4137 | cache->space_info->disk_used += num_bytes * factor; | 4145 | cache->space_info->disk_used += num_bytes * factor; |
4138 | spin_unlock(&cache->lock); | 4146 | spin_unlock(&cache->lock); |
@@ -4184,6 +4192,7 @@ static int pin_down_extent(struct btrfs_root *root, | |||
4184 | if (reserved) { | 4192 | if (reserved) { |
4185 | cache->reserved -= num_bytes; | 4193 | cache->reserved -= num_bytes; |
4186 | cache->space_info->bytes_reserved -= num_bytes; | 4194 | cache->space_info->bytes_reserved -= num_bytes; |
4195 | cache->space_info->reservation_progress++; | ||
4187 | } | 4196 | } |
4188 | spin_unlock(&cache->lock); | 4197 | spin_unlock(&cache->lock); |
4189 | spin_unlock(&cache->space_info->lock); | 4198 | spin_unlock(&cache->space_info->lock); |
@@ -4234,6 +4243,7 @@ static int update_reserved_bytes(struct btrfs_block_group_cache *cache, | |||
4234 | space_info->bytes_readonly += num_bytes; | 4243 | space_info->bytes_readonly += num_bytes; |
4235 | cache->reserved -= num_bytes; | 4244 | cache->reserved -= num_bytes; |
4236 | space_info->bytes_reserved -= num_bytes; | 4245 | space_info->bytes_reserved -= num_bytes; |
4246 | space_info->reservation_progress++; | ||
4237 | } | 4247 | } |
4238 | spin_unlock(&cache->lock); | 4248 | spin_unlock(&cache->lock); |
4239 | spin_unlock(&space_info->lock); | 4249 | spin_unlock(&space_info->lock); |
@@ -4712,6 +4722,7 @@ void btrfs_free_tree_block(struct btrfs_trans_handle *trans, | |||
4712 | if (ret) { | 4722 | if (ret) { |
4713 | spin_lock(&cache->space_info->lock); | 4723 | spin_lock(&cache->space_info->lock); |
4714 | cache->space_info->bytes_reserved -= buf->len; | 4724 | cache->space_info->bytes_reserved -= buf->len; |
4725 | cache->space_info->reservation_progress++; | ||
4715 | spin_unlock(&cache->space_info->lock); | 4726 | spin_unlock(&cache->space_info->lock); |
4716 | } | 4727 | } |
4717 | goto out; | 4728 | goto out; |
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index fd3f172e94e6..714adc4ac4c2 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c | |||
@@ -3046,17 +3046,38 @@ int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, | |||
3046 | } | 3046 | } |
3047 | 3047 | ||
3048 | while (!end) { | 3048 | while (!end) { |
3049 | off = extent_map_end(em); | 3049 | u64 offset_in_extent; |
3050 | if (off >= max) | 3050 | |
3051 | end = 1; | 3051 | /* break if the extent we found is outside the range */ |
3052 | if (em->start >= max || extent_map_end(em) < off) | ||
3053 | break; | ||
3054 | |||
3055 | /* | ||
3056 | * get_extent may return an extent that starts before our | ||
3057 | * requested range. We have to make sure the ranges | ||
3058 | * we return to fiemap always move forward and don't | ||
3059 | * overlap, so adjust the offsets here | ||
3060 | */ | ||
3061 | em_start = max(em->start, off); | ||
3052 | 3062 | ||
3053 | em_start = em->start; | 3063 | /* |
3054 | em_len = em->len; | 3064 | * record the offset from the start of the extent |
3065 | * for adjusting the disk offset below | ||
3066 | */ | ||
3067 | offset_in_extent = em_start - em->start; | ||
3055 | em_end = extent_map_end(em); | 3068 | em_end = extent_map_end(em); |
3069 | em_len = em_end - em_start; | ||
3056 | emflags = em->flags; | 3070 | emflags = em->flags; |
3057 | disko = 0; | 3071 | disko = 0; |
3058 | flags = 0; | 3072 | flags = 0; |
3059 | 3073 | ||
3074 | /* | ||
3075 | * bump off for our next call to get_extent | ||
3076 | */ | ||
3077 | off = extent_map_end(em); | ||
3078 | if (off >= max) | ||
3079 | end = 1; | ||
3080 | |||
3060 | if (em->block_start == EXTENT_MAP_LAST_BYTE) { | 3081 | if (em->block_start == EXTENT_MAP_LAST_BYTE) { |
3061 | end = 1; | 3082 | end = 1; |
3062 | flags |= FIEMAP_EXTENT_LAST; | 3083 | flags |= FIEMAP_EXTENT_LAST; |
@@ -3067,7 +3088,7 @@ int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, | |||
3067 | flags |= (FIEMAP_EXTENT_DELALLOC | | 3088 | flags |= (FIEMAP_EXTENT_DELALLOC | |
3068 | FIEMAP_EXTENT_UNKNOWN); | 3089 | FIEMAP_EXTENT_UNKNOWN); |
3069 | } else { | 3090 | } else { |
3070 | disko = em->block_start; | 3091 | disko = em->block_start + offset_in_extent; |
3071 | } | 3092 | } |
3072 | if (test_bit(EXTENT_FLAG_COMPRESSED, &em->flags)) | 3093 | if (test_bit(EXTENT_FLAG_COMPRESSED, &em->flags)) |
3073 | flags |= FIEMAP_EXTENT_ENCODED; | 3094 | flags |= FIEMAP_EXTENT_ENCODED; |
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index 7084140d5940..f447b783bb84 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c | |||
@@ -70,6 +70,19 @@ static noinline int btrfs_copy_from_user(loff_t pos, int num_pages, | |||
70 | 70 | ||
71 | /* Flush processor's dcache for this page */ | 71 | /* Flush processor's dcache for this page */ |
72 | flush_dcache_page(page); | 72 | flush_dcache_page(page); |
73 | |||
74 | /* | ||
75 | * if we get a partial write, we can end up with | ||
76 | * partially up to date pages. These add | ||
77 | * a lot of complexity, so make sure they don't | ||
78 | * happen by forcing this copy to be retried. | ||
79 | * | ||
80 | * The rest of the btrfs_file_write code will fall | ||
81 | * back to page at a time copies after we return 0. | ||
82 | */ | ||
83 | if (!PageUptodate(page) && copied < count) | ||
84 | copied = 0; | ||
85 | |||
73 | iov_iter_advance(i, copied); | 86 | iov_iter_advance(i, copied); |
74 | write_bytes -= copied; | 87 | write_bytes -= copied; |
75 | total_copied += copied; | 88 | total_copied += copied; |
@@ -763,6 +776,27 @@ out: | |||
763 | } | 776 | } |
764 | 777 | ||
765 | /* | 778 | /* |
779 | * on error we return an unlocked page and the error value | ||
780 | * on success we return a locked page and 0 | ||
781 | */ | ||
782 | static int prepare_uptodate_page(struct page *page, u64 pos) | ||
783 | { | ||
784 | int ret = 0; | ||
785 | |||
786 | if ((pos & (PAGE_CACHE_SIZE - 1)) && !PageUptodate(page)) { | ||
787 | ret = btrfs_readpage(NULL, page); | ||
788 | if (ret) | ||
789 | return ret; | ||
790 | lock_page(page); | ||
791 | if (!PageUptodate(page)) { | ||
792 | unlock_page(page); | ||
793 | return -EIO; | ||
794 | } | ||
795 | } | ||
796 | return 0; | ||
797 | } | ||
798 | |||
799 | /* | ||
766 | * this gets pages into the page cache and locks them down, it also properly | 800 | * this gets pages into the page cache and locks them down, it also properly |
767 | * waits for data=ordered extents to finish before allowing the pages to be | 801 | * waits for data=ordered extents to finish before allowing the pages to be |
768 | * modified. | 802 | * modified. |
@@ -777,6 +811,7 @@ static noinline int prepare_pages(struct btrfs_root *root, struct file *file, | |||
777 | unsigned long index = pos >> PAGE_CACHE_SHIFT; | 811 | unsigned long index = pos >> PAGE_CACHE_SHIFT; |
778 | struct inode *inode = fdentry(file)->d_inode; | 812 | struct inode *inode = fdentry(file)->d_inode; |
779 | int err = 0; | 813 | int err = 0; |
814 | int faili = 0; | ||
780 | u64 start_pos; | 815 | u64 start_pos; |
781 | u64 last_pos; | 816 | u64 last_pos; |
782 | 817 | ||
@@ -794,15 +829,24 @@ again: | |||
794 | for (i = 0; i < num_pages; i++) { | 829 | for (i = 0; i < num_pages; i++) { |
795 | pages[i] = grab_cache_page(inode->i_mapping, index + i); | 830 | pages[i] = grab_cache_page(inode->i_mapping, index + i); |
796 | if (!pages[i]) { | 831 | if (!pages[i]) { |
797 | int c; | 832 | faili = i - 1; |
798 | for (c = i - 1; c >= 0; c--) { | 833 | err = -ENOMEM; |
799 | unlock_page(pages[c]); | 834 | goto fail; |
800 | page_cache_release(pages[c]); | 835 | } |
801 | } | 836 | |
802 | return -ENOMEM; | 837 | if (i == 0) |
838 | err = prepare_uptodate_page(pages[i], pos); | ||
839 | if (i == num_pages - 1) | ||
840 | err = prepare_uptodate_page(pages[i], | ||
841 | pos + write_bytes); | ||
842 | if (err) { | ||
843 | page_cache_release(pages[i]); | ||
844 | faili = i - 1; | ||
845 | goto fail; | ||
803 | } | 846 | } |
804 | wait_on_page_writeback(pages[i]); | 847 | wait_on_page_writeback(pages[i]); |
805 | } | 848 | } |
849 | err = 0; | ||
806 | if (start_pos < inode->i_size) { | 850 | if (start_pos < inode->i_size) { |
807 | struct btrfs_ordered_extent *ordered; | 851 | struct btrfs_ordered_extent *ordered; |
808 | lock_extent_bits(&BTRFS_I(inode)->io_tree, | 852 | lock_extent_bits(&BTRFS_I(inode)->io_tree, |
@@ -842,6 +886,14 @@ again: | |||
842 | WARN_ON(!PageLocked(pages[i])); | 886 | WARN_ON(!PageLocked(pages[i])); |
843 | } | 887 | } |
844 | return 0; | 888 | return 0; |
889 | fail: | ||
890 | while (faili >= 0) { | ||
891 | unlock_page(pages[faili]); | ||
892 | page_cache_release(pages[faili]); | ||
893 | faili--; | ||
894 | } | ||
895 | return err; | ||
896 | |||
845 | } | 897 | } |
846 | 898 | ||
847 | static ssize_t btrfs_file_aio_write(struct kiocb *iocb, | 899 | static ssize_t btrfs_file_aio_write(struct kiocb *iocb, |
@@ -851,7 +903,6 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb, | |||
851 | struct file *file = iocb->ki_filp; | 903 | struct file *file = iocb->ki_filp; |
852 | struct inode *inode = fdentry(file)->d_inode; | 904 | struct inode *inode = fdentry(file)->d_inode; |
853 | struct btrfs_root *root = BTRFS_I(inode)->root; | 905 | struct btrfs_root *root = BTRFS_I(inode)->root; |
854 | struct page *pinned[2]; | ||
855 | struct page **pages = NULL; | 906 | struct page **pages = NULL; |
856 | struct iov_iter i; | 907 | struct iov_iter i; |
857 | loff_t *ppos = &iocb->ki_pos; | 908 | loff_t *ppos = &iocb->ki_pos; |
@@ -872,9 +923,6 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb, | |||
872 | will_write = ((file->f_flags & O_DSYNC) || IS_SYNC(inode) || | 923 | will_write = ((file->f_flags & O_DSYNC) || IS_SYNC(inode) || |
873 | (file->f_flags & O_DIRECT)); | 924 | (file->f_flags & O_DIRECT)); |
874 | 925 | ||
875 | pinned[0] = NULL; | ||
876 | pinned[1] = NULL; | ||
877 | |||
878 | start_pos = pos; | 926 | start_pos = pos; |
879 | 927 | ||
880 | vfs_check_frozen(inode->i_sb, SB_FREEZE_WRITE); | 928 | vfs_check_frozen(inode->i_sb, SB_FREEZE_WRITE); |
@@ -962,32 +1010,6 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb, | |||
962 | first_index = pos >> PAGE_CACHE_SHIFT; | 1010 | first_index = pos >> PAGE_CACHE_SHIFT; |
963 | last_index = (pos + iov_iter_count(&i)) >> PAGE_CACHE_SHIFT; | 1011 | last_index = (pos + iov_iter_count(&i)) >> PAGE_CACHE_SHIFT; |
964 | 1012 | ||
965 | /* | ||
966 | * there are lots of better ways to do this, but this code | ||
967 | * makes sure the first and last page in the file range are | ||
968 | * up to date and ready for cow | ||
969 | */ | ||
970 | if ((pos & (PAGE_CACHE_SIZE - 1))) { | ||
971 | pinned[0] = grab_cache_page(inode->i_mapping, first_index); | ||
972 | if (!PageUptodate(pinned[0])) { | ||
973 | ret = btrfs_readpage(NULL, pinned[0]); | ||
974 | BUG_ON(ret); | ||
975 | wait_on_page_locked(pinned[0]); | ||
976 | } else { | ||
977 | unlock_page(pinned[0]); | ||
978 | } | ||
979 | } | ||
980 | if ((pos + iov_iter_count(&i)) & (PAGE_CACHE_SIZE - 1)) { | ||
981 | pinned[1] = grab_cache_page(inode->i_mapping, last_index); | ||
982 | if (!PageUptodate(pinned[1])) { | ||
983 | ret = btrfs_readpage(NULL, pinned[1]); | ||
984 | BUG_ON(ret); | ||
985 | wait_on_page_locked(pinned[1]); | ||
986 | } else { | ||
987 | unlock_page(pinned[1]); | ||
988 | } | ||
989 | } | ||
990 | |||
991 | while (iov_iter_count(&i) > 0) { | 1013 | while (iov_iter_count(&i) > 0) { |
992 | size_t offset = pos & (PAGE_CACHE_SIZE - 1); | 1014 | size_t offset = pos & (PAGE_CACHE_SIZE - 1); |
993 | size_t write_bytes = min(iov_iter_count(&i), | 1015 | size_t write_bytes = min(iov_iter_count(&i), |
@@ -1024,8 +1046,20 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb, | |||
1024 | 1046 | ||
1025 | copied = btrfs_copy_from_user(pos, num_pages, | 1047 | copied = btrfs_copy_from_user(pos, num_pages, |
1026 | write_bytes, pages, &i); | 1048 | write_bytes, pages, &i); |
1027 | dirty_pages = (copied + offset + PAGE_CACHE_SIZE - 1) >> | 1049 | |
1028 | PAGE_CACHE_SHIFT; | 1050 | /* |
1051 | * if we have trouble faulting in the pages, fall | ||
1052 | * back to one page at a time | ||
1053 | */ | ||
1054 | if (copied < write_bytes) | ||
1055 | nrptrs = 1; | ||
1056 | |||
1057 | if (copied == 0) | ||
1058 | dirty_pages = 0; | ||
1059 | else | ||
1060 | dirty_pages = (copied + offset + | ||
1061 | PAGE_CACHE_SIZE - 1) >> | ||
1062 | PAGE_CACHE_SHIFT; | ||
1029 | 1063 | ||
1030 | if (num_pages > dirty_pages) { | 1064 | if (num_pages > dirty_pages) { |
1031 | if (copied > 0) | 1065 | if (copied > 0) |
@@ -1069,10 +1103,6 @@ out: | |||
1069 | err = ret; | 1103 | err = ret; |
1070 | 1104 | ||
1071 | kfree(pages); | 1105 | kfree(pages); |
1072 | if (pinned[0]) | ||
1073 | page_cache_release(pinned[0]); | ||
1074 | if (pinned[1]) | ||
1075 | page_cache_release(pinned[1]); | ||
1076 | *ppos = pos; | 1106 | *ppos = pos; |
1077 | 1107 | ||
1078 | /* | 1108 | /* |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index c23f050f47c2..4a0107e18747 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -4818,10 +4818,11 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir, | |||
4818 | goto fail; | 4818 | goto fail; |
4819 | 4819 | ||
4820 | /* | 4820 | /* |
4821 | * 1 item for inode ref | 4821 | * 2 items for inode and inode ref |
4822 | * 2 items for dir items | 4822 | * 2 items for dir items |
4823 | * 1 item for parent inode | ||
4823 | */ | 4824 | */ |
4824 | trans = btrfs_start_transaction(root, 3); | 4825 | trans = btrfs_start_transaction(root, 5); |
4825 | if (IS_ERR(trans)) { | 4826 | if (IS_ERR(trans)) { |
4826 | err = PTR_ERR(trans); | 4827 | err = PTR_ERR(trans); |
4827 | goto fail; | 4828 | goto fail; |
@@ -6053,6 +6054,7 @@ static void btrfs_submit_direct(int rw, struct bio *bio, struct inode *inode, | |||
6053 | if (!skip_sum) { | 6054 | if (!skip_sum) { |
6054 | dip->csums = kmalloc(sizeof(u32) * bio->bi_vcnt, GFP_NOFS); | 6055 | dip->csums = kmalloc(sizeof(u32) * bio->bi_vcnt, GFP_NOFS); |
6055 | if (!dip->csums) { | 6056 | if (!dip->csums) { |
6057 | kfree(dip); | ||
6056 | ret = -ENOMEM; | 6058 | ret = -ENOMEM; |
6057 | goto free_ordered; | 6059 | goto free_ordered; |
6058 | } | 6060 | } |
diff --git a/fs/dcache.c b/fs/dcache.c index 611ffe928c03..a39fe47c466f 100644 --- a/fs/dcache.c +++ b/fs/dcache.c | |||
@@ -296,8 +296,12 @@ static struct dentry *d_kill(struct dentry *dentry, struct dentry *parent) | |||
296 | __releases(parent->d_lock) | 296 | __releases(parent->d_lock) |
297 | __releases(dentry->d_inode->i_lock) | 297 | __releases(dentry->d_inode->i_lock) |
298 | { | 298 | { |
299 | dentry->d_parent = NULL; | ||
300 | list_del(&dentry->d_u.d_child); | 299 | list_del(&dentry->d_u.d_child); |
300 | /* | ||
301 | * Inform try_to_ascend() that we are no longer attached to the | ||
302 | * dentry tree | ||
303 | */ | ||
304 | dentry->d_flags |= DCACHE_DISCONNECTED; | ||
301 | if (parent) | 305 | if (parent) |
302 | spin_unlock(&parent->d_lock); | 306 | spin_unlock(&parent->d_lock); |
303 | dentry_iput(dentry); | 307 | dentry_iput(dentry); |
@@ -1012,6 +1016,35 @@ void shrink_dcache_for_umount(struct super_block *sb) | |||
1012 | } | 1016 | } |
1013 | 1017 | ||
1014 | /* | 1018 | /* |
1019 | * This tries to ascend one level of parenthood, but | ||
1020 | * we can race with renaming, so we need to re-check | ||
1021 | * the parenthood after dropping the lock and check | ||
1022 | * that the sequence number still matches. | ||
1023 | */ | ||
1024 | static struct dentry *try_to_ascend(struct dentry *old, int locked, unsigned seq) | ||
1025 | { | ||
1026 | struct dentry *new = old->d_parent; | ||
1027 | |||
1028 | rcu_read_lock(); | ||
1029 | spin_unlock(&old->d_lock); | ||
1030 | spin_lock(&new->d_lock); | ||
1031 | |||
1032 | /* | ||
1033 | * might go back up the wrong parent if we have had a rename | ||
1034 | * or deletion | ||
1035 | */ | ||
1036 | if (new != old->d_parent || | ||
1037 | (old->d_flags & DCACHE_DISCONNECTED) || | ||
1038 | (!locked && read_seqretry(&rename_lock, seq))) { | ||
1039 | spin_unlock(&new->d_lock); | ||
1040 | new = NULL; | ||
1041 | } | ||
1042 | rcu_read_unlock(); | ||
1043 | return new; | ||
1044 | } | ||
1045 | |||
1046 | |||
1047 | /* | ||
1015 | * Search for at least 1 mount point in the dentry's subdirs. | 1048 | * Search for at least 1 mount point in the dentry's subdirs. |
1016 | * We descend to the next level whenever the d_subdirs | 1049 | * We descend to the next level whenever the d_subdirs |
1017 | * list is non-empty and continue searching. | 1050 | * list is non-empty and continue searching. |
@@ -1066,24 +1099,10 @@ resume: | |||
1066 | * All done at this level ... ascend and resume the search. | 1099 | * All done at this level ... ascend and resume the search. |
1067 | */ | 1100 | */ |
1068 | if (this_parent != parent) { | 1101 | if (this_parent != parent) { |
1069 | struct dentry *tmp; | 1102 | struct dentry *child = this_parent; |
1070 | struct dentry *child; | 1103 | this_parent = try_to_ascend(this_parent, locked, seq); |
1071 | 1104 | if (!this_parent) | |
1072 | tmp = this_parent->d_parent; | ||
1073 | rcu_read_lock(); | ||
1074 | spin_unlock(&this_parent->d_lock); | ||
1075 | child = this_parent; | ||
1076 | this_parent = tmp; | ||
1077 | spin_lock(&this_parent->d_lock); | ||
1078 | /* might go back up the wrong parent if we have had a rename | ||
1079 | * or deletion */ | ||
1080 | if (this_parent != child->d_parent || | ||
1081 | (!locked && read_seqretry(&rename_lock, seq))) { | ||
1082 | spin_unlock(&this_parent->d_lock); | ||
1083 | rcu_read_unlock(); | ||
1084 | goto rename_retry; | 1105 | goto rename_retry; |
1085 | } | ||
1086 | rcu_read_unlock(); | ||
1087 | next = child->d_u.d_child.next; | 1106 | next = child->d_u.d_child.next; |
1088 | goto resume; | 1107 | goto resume; |
1089 | } | 1108 | } |
@@ -1181,24 +1200,10 @@ resume: | |||
1181 | * All done at this level ... ascend and resume the search. | 1200 | * All done at this level ... ascend and resume the search. |
1182 | */ | 1201 | */ |
1183 | if (this_parent != parent) { | 1202 | if (this_parent != parent) { |
1184 | struct dentry *tmp; | 1203 | struct dentry *child = this_parent; |
1185 | struct dentry *child; | 1204 | this_parent = try_to_ascend(this_parent, locked, seq); |
1186 | 1205 | if (!this_parent) | |
1187 | tmp = this_parent->d_parent; | ||
1188 | rcu_read_lock(); | ||
1189 | spin_unlock(&this_parent->d_lock); | ||
1190 | child = this_parent; | ||
1191 | this_parent = tmp; | ||
1192 | spin_lock(&this_parent->d_lock); | ||
1193 | /* might go back up the wrong parent if we have had a rename | ||
1194 | * or deletion */ | ||
1195 | if (this_parent != child->d_parent || | ||
1196 | (!locked && read_seqretry(&rename_lock, seq))) { | ||
1197 | spin_unlock(&this_parent->d_lock); | ||
1198 | rcu_read_unlock(); | ||
1199 | goto rename_retry; | 1206 | goto rename_retry; |
1200 | } | ||
1201 | rcu_read_unlock(); | ||
1202 | next = child->d_u.d_child.next; | 1207 | next = child->d_u.d_child.next; |
1203 | goto resume; | 1208 | goto resume; |
1204 | } | 1209 | } |
@@ -2942,28 +2947,14 @@ resume: | |||
2942 | spin_unlock(&dentry->d_lock); | 2947 | spin_unlock(&dentry->d_lock); |
2943 | } | 2948 | } |
2944 | if (this_parent != root) { | 2949 | if (this_parent != root) { |
2945 | struct dentry *tmp; | 2950 | struct dentry *child = this_parent; |
2946 | struct dentry *child; | ||
2947 | |||
2948 | tmp = this_parent->d_parent; | ||
2949 | if (!(this_parent->d_flags & DCACHE_GENOCIDE)) { | 2951 | if (!(this_parent->d_flags & DCACHE_GENOCIDE)) { |
2950 | this_parent->d_flags |= DCACHE_GENOCIDE; | 2952 | this_parent->d_flags |= DCACHE_GENOCIDE; |
2951 | this_parent->d_count--; | 2953 | this_parent->d_count--; |
2952 | } | 2954 | } |
2953 | rcu_read_lock(); | 2955 | this_parent = try_to_ascend(this_parent, locked, seq); |
2954 | spin_unlock(&this_parent->d_lock); | 2956 | if (!this_parent) |
2955 | child = this_parent; | ||
2956 | this_parent = tmp; | ||
2957 | spin_lock(&this_parent->d_lock); | ||
2958 | /* might go back up the wrong parent if we have had a rename | ||
2959 | * or deletion */ | ||
2960 | if (this_parent != child->d_parent || | ||
2961 | (!locked && read_seqretry(&rename_lock, seq))) { | ||
2962 | spin_unlock(&this_parent->d_lock); | ||
2963 | rcu_read_unlock(); | ||
2964 | goto rename_retry; | 2957 | goto rename_retry; |
2965 | } | ||
2966 | rcu_read_unlock(); | ||
2967 | next = child->d_u.d_child.next; | 2958 | next = child->d_u.d_child.next; |
2968 | goto resume; | 2959 | goto resume; |
2969 | } | 2960 | } |
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 1cc600e77bb4..2f8e61816d75 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include <linux/inet.h> | 37 | #include <linux/inet.h> |
38 | #include <linux/nfs_xdr.h> | 38 | #include <linux/nfs_xdr.h> |
39 | #include <linux/slab.h> | 39 | #include <linux/slab.h> |
40 | #include <linux/compat.h> | ||
40 | 41 | ||
41 | #include <asm/system.h> | 42 | #include <asm/system.h> |
42 | #include <asm/uaccess.h> | 43 | #include <asm/uaccess.h> |
@@ -89,7 +90,11 @@ int nfs_wait_bit_killable(void *word) | |||
89 | */ | 90 | */ |
90 | u64 nfs_compat_user_ino64(u64 fileid) | 91 | u64 nfs_compat_user_ino64(u64 fileid) |
91 | { | 92 | { |
92 | int ino; | 93 | #ifdef CONFIG_COMPAT |
94 | compat_ulong_t ino; | ||
95 | #else | ||
96 | unsigned long ino; | ||
97 | #endif | ||
93 | 98 | ||
94 | if (enable_ino64) | 99 | if (enable_ino64) |
95 | return fileid; | 100 | return fileid; |
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h index 7a7474073148..1be36cf65bfc 100644 --- a/fs/nfs/nfs4_fs.h +++ b/fs/nfs/nfs4_fs.h | |||
@@ -298,6 +298,11 @@ struct rpc_cred *nfs4_get_renew_cred_locked(struct nfs_client *clp); | |||
298 | #if defined(CONFIG_NFS_V4_1) | 298 | #if defined(CONFIG_NFS_V4_1) |
299 | struct rpc_cred *nfs4_get_machine_cred_locked(struct nfs_client *clp); | 299 | struct rpc_cred *nfs4_get_machine_cred_locked(struct nfs_client *clp); |
300 | struct rpc_cred *nfs4_get_exchange_id_cred(struct nfs_client *clp); | 300 | struct rpc_cred *nfs4_get_exchange_id_cred(struct nfs_client *clp); |
301 | extern void nfs4_schedule_session_recovery(struct nfs4_session *); | ||
302 | #else | ||
303 | static inline void nfs4_schedule_session_recovery(struct nfs4_session *session) | ||
304 | { | ||
305 | } | ||
301 | #endif /* CONFIG_NFS_V4_1 */ | 306 | #endif /* CONFIG_NFS_V4_1 */ |
302 | 307 | ||
303 | extern struct nfs4_state_owner * nfs4_get_state_owner(struct nfs_server *, struct rpc_cred *); | 308 | extern struct nfs4_state_owner * nfs4_get_state_owner(struct nfs_server *, struct rpc_cred *); |
@@ -307,10 +312,9 @@ extern void nfs4_put_open_state(struct nfs4_state *); | |||
307 | extern void nfs4_close_state(struct path *, struct nfs4_state *, fmode_t); | 312 | extern void nfs4_close_state(struct path *, struct nfs4_state *, fmode_t); |
308 | extern void nfs4_close_sync(struct path *, struct nfs4_state *, fmode_t); | 313 | extern void nfs4_close_sync(struct path *, struct nfs4_state *, fmode_t); |
309 | extern void nfs4_state_set_mode_locked(struct nfs4_state *, fmode_t); | 314 | extern void nfs4_state_set_mode_locked(struct nfs4_state *, fmode_t); |
310 | extern void nfs4_schedule_state_recovery(struct nfs_client *); | 315 | extern void nfs4_schedule_lease_recovery(struct nfs_client *); |
311 | extern void nfs4_schedule_state_manager(struct nfs_client *); | 316 | extern void nfs4_schedule_state_manager(struct nfs_client *); |
312 | extern int nfs4_state_mark_reclaim_nograce(struct nfs_client *clp, struct nfs4_state *state); | 317 | extern void nfs4_schedule_stateid_recovery(const struct nfs_server *, struct nfs4_state *); |
313 | extern int nfs4_state_mark_reclaim_reboot(struct nfs_client *clp, struct nfs4_state *state); | ||
314 | extern void nfs41_handle_sequence_flag_errors(struct nfs_client *clp, u32 flags); | 318 | extern void nfs41_handle_sequence_flag_errors(struct nfs_client *clp, u32 flags); |
315 | extern void nfs41_handle_recall_slot(struct nfs_client *clp); | 319 | extern void nfs41_handle_recall_slot(struct nfs_client *clp); |
316 | extern void nfs4_put_lock_state(struct nfs4_lock_state *lsp); | 320 | extern void nfs4_put_lock_state(struct nfs4_lock_state *lsp); |
diff --git a/fs/nfs/nfs4filelayoutdev.c b/fs/nfs/nfs4filelayoutdev.c index f5c9b125e8cc..b73c34375f60 100644 --- a/fs/nfs/nfs4filelayoutdev.c +++ b/fs/nfs/nfs4filelayoutdev.c | |||
@@ -219,6 +219,10 @@ decode_and_add_ds(__be32 **pp, struct inode *inode) | |||
219 | goto out_err; | 219 | goto out_err; |
220 | } | 220 | } |
221 | buf = kmalloc(rlen + 1, GFP_KERNEL); | 221 | buf = kmalloc(rlen + 1, GFP_KERNEL); |
222 | if (!buf) { | ||
223 | dprintk("%s: Not enough memory\n", __func__); | ||
224 | goto out_err; | ||
225 | } | ||
222 | buf[rlen] = '\0'; | 226 | buf[rlen] = '\0'; |
223 | memcpy(buf, r_addr, rlen); | 227 | memcpy(buf, r_addr, rlen); |
224 | 228 | ||
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 1ff76acc7e98..0a07e353a961 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -51,7 +51,6 @@ | |||
51 | #include <linux/sunrpc/bc_xprt.h> | 51 | #include <linux/sunrpc/bc_xprt.h> |
52 | #include <linux/xattr.h> | 52 | #include <linux/xattr.h> |
53 | #include <linux/utsname.h> | 53 | #include <linux/utsname.h> |
54 | #include <linux/mm.h> | ||
55 | 54 | ||
56 | #include "nfs4_fs.h" | 55 | #include "nfs4_fs.h" |
57 | #include "delegation.h" | 56 | #include "delegation.h" |
@@ -257,12 +256,13 @@ static int nfs4_handle_exception(const struct nfs_server *server, int errorcode, | |||
257 | case -NFS4ERR_OPENMODE: | 256 | case -NFS4ERR_OPENMODE: |
258 | if (state == NULL) | 257 | if (state == NULL) |
259 | break; | 258 | break; |
260 | nfs4_state_mark_reclaim_nograce(clp, state); | 259 | nfs4_schedule_stateid_recovery(server, state); |
261 | goto do_state_recovery; | 260 | goto wait_on_recovery; |
262 | case -NFS4ERR_STALE_STATEID: | 261 | case -NFS4ERR_STALE_STATEID: |
263 | case -NFS4ERR_STALE_CLIENTID: | 262 | case -NFS4ERR_STALE_CLIENTID: |
264 | case -NFS4ERR_EXPIRED: | 263 | case -NFS4ERR_EXPIRED: |
265 | goto do_state_recovery; | 264 | nfs4_schedule_lease_recovery(clp); |
265 | goto wait_on_recovery; | ||
266 | #if defined(CONFIG_NFS_V4_1) | 266 | #if defined(CONFIG_NFS_V4_1) |
267 | case -NFS4ERR_BADSESSION: | 267 | case -NFS4ERR_BADSESSION: |
268 | case -NFS4ERR_BADSLOT: | 268 | case -NFS4ERR_BADSLOT: |
@@ -273,7 +273,7 @@ static int nfs4_handle_exception(const struct nfs_server *server, int errorcode, | |||
273 | case -NFS4ERR_SEQ_MISORDERED: | 273 | case -NFS4ERR_SEQ_MISORDERED: |
274 | dprintk("%s ERROR: %d Reset session\n", __func__, | 274 | dprintk("%s ERROR: %d Reset session\n", __func__, |
275 | errorcode); | 275 | errorcode); |
276 | nfs4_schedule_state_recovery(clp); | 276 | nfs4_schedule_session_recovery(clp->cl_session); |
277 | exception->retry = 1; | 277 | exception->retry = 1; |
278 | break; | 278 | break; |
279 | #endif /* defined(CONFIG_NFS_V4_1) */ | 279 | #endif /* defined(CONFIG_NFS_V4_1) */ |
@@ -296,8 +296,7 @@ static int nfs4_handle_exception(const struct nfs_server *server, int errorcode, | |||
296 | } | 296 | } |
297 | /* We failed to handle the error */ | 297 | /* We failed to handle the error */ |
298 | return nfs4_map_errors(ret); | 298 | return nfs4_map_errors(ret); |
299 | do_state_recovery: | 299 | wait_on_recovery: |
300 | nfs4_schedule_state_recovery(clp); | ||
301 | ret = nfs4_wait_clnt_recover(clp); | 300 | ret = nfs4_wait_clnt_recover(clp); |
302 | if (ret == 0) | 301 | if (ret == 0) |
303 | exception->retry = 1; | 302 | exception->retry = 1; |
@@ -436,8 +435,8 @@ static int nfs41_sequence_done(struct rpc_task *task, struct nfs4_sequence_res * | |||
436 | clp = res->sr_session->clp; | 435 | clp = res->sr_session->clp; |
437 | do_renew_lease(clp, timestamp); | 436 | do_renew_lease(clp, timestamp); |
438 | /* Check sequence flags */ | 437 | /* Check sequence flags */ |
439 | if (atomic_read(&clp->cl_count) > 1) | 438 | if (res->sr_status_flags != 0) |
440 | nfs41_handle_sequence_flag_errors(clp, res->sr_status_flags); | 439 | nfs4_schedule_lease_recovery(clp); |
441 | break; | 440 | break; |
442 | case -NFS4ERR_DELAY: | 441 | case -NFS4ERR_DELAY: |
443 | /* The server detected a resend of the RPC call and | 442 | /* The server detected a resend of the RPC call and |
@@ -1256,14 +1255,13 @@ int nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs4_state | |||
1256 | case -NFS4ERR_BAD_HIGH_SLOT: | 1255 | case -NFS4ERR_BAD_HIGH_SLOT: |
1257 | case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION: | 1256 | case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION: |
1258 | case -NFS4ERR_DEADSESSION: | 1257 | case -NFS4ERR_DEADSESSION: |
1259 | nfs4_schedule_state_recovery( | 1258 | nfs4_schedule_session_recovery(server->nfs_client->cl_session); |
1260 | server->nfs_client); | ||
1261 | goto out; | 1259 | goto out; |
1262 | case -NFS4ERR_STALE_CLIENTID: | 1260 | case -NFS4ERR_STALE_CLIENTID: |
1263 | case -NFS4ERR_STALE_STATEID: | 1261 | case -NFS4ERR_STALE_STATEID: |
1264 | case -NFS4ERR_EXPIRED: | 1262 | case -NFS4ERR_EXPIRED: |
1265 | /* Don't recall a delegation if it was lost */ | 1263 | /* Don't recall a delegation if it was lost */ |
1266 | nfs4_schedule_state_recovery(server->nfs_client); | 1264 | nfs4_schedule_lease_recovery(server->nfs_client); |
1267 | goto out; | 1265 | goto out; |
1268 | case -ERESTARTSYS: | 1266 | case -ERESTARTSYS: |
1269 | /* | 1267 | /* |
@@ -1272,7 +1270,7 @@ int nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs4_state | |||
1272 | */ | 1270 | */ |
1273 | case -NFS4ERR_ADMIN_REVOKED: | 1271 | case -NFS4ERR_ADMIN_REVOKED: |
1274 | case -NFS4ERR_BAD_STATEID: | 1272 | case -NFS4ERR_BAD_STATEID: |
1275 | nfs4_state_mark_reclaim_nograce(server->nfs_client, state); | 1273 | nfs4_schedule_stateid_recovery(server, state); |
1276 | case -EKEYEXPIRED: | 1274 | case -EKEYEXPIRED: |
1277 | /* | 1275 | /* |
1278 | * User RPCSEC_GSS context has expired. | 1276 | * User RPCSEC_GSS context has expired. |
@@ -1588,7 +1586,7 @@ static int nfs4_recover_expired_lease(struct nfs_server *server) | |||
1588 | if (!test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) && | 1586 | if (!test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) && |
1589 | !test_bit(NFS4CLNT_CHECK_LEASE,&clp->cl_state)) | 1587 | !test_bit(NFS4CLNT_CHECK_LEASE,&clp->cl_state)) |
1590 | break; | 1588 | break; |
1591 | nfs4_schedule_state_recovery(clp); | 1589 | nfs4_schedule_state_manager(clp); |
1592 | ret = -EIO; | 1590 | ret = -EIO; |
1593 | } | 1591 | } |
1594 | return ret; | 1592 | return ret; |
@@ -3179,7 +3177,7 @@ static void nfs4_renew_done(struct rpc_task *task, void *calldata) | |||
3179 | if (task->tk_status < 0) { | 3177 | if (task->tk_status < 0) { |
3180 | /* Unless we're shutting down, schedule state recovery! */ | 3178 | /* Unless we're shutting down, schedule state recovery! */ |
3181 | if (test_bit(NFS_CS_RENEWD, &clp->cl_res_state) != 0) | 3179 | if (test_bit(NFS_CS_RENEWD, &clp->cl_res_state) != 0) |
3182 | nfs4_schedule_state_recovery(clp); | 3180 | nfs4_schedule_lease_recovery(clp); |
3183 | return; | 3181 | return; |
3184 | } | 3182 | } |
3185 | do_renew_lease(clp, timestamp); | 3183 | do_renew_lease(clp, timestamp); |
@@ -3262,7 +3260,7 @@ static int buf_to_pages_noslab(const void *buf, size_t buflen, | |||
3262 | spages = pages; | 3260 | spages = pages; |
3263 | 3261 | ||
3264 | do { | 3262 | do { |
3265 | len = min(PAGE_CACHE_SIZE, buflen); | 3263 | len = min_t(size_t, PAGE_CACHE_SIZE, buflen); |
3266 | newpage = alloc_page(GFP_KERNEL); | 3264 | newpage = alloc_page(GFP_KERNEL); |
3267 | 3265 | ||
3268 | if (newpage == NULL) | 3266 | if (newpage == NULL) |
@@ -3504,12 +3502,13 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server, | |||
3504 | case -NFS4ERR_OPENMODE: | 3502 | case -NFS4ERR_OPENMODE: |
3505 | if (state == NULL) | 3503 | if (state == NULL) |
3506 | break; | 3504 | break; |
3507 | nfs4_state_mark_reclaim_nograce(clp, state); | 3505 | nfs4_schedule_stateid_recovery(server, state); |
3508 | goto do_state_recovery; | 3506 | goto wait_on_recovery; |
3509 | case -NFS4ERR_STALE_STATEID: | 3507 | case -NFS4ERR_STALE_STATEID: |
3510 | case -NFS4ERR_STALE_CLIENTID: | 3508 | case -NFS4ERR_STALE_CLIENTID: |
3511 | case -NFS4ERR_EXPIRED: | 3509 | case -NFS4ERR_EXPIRED: |
3512 | goto do_state_recovery; | 3510 | nfs4_schedule_lease_recovery(clp); |
3511 | goto wait_on_recovery; | ||
3513 | #if defined(CONFIG_NFS_V4_1) | 3512 | #if defined(CONFIG_NFS_V4_1) |
3514 | case -NFS4ERR_BADSESSION: | 3513 | case -NFS4ERR_BADSESSION: |
3515 | case -NFS4ERR_BADSLOT: | 3514 | case -NFS4ERR_BADSLOT: |
@@ -3520,7 +3519,7 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server, | |||
3520 | case -NFS4ERR_SEQ_MISORDERED: | 3519 | case -NFS4ERR_SEQ_MISORDERED: |
3521 | dprintk("%s ERROR %d, Reset session\n", __func__, | 3520 | dprintk("%s ERROR %d, Reset session\n", __func__, |
3522 | task->tk_status); | 3521 | task->tk_status); |
3523 | nfs4_schedule_state_recovery(clp); | 3522 | nfs4_schedule_session_recovery(clp->cl_session); |
3524 | task->tk_status = 0; | 3523 | task->tk_status = 0; |
3525 | return -EAGAIN; | 3524 | return -EAGAIN; |
3526 | #endif /* CONFIG_NFS_V4_1 */ | 3525 | #endif /* CONFIG_NFS_V4_1 */ |
@@ -3537,9 +3536,8 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server, | |||
3537 | } | 3536 | } |
3538 | task->tk_status = nfs4_map_errors(task->tk_status); | 3537 | task->tk_status = nfs4_map_errors(task->tk_status); |
3539 | return 0; | 3538 | return 0; |
3540 | do_state_recovery: | 3539 | wait_on_recovery: |
3541 | rpc_sleep_on(&clp->cl_rpcwaitq, task, NULL); | 3540 | rpc_sleep_on(&clp->cl_rpcwaitq, task, NULL); |
3542 | nfs4_schedule_state_recovery(clp); | ||
3543 | if (test_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) == 0) | 3541 | if (test_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) == 0) |
3544 | rpc_wake_up_queued_task(&clp->cl_rpcwaitq, task); | 3542 | rpc_wake_up_queued_task(&clp->cl_rpcwaitq, task); |
3545 | task->tk_status = 0; | 3543 | task->tk_status = 0; |
@@ -4150,7 +4148,7 @@ static void nfs4_lock_release(void *calldata) | |||
4150 | task = nfs4_do_unlck(&data->fl, data->ctx, data->lsp, | 4148 | task = nfs4_do_unlck(&data->fl, data->ctx, data->lsp, |
4151 | data->arg.lock_seqid); | 4149 | data->arg.lock_seqid); |
4152 | if (!IS_ERR(task)) | 4150 | if (!IS_ERR(task)) |
4153 | rpc_put_task(task); | 4151 | rpc_put_task_async(task); |
4154 | dprintk("%s: cancelling lock!\n", __func__); | 4152 | dprintk("%s: cancelling lock!\n", __func__); |
4155 | } else | 4153 | } else |
4156 | nfs_free_seqid(data->arg.lock_seqid); | 4154 | nfs_free_seqid(data->arg.lock_seqid); |
@@ -4174,23 +4172,18 @@ static const struct rpc_call_ops nfs4_recover_lock_ops = { | |||
4174 | 4172 | ||
4175 | static void nfs4_handle_setlk_error(struct nfs_server *server, struct nfs4_lock_state *lsp, int new_lock_owner, int error) | 4173 | static void nfs4_handle_setlk_error(struct nfs_server *server, struct nfs4_lock_state *lsp, int new_lock_owner, int error) |
4176 | { | 4174 | { |
4177 | struct nfs_client *clp = server->nfs_client; | ||
4178 | struct nfs4_state *state = lsp->ls_state; | ||
4179 | |||
4180 | switch (error) { | 4175 | switch (error) { |
4181 | case -NFS4ERR_ADMIN_REVOKED: | 4176 | case -NFS4ERR_ADMIN_REVOKED: |
4182 | case -NFS4ERR_BAD_STATEID: | 4177 | case -NFS4ERR_BAD_STATEID: |
4183 | case -NFS4ERR_EXPIRED: | 4178 | lsp->ls_seqid.flags &= ~NFS_SEQID_CONFIRMED; |
4184 | if (new_lock_owner != 0 || | 4179 | if (new_lock_owner != 0 || |
4185 | (lsp->ls_flags & NFS_LOCK_INITIALIZED) != 0) | 4180 | (lsp->ls_flags & NFS_LOCK_INITIALIZED) != 0) |
4186 | nfs4_state_mark_reclaim_nograce(clp, state); | 4181 | nfs4_schedule_stateid_recovery(server, lsp->ls_state); |
4187 | lsp->ls_seqid.flags &= ~NFS_SEQID_CONFIRMED; | ||
4188 | break; | 4182 | break; |
4189 | case -NFS4ERR_STALE_STATEID: | 4183 | case -NFS4ERR_STALE_STATEID: |
4190 | if (new_lock_owner != 0 || | ||
4191 | (lsp->ls_flags & NFS_LOCK_INITIALIZED) != 0) | ||
4192 | nfs4_state_mark_reclaim_reboot(clp, state); | ||
4193 | lsp->ls_seqid.flags &= ~NFS_SEQID_CONFIRMED; | 4184 | lsp->ls_seqid.flags &= ~NFS_SEQID_CONFIRMED; |
4185 | case -NFS4ERR_EXPIRED: | ||
4186 | nfs4_schedule_lease_recovery(server->nfs_client); | ||
4194 | }; | 4187 | }; |
4195 | } | 4188 | } |
4196 | 4189 | ||
@@ -4406,12 +4399,14 @@ int nfs4_lock_delegation_recall(struct nfs4_state *state, struct file_lock *fl) | |||
4406 | case -NFS4ERR_EXPIRED: | 4399 | case -NFS4ERR_EXPIRED: |
4407 | case -NFS4ERR_STALE_CLIENTID: | 4400 | case -NFS4ERR_STALE_CLIENTID: |
4408 | case -NFS4ERR_STALE_STATEID: | 4401 | case -NFS4ERR_STALE_STATEID: |
4402 | nfs4_schedule_lease_recovery(server->nfs_client); | ||
4403 | goto out; | ||
4409 | case -NFS4ERR_BADSESSION: | 4404 | case -NFS4ERR_BADSESSION: |
4410 | case -NFS4ERR_BADSLOT: | 4405 | case -NFS4ERR_BADSLOT: |
4411 | case -NFS4ERR_BAD_HIGH_SLOT: | 4406 | case -NFS4ERR_BAD_HIGH_SLOT: |
4412 | case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION: | 4407 | case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION: |
4413 | case -NFS4ERR_DEADSESSION: | 4408 | case -NFS4ERR_DEADSESSION: |
4414 | nfs4_schedule_state_recovery(server->nfs_client); | 4409 | nfs4_schedule_session_recovery(server->nfs_client->cl_session); |
4415 | goto out; | 4410 | goto out; |
4416 | case -ERESTARTSYS: | 4411 | case -ERESTARTSYS: |
4417 | /* | 4412 | /* |
@@ -4421,7 +4416,7 @@ int nfs4_lock_delegation_recall(struct nfs4_state *state, struct file_lock *fl) | |||
4421 | case -NFS4ERR_ADMIN_REVOKED: | 4416 | case -NFS4ERR_ADMIN_REVOKED: |
4422 | case -NFS4ERR_BAD_STATEID: | 4417 | case -NFS4ERR_BAD_STATEID: |
4423 | case -NFS4ERR_OPENMODE: | 4418 | case -NFS4ERR_OPENMODE: |
4424 | nfs4_state_mark_reclaim_nograce(server->nfs_client, state); | 4419 | nfs4_schedule_stateid_recovery(server, state); |
4425 | err = 0; | 4420 | err = 0; |
4426 | goto out; | 4421 | goto out; |
4427 | case -EKEYEXPIRED: | 4422 | case -EKEYEXPIRED: |
@@ -5028,10 +5023,20 @@ int nfs4_proc_create_session(struct nfs_client *clp) | |||
5028 | int status; | 5023 | int status; |
5029 | unsigned *ptr; | 5024 | unsigned *ptr; |
5030 | struct nfs4_session *session = clp->cl_session; | 5025 | struct nfs4_session *session = clp->cl_session; |
5026 | long timeout = 0; | ||
5027 | int err; | ||
5031 | 5028 | ||
5032 | dprintk("--> %s clp=%p session=%p\n", __func__, clp, session); | 5029 | dprintk("--> %s clp=%p session=%p\n", __func__, clp, session); |
5033 | 5030 | ||
5034 | status = _nfs4_proc_create_session(clp); | 5031 | do { |
5032 | status = _nfs4_proc_create_session(clp); | ||
5033 | if (status == -NFS4ERR_DELAY) { | ||
5034 | err = nfs4_delay(clp->cl_rpcclient, &timeout); | ||
5035 | if (err) | ||
5036 | status = err; | ||
5037 | } | ||
5038 | } while (status == -NFS4ERR_DELAY); | ||
5039 | |||
5035 | if (status) | 5040 | if (status) |
5036 | goto out; | 5041 | goto out; |
5037 | 5042 | ||
@@ -5140,7 +5145,7 @@ static int nfs41_sequence_handle_errors(struct rpc_task *task, struct nfs_client | |||
5140 | rpc_delay(task, NFS4_POLL_RETRY_MAX); | 5145 | rpc_delay(task, NFS4_POLL_RETRY_MAX); |
5141 | return -EAGAIN; | 5146 | return -EAGAIN; |
5142 | default: | 5147 | default: |
5143 | nfs4_schedule_state_recovery(clp); | 5148 | nfs4_schedule_lease_recovery(clp); |
5144 | } | 5149 | } |
5145 | return 0; | 5150 | return 0; |
5146 | } | 5151 | } |
@@ -5227,7 +5232,7 @@ static int nfs41_proc_async_sequence(struct nfs_client *clp, struct rpc_cred *cr | |||
5227 | if (IS_ERR(task)) | 5232 | if (IS_ERR(task)) |
5228 | ret = PTR_ERR(task); | 5233 | ret = PTR_ERR(task); |
5229 | else | 5234 | else |
5230 | rpc_put_task(task); | 5235 | rpc_put_task_async(task); |
5231 | dprintk("<-- %s status=%d\n", __func__, ret); | 5236 | dprintk("<-- %s status=%d\n", __func__, ret); |
5232 | return ret; | 5237 | return ret; |
5233 | } | 5238 | } |
@@ -5243,8 +5248,13 @@ static int nfs4_proc_sequence(struct nfs_client *clp, struct rpc_cred *cred) | |||
5243 | goto out; | 5248 | goto out; |
5244 | } | 5249 | } |
5245 | ret = rpc_wait_for_completion_task(task); | 5250 | ret = rpc_wait_for_completion_task(task); |
5246 | if (!ret) | 5251 | if (!ret) { |
5252 | struct nfs4_sequence_res *res = task->tk_msg.rpc_resp; | ||
5253 | |||
5254 | if (task->tk_status == 0) | ||
5255 | nfs41_handle_sequence_flag_errors(clp, res->sr_status_flags); | ||
5247 | ret = task->tk_status; | 5256 | ret = task->tk_status; |
5257 | } | ||
5248 | rpc_put_task(task); | 5258 | rpc_put_task(task); |
5249 | out: | 5259 | out: |
5250 | dprintk("<-- %s status=%d\n", __func__, ret); | 5260 | dprintk("<-- %s status=%d\n", __func__, ret); |
@@ -5281,7 +5291,7 @@ static int nfs41_reclaim_complete_handle_errors(struct rpc_task *task, struct nf | |||
5281 | rpc_delay(task, NFS4_POLL_RETRY_MAX); | 5291 | rpc_delay(task, NFS4_POLL_RETRY_MAX); |
5282 | return -EAGAIN; | 5292 | return -EAGAIN; |
5283 | default: | 5293 | default: |
5284 | nfs4_schedule_state_recovery(clp); | 5294 | nfs4_schedule_lease_recovery(clp); |
5285 | } | 5295 | } |
5286 | return 0; | 5296 | return 0; |
5287 | } | 5297 | } |
@@ -5349,6 +5359,9 @@ static int nfs41_proc_reclaim_complete(struct nfs_client *clp) | |||
5349 | status = PTR_ERR(task); | 5359 | status = PTR_ERR(task); |
5350 | goto out; | 5360 | goto out; |
5351 | } | 5361 | } |
5362 | status = nfs4_wait_for_completion_rpc_task(task); | ||
5363 | if (status == 0) | ||
5364 | status = task->tk_status; | ||
5352 | rpc_put_task(task); | 5365 | rpc_put_task(task); |
5353 | return 0; | 5366 | return 0; |
5354 | out: | 5367 | out: |
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index e6742b57a04c..0592288f9f06 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c | |||
@@ -1007,9 +1007,9 @@ void nfs4_schedule_state_manager(struct nfs_client *clp) | |||
1007 | } | 1007 | } |
1008 | 1008 | ||
1009 | /* | 1009 | /* |
1010 | * Schedule a state recovery attempt | 1010 | * Schedule a lease recovery attempt |
1011 | */ | 1011 | */ |
1012 | void nfs4_schedule_state_recovery(struct nfs_client *clp) | 1012 | void nfs4_schedule_lease_recovery(struct nfs_client *clp) |
1013 | { | 1013 | { |
1014 | if (!clp) | 1014 | if (!clp) |
1015 | return; | 1015 | return; |
@@ -1018,7 +1018,7 @@ void nfs4_schedule_state_recovery(struct nfs_client *clp) | |||
1018 | nfs4_schedule_state_manager(clp); | 1018 | nfs4_schedule_state_manager(clp); |
1019 | } | 1019 | } |
1020 | 1020 | ||
1021 | int nfs4_state_mark_reclaim_reboot(struct nfs_client *clp, struct nfs4_state *state) | 1021 | static int nfs4_state_mark_reclaim_reboot(struct nfs_client *clp, struct nfs4_state *state) |
1022 | { | 1022 | { |
1023 | 1023 | ||
1024 | set_bit(NFS_STATE_RECLAIM_REBOOT, &state->flags); | 1024 | set_bit(NFS_STATE_RECLAIM_REBOOT, &state->flags); |
@@ -1032,7 +1032,7 @@ int nfs4_state_mark_reclaim_reboot(struct nfs_client *clp, struct nfs4_state *st | |||
1032 | return 1; | 1032 | return 1; |
1033 | } | 1033 | } |
1034 | 1034 | ||
1035 | int nfs4_state_mark_reclaim_nograce(struct nfs_client *clp, struct nfs4_state *state) | 1035 | static int nfs4_state_mark_reclaim_nograce(struct nfs_client *clp, struct nfs4_state *state) |
1036 | { | 1036 | { |
1037 | set_bit(NFS_STATE_RECLAIM_NOGRACE, &state->flags); | 1037 | set_bit(NFS_STATE_RECLAIM_NOGRACE, &state->flags); |
1038 | clear_bit(NFS_STATE_RECLAIM_REBOOT, &state->flags); | 1038 | clear_bit(NFS_STATE_RECLAIM_REBOOT, &state->flags); |
@@ -1041,6 +1041,14 @@ int nfs4_state_mark_reclaim_nograce(struct nfs_client *clp, struct nfs4_state *s | |||
1041 | return 1; | 1041 | return 1; |
1042 | } | 1042 | } |
1043 | 1043 | ||
1044 | void nfs4_schedule_stateid_recovery(const struct nfs_server *server, struct nfs4_state *state) | ||
1045 | { | ||
1046 | struct nfs_client *clp = server->nfs_client; | ||
1047 | |||
1048 | nfs4_state_mark_reclaim_nograce(clp, state); | ||
1049 | nfs4_schedule_state_manager(clp); | ||
1050 | } | ||
1051 | |||
1044 | static int nfs4_reclaim_locks(struct nfs4_state *state, const struct nfs4_state_recovery_ops *ops) | 1052 | static int nfs4_reclaim_locks(struct nfs4_state *state, const struct nfs4_state_recovery_ops *ops) |
1045 | { | 1053 | { |
1046 | struct inode *inode = state->inode; | 1054 | struct inode *inode = state->inode; |
@@ -1436,10 +1444,15 @@ static int nfs4_reclaim_lease(struct nfs_client *clp) | |||
1436 | } | 1444 | } |
1437 | 1445 | ||
1438 | #ifdef CONFIG_NFS_V4_1 | 1446 | #ifdef CONFIG_NFS_V4_1 |
1447 | void nfs4_schedule_session_recovery(struct nfs4_session *session) | ||
1448 | { | ||
1449 | nfs4_schedule_lease_recovery(session->clp); | ||
1450 | } | ||
1451 | |||
1439 | void nfs41_handle_recall_slot(struct nfs_client *clp) | 1452 | void nfs41_handle_recall_slot(struct nfs_client *clp) |
1440 | { | 1453 | { |
1441 | set_bit(NFS4CLNT_RECALL_SLOT, &clp->cl_state); | 1454 | set_bit(NFS4CLNT_RECALL_SLOT, &clp->cl_state); |
1442 | nfs4_schedule_state_recovery(clp); | 1455 | nfs4_schedule_state_manager(clp); |
1443 | } | 1456 | } |
1444 | 1457 | ||
1445 | static void nfs4_reset_all_state(struct nfs_client *clp) | 1458 | static void nfs4_reset_all_state(struct nfs_client *clp) |
@@ -1447,7 +1460,7 @@ static void nfs4_reset_all_state(struct nfs_client *clp) | |||
1447 | if (test_and_set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) == 0) { | 1460 | if (test_and_set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) == 0) { |
1448 | clp->cl_boot_time = CURRENT_TIME; | 1461 | clp->cl_boot_time = CURRENT_TIME; |
1449 | nfs4_state_start_reclaim_nograce(clp); | 1462 | nfs4_state_start_reclaim_nograce(clp); |
1450 | nfs4_schedule_state_recovery(clp); | 1463 | nfs4_schedule_state_manager(clp); |
1451 | } | 1464 | } |
1452 | } | 1465 | } |
1453 | 1466 | ||
@@ -1455,7 +1468,7 @@ static void nfs41_handle_server_reboot(struct nfs_client *clp) | |||
1455 | { | 1468 | { |
1456 | if (test_and_set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) == 0) { | 1469 | if (test_and_set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) == 0) { |
1457 | nfs4_state_start_reclaim_reboot(clp); | 1470 | nfs4_state_start_reclaim_reboot(clp); |
1458 | nfs4_schedule_state_recovery(clp); | 1471 | nfs4_schedule_state_manager(clp); |
1459 | } | 1472 | } |
1460 | } | 1473 | } |
1461 | 1474 | ||
@@ -1475,7 +1488,7 @@ static void nfs41_handle_cb_path_down(struct nfs_client *clp) | |||
1475 | { | 1488 | { |
1476 | nfs_expire_all_delegations(clp); | 1489 | nfs_expire_all_delegations(clp); |
1477 | if (test_and_set_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state) == 0) | 1490 | if (test_and_set_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state) == 0) |
1478 | nfs4_schedule_state_recovery(clp); | 1491 | nfs4_schedule_state_manager(clp); |
1479 | } | 1492 | } |
1480 | 1493 | ||
1481 | void nfs41_handle_sequence_flag_errors(struct nfs_client *clp, u32 flags) | 1494 | void nfs41_handle_sequence_flag_errors(struct nfs_client *clp, u32 flags) |
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index 4e2c168b6ee9..94d50e86a124 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c | |||
@@ -1660,7 +1660,7 @@ static void encode_create_session(struct xdr_stream *xdr, | |||
1660 | 1660 | ||
1661 | p = reserve_space(xdr, 20 + 2*28 + 20 + len + 12); | 1661 | p = reserve_space(xdr, 20 + 2*28 + 20 + len + 12); |
1662 | *p++ = cpu_to_be32(OP_CREATE_SESSION); | 1662 | *p++ = cpu_to_be32(OP_CREATE_SESSION); |
1663 | p = xdr_encode_hyper(p, clp->cl_ex_clid); | 1663 | p = xdr_encode_hyper(p, clp->cl_clientid); |
1664 | *p++ = cpu_to_be32(clp->cl_seqid); /*Sequence id */ | 1664 | *p++ = cpu_to_be32(clp->cl_seqid); /*Sequence id */ |
1665 | *p++ = cpu_to_be32(args->flags); /*flags */ | 1665 | *p++ = cpu_to_be32(args->flags); /*flags */ |
1666 | 1666 | ||
@@ -4694,7 +4694,7 @@ static int decode_exchange_id(struct xdr_stream *xdr, | |||
4694 | p = xdr_inline_decode(xdr, 8); | 4694 | p = xdr_inline_decode(xdr, 8); |
4695 | if (unlikely(!p)) | 4695 | if (unlikely(!p)) |
4696 | goto out_overflow; | 4696 | goto out_overflow; |
4697 | xdr_decode_hyper(p, &clp->cl_ex_clid); | 4697 | xdr_decode_hyper(p, &clp->cl_clientid); |
4698 | p = xdr_inline_decode(xdr, 12); | 4698 | p = xdr_inline_decode(xdr, 12); |
4699 | if (unlikely(!p)) | 4699 | if (unlikely(!p)) |
4700 | goto out_overflow; | 4700 | goto out_overflow; |
diff --git a/fs/nfs/nfsroot.c b/fs/nfs/nfsroot.c index 903908a20023..c541093a5bf2 100644 --- a/fs/nfs/nfsroot.c +++ b/fs/nfs/nfsroot.c | |||
@@ -86,11 +86,14 @@ | |||
86 | /* Default path we try to mount. "%s" gets replaced by our IP address */ | 86 | /* Default path we try to mount. "%s" gets replaced by our IP address */ |
87 | #define NFS_ROOT "/tftpboot/%s" | 87 | #define NFS_ROOT "/tftpboot/%s" |
88 | 88 | ||
89 | /* Default NFSROOT mount options. */ | ||
90 | #define NFS_DEF_OPTIONS "udp" | ||
91 | |||
89 | /* Parameters passed from the kernel command line */ | 92 | /* Parameters passed from the kernel command line */ |
90 | static char nfs_root_parms[256] __initdata = ""; | 93 | static char nfs_root_parms[256] __initdata = ""; |
91 | 94 | ||
92 | /* Text-based mount options passed to super.c */ | 95 | /* Text-based mount options passed to super.c */ |
93 | static char nfs_root_options[256] __initdata = ""; | 96 | static char nfs_root_options[256] __initdata = NFS_DEF_OPTIONS; |
94 | 97 | ||
95 | /* Address of NFS server */ | 98 | /* Address of NFS server */ |
96 | static __be32 servaddr __initdata = htonl(INADDR_NONE); | 99 | static __be32 servaddr __initdata = htonl(INADDR_NONE); |
@@ -160,8 +163,14 @@ static int __init root_nfs_copy(char *dest, const char *src, | |||
160 | } | 163 | } |
161 | 164 | ||
162 | static int __init root_nfs_cat(char *dest, const char *src, | 165 | static int __init root_nfs_cat(char *dest, const char *src, |
163 | const size_t destlen) | 166 | const size_t destlen) |
164 | { | 167 | { |
168 | size_t len = strlen(dest); | ||
169 | |||
170 | if (len && dest[len - 1] != ',') | ||
171 | if (strlcat(dest, ",", destlen) > destlen) | ||
172 | return -1; | ||
173 | |||
165 | if (strlcat(dest, src, destlen) > destlen) | 174 | if (strlcat(dest, src, destlen) > destlen) |
166 | return -1; | 175 | return -1; |
167 | return 0; | 176 | return 0; |
@@ -194,16 +203,6 @@ static int __init root_nfs_parse_options(char *incoming, char *exppath, | |||
194 | if (root_nfs_cat(nfs_root_options, incoming, | 203 | if (root_nfs_cat(nfs_root_options, incoming, |
195 | sizeof(nfs_root_options))) | 204 | sizeof(nfs_root_options))) |
196 | return -1; | 205 | return -1; |
197 | |||
198 | /* | ||
199 | * Possibly prepare for more options to be appended | ||
200 | */ | ||
201 | if (nfs_root_options[0] != '\0' && | ||
202 | nfs_root_options[strlen(nfs_root_options)] != ',') | ||
203 | if (root_nfs_cat(nfs_root_options, ",", | ||
204 | sizeof(nfs_root_options))) | ||
205 | return -1; | ||
206 | |||
207 | return 0; | 206 | return 0; |
208 | } | 207 | } |
209 | 208 | ||
@@ -217,7 +216,7 @@ static int __init root_nfs_parse_options(char *incoming, char *exppath, | |||
217 | */ | 216 | */ |
218 | static int __init root_nfs_data(char *cmdline) | 217 | static int __init root_nfs_data(char *cmdline) |
219 | { | 218 | { |
220 | char addr_option[sizeof("nolock,addr=") + INET_ADDRSTRLEN + 1]; | 219 | char mand_options[sizeof("nolock,addr=") + INET_ADDRSTRLEN + 1]; |
221 | int len, retval = -1; | 220 | int len, retval = -1; |
222 | char *tmp = NULL; | 221 | char *tmp = NULL; |
223 | const size_t tmplen = sizeof(nfs_export_path); | 222 | const size_t tmplen = sizeof(nfs_export_path); |
@@ -244,9 +243,9 @@ static int __init root_nfs_data(char *cmdline) | |||
244 | * Append mandatory options for nfsroot so they override | 243 | * Append mandatory options for nfsroot so they override |
245 | * what has come before | 244 | * what has come before |
246 | */ | 245 | */ |
247 | snprintf(addr_option, sizeof(addr_option), "nolock,addr=%pI4", | 246 | snprintf(mand_options, sizeof(mand_options), "nolock,addr=%pI4", |
248 | &servaddr); | 247 | &servaddr); |
249 | if (root_nfs_cat(nfs_root_options, addr_option, | 248 | if (root_nfs_cat(nfs_root_options, mand_options, |
250 | sizeof(nfs_root_options))) | 249 | sizeof(nfs_root_options))) |
251 | goto out_optionstoolong; | 250 | goto out_optionstoolong; |
252 | 251 | ||
diff --git a/fs/nfs/unlink.c b/fs/nfs/unlink.c index e313a51acdd1..6481d537d69d 100644 --- a/fs/nfs/unlink.c +++ b/fs/nfs/unlink.c | |||
@@ -180,7 +180,7 @@ static int nfs_do_call_unlink(struct dentry *parent, struct inode *dir, struct n | |||
180 | task_setup_data.rpc_client = NFS_CLIENT(dir); | 180 | task_setup_data.rpc_client = NFS_CLIENT(dir); |
181 | task = rpc_run_task(&task_setup_data); | 181 | task = rpc_run_task(&task_setup_data); |
182 | if (!IS_ERR(task)) | 182 | if (!IS_ERR(task)) |
183 | rpc_put_task(task); | 183 | rpc_put_task_async(task); |
184 | return 1; | 184 | return 1; |
185 | } | 185 | } |
186 | 186 | ||
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index c8278f4046cb..42b92d7a9cc4 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
@@ -1292,6 +1292,8 @@ static int nfs_commit_rpcsetup(struct list_head *head, | |||
1292 | task = rpc_run_task(&task_setup_data); | 1292 | task = rpc_run_task(&task_setup_data); |
1293 | if (IS_ERR(task)) | 1293 | if (IS_ERR(task)) |
1294 | return PTR_ERR(task); | 1294 | return PTR_ERR(task); |
1295 | if (how & FLUSH_SYNC) | ||
1296 | rpc_wait_for_completion_task(task); | ||
1295 | rpc_put_task(task); | 1297 | rpc_put_task(task); |
1296 | return 0; | 1298 | return 0; |
1297 | } | 1299 | } |
diff --git a/fs/partitions/osf.c b/fs/partitions/osf.c index 48cec7cbca17..be03a0b08b47 100644 --- a/fs/partitions/osf.c +++ b/fs/partitions/osf.c | |||
@@ -10,10 +10,13 @@ | |||
10 | #include "check.h" | 10 | #include "check.h" |
11 | #include "osf.h" | 11 | #include "osf.h" |
12 | 12 | ||
13 | #define MAX_OSF_PARTITIONS 8 | ||
14 | |||
13 | int osf_partition(struct parsed_partitions *state) | 15 | int osf_partition(struct parsed_partitions *state) |
14 | { | 16 | { |
15 | int i; | 17 | int i; |
16 | int slot = 1; | 18 | int slot = 1; |
19 | unsigned int npartitions; | ||
17 | Sector sect; | 20 | Sector sect; |
18 | unsigned char *data; | 21 | unsigned char *data; |
19 | struct disklabel { | 22 | struct disklabel { |
@@ -45,7 +48,7 @@ int osf_partition(struct parsed_partitions *state) | |||
45 | u8 p_fstype; | 48 | u8 p_fstype; |
46 | u8 p_frag; | 49 | u8 p_frag; |
47 | __le16 p_cpg; | 50 | __le16 p_cpg; |
48 | } d_partitions[8]; | 51 | } d_partitions[MAX_OSF_PARTITIONS]; |
49 | } * label; | 52 | } * label; |
50 | struct d_partition * partition; | 53 | struct d_partition * partition; |
51 | 54 | ||
@@ -63,7 +66,12 @@ int osf_partition(struct parsed_partitions *state) | |||
63 | put_dev_sector(sect); | 66 | put_dev_sector(sect); |
64 | return 0; | 67 | return 0; |
65 | } | 68 | } |
66 | for (i = 0 ; i < le16_to_cpu(label->d_npartitions); i++, partition++) { | 69 | npartitions = le16_to_cpu(label->d_npartitions); |
70 | if (npartitions > MAX_OSF_PARTITIONS) { | ||
71 | put_dev_sector(sect); | ||
72 | return 0; | ||
73 | } | ||
74 | for (i = 0 ; i < npartitions; i++, partition++) { | ||
67 | if (slot == state->limit) | 75 | if (slot == state->limit) |
68 | break; | 76 | break; |
69 | if (le32_to_cpu(partition->p_size)) | 77 | if (le32_to_cpu(partition->p_size)) |
diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h index 55e0d4253e49..d746da19c6a2 100644 --- a/include/linux/interrupt.h +++ b/include/linux/interrupt.h | |||
@@ -55,7 +55,7 @@ | |||
55 | * Used by threaded interrupts which need to keep the | 55 | * Used by threaded interrupts which need to keep the |
56 | * irq line disabled until the threaded handler has been run. | 56 | * irq line disabled until the threaded handler has been run. |
57 | * IRQF_NO_SUSPEND - Do not disable this IRQ during suspend | 57 | * IRQF_NO_SUSPEND - Do not disable this IRQ during suspend |
58 | * | 58 | * IRQF_FORCE_RESUME - Force enable it on resume even if IRQF_NO_SUSPEND is set |
59 | */ | 59 | */ |
60 | #define IRQF_DISABLED 0x00000020 | 60 | #define IRQF_DISABLED 0x00000020 |
61 | #define IRQF_SAMPLE_RANDOM 0x00000040 | 61 | #define IRQF_SAMPLE_RANDOM 0x00000040 |
@@ -67,6 +67,7 @@ | |||
67 | #define IRQF_IRQPOLL 0x00001000 | 67 | #define IRQF_IRQPOLL 0x00001000 |
68 | #define IRQF_ONESHOT 0x00002000 | 68 | #define IRQF_ONESHOT 0x00002000 |
69 | #define IRQF_NO_SUSPEND 0x00004000 | 69 | #define IRQF_NO_SUSPEND 0x00004000 |
70 | #define IRQF_FORCE_RESUME 0x00008000 | ||
70 | 71 | ||
71 | #define IRQF_TIMER (__IRQF_TIMER | IRQF_NO_SUSPEND) | 72 | #define IRQF_TIMER (__IRQF_TIMER | IRQF_NO_SUSPEND) |
72 | 73 | ||
diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h index b197563913bf..3e112de12d8d 100644 --- a/include/linux/nfs_fs_sb.h +++ b/include/linux/nfs_fs_sb.h | |||
@@ -68,11 +68,7 @@ struct nfs_client { | |||
68 | unsigned char cl_id_uniquifier; | 68 | unsigned char cl_id_uniquifier; |
69 | u32 cl_cb_ident; /* v4.0 callback identifier */ | 69 | u32 cl_cb_ident; /* v4.0 callback identifier */ |
70 | const struct nfs4_minor_version_ops *cl_mvops; | 70 | const struct nfs4_minor_version_ops *cl_mvops; |
71 | #endif /* CONFIG_NFS_V4 */ | ||
72 | 71 | ||
73 | #ifdef CONFIG_NFS_V4_1 | ||
74 | /* clientid returned from EXCHANGE_ID, used by session operations */ | ||
75 | u64 cl_ex_clid; | ||
76 | /* The sequence id to use for the next CREATE_SESSION */ | 72 | /* The sequence id to use for the next CREATE_SESSION */ |
77 | u32 cl_seqid; | 73 | u32 cl_seqid; |
78 | /* The flags used for obtaining the clientid during EXCHANGE_ID */ | 74 | /* The flags used for obtaining the clientid during EXCHANGE_ID */ |
@@ -80,7 +76,7 @@ struct nfs_client { | |||
80 | struct nfs4_session *cl_session; /* sharred session */ | 76 | struct nfs4_session *cl_session; /* sharred session */ |
81 | struct list_head cl_layouts; | 77 | struct list_head cl_layouts; |
82 | struct pnfs_deviceid_cache *cl_devid_cache; /* pNFS deviceid cache */ | 78 | struct pnfs_deviceid_cache *cl_devid_cache; /* pNFS deviceid cache */ |
83 | #endif /* CONFIG_NFS_V4_1 */ | 79 | #endif /* CONFIG_NFS_V4 */ |
84 | 80 | ||
85 | #ifdef CONFIG_NFS_FSCACHE | 81 | #ifdef CONFIG_NFS_FSCACHE |
86 | struct fscache_cookie *fscache; /* client index cache cookie */ | 82 | struct fscache_cookie *fscache; /* client index cache cookie */ |
@@ -185,7 +181,7 @@ struct nfs_server { | |||
185 | /* maximum number of slots to use */ | 181 | /* maximum number of slots to use */ |
186 | #define NFS4_MAX_SLOT_TABLE RPC_MAX_SLOT_TABLE | 182 | #define NFS4_MAX_SLOT_TABLE RPC_MAX_SLOT_TABLE |
187 | 183 | ||
188 | #if defined(CONFIG_NFS_V4_1) | 184 | #if defined(CONFIG_NFS_V4) |
189 | 185 | ||
190 | /* Sessions */ | 186 | /* Sessions */ |
191 | #define SLOT_TABLE_SZ (NFS4_MAX_SLOT_TABLE/(8*sizeof(long))) | 187 | #define SLOT_TABLE_SZ (NFS4_MAX_SLOT_TABLE/(8*sizeof(long))) |
@@ -225,5 +221,5 @@ struct nfs4_session { | |||
225 | struct nfs_client *clp; | 221 | struct nfs_client *clp; |
226 | }; | 222 | }; |
227 | 223 | ||
228 | #endif /* CONFIG_NFS_V4_1 */ | 224 | #endif /* CONFIG_NFS_V4 */ |
229 | #endif | 225 | #endif |
diff --git a/include/linux/sunrpc/sched.h b/include/linux/sunrpc/sched.h index 88513fd8e208..d81db8012c63 100644 --- a/include/linux/sunrpc/sched.h +++ b/include/linux/sunrpc/sched.h | |||
@@ -212,6 +212,7 @@ struct rpc_task *rpc_run_task(const struct rpc_task_setup *); | |||
212 | struct rpc_task *rpc_run_bc_task(struct rpc_rqst *req, | 212 | struct rpc_task *rpc_run_bc_task(struct rpc_rqst *req, |
213 | const struct rpc_call_ops *ops); | 213 | const struct rpc_call_ops *ops); |
214 | void rpc_put_task(struct rpc_task *); | 214 | void rpc_put_task(struct rpc_task *); |
215 | void rpc_put_task_async(struct rpc_task *); | ||
215 | void rpc_exit_task(struct rpc_task *); | 216 | void rpc_exit_task(struct rpc_task *); |
216 | void rpc_exit(struct rpc_task *, int); | 217 | void rpc_exit(struct rpc_task *, int); |
217 | void rpc_release_calldata(const struct rpc_call_ops *, void *); | 218 | void rpc_release_calldata(const struct rpc_call_ops *, void *); |
diff --git a/include/target/target_core_transport.h b/include/target/target_core_transport.h index 246940511579..2e8ec51f0615 100644 --- a/include/target/target_core_transport.h +++ b/include/target/target_core_transport.h | |||
@@ -135,6 +135,8 @@ extern void transport_complete_task(struct se_task *, int); | |||
135 | extern void transport_add_task_to_execute_queue(struct se_task *, | 135 | extern void transport_add_task_to_execute_queue(struct se_task *, |
136 | struct se_task *, | 136 | struct se_task *, |
137 | struct se_device *); | 137 | struct se_device *); |
138 | extern void transport_remove_task_from_execute_queue(struct se_task *, | ||
139 | struct se_device *); | ||
138 | unsigned char *transport_dump_cmd_direction(struct se_cmd *); | 140 | unsigned char *transport_dump_cmd_direction(struct se_cmd *); |
139 | extern void transport_dump_dev_state(struct se_device *, char *, int *); | 141 | extern void transport_dump_dev_state(struct se_device *, char *, int *); |
140 | extern void transport_dump_dev_info(struct se_device *, struct se_lun *, | 142 | extern void transport_dump_dev_info(struct se_device *, struct se_lun *, |
diff --git a/include/xen/events.h b/include/xen/events.h index 00f53ddcc062..962da2ced5b4 100644 --- a/include/xen/events.h +++ b/include/xen/events.h | |||
@@ -75,11 +75,9 @@ int xen_allocate_pirq(unsigned gsi, int shareable, char *name); | |||
75 | int xen_map_pirq_gsi(unsigned pirq, unsigned gsi, int shareable, char *name); | 75 | int xen_map_pirq_gsi(unsigned pirq, unsigned gsi, int shareable, char *name); |
76 | 76 | ||
77 | #ifdef CONFIG_PCI_MSI | 77 | #ifdef CONFIG_PCI_MSI |
78 | /* Allocate an irq and a pirq to be used with MSIs. */ | 78 | int xen_allocate_pirq_msi(struct pci_dev *dev, struct msi_desc *msidesc); |
79 | #define XEN_ALLOC_PIRQ (1 << 0) | 79 | int xen_bind_pirq_msi_to_irq(struct pci_dev *dev, struct msi_desc *msidesc, |
80 | #define XEN_ALLOC_IRQ (1 << 1) | 80 | int pirq, int vector, const char *name); |
81 | void xen_allocate_pirq_msi(char *name, int *irq, int *pirq, int alloc_mask); | ||
82 | int xen_create_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc, int type); | ||
83 | #endif | 81 | #endif |
84 | 82 | ||
85 | /* De-allocates the above mentioned physical interrupt. */ | 83 | /* De-allocates the above mentioned physical interrupt. */ |
diff --git a/include/xen/interface/io/blkif.h b/include/xen/interface/io/blkif.h index c2d1fa4dc1ee..61e523af3c46 100644 --- a/include/xen/interface/io/blkif.h +++ b/include/xen/interface/io/blkif.h | |||
@@ -51,11 +51,7 @@ typedef uint64_t blkif_sector_t; | |||
51 | */ | 51 | */ |
52 | #define BLKIF_MAX_SEGMENTS_PER_REQUEST 11 | 52 | #define BLKIF_MAX_SEGMENTS_PER_REQUEST 11 |
53 | 53 | ||
54 | struct blkif_request { | 54 | struct blkif_request_rw { |
55 | uint8_t operation; /* BLKIF_OP_??? */ | ||
56 | uint8_t nr_segments; /* number of segments */ | ||
57 | blkif_vdev_t handle; /* only for read/write requests */ | ||
58 | uint64_t id; /* private guest value, echoed in resp */ | ||
59 | blkif_sector_t sector_number;/* start sector idx on disk (r/w only) */ | 55 | blkif_sector_t sector_number;/* start sector idx on disk (r/w only) */ |
60 | struct blkif_request_segment { | 56 | struct blkif_request_segment { |
61 | grant_ref_t gref; /* reference to I/O buffer frame */ | 57 | grant_ref_t gref; /* reference to I/O buffer frame */ |
@@ -65,6 +61,16 @@ struct blkif_request { | |||
65 | } seg[BLKIF_MAX_SEGMENTS_PER_REQUEST]; | 61 | } seg[BLKIF_MAX_SEGMENTS_PER_REQUEST]; |
66 | }; | 62 | }; |
67 | 63 | ||
64 | struct blkif_request { | ||
65 | uint8_t operation; /* BLKIF_OP_??? */ | ||
66 | uint8_t nr_segments; /* number of segments */ | ||
67 | blkif_vdev_t handle; /* only for read/write requests */ | ||
68 | uint64_t id; /* private guest value, echoed in resp */ | ||
69 | union { | ||
70 | struct blkif_request_rw rw; | ||
71 | } u; | ||
72 | }; | ||
73 | |||
68 | struct blkif_response { | 74 | struct blkif_response { |
69 | uint64_t id; /* copied from request */ | 75 | uint64_t id; /* copied from request */ |
70 | uint8_t operation; /* copied from request */ | 76 | uint8_t operation; /* copied from request */ |
@@ -91,4 +97,25 @@ DEFINE_RING_TYPES(blkif, struct blkif_request, struct blkif_response); | |||
91 | #define VDISK_REMOVABLE 0x2 | 97 | #define VDISK_REMOVABLE 0x2 |
92 | #define VDISK_READONLY 0x4 | 98 | #define VDISK_READONLY 0x4 |
93 | 99 | ||
100 | /* Xen-defined major numbers for virtual disks, they look strangely | ||
101 | * familiar */ | ||
102 | #define XEN_IDE0_MAJOR 3 | ||
103 | #define XEN_IDE1_MAJOR 22 | ||
104 | #define XEN_SCSI_DISK0_MAJOR 8 | ||
105 | #define XEN_SCSI_DISK1_MAJOR 65 | ||
106 | #define XEN_SCSI_DISK2_MAJOR 66 | ||
107 | #define XEN_SCSI_DISK3_MAJOR 67 | ||
108 | #define XEN_SCSI_DISK4_MAJOR 68 | ||
109 | #define XEN_SCSI_DISK5_MAJOR 69 | ||
110 | #define XEN_SCSI_DISK6_MAJOR 70 | ||
111 | #define XEN_SCSI_DISK7_MAJOR 71 | ||
112 | #define XEN_SCSI_DISK8_MAJOR 128 | ||
113 | #define XEN_SCSI_DISK9_MAJOR 129 | ||
114 | #define XEN_SCSI_DISK10_MAJOR 130 | ||
115 | #define XEN_SCSI_DISK11_MAJOR 131 | ||
116 | #define XEN_SCSI_DISK12_MAJOR 132 | ||
117 | #define XEN_SCSI_DISK13_MAJOR 133 | ||
118 | #define XEN_SCSI_DISK14_MAJOR 134 | ||
119 | #define XEN_SCSI_DISK15_MAJOR 135 | ||
120 | |||
94 | #endif /* __XEN_PUBLIC_IO_BLKIF_H__ */ | 121 | #endif /* __XEN_PUBLIC_IO_BLKIF_H__ */ |
diff --git a/include/xen/interface/xen.h b/include/xen/interface/xen.h index 2befa3e2f1bc..b33257bc7e83 100644 --- a/include/xen/interface/xen.h +++ b/include/xen/interface/xen.h | |||
@@ -30,7 +30,7 @@ | |||
30 | #define __HYPERVISOR_stack_switch 3 | 30 | #define __HYPERVISOR_stack_switch 3 |
31 | #define __HYPERVISOR_set_callbacks 4 | 31 | #define __HYPERVISOR_set_callbacks 4 |
32 | #define __HYPERVISOR_fpu_taskswitch 5 | 32 | #define __HYPERVISOR_fpu_taskswitch 5 |
33 | #define __HYPERVISOR_sched_op 6 | 33 | #define __HYPERVISOR_sched_op_compat 6 |
34 | #define __HYPERVISOR_dom0_op 7 | 34 | #define __HYPERVISOR_dom0_op 7 |
35 | #define __HYPERVISOR_set_debugreg 8 | 35 | #define __HYPERVISOR_set_debugreg 8 |
36 | #define __HYPERVISOR_get_debugreg 9 | 36 | #define __HYPERVISOR_get_debugreg 9 |
@@ -52,7 +52,7 @@ | |||
52 | #define __HYPERVISOR_mmuext_op 26 | 52 | #define __HYPERVISOR_mmuext_op 26 |
53 | #define __HYPERVISOR_acm_op 27 | 53 | #define __HYPERVISOR_acm_op 27 |
54 | #define __HYPERVISOR_nmi_op 28 | 54 | #define __HYPERVISOR_nmi_op 28 |
55 | #define __HYPERVISOR_sched_op_new 29 | 55 | #define __HYPERVISOR_sched_op 29 |
56 | #define __HYPERVISOR_callback_op 30 | 56 | #define __HYPERVISOR_callback_op 30 |
57 | #define __HYPERVISOR_xenoprof_op 31 | 57 | #define __HYPERVISOR_xenoprof_op 31 |
58 | #define __HYPERVISOR_event_channel_op 32 | 58 | #define __HYPERVISOR_event_channel_op 32 |
diff --git a/include/xen/xen-ops.h b/include/xen/xen-ops.h index 98b92154a264..03c85d7387fb 100644 --- a/include/xen/xen-ops.h +++ b/include/xen/xen-ops.h | |||
@@ -5,9 +5,9 @@ | |||
5 | 5 | ||
6 | DECLARE_PER_CPU(struct vcpu_info *, xen_vcpu); | 6 | DECLARE_PER_CPU(struct vcpu_info *, xen_vcpu); |
7 | 7 | ||
8 | void xen_pre_suspend(void); | 8 | void xen_arch_pre_suspend(void); |
9 | void xen_post_suspend(int suspend_cancelled); | 9 | void xen_arch_post_suspend(int suspend_cancelled); |
10 | void xen_hvm_post_suspend(int suspend_cancelled); | 10 | void xen_arch_hvm_post_suspend(int suspend_cancelled); |
11 | 11 | ||
12 | void xen_mm_pin_all(void); | 12 | void xen_mm_pin_all(void); |
13 | void xen_mm_unpin_all(void); | 13 | void xen_mm_unpin_all(void); |
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index 9033c1c70828..2782bacdf494 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c | |||
@@ -282,8 +282,17 @@ EXPORT_SYMBOL(disable_irq); | |||
282 | 282 | ||
283 | void __enable_irq(struct irq_desc *desc, unsigned int irq, bool resume) | 283 | void __enable_irq(struct irq_desc *desc, unsigned int irq, bool resume) |
284 | { | 284 | { |
285 | if (resume) | 285 | if (resume) { |
286 | if (!(desc->status & IRQ_SUSPENDED)) { | ||
287 | if (!desc->action) | ||
288 | return; | ||
289 | if (!(desc->action->flags & IRQF_FORCE_RESUME)) | ||
290 | return; | ||
291 | /* Pretend that it got disabled ! */ | ||
292 | desc->depth++; | ||
293 | } | ||
286 | desc->status &= ~IRQ_SUSPENDED; | 294 | desc->status &= ~IRQ_SUSPENDED; |
295 | } | ||
287 | 296 | ||
288 | switch (desc->depth) { | 297 | switch (desc->depth) { |
289 | case 0: | 298 | case 0: |
diff --git a/kernel/irq/pm.c b/kernel/irq/pm.c index 0d4005d85b03..d6bfb89cce91 100644 --- a/kernel/irq/pm.c +++ b/kernel/irq/pm.c | |||
@@ -53,9 +53,6 @@ void resume_device_irqs(void) | |||
53 | for_each_irq_desc(irq, desc) { | 53 | for_each_irq_desc(irq, desc) { |
54 | unsigned long flags; | 54 | unsigned long flags; |
55 | 55 | ||
56 | if (!(desc->status & IRQ_SUSPENDED)) | ||
57 | continue; | ||
58 | |||
59 | raw_spin_lock_irqsave(&desc->lock, flags); | 56 | raw_spin_lock_irqsave(&desc->lock, flags); |
60 | __enable_irq(desc, irq, true); | 57 | __enable_irq(desc, irq, true); |
61 | raw_spin_unlock_irqrestore(&desc->lock, flags); | 58 | raw_spin_unlock_irqrestore(&desc->lock, flags); |
diff --git a/kernel/sched.c b/kernel/sched.c index 18d38e4ec7ba..42eab5a8437d 100644 --- a/kernel/sched.c +++ b/kernel/sched.c | |||
@@ -4213,6 +4213,7 @@ void __wake_up_locked_key(wait_queue_head_t *q, unsigned int mode, void *key) | |||
4213 | { | 4213 | { |
4214 | __wake_up_common(q, mode, 1, 0, key); | 4214 | __wake_up_common(q, mode, 1, 0, key); |
4215 | } | 4215 | } |
4216 | EXPORT_SYMBOL_GPL(__wake_up_locked_key); | ||
4216 | 4217 | ||
4217 | /** | 4218 | /** |
4218 | * __wake_up_sync_key - wake up threads blocked on a waitqueue. | 4219 | * __wake_up_sync_key - wake up threads blocked on a waitqueue. |
diff --git a/mm/huge_memory.c b/mm/huge_memory.c index dbe99a5f2073..113e35c47502 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c | |||
@@ -1762,6 +1762,10 @@ static void collapse_huge_page(struct mm_struct *mm, | |||
1762 | #ifndef CONFIG_NUMA | 1762 | #ifndef CONFIG_NUMA |
1763 | VM_BUG_ON(!*hpage); | 1763 | VM_BUG_ON(!*hpage); |
1764 | new_page = *hpage; | 1764 | new_page = *hpage; |
1765 | if (unlikely(mem_cgroup_newpage_charge(new_page, mm, GFP_KERNEL))) { | ||
1766 | up_read(&mm->mmap_sem); | ||
1767 | return; | ||
1768 | } | ||
1765 | #else | 1769 | #else |
1766 | VM_BUG_ON(*hpage); | 1770 | VM_BUG_ON(*hpage); |
1767 | /* | 1771 | /* |
@@ -1781,12 +1785,12 @@ static void collapse_huge_page(struct mm_struct *mm, | |||
1781 | *hpage = ERR_PTR(-ENOMEM); | 1785 | *hpage = ERR_PTR(-ENOMEM); |
1782 | return; | 1786 | return; |
1783 | } | 1787 | } |
1784 | #endif | ||
1785 | if (unlikely(mem_cgroup_newpage_charge(new_page, mm, GFP_KERNEL))) { | 1788 | if (unlikely(mem_cgroup_newpage_charge(new_page, mm, GFP_KERNEL))) { |
1786 | up_read(&mm->mmap_sem); | 1789 | up_read(&mm->mmap_sem); |
1787 | put_page(new_page); | 1790 | put_page(new_page); |
1788 | return; | 1791 | return; |
1789 | } | 1792 | } |
1793 | #endif | ||
1790 | 1794 | ||
1791 | /* after allocating the hugepage upgrade to mmap_sem write mode */ | 1795 | /* after allocating the hugepage upgrade to mmap_sem write mode */ |
1792 | up_read(&mm->mmap_sem); | 1796 | up_read(&mm->mmap_sem); |
@@ -497,41 +497,51 @@ int page_referenced_one(struct page *page, struct vm_area_struct *vma, | |||
497 | struct mm_struct *mm = vma->vm_mm; | 497 | struct mm_struct *mm = vma->vm_mm; |
498 | int referenced = 0; | 498 | int referenced = 0; |
499 | 499 | ||
500 | /* | ||
501 | * Don't want to elevate referenced for mlocked page that gets this far, | ||
502 | * in order that it progresses to try_to_unmap and is moved to the | ||
503 | * unevictable list. | ||
504 | */ | ||
505 | if (vma->vm_flags & VM_LOCKED) { | ||
506 | *mapcount = 0; /* break early from loop */ | ||
507 | *vm_flags |= VM_LOCKED; | ||
508 | goto out; | ||
509 | } | ||
510 | |||
511 | /* Pretend the page is referenced if the task has the | ||
512 | swap token and is in the middle of a page fault. */ | ||
513 | if (mm != current->mm && has_swap_token(mm) && | ||
514 | rwsem_is_locked(&mm->mmap_sem)) | ||
515 | referenced++; | ||
516 | |||
517 | if (unlikely(PageTransHuge(page))) { | 500 | if (unlikely(PageTransHuge(page))) { |
518 | pmd_t *pmd; | 501 | pmd_t *pmd; |
519 | 502 | ||
520 | spin_lock(&mm->page_table_lock); | 503 | spin_lock(&mm->page_table_lock); |
504 | /* | ||
505 | * rmap might return false positives; we must filter | ||
506 | * these out using page_check_address_pmd(). | ||
507 | */ | ||
521 | pmd = page_check_address_pmd(page, mm, address, | 508 | pmd = page_check_address_pmd(page, mm, address, |
522 | PAGE_CHECK_ADDRESS_PMD_FLAG); | 509 | PAGE_CHECK_ADDRESS_PMD_FLAG); |
523 | if (pmd && !pmd_trans_splitting(*pmd) && | 510 | if (!pmd) { |
524 | pmdp_clear_flush_young_notify(vma, address, pmd)) | 511 | spin_unlock(&mm->page_table_lock); |
512 | goto out; | ||
513 | } | ||
514 | |||
515 | if (vma->vm_flags & VM_LOCKED) { | ||
516 | spin_unlock(&mm->page_table_lock); | ||
517 | *mapcount = 0; /* break early from loop */ | ||
518 | *vm_flags |= VM_LOCKED; | ||
519 | goto out; | ||
520 | } | ||
521 | |||
522 | /* go ahead even if the pmd is pmd_trans_splitting() */ | ||
523 | if (pmdp_clear_flush_young_notify(vma, address, pmd)) | ||
525 | referenced++; | 524 | referenced++; |
526 | spin_unlock(&mm->page_table_lock); | 525 | spin_unlock(&mm->page_table_lock); |
527 | } else { | 526 | } else { |
528 | pte_t *pte; | 527 | pte_t *pte; |
529 | spinlock_t *ptl; | 528 | spinlock_t *ptl; |
530 | 529 | ||
530 | /* | ||
531 | * rmap might return false positives; we must filter | ||
532 | * these out using page_check_address(). | ||
533 | */ | ||
531 | pte = page_check_address(page, mm, address, &ptl, 0); | 534 | pte = page_check_address(page, mm, address, &ptl, 0); |
532 | if (!pte) | 535 | if (!pte) |
533 | goto out; | 536 | goto out; |
534 | 537 | ||
538 | if (vma->vm_flags & VM_LOCKED) { | ||
539 | pte_unmap_unlock(pte, ptl); | ||
540 | *mapcount = 0; /* break early from loop */ | ||
541 | *vm_flags |= VM_LOCKED; | ||
542 | goto out; | ||
543 | } | ||
544 | |||
535 | if (ptep_clear_flush_young_notify(vma, address, pte)) { | 545 | if (ptep_clear_flush_young_notify(vma, address, pte)) { |
536 | /* | 546 | /* |
537 | * Don't treat a reference through a sequentially read | 547 | * Don't treat a reference through a sequentially read |
@@ -546,6 +556,12 @@ int page_referenced_one(struct page *page, struct vm_area_struct *vma, | |||
546 | pte_unmap_unlock(pte, ptl); | 556 | pte_unmap_unlock(pte, ptl); |
547 | } | 557 | } |
548 | 558 | ||
559 | /* Pretend the page is referenced if the task has the | ||
560 | swap token and is in the middle of a page fault. */ | ||
561 | if (mm != current->mm && has_swap_token(mm) && | ||
562 | rwsem_is_locked(&mm->mmap_sem)) | ||
563 | referenced++; | ||
564 | |||
549 | (*mapcount)--; | 565 | (*mapcount)--; |
550 | 566 | ||
551 | if (referenced) | 567 | if (referenced) |
diff --git a/net/Makefile b/net/Makefile index a3330ebe2c53..a51d9465e628 100644 --- a/net/Makefile +++ b/net/Makefile | |||
@@ -19,9 +19,7 @@ obj-$(CONFIG_NETFILTER) += netfilter/ | |||
19 | obj-$(CONFIG_INET) += ipv4/ | 19 | obj-$(CONFIG_INET) += ipv4/ |
20 | obj-$(CONFIG_XFRM) += xfrm/ | 20 | obj-$(CONFIG_XFRM) += xfrm/ |
21 | obj-$(CONFIG_UNIX) += unix/ | 21 | obj-$(CONFIG_UNIX) += unix/ |
22 | ifneq ($(CONFIG_IPV6),) | 22 | obj-$(CONFIG_NET) += ipv6/ |
23 | obj-y += ipv6/ | ||
24 | endif | ||
25 | obj-$(CONFIG_PACKET) += packet/ | 23 | obj-$(CONFIG_PACKET) += packet/ |
26 | obj-$(CONFIG_NET_KEY) += key/ | 24 | obj-$(CONFIG_NET_KEY) += key/ |
27 | obj-$(CONFIG_BRIDGE) += bridge/ | 25 | obj-$(CONFIG_BRIDGE) += bridge/ |
diff --git a/net/bridge/Kconfig b/net/bridge/Kconfig index 9190ae462cb4..6dee7bf648a9 100644 --- a/net/bridge/Kconfig +++ b/net/bridge/Kconfig | |||
@@ -6,6 +6,7 @@ config BRIDGE | |||
6 | tristate "802.1d Ethernet Bridging" | 6 | tristate "802.1d Ethernet Bridging" |
7 | select LLC | 7 | select LLC |
8 | select STP | 8 | select STP |
9 | depends on IPV6 || IPV6=n | ||
9 | ---help--- | 10 | ---help--- |
10 | If you say Y here, then your Linux box will be able to act as an | 11 | If you say Y here, then your Linux box will be able to act as an |
11 | Ethernet bridge, which means that the different Ethernet segments it | 12 | Ethernet bridge, which means that the different Ethernet segments it |
diff --git a/net/core/pktgen.c b/net/core/pktgen.c index a9e7fc4c461f..b5bada92f637 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c | |||
@@ -3321,7 +3321,7 @@ static void show_results(struct pktgen_dev *pkt_dev, int nr_frags) | |||
3321 | pkt_dev->started_at); | 3321 | pkt_dev->started_at); |
3322 | ktime_t idle = ns_to_ktime(pkt_dev->idle_acc); | 3322 | ktime_t idle = ns_to_ktime(pkt_dev->idle_acc); |
3323 | 3323 | ||
3324 | p += sprintf(p, "OK: %llu(c%llu+d%llu) nsec, %llu (%dbyte,%dfrags)\n", | 3324 | p += sprintf(p, "OK: %llu(c%llu+d%llu) usec, %llu (%dbyte,%dfrags)\n", |
3325 | (unsigned long long)ktime_to_us(elapsed), | 3325 | (unsigned long long)ktime_to_us(elapsed), |
3326 | (unsigned long long)ktime_to_us(ktime_sub(elapsed, idle)), | 3326 | (unsigned long long)ktime_to_us(ktime_sub(elapsed, idle)), |
3327 | (unsigned long long)ktime_to_us(idle), | 3327 | (unsigned long long)ktime_to_us(idle), |
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index df4616fce929..036652c8166d 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c | |||
@@ -670,7 +670,7 @@ int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg) | |||
670 | ifap = &ifa->ifa_next) { | 670 | ifap = &ifa->ifa_next) { |
671 | if (!strcmp(ifr.ifr_name, ifa->ifa_label) && | 671 | if (!strcmp(ifr.ifr_name, ifa->ifa_label) && |
672 | sin_orig.sin_addr.s_addr == | 672 | sin_orig.sin_addr.s_addr == |
673 | ifa->ifa_address) { | 673 | ifa->ifa_local) { |
674 | break; /* found */ | 674 | break; /* found */ |
675 | } | 675 | } |
676 | } | 676 | } |
@@ -1040,8 +1040,8 @@ static void inetdev_send_gratuitous_arp(struct net_device *dev, | |||
1040 | return; | 1040 | return; |
1041 | 1041 | ||
1042 | arp_send(ARPOP_REQUEST, ETH_P_ARP, | 1042 | arp_send(ARPOP_REQUEST, ETH_P_ARP, |
1043 | ifa->ifa_address, dev, | 1043 | ifa->ifa_local, dev, |
1044 | ifa->ifa_address, NULL, | 1044 | ifa->ifa_local, NULL, |
1045 | dev->dev_addr, NULL); | 1045 | dev->dev_addr, NULL); |
1046 | } | 1046 | } |
1047 | 1047 | ||
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index 4f4483e697bd..e528a42a52be 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c | |||
@@ -57,6 +57,7 @@ | |||
57 | MODULE_AUTHOR("Ville Nuorvala"); | 57 | MODULE_AUTHOR("Ville Nuorvala"); |
58 | MODULE_DESCRIPTION("IPv6 tunneling device"); | 58 | MODULE_DESCRIPTION("IPv6 tunneling device"); |
59 | MODULE_LICENSE("GPL"); | 59 | MODULE_LICENSE("GPL"); |
60 | MODULE_ALIAS_NETDEV("ip6tnl0"); | ||
60 | 61 | ||
61 | #ifdef IP6_TNL_DEBUG | 62 | #ifdef IP6_TNL_DEBUG |
62 | #define IP6_TNL_TRACE(x...) printk(KERN_DEBUG "%s:" x "\n", __func__) | 63 | #define IP6_TNL_TRACE(x...) printk(KERN_DEBUG "%s:" x "\n", __func__) |
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 904312e25a3c..e7db7014e89f 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -739,8 +739,10 @@ restart: | |||
739 | 739 | ||
740 | if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP)) | 740 | if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP)) |
741 | nrt = rt6_alloc_cow(rt, &fl->fl6_dst, &fl->fl6_src); | 741 | nrt = rt6_alloc_cow(rt, &fl->fl6_dst, &fl->fl6_src); |
742 | else | 742 | else if (!(rt->dst.flags & DST_HOST)) |
743 | nrt = rt6_alloc_clone(rt, &fl->fl6_dst); | 743 | nrt = rt6_alloc_clone(rt, &fl->fl6_dst); |
744 | else | ||
745 | goto out2; | ||
744 | 746 | ||
745 | dst_release(&rt->dst); | 747 | dst_release(&rt->dst); |
746 | rt = nrt ? : net->ipv6.ip6_null_entry; | 748 | rt = nrt ? : net->ipv6.ip6_null_entry; |
diff --git a/net/rds/ib_send.c b/net/rds/ib_send.c index 71f373c421bc..c47a511f203d 100644 --- a/net/rds/ib_send.c +++ b/net/rds/ib_send.c | |||
@@ -551,7 +551,10 @@ int rds_ib_xmit(struct rds_connection *conn, struct rds_message *rm, | |||
551 | if (conn->c_loopback | 551 | if (conn->c_loopback |
552 | && rm->m_inc.i_hdr.h_flags & RDS_FLAG_CONG_BITMAP) { | 552 | && rm->m_inc.i_hdr.h_flags & RDS_FLAG_CONG_BITMAP) { |
553 | rds_cong_map_updated(conn->c_fcong, ~(u64) 0); | 553 | rds_cong_map_updated(conn->c_fcong, ~(u64) 0); |
554 | return sizeof(struct rds_header) + RDS_CONG_MAP_BYTES; | 554 | scat = &rm->data.op_sg[sg]; |
555 | ret = sizeof(struct rds_header) + RDS_CONG_MAP_BYTES; | ||
556 | ret = min_t(int, ret, scat->length - conn->c_xmit_data_off); | ||
557 | return ret; | ||
555 | } | 558 | } |
556 | 559 | ||
557 | /* FIXME we may overallocate here */ | 560 | /* FIXME we may overallocate here */ |
diff --git a/net/rds/loop.c b/net/rds/loop.c index aeec1d483b17..bca6761a3ca2 100644 --- a/net/rds/loop.c +++ b/net/rds/loop.c | |||
@@ -61,10 +61,15 @@ static int rds_loop_xmit(struct rds_connection *conn, struct rds_message *rm, | |||
61 | unsigned int hdr_off, unsigned int sg, | 61 | unsigned int hdr_off, unsigned int sg, |
62 | unsigned int off) | 62 | unsigned int off) |
63 | { | 63 | { |
64 | struct scatterlist *sgp = &rm->data.op_sg[sg]; | ||
65 | int ret = sizeof(struct rds_header) + | ||
66 | be32_to_cpu(rm->m_inc.i_hdr.h_len); | ||
67 | |||
64 | /* Do not send cong updates to loopback */ | 68 | /* Do not send cong updates to loopback */ |
65 | if (rm->m_inc.i_hdr.h_flags & RDS_FLAG_CONG_BITMAP) { | 69 | if (rm->m_inc.i_hdr.h_flags & RDS_FLAG_CONG_BITMAP) { |
66 | rds_cong_map_updated(conn->c_fcong, ~(u64) 0); | 70 | rds_cong_map_updated(conn->c_fcong, ~(u64) 0); |
67 | return sizeof(struct rds_header) + RDS_CONG_MAP_BYTES; | 71 | ret = min_t(int, ret, sgp->length - conn->c_xmit_data_off); |
72 | goto out; | ||
68 | } | 73 | } |
69 | 74 | ||
70 | BUG_ON(hdr_off || sg || off); | 75 | BUG_ON(hdr_off || sg || off); |
@@ -80,8 +85,8 @@ static int rds_loop_xmit(struct rds_connection *conn, struct rds_message *rm, | |||
80 | NULL); | 85 | NULL); |
81 | 86 | ||
82 | rds_inc_put(&rm->m_inc); | 87 | rds_inc_put(&rm->m_inc); |
83 | 88 | out: | |
84 | return sizeof(struct rds_header) + be32_to_cpu(rm->m_inc.i_hdr.h_len); | 89 | return ret; |
85 | } | 90 | } |
86 | 91 | ||
87 | /* | 92 | /* |
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index 243fc09b164e..59e599498e37 100644 --- a/net/sunrpc/sched.c +++ b/net/sunrpc/sched.c | |||
@@ -252,23 +252,37 @@ static void rpc_set_active(struct rpc_task *task) | |||
252 | 252 | ||
253 | /* | 253 | /* |
254 | * Mark an RPC call as having completed by clearing the 'active' bit | 254 | * Mark an RPC call as having completed by clearing the 'active' bit |
255 | * and then waking up all tasks that were sleeping. | ||
255 | */ | 256 | */ |
256 | static void rpc_mark_complete_task(struct rpc_task *task) | 257 | static int rpc_complete_task(struct rpc_task *task) |
257 | { | 258 | { |
258 | smp_mb__before_clear_bit(); | 259 | void *m = &task->tk_runstate; |
260 | wait_queue_head_t *wq = bit_waitqueue(m, RPC_TASK_ACTIVE); | ||
261 | struct wait_bit_key k = __WAIT_BIT_KEY_INITIALIZER(m, RPC_TASK_ACTIVE); | ||
262 | unsigned long flags; | ||
263 | int ret; | ||
264 | |||
265 | spin_lock_irqsave(&wq->lock, flags); | ||
259 | clear_bit(RPC_TASK_ACTIVE, &task->tk_runstate); | 266 | clear_bit(RPC_TASK_ACTIVE, &task->tk_runstate); |
260 | smp_mb__after_clear_bit(); | 267 | ret = atomic_dec_and_test(&task->tk_count); |
261 | wake_up_bit(&task->tk_runstate, RPC_TASK_ACTIVE); | 268 | if (waitqueue_active(wq)) |
269 | __wake_up_locked_key(wq, TASK_NORMAL, &k); | ||
270 | spin_unlock_irqrestore(&wq->lock, flags); | ||
271 | return ret; | ||
262 | } | 272 | } |
263 | 273 | ||
264 | /* | 274 | /* |
265 | * Allow callers to wait for completion of an RPC call | 275 | * Allow callers to wait for completion of an RPC call |
276 | * | ||
277 | * Note the use of out_of_line_wait_on_bit() rather than wait_on_bit() | ||
278 | * to enforce taking of the wq->lock and hence avoid races with | ||
279 | * rpc_complete_task(). | ||
266 | */ | 280 | */ |
267 | int __rpc_wait_for_completion_task(struct rpc_task *task, int (*action)(void *)) | 281 | int __rpc_wait_for_completion_task(struct rpc_task *task, int (*action)(void *)) |
268 | { | 282 | { |
269 | if (action == NULL) | 283 | if (action == NULL) |
270 | action = rpc_wait_bit_killable; | 284 | action = rpc_wait_bit_killable; |
271 | return wait_on_bit(&task->tk_runstate, RPC_TASK_ACTIVE, | 285 | return out_of_line_wait_on_bit(&task->tk_runstate, RPC_TASK_ACTIVE, |
272 | action, TASK_KILLABLE); | 286 | action, TASK_KILLABLE); |
273 | } | 287 | } |
274 | EXPORT_SYMBOL_GPL(__rpc_wait_for_completion_task); | 288 | EXPORT_SYMBOL_GPL(__rpc_wait_for_completion_task); |
@@ -857,34 +871,67 @@ static void rpc_async_release(struct work_struct *work) | |||
857 | rpc_free_task(container_of(work, struct rpc_task, u.tk_work)); | 871 | rpc_free_task(container_of(work, struct rpc_task, u.tk_work)); |
858 | } | 872 | } |
859 | 873 | ||
860 | void rpc_put_task(struct rpc_task *task) | 874 | static void rpc_release_resources_task(struct rpc_task *task) |
861 | { | 875 | { |
862 | if (!atomic_dec_and_test(&task->tk_count)) | ||
863 | return; | ||
864 | /* Release resources */ | ||
865 | if (task->tk_rqstp) | 876 | if (task->tk_rqstp) |
866 | xprt_release(task); | 877 | xprt_release(task); |
867 | if (task->tk_msg.rpc_cred) | 878 | if (task->tk_msg.rpc_cred) |
868 | put_rpccred(task->tk_msg.rpc_cred); | 879 | put_rpccred(task->tk_msg.rpc_cred); |
869 | rpc_task_release_client(task); | 880 | rpc_task_release_client(task); |
870 | if (task->tk_workqueue != NULL) { | 881 | } |
882 | |||
883 | static void rpc_final_put_task(struct rpc_task *task, | ||
884 | struct workqueue_struct *q) | ||
885 | { | ||
886 | if (q != NULL) { | ||
871 | INIT_WORK(&task->u.tk_work, rpc_async_release); | 887 | INIT_WORK(&task->u.tk_work, rpc_async_release); |
872 | queue_work(task->tk_workqueue, &task->u.tk_work); | 888 | queue_work(q, &task->u.tk_work); |
873 | } else | 889 | } else |
874 | rpc_free_task(task); | 890 | rpc_free_task(task); |
875 | } | 891 | } |
892 | |||
893 | static void rpc_do_put_task(struct rpc_task *task, struct workqueue_struct *q) | ||
894 | { | ||
895 | if (atomic_dec_and_test(&task->tk_count)) { | ||
896 | rpc_release_resources_task(task); | ||
897 | rpc_final_put_task(task, q); | ||
898 | } | ||
899 | } | ||
900 | |||
901 | void rpc_put_task(struct rpc_task *task) | ||
902 | { | ||
903 | rpc_do_put_task(task, NULL); | ||
904 | } | ||
876 | EXPORT_SYMBOL_GPL(rpc_put_task); | 905 | EXPORT_SYMBOL_GPL(rpc_put_task); |
877 | 906 | ||
907 | void rpc_put_task_async(struct rpc_task *task) | ||
908 | { | ||
909 | rpc_do_put_task(task, task->tk_workqueue); | ||
910 | } | ||
911 | EXPORT_SYMBOL_GPL(rpc_put_task_async); | ||
912 | |||
878 | static void rpc_release_task(struct rpc_task *task) | 913 | static void rpc_release_task(struct rpc_task *task) |
879 | { | 914 | { |
880 | dprintk("RPC: %5u release task\n", task->tk_pid); | 915 | dprintk("RPC: %5u release task\n", task->tk_pid); |
881 | 916 | ||
882 | BUG_ON (RPC_IS_QUEUED(task)); | 917 | BUG_ON (RPC_IS_QUEUED(task)); |
883 | 918 | ||
884 | /* Wake up anyone who is waiting for task completion */ | 919 | rpc_release_resources_task(task); |
885 | rpc_mark_complete_task(task); | ||
886 | 920 | ||
887 | rpc_put_task(task); | 921 | /* |
922 | * Note: at this point we have been removed from rpc_clnt->cl_tasks, | ||
923 | * so it should be safe to use task->tk_count as a test for whether | ||
924 | * or not any other processes still hold references to our rpc_task. | ||
925 | */ | ||
926 | if (atomic_read(&task->tk_count) != 1 + !RPC_IS_ASYNC(task)) { | ||
927 | /* Wake up anyone who may be waiting for task completion */ | ||
928 | if (!rpc_complete_task(task)) | ||
929 | return; | ||
930 | } else { | ||
931 | if (!atomic_dec_and_test(&task->tk_count)) | ||
932 | return; | ||
933 | } | ||
934 | rpc_final_put_task(task, task->tk_workqueue); | ||
888 | } | 935 | } |
889 | 936 | ||
890 | int rpciod_up(void) | 937 | int rpciod_up(void) |
diff --git a/net/sunrpc/xprtrdma/svc_rdma_transport.c b/net/sunrpc/xprtrdma/svc_rdma_transport.c index 9df1eadc912a..1a10dcd999ea 100644 --- a/net/sunrpc/xprtrdma/svc_rdma_transport.c +++ b/net/sunrpc/xprtrdma/svc_rdma_transport.c | |||
@@ -1335,6 +1335,7 @@ void svc_rdma_send_error(struct svcxprt_rdma *xprt, struct rpcrdma_msg *rmsgp, | |||
1335 | p, 0, length, DMA_FROM_DEVICE); | 1335 | p, 0, length, DMA_FROM_DEVICE); |
1336 | if (ib_dma_mapping_error(xprt->sc_cm_id->device, ctxt->sge[0].addr)) { | 1336 | if (ib_dma_mapping_error(xprt->sc_cm_id->device, ctxt->sge[0].addr)) { |
1337 | put_page(p); | 1337 | put_page(p); |
1338 | svc_rdma_put_context(ctxt, 1); | ||
1338 | return; | 1339 | return; |
1339 | } | 1340 | } |
1340 | atomic_inc(&xprt->sc_dma_used); | 1341 | atomic_inc(&xprt->sc_dma_used); |
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index c431f5a57960..be96d429b475 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c | |||
@@ -1631,7 +1631,8 @@ static struct socket *xs_create_sock(struct rpc_xprt *xprt, | |||
1631 | } | 1631 | } |
1632 | xs_reclassify_socket(family, sock); | 1632 | xs_reclassify_socket(family, sock); |
1633 | 1633 | ||
1634 | if (xs_bind(transport, sock)) { | 1634 | err = xs_bind(transport, sock); |
1635 | if (err) { | ||
1635 | sock_release(sock); | 1636 | sock_release(sock); |
1636 | goto out; | 1637 | goto out; |
1637 | } | 1638 | } |
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index d8c04a602cf1..ba5b8c208498 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c | |||
@@ -1724,7 +1724,11 @@ static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1724 | 1724 | ||
1725 | msg->msg_namelen = 0; | 1725 | msg->msg_namelen = 0; |
1726 | 1726 | ||
1727 | mutex_lock(&u->readlock); | 1727 | err = mutex_lock_interruptible(&u->readlock); |
1728 | if (err) { | ||
1729 | err = sock_intr_errno(sock_rcvtimeo(sk, noblock)); | ||
1730 | goto out; | ||
1731 | } | ||
1728 | 1732 | ||
1729 | skb = skb_recv_datagram(sk, flags, noblock, &err); | 1733 | skb = skb_recv_datagram(sk, flags, noblock, &err); |
1730 | if (!skb) { | 1734 | if (!skb) { |
@@ -1864,7 +1868,11 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1864 | memset(&tmp_scm, 0, sizeof(tmp_scm)); | 1868 | memset(&tmp_scm, 0, sizeof(tmp_scm)); |
1865 | } | 1869 | } |
1866 | 1870 | ||
1867 | mutex_lock(&u->readlock); | 1871 | err = mutex_lock_interruptible(&u->readlock); |
1872 | if (err) { | ||
1873 | err = sock_intr_errno(timeo); | ||
1874 | goto out; | ||
1875 | } | ||
1868 | 1876 | ||
1869 | do { | 1877 | do { |
1870 | int chunk; | 1878 | int chunk; |
@@ -1895,11 +1903,12 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1895 | 1903 | ||
1896 | timeo = unix_stream_data_wait(sk, timeo); | 1904 | timeo = unix_stream_data_wait(sk, timeo); |
1897 | 1905 | ||
1898 | if (signal_pending(current)) { | 1906 | if (signal_pending(current) |
1907 | || mutex_lock_interruptible(&u->readlock)) { | ||
1899 | err = sock_intr_errno(timeo); | 1908 | err = sock_intr_errno(timeo); |
1900 | goto out; | 1909 | goto out; |
1901 | } | 1910 | } |
1902 | mutex_lock(&u->readlock); | 1911 | |
1903 | continue; | 1912 | continue; |
1904 | unlock: | 1913 | unlock: |
1905 | unix_state_unlock(sk); | 1914 | unix_state_unlock(sk); |
diff --git a/scripts/basic/fixdep.c b/scripts/basic/fixdep.c index 6c94c6ce2925..291228e25984 100644 --- a/scripts/basic/fixdep.c +++ b/scripts/basic/fixdep.c | |||
@@ -309,6 +309,11 @@ static void do_config_file(const char *filename) | |||
309 | close(fd); | 309 | close(fd); |
310 | } | 310 | } |
311 | 311 | ||
312 | /* | ||
313 | * Important: The below generated source_foo.o and deps_foo.o variable | ||
314 | * assignments are parsed not only by make, but also by the rather simple | ||
315 | * parser in scripts/mod/sumversion.c. | ||
316 | */ | ||
312 | static void parse_dep_file(void *map, size_t len) | 317 | static void parse_dep_file(void *map, size_t len) |
313 | { | 318 | { |
314 | char *m = map; | 319 | char *m = map; |
@@ -323,7 +328,6 @@ static void parse_dep_file(void *map, size_t len) | |||
323 | exit(1); | 328 | exit(1); |
324 | } | 329 | } |
325 | memcpy(s, m, p-m); s[p-m] = 0; | 330 | memcpy(s, m, p-m); s[p-m] = 0; |
326 | printf("deps_%s := \\\n", target); | ||
327 | m = p+1; | 331 | m = p+1; |
328 | 332 | ||
329 | clear_config(); | 333 | clear_config(); |
@@ -343,12 +347,15 @@ static void parse_dep_file(void *map, size_t len) | |||
343 | strrcmp(s, "arch/um/include/uml-config.h") && | 347 | strrcmp(s, "arch/um/include/uml-config.h") && |
344 | strrcmp(s, ".ver")) { | 348 | strrcmp(s, ".ver")) { |
345 | /* | 349 | /* |
346 | * Do not output the first dependency (the | 350 | * Do not list the source file as dependency, so that |
347 | * source file), so that kbuild is not confused | 351 | * kbuild is not confused if a .c file is rewritten |
348 | * if a .c file is rewritten into .S or vice | 352 | * into .S or vice versa. Storing it in source_* is |
349 | * versa. | 353 | * needed for modpost to compute srcversions. |
350 | */ | 354 | */ |
351 | if (!first) | 355 | if (first) { |
356 | printf("source_%s := %s\n\n", target, s); | ||
357 | printf("deps_%s := \\\n", target); | ||
358 | } else | ||
352 | printf(" %s \\\n", s); | 359 | printf(" %s \\\n", s); |
353 | do_config_file(s); | 360 | do_config_file(s); |
354 | } | 361 | } |
diff --git a/scripts/mod/sumversion.c b/scripts/mod/sumversion.c index ecf9c7dc1825..9dfcd6d988da 100644 --- a/scripts/mod/sumversion.c +++ b/scripts/mod/sumversion.c | |||
@@ -300,8 +300,8 @@ static int is_static_library(const char *objfile) | |||
300 | return 0; | 300 | return 0; |
301 | } | 301 | } |
302 | 302 | ||
303 | /* We have dir/file.o. Open dir/.file.o.cmd, look for deps_ line to | 303 | /* We have dir/file.o. Open dir/.file.o.cmd, look for source_ and deps_ line |
304 | * figure out source file. */ | 304 | * to figure out source files. */ |
305 | static int parse_source_files(const char *objfile, struct md4_ctx *md) | 305 | static int parse_source_files(const char *objfile, struct md4_ctx *md) |
306 | { | 306 | { |
307 | char *cmd, *file, *line, *dir; | 307 | char *cmd, *file, *line, *dir; |
@@ -340,6 +340,21 @@ static int parse_source_files(const char *objfile, struct md4_ctx *md) | |||
340 | */ | 340 | */ |
341 | while ((line = get_next_line(&pos, file, flen)) != NULL) { | 341 | while ((line = get_next_line(&pos, file, flen)) != NULL) { |
342 | char* p = line; | 342 | char* p = line; |
343 | |||
344 | if (strncmp(line, "source_", sizeof("source_")-1) == 0) { | ||
345 | p = strrchr(line, ' '); | ||
346 | if (!p) { | ||
347 | warn("malformed line: %s\n", line); | ||
348 | goto out_file; | ||
349 | } | ||
350 | p++; | ||
351 | if (!parse_file(p, md)) { | ||
352 | warn("could not open %s: %s\n", | ||
353 | p, strerror(errno)); | ||
354 | goto out_file; | ||
355 | } | ||
356 | continue; | ||
357 | } | ||
343 | if (strncmp(line, "deps_", sizeof("deps_")-1) == 0) { | 358 | if (strncmp(line, "deps_", sizeof("deps_")-1) == 0) { |
344 | check_files = 1; | 359 | check_files = 1; |
345 | continue; | 360 | continue; |
diff --git a/sound/soc/codecs/wm8978.c b/sound/soc/codecs/wm8978.c index 4bbc3442703f..8dfb0a0da673 100644 --- a/sound/soc/codecs/wm8978.c +++ b/sound/soc/codecs/wm8978.c | |||
@@ -145,18 +145,18 @@ static const struct snd_kcontrol_new wm8978_snd_controls[] = { | |||
145 | SOC_SINGLE("DAC Playback Limiter Threshold", | 145 | SOC_SINGLE("DAC Playback Limiter Threshold", |
146 | WM8978_DAC_LIMITER_2, 4, 7, 0), | 146 | WM8978_DAC_LIMITER_2, 4, 7, 0), |
147 | SOC_SINGLE("DAC Playback Limiter Boost", | 147 | SOC_SINGLE("DAC Playback Limiter Boost", |
148 | WM8978_DAC_LIMITER_2, 0, 15, 0), | 148 | WM8978_DAC_LIMITER_2, 0, 12, 0), |
149 | 149 | ||
150 | SOC_ENUM("ALC Enable Switch", alc1), | 150 | SOC_ENUM("ALC Enable Switch", alc1), |
151 | SOC_SINGLE("ALC Capture Min Gain", WM8978_ALC_CONTROL_1, 0, 7, 0), | 151 | SOC_SINGLE("ALC Capture Min Gain", WM8978_ALC_CONTROL_1, 0, 7, 0), |
152 | SOC_SINGLE("ALC Capture Max Gain", WM8978_ALC_CONTROL_1, 3, 7, 0), | 152 | SOC_SINGLE("ALC Capture Max Gain", WM8978_ALC_CONTROL_1, 3, 7, 0), |
153 | 153 | ||
154 | SOC_SINGLE("ALC Capture Hold", WM8978_ALC_CONTROL_2, 4, 7, 0), | 154 | SOC_SINGLE("ALC Capture Hold", WM8978_ALC_CONTROL_2, 4, 10, 0), |
155 | SOC_SINGLE("ALC Capture Target", WM8978_ALC_CONTROL_2, 0, 15, 0), | 155 | SOC_SINGLE("ALC Capture Target", WM8978_ALC_CONTROL_2, 0, 15, 0), |
156 | 156 | ||
157 | SOC_ENUM("ALC Capture Mode", alc3), | 157 | SOC_ENUM("ALC Capture Mode", alc3), |
158 | SOC_SINGLE("ALC Capture Decay", WM8978_ALC_CONTROL_3, 4, 15, 0), | 158 | SOC_SINGLE("ALC Capture Decay", WM8978_ALC_CONTROL_3, 4, 10, 0), |
159 | SOC_SINGLE("ALC Capture Attack", WM8978_ALC_CONTROL_3, 0, 15, 0), | 159 | SOC_SINGLE("ALC Capture Attack", WM8978_ALC_CONTROL_3, 0, 10, 0), |
160 | 160 | ||
161 | SOC_SINGLE("ALC Capture Noise Gate Switch", WM8978_NOISE_GATE, 3, 1, 0), | 161 | SOC_SINGLE("ALC Capture Noise Gate Switch", WM8978_NOISE_GATE, 3, 1, 0), |
162 | SOC_SINGLE("ALC Capture Noise Gate Threshold", | 162 | SOC_SINGLE("ALC Capture Noise Gate Threshold", |
@@ -211,8 +211,10 @@ static const struct snd_kcontrol_new wm8978_snd_controls[] = { | |||
211 | WM8978_LOUT2_SPK_CONTROL, WM8978_ROUT2_SPK_CONTROL, 6, 1, 1), | 211 | WM8978_LOUT2_SPK_CONTROL, WM8978_ROUT2_SPK_CONTROL, 6, 1, 1), |
212 | 212 | ||
213 | /* DAC / ADC oversampling */ | 213 | /* DAC / ADC oversampling */ |
214 | SOC_SINGLE("DAC 128x Oversampling Switch", WM8978_DAC_CONTROL, 8, 1, 0), | 214 | SOC_SINGLE("DAC 128x Oversampling Switch", WM8978_DAC_CONTROL, |
215 | SOC_SINGLE("ADC 128x Oversampling Switch", WM8978_ADC_CONTROL, 8, 1, 0), | 215 | 5, 1, 0), |
216 | SOC_SINGLE("ADC 128x Oversampling Switch", WM8978_ADC_CONTROL, | ||
217 | 5, 1, 0), | ||
216 | }; | 218 | }; |
217 | 219 | ||
218 | /* Mixer #1: Output (OUT1, OUT2) Mixer: mix AUX, Input mixer output and DAC */ | 220 | /* Mixer #1: Output (OUT1, OUT2) Mixer: mix AUX, Input mixer output and DAC */ |
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 4afbe3b2e443..c6c958ee5d59 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c | |||
@@ -1418,7 +1418,7 @@ SND_SOC_DAPM_DAC_E("DAC1R", NULL, SND_SOC_NOPM, 0, 0, | |||
1418 | 1418 | ||
1419 | static const struct snd_soc_dapm_widget wm8994_dac_widgets[] = { | 1419 | static const struct snd_soc_dapm_widget wm8994_dac_widgets[] = { |
1420 | SND_SOC_DAPM_DAC("DAC2L", NULL, WM8994_POWER_MANAGEMENT_5, 3, 0), | 1420 | SND_SOC_DAPM_DAC("DAC2L", NULL, WM8994_POWER_MANAGEMENT_5, 3, 0), |
1421 | SND_SOC_DAPM_DAC("DAC1R", NULL, WM8994_POWER_MANAGEMENT_5, 2, 0), | 1421 | SND_SOC_DAPM_DAC("DAC2R", NULL, WM8994_POWER_MANAGEMENT_5, 2, 0), |
1422 | SND_SOC_DAPM_DAC("DAC1L", NULL, WM8994_POWER_MANAGEMENT_5, 1, 0), | 1422 | SND_SOC_DAPM_DAC("DAC1L", NULL, WM8994_POWER_MANAGEMENT_5, 1, 0), |
1423 | SND_SOC_DAPM_DAC("DAC1R", NULL, WM8994_POWER_MANAGEMENT_5, 0, 0), | 1423 | SND_SOC_DAPM_DAC("DAC1R", NULL, WM8994_POWER_MANAGEMENT_5, 0, 0), |
1424 | }; | 1424 | }; |
@@ -3325,6 +3325,12 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) | |||
3325 | case WM8958: | 3325 | case WM8958: |
3326 | snd_soc_add_controls(codec, wm8958_snd_controls, | 3326 | snd_soc_add_controls(codec, wm8958_snd_controls, |
3327 | ARRAY_SIZE(wm8958_snd_controls)); | 3327 | ARRAY_SIZE(wm8958_snd_controls)); |
3328 | snd_soc_dapm_new_controls(dapm, wm8994_lateclk_widgets, | ||
3329 | ARRAY_SIZE(wm8994_lateclk_widgets)); | ||
3330 | snd_soc_dapm_new_controls(dapm, wm8994_adc_widgets, | ||
3331 | ARRAY_SIZE(wm8994_adc_widgets)); | ||
3332 | snd_soc_dapm_new_controls(dapm, wm8994_dac_widgets, | ||
3333 | ARRAY_SIZE(wm8994_dac_widgets)); | ||
3328 | snd_soc_dapm_new_controls(dapm, wm8958_dapm_widgets, | 3334 | snd_soc_dapm_new_controls(dapm, wm8958_dapm_widgets, |
3329 | ARRAY_SIZE(wm8958_dapm_widgets)); | 3335 | ARRAY_SIZE(wm8958_dapm_widgets)); |
3330 | break; | 3336 | break; |
@@ -3350,6 +3356,8 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) | |||
3350 | } | 3356 | } |
3351 | break; | 3357 | break; |
3352 | case WM8958: | 3358 | case WM8958: |
3359 | snd_soc_dapm_add_routes(dapm, wm8994_lateclk_intercon, | ||
3360 | ARRAY_SIZE(wm8994_lateclk_intercon)); | ||
3353 | snd_soc_dapm_add_routes(dapm, wm8958_intercon, | 3361 | snd_soc_dapm_add_routes(dapm, wm8958_intercon, |
3354 | ARRAY_SIZE(wm8958_intercon)); | 3362 | ARRAY_SIZE(wm8958_intercon)); |
3355 | break; | 3363 | break; |
diff --git a/sound/soc/omap/am3517evm.c b/sound/soc/omap/am3517evm.c index 161750443ebc..73dde4a1adc3 100644 --- a/sound/soc/omap/am3517evm.c +++ b/sound/soc/omap/am3517evm.c | |||
@@ -139,7 +139,7 @@ static struct snd_soc_dai_link am3517evm_dai = { | |||
139 | .cpu_dai_name ="omap-mcbsp-dai.0", | 139 | .cpu_dai_name ="omap-mcbsp-dai.0", |
140 | .codec_dai_name = "tlv320aic23-hifi", | 140 | .codec_dai_name = "tlv320aic23-hifi", |
141 | .platform_name = "omap-pcm-audio", | 141 | .platform_name = "omap-pcm-audio", |
142 | .codec_name = "tlv320aic23-codec", | 142 | .codec_name = "tlv320aic23-codec.2-001a", |
143 | .init = am3517evm_aic23_init, | 143 | .init = am3517evm_aic23_init, |
144 | .ops = &am3517evm_ops, | 144 | .ops = &am3517evm_ops, |
145 | }; | 145 | }; |
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 25e54230cc6a..1790f83ee665 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c | |||
@@ -941,7 +941,7 @@ static void dapm_seq_run(struct snd_soc_dapm_context *dapm, | |||
941 | } | 941 | } |
942 | 942 | ||
943 | if (!list_empty(&pending)) | 943 | if (!list_empty(&pending)) |
944 | dapm_seq_run_coalesced(dapm, &pending); | 944 | dapm_seq_run_coalesced(cur_dapm, &pending); |
945 | } | 945 | } |
946 | 946 | ||
947 | static void dapm_widget_update(struct snd_soc_dapm_context *dapm) | 947 | static void dapm_widget_update(struct snd_soc_dapm_context *dapm) |