diff options
160 files changed, 5261 insertions, 1090 deletions
diff --git a/Documentation/ABI/obsolete/proc-pid-oom_adj b/Documentation/ABI/obsolete/proc-pid-oom_adj index cf63f264ce0f..9a3cb88ade47 100644 --- a/Documentation/ABI/obsolete/proc-pid-oom_adj +++ b/Documentation/ABI/obsolete/proc-pid-oom_adj | |||
@@ -14,7 +14,7 @@ Why: /proc/<pid>/oom_adj allows userspace to influence the oom killer's | |||
14 | 14 | ||
15 | A much more powerful interface, /proc/<pid>/oom_score_adj, was | 15 | A much more powerful interface, /proc/<pid>/oom_score_adj, was |
16 | introduced with the oom killer rewrite that allows users to increase or | 16 | introduced with the oom killer rewrite that allows users to increase or |
17 | decrease the badness() score linearly. This interface will replace | 17 | decrease the badness score linearly. This interface will replace |
18 | /proc/<pid>/oom_adj. | 18 | /proc/<pid>/oom_adj. |
19 | 19 | ||
20 | A warning will be emitted to the kernel log if an application uses this | 20 | A warning will be emitted to the kernel log if an application uses this |
diff --git a/Documentation/ABI/testing/sysfs-bus-i2c-devices-fsa9480 b/Documentation/ABI/testing/sysfs-bus-i2c-devices-fsa9480 new file mode 100644 index 000000000000..9de269bb0ae5 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-bus-i2c-devices-fsa9480 | |||
@@ -0,0 +1,21 @@ | |||
1 | What: /sys/bus/i2c/devices/.../device | ||
2 | Date: February 2011 | ||
3 | Contact: Minkyu Kang <mk7.kang@samsung.com> | ||
4 | Description: | ||
5 | show what device is attached | ||
6 | NONE - no device | ||
7 | USB - USB device is attached | ||
8 | UART - UART is attached | ||
9 | CHARGER - Charger is attaced | ||
10 | JIG - JIG is attached | ||
11 | |||
12 | What: /sys/bus/i2c/devices/.../switch | ||
13 | Date: February 2011 | ||
14 | Contact: Minkyu Kang <mk7.kang@samsung.com> | ||
15 | Description: | ||
16 | show or set the state of manual switch | ||
17 | VAUDIO - switch to VAUDIO path | ||
18 | UART - switch to UART path | ||
19 | AUDIO - switch to AUDIO path | ||
20 | DHOST - switch to DHOST path | ||
21 | AUTO - switch automatically by device | ||
diff --git a/Documentation/SubmitChecklist b/Documentation/SubmitChecklist index 7b13be41c085..dc0e33210d7e 100644 --- a/Documentation/SubmitChecklist +++ b/Documentation/SubmitChecklist | |||
@@ -53,8 +53,8 @@ kernel patches. | |||
53 | 53 | ||
54 | 12: Has been tested with CONFIG_PREEMPT, CONFIG_DEBUG_PREEMPT, | 54 | 12: Has been tested with CONFIG_PREEMPT, CONFIG_DEBUG_PREEMPT, |
55 | CONFIG_DEBUG_SLAB, CONFIG_DEBUG_PAGEALLOC, CONFIG_DEBUG_MUTEXES, | 55 | CONFIG_DEBUG_SLAB, CONFIG_DEBUG_PAGEALLOC, CONFIG_DEBUG_MUTEXES, |
56 | CONFIG_DEBUG_SPINLOCK, CONFIG_DEBUG_ATOMIC_SLEEP all simultaneously | 56 | CONFIG_DEBUG_SPINLOCK, CONFIG_DEBUG_ATOMIC_SLEEP, CONFIG_PROVE_RCU |
57 | enabled. | 57 | and CONFIG_DEBUG_OBJECTS_RCU_HEAD all simultaneously enabled. |
58 | 58 | ||
59 | 13: Has been build- and runtime tested with and without CONFIG_SMP and | 59 | 13: Has been build- and runtime tested with and without CONFIG_SMP and |
60 | CONFIG_PREEMPT. | 60 | CONFIG_PREEMPT. |
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index c8616f741746..89e46d3dc642 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt | |||
@@ -184,7 +184,7 @@ Why: /proc/<pid>/oom_adj allows userspace to influence the oom killer's | |||
184 | 184 | ||
185 | A much more powerful interface, /proc/<pid>/oom_score_adj, was | 185 | A much more powerful interface, /proc/<pid>/oom_score_adj, was |
186 | introduced with the oom killer rewrite that allows users to increase or | 186 | introduced with the oom killer rewrite that allows users to increase or |
187 | decrease the badness() score linearly. This interface will replace | 187 | decrease the badness score linearly. This interface will replace |
188 | /proc/<pid>/oom_adj. | 188 | /proc/<pid>/oom_adj. |
189 | 189 | ||
190 | A warning will be emitted to the kernel log if an application uses this | 190 | A warning will be emitted to the kernel log if an application uses this |
@@ -518,22 +518,6 @@ Files: net/netfilter/xt_connlimit.c | |||
518 | 518 | ||
519 | ---------------------------- | 519 | ---------------------------- |
520 | 520 | ||
521 | What: noswapaccount kernel command line parameter | ||
522 | When: 3.0 | ||
523 | Why: The original implementation of memsw feature enabled by | ||
524 | CONFIG_CGROUP_MEM_RES_CTLR_SWAP could be disabled by the noswapaccount | ||
525 | kernel parameter (introduced in 2.6.29-rc1). Later on, this decision | ||
526 | turned out to be not ideal because we cannot have the feature compiled | ||
527 | in and disabled by default and let only interested to enable it | ||
528 | (e.g. general distribution kernels might need it). Therefore we have | ||
529 | added swapaccount[=0|1] parameter (introduced in 2.6.37) which provides | ||
530 | the both possibilities. If we remove noswapaccount we will have | ||
531 | less command line parameters with the same functionality and we | ||
532 | can also cleanup the parameter handling a bit (). | ||
533 | Who: Michal Hocko <mhocko@suse.cz> | ||
534 | |||
535 | ---------------------------- | ||
536 | |||
537 | What: ipt_addrtype match include file | 521 | What: ipt_addrtype match include file |
538 | When: 2012 | 522 | When: 2012 |
539 | Why: superseded by xt_addrtype | 523 | Why: superseded by xt_addrtype |
diff --git a/MAINTAINERS b/MAINTAINERS index 91e5cc7db8c8..846f70ddc8db 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -3012,7 +3012,7 @@ F: kernel/hrtimer.c | |||
3012 | F: kernel/time/clockevents.c | 3012 | F: kernel/time/clockevents.c |
3013 | F: kernel/time/tick*.* | 3013 | F: kernel/time/tick*.* |
3014 | F: kernel/time/timer_*.c | 3014 | F: kernel/time/timer_*.c |
3015 | F: include/linux/clockevents.h | 3015 | F: include/linux/clockchips.h |
3016 | F: include/linux/hrtimer.h | 3016 | F: include/linux/hrtimer.h |
3017 | 3017 | ||
3018 | HIGH-SPEED SCC DRIVER FOR AX.25 | 3018 | HIGH-SPEED SCC DRIVER FOR AX.25 |
diff --git a/arch/alpha/kernel/process.c b/arch/alpha/kernel/process.c index 838eac128409..89bbe5b41145 100644 --- a/arch/alpha/kernel/process.c +++ b/arch/alpha/kernel/process.c | |||
@@ -200,7 +200,6 @@ show_regs(struct pt_regs *regs) | |||
200 | void | 200 | void |
201 | start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp) | 201 | start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp) |
202 | { | 202 | { |
203 | set_fs(USER_DS); | ||
204 | regs->pc = pc; | 203 | regs->pc = pc; |
205 | regs->ps = 8; | 204 | regs->ps = 8; |
206 | wrusp(sp); | 205 | wrusp(sp); |
diff --git a/arch/arm/mach-ux500/board-u5500.c b/arch/arm/mach-ux500/board-u5500.c index 44fd3b5c33ec..e58f0f562426 100644 --- a/arch/arm/mach-ux500/board-u5500.c +++ b/arch/arm/mach-ux500/board-u5500.c | |||
@@ -10,16 +10,97 @@ | |||
10 | #include <linux/amba/bus.h> | 10 | #include <linux/amba/bus.h> |
11 | #include <linux/gpio.h> | 11 | #include <linux/gpio.h> |
12 | #include <linux/irq.h> | 12 | #include <linux/irq.h> |
13 | #include <linux/i2c.h> | ||
13 | 14 | ||
14 | #include <asm/mach/arch.h> | 15 | #include <asm/mach/arch.h> |
15 | #include <asm/mach-types.h> | 16 | #include <asm/mach-types.h> |
16 | 17 | ||
18 | #include <plat/pincfg.h> | ||
19 | #include <plat/i2c.h> | ||
20 | |||
17 | #include <mach/hardware.h> | 21 | #include <mach/hardware.h> |
18 | #include <mach/devices.h> | 22 | #include <mach/devices.h> |
19 | #include <mach/setup.h> | 23 | #include <mach/setup.h> |
20 | 24 | ||
25 | #include "pins-db5500.h" | ||
21 | #include "devices-db5500.h" | 26 | #include "devices-db5500.h" |
27 | #include <linux/led-lm3530.h> | ||
28 | |||
29 | /* | ||
30 | * GPIO | ||
31 | */ | ||
32 | |||
33 | static pin_cfg_t u5500_pins[] = { | ||
34 | /* I2C */ | ||
35 | GPIO218_I2C2_SCL | PIN_INPUT_PULLUP, | ||
36 | GPIO219_I2C2_SDA | PIN_INPUT_PULLUP, | ||
37 | |||
38 | /* DISPLAY_ENABLE */ | ||
39 | GPIO226_GPIO | PIN_OUTPUT_LOW, | ||
40 | |||
41 | /* Backlight Enbale */ | ||
42 | GPIO224_GPIO | PIN_OUTPUT_HIGH, | ||
43 | }; | ||
44 | /* | ||
45 | * I2C | ||
46 | */ | ||
47 | |||
48 | #define U5500_I2C_CONTROLLER(id, _slsu, _tft, _rft, clk, _sm) \ | ||
49 | static struct nmk_i2c_controller u5500_i2c##id##_data = { \ | ||
50 | /* \ | ||
51 | * slave data setup time, which is \ | ||
52 | * 250 ns,100ns,10ns which is 14,6,2 \ | ||
53 | * respectively for a 48 Mhz \ | ||
54 | * i2c clock \ | ||
55 | */ \ | ||
56 | .slsu = _slsu, \ | ||
57 | /* Tx FIFO threshold */ \ | ||
58 | .tft = _tft, \ | ||
59 | /* Rx FIFO threshold */ \ | ||
60 | .rft = _rft, \ | ||
61 | /* std. mode operation */ \ | ||
62 | .clk_freq = clk, \ | ||
63 | .sm = _sm, \ | ||
64 | } | ||
65 | /* | ||
66 | * The board uses TODO <3> i2c controllers, initialize all of | ||
67 | * them with slave data setup time of 250 ns, | ||
68 | * Tx & Rx FIFO threshold values as 1 and standard | ||
69 | * mode of operation | ||
70 | */ | ||
71 | |||
72 | U5500_I2C_CONTROLLER(2, 0xe, 1, 1, 400000, I2C_FREQ_MODE_FAST); | ||
73 | |||
74 | static struct lm3530_platform_data u5500_als_platform_data = { | ||
75 | .mode = LM3530_BL_MODE_MANUAL, | ||
76 | .als_input_mode = LM3530_INPUT_ALS1, | ||
77 | .max_current = LM3530_FS_CURR_26mA, | ||
78 | .pwm_pol_hi = true, | ||
79 | .als_avrg_time = LM3530_ALS_AVRG_TIME_512ms, | ||
80 | .brt_ramp_law = 1, /* Linear */ | ||
81 | .brt_ramp_fall = LM3530_RAMP_TIME_8s, | ||
82 | .brt_ramp_rise = LM3530_RAMP_TIME_8s, | ||
83 | .als1_resistor_sel = LM3530_ALS_IMPD_13_53kOhm, | ||
84 | .als2_resistor_sel = LM3530_ALS_IMPD_Z, | ||
85 | .als_vmin = 730, /* mV */ | ||
86 | .als_vmax = 1020, /* mV */ | ||
87 | .brt_val = 0x7F, /* Max brightness */ | ||
88 | }; | ||
22 | 89 | ||
90 | |||
91 | static struct i2c_board_info __initdata u5500_i2c2_devices[] = { | ||
92 | { | ||
93 | /* Backlight */ | ||
94 | I2C_BOARD_INFO("lm3530-led", 0x36), | ||
95 | .platform_data = &u5500_als_platform_data, | ||
96 | }, | ||
97 | }; | ||
98 | |||
99 | static void __init u5500_i2c_init(void) | ||
100 | { | ||
101 | db5500_add_i2c2(&u5500_i2c2_data); | ||
102 | i2c_register_board_info(2, ARRAY_AND_SIZE(u5500_i2c2_devices)); | ||
103 | } | ||
23 | static void __init u5500_uart_init(void) | 104 | static void __init u5500_uart_init(void) |
24 | { | 105 | { |
25 | db5500_add_uart0(NULL); | 106 | db5500_add_uart0(NULL); |
@@ -30,7 +111,8 @@ static void __init u5500_uart_init(void) | |||
30 | static void __init u5500_init_machine(void) | 111 | static void __init u5500_init_machine(void) |
31 | { | 112 | { |
32 | u5500_init_devices(); | 113 | u5500_init_devices(); |
33 | 114 | nmk_config_pins(u5500_pins, ARRAY_SIZE(u5500_pins)); | |
115 | u5500_i2c_init(); | ||
34 | u5500_sdi_init(); | 116 | u5500_sdi_init(); |
35 | u5500_uart_init(); | 117 | u5500_uart_init(); |
36 | } | 118 | } |
diff --git a/arch/cris/arch-v32/mach-a3/pinmux.c b/arch/cris/arch-v32/mach-a3/pinmux.c index 18648ef2d874..591f77526746 100644 --- a/arch/cris/arch-v32/mach-a3/pinmux.c +++ b/arch/cris/arch-v32/mach-a3/pinmux.c | |||
@@ -85,6 +85,8 @@ crisv32_pinmux_alloc_fixed(enum fixed_function function) | |||
85 | int ret = -EINVAL; | 85 | int ret = -EINVAL; |
86 | char saved[sizeof pins]; | 86 | char saved[sizeof pins]; |
87 | unsigned long flags; | 87 | unsigned long flags; |
88 | reg_pinmux_rw_hwprot hwprot; | ||
89 | reg_clkgen_rw_clk_ctrl clk_ctrl; | ||
88 | 90 | ||
89 | spin_lock_irqsave(&pinmux_lock, flags); | 91 | spin_lock_irqsave(&pinmux_lock, flags); |
90 | 92 | ||
@@ -93,9 +95,8 @@ crisv32_pinmux_alloc_fixed(enum fixed_function function) | |||
93 | 95 | ||
94 | crisv32_pinmux_init(); /* must be done before we read rw_hwprot */ | 96 | crisv32_pinmux_init(); /* must be done before we read rw_hwprot */ |
95 | 97 | ||
96 | reg_pinmux_rw_hwprot hwprot = REG_RD(pinmux, regi_pinmux, rw_hwprot); | 98 | hwprot = REG_RD(pinmux, regi_pinmux, rw_hwprot); |
97 | reg_clkgen_rw_clk_ctrl clk_ctrl = REG_RD(clkgen, regi_clkgen, | 99 | clk_ctrl = REG_RD(clkgen, regi_clkgen, rw_clk_ctrl); |
98 | rw_clk_ctrl); | ||
99 | 100 | ||
100 | switch (function) { | 101 | switch (function) { |
101 | case pinmux_eth: | 102 | case pinmux_eth: |
@@ -262,6 +263,7 @@ crisv32_pinmux_dealloc_fixed(enum fixed_function function) | |||
262 | int ret = -EINVAL; | 263 | int ret = -EINVAL; |
263 | char saved[sizeof pins]; | 264 | char saved[sizeof pins]; |
264 | unsigned long flags; | 265 | unsigned long flags; |
266 | reg_pinmux_rw_hwprot hwprot; | ||
265 | 267 | ||
266 | spin_lock_irqsave(&pinmux_lock, flags); | 268 | spin_lock_irqsave(&pinmux_lock, flags); |
267 | 269 | ||
@@ -270,7 +272,7 @@ crisv32_pinmux_dealloc_fixed(enum fixed_function function) | |||
270 | 272 | ||
271 | crisv32_pinmux_init(); /* must be done before we read rw_hwprot */ | 273 | crisv32_pinmux_init(); /* must be done before we read rw_hwprot */ |
272 | 274 | ||
273 | reg_pinmux_rw_hwprot hwprot = REG_RD(pinmux, regi_pinmux, rw_hwprot); | 275 | hwprot = REG_RD(pinmux, regi_pinmux, rw_hwprot); |
274 | 276 | ||
275 | switch (function) { | 277 | switch (function) { |
276 | case pinmux_eth: | 278 | case pinmux_eth: |
diff --git a/arch/cris/include/arch-v10/arch/processor.h b/arch/cris/include/arch-v10/arch/processor.h index cc692c7a0660..93feb2a487d8 100644 --- a/arch/cris/include/arch-v10/arch/processor.h +++ b/arch/cris/include/arch-v10/arch/processor.h | |||
@@ -53,7 +53,6 @@ struct thread_struct { | |||
53 | */ | 53 | */ |
54 | 54 | ||
55 | #define start_thread(regs, ip, usp) do { \ | 55 | #define start_thread(regs, ip, usp) do { \ |
56 | set_fs(USER_DS); \ | ||
57 | regs->irp = ip; \ | 56 | regs->irp = ip; \ |
58 | regs->dccr |= 1 << U_DCCR_BITNR; \ | 57 | regs->dccr |= 1 << U_DCCR_BITNR; \ |
59 | wrusp(usp); \ | 58 | wrusp(usp); \ |
diff --git a/arch/cris/include/arch-v32/arch/processor.h b/arch/cris/include/arch-v32/arch/processor.h index f80b47790ca6..9603c907fbc4 100644 --- a/arch/cris/include/arch-v32/arch/processor.h +++ b/arch/cris/include/arch-v32/arch/processor.h | |||
@@ -47,7 +47,6 @@ struct thread_struct { | |||
47 | */ | 47 | */ |
48 | #define start_thread(regs, ip, usp) \ | 48 | #define start_thread(regs, ip, usp) \ |
49 | do { \ | 49 | do { \ |
50 | set_fs(USER_DS); \ | ||
51 | regs->erp = ip; \ | 50 | regs->erp = ip; \ |
52 | regs->ccs |= 1 << (U_CCS_BITNR + CCS_SHIFT); \ | 51 | regs->ccs |= 1 << (U_CCS_BITNR + CCS_SHIFT); \ |
53 | wrusp(usp); \ | 52 | wrusp(usp); \ |
diff --git a/arch/h8300/include/asm/processor.h b/arch/h8300/include/asm/processor.h index 69e8a34eb6d5..e834b6018897 100644 --- a/arch/h8300/include/asm/processor.h +++ b/arch/h8300/include/asm/processor.h | |||
@@ -81,7 +81,6 @@ struct thread_struct { | |||
81 | #if defined(__H8300H__) | 81 | #if defined(__H8300H__) |
82 | #define start_thread(_regs, _pc, _usp) \ | 82 | #define start_thread(_regs, _pc, _usp) \ |
83 | do { \ | 83 | do { \ |
84 | set_fs(USER_DS); /* reads from user space */ \ | ||
85 | (_regs)->pc = (_pc); \ | 84 | (_regs)->pc = (_pc); \ |
86 | (_regs)->ccr = 0x00; /* clear all flags */ \ | 85 | (_regs)->ccr = 0x00; /* clear all flags */ \ |
87 | (_regs)->er5 = current->mm->start_data; /* GOT base */ \ | 86 | (_regs)->er5 = current->mm->start_data; /* GOT base */ \ |
@@ -91,7 +90,6 @@ do { \ | |||
91 | #if defined(__H8300S__) | 90 | #if defined(__H8300S__) |
92 | #define start_thread(_regs, _pc, _usp) \ | 91 | #define start_thread(_regs, _pc, _usp) \ |
93 | do { \ | 92 | do { \ |
94 | set_fs(USER_DS); /* reads from user space */ \ | ||
95 | (_regs)->pc = (_pc); \ | 93 | (_regs)->pc = (_pc); \ |
96 | (_regs)->ccr = 0x00; /* clear kernel flag */ \ | 94 | (_regs)->ccr = 0x00; /* clear kernel flag */ \ |
97 | (_regs)->exr = 0x78; /* enable all interrupts */ \ | 95 | (_regs)->exr = 0x78; /* enable all interrupts */ \ |
diff --git a/arch/m32r/include/asm/processor.h b/arch/m32r/include/asm/processor.h index 8397c249989b..e1f46d757460 100644 --- a/arch/m32r/include/asm/processor.h +++ b/arch/m32r/include/asm/processor.h | |||
@@ -106,7 +106,6 @@ struct thread_struct { | |||
106 | 106 | ||
107 | #define start_thread(regs, new_pc, new_spu) \ | 107 | #define start_thread(regs, new_pc, new_spu) \ |
108 | do { \ | 108 | do { \ |
109 | set_fs(USER_DS); \ | ||
110 | regs->psw = (regs->psw | USERPS_BPSW) & 0x0000FFFFUL; \ | 109 | regs->psw = (regs->psw | USERPS_BPSW) & 0x0000FFFFUL; \ |
111 | regs->bpc = new_pc; \ | 110 | regs->bpc = new_pc; \ |
112 | regs->spu = new_spu; \ | 111 | regs->spu = new_spu; \ |
diff --git a/arch/m68k/include/asm/processor.h b/arch/m68k/include/asm/processor.h index f111b02b704f..d8ef53ac03f9 100644 --- a/arch/m68k/include/asm/processor.h +++ b/arch/m68k/include/asm/processor.h | |||
@@ -105,9 +105,6 @@ struct thread_struct { | |||
105 | static inline void start_thread(struct pt_regs * regs, unsigned long pc, | 105 | static inline void start_thread(struct pt_regs * regs, unsigned long pc, |
106 | unsigned long usp) | 106 | unsigned long usp) |
107 | { | 107 | { |
108 | /* reads from user space */ | ||
109 | set_fs(USER_DS); | ||
110 | |||
111 | regs->pc = pc; | 108 | regs->pc = pc; |
112 | regs->sr &= ~0x2000; | 109 | regs->sr &= ~0x2000; |
113 | wrusp(usp); | 110 | wrusp(usp); |
@@ -129,7 +126,6 @@ extern int handle_kernel_fault(struct pt_regs *regs); | |||
129 | 126 | ||
130 | #define start_thread(_regs, _pc, _usp) \ | 127 | #define start_thread(_regs, _pc, _usp) \ |
131 | do { \ | 128 | do { \ |
132 | set_fs(USER_DS); /* reads from user space */ \ | ||
133 | (_regs)->pc = (_pc); \ | 129 | (_regs)->pc = (_pc); \ |
134 | ((struct switch_stack *)(_regs))[-1].a6 = 0; \ | 130 | ((struct switch_stack *)(_regs))[-1].a6 = 0; \ |
135 | reformat(_regs); \ | 131 | reformat(_regs); \ |
diff --git a/arch/m68k/kernel/process_mm.c b/arch/m68k/kernel/process_mm.c index c2a1fc23dd75..1bc223aa07ec 100644 --- a/arch/m68k/kernel/process_mm.c +++ b/arch/m68k/kernel/process_mm.c | |||
@@ -185,7 +185,7 @@ EXPORT_SYMBOL(kernel_thread); | |||
185 | void flush_thread(void) | 185 | void flush_thread(void) |
186 | { | 186 | { |
187 | unsigned long zero = 0; | 187 | unsigned long zero = 0; |
188 | set_fs(USER_DS); | 188 | |
189 | current->thread.fs = __USER_DS; | 189 | current->thread.fs = __USER_DS; |
190 | if (!FPU_IS_EMU) | 190 | if (!FPU_IS_EMU) |
191 | asm volatile (".chip 68k/68881\n\t" | 191 | asm volatile (".chip 68k/68881\n\t" |
diff --git a/arch/m68k/kernel/process_no.c b/arch/m68k/kernel/process_no.c index 9b86ad11c68e..69c1803fcf1b 100644 --- a/arch/m68k/kernel/process_no.c +++ b/arch/m68k/kernel/process_no.c | |||
@@ -158,7 +158,7 @@ void flush_thread(void) | |||
158 | #ifdef CONFIG_FPU | 158 | #ifdef CONFIG_FPU |
159 | unsigned long zero = 0; | 159 | unsigned long zero = 0; |
160 | #endif | 160 | #endif |
161 | set_fs(USER_DS); | 161 | |
162 | current->thread.fs = __USER_DS; | 162 | current->thread.fs = __USER_DS; |
163 | #ifdef CONFIG_FPU | 163 | #ifdef CONFIG_FPU |
164 | if (!FPU_IS_EMU) | 164 | if (!FPU_IS_EMU) |
diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c index 271ff6318eda..0e0ea941156f 100644 --- a/arch/powerpc/kernel/rtas.c +++ b/arch/powerpc/kernel/rtas.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/cpumask.h> | 24 | #include <linux/cpumask.h> |
25 | #include <linux/memblock.h> | 25 | #include <linux/memblock.h> |
26 | #include <linux/slab.h> | 26 | #include <linux/slab.h> |
27 | #include <linux/reboot.h> | ||
27 | 28 | ||
28 | #include <asm/prom.h> | 29 | #include <asm/prom.h> |
29 | #include <asm/rtas.h> | 30 | #include <asm/rtas.h> |
diff --git a/arch/powerpc/kernel/rtas_flash.c b/arch/powerpc/kernel/rtas_flash.c index bf5f5ce3a7bd..e037c7494fd8 100644 --- a/arch/powerpc/kernel/rtas_flash.c +++ b/arch/powerpc/kernel/rtas_flash.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/init.h> | 17 | #include <linux/init.h> |
18 | #include <linux/slab.h> | 18 | #include <linux/slab.h> |
19 | #include <linux/proc_fs.h> | 19 | #include <linux/proc_fs.h> |
20 | #include <linux/reboot.h> | ||
20 | #include <asm/delay.h> | 21 | #include <asm/delay.h> |
21 | #include <asm/uaccess.h> | 22 | #include <asm/uaccess.h> |
22 | #include <asm/rtas.h> | 23 | #include <asm/rtas.h> |
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig index 253986bd6bb6..1074dddcb104 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig | |||
@@ -41,6 +41,7 @@ config SPARC64 | |||
41 | select HAVE_FUNCTION_TRACE_MCOUNT_TEST | 41 | select HAVE_FUNCTION_TRACE_MCOUNT_TEST |
42 | select HAVE_KRETPROBES | 42 | select HAVE_KRETPROBES |
43 | select HAVE_KPROBES | 43 | select HAVE_KPROBES |
44 | select HAVE_RCU_TABLE_FREE if SMP | ||
44 | select HAVE_MEMBLOCK | 45 | select HAVE_MEMBLOCK |
45 | select HAVE_SYSCALL_WRAPPERS | 46 | select HAVE_SYSCALL_WRAPPERS |
46 | select HAVE_DYNAMIC_FTRACE | 47 | select HAVE_DYNAMIC_FTRACE |
@@ -81,10 +82,6 @@ config IOMMU_HELPER | |||
81 | bool | 82 | bool |
82 | default y if SPARC64 | 83 | default y if SPARC64 |
83 | 84 | ||
84 | config QUICKLIST | ||
85 | bool | ||
86 | default y if SPARC64 | ||
87 | |||
88 | config STACKTRACE_SUPPORT | 85 | config STACKTRACE_SUPPORT |
89 | bool | 86 | bool |
90 | default y if SPARC64 | 87 | default y if SPARC64 |
diff --git a/arch/sparc/include/asm/pgalloc_64.h b/arch/sparc/include/asm/pgalloc_64.h index 4e5e0878144f..40b2d7a7023d 100644 --- a/arch/sparc/include/asm/pgalloc_64.h +++ b/arch/sparc/include/asm/pgalloc_64.h | |||
@@ -5,7 +5,6 @@ | |||
5 | #include <linux/sched.h> | 5 | #include <linux/sched.h> |
6 | #include <linux/mm.h> | 6 | #include <linux/mm.h> |
7 | #include <linux/slab.h> | 7 | #include <linux/slab.h> |
8 | #include <linux/quicklist.h> | ||
9 | 8 | ||
10 | #include <asm/spitfire.h> | 9 | #include <asm/spitfire.h> |
11 | #include <asm/cpudata.h> | 10 | #include <asm/cpudata.h> |
@@ -14,71 +13,114 @@ | |||
14 | 13 | ||
15 | /* Page table allocation/freeing. */ | 14 | /* Page table allocation/freeing. */ |
16 | 15 | ||
16 | extern struct kmem_cache *pgtable_cache; | ||
17 | |||
17 | static inline pgd_t *pgd_alloc(struct mm_struct *mm) | 18 | static inline pgd_t *pgd_alloc(struct mm_struct *mm) |
18 | { | 19 | { |
19 | return quicklist_alloc(0, GFP_KERNEL, NULL); | 20 | return kmem_cache_alloc(pgtable_cache, GFP_KERNEL); |
20 | } | 21 | } |
21 | 22 | ||
22 | static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd) | 23 | static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd) |
23 | { | 24 | { |
24 | quicklist_free(0, NULL, pgd); | 25 | kmem_cache_free(pgtable_cache, pgd); |
25 | } | 26 | } |
26 | 27 | ||
27 | #define pud_populate(MM, PUD, PMD) pud_set(PUD, PMD) | 28 | #define pud_populate(MM, PUD, PMD) pud_set(PUD, PMD) |
28 | 29 | ||
29 | static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr) | 30 | static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr) |
30 | { | 31 | { |
31 | return quicklist_alloc(0, GFP_KERNEL, NULL); | 32 | return kmem_cache_alloc(pgtable_cache, |
33 | GFP_KERNEL|__GFP_REPEAT); | ||
32 | } | 34 | } |
33 | 35 | ||
34 | static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd) | 36 | static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd) |
35 | { | 37 | { |
36 | quicklist_free(0, NULL, pmd); | 38 | kmem_cache_free(pgtable_cache, pmd); |
37 | } | 39 | } |
38 | 40 | ||
39 | static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, | 41 | static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, |
40 | unsigned long address) | 42 | unsigned long address) |
41 | { | 43 | { |
42 | return quicklist_alloc(0, GFP_KERNEL, NULL); | 44 | return (pte_t *)__get_free_page(GFP_KERNEL | __GFP_REPEAT | __GFP_ZERO); |
43 | } | 45 | } |
44 | 46 | ||
45 | static inline pgtable_t pte_alloc_one(struct mm_struct *mm, | 47 | static inline pgtable_t pte_alloc_one(struct mm_struct *mm, |
46 | unsigned long address) | 48 | unsigned long address) |
47 | { | 49 | { |
48 | struct page *page; | 50 | struct page *page; |
49 | void *pg; | 51 | pte_t *pte; |
50 | 52 | ||
51 | pg = quicklist_alloc(0, GFP_KERNEL, NULL); | 53 | pte = pte_alloc_one_kernel(mm, address); |
52 | if (!pg) | 54 | if (!pte) |
53 | return NULL; | 55 | return NULL; |
54 | page = virt_to_page(pg); | 56 | page = virt_to_page(pte); |
55 | pgtable_page_ctor(page); | 57 | pgtable_page_ctor(page); |
56 | return page; | 58 | return page; |
57 | } | 59 | } |
58 | 60 | ||
59 | static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte) | 61 | static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte) |
60 | { | 62 | { |
61 | quicklist_free(0, NULL, pte); | 63 | free_page((unsigned long)pte); |
62 | } | 64 | } |
63 | 65 | ||
64 | static inline void pte_free(struct mm_struct *mm, pgtable_t ptepage) | 66 | static inline void pte_free(struct mm_struct *mm, pgtable_t ptepage) |
65 | { | 67 | { |
66 | pgtable_page_dtor(ptepage); | 68 | pgtable_page_dtor(ptepage); |
67 | quicklist_free_page(0, NULL, ptepage); | 69 | __free_page(ptepage); |
68 | } | 70 | } |
69 | 71 | ||
70 | |||
71 | #define pmd_populate_kernel(MM, PMD, PTE) pmd_set(PMD, PTE) | 72 | #define pmd_populate_kernel(MM, PMD, PTE) pmd_set(PMD, PTE) |
72 | #define pmd_populate(MM,PMD,PTE_PAGE) \ | 73 | #define pmd_populate(MM,PMD,PTE_PAGE) \ |
73 | pmd_populate_kernel(MM,PMD,page_address(PTE_PAGE)) | 74 | pmd_populate_kernel(MM,PMD,page_address(PTE_PAGE)) |
74 | #define pmd_pgtable(pmd) pmd_page(pmd) | 75 | #define pmd_pgtable(pmd) pmd_page(pmd) |
75 | 76 | ||
76 | static inline void check_pgt_cache(void) | 77 | #define check_pgt_cache() do { } while (0) |
78 | |||
79 | static inline void pgtable_free(void *table, bool is_page) | ||
80 | { | ||
81 | if (is_page) | ||
82 | free_page((unsigned long)table); | ||
83 | else | ||
84 | kmem_cache_free(pgtable_cache, table); | ||
85 | } | ||
86 | |||
87 | #ifdef CONFIG_SMP | ||
88 | |||
89 | struct mmu_gather; | ||
90 | extern void tlb_remove_table(struct mmu_gather *, void *); | ||
91 | |||
92 | static inline void pgtable_free_tlb(struct mmu_gather *tlb, void *table, bool is_page) | ||
93 | { | ||
94 | unsigned long pgf = (unsigned long)table; | ||
95 | if (is_page) | ||
96 | pgf |= 0x1UL; | ||
97 | tlb_remove_table(tlb, (void *)pgf); | ||
98 | } | ||
99 | |||
100 | static inline void __tlb_remove_table(void *_table) | ||
101 | { | ||
102 | void *table = (void *)((unsigned long)_table & ~0x1UL); | ||
103 | bool is_page = false; | ||
104 | |||
105 | if ((unsigned long)_table & 0x1UL) | ||
106 | is_page = true; | ||
107 | pgtable_free(table, is_page); | ||
108 | } | ||
109 | #else /* CONFIG_SMP */ | ||
110 | static inline void pgtable_free_tlb(struct mmu_gather *tlb, void *table, bool is_page) | ||
77 | { | 111 | { |
78 | quicklist_trim(0, NULL, 25, 16); | 112 | pgtable_free(table, is_page); |
113 | } | ||
114 | #endif /* !CONFIG_SMP */ | ||
115 | |||
116 | static inline void __pte_free_tlb(struct mmu_gather *tlb, struct page *ptepage, | ||
117 | unsigned long address) | ||
118 | { | ||
119 | pgtable_page_dtor(ptepage); | ||
120 | pgtable_free_tlb(tlb, page_address(ptepage), true); | ||
79 | } | 121 | } |
80 | 122 | ||
81 | #define __pte_free_tlb(tlb, pte, addr) pte_free((tlb)->mm, pte) | 123 | #define __pmd_free_tlb(tlb, pmd, addr) \ |
82 | #define __pmd_free_tlb(tlb, pmd, addr) pmd_free((tlb)->mm, pmd) | 124 | pgtable_free_tlb(tlb, pmd, false) |
83 | 125 | ||
84 | #endif /* _SPARC64_PGALLOC_H */ | 126 | #endif /* _SPARC64_PGALLOC_H */ |
diff --git a/arch/sparc/include/asm/pgtable_64.h b/arch/sparc/include/asm/pgtable_64.h index 1e03c5a6b4f7..adf89329af59 100644 --- a/arch/sparc/include/asm/pgtable_64.h +++ b/arch/sparc/include/asm/pgtable_64.h | |||
@@ -95,6 +95,10 @@ | |||
95 | /* PTE bits which are the same in SUN4U and SUN4V format. */ | 95 | /* PTE bits which are the same in SUN4U and SUN4V format. */ |
96 | #define _PAGE_VALID _AC(0x8000000000000000,UL) /* Valid TTE */ | 96 | #define _PAGE_VALID _AC(0x8000000000000000,UL) /* Valid TTE */ |
97 | #define _PAGE_R _AC(0x8000000000000000,UL) /* Keep ref bit uptodate*/ | 97 | #define _PAGE_R _AC(0x8000000000000000,UL) /* Keep ref bit uptodate*/ |
98 | #define _PAGE_SPECIAL _AC(0x0200000000000000,UL) /* Special page */ | ||
99 | |||
100 | /* Advertise support for _PAGE_SPECIAL */ | ||
101 | #define __HAVE_ARCH_PTE_SPECIAL | ||
98 | 102 | ||
99 | /* SUN4U pte bits... */ | 103 | /* SUN4U pte bits... */ |
100 | #define _PAGE_SZ4MB_4U _AC(0x6000000000000000,UL) /* 4MB Page */ | 104 | #define _PAGE_SZ4MB_4U _AC(0x6000000000000000,UL) /* 4MB Page */ |
@@ -104,6 +108,7 @@ | |||
104 | #define _PAGE_NFO_4U _AC(0x1000000000000000,UL) /* No Fault Only */ | 108 | #define _PAGE_NFO_4U _AC(0x1000000000000000,UL) /* No Fault Only */ |
105 | #define _PAGE_IE_4U _AC(0x0800000000000000,UL) /* Invert Endianness */ | 109 | #define _PAGE_IE_4U _AC(0x0800000000000000,UL) /* Invert Endianness */ |
106 | #define _PAGE_SOFT2_4U _AC(0x07FC000000000000,UL) /* Software bits, set 2 */ | 110 | #define _PAGE_SOFT2_4U _AC(0x07FC000000000000,UL) /* Software bits, set 2 */ |
111 | #define _PAGE_SPECIAL_4U _AC(0x0200000000000000,UL) /* Special page */ | ||
107 | #define _PAGE_RES1_4U _AC(0x0002000000000000,UL) /* Reserved */ | 112 | #define _PAGE_RES1_4U _AC(0x0002000000000000,UL) /* Reserved */ |
108 | #define _PAGE_SZ32MB_4U _AC(0x0001000000000000,UL) /* (Panther) 32MB page */ | 113 | #define _PAGE_SZ32MB_4U _AC(0x0001000000000000,UL) /* (Panther) 32MB page */ |
109 | #define _PAGE_SZ256MB_4U _AC(0x2001000000000000,UL) /* (Panther) 256MB page */ | 114 | #define _PAGE_SZ256MB_4U _AC(0x2001000000000000,UL) /* (Panther) 256MB page */ |
@@ -133,6 +138,7 @@ | |||
133 | #define _PAGE_ACCESSED_4V _AC(0x1000000000000000,UL) /* Accessed (ref'd) */ | 138 | #define _PAGE_ACCESSED_4V _AC(0x1000000000000000,UL) /* Accessed (ref'd) */ |
134 | #define _PAGE_READ_4V _AC(0x0800000000000000,UL) /* Readable SW Bit */ | 139 | #define _PAGE_READ_4V _AC(0x0800000000000000,UL) /* Readable SW Bit */ |
135 | #define _PAGE_WRITE_4V _AC(0x0400000000000000,UL) /* Writable SW Bit */ | 140 | #define _PAGE_WRITE_4V _AC(0x0400000000000000,UL) /* Writable SW Bit */ |
141 | #define _PAGE_SPECIAL_4V _AC(0x0200000000000000,UL) /* Special page */ | ||
136 | #define _PAGE_PADDR_4V _AC(0x00FFFFFFFFFFE000,UL) /* paddr[55:13] */ | 142 | #define _PAGE_PADDR_4V _AC(0x00FFFFFFFFFFE000,UL) /* paddr[55:13] */ |
137 | #define _PAGE_IE_4V _AC(0x0000000000001000,UL) /* Invert Endianness */ | 143 | #define _PAGE_IE_4V _AC(0x0000000000001000,UL) /* Invert Endianness */ |
138 | #define _PAGE_E_4V _AC(0x0000000000000800,UL) /* side-Effect */ | 144 | #define _PAGE_E_4V _AC(0x0000000000000800,UL) /* side-Effect */ |
@@ -302,10 +308,10 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t prot) | |||
302 | : "=r" (mask), "=r" (tmp) | 308 | : "=r" (mask), "=r" (tmp) |
303 | : "i" (_PAGE_PADDR_4U | _PAGE_MODIFIED_4U | _PAGE_ACCESSED_4U | | 309 | : "i" (_PAGE_PADDR_4U | _PAGE_MODIFIED_4U | _PAGE_ACCESSED_4U | |
304 | _PAGE_CP_4U | _PAGE_CV_4U | _PAGE_E_4U | _PAGE_PRESENT_4U | | 310 | _PAGE_CP_4U | _PAGE_CV_4U | _PAGE_E_4U | _PAGE_PRESENT_4U | |
305 | _PAGE_SZBITS_4U), | 311 | _PAGE_SZBITS_4U | _PAGE_SPECIAL), |
306 | "i" (_PAGE_PADDR_4V | _PAGE_MODIFIED_4V | _PAGE_ACCESSED_4V | | 312 | "i" (_PAGE_PADDR_4V | _PAGE_MODIFIED_4V | _PAGE_ACCESSED_4V | |
307 | _PAGE_CP_4V | _PAGE_CV_4V | _PAGE_E_4V | _PAGE_PRESENT_4V | | 313 | _PAGE_CP_4V | _PAGE_CV_4V | _PAGE_E_4V | _PAGE_PRESENT_4V | |
308 | _PAGE_SZBITS_4V)); | 314 | _PAGE_SZBITS_4V | _PAGE_SPECIAL)); |
309 | 315 | ||
310 | return __pte((pte_val(pte) & mask) | (pgprot_val(prot) & ~mask)); | 316 | return __pte((pte_val(pte) & mask) | (pgprot_val(prot) & ~mask)); |
311 | } | 317 | } |
@@ -502,6 +508,7 @@ static inline pte_t pte_mkyoung(pte_t pte) | |||
502 | 508 | ||
503 | static inline pte_t pte_mkspecial(pte_t pte) | 509 | static inline pte_t pte_mkspecial(pte_t pte) |
504 | { | 510 | { |
511 | pte_val(pte) |= _PAGE_SPECIAL; | ||
505 | return pte; | 512 | return pte; |
506 | } | 513 | } |
507 | 514 | ||
@@ -607,9 +614,9 @@ static inline unsigned long pte_present(pte_t pte) | |||
607 | return val; | 614 | return val; |
608 | } | 615 | } |
609 | 616 | ||
610 | static inline int pte_special(pte_t pte) | 617 | static inline unsigned long pte_special(pte_t pte) |
611 | { | 618 | { |
612 | return 0; | 619 | return pte_val(pte) & _PAGE_SPECIAL; |
613 | } | 620 | } |
614 | 621 | ||
615 | #define pmd_set(pmdp, ptep) \ | 622 | #define pmd_set(pmdp, ptep) \ |
diff --git a/arch/sparc/mm/Makefile b/arch/sparc/mm/Makefile index 79836a7dd00c..e3cda21b5ee9 100644 --- a/arch/sparc/mm/Makefile +++ b/arch/sparc/mm/Makefile | |||
@@ -4,7 +4,7 @@ | |||
4 | asflags-y := -ansi | 4 | asflags-y := -ansi |
5 | ccflags-y := -Werror | 5 | ccflags-y := -Werror |
6 | 6 | ||
7 | obj-$(CONFIG_SPARC64) += ultra.o tlb.o tsb.o | 7 | obj-$(CONFIG_SPARC64) += ultra.o tlb.o tsb.o gup.o |
8 | obj-y += fault_$(BITS).o | 8 | obj-y += fault_$(BITS).o |
9 | obj-y += init_$(BITS).o | 9 | obj-y += init_$(BITS).o |
10 | obj-$(CONFIG_SPARC32) += loadmmu.o | 10 | obj-$(CONFIG_SPARC32) += loadmmu.o |
diff --git a/arch/sparc/mm/gup.c b/arch/sparc/mm/gup.c new file mode 100644 index 000000000000..a986b5d05712 --- /dev/null +++ b/arch/sparc/mm/gup.c | |||
@@ -0,0 +1,181 @@ | |||
1 | /* | ||
2 | * Lockless get_user_pages_fast for sparc, cribbed from powerpc | ||
3 | * | ||
4 | * Copyright (C) 2008 Nick Piggin | ||
5 | * Copyright (C) 2008 Novell Inc. | ||
6 | */ | ||
7 | |||
8 | #include <linux/sched.h> | ||
9 | #include <linux/mm.h> | ||
10 | #include <linux/vmstat.h> | ||
11 | #include <linux/pagemap.h> | ||
12 | #include <linux/rwsem.h> | ||
13 | #include <asm/pgtable.h> | ||
14 | |||
15 | /* | ||
16 | * The performance critical leaf functions are made noinline otherwise gcc | ||
17 | * inlines everything into a single function which results in too much | ||
18 | * register pressure. | ||
19 | */ | ||
20 | static noinline int gup_pte_range(pmd_t pmd, unsigned long addr, | ||
21 | unsigned long end, int write, struct page **pages, int *nr) | ||
22 | { | ||
23 | unsigned long mask, result; | ||
24 | pte_t *ptep; | ||
25 | |||
26 | if (tlb_type == hypervisor) { | ||
27 | result = _PAGE_PRESENT_4V|_PAGE_P_4V; | ||
28 | if (write) | ||
29 | result |= _PAGE_WRITE_4V; | ||
30 | } else { | ||
31 | result = _PAGE_PRESENT_4U|_PAGE_P_4U; | ||
32 | if (write) | ||
33 | result |= _PAGE_WRITE_4U; | ||
34 | } | ||
35 | mask = result | _PAGE_SPECIAL; | ||
36 | |||
37 | ptep = pte_offset_kernel(&pmd, addr); | ||
38 | do { | ||
39 | struct page *page, *head; | ||
40 | pte_t pte = *ptep; | ||
41 | |||
42 | if ((pte_val(pte) & mask) != result) | ||
43 | return 0; | ||
44 | VM_BUG_ON(!pfn_valid(pte_pfn(pte))); | ||
45 | |||
46 | /* The hugepage case is simplified on sparc64 because | ||
47 | * we encode the sub-page pfn offsets into the | ||
48 | * hugepage PTEs. We could optimize this in the future | ||
49 | * use page_cache_add_speculative() for the hugepage case. | ||
50 | */ | ||
51 | page = pte_page(pte); | ||
52 | head = compound_head(page); | ||
53 | if (!page_cache_get_speculative(head)) | ||
54 | return 0; | ||
55 | if (unlikely(pte_val(pte) != pte_val(*ptep))) { | ||
56 | put_page(head); | ||
57 | return 0; | ||
58 | } | ||
59 | |||
60 | pages[*nr] = page; | ||
61 | (*nr)++; | ||
62 | } while (ptep++, addr += PAGE_SIZE, addr != end); | ||
63 | |||
64 | return 1; | ||
65 | } | ||
66 | |||
67 | static int gup_pmd_range(pud_t pud, unsigned long addr, unsigned long end, | ||
68 | int write, struct page **pages, int *nr) | ||
69 | { | ||
70 | unsigned long next; | ||
71 | pmd_t *pmdp; | ||
72 | |||
73 | pmdp = pmd_offset(&pud, addr); | ||
74 | do { | ||
75 | pmd_t pmd = *pmdp; | ||
76 | |||
77 | next = pmd_addr_end(addr, end); | ||
78 | if (pmd_none(pmd)) | ||
79 | return 0; | ||
80 | if (!gup_pte_range(pmd, addr, next, write, pages, nr)) | ||
81 | return 0; | ||
82 | } while (pmdp++, addr = next, addr != end); | ||
83 | |||
84 | return 1; | ||
85 | } | ||
86 | |||
87 | static int gup_pud_range(pgd_t pgd, unsigned long addr, unsigned long end, | ||
88 | int write, struct page **pages, int *nr) | ||
89 | { | ||
90 | unsigned long next; | ||
91 | pud_t *pudp; | ||
92 | |||
93 | pudp = pud_offset(&pgd, addr); | ||
94 | do { | ||
95 | pud_t pud = *pudp; | ||
96 | |||
97 | next = pud_addr_end(addr, end); | ||
98 | if (pud_none(pud)) | ||
99 | return 0; | ||
100 | if (!gup_pmd_range(pud, addr, next, write, pages, nr)) | ||
101 | return 0; | ||
102 | } while (pudp++, addr = next, addr != end); | ||
103 | |||
104 | return 1; | ||
105 | } | ||
106 | |||
107 | int get_user_pages_fast(unsigned long start, int nr_pages, int write, | ||
108 | struct page **pages) | ||
109 | { | ||
110 | struct mm_struct *mm = current->mm; | ||
111 | unsigned long addr, len, end; | ||
112 | unsigned long next; | ||
113 | pgd_t *pgdp; | ||
114 | int nr = 0; | ||
115 | |||
116 | start &= PAGE_MASK; | ||
117 | addr = start; | ||
118 | len = (unsigned long) nr_pages << PAGE_SHIFT; | ||
119 | end = start + len; | ||
120 | |||
121 | /* | ||
122 | * XXX: batch / limit 'nr', to avoid large irq off latency | ||
123 | * needs some instrumenting to determine the common sizes used by | ||
124 | * important workloads (eg. DB2), and whether limiting the batch size | ||
125 | * will decrease performance. | ||
126 | * | ||
127 | * It seems like we're in the clear for the moment. Direct-IO is | ||
128 | * the main guy that batches up lots of get_user_pages, and even | ||
129 | * they are limited to 64-at-a-time which is not so many. | ||
130 | */ | ||
131 | /* | ||
132 | * This doesn't prevent pagetable teardown, but does prevent | ||
133 | * the pagetables from being freed on sparc. | ||
134 | * | ||
135 | * So long as we atomically load page table pointers versus teardown, | ||
136 | * we can follow the address down to the the page and take a ref on it. | ||
137 | */ | ||
138 | local_irq_disable(); | ||
139 | |||
140 | pgdp = pgd_offset(mm, addr); | ||
141 | do { | ||
142 | pgd_t pgd = *pgdp; | ||
143 | |||
144 | next = pgd_addr_end(addr, end); | ||
145 | if (pgd_none(pgd)) | ||
146 | goto slow; | ||
147 | if (!gup_pud_range(pgd, addr, next, write, pages, &nr)) | ||
148 | goto slow; | ||
149 | } while (pgdp++, addr = next, addr != end); | ||
150 | |||
151 | local_irq_enable(); | ||
152 | |||
153 | VM_BUG_ON(nr != (end - start) >> PAGE_SHIFT); | ||
154 | return nr; | ||
155 | |||
156 | { | ||
157 | int ret; | ||
158 | |||
159 | slow: | ||
160 | local_irq_enable(); | ||
161 | |||
162 | /* Try to get the remaining pages with get_user_pages */ | ||
163 | start += nr << PAGE_SHIFT; | ||
164 | pages += nr; | ||
165 | |||
166 | down_read(&mm->mmap_sem); | ||
167 | ret = get_user_pages(current, mm, start, | ||
168 | (end - start) >> PAGE_SHIFT, write, 0, pages, NULL); | ||
169 | up_read(&mm->mmap_sem); | ||
170 | |||
171 | /* Have to be a bit careful with return values */ | ||
172 | if (nr > 0) { | ||
173 | if (ret < 0) | ||
174 | ret = nr; | ||
175 | else | ||
176 | ret += nr; | ||
177 | } | ||
178 | |||
179 | return ret; | ||
180 | } | ||
181 | } | ||
diff --git a/arch/sparc/mm/tsb.c b/arch/sparc/mm/tsb.c index a5f51b22fcbe..536412d8f416 100644 --- a/arch/sparc/mm/tsb.c +++ b/arch/sparc/mm/tsb.c | |||
@@ -236,6 +236,8 @@ static void setup_tsb_params(struct mm_struct *mm, unsigned long tsb_idx, unsign | |||
236 | } | 236 | } |
237 | } | 237 | } |
238 | 238 | ||
239 | struct kmem_cache *pgtable_cache __read_mostly; | ||
240 | |||
239 | static struct kmem_cache *tsb_caches[8] __read_mostly; | 241 | static struct kmem_cache *tsb_caches[8] __read_mostly; |
240 | 242 | ||
241 | static const char *tsb_cache_names[8] = { | 243 | static const char *tsb_cache_names[8] = { |
@@ -253,6 +255,15 @@ void __init pgtable_cache_init(void) | |||
253 | { | 255 | { |
254 | unsigned long i; | 256 | unsigned long i; |
255 | 257 | ||
258 | pgtable_cache = kmem_cache_create("pgtable_cache", | ||
259 | PAGE_SIZE, PAGE_SIZE, | ||
260 | 0, | ||
261 | _clear_page); | ||
262 | if (!pgtable_cache) { | ||
263 | prom_printf("pgtable_cache_init(): Could not create!\n"); | ||
264 | prom_halt(); | ||
265 | } | ||
266 | |||
256 | for (i = 0; i < 8; i++) { | 267 | for (i = 0; i < 8; i++) { |
257 | unsigned long size = 8192 << i; | 268 | unsigned long size = 8192 << i; |
258 | const char *name = tsb_cache_names[i]; | 269 | const char *name = tsb_cache_names[i]; |
diff --git a/arch/um/Kconfig.x86 b/arch/um/Kconfig.x86 index 8aae429a56e2..d31ecf346b4e 100644 --- a/arch/um/Kconfig.x86 +++ b/arch/um/Kconfig.x86 | |||
@@ -1,3 +1,5 @@ | |||
1 | mainmenu "User Mode Linux/$SUBARCH $KERNELVERSION Kernel Configuration" | ||
2 | |||
1 | source "arch/um/Kconfig.common" | 3 | source "arch/um/Kconfig.common" |
2 | 4 | ||
3 | menu "UML-specific options" | 5 | menu "UML-specific options" |
diff --git a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c index 25e1965df7ce..d4191fe1cede 100644 --- a/arch/um/drivers/chan_kern.c +++ b/arch/um/drivers/chan_kern.c | |||
@@ -543,11 +543,10 @@ int parse_chan_pair(char *str, struct line *line, int device, | |||
543 | const struct chan_opts *opts, char **error_out) | 543 | const struct chan_opts *opts, char **error_out) |
544 | { | 544 | { |
545 | struct list_head *chans = &line->chan_list; | 545 | struct list_head *chans = &line->chan_list; |
546 | struct chan *new, *chan; | 546 | struct chan *new; |
547 | char *in, *out; | 547 | char *in, *out; |
548 | 548 | ||
549 | if (!list_empty(chans)) { | 549 | if (!list_empty(chans)) { |
550 | chan = list_entry(chans->next, struct chan, list); | ||
551 | free_chan(chans, 0); | 550 | free_chan(chans, 0); |
552 | INIT_LIST_HEAD(chans); | 551 | INIT_LIST_HEAD(chans); |
553 | } | 552 | } |
diff --git a/arch/um/drivers/cow_user.c b/arch/um/drivers/cow_user.c index 93f227a25ba4..9cbb426c0b91 100644 --- a/arch/um/drivers/cow_user.c +++ b/arch/um/drivers/cow_user.c | |||
@@ -186,7 +186,11 @@ static int absolutize(char *to, int size, char *from) | |||
186 | strcat(to, "/"); | 186 | strcat(to, "/"); |
187 | strcat(to, from); | 187 | strcat(to, from); |
188 | } | 188 | } |
189 | chdir(save_cwd); | 189 | if (chdir(save_cwd)) { |
190 | cow_printf("absolutize : Can't cd to '%s' - " | ||
191 | "errno = %d\n", save_cwd, errno); | ||
192 | return -1; | ||
193 | } | ||
190 | return 0; | 194 | return 0; |
191 | } | 195 | } |
192 | 196 | ||
diff --git a/arch/um/drivers/harddog_user.c b/arch/um/drivers/harddog_user.c index b56f8e0196a9..84dce3fc590c 100644 --- a/arch/um/drivers/harddog_user.c +++ b/arch/um/drivers/harddog_user.c | |||
@@ -32,7 +32,7 @@ int start_watchdog(int *in_fd_ret, int *out_fd_ret, char *sock) | |||
32 | { | 32 | { |
33 | struct dog_data data; | 33 | struct dog_data data; |
34 | int in_fds[2], out_fds[2], pid, n, err; | 34 | int in_fds[2], out_fds[2], pid, n, err; |
35 | char pid_buf[sizeof("nnnnn\0")], c; | 35 | char pid_buf[sizeof("nnnnnnn\0")], c; |
36 | char *pid_args[] = { "/usr/bin/uml_watchdog", "-pid", pid_buf, NULL }; | 36 | char *pid_args[] = { "/usr/bin/uml_watchdog", "-pid", pid_buf, NULL }; |
37 | char *mconsole_args[] = { "/usr/bin/uml_watchdog", "-mconsole", NULL, | 37 | char *mconsole_args[] = { "/usr/bin/uml_watchdog", "-mconsole", NULL, |
38 | NULL }; | 38 | NULL }; |
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c index 35dd0b86401a..d51c404239a8 100644 --- a/arch/um/drivers/line.c +++ b/arch/um/drivers/line.c | |||
@@ -176,10 +176,9 @@ void line_flush_buffer(struct tty_struct *tty) | |||
176 | { | 176 | { |
177 | struct line *line = tty->driver_data; | 177 | struct line *line = tty->driver_data; |
178 | unsigned long flags; | 178 | unsigned long flags; |
179 | int err; | ||
180 | 179 | ||
181 | spin_lock_irqsave(&line->lock, flags); | 180 | spin_lock_irqsave(&line->lock, flags); |
182 | err = flush_buffer(line); | 181 | flush_buffer(line); |
183 | spin_unlock_irqrestore(&line->lock, flags); | 182 | spin_unlock_irqrestore(&line->lock, flags); |
184 | } | 183 | } |
185 | 184 | ||
diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c index 47d0c37897d5..22745b47c829 100644 --- a/arch/um/drivers/net_kern.c +++ b/arch/um/drivers/net_kern.c | |||
@@ -262,6 +262,15 @@ static int uml_net_change_mtu(struct net_device *dev, int new_mtu) | |||
262 | return 0; | 262 | return 0; |
263 | } | 263 | } |
264 | 264 | ||
265 | #ifdef CONFIG_NET_POLL_CONTROLLER | ||
266 | static void uml_net_poll_controller(struct net_device *dev) | ||
267 | { | ||
268 | disable_irq(dev->irq); | ||
269 | uml_net_interrupt(dev->irq, dev); | ||
270 | enable_irq(dev->irq); | ||
271 | } | ||
272 | #endif | ||
273 | |||
265 | static void uml_net_get_drvinfo(struct net_device *dev, | 274 | static void uml_net_get_drvinfo(struct net_device *dev, |
266 | struct ethtool_drvinfo *info) | 275 | struct ethtool_drvinfo *info) |
267 | { | 276 | { |
@@ -364,6 +373,9 @@ static const struct net_device_ops uml_netdev_ops = { | |||
364 | .ndo_set_mac_address = eth_mac_addr, | 373 | .ndo_set_mac_address = eth_mac_addr, |
365 | .ndo_change_mtu = uml_net_change_mtu, | 374 | .ndo_change_mtu = uml_net_change_mtu, |
366 | .ndo_validate_addr = eth_validate_addr, | 375 | .ndo_validate_addr = eth_validate_addr, |
376 | #ifdef CONFIG_NET_POLL_CONTROLLER | ||
377 | .ndo_poll_controller = uml_net_poll_controller, | ||
378 | #endif | ||
367 | }; | 379 | }; |
368 | 380 | ||
369 | /* | 381 | /* |
diff --git a/arch/um/drivers/net_user.c b/arch/um/drivers/net_user.c index 9415dd9e63ef..520118888f16 100644 --- a/arch/um/drivers/net_user.c +++ b/arch/um/drivers/net_user.c | |||
@@ -228,7 +228,10 @@ static void change(char *dev, char *what, unsigned char *addr, | |||
228 | "buffer\n"); | 228 | "buffer\n"); |
229 | 229 | ||
230 | pid = change_tramp(argv, output, output_len); | 230 | pid = change_tramp(argv, output, output_len); |
231 | if (pid < 0) return; | 231 | if (pid < 0) { |
232 | kfree(output); | ||
233 | return; | ||
234 | } | ||
232 | 235 | ||
233 | if (output != NULL) { | 236 | if (output != NULL) { |
234 | printk("%s", output); | 237 | printk("%s", output); |
diff --git a/arch/um/drivers/slip_user.c b/arch/um/drivers/slip_user.c index a1c2d2c98a94..cbacfc4e63e6 100644 --- a/arch/um/drivers/slip_user.c +++ b/arch/um/drivers/slip_user.c | |||
@@ -102,7 +102,7 @@ static int slip_tramp(char **argv, int fd) | |||
102 | "buffer\n"); | 102 | "buffer\n"); |
103 | os_kill_process(pid, 1); | 103 | os_kill_process(pid, 1); |
104 | err = -ENOMEM; | 104 | err = -ENOMEM; |
105 | goto out_free; | 105 | goto out_close; |
106 | } | 106 | } |
107 | 107 | ||
108 | close(fds[1]); | 108 | close(fds[1]); |
@@ -112,7 +112,6 @@ static int slip_tramp(char **argv, int fd) | |||
112 | err = helper_wait(pid); | 112 | err = helper_wait(pid); |
113 | close(fds[0]); | 113 | close(fds[0]); |
114 | 114 | ||
115 | out_free: | ||
116 | kfree(output); | 115 | kfree(output); |
117 | return err; | 116 | return err; |
118 | 117 | ||
diff --git a/arch/um/include/asm/delay.h b/arch/um/include/asm/delay.h index c71e32b6741e..8a5576d8eda5 100644 --- a/arch/um/include/asm/delay.h +++ b/arch/um/include/asm/delay.h | |||
@@ -1,20 +1,18 @@ | |||
1 | #ifndef __UM_DELAY_H | 1 | #ifndef __UM_DELAY_H |
2 | #define __UM_DELAY_H | 2 | #define __UM_DELAY_H |
3 | 3 | ||
4 | #define MILLION 1000000 | ||
5 | |||
6 | /* Undefined on purpose */ | 4 | /* Undefined on purpose */ |
7 | extern void __bad_udelay(void); | 5 | extern void __bad_udelay(void); |
6 | extern void __bad_ndelay(void); | ||
8 | 7 | ||
9 | extern void __udelay(unsigned long usecs); | 8 | extern void __udelay(unsigned long usecs); |
9 | extern void __ndelay(unsigned long usecs); | ||
10 | extern void __delay(unsigned long loops); | 10 | extern void __delay(unsigned long loops); |
11 | 11 | ||
12 | #define udelay(n) ((__builtin_constant_p(n) && (n) > 20000) ? \ | 12 | #define udelay(n) ((__builtin_constant_p(n) && (n) > 20000) ? \ |
13 | __bad_udelay() : __udelay(n)) | 13 | __bad_udelay() : __udelay(n)) |
14 | 14 | ||
15 | /* It appears that ndelay is not used at all for UML, and has never been | 15 | #define ndelay(n) ((__builtin_constant_p(n) && (n) > 20000) ? \ |
16 | * implemented. */ | 16 | __bad_ndelay() : __ndelay(n)) |
17 | extern void __unimplemented_ndelay(void); | ||
18 | #define ndelay(n) __unimplemented_ndelay() | ||
19 | 17 | ||
20 | #endif | 18 | #endif |
diff --git a/arch/um/kernel/exec.c b/arch/um/kernel/exec.c index 09bd7b585726..939a4a67f0fd 100644 --- a/arch/um/kernel/exec.c +++ b/arch/um/kernel/exec.c | |||
@@ -38,7 +38,6 @@ void flush_thread(void) | |||
38 | 38 | ||
39 | void start_thread(struct pt_regs *regs, unsigned long eip, unsigned long esp) | 39 | void start_thread(struct pt_regs *regs, unsigned long eip, unsigned long esp) |
40 | { | 40 | { |
41 | set_fs(USER_DS); | ||
42 | PT_REGS_IP(regs) = eip; | 41 | PT_REGS_IP(regs) = eip; |
43 | PT_REGS_SP(regs) = esp; | 42 | PT_REGS_SP(regs) = esp; |
44 | } | 43 | } |
diff --git a/arch/um/kernel/reboot.c b/arch/um/kernel/reboot.c index 869bec9f2516..4d93dff6b371 100644 --- a/arch/um/kernel/reboot.c +++ b/arch/um/kernel/reboot.c | |||
@@ -20,9 +20,8 @@ static void kill_off_processes(void) | |||
20 | os_kill_ptraced_process(userspace_pid[0], 1); | 20 | os_kill_ptraced_process(userspace_pid[0], 1); |
21 | else { | 21 | else { |
22 | struct task_struct *p; | 22 | struct task_struct *p; |
23 | int pid, me; | 23 | int pid; |
24 | 24 | ||
25 | me = os_getpid(); | ||
26 | for_each_process(p) { | 25 | for_each_process(p) { |
27 | if (p->mm == NULL) | 26 | if (p->mm == NULL) |
28 | continue; | 27 | continue; |
diff --git a/arch/um/os-Linux/Makefile b/arch/um/os-Linux/Makefile index d66f0388f091..b33f4dfe7ae5 100644 --- a/arch/um/os-Linux/Makefile +++ b/arch/um/os-Linux/Makefile | |||
@@ -3,10 +3,12 @@ | |||
3 | # Licensed under the GPL | 3 | # Licensed under the GPL |
4 | # | 4 | # |
5 | 5 | ||
6 | obj-y = aio.o elf_aux.o execvp.o file.o helper.o irq.o main.o mem.o process.o \ | 6 | obj-y = aio.o execvp.o file.o helper.o irq.o main.o mem.o process.o \ |
7 | registers.o sigio.o signal.o start_up.o time.o tty.o uaccess.o \ | 7 | registers.o sigio.o signal.o start_up.o time.o tty.o uaccess.o \ |
8 | umid.o tls.o user_syms.o util.o drivers/ sys-$(SUBARCH)/ skas/ | 8 | umid.o tls.o user_syms.o util.o drivers/ sys-$(SUBARCH)/ skas/ |
9 | 9 | ||
10 | obj-$(CONFIG_ARCH_REUSE_HOST_VSYSCALL_AREA) += elf_aux.o | ||
11 | |||
10 | USER_OBJS := $(user-objs-y) aio.o elf_aux.o execvp.o file.o helper.o irq.o \ | 12 | USER_OBJS := $(user-objs-y) aio.o elf_aux.o execvp.o file.o helper.o irq.o \ |
11 | main.o mem.o process.o registers.o sigio.o signal.o start_up.o time.o \ | 13 | main.o mem.o process.o registers.o sigio.o signal.o start_up.o time.o \ |
12 | tty.o tls.o uaccess.o umid.o util.o | 14 | tty.o tls.o uaccess.o umid.o util.o |
diff --git a/arch/um/os-Linux/elf_aux.c b/arch/um/os-Linux/elf_aux.c index 608784d4ec57..953323799381 100644 --- a/arch/um/os-Linux/elf_aux.c +++ b/arch/um/os-Linux/elf_aux.c | |||
@@ -14,16 +14,11 @@ | |||
14 | #include "mem_user.h" | 14 | #include "mem_user.h" |
15 | #include <kern_constants.h> | 15 | #include <kern_constants.h> |
16 | 16 | ||
17 | /* Use the one from the kernel - the host may miss it, if having old headers. */ | ||
18 | #if UM_ELF_CLASS == UM_ELFCLASS32 | ||
19 | typedef Elf32_auxv_t elf_auxv_t; | 17 | typedef Elf32_auxv_t elf_auxv_t; |
20 | #else | ||
21 | typedef Elf64_auxv_t elf_auxv_t; | ||
22 | #endif | ||
23 | 18 | ||
24 | /* These are initialized very early in boot and never changed */ | 19 | /* These are initialized very early in boot and never changed */ |
25 | char * elf_aux_platform; | 20 | char * elf_aux_platform; |
26 | long elf_aux_hwcap; | 21 | extern long elf_aux_hwcap; |
27 | unsigned long vsyscall_ehdr; | 22 | unsigned long vsyscall_ehdr; |
28 | unsigned long vsyscall_end; | 23 | unsigned long vsyscall_end; |
29 | unsigned long __kernel_vsyscall; | 24 | unsigned long __kernel_vsyscall; |
diff --git a/arch/um/os-Linux/helper.c b/arch/um/os-Linux/helper.c index b6b1096152aa..feff22d64672 100644 --- a/arch/um/os-Linux/helper.c +++ b/arch/um/os-Linux/helper.c | |||
@@ -28,14 +28,14 @@ static int helper_child(void *arg) | |||
28 | { | 28 | { |
29 | struct helper_data *data = arg; | 29 | struct helper_data *data = arg; |
30 | char **argv = data->argv; | 30 | char **argv = data->argv; |
31 | int err; | 31 | int err, ret; |
32 | 32 | ||
33 | if (data->pre_exec != NULL) | 33 | if (data->pre_exec != NULL) |
34 | (*data->pre_exec)(data->pre_data); | 34 | (*data->pre_exec)(data->pre_data); |
35 | err = execvp_noalloc(data->buf, argv[0], argv); | 35 | err = execvp_noalloc(data->buf, argv[0], argv); |
36 | 36 | ||
37 | /* If the exec succeeds, we don't get here */ | 37 | /* If the exec succeeds, we don't get here */ |
38 | write(data->fd, &err, sizeof(err)); | 38 | CATCH_EINTR(ret = write(data->fd, &err, sizeof(err))); |
39 | 39 | ||
40 | return 0; | 40 | return 0; |
41 | } | 41 | } |
diff --git a/arch/um/os-Linux/main.c b/arch/um/os-Linux/main.c index fb2a97a75fb1..8471b817d94f 100644 --- a/arch/um/os-Linux/main.c +++ b/arch/um/os-Linux/main.c | |||
@@ -21,6 +21,8 @@ | |||
21 | #define STACKSIZE (8 * 1024 * 1024) | 21 | #define STACKSIZE (8 * 1024 * 1024) |
22 | #define THREAD_NAME_LEN (256) | 22 | #define THREAD_NAME_LEN (256) |
23 | 23 | ||
24 | long elf_aux_hwcap; | ||
25 | |||
24 | static void set_stklim(void) | 26 | static void set_stklim(void) |
25 | { | 27 | { |
26 | struct rlimit lim; | 28 | struct rlimit lim; |
@@ -143,7 +145,9 @@ int __init main(int argc, char **argv, char **envp) | |||
143 | install_fatal_handler(SIGINT); | 145 | install_fatal_handler(SIGINT); |
144 | install_fatal_handler(SIGTERM); | 146 | install_fatal_handler(SIGTERM); |
145 | 147 | ||
148 | #ifdef CONFIG_ARCH_REUSE_HOST_VSYSCALL_AREA | ||
146 | scan_elf_aux(envp); | 149 | scan_elf_aux(envp); |
150 | #endif | ||
147 | 151 | ||
148 | do_uml_initcalls(); | 152 | do_uml_initcalls(); |
149 | ret = linux_main(argc, argv); | 153 | ret = linux_main(argc, argv); |
diff --git a/arch/um/os-Linux/mem.c b/arch/um/os-Linux/mem.c index e696144d2be3..62878cf1d33f 100644 --- a/arch/um/os-Linux/mem.c +++ b/arch/um/os-Linux/mem.c | |||
@@ -176,7 +176,7 @@ static int __init make_tempfile(const char *template, char **out_tempname, | |||
176 | 176 | ||
177 | find_tempdir(); | 177 | find_tempdir(); |
178 | if ((tempdir == NULL) || (strlen(tempdir) >= MAXPATHLEN)) | 178 | if ((tempdir == NULL) || (strlen(tempdir) >= MAXPATHLEN)) |
179 | return -1; | 179 | goto out; |
180 | 180 | ||
181 | if (template[0] != '/') | 181 | if (template[0] != '/') |
182 | strcpy(tempname, tempdir); | 182 | strcpy(tempname, tempdir); |
@@ -191,13 +191,15 @@ static int __init make_tempfile(const char *template, char **out_tempname, | |||
191 | } | 191 | } |
192 | if (do_unlink && (unlink(tempname) < 0)) { | 192 | if (do_unlink && (unlink(tempname) < 0)) { |
193 | perror("unlink"); | 193 | perror("unlink"); |
194 | goto out; | 194 | goto close; |
195 | } | 195 | } |
196 | if (out_tempname) { | 196 | if (out_tempname) { |
197 | *out_tempname = tempname; | 197 | *out_tempname = tempname; |
198 | } else | 198 | } else |
199 | free(tempname); | 199 | free(tempname); |
200 | return fd; | 200 | return fd; |
201 | close: | ||
202 | close(fd); | ||
201 | out: | 203 | out: |
202 | free(tempname); | 204 | free(tempname); |
203 | return -1; | 205 | return -1; |
diff --git a/arch/um/os-Linux/user_syms.c b/arch/um/os-Linux/user_syms.c index 05f5ea8e83d2..45ffe46871e0 100644 --- a/arch/um/os-Linux/user_syms.c +++ b/arch/um/os-Linux/user_syms.c | |||
@@ -113,3 +113,8 @@ EXPORT_SYMBOL(__stack_smash_handler); | |||
113 | 113 | ||
114 | extern long __guard __attribute__((weak)); | 114 | extern long __guard __attribute__((weak)); |
115 | EXPORT_SYMBOL(__guard); | 115 | EXPORT_SYMBOL(__guard); |
116 | |||
117 | #ifdef _FORTIFY_SOURCE | ||
118 | extern int __sprintf_chk(char *str, int flag, size_t strlen, const char *format); | ||
119 | EXPORT_SYMBOL(__sprintf_chk); | ||
120 | #endif | ||
diff --git a/arch/um/sys-i386/Makefile b/arch/um/sys-i386/Makefile index 87b659dadf3f..3923cfb87649 100644 --- a/arch/um/sys-i386/Makefile +++ b/arch/um/sys-i386/Makefile | |||
@@ -4,7 +4,7 @@ | |||
4 | 4 | ||
5 | obj-y = bug.o bugs.o checksum.o delay.o fault.o ksyms.o ldt.o ptrace.o \ | 5 | obj-y = bug.o bugs.o checksum.o delay.o fault.o ksyms.o ldt.o ptrace.o \ |
6 | ptrace_user.o setjmp.o signal.o stub.o stub_segv.o syscalls.o sysrq.o \ | 6 | ptrace_user.o setjmp.o signal.o stub.o stub_segv.o syscalls.o sysrq.o \ |
7 | sys_call_table.o tls.o atomic64_cx8_32.o | 7 | sys_call_table.o tls.o atomic64_cx8_32.o mem.o |
8 | 8 | ||
9 | obj-$(CONFIG_BINFMT_ELF) += elfcore.o | 9 | obj-$(CONFIG_BINFMT_ELF) += elfcore.o |
10 | 10 | ||
diff --git a/arch/um/sys-i386/asm/elf.h b/arch/um/sys-i386/asm/elf.h index d964a4111ac6..42305551d204 100644 --- a/arch/um/sys-i386/asm/elf.h +++ b/arch/um/sys-i386/asm/elf.h | |||
@@ -105,6 +105,8 @@ extern unsigned long __kernel_vsyscall; | |||
105 | #define FIXADDR_USER_START VSYSCALL_BASE | 105 | #define FIXADDR_USER_START VSYSCALL_BASE |
106 | #define FIXADDR_USER_END VSYSCALL_END | 106 | #define FIXADDR_USER_END VSYSCALL_END |
107 | 107 | ||
108 | #define __HAVE_ARCH_GATE_AREA 1 | ||
109 | |||
108 | /* | 110 | /* |
109 | * Architecture-neutral AT_ values in 0-17, leave some room | 111 | * Architecture-neutral AT_ values in 0-17, leave some room |
110 | * for more of them, start the x86-specific ones at 32. | 112 | * for more of them, start the x86-specific ones at 32. |
diff --git a/arch/um/sys-i386/delay.c b/arch/um/sys-i386/delay.c index d623e074f41d..f3fe1a688f7e 100644 --- a/arch/um/sys-i386/delay.c +++ b/arch/um/sys-i386/delay.c | |||
@@ -1,29 +1,60 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2011 Richard Weinberger <richrd@nod.at> | ||
3 | * Mostly copied from arch/x86/lib/delay.c | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License version 2 as | ||
7 | * published by the Free Software Foundation. | ||
8 | */ | ||
9 | |||
1 | #include <linux/module.h> | 10 | #include <linux/module.h> |
2 | #include <linux/kernel.h> | 11 | #include <linux/kernel.h> |
3 | #include <linux/delay.h> | 12 | #include <linux/delay.h> |
4 | #include <asm/param.h> | 13 | #include <asm/param.h> |
5 | 14 | ||
6 | void __delay(unsigned long time) | 15 | void __delay(unsigned long loops) |
7 | { | 16 | { |
8 | /* Stolen from the i386 __loop_delay */ | 17 | asm volatile( |
9 | int d0; | 18 | "test %0,%0\n" |
10 | __asm__ __volatile__( | 19 | "jz 3f\n" |
11 | "\tjmp 1f\n" | 20 | "jmp 1f\n" |
21 | |||
12 | ".align 16\n" | 22 | ".align 16\n" |
13 | "1:\tjmp 2f\n" | 23 | "1: jmp 2f\n" |
24 | |||
14 | ".align 16\n" | 25 | ".align 16\n" |
15 | "2:\tdecl %0\n\tjns 2b" | 26 | "2: dec %0\n" |
16 | :"=&a" (d0) | 27 | " jnz 2b\n" |
17 | :"0" (time)); | 28 | "3: dec %0\n" |
29 | |||
30 | : /* we don't need output */ | ||
31 | : "a" (loops) | ||
32 | ); | ||
18 | } | 33 | } |
34 | EXPORT_SYMBOL(__delay); | ||
19 | 35 | ||
20 | void __udelay(unsigned long usecs) | 36 | inline void __const_udelay(unsigned long xloops) |
21 | { | 37 | { |
22 | int i, n; | 38 | int d0; |
23 | 39 | ||
24 | n = (loops_per_jiffy * HZ * usecs) / MILLION; | 40 | xloops *= 4; |
25 | for(i=0;i<n;i++) | 41 | asm("mull %%edx" |
26 | cpu_relax(); | 42 | : "=d" (xloops), "=&a" (d0) |
43 | : "1" (xloops), "0" | ||
44 | (loops_per_jiffy * (HZ/4))); | ||
45 | |||
46 | __delay(++xloops); | ||
27 | } | 47 | } |
48 | EXPORT_SYMBOL(__const_udelay); | ||
28 | 49 | ||
50 | void __udelay(unsigned long usecs) | ||
51 | { | ||
52 | __const_udelay(usecs * 0x000010c7); /* 2**32 / 1000000 (rounded up) */ | ||
53 | } | ||
29 | EXPORT_SYMBOL(__udelay); | 54 | EXPORT_SYMBOL(__udelay); |
55 | |||
56 | void __ndelay(unsigned long nsecs) | ||
57 | { | ||
58 | __const_udelay(nsecs * 0x00005); /* 2**32 / 1000000000 (rounded up) */ | ||
59 | } | ||
60 | EXPORT_SYMBOL(__ndelay); | ||
diff --git a/arch/um/sys-i386/mem.c b/arch/um/sys-i386/mem.c new file mode 100644 index 000000000000..639900a6fde9 --- /dev/null +++ b/arch/um/sys-i386/mem.c | |||
@@ -0,0 +1,62 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2011 Richard Weinberger <richrd@nod.at> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | */ | ||
8 | |||
9 | #include <linux/mm.h> | ||
10 | #include <asm/page.h> | ||
11 | #include <asm/mman.h> | ||
12 | |||
13 | static struct vm_area_struct gate_vma; | ||
14 | |||
15 | static int __init gate_vma_init(void) | ||
16 | { | ||
17 | if (!FIXADDR_USER_START) | ||
18 | return 0; | ||
19 | |||
20 | gate_vma.vm_mm = NULL; | ||
21 | gate_vma.vm_start = FIXADDR_USER_START; | ||
22 | gate_vma.vm_end = FIXADDR_USER_END; | ||
23 | gate_vma.vm_flags = VM_READ | VM_MAYREAD | VM_EXEC | VM_MAYEXEC; | ||
24 | gate_vma.vm_page_prot = __P101; | ||
25 | |||
26 | /* | ||
27 | * Make sure the vDSO gets into every core dump. | ||
28 | * Dumping its contents makes post-mortem fully interpretable later | ||
29 | * without matching up the same kernel and hardware config to see | ||
30 | * what PC values meant. | ||
31 | */ | ||
32 | gate_vma.vm_flags |= VM_ALWAYSDUMP; | ||
33 | |||
34 | return 0; | ||
35 | } | ||
36 | __initcall(gate_vma_init); | ||
37 | |||
38 | struct vm_area_struct *get_gate_vma(struct mm_struct *mm) | ||
39 | { | ||
40 | return FIXADDR_USER_START ? &gate_vma : NULL; | ||
41 | } | ||
42 | |||
43 | int in_gate_area_no_mm(unsigned long addr) | ||
44 | { | ||
45 | if (!FIXADDR_USER_START) | ||
46 | return 0; | ||
47 | |||
48 | if ((addr >= FIXADDR_USER_START) && (addr < FIXADDR_USER_END)) | ||
49 | return 1; | ||
50 | |||
51 | return 0; | ||
52 | } | ||
53 | |||
54 | int in_gate_area(struct mm_struct *mm, unsigned long addr) | ||
55 | { | ||
56 | struct vm_area_struct *vma = get_gate_vma(mm); | ||
57 | |||
58 | if (!vma) | ||
59 | return 0; | ||
60 | |||
61 | return (addr >= vma->vm_start) && (addr < vma->vm_end); | ||
62 | } | ||
diff --git a/arch/um/sys-x86_64/Makefile b/arch/um/sys-x86_64/Makefile index 61fc99a42e10..bd4d1d3ba919 100644 --- a/arch/um/sys-x86_64/Makefile +++ b/arch/um/sys-x86_64/Makefile | |||
@@ -4,10 +4,12 @@ | |||
4 | # Licensed under the GPL | 4 | # Licensed under the GPL |
5 | # | 5 | # |
6 | 6 | ||
7 | obj-y = bug.o bugs.o delay.o fault.o ldt.o mem.o ptrace.o ptrace_user.o \ | 7 | obj-y = bug.o bugs.o delay.o fault.o ldt.o ptrace.o ptrace_user.o mem.o \ |
8 | setjmp.o signal.o stub.o stub_segv.o syscalls.o syscall_table.o \ | 8 | setjmp.o signal.o stub.o stub_segv.o syscalls.o syscall_table.o \ |
9 | sysrq.o ksyms.o tls.o | 9 | sysrq.o ksyms.o tls.o |
10 | 10 | ||
11 | obj-y += vdso/ | ||
12 | |||
11 | subarch-obj-y = lib/csum-partial_64.o lib/memcpy_64.o lib/thunk_64.o \ | 13 | subarch-obj-y = lib/csum-partial_64.o lib/memcpy_64.o lib/thunk_64.o \ |
12 | lib/rwsem.o | 14 | lib/rwsem.o |
13 | subarch-obj-$(CONFIG_MODULES) += kernel/module.o | 15 | subarch-obj-$(CONFIG_MODULES) += kernel/module.o |
diff --git a/arch/um/sys-x86_64/asm/elf.h b/arch/um/sys-x86_64/asm/elf.h index d6d5af376251..11a2bfb38859 100644 --- a/arch/um/sys-x86_64/asm/elf.h +++ b/arch/um/sys-x86_64/asm/elf.h | |||
@@ -119,4 +119,14 @@ extern long elf_aux_hwcap; | |||
119 | 119 | ||
120 | #define SET_PERSONALITY(ex) do ; while(0) | 120 | #define SET_PERSONALITY(ex) do ; while(0) |
121 | 121 | ||
122 | #define __HAVE_ARCH_GATE_AREA 1 | ||
123 | #define ARCH_HAS_SETUP_ADDITIONAL_PAGES 1 | ||
124 | struct linux_binprm; | ||
125 | extern int arch_setup_additional_pages(struct linux_binprm *bprm, | ||
126 | int uses_interp); | ||
127 | |||
128 | extern unsigned long um_vdso_addr; | ||
129 | #define AT_SYSINFO_EHDR 33 | ||
130 | #define ARCH_DLINFO NEW_AUX_ENT(AT_SYSINFO_EHDR, um_vdso_addr) | ||
131 | |||
122 | #endif | 132 | #endif |
diff --git a/arch/um/sys-x86_64/delay.c b/arch/um/sys-x86_64/delay.c index dee5be66da82..f3fe1a688f7e 100644 --- a/arch/um/sys-x86_64/delay.c +++ b/arch/um/sys-x86_64/delay.c | |||
@@ -1,30 +1,60 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright 2003 PathScale, Inc. | 2 | * Copyright (C) 2011 Richard Weinberger <richrd@nod.at> |
3 | * Copied from arch/x86_64 | 3 | * Mostly copied from arch/x86/lib/delay.c |
4 | * | 4 | * |
5 | * Licensed under the GPL | 5 | * This program is free software; you can redistribute it and/or modify |
6 | * it under the terms of the GNU General Public License version 2 as | ||
7 | * published by the Free Software Foundation. | ||
6 | */ | 8 | */ |
7 | 9 | ||
8 | #include <linux/module.h> | 10 | #include <linux/module.h> |
11 | #include <linux/kernel.h> | ||
9 | #include <linux/delay.h> | 12 | #include <linux/delay.h> |
10 | #include <asm/processor.h> | ||
11 | #include <asm/param.h> | 13 | #include <asm/param.h> |
12 | 14 | ||
13 | void __delay(unsigned long loops) | 15 | void __delay(unsigned long loops) |
14 | { | 16 | { |
15 | unsigned long i; | 17 | asm volatile( |
18 | "test %0,%0\n" | ||
19 | "jz 3f\n" | ||
20 | "jmp 1f\n" | ||
16 | 21 | ||
17 | for(i = 0; i < loops; i++) | 22 | ".align 16\n" |
18 | cpu_relax(); | 23 | "1: jmp 2f\n" |
24 | |||
25 | ".align 16\n" | ||
26 | "2: dec %0\n" | ||
27 | " jnz 2b\n" | ||
28 | "3: dec %0\n" | ||
29 | |||
30 | : /* we don't need output */ | ||
31 | : "a" (loops) | ||
32 | ); | ||
19 | } | 33 | } |
34 | EXPORT_SYMBOL(__delay); | ||
20 | 35 | ||
21 | void __udelay(unsigned long usecs) | 36 | inline void __const_udelay(unsigned long xloops) |
22 | { | 37 | { |
23 | unsigned long i, n; | 38 | int d0; |
24 | 39 | ||
25 | n = (loops_per_jiffy * HZ * usecs) / MILLION; | 40 | xloops *= 4; |
26 | for(i=0;i<n;i++) | 41 | asm("mull %%edx" |
27 | cpu_relax(); | 42 | : "=d" (xloops), "=&a" (d0) |
43 | : "1" (xloops), "0" | ||
44 | (loops_per_jiffy * (HZ/4))); | ||
45 | |||
46 | __delay(++xloops); | ||
28 | } | 47 | } |
48 | EXPORT_SYMBOL(__const_udelay); | ||
29 | 49 | ||
50 | void __udelay(unsigned long usecs) | ||
51 | { | ||
52 | __const_udelay(usecs * 0x000010c7); /* 2**32 / 1000000 (rounded up) */ | ||
53 | } | ||
30 | EXPORT_SYMBOL(__udelay); | 54 | EXPORT_SYMBOL(__udelay); |
55 | |||
56 | void __ndelay(unsigned long nsecs) | ||
57 | { | ||
58 | __const_udelay(nsecs * 0x00005); /* 2**32 / 1000000000 (rounded up) */ | ||
59 | } | ||
60 | EXPORT_SYMBOL(__ndelay); | ||
diff --git a/arch/um/sys-x86_64/mem.c b/arch/um/sys-x86_64/mem.c index 3f8df8abf347..546518727a73 100644 --- a/arch/um/sys-x86_64/mem.c +++ b/arch/um/sys-x86_64/mem.c | |||
@@ -1,16 +1,26 @@ | |||
1 | /* | ||
2 | * Copyright 2003 PathScale, Inc. | ||
3 | * | ||
4 | * Licensed under the GPL | ||
5 | */ | ||
6 | |||
7 | #include "linux/mm.h" | 1 | #include "linux/mm.h" |
8 | #include "asm/page.h" | 2 | #include "asm/page.h" |
9 | #include "asm/mman.h" | 3 | #include "asm/mman.h" |
10 | 4 | ||
11 | unsigned long vm_stack_flags = __VM_STACK_FLAGS; | 5 | const char *arch_vma_name(struct vm_area_struct *vma) |
12 | unsigned long vm_stack_flags32 = __VM_STACK_FLAGS; | 6 | { |
13 | unsigned long vm_data_default_flags = __VM_DATA_DEFAULT_FLAGS; | 7 | if (vma->vm_mm && vma->vm_start == um_vdso_addr) |
14 | unsigned long vm_data_default_flags32 = __VM_DATA_DEFAULT_FLAGS; | 8 | return "[vdso]"; |
15 | unsigned long vm_force_exec32 = PROT_EXEC; | 9 | |
10 | return NULL; | ||
11 | } | ||
12 | |||
13 | struct vm_area_struct *get_gate_vma(struct mm_struct *mm) | ||
14 | { | ||
15 | return NULL; | ||
16 | } | ||
17 | |||
18 | int in_gate_area(struct mm_struct *mm, unsigned long addr) | ||
19 | { | ||
20 | return 0; | ||
21 | } | ||
16 | 22 | ||
23 | int in_gate_area_no_mm(unsigned long addr) | ||
24 | { | ||
25 | return 0; | ||
26 | } | ||
diff --git a/arch/um/sys-x86_64/shared/sysdep/vm-flags.h b/arch/um/sys-x86_64/shared/sysdep/vm-flags.h index 3213edfa7888..3978e55132d2 100644 --- a/arch/um/sys-x86_64/shared/sysdep/vm-flags.h +++ b/arch/um/sys-x86_64/shared/sysdep/vm-flags.h | |||
@@ -7,27 +7,9 @@ | |||
7 | #ifndef __VM_FLAGS_X86_64_H | 7 | #ifndef __VM_FLAGS_X86_64_H |
8 | #define __VM_FLAGS_X86_64_H | 8 | #define __VM_FLAGS_X86_64_H |
9 | 9 | ||
10 | #define __VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \ | 10 | #define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \ |
11 | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) | 11 | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) |
12 | #define __VM_STACK_FLAGS (VM_GROWSDOWN | VM_READ | VM_WRITE | \ | 12 | #define VM_STACK_DEFAULT_FLAGS (VM_GROWSDOWN | VM_READ | VM_WRITE | \ |
13 | VM_EXEC | VM_MAYREAD | VM_MAYWRITE | \ | 13 | VM_EXEC | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) |
14 | VM_MAYEXEC) | ||
15 | |||
16 | extern unsigned long vm_stack_flags, vm_stack_flags32; | ||
17 | extern unsigned long vm_data_default_flags, vm_data_default_flags32; | ||
18 | extern unsigned long vm_force_exec32; | ||
19 | |||
20 | #ifdef TIF_IA32 | ||
21 | #define VM_DATA_DEFAULT_FLAGS \ | ||
22 | (test_thread_flag(TIF_IA32) ? vm_data_default_flags32 : \ | ||
23 | vm_data_default_flags) | ||
24 | |||
25 | #define VM_STACK_DEFAULT_FLAGS \ | ||
26 | (test_thread_flag(TIF_IA32) ? vm_stack_flags32 : vm_stack_flags) | ||
27 | #endif | ||
28 | |||
29 | #define VM_DATA_DEFAULT_FLAGS vm_data_default_flags | ||
30 | |||
31 | #define VM_STACK_DEFAULT_FLAGS vm_stack_flags | ||
32 | 14 | ||
33 | #endif | 15 | #endif |
diff --git a/arch/um/sys-x86_64/vdso/Makefile b/arch/um/sys-x86_64/vdso/Makefile new file mode 100644 index 000000000000..5dffe6d46686 --- /dev/null +++ b/arch/um/sys-x86_64/vdso/Makefile | |||
@@ -0,0 +1,90 @@ | |||
1 | # | ||
2 | # Building vDSO images for x86. | ||
3 | # | ||
4 | |||
5 | VDSO64-y := y | ||
6 | |||
7 | vdso-install-$(VDSO64-y) += vdso.so | ||
8 | |||
9 | |||
10 | # files to link into the vdso | ||
11 | vobjs-y := vdso-note.o um_vdso.o | ||
12 | |||
13 | # files to link into kernel | ||
14 | obj-$(VDSO64-y) += vdso.o vma.o | ||
15 | |||
16 | vobjs := $(foreach F,$(vobjs-y),$(obj)/$F) | ||
17 | |||
18 | $(obj)/vdso.o: $(obj)/vdso.so | ||
19 | |||
20 | targets += vdso.so vdso.so.dbg vdso.lds $(vobjs-y) | ||
21 | |||
22 | export CPPFLAGS_vdso.lds += -P -C | ||
23 | |||
24 | VDSO_LDFLAGS_vdso.lds = -m64 -Wl,-soname=linux-vdso.so.1 \ | ||
25 | -Wl,-z,max-page-size=4096 -Wl,-z,common-page-size=4096 | ||
26 | |||
27 | $(obj)/vdso.o: $(src)/vdso.S $(obj)/vdso.so | ||
28 | |||
29 | $(obj)/vdso.so.dbg: $(src)/vdso.lds $(vobjs) FORCE | ||
30 | $(call if_changed,vdso) | ||
31 | |||
32 | $(obj)/%.so: OBJCOPYFLAGS := -S | ||
33 | $(obj)/%.so: $(obj)/%.so.dbg FORCE | ||
34 | $(call if_changed,objcopy) | ||
35 | |||
36 | # | ||
37 | # Don't omit frame pointers for ease of userspace debugging, but do | ||
38 | # optimize sibling calls. | ||
39 | # | ||
40 | CFL := $(PROFILING) -mcmodel=small -fPIC -O2 -fasynchronous-unwind-tables -m64 \ | ||
41 | $(filter -g%,$(KBUILD_CFLAGS)) $(call cc-option, -fno-stack-protector) \ | ||
42 | -fno-omit-frame-pointer -foptimize-sibling-calls | ||
43 | |||
44 | $(vobjs): KBUILD_CFLAGS += $(CFL) | ||
45 | |||
46 | # | ||
47 | # vDSO code runs in userspace and -pg doesn't help with profiling anyway. | ||
48 | # | ||
49 | CFLAGS_REMOVE_vdso-note.o = -pg | ||
50 | CFLAGS_REMOVE_um_vdso.o = -pg | ||
51 | |||
52 | targets += vdso-syms.lds | ||
53 | obj-$(VDSO64-y) += vdso-syms.lds | ||
54 | |||
55 | # | ||
56 | # Match symbols in the DSO that look like VDSO*; produce a file of constants. | ||
57 | # | ||
58 | sed-vdsosym := -e 's/^00*/0/' \ | ||
59 | -e 's/^\([0-9a-fA-F]*\) . \(VDSO[a-zA-Z0-9_]*\)$$/\2 = 0x\1;/p' | ||
60 | quiet_cmd_vdsosym = VDSOSYM $@ | ||
61 | define cmd_vdsosym | ||
62 | $(NM) $< | LC_ALL=C sed -n $(sed-vdsosym) | LC_ALL=C sort > $@ | ||
63 | endef | ||
64 | |||
65 | $(obj)/%-syms.lds: $(obj)/%.so.dbg FORCE | ||
66 | $(call if_changed,vdsosym) | ||
67 | |||
68 | # | ||
69 | # The DSO images are built using a special linker script. | ||
70 | # | ||
71 | quiet_cmd_vdso = VDSO $@ | ||
72 | cmd_vdso = $(CC) -nostdlib -o $@ \ | ||
73 | $(VDSO_LDFLAGS) $(VDSO_LDFLAGS_$(filter %.lds,$(^F))) \ | ||
74 | -Wl,-T,$(filter %.lds,$^) $(filter %.o,$^) && \ | ||
75 | sh $(srctree)/$(src)/checkundef.sh '$(NM)' '$@' | ||
76 | |||
77 | VDSO_LDFLAGS = -fPIC -shared $(call cc-ldoption, -Wl$(comma)--hash-style=sysv) | ||
78 | GCOV_PROFILE := n | ||
79 | |||
80 | # | ||
81 | # Install the unstripped copy of vdso*.so listed in $(vdso-install-y). | ||
82 | # | ||
83 | quiet_cmd_vdso_install = INSTALL $@ | ||
84 | cmd_vdso_install = cp $(obj)/$@.dbg $(MODLIB)/vdso/$@ | ||
85 | $(vdso-install-y): %.so: $(obj)/%.so.dbg FORCE | ||
86 | @mkdir -p $(MODLIB)/vdso | ||
87 | $(call cmd,vdso_install) | ||
88 | |||
89 | PHONY += vdso_install $(vdso-install-y) | ||
90 | vdso_install: $(vdso-install-y) | ||
diff --git a/arch/um/sys-x86_64/vdso/checkundef.sh b/arch/um/sys-x86_64/vdso/checkundef.sh new file mode 100644 index 000000000000..7ee90a9b549d --- /dev/null +++ b/arch/um/sys-x86_64/vdso/checkundef.sh | |||
@@ -0,0 +1,10 @@ | |||
1 | #!/bin/sh | ||
2 | nm="$1" | ||
3 | file="$2" | ||
4 | $nm "$file" | grep '^ *U' > /dev/null 2>&1 | ||
5 | if [ $? -eq 1 ]; then | ||
6 | exit 0 | ||
7 | else | ||
8 | echo "$file: undefined symbols found" >&2 | ||
9 | exit 1 | ||
10 | fi | ||
diff --git a/arch/um/sys-x86_64/vdso/um_vdso.c b/arch/um/sys-x86_64/vdso/um_vdso.c new file mode 100644 index 000000000000..7c441b59d375 --- /dev/null +++ b/arch/um/sys-x86_64/vdso/um_vdso.c | |||
@@ -0,0 +1,71 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2011 Richard Weinberger <richrd@nod.at> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * This vDSO turns all calls into a syscall so that UML can trap them. | ||
9 | */ | ||
10 | |||
11 | |||
12 | /* Disable profiling for userspace code */ | ||
13 | #define DISABLE_BRANCH_PROFILING | ||
14 | |||
15 | #include <linux/time.h> | ||
16 | #include <linux/getcpu.h> | ||
17 | #include <asm/unistd.h> | ||
18 | |||
19 | int __vdso_clock_gettime(clockid_t clock, struct timespec *ts) | ||
20 | { | ||
21 | long ret; | ||
22 | |||
23 | asm("syscall" : "=a" (ret) : | ||
24 | "0" (__NR_clock_gettime), "D" (clock), "S" (ts) : "memory"); | ||
25 | |||
26 | return ret; | ||
27 | } | ||
28 | int clock_gettime(clockid_t, struct timespec *) | ||
29 | __attribute__((weak, alias("__vdso_clock_gettime"))); | ||
30 | |||
31 | int __vdso_gettimeofday(struct timeval *tv, struct timezone *tz) | ||
32 | { | ||
33 | long ret; | ||
34 | |||
35 | asm("syscall" : "=a" (ret) : | ||
36 | "0" (__NR_gettimeofday), "D" (tv), "S" (tz) : "memory"); | ||
37 | |||
38 | return ret; | ||
39 | } | ||
40 | int gettimeofday(struct timeval *, struct timezone *) | ||
41 | __attribute__((weak, alias("__vdso_gettimeofday"))); | ||
42 | |||
43 | time_t __vdso_time(time_t *t) | ||
44 | { | ||
45 | long secs; | ||
46 | |||
47 | asm volatile("syscall" | ||
48 | : "=a" (secs) | ||
49 | : "0" (__NR_time), "D" (t) : "cc", "r11", "cx", "memory"); | ||
50 | |||
51 | return secs; | ||
52 | } | ||
53 | int time(time_t *t) __attribute__((weak, alias("__vdso_time"))); | ||
54 | |||
55 | long | ||
56 | __vdso_getcpu(unsigned *cpu, unsigned *node, struct getcpu_cache *unused) | ||
57 | { | ||
58 | /* | ||
59 | * UML does not support SMP, we can cheat here. :) | ||
60 | */ | ||
61 | |||
62 | if (cpu) | ||
63 | *cpu = 0; | ||
64 | if (node) | ||
65 | *node = 0; | ||
66 | |||
67 | return 0; | ||
68 | } | ||
69 | |||
70 | long getcpu(unsigned *cpu, unsigned *node, struct getcpu_cache *tcache) | ||
71 | __attribute__((weak, alias("__vdso_getcpu"))); | ||
diff --git a/arch/um/sys-x86_64/vdso/vdso-layout.lds.S b/arch/um/sys-x86_64/vdso/vdso-layout.lds.S new file mode 100644 index 000000000000..634a2cf62046 --- /dev/null +++ b/arch/um/sys-x86_64/vdso/vdso-layout.lds.S | |||
@@ -0,0 +1,64 @@ | |||
1 | /* | ||
2 | * Linker script for vDSO. This is an ELF shared object prelinked to | ||
3 | * its virtual address, and with only one read-only segment. | ||
4 | * This script controls its layout. | ||
5 | */ | ||
6 | |||
7 | SECTIONS | ||
8 | { | ||
9 | . = VDSO_PRELINK + SIZEOF_HEADERS; | ||
10 | |||
11 | .hash : { *(.hash) } :text | ||
12 | .gnu.hash : { *(.gnu.hash) } | ||
13 | .dynsym : { *(.dynsym) } | ||
14 | .dynstr : { *(.dynstr) } | ||
15 | .gnu.version : { *(.gnu.version) } | ||
16 | .gnu.version_d : { *(.gnu.version_d) } | ||
17 | .gnu.version_r : { *(.gnu.version_r) } | ||
18 | |||
19 | .note : { *(.note.*) } :text :note | ||
20 | |||
21 | .eh_frame_hdr : { *(.eh_frame_hdr) } :text :eh_frame_hdr | ||
22 | .eh_frame : { KEEP (*(.eh_frame)) } :text | ||
23 | |||
24 | .dynamic : { *(.dynamic) } :text :dynamic | ||
25 | |||
26 | .rodata : { *(.rodata*) } :text | ||
27 | .data : { | ||
28 | *(.data*) | ||
29 | *(.sdata*) | ||
30 | *(.got.plt) *(.got) | ||
31 | *(.gnu.linkonce.d.*) | ||
32 | *(.bss*) | ||
33 | *(.dynbss*) | ||
34 | *(.gnu.linkonce.b.*) | ||
35 | } | ||
36 | |||
37 | .altinstructions : { *(.altinstructions) } | ||
38 | .altinstr_replacement : { *(.altinstr_replacement) } | ||
39 | |||
40 | /* | ||
41 | * Align the actual code well away from the non-instruction data. | ||
42 | * This is the best thing for the I-cache. | ||
43 | */ | ||
44 | . = ALIGN(0x100); | ||
45 | |||
46 | .text : { *(.text*) } :text =0x90909090 | ||
47 | } | ||
48 | |||
49 | /* | ||
50 | * Very old versions of ld do not recognize this name token; use the constant. | ||
51 | */ | ||
52 | #define PT_GNU_EH_FRAME 0x6474e550 | ||
53 | |||
54 | /* | ||
55 | * We must supply the ELF program headers explicitly to get just one | ||
56 | * PT_LOAD segment, and set the flags explicitly to make segments read-only. | ||
57 | */ | ||
58 | PHDRS | ||
59 | { | ||
60 | text PT_LOAD FLAGS(5) FILEHDR PHDRS; /* PF_R|PF_X */ | ||
61 | dynamic PT_DYNAMIC FLAGS(4); /* PF_R */ | ||
62 | note PT_NOTE FLAGS(4); /* PF_R */ | ||
63 | eh_frame_hdr PT_GNU_EH_FRAME; | ||
64 | } | ||
diff --git a/arch/um/sys-x86_64/vdso/vdso-note.S b/arch/um/sys-x86_64/vdso/vdso-note.S new file mode 100644 index 000000000000..79a071e4357e --- /dev/null +++ b/arch/um/sys-x86_64/vdso/vdso-note.S | |||
@@ -0,0 +1,12 @@ | |||
1 | /* | ||
2 | * This supplies .note.* sections to go into the PT_NOTE inside the vDSO text. | ||
3 | * Here we can supply some information useful to userland. | ||
4 | */ | ||
5 | |||
6 | #include <linux/uts.h> | ||
7 | #include <linux/version.h> | ||
8 | #include <linux/elfnote.h> | ||
9 | |||
10 | ELFNOTE_START(Linux, 0, "a") | ||
11 | .long LINUX_VERSION_CODE | ||
12 | ELFNOTE_END | ||
diff --git a/arch/um/sys-x86_64/vdso/vdso.S b/arch/um/sys-x86_64/vdso/vdso.S new file mode 100644 index 000000000000..ec82c1686bd6 --- /dev/null +++ b/arch/um/sys-x86_64/vdso/vdso.S | |||
@@ -0,0 +1,10 @@ | |||
1 | #include <linux/init.h> | ||
2 | |||
3 | __INITDATA | ||
4 | |||
5 | .globl vdso_start, vdso_end | ||
6 | vdso_start: | ||
7 | .incbin "arch/um/sys-x86_64/vdso/vdso.so" | ||
8 | vdso_end: | ||
9 | |||
10 | __FINIT | ||
diff --git a/arch/um/sys-x86_64/vdso/vdso.lds.S b/arch/um/sys-x86_64/vdso/vdso.lds.S new file mode 100644 index 000000000000..b96b2677cad8 --- /dev/null +++ b/arch/um/sys-x86_64/vdso/vdso.lds.S | |||
@@ -0,0 +1,32 @@ | |||
1 | /* | ||
2 | * Linker script for 64-bit vDSO. | ||
3 | * We #include the file to define the layout details. | ||
4 | * Here we only choose the prelinked virtual address. | ||
5 | * | ||
6 | * This file defines the version script giving the user-exported symbols in | ||
7 | * the DSO. We can define local symbols here called VDSO* to make their | ||
8 | * values visible using the asm-x86/vdso.h macros from the kernel proper. | ||
9 | */ | ||
10 | |||
11 | #define VDSO_PRELINK 0xffffffffff700000 | ||
12 | #include "vdso-layout.lds.S" | ||
13 | |||
14 | /* | ||
15 | * This controls what userland symbols we export from the vDSO. | ||
16 | */ | ||
17 | VERSION { | ||
18 | LINUX_2.6 { | ||
19 | global: | ||
20 | clock_gettime; | ||
21 | __vdso_clock_gettime; | ||
22 | gettimeofday; | ||
23 | __vdso_gettimeofday; | ||
24 | getcpu; | ||
25 | __vdso_getcpu; | ||
26 | time; | ||
27 | __vdso_time; | ||
28 | local: *; | ||
29 | }; | ||
30 | } | ||
31 | |||
32 | VDSO64_PRELINK = VDSO_PRELINK; | ||
diff --git a/arch/um/sys-x86_64/vdso/vma.c b/arch/um/sys-x86_64/vdso/vma.c new file mode 100644 index 000000000000..9495c8d0ce37 --- /dev/null +++ b/arch/um/sys-x86_64/vdso/vma.c | |||
@@ -0,0 +1,74 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2011 Richard Weinberger <richrd@nod.at> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | */ | ||
8 | |||
9 | #include <linux/slab.h> | ||
10 | #include <linux/sched.h> | ||
11 | #include <linux/mm.h> | ||
12 | #include <asm/page.h> | ||
13 | #include <linux/init.h> | ||
14 | |||
15 | unsigned int __read_mostly vdso_enabled = 1; | ||
16 | unsigned long um_vdso_addr; | ||
17 | |||
18 | extern unsigned long task_size; | ||
19 | extern char vdso_start[], vdso_end[]; | ||
20 | |||
21 | static struct page **vdsop; | ||
22 | |||
23 | static int __init init_vdso(void) | ||
24 | { | ||
25 | struct page *um_vdso; | ||
26 | |||
27 | BUG_ON(vdso_end - vdso_start > PAGE_SIZE); | ||
28 | |||
29 | um_vdso_addr = task_size - PAGE_SIZE; | ||
30 | |||
31 | vdsop = kmalloc(GFP_KERNEL, sizeof(struct page *)); | ||
32 | if (!vdsop) | ||
33 | goto oom; | ||
34 | |||
35 | um_vdso = alloc_page(GFP_KERNEL); | ||
36 | if (!um_vdso) { | ||
37 | kfree(vdsop); | ||
38 | |||
39 | goto oom; | ||
40 | } | ||
41 | |||
42 | copy_page(page_address(um_vdso), vdso_start); | ||
43 | *vdsop = um_vdso; | ||
44 | |||
45 | return 0; | ||
46 | |||
47 | oom: | ||
48 | printk(KERN_ERR "Cannot allocate vdso\n"); | ||
49 | vdso_enabled = 0; | ||
50 | |||
51 | return -ENOMEM; | ||
52 | } | ||
53 | subsys_initcall(init_vdso); | ||
54 | |||
55 | int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp) | ||
56 | { | ||
57 | int err; | ||
58 | struct mm_struct *mm = current->mm; | ||
59 | |||
60 | if (!vdso_enabled) | ||
61 | return 0; | ||
62 | |||
63 | down_write(&mm->mmap_sem); | ||
64 | |||
65 | err = install_special_mapping(mm, um_vdso_addr, PAGE_SIZE, | ||
66 | VM_READ|VM_EXEC| | ||
67 | VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC| | ||
68 | VM_ALWAYSDUMP, | ||
69 | vdsop); | ||
70 | |||
71 | up_write(&mm->mmap_sem); | ||
72 | |||
73 | return err; | ||
74 | } | ||
diff --git a/arch/xtensa/include/asm/uaccess.h b/arch/xtensa/include/asm/uaccess.h index 82d4e3815c89..3fa526fd3c99 100644 --- a/arch/xtensa/include/asm/uaccess.h +++ b/arch/xtensa/include/asm/uaccess.h | |||
@@ -17,6 +17,7 @@ | |||
17 | #define _XTENSA_UACCESS_H | 17 | #define _XTENSA_UACCESS_H |
18 | 18 | ||
19 | #include <linux/errno.h> | 19 | #include <linux/errno.h> |
20 | #include <linux/prefetch.h> | ||
20 | #include <asm/types.h> | 21 | #include <asm/types.h> |
21 | 22 | ||
22 | #define VERIFY_READ 0 | 23 | #define VERIFY_READ 0 |
diff --git a/arch/xtensa/kernel/ptrace.c b/arch/xtensa/kernel/ptrace.c index c72c9473ef99..a0d042aa2967 100644 --- a/arch/xtensa/kernel/ptrace.c +++ b/arch/xtensa/kernel/ptrace.c | |||
@@ -147,6 +147,9 @@ int ptrace_setxregs(struct task_struct *child, void __user *uregs) | |||
147 | elf_xtregs_t *xtregs = uregs; | 147 | elf_xtregs_t *xtregs = uregs; |
148 | int ret = 0; | 148 | int ret = 0; |
149 | 149 | ||
150 | if (!access_ok(VERIFY_READ, uregs, sizeof(elf_xtregs_t))) | ||
151 | return -EFAULT; | ||
152 | |||
150 | #if XTENSA_HAVE_COPROCESSORS | 153 | #if XTENSA_HAVE_COPROCESSORS |
151 | /* Flush all coprocessors before we overwrite them. */ | 154 | /* Flush all coprocessors before we overwrite them. */ |
152 | coprocessor_flush_all(ti); | 155 | coprocessor_flush_all(ti); |
diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c index b02c4ffa4db0..0a9a774a7e1e 100644 --- a/drivers/ata/sata_dwc_460ex.c +++ b/drivers/ata/sata_dwc_460ex.c | |||
@@ -1642,13 +1642,12 @@ static int sata_dwc_probe(struct platform_device *ofdev) | |||
1642 | const struct ata_port_info *ppi[] = { &pi, NULL }; | 1642 | const struct ata_port_info *ppi[] = { &pi, NULL }; |
1643 | 1643 | ||
1644 | /* Allocate DWC SATA device */ | 1644 | /* Allocate DWC SATA device */ |
1645 | hsdev = kmalloc(sizeof(*hsdev), GFP_KERNEL); | 1645 | hsdev = kzalloc(sizeof(*hsdev), GFP_KERNEL); |
1646 | if (hsdev == NULL) { | 1646 | if (hsdev == NULL) { |
1647 | dev_err(&ofdev->dev, "kmalloc failed for hsdev\n"); | 1647 | dev_err(&ofdev->dev, "kmalloc failed for hsdev\n"); |
1648 | err = -ENOMEM; | 1648 | err = -ENOMEM; |
1649 | goto error; | 1649 | goto error; |
1650 | } | 1650 | } |
1651 | memset(hsdev, 0, sizeof(*hsdev)); | ||
1652 | 1651 | ||
1653 | /* Ioremap SATA registers */ | 1652 | /* Ioremap SATA registers */ |
1654 | base = of_iomap(ofdev->dev.of_node, 0); | 1653 | base = of_iomap(ofdev->dev.of_node, 0); |
diff --git a/drivers/connector/cn_proc.c b/drivers/connector/cn_proc.c index 281902d3f7ec..0debc17c8e28 100644 --- a/drivers/connector/cn_proc.c +++ b/drivers/connector/cn_proc.c | |||
@@ -173,7 +173,6 @@ void proc_ptrace_connector(struct task_struct *task, int ptrace_id) | |||
173 | struct proc_event *ev; | 173 | struct proc_event *ev; |
174 | struct timespec ts; | 174 | struct timespec ts; |
175 | __u8 buffer[CN_PROC_MSG_SIZE]; | 175 | __u8 buffer[CN_PROC_MSG_SIZE]; |
176 | struct task_struct *tracer; | ||
177 | 176 | ||
178 | if (atomic_read(&proc_event_num_listeners) < 1) | 177 | if (atomic_read(&proc_event_num_listeners) < 1) |
179 | return; | 178 | return; |
diff --git a/drivers/eisa/pci_eisa.c b/drivers/eisa/pci_eisa.c index 0dd0f633b18d..30da70d06a6d 100644 --- a/drivers/eisa/pci_eisa.c +++ b/drivers/eisa/pci_eisa.c | |||
@@ -45,13 +45,13 @@ static int __init pci_eisa_init(struct pci_dev *pdev, | |||
45 | return 0; | 45 | return 0; |
46 | } | 46 | } |
47 | 47 | ||
48 | static struct pci_device_id pci_eisa_pci_tbl[] = { | 48 | static struct pci_device_id __initdata pci_eisa_pci_tbl[] = { |
49 | { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, | 49 | { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, |
50 | PCI_CLASS_BRIDGE_EISA << 8, 0xffff00, 0 }, | 50 | PCI_CLASS_BRIDGE_EISA << 8, 0xffff00, 0 }, |
51 | { 0, } | 51 | { 0, } |
52 | }; | 52 | }; |
53 | 53 | ||
54 | static struct pci_driver pci_eisa_driver = { | 54 | static struct pci_driver __initdata pci_eisa_driver = { |
55 | .name = "pci_eisa", | 55 | .name = "pci_eisa", |
56 | .id_table = pci_eisa_pci_tbl, | 56 | .id_table = pci_eisa_pci_tbl, |
57 | .probe = pci_eisa_init, | 57 | .probe = pci_eisa_init, |
diff --git a/drivers/firmware/sigma.c b/drivers/firmware/sigma.c index c19cd2c39fa6..f10fc521951b 100644 --- a/drivers/firmware/sigma.c +++ b/drivers/firmware/sigma.c | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <linux/firmware.h> | 11 | #include <linux/firmware.h> |
12 | #include <linux/kernel.h> | 12 | #include <linux/kernel.h> |
13 | #include <linux/i2c.h> | 13 | #include <linux/i2c.h> |
14 | #include <linux/module.h> | ||
14 | #include <linux/sigma.h> | 15 | #include <linux/sigma.h> |
15 | 16 | ||
16 | /* Return: 0==OK, <0==error, =1 ==no more actions */ | 17 | /* Return: 0==OK, <0==error, =1 ==no more actions */ |
@@ -113,3 +114,5 @@ int process_sigma_firmware(struct i2c_client *client, const char *name) | |||
113 | return ret; | 114 | return ret; |
114 | } | 115 | } |
115 | EXPORT_SYMBOL(process_sigma_firmware); | 116 | EXPORT_SYMBOL(process_sigma_firmware); |
117 | |||
118 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/gpu/drm/drm_scatter.c b/drivers/gpu/drm/drm_scatter.c index d15e09b0ae0b..7525e0311e59 100644 --- a/drivers/gpu/drm/drm_scatter.c +++ b/drivers/gpu/drm/drm_scatter.c | |||
@@ -83,30 +83,26 @@ int drm_sg_alloc(struct drm_device *dev, struct drm_scatter_gather * request) | |||
83 | if (dev->sg) | 83 | if (dev->sg) |
84 | return -EINVAL; | 84 | return -EINVAL; |
85 | 85 | ||
86 | entry = kmalloc(sizeof(*entry), GFP_KERNEL); | 86 | entry = kzalloc(sizeof(*entry), GFP_KERNEL); |
87 | if (!entry) | 87 | if (!entry) |
88 | return -ENOMEM; | 88 | return -ENOMEM; |
89 | 89 | ||
90 | memset(entry, 0, sizeof(*entry)); | ||
91 | pages = (request->size + PAGE_SIZE - 1) / PAGE_SIZE; | 90 | pages = (request->size + PAGE_SIZE - 1) / PAGE_SIZE; |
92 | DRM_DEBUG("size=%ld pages=%ld\n", request->size, pages); | 91 | DRM_DEBUG("size=%ld pages=%ld\n", request->size, pages); |
93 | 92 | ||
94 | entry->pages = pages; | 93 | entry->pages = pages; |
95 | entry->pagelist = kmalloc(pages * sizeof(*entry->pagelist), GFP_KERNEL); | 94 | entry->pagelist = kcalloc(pages, sizeof(*entry->pagelist), GFP_KERNEL); |
96 | if (!entry->pagelist) { | 95 | if (!entry->pagelist) { |
97 | kfree(entry); | 96 | kfree(entry); |
98 | return -ENOMEM; | 97 | return -ENOMEM; |
99 | } | 98 | } |
100 | 99 | ||
101 | memset(entry->pagelist, 0, pages * sizeof(*entry->pagelist)); | 100 | entry->busaddr = kcalloc(pages, sizeof(*entry->busaddr), GFP_KERNEL); |
102 | |||
103 | entry->busaddr = kmalloc(pages * sizeof(*entry->busaddr), GFP_KERNEL); | ||
104 | if (!entry->busaddr) { | 101 | if (!entry->busaddr) { |
105 | kfree(entry->pagelist); | 102 | kfree(entry->pagelist); |
106 | kfree(entry); | 103 | kfree(entry); |
107 | return -ENOMEM; | 104 | return -ENOMEM; |
108 | } | 105 | } |
109 | memset((void *)entry->busaddr, 0, pages * sizeof(*entry->busaddr)); | ||
110 | 106 | ||
111 | entry->virtual = drm_vmalloc_dma(pages << PAGE_SHIFT); | 107 | entry->virtual = drm_vmalloc_dma(pages << PAGE_SHIFT); |
112 | if (!entry->virtual) { | 108 | if (!entry->virtual) { |
diff --git a/drivers/gpu/drm/radeon/radeon_mem.c b/drivers/gpu/drm/radeon/radeon_mem.c index ed95155c4b1d..988548efea92 100644 --- a/drivers/gpu/drm/radeon/radeon_mem.c +++ b/drivers/gpu/drm/radeon/radeon_mem.c | |||
@@ -139,7 +139,7 @@ static int init_heap(struct mem_block **heap, int start, int size) | |||
139 | if (!blocks) | 139 | if (!blocks) |
140 | return -ENOMEM; | 140 | return -ENOMEM; |
141 | 141 | ||
142 | *heap = kmalloc(sizeof(**heap), GFP_KERNEL); | 142 | *heap = kzalloc(sizeof(**heap), GFP_KERNEL); |
143 | if (!*heap) { | 143 | if (!*heap) { |
144 | kfree(blocks); | 144 | kfree(blocks); |
145 | return -ENOMEM; | 145 | return -ENOMEM; |
@@ -150,7 +150,6 @@ static int init_heap(struct mem_block **heap, int start, int size) | |||
150 | blocks->file_priv = NULL; | 150 | blocks->file_priv = NULL; |
151 | blocks->next = blocks->prev = *heap; | 151 | blocks->next = blocks->prev = *heap; |
152 | 152 | ||
153 | memset(*heap, 0, sizeof(**heap)); | ||
154 | (*heap)->file_priv = (struct drm_file *) - 1; | 153 | (*heap)->file_priv = (struct drm_file *) - 1; |
155 | (*heap)->next = (*heap)->prev = blocks; | 154 | (*heap)->next = (*heap)->prev = blocks; |
156 | return 0; | 155 | return 0; |
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c b/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c index f1a52f9e7298..07ce02da78a4 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c | |||
@@ -585,11 +585,10 @@ int vmw_overlay_init(struct vmw_private *dev_priv) | |||
585 | return -ENOSYS; | 585 | return -ENOSYS; |
586 | } | 586 | } |
587 | 587 | ||
588 | overlay = kmalloc(sizeof(*overlay), GFP_KERNEL); | 588 | overlay = kzalloc(sizeof(*overlay), GFP_KERNEL); |
589 | if (!overlay) | 589 | if (!overlay) |
590 | return -ENOMEM; | 590 | return -ENOMEM; |
591 | 591 | ||
592 | memset(overlay, 0, sizeof(*overlay)); | ||
593 | mutex_init(&overlay->mutex); | 592 | mutex_init(&overlay->mutex); |
594 | for (i = 0; i < VMW_MAX_NUM_STREAMS; i++) { | 593 | for (i = 0; i < VMW_MAX_NUM_STREAMS; i++) { |
595 | overlay->stream[i].buf = NULL; | 594 | overlay->stream[i].buf = NULL; |
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c index 5408b1b7996f..bfe1bcce7f8a 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c | |||
@@ -612,11 +612,9 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data, | |||
612 | srf->sizes[0].height == 64 && | 612 | srf->sizes[0].height == 64 && |
613 | srf->format == SVGA3D_A8R8G8B8) { | 613 | srf->format == SVGA3D_A8R8G8B8) { |
614 | 614 | ||
615 | srf->snooper.image = kmalloc(64 * 64 * 4, GFP_KERNEL); | 615 | /* allocate image area and clear it */ |
616 | /* clear the image */ | 616 | srf->snooper.image = kzalloc(64 * 64 * 4, GFP_KERNEL); |
617 | if (srf->snooper.image) { | 617 | if (!srf->snooper.image) { |
618 | memset(srf->snooper.image, 0x00, 64 * 64 * 4); | ||
619 | } else { | ||
620 | DRM_ERROR("Failed to allocate cursor_image\n"); | 618 | DRM_ERROR("Failed to allocate cursor_image\n"); |
621 | ret = -ENOMEM; | 619 | ret = -ENOMEM; |
622 | goto out_err1; | 620 | goto out_err1; |
diff --git a/drivers/gpu/vga/vgaarb.c b/drivers/gpu/vga/vgaarb.c index 8a1021f2e319..c72f1c0b5e63 100644 --- a/drivers/gpu/vga/vgaarb.c +++ b/drivers/gpu/vga/vgaarb.c | |||
@@ -1171,10 +1171,9 @@ static int vga_arb_open(struct inode *inode, struct file *file) | |||
1171 | 1171 | ||
1172 | pr_debug("%s\n", __func__); | 1172 | pr_debug("%s\n", __func__); |
1173 | 1173 | ||
1174 | priv = kmalloc(sizeof(struct vga_arb_private), GFP_KERNEL); | 1174 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); |
1175 | if (priv == NULL) | 1175 | if (priv == NULL) |
1176 | return -ENOMEM; | 1176 | return -ENOMEM; |
1177 | memset(priv, 0, sizeof(*priv)); | ||
1178 | spin_lock_init(&priv->lock); | 1177 | spin_lock_init(&priv->lock); |
1179 | file->private_data = priv; | 1178 | file->private_data = priv; |
1180 | 1179 | ||
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index 6c21c2986ca1..b591e726a6fa 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig | |||
@@ -365,6 +365,7 @@ config LEDS_NS2 | |||
365 | config LEDS_NETXBIG | 365 | config LEDS_NETXBIG |
366 | tristate "LED support for Big Network series LEDs" | 366 | tristate "LED support for Big Network series LEDs" |
367 | depends on MACH_NET2BIG_V2 || MACH_NET5BIG_V2 | 367 | depends on MACH_NET2BIG_V2 || MACH_NET5BIG_V2 |
368 | depends on LEDS_CLASS | ||
368 | default y | 369 | default y |
369 | help | 370 | help |
370 | This option enable support for LEDs found on the LaCie 2Big | 371 | This option enable support for LEDs found on the LaCie 2Big |
diff --git a/drivers/leds/leds-lm3530.c b/drivers/leds/leds-lm3530.c index 4d7ce7631acf..3dd7090a9a9b 100644 --- a/drivers/leds/leds-lm3530.c +++ b/drivers/leds/leds-lm3530.c | |||
@@ -68,17 +68,16 @@ | |||
68 | #define LM3530_ALS2_IMP_SHIFT (4) | 68 | #define LM3530_ALS2_IMP_SHIFT (4) |
69 | 69 | ||
70 | /* Zone Boundary Register defaults */ | 70 | /* Zone Boundary Register defaults */ |
71 | #define LM3530_DEF_ZB_0 (0x33) | 71 | #define LM3530_ALS_ZB_MAX (4) |
72 | #define LM3530_DEF_ZB_1 (0x66) | 72 | #define LM3530_ALS_WINDOW_mV (1000) |
73 | #define LM3530_DEF_ZB_2 (0x99) | 73 | #define LM3530_ALS_OFFSET_mV (4) |
74 | #define LM3530_DEF_ZB_3 (0xCC) | ||
75 | 74 | ||
76 | /* Zone Target Register defaults */ | 75 | /* Zone Target Register defaults */ |
77 | #define LM3530_DEF_ZT_0 (0x19) | 76 | #define LM3530_DEF_ZT_0 (0x7F) |
78 | #define LM3530_DEF_ZT_1 (0x33) | 77 | #define LM3530_DEF_ZT_1 (0x66) |
79 | #define LM3530_DEF_ZT_2 (0x4C) | 78 | #define LM3530_DEF_ZT_2 (0x4C) |
80 | #define LM3530_DEF_ZT_3 (0x66) | 79 | #define LM3530_DEF_ZT_3 (0x33) |
81 | #define LM3530_DEF_ZT_4 (0x7F) | 80 | #define LM3530_DEF_ZT_4 (0x19) |
82 | 81 | ||
83 | struct lm3530_mode_map { | 82 | struct lm3530_mode_map { |
84 | const char *mode; | 83 | const char *mode; |
@@ -150,6 +149,8 @@ static int lm3530_init_registers(struct lm3530_data *drvdata) | |||
150 | u8 als_imp_sel = 0; | 149 | u8 als_imp_sel = 0; |
151 | u8 brightness; | 150 | u8 brightness; |
152 | u8 reg_val[LM3530_REG_MAX]; | 151 | u8 reg_val[LM3530_REG_MAX]; |
152 | u8 zones[LM3530_ALS_ZB_MAX]; | ||
153 | u32 als_vmin, als_vmax, als_vstep; | ||
153 | struct lm3530_platform_data *pltfm = drvdata->pdata; | 154 | struct lm3530_platform_data *pltfm = drvdata->pdata; |
154 | struct i2c_client *client = drvdata->client; | 155 | struct i2c_client *client = drvdata->client; |
155 | 156 | ||
@@ -161,6 +162,26 @@ static int lm3530_init_registers(struct lm3530_data *drvdata) | |||
161 | gen_config |= (LM3530_ENABLE_I2C); | 162 | gen_config |= (LM3530_ENABLE_I2C); |
162 | 163 | ||
163 | if (drvdata->mode == LM3530_BL_MODE_ALS) { | 164 | if (drvdata->mode == LM3530_BL_MODE_ALS) { |
165 | if (pltfm->als_vmax == 0) { | ||
166 | pltfm->als_vmin = als_vmin = 0; | ||
167 | pltfm->als_vmin = als_vmax = LM3530_ALS_WINDOW_mV; | ||
168 | } | ||
169 | |||
170 | als_vmin = pltfm->als_vmin; | ||
171 | als_vmax = pltfm->als_vmax; | ||
172 | |||
173 | if ((als_vmax - als_vmin) > LM3530_ALS_WINDOW_mV) | ||
174 | pltfm->als_vmax = als_vmax = | ||
175 | als_vmin + LM3530_ALS_WINDOW_mV; | ||
176 | |||
177 | /* n zone boundary makes n+1 zones */ | ||
178 | als_vstep = (als_vmax - als_vmin) / (LM3530_ALS_ZB_MAX + 1); | ||
179 | |||
180 | for (i = 0; i < LM3530_ALS_ZB_MAX; i++) | ||
181 | zones[i] = (((als_vmin + LM3530_ALS_OFFSET_mV) + | ||
182 | als_vstep + (i * als_vstep)) * LED_FULL) | ||
183 | / 1000; | ||
184 | |||
164 | als_config = | 185 | als_config = |
165 | (pltfm->als_avrg_time << LM3530_ALS_AVG_TIME_SHIFT) | | 186 | (pltfm->als_avrg_time << LM3530_ALS_AVG_TIME_SHIFT) | |
166 | (LM3530_ENABLE_ALS) | | 187 | (LM3530_ENABLE_ALS) | |
@@ -169,6 +190,7 @@ static int lm3530_init_registers(struct lm3530_data *drvdata) | |||
169 | als_imp_sel = | 190 | als_imp_sel = |
170 | (pltfm->als1_resistor_sel << LM3530_ALS1_IMP_SHIFT) | | 191 | (pltfm->als1_resistor_sel << LM3530_ALS1_IMP_SHIFT) | |
171 | (pltfm->als2_resistor_sel << LM3530_ALS2_IMP_SHIFT); | 192 | (pltfm->als2_resistor_sel << LM3530_ALS2_IMP_SHIFT); |
193 | |||
172 | } | 194 | } |
173 | 195 | ||
174 | if (drvdata->mode == LM3530_BL_MODE_PWM) | 196 | if (drvdata->mode == LM3530_BL_MODE_PWM) |
@@ -190,10 +212,10 @@ static int lm3530_init_registers(struct lm3530_data *drvdata) | |||
190 | reg_val[3] = 0x00; /* LM3530_ALS_ZONE_REG */ | 212 | reg_val[3] = 0x00; /* LM3530_ALS_ZONE_REG */ |
191 | reg_val[4] = als_imp_sel; /* LM3530_ALS_IMP_SELECT */ | 213 | reg_val[4] = als_imp_sel; /* LM3530_ALS_IMP_SELECT */ |
192 | reg_val[5] = brightness; /* LM3530_BRT_CTRL_REG */ | 214 | reg_val[5] = brightness; /* LM3530_BRT_CTRL_REG */ |
193 | reg_val[6] = LM3530_DEF_ZB_0; /* LM3530_ALS_ZB0_REG */ | 215 | reg_val[6] = zones[0]; /* LM3530_ALS_ZB0_REG */ |
194 | reg_val[7] = LM3530_DEF_ZB_1; /* LM3530_ALS_ZB1_REG */ | 216 | reg_val[7] = zones[1]; /* LM3530_ALS_ZB1_REG */ |
195 | reg_val[8] = LM3530_DEF_ZB_2; /* LM3530_ALS_ZB2_REG */ | 217 | reg_val[8] = zones[2]; /* LM3530_ALS_ZB2_REG */ |
196 | reg_val[9] = LM3530_DEF_ZB_3; /* LM3530_ALS_ZB3_REG */ | 218 | reg_val[9] = zones[3]; /* LM3530_ALS_ZB3_REG */ |
197 | reg_val[10] = LM3530_DEF_ZT_0; /* LM3530_ALS_Z0T_REG */ | 219 | reg_val[10] = LM3530_DEF_ZT_0; /* LM3530_ALS_Z0T_REG */ |
198 | reg_val[11] = LM3530_DEF_ZT_1; /* LM3530_ALS_Z1T_REG */ | 220 | reg_val[11] = LM3530_DEF_ZT_1; /* LM3530_ALS_Z1T_REG */ |
199 | reg_val[12] = LM3530_DEF_ZT_2; /* LM3530_ALS_Z2T_REG */ | 221 | reg_val[12] = LM3530_DEF_ZT_2; /* LM3530_ALS_Z2T_REG */ |
@@ -265,6 +287,24 @@ static void lm3530_brightness_set(struct led_classdev *led_cdev, | |||
265 | } | 287 | } |
266 | } | 288 | } |
267 | 289 | ||
290 | static ssize_t lm3530_mode_get(struct device *dev, | ||
291 | struct device_attribute *attr, char *buf) | ||
292 | { | ||
293 | struct i2c_client *client = container_of( | ||
294 | dev->parent, struct i2c_client, dev); | ||
295 | struct lm3530_data *drvdata = i2c_get_clientdata(client); | ||
296 | int i, len = 0; | ||
297 | |||
298 | for (i = 0; i < ARRAY_SIZE(mode_map); i++) | ||
299 | if (drvdata->mode == mode_map[i].mode_val) | ||
300 | len += sprintf(buf + len, "[%s] ", mode_map[i].mode); | ||
301 | else | ||
302 | len += sprintf(buf + len, "%s ", mode_map[i].mode); | ||
303 | |||
304 | len += sprintf(buf + len, "\n"); | ||
305 | |||
306 | return len; | ||
307 | } | ||
268 | 308 | ||
269 | static ssize_t lm3530_mode_set(struct device *dev, struct device_attribute | 309 | static ssize_t lm3530_mode_set(struct device *dev, struct device_attribute |
270 | *attr, const char *buf, size_t size) | 310 | *attr, const char *buf, size_t size) |
@@ -298,8 +338,7 @@ static ssize_t lm3530_mode_set(struct device *dev, struct device_attribute | |||
298 | 338 | ||
299 | return sizeof(drvdata->mode); | 339 | return sizeof(drvdata->mode); |
300 | } | 340 | } |
301 | 341 | static DEVICE_ATTR(mode, 0644, lm3530_mode_get, lm3530_mode_set); | |
302 | static DEVICE_ATTR(mode, 0644, NULL, lm3530_mode_set); | ||
303 | 342 | ||
304 | static int __devinit lm3530_probe(struct i2c_client *client, | 343 | static int __devinit lm3530_probe(struct i2c_client *client, |
305 | const struct i2c_device_id *id) | 344 | const struct i2c_device_id *id) |
diff --git a/drivers/leds/leds-lp5521.c b/drivers/leds/leds-lp5521.c index cc1dc4817fac..9fc122c81f06 100644 --- a/drivers/leds/leds-lp5521.c +++ b/drivers/leds/leds-lp5521.c | |||
@@ -744,7 +744,7 @@ fail1: | |||
744 | return ret; | 744 | return ret; |
745 | } | 745 | } |
746 | 746 | ||
747 | static int lp5521_remove(struct i2c_client *client) | 747 | static int __devexit lp5521_remove(struct i2c_client *client) |
748 | { | 748 | { |
749 | struct lp5521_chip *chip = i2c_get_clientdata(client); | 749 | struct lp5521_chip *chip = i2c_get_clientdata(client); |
750 | int i; | 750 | int i; |
@@ -775,7 +775,7 @@ static struct i2c_driver lp5521_driver = { | |||
775 | .name = "lp5521", | 775 | .name = "lp5521", |
776 | }, | 776 | }, |
777 | .probe = lp5521_probe, | 777 | .probe = lp5521_probe, |
778 | .remove = lp5521_remove, | 778 | .remove = __devexit_p(lp5521_remove), |
779 | .id_table = lp5521_id, | 779 | .id_table = lp5521_id, |
780 | }; | 780 | }; |
781 | 781 | ||
diff --git a/drivers/leds/leds-sunfire.c b/drivers/leds/leds-sunfire.c index ab6d18f5c39f..1757396b20b3 100644 --- a/drivers/leds/leds-sunfire.c +++ b/drivers/leds/leds-sunfire.c | |||
@@ -127,17 +127,19 @@ static int __devinit sunfire_led_generic_probe(struct platform_device *pdev, | |||
127 | struct led_type *types) | 127 | struct led_type *types) |
128 | { | 128 | { |
129 | struct sunfire_drvdata *p; | 129 | struct sunfire_drvdata *p; |
130 | int i, err = -EINVAL; | 130 | int i, err; |
131 | 131 | ||
132 | if (pdev->num_resources != 1) { | 132 | if (pdev->num_resources != 1) { |
133 | printk(KERN_ERR PFX "Wrong number of resources %d, should be 1\n", | 133 | printk(KERN_ERR PFX "Wrong number of resources %d, should be 1\n", |
134 | pdev->num_resources); | 134 | pdev->num_resources); |
135 | err = -EINVAL; | ||
135 | goto out; | 136 | goto out; |
136 | } | 137 | } |
137 | 138 | ||
138 | p = kzalloc(sizeof(*p), GFP_KERNEL); | 139 | p = kzalloc(sizeof(*p), GFP_KERNEL); |
139 | if (!p) { | 140 | if (!p) { |
140 | printk(KERN_ERR PFX "Could not allocate struct sunfire_drvdata\n"); | 141 | printk(KERN_ERR PFX "Could not allocate struct sunfire_drvdata\n"); |
142 | err = -ENOMEM; | ||
141 | goto out; | 143 | goto out; |
142 | } | 144 | } |
143 | 145 | ||
@@ -160,14 +162,14 @@ static int __devinit sunfire_led_generic_probe(struct platform_device *pdev, | |||
160 | 162 | ||
161 | dev_set_drvdata(&pdev->dev, p); | 163 | dev_set_drvdata(&pdev->dev, p); |
162 | 164 | ||
163 | err = 0; | 165 | return 0; |
164 | out: | ||
165 | return err; | ||
166 | 166 | ||
167 | out_unregister_led_cdevs: | 167 | out_unregister_led_cdevs: |
168 | for (i--; i >= 0; i--) | 168 | for (i--; i >= 0; i--) |
169 | led_classdev_unregister(&p->leds[i].led_cdev); | 169 | led_classdev_unregister(&p->leds[i].led_cdev); |
170 | goto out; | 170 | kfree(p); |
171 | out: | ||
172 | return err; | ||
171 | } | 173 | } |
172 | 174 | ||
173 | static int __devexit sunfire_led_generic_remove(struct platform_device *pdev) | 175 | static int __devexit sunfire_led_generic_remove(struct platform_device *pdev) |
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 4e349cd98bcf..0a4d86c6c4a4 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig | |||
@@ -245,8 +245,7 @@ config SGI_XP | |||
245 | 245 | ||
246 | config CS5535_MFGPT | 246 | config CS5535_MFGPT |
247 | tristate "CS5535/CS5536 Geode Multi-Function General Purpose Timer (MFGPT) support" | 247 | tristate "CS5535/CS5536 Geode Multi-Function General Purpose Timer (MFGPT) support" |
248 | depends on PCI | 248 | depends on PCI && X86 && MFD_CS5535 |
249 | depends on X86 | ||
250 | default n | 249 | default n |
251 | help | 250 | help |
252 | This driver provides access to MFGPT functionality for other | 251 | This driver provides access to MFGPT functionality for other |
@@ -490,6 +489,15 @@ config PCH_PHUB | |||
490 | To compile this driver as a module, choose M here: the module will | 489 | To compile this driver as a module, choose M here: the module will |
491 | be called pch_phub. | 490 | be called pch_phub. |
492 | 491 | ||
492 | config USB_SWITCH_FSA9480 | ||
493 | tristate "FSA9480 USB Switch" | ||
494 | depends on I2C | ||
495 | help | ||
496 | The FSA9480 is a USB port accessory detector and switch. | ||
497 | The FSA9480 is fully controlled using I2C and enables USB data, | ||
498 | stereo and mono audio, video, microphone and UART data to use | ||
499 | a common connector port. | ||
500 | |||
493 | source "drivers/misc/c2port/Kconfig" | 501 | source "drivers/misc/c2port/Kconfig" |
494 | source "drivers/misc/eeprom/Kconfig" | 502 | source "drivers/misc/eeprom/Kconfig" |
495 | source "drivers/misc/cb710/Kconfig" | 503 | source "drivers/misc/cb710/Kconfig" |
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 5f03172cc0b5..33282157bc3c 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile | |||
@@ -46,3 +46,4 @@ obj-y += ti-st/ | |||
46 | obj-$(CONFIG_AB8500_PWM) += ab8500-pwm.o | 46 | obj-$(CONFIG_AB8500_PWM) += ab8500-pwm.o |
47 | obj-y += lis3lv02d/ | 47 | obj-y += lis3lv02d/ |
48 | obj-y += carma/ | 48 | obj-y += carma/ |
49 | obj-$(CONFIG_USB_SWITCH_FSA9480) += fsa9480.o | ||
diff --git a/drivers/misc/eeprom/Kconfig b/drivers/misc/eeprom/Kconfig index 9118613af321..26cf12ca7f50 100644 --- a/drivers/misc/eeprom/Kconfig +++ b/drivers/misc/eeprom/Kconfig | |||
@@ -70,4 +70,29 @@ config EEPROM_93CX6 | |||
70 | 70 | ||
71 | If unsure, say N. | 71 | If unsure, say N. |
72 | 72 | ||
73 | config EEPROM_93XX46 | ||
74 | tristate "Microwire EEPROM 93XX46 support" | ||
75 | depends on SPI && SYSFS | ||
76 | help | ||
77 | Driver for the microwire EEPROM chipsets 93xx46x. The driver | ||
78 | supports both read and write commands and also the command to | ||
79 | erase the whole EEPROM. | ||
80 | |||
81 | This driver can also be built as a module. If so, the module | ||
82 | will be called eeprom_93xx46. | ||
83 | |||
84 | If unsure, say N. | ||
85 | |||
86 | config EEPROM_DIGSY_MTC_CFG | ||
87 | bool "DigsyMTC display configuration EEPROMs device" | ||
88 | depends on PPC_MPC5200_GPIO && GPIOLIB && SPI_GPIO | ||
89 | help | ||
90 | This option enables access to display configuration EEPROMs | ||
91 | on digsy_mtc board. You have to additionally select Microwire | ||
92 | EEPROM 93XX46 driver. sysfs entries will be created for that | ||
93 | EEPROM allowing to read/write the configuration data or to | ||
94 | erase the whole EEPROM. | ||
95 | |||
96 | If unsure, say N. | ||
97 | |||
73 | endmenu | 98 | endmenu |
diff --git a/drivers/misc/eeprom/Makefile b/drivers/misc/eeprom/Makefile index df3d68ffa9d1..fc1e81d29267 100644 --- a/drivers/misc/eeprom/Makefile +++ b/drivers/misc/eeprom/Makefile | |||
@@ -3,3 +3,5 @@ obj-$(CONFIG_EEPROM_AT25) += at25.o | |||
3 | obj-$(CONFIG_EEPROM_LEGACY) += eeprom.o | 3 | obj-$(CONFIG_EEPROM_LEGACY) += eeprom.o |
4 | obj-$(CONFIG_EEPROM_MAX6875) += max6875.o | 4 | obj-$(CONFIG_EEPROM_MAX6875) += max6875.o |
5 | obj-$(CONFIG_EEPROM_93CX6) += eeprom_93cx6.o | 5 | obj-$(CONFIG_EEPROM_93CX6) += eeprom_93cx6.o |
6 | obj-$(CONFIG_EEPROM_93XX46) += eeprom_93xx46.o | ||
7 | obj-$(CONFIG_EEPROM_DIGSY_MTC_CFG) += digsy_mtc_eeprom.o | ||
diff --git a/drivers/misc/eeprom/digsy_mtc_eeprom.c b/drivers/misc/eeprom/digsy_mtc_eeprom.c new file mode 100644 index 000000000000..66d9e1baeae5 --- /dev/null +++ b/drivers/misc/eeprom/digsy_mtc_eeprom.c | |||
@@ -0,0 +1,85 @@ | |||
1 | /* | ||
2 | * EEPROMs access control driver for display configuration EEPROMs | ||
3 | * on DigsyMTC board. | ||
4 | * | ||
5 | * (C) 2011 DENX Software Engineering, Anatolij Gustschin <agust@denx.de> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #include <linux/gpio.h> | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/platform_device.h> | ||
15 | #include <linux/spi/spi.h> | ||
16 | #include <linux/spi/spi_gpio.h> | ||
17 | #include <linux/eeprom_93xx46.h> | ||
18 | |||
19 | #define GPIO_EEPROM_CLK 216 | ||
20 | #define GPIO_EEPROM_CS 210 | ||
21 | #define GPIO_EEPROM_DI 217 | ||
22 | #define GPIO_EEPROM_DO 249 | ||
23 | #define GPIO_EEPROM_OE 255 | ||
24 | #define EE_SPI_BUS_NUM 1 | ||
25 | |||
26 | static void digsy_mtc_op_prepare(void *p) | ||
27 | { | ||
28 | /* enable */ | ||
29 | gpio_set_value(GPIO_EEPROM_OE, 0); | ||
30 | } | ||
31 | |||
32 | static void digsy_mtc_op_finish(void *p) | ||
33 | { | ||
34 | /* disable */ | ||
35 | gpio_set_value(GPIO_EEPROM_OE, 1); | ||
36 | } | ||
37 | |||
38 | struct eeprom_93xx46_platform_data digsy_mtc_eeprom_data = { | ||
39 | .flags = EE_ADDR8, | ||
40 | .prepare = digsy_mtc_op_prepare, | ||
41 | .finish = digsy_mtc_op_finish, | ||
42 | }; | ||
43 | |||
44 | static struct spi_gpio_platform_data eeprom_spi_gpio_data = { | ||
45 | .sck = GPIO_EEPROM_CLK, | ||
46 | .mosi = GPIO_EEPROM_DI, | ||
47 | .miso = GPIO_EEPROM_DO, | ||
48 | .num_chipselect = 1, | ||
49 | }; | ||
50 | |||
51 | static struct platform_device digsy_mtc_eeprom = { | ||
52 | .name = "spi_gpio", | ||
53 | .id = EE_SPI_BUS_NUM, | ||
54 | .dev = { | ||
55 | .platform_data = &eeprom_spi_gpio_data, | ||
56 | }, | ||
57 | }; | ||
58 | |||
59 | static struct spi_board_info digsy_mtc_eeprom_info[] __initdata = { | ||
60 | { | ||
61 | .modalias = "93xx46", | ||
62 | .max_speed_hz = 1000000, | ||
63 | .bus_num = EE_SPI_BUS_NUM, | ||
64 | .chip_select = 0, | ||
65 | .mode = SPI_MODE_0, | ||
66 | .controller_data = (void *)GPIO_EEPROM_CS, | ||
67 | .platform_data = &digsy_mtc_eeprom_data, | ||
68 | }, | ||
69 | }; | ||
70 | |||
71 | static int __init digsy_mtc_eeprom_devices_init(void) | ||
72 | { | ||
73 | int ret; | ||
74 | |||
75 | ret = gpio_request_one(GPIO_EEPROM_OE, GPIOF_OUT_INIT_HIGH, | ||
76 | "93xx46 EEPROMs OE"); | ||
77 | if (ret) { | ||
78 | pr_err("can't request gpio %d\n", GPIO_EEPROM_OE); | ||
79 | return ret; | ||
80 | } | ||
81 | spi_register_board_info(digsy_mtc_eeprom_info, | ||
82 | ARRAY_SIZE(digsy_mtc_eeprom_info)); | ||
83 | return platform_device_register(&digsy_mtc_eeprom); | ||
84 | } | ||
85 | device_initcall(digsy_mtc_eeprom_devices_init); | ||
diff --git a/drivers/misc/eeprom/eeprom_93xx46.c b/drivers/misc/eeprom/eeprom_93xx46.c new file mode 100644 index 000000000000..0c7ebb1e19e5 --- /dev/null +++ b/drivers/misc/eeprom/eeprom_93xx46.c | |||
@@ -0,0 +1,410 @@ | |||
1 | /* | ||
2 | * Driver for 93xx46 EEPROMs | ||
3 | * | ||
4 | * (C) 2011 DENX Software Engineering, Anatolij Gustschin <agust@denx.de> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #include <linux/delay.h> | ||
12 | #include <linux/device.h> | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/module.h> | ||
16 | #include <linux/mutex.h> | ||
17 | #include <linux/slab.h> | ||
18 | #include <linux/spi/spi.h> | ||
19 | #include <linux/sysfs.h> | ||
20 | #include <linux/eeprom_93xx46.h> | ||
21 | |||
22 | #define OP_START 0x4 | ||
23 | #define OP_WRITE (OP_START | 0x1) | ||
24 | #define OP_READ (OP_START | 0x2) | ||
25 | #define ADDR_EWDS 0x00 | ||
26 | #define ADDR_ERAL 0x20 | ||
27 | #define ADDR_EWEN 0x30 | ||
28 | |||
29 | struct eeprom_93xx46_dev { | ||
30 | struct spi_device *spi; | ||
31 | struct eeprom_93xx46_platform_data *pdata; | ||
32 | struct bin_attribute bin; | ||
33 | struct mutex lock; | ||
34 | int addrlen; | ||
35 | }; | ||
36 | |||
37 | static ssize_t | ||
38 | eeprom_93xx46_bin_read(struct file *filp, struct kobject *kobj, | ||
39 | struct bin_attribute *bin_attr, | ||
40 | char *buf, loff_t off, size_t count) | ||
41 | { | ||
42 | struct eeprom_93xx46_dev *edev; | ||
43 | struct device *dev; | ||
44 | struct spi_message m; | ||
45 | struct spi_transfer t[2]; | ||
46 | int bits, ret; | ||
47 | u16 cmd_addr; | ||
48 | |||
49 | dev = container_of(kobj, struct device, kobj); | ||
50 | edev = dev_get_drvdata(dev); | ||
51 | |||
52 | if (unlikely(off >= edev->bin.size)) | ||
53 | return 0; | ||
54 | if ((off + count) > edev->bin.size) | ||
55 | count = edev->bin.size - off; | ||
56 | if (unlikely(!count)) | ||
57 | return count; | ||
58 | |||
59 | cmd_addr = OP_READ << edev->addrlen; | ||
60 | |||
61 | if (edev->addrlen == 7) { | ||
62 | cmd_addr |= off & 0x7f; | ||
63 | bits = 10; | ||
64 | } else { | ||
65 | cmd_addr |= off & 0x3f; | ||
66 | bits = 9; | ||
67 | } | ||
68 | |||
69 | dev_dbg(&edev->spi->dev, "read cmd 0x%x, %d Hz\n", | ||
70 | cmd_addr, edev->spi->max_speed_hz); | ||
71 | |||
72 | spi_message_init(&m); | ||
73 | memset(t, 0, sizeof(t)); | ||
74 | |||
75 | t[0].tx_buf = (char *)&cmd_addr; | ||
76 | t[0].len = 2; | ||
77 | t[0].bits_per_word = bits; | ||
78 | spi_message_add_tail(&t[0], &m); | ||
79 | |||
80 | t[1].rx_buf = buf; | ||
81 | t[1].len = count; | ||
82 | t[1].bits_per_word = 8; | ||
83 | spi_message_add_tail(&t[1], &m); | ||
84 | |||
85 | mutex_lock(&edev->lock); | ||
86 | |||
87 | if (edev->pdata->prepare) | ||
88 | edev->pdata->prepare(edev); | ||
89 | |||
90 | ret = spi_sync(edev->spi, &m); | ||
91 | /* have to wait at least Tcsl ns */ | ||
92 | ndelay(250); | ||
93 | if (ret) { | ||
94 | dev_err(&edev->spi->dev, "read %zu bytes at %d: err. %d\n", | ||
95 | count, (int)off, ret); | ||
96 | } | ||
97 | |||
98 | if (edev->pdata->finish) | ||
99 | edev->pdata->finish(edev); | ||
100 | |||
101 | mutex_unlock(&edev->lock); | ||
102 | return ret ? : count; | ||
103 | } | ||
104 | |||
105 | static int eeprom_93xx46_ew(struct eeprom_93xx46_dev *edev, int is_on) | ||
106 | { | ||
107 | struct spi_message m; | ||
108 | struct spi_transfer t; | ||
109 | int bits, ret; | ||
110 | u16 cmd_addr; | ||
111 | |||
112 | cmd_addr = OP_START << edev->addrlen; | ||
113 | if (edev->addrlen == 7) { | ||
114 | cmd_addr |= (is_on ? ADDR_EWEN : ADDR_EWDS) << 1; | ||
115 | bits = 10; | ||
116 | } else { | ||
117 | cmd_addr |= (is_on ? ADDR_EWEN : ADDR_EWDS); | ||
118 | bits = 9; | ||
119 | } | ||
120 | |||
121 | dev_dbg(&edev->spi->dev, "ew cmd 0x%04x\n", cmd_addr); | ||
122 | |||
123 | spi_message_init(&m); | ||
124 | memset(&t, 0, sizeof(t)); | ||
125 | |||
126 | t.tx_buf = &cmd_addr; | ||
127 | t.len = 2; | ||
128 | t.bits_per_word = bits; | ||
129 | spi_message_add_tail(&t, &m); | ||
130 | |||
131 | mutex_lock(&edev->lock); | ||
132 | |||
133 | if (edev->pdata->prepare) | ||
134 | edev->pdata->prepare(edev); | ||
135 | |||
136 | ret = spi_sync(edev->spi, &m); | ||
137 | /* have to wait at least Tcsl ns */ | ||
138 | ndelay(250); | ||
139 | if (ret) | ||
140 | dev_err(&edev->spi->dev, "erase/write %sable error %d\n", | ||
141 | is_on ? "en" : "dis", ret); | ||
142 | |||
143 | if (edev->pdata->finish) | ||
144 | edev->pdata->finish(edev); | ||
145 | |||
146 | mutex_unlock(&edev->lock); | ||
147 | return ret; | ||
148 | } | ||
149 | |||
150 | static ssize_t | ||
151 | eeprom_93xx46_write_word(struct eeprom_93xx46_dev *edev, | ||
152 | const char *buf, unsigned off) | ||
153 | { | ||
154 | struct spi_message m; | ||
155 | struct spi_transfer t[2]; | ||
156 | int bits, data_len, ret; | ||
157 | u16 cmd_addr; | ||
158 | |||
159 | cmd_addr = OP_WRITE << edev->addrlen; | ||
160 | |||
161 | if (edev->addrlen == 7) { | ||
162 | cmd_addr |= off & 0x7f; | ||
163 | bits = 10; | ||
164 | data_len = 1; | ||
165 | } else { | ||
166 | cmd_addr |= off & 0x3f; | ||
167 | bits = 9; | ||
168 | data_len = 2; | ||
169 | } | ||
170 | |||
171 | dev_dbg(&edev->spi->dev, "write cmd 0x%x\n", cmd_addr); | ||
172 | |||
173 | spi_message_init(&m); | ||
174 | memset(t, 0, sizeof(t)); | ||
175 | |||
176 | t[0].tx_buf = (char *)&cmd_addr; | ||
177 | t[0].len = 2; | ||
178 | t[0].bits_per_word = bits; | ||
179 | spi_message_add_tail(&t[0], &m); | ||
180 | |||
181 | t[1].tx_buf = buf; | ||
182 | t[1].len = data_len; | ||
183 | t[1].bits_per_word = 8; | ||
184 | spi_message_add_tail(&t[1], &m); | ||
185 | |||
186 | ret = spi_sync(edev->spi, &m); | ||
187 | /* have to wait program cycle time Twc ms */ | ||
188 | mdelay(6); | ||
189 | return ret; | ||
190 | } | ||
191 | |||
192 | static ssize_t | ||
193 | eeprom_93xx46_bin_write(struct file *filp, struct kobject *kobj, | ||
194 | struct bin_attribute *bin_attr, | ||
195 | char *buf, loff_t off, size_t count) | ||
196 | { | ||
197 | struct eeprom_93xx46_dev *edev; | ||
198 | struct device *dev; | ||
199 | int i, ret, step = 1; | ||
200 | |||
201 | dev = container_of(kobj, struct device, kobj); | ||
202 | edev = dev_get_drvdata(dev); | ||
203 | |||
204 | if (unlikely(off >= edev->bin.size)) | ||
205 | return 0; | ||
206 | if ((off + count) > edev->bin.size) | ||
207 | count = edev->bin.size - off; | ||
208 | if (unlikely(!count)) | ||
209 | return count; | ||
210 | |||
211 | /* only write even number of bytes on 16-bit devices */ | ||
212 | if (edev->addrlen == 6) { | ||
213 | step = 2; | ||
214 | count &= ~1; | ||
215 | } | ||
216 | |||
217 | /* erase/write enable */ | ||
218 | ret = eeprom_93xx46_ew(edev, 1); | ||
219 | if (ret) | ||
220 | return ret; | ||
221 | |||
222 | mutex_lock(&edev->lock); | ||
223 | |||
224 | if (edev->pdata->prepare) | ||
225 | edev->pdata->prepare(edev); | ||
226 | |||
227 | for (i = 0; i < count; i += step) { | ||
228 | ret = eeprom_93xx46_write_word(edev, &buf[i], off + i); | ||
229 | if (ret) { | ||
230 | dev_err(&edev->spi->dev, "write failed at %d: %d\n", | ||
231 | (int)off + i, ret); | ||
232 | break; | ||
233 | } | ||
234 | } | ||
235 | |||
236 | if (edev->pdata->finish) | ||
237 | edev->pdata->finish(edev); | ||
238 | |||
239 | mutex_unlock(&edev->lock); | ||
240 | |||
241 | /* erase/write disable */ | ||
242 | eeprom_93xx46_ew(edev, 0); | ||
243 | return ret ? : count; | ||
244 | } | ||
245 | |||
246 | static int eeprom_93xx46_eral(struct eeprom_93xx46_dev *edev) | ||
247 | { | ||
248 | struct eeprom_93xx46_platform_data *pd = edev->pdata; | ||
249 | struct spi_message m; | ||
250 | struct spi_transfer t; | ||
251 | int bits, ret; | ||
252 | u16 cmd_addr; | ||
253 | |||
254 | cmd_addr = OP_START << edev->addrlen; | ||
255 | if (edev->addrlen == 7) { | ||
256 | cmd_addr |= ADDR_ERAL << 1; | ||
257 | bits = 10; | ||
258 | } else { | ||
259 | cmd_addr |= ADDR_ERAL; | ||
260 | bits = 9; | ||
261 | } | ||
262 | |||
263 | spi_message_init(&m); | ||
264 | memset(&t, 0, sizeof(t)); | ||
265 | |||
266 | t.tx_buf = &cmd_addr; | ||
267 | t.len = 2; | ||
268 | t.bits_per_word = bits; | ||
269 | spi_message_add_tail(&t, &m); | ||
270 | |||
271 | mutex_lock(&edev->lock); | ||
272 | |||
273 | if (edev->pdata->prepare) | ||
274 | edev->pdata->prepare(edev); | ||
275 | |||
276 | ret = spi_sync(edev->spi, &m); | ||
277 | if (ret) | ||
278 | dev_err(&edev->spi->dev, "erase error %d\n", ret); | ||
279 | /* have to wait erase cycle time Tec ms */ | ||
280 | mdelay(6); | ||
281 | |||
282 | if (pd->finish) | ||
283 | pd->finish(edev); | ||
284 | |||
285 | mutex_unlock(&edev->lock); | ||
286 | return ret; | ||
287 | } | ||
288 | |||
289 | static ssize_t eeprom_93xx46_store_erase(struct device *dev, | ||
290 | struct device_attribute *attr, | ||
291 | const char *buf, size_t count) | ||
292 | { | ||
293 | struct eeprom_93xx46_dev *edev = dev_get_drvdata(dev); | ||
294 | int erase = 0, ret; | ||
295 | |||
296 | sscanf(buf, "%d", &erase); | ||
297 | if (erase) { | ||
298 | ret = eeprom_93xx46_ew(edev, 1); | ||
299 | if (ret) | ||
300 | return ret; | ||
301 | ret = eeprom_93xx46_eral(edev); | ||
302 | if (ret) | ||
303 | return ret; | ||
304 | ret = eeprom_93xx46_ew(edev, 0); | ||
305 | if (ret) | ||
306 | return ret; | ||
307 | } | ||
308 | return count; | ||
309 | } | ||
310 | static DEVICE_ATTR(erase, S_IWUSR, NULL, eeprom_93xx46_store_erase); | ||
311 | |||
312 | static int __devinit eeprom_93xx46_probe(struct spi_device *spi) | ||
313 | { | ||
314 | struct eeprom_93xx46_platform_data *pd; | ||
315 | struct eeprom_93xx46_dev *edev; | ||
316 | int err; | ||
317 | |||
318 | pd = spi->dev.platform_data; | ||
319 | if (!pd) { | ||
320 | dev_err(&spi->dev, "missing platform data\n"); | ||
321 | return -ENODEV; | ||
322 | } | ||
323 | |||
324 | edev = kzalloc(sizeof(*edev), GFP_KERNEL); | ||
325 | if (!edev) | ||
326 | return -ENOMEM; | ||
327 | |||
328 | if (pd->flags & EE_ADDR8) | ||
329 | edev->addrlen = 7; | ||
330 | else if (pd->flags & EE_ADDR16) | ||
331 | edev->addrlen = 6; | ||
332 | else { | ||
333 | dev_err(&spi->dev, "unspecified address type\n"); | ||
334 | err = -EINVAL; | ||
335 | goto fail; | ||
336 | } | ||
337 | |||
338 | mutex_init(&edev->lock); | ||
339 | |||
340 | edev->spi = spi_dev_get(spi); | ||
341 | edev->pdata = pd; | ||
342 | |||
343 | sysfs_bin_attr_init(&edev->bin); | ||
344 | edev->bin.attr.name = "eeprom"; | ||
345 | edev->bin.attr.mode = S_IRUSR; | ||
346 | edev->bin.read = eeprom_93xx46_bin_read; | ||
347 | edev->bin.size = 128; | ||
348 | if (!(pd->flags & EE_READONLY)) { | ||
349 | edev->bin.write = eeprom_93xx46_bin_write; | ||
350 | edev->bin.attr.mode |= S_IWUSR; | ||
351 | } | ||
352 | |||
353 | err = sysfs_create_bin_file(&spi->dev.kobj, &edev->bin); | ||
354 | if (err) | ||
355 | goto fail; | ||
356 | |||
357 | dev_info(&spi->dev, "%d-bit eeprom %s\n", | ||
358 | (pd->flags & EE_ADDR8) ? 8 : 16, | ||
359 | (pd->flags & EE_READONLY) ? "(readonly)" : ""); | ||
360 | |||
361 | if (!(pd->flags & EE_READONLY)) { | ||
362 | if (device_create_file(&spi->dev, &dev_attr_erase)) | ||
363 | dev_err(&spi->dev, "can't create erase interface\n"); | ||
364 | } | ||
365 | |||
366 | dev_set_drvdata(&spi->dev, edev); | ||
367 | return 0; | ||
368 | fail: | ||
369 | kfree(edev); | ||
370 | return err; | ||
371 | } | ||
372 | |||
373 | static int __devexit eeprom_93xx46_remove(struct spi_device *spi) | ||
374 | { | ||
375 | struct eeprom_93xx46_dev *edev = dev_get_drvdata(&spi->dev); | ||
376 | |||
377 | if (!(edev->pdata->flags & EE_READONLY)) | ||
378 | device_remove_file(&spi->dev, &dev_attr_erase); | ||
379 | |||
380 | sysfs_remove_bin_file(&spi->dev.kobj, &edev->bin); | ||
381 | dev_set_drvdata(&spi->dev, NULL); | ||
382 | kfree(edev); | ||
383 | return 0; | ||
384 | } | ||
385 | |||
386 | static struct spi_driver eeprom_93xx46_driver = { | ||
387 | .driver = { | ||
388 | .name = "93xx46", | ||
389 | .owner = THIS_MODULE, | ||
390 | }, | ||
391 | .probe = eeprom_93xx46_probe, | ||
392 | .remove = __devexit_p(eeprom_93xx46_remove), | ||
393 | }; | ||
394 | |||
395 | static int __init eeprom_93xx46_init(void) | ||
396 | { | ||
397 | return spi_register_driver(&eeprom_93xx46_driver); | ||
398 | } | ||
399 | module_init(eeprom_93xx46_init); | ||
400 | |||
401 | static void __exit eeprom_93xx46_exit(void) | ||
402 | { | ||
403 | spi_unregister_driver(&eeprom_93xx46_driver); | ||
404 | } | ||
405 | module_exit(eeprom_93xx46_exit); | ||
406 | |||
407 | MODULE_LICENSE("GPL"); | ||
408 | MODULE_DESCRIPTION("Driver for 93xx46 EEPROMs"); | ||
409 | MODULE_AUTHOR("Anatolij Gustschin <agust@denx.de>"); | ||
410 | MODULE_ALIAS("spi:93xx46"); | ||
diff --git a/drivers/misc/fsa9480.c b/drivers/misc/fsa9480.c new file mode 100644 index 000000000000..5325a7e70dcf --- /dev/null +++ b/drivers/misc/fsa9480.c | |||
@@ -0,0 +1,557 @@ | |||
1 | /* | ||
2 | * fsa9480.c - FSA9480 micro USB switch device driver | ||
3 | * | ||
4 | * Copyright (C) 2010 Samsung Electronics | ||
5 | * Minkyu Kang <mk7.kang@samsung.com> | ||
6 | * Wonguk Jeong <wonguk.jeong@samsung.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/err.h> | ||
16 | #include <linux/i2c.h> | ||
17 | #include <linux/platform_data/fsa9480.h> | ||
18 | #include <linux/irq.h> | ||
19 | #include <linux/interrupt.h> | ||
20 | #include <linux/workqueue.h> | ||
21 | #include <linux/platform_device.h> | ||
22 | #include <linux/slab.h> | ||
23 | #include <linux/pm_runtime.h> | ||
24 | |||
25 | /* FSA9480 I2C registers */ | ||
26 | #define FSA9480_REG_DEVID 0x01 | ||
27 | #define FSA9480_REG_CTRL 0x02 | ||
28 | #define FSA9480_REG_INT1 0x03 | ||
29 | #define FSA9480_REG_INT2 0x04 | ||
30 | #define FSA9480_REG_INT1_MASK 0x05 | ||
31 | #define FSA9480_REG_INT2_MASK 0x06 | ||
32 | #define FSA9480_REG_ADC 0x07 | ||
33 | #define FSA9480_REG_TIMING1 0x08 | ||
34 | #define FSA9480_REG_TIMING2 0x09 | ||
35 | #define FSA9480_REG_DEV_T1 0x0a | ||
36 | #define FSA9480_REG_DEV_T2 0x0b | ||
37 | #define FSA9480_REG_BTN1 0x0c | ||
38 | #define FSA9480_REG_BTN2 0x0d | ||
39 | #define FSA9480_REG_CK 0x0e | ||
40 | #define FSA9480_REG_CK_INT1 0x0f | ||
41 | #define FSA9480_REG_CK_INT2 0x10 | ||
42 | #define FSA9480_REG_CK_INTMASK1 0x11 | ||
43 | #define FSA9480_REG_CK_INTMASK2 0x12 | ||
44 | #define FSA9480_REG_MANSW1 0x13 | ||
45 | #define FSA9480_REG_MANSW2 0x14 | ||
46 | |||
47 | /* Control */ | ||
48 | #define CON_SWITCH_OPEN (1 << 4) | ||
49 | #define CON_RAW_DATA (1 << 3) | ||
50 | #define CON_MANUAL_SW (1 << 2) | ||
51 | #define CON_WAIT (1 << 1) | ||
52 | #define CON_INT_MASK (1 << 0) | ||
53 | #define CON_MASK (CON_SWITCH_OPEN | CON_RAW_DATA | \ | ||
54 | CON_MANUAL_SW | CON_WAIT) | ||
55 | |||
56 | /* Device Type 1 */ | ||
57 | #define DEV_USB_OTG (1 << 7) | ||
58 | #define DEV_DEDICATED_CHG (1 << 6) | ||
59 | #define DEV_USB_CHG (1 << 5) | ||
60 | #define DEV_CAR_KIT (1 << 4) | ||
61 | #define DEV_UART (1 << 3) | ||
62 | #define DEV_USB (1 << 2) | ||
63 | #define DEV_AUDIO_2 (1 << 1) | ||
64 | #define DEV_AUDIO_1 (1 << 0) | ||
65 | |||
66 | #define DEV_T1_USB_MASK (DEV_USB_OTG | DEV_USB) | ||
67 | #define DEV_T1_UART_MASK (DEV_UART) | ||
68 | #define DEV_T1_CHARGER_MASK (DEV_DEDICATED_CHG | DEV_USB_CHG) | ||
69 | |||
70 | /* Device Type 2 */ | ||
71 | #define DEV_AV (1 << 6) | ||
72 | #define DEV_TTY (1 << 5) | ||
73 | #define DEV_PPD (1 << 4) | ||
74 | #define DEV_JIG_UART_OFF (1 << 3) | ||
75 | #define DEV_JIG_UART_ON (1 << 2) | ||
76 | #define DEV_JIG_USB_OFF (1 << 1) | ||
77 | #define DEV_JIG_USB_ON (1 << 0) | ||
78 | |||
79 | #define DEV_T2_USB_MASK (DEV_JIG_USB_OFF | DEV_JIG_USB_ON) | ||
80 | #define DEV_T2_UART_MASK (DEV_JIG_UART_OFF | DEV_JIG_UART_ON) | ||
81 | #define DEV_T2_JIG_MASK (DEV_JIG_USB_OFF | DEV_JIG_USB_ON | \ | ||
82 | DEV_JIG_UART_OFF | DEV_JIG_UART_ON) | ||
83 | |||
84 | /* | ||
85 | * Manual Switch | ||
86 | * D- [7:5] / D+ [4:2] | ||
87 | * 000: Open all / 001: USB / 010: AUDIO / 011: UART / 100: V_AUDIO | ||
88 | */ | ||
89 | #define SW_VAUDIO ((4 << 5) | (4 << 2)) | ||
90 | #define SW_UART ((3 << 5) | (3 << 2)) | ||
91 | #define SW_AUDIO ((2 << 5) | (2 << 2)) | ||
92 | #define SW_DHOST ((1 << 5) | (1 << 2)) | ||
93 | #define SW_AUTO ((0 << 5) | (0 << 2)) | ||
94 | |||
95 | /* Interrupt 1 */ | ||
96 | #define INT_DETACH (1 << 1) | ||
97 | #define INT_ATTACH (1 << 0) | ||
98 | |||
99 | struct fsa9480_usbsw { | ||
100 | struct i2c_client *client; | ||
101 | struct fsa9480_platform_data *pdata; | ||
102 | int dev1; | ||
103 | int dev2; | ||
104 | int mansw; | ||
105 | }; | ||
106 | |||
107 | static struct fsa9480_usbsw *chip; | ||
108 | |||
109 | static int fsa9480_write_reg(struct i2c_client *client, | ||
110 | int reg, int value) | ||
111 | { | ||
112 | int ret; | ||
113 | |||
114 | ret = i2c_smbus_write_byte_data(client, reg, value); | ||
115 | |||
116 | if (ret < 0) | ||
117 | dev_err(&client->dev, "%s: err %d\n", __func__, ret); | ||
118 | |||
119 | return ret; | ||
120 | } | ||
121 | |||
122 | static int fsa9480_read_reg(struct i2c_client *client, int reg) | ||
123 | { | ||
124 | int ret; | ||
125 | |||
126 | ret = i2c_smbus_read_byte_data(client, reg); | ||
127 | |||
128 | if (ret < 0) | ||
129 | dev_err(&client->dev, "%s: err %d\n", __func__, ret); | ||
130 | |||
131 | return ret; | ||
132 | } | ||
133 | |||
134 | static int fsa9480_read_irq(struct i2c_client *client, int *value) | ||
135 | { | ||
136 | int ret; | ||
137 | |||
138 | ret = i2c_smbus_read_i2c_block_data(client, | ||
139 | FSA9480_REG_INT1, 2, (u8 *)value); | ||
140 | *value &= 0xffff; | ||
141 | |||
142 | if (ret < 0) | ||
143 | dev_err(&client->dev, "%s: err %d\n", __func__, ret); | ||
144 | |||
145 | return ret; | ||
146 | } | ||
147 | |||
148 | static void fsa9480_set_switch(const char *buf) | ||
149 | { | ||
150 | struct fsa9480_usbsw *usbsw = chip; | ||
151 | struct i2c_client *client = usbsw->client; | ||
152 | unsigned int value; | ||
153 | unsigned int path = 0; | ||
154 | |||
155 | value = fsa9480_read_reg(client, FSA9480_REG_CTRL); | ||
156 | |||
157 | if (!strncmp(buf, "VAUDIO", 6)) { | ||
158 | path = SW_VAUDIO; | ||
159 | value &= ~CON_MANUAL_SW; | ||
160 | } else if (!strncmp(buf, "UART", 4)) { | ||
161 | path = SW_UART; | ||
162 | value &= ~CON_MANUAL_SW; | ||
163 | } else if (!strncmp(buf, "AUDIO", 5)) { | ||
164 | path = SW_AUDIO; | ||
165 | value &= ~CON_MANUAL_SW; | ||
166 | } else if (!strncmp(buf, "DHOST", 5)) { | ||
167 | path = SW_DHOST; | ||
168 | value &= ~CON_MANUAL_SW; | ||
169 | } else if (!strncmp(buf, "AUTO", 4)) { | ||
170 | path = SW_AUTO; | ||
171 | value |= CON_MANUAL_SW; | ||
172 | } else { | ||
173 | printk(KERN_ERR "Wrong command\n"); | ||
174 | return; | ||
175 | } | ||
176 | |||
177 | usbsw->mansw = path; | ||
178 | fsa9480_write_reg(client, FSA9480_REG_MANSW1, path); | ||
179 | fsa9480_write_reg(client, FSA9480_REG_CTRL, value); | ||
180 | } | ||
181 | |||
182 | static ssize_t fsa9480_get_switch(char *buf) | ||
183 | { | ||
184 | struct fsa9480_usbsw *usbsw = chip; | ||
185 | struct i2c_client *client = usbsw->client; | ||
186 | unsigned int value; | ||
187 | |||
188 | value = fsa9480_read_reg(client, FSA9480_REG_MANSW1); | ||
189 | |||
190 | if (value == SW_VAUDIO) | ||
191 | return sprintf(buf, "VAUDIO\n"); | ||
192 | else if (value == SW_UART) | ||
193 | return sprintf(buf, "UART\n"); | ||
194 | else if (value == SW_AUDIO) | ||
195 | return sprintf(buf, "AUDIO\n"); | ||
196 | else if (value == SW_DHOST) | ||
197 | return sprintf(buf, "DHOST\n"); | ||
198 | else if (value == SW_AUTO) | ||
199 | return sprintf(buf, "AUTO\n"); | ||
200 | else | ||
201 | return sprintf(buf, "%x", value); | ||
202 | } | ||
203 | |||
204 | static ssize_t fsa9480_show_device(struct device *dev, | ||
205 | struct device_attribute *attr, | ||
206 | char *buf) | ||
207 | { | ||
208 | struct fsa9480_usbsw *usbsw = dev_get_drvdata(dev); | ||
209 | struct i2c_client *client = usbsw->client; | ||
210 | int dev1, dev2; | ||
211 | |||
212 | dev1 = fsa9480_read_reg(client, FSA9480_REG_DEV_T1); | ||
213 | dev2 = fsa9480_read_reg(client, FSA9480_REG_DEV_T2); | ||
214 | |||
215 | if (!dev1 && !dev2) | ||
216 | return sprintf(buf, "NONE\n"); | ||
217 | |||
218 | /* USB */ | ||
219 | if (dev1 & DEV_T1_USB_MASK || dev2 & DEV_T2_USB_MASK) | ||
220 | return sprintf(buf, "USB\n"); | ||
221 | |||
222 | /* UART */ | ||
223 | if (dev1 & DEV_T1_UART_MASK || dev2 & DEV_T2_UART_MASK) | ||
224 | return sprintf(buf, "UART\n"); | ||
225 | |||
226 | /* CHARGER */ | ||
227 | if (dev1 & DEV_T1_CHARGER_MASK) | ||
228 | return sprintf(buf, "CHARGER\n"); | ||
229 | |||
230 | /* JIG */ | ||
231 | if (dev2 & DEV_T2_JIG_MASK) | ||
232 | return sprintf(buf, "JIG\n"); | ||
233 | |||
234 | return sprintf(buf, "UNKNOWN\n"); | ||
235 | } | ||
236 | |||
237 | static ssize_t fsa9480_show_manualsw(struct device *dev, | ||
238 | struct device_attribute *attr, char *buf) | ||
239 | { | ||
240 | return fsa9480_get_switch(buf); | ||
241 | |||
242 | } | ||
243 | |||
244 | static ssize_t fsa9480_set_manualsw(struct device *dev, | ||
245 | struct device_attribute *attr, | ||
246 | const char *buf, size_t count) | ||
247 | { | ||
248 | fsa9480_set_switch(buf); | ||
249 | |||
250 | return count; | ||
251 | } | ||
252 | |||
253 | static DEVICE_ATTR(device, S_IRUGO, fsa9480_show_device, NULL); | ||
254 | static DEVICE_ATTR(switch, S_IRUGO | S_IWUSR, | ||
255 | fsa9480_show_manualsw, fsa9480_set_manualsw); | ||
256 | |||
257 | static struct attribute *fsa9480_attributes[] = { | ||
258 | &dev_attr_device.attr, | ||
259 | &dev_attr_switch.attr, | ||
260 | NULL | ||
261 | }; | ||
262 | |||
263 | static const struct attribute_group fsa9480_group = { | ||
264 | .attrs = fsa9480_attributes, | ||
265 | }; | ||
266 | |||
267 | static void fsa9480_detect_dev(struct fsa9480_usbsw *usbsw, int intr) | ||
268 | { | ||
269 | int val1, val2, ctrl; | ||
270 | struct fsa9480_platform_data *pdata = usbsw->pdata; | ||
271 | struct i2c_client *client = usbsw->client; | ||
272 | |||
273 | val1 = fsa9480_read_reg(client, FSA9480_REG_DEV_T1); | ||
274 | val2 = fsa9480_read_reg(client, FSA9480_REG_DEV_T2); | ||
275 | ctrl = fsa9480_read_reg(client, FSA9480_REG_CTRL); | ||
276 | |||
277 | dev_info(&client->dev, "intr: 0x%x, dev1: 0x%x, dev2: 0x%x\n", | ||
278 | intr, val1, val2); | ||
279 | |||
280 | if (!intr) | ||
281 | goto out; | ||
282 | |||
283 | if (intr & INT_ATTACH) { /* Attached */ | ||
284 | /* USB */ | ||
285 | if (val1 & DEV_T1_USB_MASK || val2 & DEV_T2_USB_MASK) { | ||
286 | if (pdata->usb_cb) | ||
287 | pdata->usb_cb(FSA9480_ATTACHED); | ||
288 | |||
289 | if (usbsw->mansw) { | ||
290 | fsa9480_write_reg(client, | ||
291 | FSA9480_REG_MANSW1, usbsw->mansw); | ||
292 | } | ||
293 | } | ||
294 | |||
295 | /* UART */ | ||
296 | if (val1 & DEV_T1_UART_MASK || val2 & DEV_T2_UART_MASK) { | ||
297 | if (pdata->uart_cb) | ||
298 | pdata->uart_cb(FSA9480_ATTACHED); | ||
299 | |||
300 | if (!(ctrl & CON_MANUAL_SW)) { | ||
301 | fsa9480_write_reg(client, | ||
302 | FSA9480_REG_MANSW1, SW_UART); | ||
303 | } | ||
304 | } | ||
305 | |||
306 | /* CHARGER */ | ||
307 | if (val1 & DEV_T1_CHARGER_MASK) { | ||
308 | if (pdata->charger_cb) | ||
309 | pdata->charger_cb(FSA9480_ATTACHED); | ||
310 | } | ||
311 | |||
312 | /* JIG */ | ||
313 | if (val2 & DEV_T2_JIG_MASK) { | ||
314 | if (pdata->jig_cb) | ||
315 | pdata->jig_cb(FSA9480_ATTACHED); | ||
316 | } | ||
317 | } else if (intr & INT_DETACH) { /* Detached */ | ||
318 | /* USB */ | ||
319 | if (usbsw->dev1 & DEV_T1_USB_MASK || | ||
320 | usbsw->dev2 & DEV_T2_USB_MASK) { | ||
321 | if (pdata->usb_cb) | ||
322 | pdata->usb_cb(FSA9480_DETACHED); | ||
323 | } | ||
324 | |||
325 | /* UART */ | ||
326 | if (usbsw->dev1 & DEV_T1_UART_MASK || | ||
327 | usbsw->dev2 & DEV_T2_UART_MASK) { | ||
328 | if (pdata->uart_cb) | ||
329 | pdata->uart_cb(FSA9480_DETACHED); | ||
330 | } | ||
331 | |||
332 | /* CHARGER */ | ||
333 | if (usbsw->dev1 & DEV_T1_CHARGER_MASK) { | ||
334 | if (pdata->charger_cb) | ||
335 | pdata->charger_cb(FSA9480_DETACHED); | ||
336 | } | ||
337 | |||
338 | /* JIG */ | ||
339 | if (usbsw->dev2 & DEV_T2_JIG_MASK) { | ||
340 | if (pdata->jig_cb) | ||
341 | pdata->jig_cb(FSA9480_DETACHED); | ||
342 | } | ||
343 | } | ||
344 | |||
345 | usbsw->dev1 = val1; | ||
346 | usbsw->dev2 = val2; | ||
347 | |||
348 | out: | ||
349 | ctrl &= ~CON_INT_MASK; | ||
350 | fsa9480_write_reg(client, FSA9480_REG_CTRL, ctrl); | ||
351 | } | ||
352 | |||
353 | static irqreturn_t fsa9480_irq_handler(int irq, void *data) | ||
354 | { | ||
355 | struct fsa9480_usbsw *usbsw = data; | ||
356 | struct i2c_client *client = usbsw->client; | ||
357 | int intr; | ||
358 | |||
359 | /* clear interrupt */ | ||
360 | fsa9480_read_irq(client, &intr); | ||
361 | |||
362 | /* device detection */ | ||
363 | fsa9480_detect_dev(usbsw, intr); | ||
364 | |||
365 | return IRQ_HANDLED; | ||
366 | } | ||
367 | |||
368 | static int fsa9480_irq_init(struct fsa9480_usbsw *usbsw) | ||
369 | { | ||
370 | struct fsa9480_platform_data *pdata = usbsw->pdata; | ||
371 | struct i2c_client *client = usbsw->client; | ||
372 | int ret; | ||
373 | int intr; | ||
374 | unsigned int ctrl = CON_MASK; | ||
375 | |||
376 | /* clear interrupt */ | ||
377 | fsa9480_read_irq(client, &intr); | ||
378 | |||
379 | /* unmask interrupt (attach/detach only) */ | ||
380 | fsa9480_write_reg(client, FSA9480_REG_INT1_MASK, 0xfc); | ||
381 | fsa9480_write_reg(client, FSA9480_REG_INT2_MASK, 0x1f); | ||
382 | |||
383 | usbsw->mansw = fsa9480_read_reg(client, FSA9480_REG_MANSW1); | ||
384 | |||
385 | if (usbsw->mansw) | ||
386 | ctrl &= ~CON_MANUAL_SW; /* Manual Switching Mode */ | ||
387 | |||
388 | fsa9480_write_reg(client, FSA9480_REG_CTRL, ctrl); | ||
389 | |||
390 | if (pdata && pdata->cfg_gpio) | ||
391 | pdata->cfg_gpio(); | ||
392 | |||
393 | if (client->irq) { | ||
394 | ret = request_threaded_irq(client->irq, NULL, | ||
395 | fsa9480_irq_handler, | ||
396 | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, | ||
397 | "fsa9480 micro USB", usbsw); | ||
398 | if (ret) { | ||
399 | dev_err(&client->dev, "failed to reqeust IRQ\n"); | ||
400 | return ret; | ||
401 | } | ||
402 | |||
403 | device_init_wakeup(&client->dev, pdata->wakeup); | ||
404 | } | ||
405 | |||
406 | return 0; | ||
407 | } | ||
408 | |||
409 | static int __devinit fsa9480_probe(struct i2c_client *client, | ||
410 | const struct i2c_device_id *id) | ||
411 | { | ||
412 | struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); | ||
413 | struct fsa9480_usbsw *usbsw; | ||
414 | int ret = 0; | ||
415 | |||
416 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | ||
417 | return -EIO; | ||
418 | |||
419 | usbsw = kzalloc(sizeof(struct fsa9480_usbsw), GFP_KERNEL); | ||
420 | if (!usbsw) { | ||
421 | dev_err(&client->dev, "failed to allocate driver data\n"); | ||
422 | return -ENOMEM; | ||
423 | } | ||
424 | |||
425 | usbsw->client = client; | ||
426 | usbsw->pdata = client->dev.platform_data; | ||
427 | |||
428 | chip = usbsw; | ||
429 | |||
430 | i2c_set_clientdata(client, usbsw); | ||
431 | |||
432 | ret = fsa9480_irq_init(usbsw); | ||
433 | if (ret) | ||
434 | goto fail1; | ||
435 | |||
436 | ret = sysfs_create_group(&client->dev.kobj, &fsa9480_group); | ||
437 | if (ret) { | ||
438 | dev_err(&client->dev, | ||
439 | "failed to create fsa9480 attribute group\n"); | ||
440 | goto fail2; | ||
441 | } | ||
442 | |||
443 | /* ADC Detect Time: 500ms */ | ||
444 | fsa9480_write_reg(client, FSA9480_REG_TIMING1, 0x6); | ||
445 | |||
446 | if (chip->pdata->reset_cb) | ||
447 | chip->pdata->reset_cb(); | ||
448 | |||
449 | /* device detection */ | ||
450 | fsa9480_detect_dev(usbsw, INT_ATTACH); | ||
451 | |||
452 | pm_runtime_set_active(&client->dev); | ||
453 | |||
454 | return 0; | ||
455 | |||
456 | fail2: | ||
457 | if (client->irq) | ||
458 | free_irq(client->irq, NULL); | ||
459 | fail1: | ||
460 | i2c_set_clientdata(client, NULL); | ||
461 | kfree(usbsw); | ||
462 | return ret; | ||
463 | } | ||
464 | |||
465 | static int __devexit fsa9480_remove(struct i2c_client *client) | ||
466 | { | ||
467 | struct fsa9480_usbsw *usbsw = i2c_get_clientdata(client); | ||
468 | if (client->irq) | ||
469 | free_irq(client->irq, NULL); | ||
470 | i2c_set_clientdata(client, NULL); | ||
471 | |||
472 | sysfs_remove_group(&client->dev.kobj, &fsa9480_group); | ||
473 | device_init_wakeup(&client->dev, 0); | ||
474 | kfree(usbsw); | ||
475 | return 0; | ||
476 | } | ||
477 | |||
478 | #ifdef CONFIG_PM | ||
479 | |||
480 | static int fsa9480_suspend(struct i2c_client *client, pm_message_t state) | ||
481 | { | ||
482 | struct fsa9480_usbsw *usbsw = i2c_get_clientdata(client); | ||
483 | struct fsa9480_platform_data *pdata = usbsw->pdata; | ||
484 | |||
485 | if (device_may_wakeup(&client->dev) && client->irq) | ||
486 | enable_irq_wake(client->irq); | ||
487 | |||
488 | if (pdata->usb_power) | ||
489 | pdata->usb_power(0); | ||
490 | |||
491 | return 0; | ||
492 | } | ||
493 | |||
494 | static int fsa9480_resume(struct i2c_client *client) | ||
495 | { | ||
496 | struct fsa9480_usbsw *usbsw = i2c_get_clientdata(client); | ||
497 | int dev1, dev2; | ||
498 | |||
499 | if (device_may_wakeup(&client->dev) && client->irq) | ||
500 | disable_irq_wake(client->irq); | ||
501 | |||
502 | /* | ||
503 | * Clear Pending interrupt. Note that detect_dev does what | ||
504 | * the interrupt handler does. So, we don't miss pending and | ||
505 | * we reenable interrupt if there is one. | ||
506 | */ | ||
507 | fsa9480_read_reg(client, FSA9480_REG_INT1); | ||
508 | fsa9480_read_reg(client, FSA9480_REG_INT2); | ||
509 | |||
510 | dev1 = fsa9480_read_reg(client, FSA9480_REG_DEV_T1); | ||
511 | dev2 = fsa9480_read_reg(client, FSA9480_REG_DEV_T2); | ||
512 | |||
513 | /* device detection */ | ||
514 | fsa9480_detect_dev(usbsw, (dev1 || dev2) ? INT_ATTACH : INT_DETACH); | ||
515 | |||
516 | return 0; | ||
517 | } | ||
518 | |||
519 | #else | ||
520 | |||
521 | #define fsa9480_suspend NULL | ||
522 | #define fsa9480_resume NULL | ||
523 | |||
524 | #endif /* CONFIG_PM */ | ||
525 | |||
526 | static const struct i2c_device_id fsa9480_id[] = { | ||
527 | {"fsa9480", 0}, | ||
528 | {} | ||
529 | }; | ||
530 | MODULE_DEVICE_TABLE(i2c, fsa9480_id); | ||
531 | |||
532 | static struct i2c_driver fsa9480_i2c_driver = { | ||
533 | .driver = { | ||
534 | .name = "fsa9480", | ||
535 | }, | ||
536 | .probe = fsa9480_probe, | ||
537 | .remove = __devexit_p(fsa9480_remove), | ||
538 | .resume = fsa9480_resume, | ||
539 | .suspend = fsa9480_suspend, | ||
540 | .id_table = fsa9480_id, | ||
541 | }; | ||
542 | |||
543 | static int __init fsa9480_init(void) | ||
544 | { | ||
545 | return i2c_add_driver(&fsa9480_i2c_driver); | ||
546 | } | ||
547 | module_init(fsa9480_init); | ||
548 | |||
549 | static void __exit fsa9480_exit(void) | ||
550 | { | ||
551 | i2c_del_driver(&fsa9480_i2c_driver); | ||
552 | } | ||
553 | module_exit(fsa9480_exit); | ||
554 | |||
555 | MODULE_AUTHOR("Minkyu Kang <mk7.kang@samsung.com>"); | ||
556 | MODULE_DESCRIPTION("FSA9480 USB Switch driver"); | ||
557 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/misc/pch_phub.c b/drivers/misc/pch_phub.c index 5fe79df44838..01eb67b4871a 100644 --- a/drivers/misc/pch_phub.c +++ b/drivers/misc/pch_phub.c | |||
@@ -686,6 +686,8 @@ static int __devinit pch_phub_probe(struct pci_dev *pdev, | |||
686 | } | 686 | } |
687 | 687 | ||
688 | if (id->driver_data == 1) { /* EG20T PCH */ | 688 | if (id->driver_data == 1) { /* EG20T PCH */ |
689 | const char *board_name; | ||
690 | |||
689 | retval = sysfs_create_file(&pdev->dev.kobj, | 691 | retval = sysfs_create_file(&pdev->dev.kobj, |
690 | &dev_attr_pch_mac.attr); | 692 | &dev_attr_pch_mac.attr); |
691 | if (retval) | 693 | if (retval) |
@@ -701,7 +703,8 @@ static int __devinit pch_phub_probe(struct pci_dev *pdev, | |||
701 | CLKCFG_CANCLK_MASK); | 703 | CLKCFG_CANCLK_MASK); |
702 | 704 | ||
703 | /* quirk for CM-iTC board */ | 705 | /* quirk for CM-iTC board */ |
704 | if (strstr(dmi_get_system_info(DMI_BOARD_NAME), "CM-iTC")) | 706 | board_name = dmi_get_system_info(DMI_BOARD_NAME); |
707 | if (board_name && strstr(board_name, "CM-iTC")) | ||
705 | pch_phub_read_modify_write_reg(chip, | 708 | pch_phub_read_modify_write_reg(chip, |
706 | (unsigned int)CLKCFG_REG_OFFSET, | 709 | (unsigned int)CLKCFG_REG_OFFSET, |
707 | CLKCFG_UART_48MHZ | CLKCFG_BAUDDIV | | 710 | CLKCFG_UART_48MHZ | CLKCFG_BAUDDIV | |
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index f091b43d00c4..89bdeaec7182 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/log2.h> | 23 | #include <linux/log2.h> |
24 | #include <linux/regulator/consumer.h> | 24 | #include <linux/regulator/consumer.h> |
25 | #include <linux/pm_runtime.h> | 25 | #include <linux/pm_runtime.h> |
26 | #include <linux/suspend.h> | ||
26 | 27 | ||
27 | #include <linux/mmc/card.h> | 28 | #include <linux/mmc/card.h> |
28 | #include <linux/mmc/host.h> | 29 | #include <linux/mmc/host.h> |
diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c index 1a6937d9118f..bbf3edd85beb 100644 --- a/drivers/pnp/pnpacpi/rsparser.c +++ b/drivers/pnp/pnpacpi/rsparser.c | |||
@@ -509,15 +509,15 @@ static __init void pnpacpi_parse_dma_option(struct pnp_dev *dev, | |||
509 | struct acpi_resource_dma *p) | 509 | struct acpi_resource_dma *p) |
510 | { | 510 | { |
511 | int i; | 511 | int i; |
512 | unsigned char map = 0, flags; | 512 | unsigned char map = 0, flags = 0; |
513 | 513 | ||
514 | if (p->channel_count == 0) | 514 | if (p->channel_count == 0) |
515 | return; | 515 | flags |= IORESOURCE_DISABLED; |
516 | 516 | ||
517 | for (i = 0; i < p->channel_count; i++) | 517 | for (i = 0; i < p->channel_count; i++) |
518 | map |= 1 << p->channels[i]; | 518 | map |= 1 << p->channels[i]; |
519 | 519 | ||
520 | flags = dma_flags(dev, p->type, p->bus_master, p->transfer); | 520 | flags |= dma_flags(dev, p->type, p->bus_master, p->transfer); |
521 | pnp_register_dma_resource(dev, option_flags, map, flags); | 521 | pnp_register_dma_resource(dev, option_flags, map, flags); |
522 | } | 522 | } |
523 | 523 | ||
@@ -527,17 +527,17 @@ static __init void pnpacpi_parse_irq_option(struct pnp_dev *dev, | |||
527 | { | 527 | { |
528 | int i; | 528 | int i; |
529 | pnp_irq_mask_t map; | 529 | pnp_irq_mask_t map; |
530 | unsigned char flags; | 530 | unsigned char flags = 0; |
531 | 531 | ||
532 | if (p->interrupt_count == 0) | 532 | if (p->interrupt_count == 0) |
533 | return; | 533 | flags |= IORESOURCE_DISABLED; |
534 | 534 | ||
535 | bitmap_zero(map.bits, PNP_IRQ_NR); | 535 | bitmap_zero(map.bits, PNP_IRQ_NR); |
536 | for (i = 0; i < p->interrupt_count; i++) | 536 | for (i = 0; i < p->interrupt_count; i++) |
537 | if (p->interrupts[i]) | 537 | if (p->interrupts[i]) |
538 | __set_bit(p->interrupts[i], map.bits); | 538 | __set_bit(p->interrupts[i], map.bits); |
539 | 539 | ||
540 | flags = irq_flags(p->triggering, p->polarity, p->sharable); | 540 | flags |= irq_flags(p->triggering, p->polarity, p->sharable); |
541 | pnp_register_irq_resource(dev, option_flags, &map, flags); | 541 | pnp_register_irq_resource(dev, option_flags, &map, flags); |
542 | } | 542 | } |
543 | 543 | ||
@@ -547,10 +547,10 @@ static __init void pnpacpi_parse_ext_irq_option(struct pnp_dev *dev, | |||
547 | { | 547 | { |
548 | int i; | 548 | int i; |
549 | pnp_irq_mask_t map; | 549 | pnp_irq_mask_t map; |
550 | unsigned char flags; | 550 | unsigned char flags = 0; |
551 | 551 | ||
552 | if (p->interrupt_count == 0) | 552 | if (p->interrupt_count == 0) |
553 | return; | 553 | flags |= IORESOURCE_DISABLED; |
554 | 554 | ||
555 | bitmap_zero(map.bits, PNP_IRQ_NR); | 555 | bitmap_zero(map.bits, PNP_IRQ_NR); |
556 | for (i = 0; i < p->interrupt_count; i++) { | 556 | for (i = 0; i < p->interrupt_count; i++) { |
@@ -564,7 +564,7 @@ static __init void pnpacpi_parse_ext_irq_option(struct pnp_dev *dev, | |||
564 | } | 564 | } |
565 | } | 565 | } |
566 | 566 | ||
567 | flags = irq_flags(p->triggering, p->polarity, p->sharable); | 567 | flags |= irq_flags(p->triggering, p->polarity, p->sharable); |
568 | pnp_register_irq_resource(dev, option_flags, &map, flags); | 568 | pnp_register_irq_resource(dev, option_flags, &map, flags); |
569 | } | 569 | } |
570 | 570 | ||
@@ -575,10 +575,10 @@ static __init void pnpacpi_parse_port_option(struct pnp_dev *dev, | |||
575 | unsigned char flags = 0; | 575 | unsigned char flags = 0; |
576 | 576 | ||
577 | if (io->address_length == 0) | 577 | if (io->address_length == 0) |
578 | return; | 578 | flags |= IORESOURCE_DISABLED; |
579 | 579 | ||
580 | if (io->io_decode == ACPI_DECODE_16) | 580 | if (io->io_decode == ACPI_DECODE_16) |
581 | flags = IORESOURCE_IO_16BIT_ADDR; | 581 | flags |= IORESOURCE_IO_16BIT_ADDR; |
582 | pnp_register_port_resource(dev, option_flags, io->minimum, io->maximum, | 582 | pnp_register_port_resource(dev, option_flags, io->minimum, io->maximum, |
583 | io->alignment, io->address_length, flags); | 583 | io->alignment, io->address_length, flags); |
584 | } | 584 | } |
@@ -587,11 +587,13 @@ static __init void pnpacpi_parse_fixed_port_option(struct pnp_dev *dev, | |||
587 | unsigned int option_flags, | 587 | unsigned int option_flags, |
588 | struct acpi_resource_fixed_io *io) | 588 | struct acpi_resource_fixed_io *io) |
589 | { | 589 | { |
590 | unsigned char flags = 0; | ||
591 | |||
590 | if (io->address_length == 0) | 592 | if (io->address_length == 0) |
591 | return; | 593 | flags |= IORESOURCE_DISABLED; |
592 | 594 | ||
593 | pnp_register_port_resource(dev, option_flags, io->address, io->address, | 595 | pnp_register_port_resource(dev, option_flags, io->address, io->address, |
594 | 0, io->address_length, IORESOURCE_IO_FIXED); | 596 | 0, io->address_length, flags | IORESOURCE_IO_FIXED); |
595 | } | 597 | } |
596 | 598 | ||
597 | static __init void pnpacpi_parse_mem24_option(struct pnp_dev *dev, | 599 | static __init void pnpacpi_parse_mem24_option(struct pnp_dev *dev, |
@@ -601,10 +603,10 @@ static __init void pnpacpi_parse_mem24_option(struct pnp_dev *dev, | |||
601 | unsigned char flags = 0; | 603 | unsigned char flags = 0; |
602 | 604 | ||
603 | if (p->address_length == 0) | 605 | if (p->address_length == 0) |
604 | return; | 606 | flags |= IORESOURCE_DISABLED; |
605 | 607 | ||
606 | if (p->write_protect == ACPI_READ_WRITE_MEMORY) | 608 | if (p->write_protect == ACPI_READ_WRITE_MEMORY) |
607 | flags = IORESOURCE_MEM_WRITEABLE; | 609 | flags |= IORESOURCE_MEM_WRITEABLE; |
608 | pnp_register_mem_resource(dev, option_flags, p->minimum, p->maximum, | 610 | pnp_register_mem_resource(dev, option_flags, p->minimum, p->maximum, |
609 | p->alignment, p->address_length, flags); | 611 | p->alignment, p->address_length, flags); |
610 | } | 612 | } |
@@ -616,10 +618,10 @@ static __init void pnpacpi_parse_mem32_option(struct pnp_dev *dev, | |||
616 | unsigned char flags = 0; | 618 | unsigned char flags = 0; |
617 | 619 | ||
618 | if (p->address_length == 0) | 620 | if (p->address_length == 0) |
619 | return; | 621 | flags |= IORESOURCE_DISABLED; |
620 | 622 | ||
621 | if (p->write_protect == ACPI_READ_WRITE_MEMORY) | 623 | if (p->write_protect == ACPI_READ_WRITE_MEMORY) |
622 | flags = IORESOURCE_MEM_WRITEABLE; | 624 | flags |= IORESOURCE_MEM_WRITEABLE; |
623 | pnp_register_mem_resource(dev, option_flags, p->minimum, p->maximum, | 625 | pnp_register_mem_resource(dev, option_flags, p->minimum, p->maximum, |
624 | p->alignment, p->address_length, flags); | 626 | p->alignment, p->address_length, flags); |
625 | } | 627 | } |
@@ -631,10 +633,10 @@ static __init void pnpacpi_parse_fixed_mem32_option(struct pnp_dev *dev, | |||
631 | unsigned char flags = 0; | 633 | unsigned char flags = 0; |
632 | 634 | ||
633 | if (p->address_length == 0) | 635 | if (p->address_length == 0) |
634 | return; | 636 | flags |= IORESOURCE_DISABLED; |
635 | 637 | ||
636 | if (p->write_protect == ACPI_READ_WRITE_MEMORY) | 638 | if (p->write_protect == ACPI_READ_WRITE_MEMORY) |
637 | flags = IORESOURCE_MEM_WRITEABLE; | 639 | flags |= IORESOURCE_MEM_WRITEABLE; |
638 | pnp_register_mem_resource(dev, option_flags, p->address, p->address, | 640 | pnp_register_mem_resource(dev, option_flags, p->address, p->address, |
639 | 0, p->address_length, flags); | 641 | 0, p->address_length, flags); |
640 | } | 642 | } |
@@ -655,18 +657,18 @@ static __init void pnpacpi_parse_address_option(struct pnp_dev *dev, | |||
655 | } | 657 | } |
656 | 658 | ||
657 | if (p->address_length == 0) | 659 | if (p->address_length == 0) |
658 | return; | 660 | flags |= IORESOURCE_DISABLED; |
659 | 661 | ||
660 | if (p->resource_type == ACPI_MEMORY_RANGE) { | 662 | if (p->resource_type == ACPI_MEMORY_RANGE) { |
661 | if (p->info.mem.write_protect == ACPI_READ_WRITE_MEMORY) | 663 | if (p->info.mem.write_protect == ACPI_READ_WRITE_MEMORY) |
662 | flags = IORESOURCE_MEM_WRITEABLE; | 664 | flags |= IORESOURCE_MEM_WRITEABLE; |
663 | pnp_register_mem_resource(dev, option_flags, p->minimum, | 665 | pnp_register_mem_resource(dev, option_flags, p->minimum, |
664 | p->minimum, 0, p->address_length, | 666 | p->minimum, 0, p->address_length, |
665 | flags); | 667 | flags); |
666 | } else if (p->resource_type == ACPI_IO_RANGE) | 668 | } else if (p->resource_type == ACPI_IO_RANGE) |
667 | pnp_register_port_resource(dev, option_flags, p->minimum, | 669 | pnp_register_port_resource(dev, option_flags, p->minimum, |
668 | p->minimum, 0, p->address_length, | 670 | p->minimum, 0, p->address_length, |
669 | IORESOURCE_IO_FIXED); | 671 | flags | IORESOURCE_IO_FIXED); |
670 | } | 672 | } |
671 | 673 | ||
672 | static __init void pnpacpi_parse_ext_address_option(struct pnp_dev *dev, | 674 | static __init void pnpacpi_parse_ext_address_option(struct pnp_dev *dev, |
@@ -677,18 +679,18 @@ static __init void pnpacpi_parse_ext_address_option(struct pnp_dev *dev, | |||
677 | unsigned char flags = 0; | 679 | unsigned char flags = 0; |
678 | 680 | ||
679 | if (p->address_length == 0) | 681 | if (p->address_length == 0) |
680 | return; | 682 | flags |= IORESOURCE_DISABLED; |
681 | 683 | ||
682 | if (p->resource_type == ACPI_MEMORY_RANGE) { | 684 | if (p->resource_type == ACPI_MEMORY_RANGE) { |
683 | if (p->info.mem.write_protect == ACPI_READ_WRITE_MEMORY) | 685 | if (p->info.mem.write_protect == ACPI_READ_WRITE_MEMORY) |
684 | flags = IORESOURCE_MEM_WRITEABLE; | 686 | flags |= IORESOURCE_MEM_WRITEABLE; |
685 | pnp_register_mem_resource(dev, option_flags, p->minimum, | 687 | pnp_register_mem_resource(dev, option_flags, p->minimum, |
686 | p->minimum, 0, p->address_length, | 688 | p->minimum, 0, p->address_length, |
687 | flags); | 689 | flags); |
688 | } else if (p->resource_type == ACPI_IO_RANGE) | 690 | } else if (p->resource_type == ACPI_IO_RANGE) |
689 | pnp_register_port_resource(dev, option_flags, p->minimum, | 691 | pnp_register_port_resource(dev, option_flags, p->minimum, |
690 | p->minimum, 0, p->address_length, | 692 | p->minimum, 0, p->address_length, |
691 | IORESOURCE_IO_FIXED); | 693 | flags | IORESOURCE_IO_FIXED); |
692 | } | 694 | } |
693 | 695 | ||
694 | struct acpipnp_parse_option_s { | 696 | struct acpipnp_parse_option_s { |
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index dcb61e23b985..5a538fc1cc85 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig | |||
@@ -1006,10 +1006,10 @@ config RTC_DRV_MC13XXX | |||
1006 | 1006 | ||
1007 | config RTC_DRV_MPC5121 | 1007 | config RTC_DRV_MPC5121 |
1008 | tristate "Freescale MPC5121 built-in RTC" | 1008 | tristate "Freescale MPC5121 built-in RTC" |
1009 | depends on PPC_MPC512x && RTC_CLASS | 1009 | depends on PPC_MPC512x || PPC_MPC52xx |
1010 | help | 1010 | help |
1011 | If you say yes here you will get support for the | 1011 | If you say yes here you will get support for the |
1012 | built-in RTC MPC5121. | 1012 | built-in RTC on MPC5121 or on MPC5200. |
1013 | 1013 | ||
1014 | This driver can also be built as a module. If so, the module | 1014 | This driver can also be built as a module. If so, the module |
1015 | will be called rtc-mpc5121. | 1015 | will be called rtc-mpc5121. |
@@ -1034,6 +1034,16 @@ config RTC_DRV_LPC32XX | |||
1034 | This driver can also be buillt as a module. If so, the module | 1034 | This driver can also be buillt as a module. If so, the module |
1035 | will be called rtc-lpc32xx. | 1035 | will be called rtc-lpc32xx. |
1036 | 1036 | ||
1037 | config RTC_DRV_PM8XXX | ||
1038 | tristate "Qualcomm PMIC8XXX RTC" | ||
1039 | depends on MFD_PM8XXX | ||
1040 | help | ||
1041 | If you say yes here you get support for the | ||
1042 | Qualcomm PMIC8XXX RTC. | ||
1043 | |||
1044 | To compile this driver as a module, choose M here: the | ||
1045 | module will be called rtc-pm8xxx. | ||
1046 | |||
1037 | config RTC_DRV_TEGRA | 1047 | config RTC_DRV_TEGRA |
1038 | tristate "NVIDIA Tegra Internal RTC driver" | 1048 | tristate "NVIDIA Tegra Internal RTC driver" |
1039 | depends on RTC_CLASS && ARCH_TEGRA | 1049 | depends on RTC_CLASS && ARCH_TEGRA |
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 0ffefe877bfa..6e6982335c10 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile | |||
@@ -77,6 +77,7 @@ obj-$(CONFIG_RTC_DRV_PCF2123) += rtc-pcf2123.o | |||
77 | obj-$(CONFIG_RTC_DRV_PCF50633) += rtc-pcf50633.o | 77 | obj-$(CONFIG_RTC_DRV_PCF50633) += rtc-pcf50633.o |
78 | obj-$(CONFIG_RTC_DRV_PL030) += rtc-pl030.o | 78 | obj-$(CONFIG_RTC_DRV_PL030) += rtc-pl030.o |
79 | obj-$(CONFIG_RTC_DRV_PL031) += rtc-pl031.o | 79 | obj-$(CONFIG_RTC_DRV_PL031) += rtc-pl031.o |
80 | obj-$(CONFIG_RTC_DRV_PM8XXX) += rtc-pm8xxx.o | ||
80 | obj-$(CONFIG_RTC_DRV_PS3) += rtc-ps3.o | 81 | obj-$(CONFIG_RTC_DRV_PS3) += rtc-ps3.o |
81 | obj-$(CONFIG_RTC_DRV_PUV3) += rtc-puv3.o | 82 | obj-$(CONFIG_RTC_DRV_PUV3) += rtc-puv3.o |
82 | obj-$(CONFIG_RTC_DRV_PXA) += rtc-pxa.o | 83 | obj-$(CONFIG_RTC_DRV_PXA) += rtc-pxa.o |
diff --git a/drivers/rtc/rtc-mpc5121.c b/drivers/rtc/rtc-mpc5121.c index 09ccd8d3ba2a..da60915818b6 100644 --- a/drivers/rtc/rtc-mpc5121.c +++ b/drivers/rtc/rtc-mpc5121.c | |||
@@ -3,6 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Copyright 2007, Domen Puncer <domen.puncer@telargo.com> | 4 | * Copyright 2007, Domen Puncer <domen.puncer@telargo.com> |
5 | * Copyright 2008, Freescale Semiconductor, Inc. All rights reserved. | 5 | * Copyright 2008, Freescale Semiconductor, Inc. All rights reserved. |
6 | * Copyright 2011, Dmitry Eremin-Solenikov | ||
6 | * | 7 | * |
7 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
8 | * it under the terms of the GNU General Public License version 2 as | 9 | * it under the terms of the GNU General Public License version 2 as |
@@ -145,6 +146,55 @@ static int mpc5121_rtc_set_time(struct device *dev, struct rtc_time *tm) | |||
145 | return 0; | 146 | return 0; |
146 | } | 147 | } |
147 | 148 | ||
149 | static int mpc5200_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
150 | { | ||
151 | struct mpc5121_rtc_data *rtc = dev_get_drvdata(dev); | ||
152 | struct mpc5121_rtc_regs __iomem *regs = rtc->regs; | ||
153 | int tmp; | ||
154 | |||
155 | tm->tm_sec = in_8(®s->second); | ||
156 | tm->tm_min = in_8(®s->minute); | ||
157 | |||
158 | /* 12 hour format? */ | ||
159 | if (in_8(®s->hour) & 0x20) | ||
160 | tm->tm_hour = (in_8(®s->hour) >> 1) + | ||
161 | (in_8(®s->hour) & 1 ? 12 : 0); | ||
162 | else | ||
163 | tm->tm_hour = in_8(®s->hour); | ||
164 | |||
165 | tmp = in_8(®s->wday_mday); | ||
166 | tm->tm_mday = tmp & 0x1f; | ||
167 | tm->tm_mon = in_8(®s->month) - 1; | ||
168 | tm->tm_year = in_be16(®s->year) - 1900; | ||
169 | tm->tm_wday = (tmp >> 5) % 7; | ||
170 | tm->tm_yday = rtc_year_days(tm->tm_mday, tm->tm_mon, tm->tm_year); | ||
171 | tm->tm_isdst = 0; | ||
172 | |||
173 | return 0; | ||
174 | } | ||
175 | |||
176 | static int mpc5200_rtc_set_time(struct device *dev, struct rtc_time *tm) | ||
177 | { | ||
178 | struct mpc5121_rtc_data *rtc = dev_get_drvdata(dev); | ||
179 | struct mpc5121_rtc_regs __iomem *regs = rtc->regs; | ||
180 | |||
181 | mpc5121_rtc_update_smh(regs, tm); | ||
182 | |||
183 | /* date */ | ||
184 | out_8(®s->month_set, tm->tm_mon + 1); | ||
185 | out_8(®s->weekday_set, tm->tm_wday ? tm->tm_wday : 7); | ||
186 | out_8(®s->date_set, tm->tm_mday); | ||
187 | out_be16(®s->year_set, tm->tm_year + 1900); | ||
188 | |||
189 | /* set date sequence */ | ||
190 | out_8(®s->set_date, 0x1); | ||
191 | out_8(®s->set_date, 0x3); | ||
192 | out_8(®s->set_date, 0x1); | ||
193 | out_8(®s->set_date, 0x0); | ||
194 | |||
195 | return 0; | ||
196 | } | ||
197 | |||
148 | static int mpc5121_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) | 198 | static int mpc5121_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) |
149 | { | 199 | { |
150 | struct mpc5121_rtc_data *rtc = dev_get_drvdata(dev); | 200 | struct mpc5121_rtc_data *rtc = dev_get_drvdata(dev); |
@@ -248,11 +298,18 @@ static const struct rtc_class_ops mpc5121_rtc_ops = { | |||
248 | .alarm_irq_enable = mpc5121_rtc_alarm_irq_enable, | 298 | .alarm_irq_enable = mpc5121_rtc_alarm_irq_enable, |
249 | }; | 299 | }; |
250 | 300 | ||
301 | static const struct rtc_class_ops mpc5200_rtc_ops = { | ||
302 | .read_time = mpc5200_rtc_read_time, | ||
303 | .set_time = mpc5200_rtc_set_time, | ||
304 | .read_alarm = mpc5121_rtc_read_alarm, | ||
305 | .set_alarm = mpc5121_rtc_set_alarm, | ||
306 | .alarm_irq_enable = mpc5121_rtc_alarm_irq_enable, | ||
307 | }; | ||
308 | |||
251 | static int __devinit mpc5121_rtc_probe(struct platform_device *op) | 309 | static int __devinit mpc5121_rtc_probe(struct platform_device *op) |
252 | { | 310 | { |
253 | struct mpc5121_rtc_data *rtc; | 311 | struct mpc5121_rtc_data *rtc; |
254 | int err = 0; | 312 | int err = 0; |
255 | u32 ka; | ||
256 | 313 | ||
257 | rtc = kzalloc(sizeof(*rtc), GFP_KERNEL); | 314 | rtc = kzalloc(sizeof(*rtc), GFP_KERNEL); |
258 | if (!rtc) | 315 | if (!rtc) |
@@ -287,15 +344,22 @@ static int __devinit mpc5121_rtc_probe(struct platform_device *op) | |||
287 | goto out_dispose2; | 344 | goto out_dispose2; |
288 | } | 345 | } |
289 | 346 | ||
290 | ka = in_be32(&rtc->regs->keep_alive); | 347 | if (of_device_is_compatible(op->dev.of_node, "fsl,mpc5121-rtc")) { |
291 | if (ka & 0x02) { | 348 | u32 ka; |
292 | dev_warn(&op->dev, | 349 | ka = in_be32(&rtc->regs->keep_alive); |
293 | "mpc5121-rtc: Battery or oscillator failure!\n"); | 350 | if (ka & 0x02) { |
294 | out_be32(&rtc->regs->keep_alive, ka); | 351 | dev_warn(&op->dev, |
352 | "mpc5121-rtc: Battery or oscillator failure!\n"); | ||
353 | out_be32(&rtc->regs->keep_alive, ka); | ||
354 | } | ||
355 | |||
356 | rtc->rtc = rtc_device_register("mpc5121-rtc", &op->dev, | ||
357 | &mpc5121_rtc_ops, THIS_MODULE); | ||
358 | } else { | ||
359 | rtc->rtc = rtc_device_register("mpc5200-rtc", &op->dev, | ||
360 | &mpc5200_rtc_ops, THIS_MODULE); | ||
295 | } | 361 | } |
296 | 362 | ||
297 | rtc->rtc = rtc_device_register("mpc5121-rtc", &op->dev, | ||
298 | &mpc5121_rtc_ops, THIS_MODULE); | ||
299 | if (IS_ERR(rtc->rtc)) { | 363 | if (IS_ERR(rtc->rtc)) { |
300 | err = PTR_ERR(rtc->rtc); | 364 | err = PTR_ERR(rtc->rtc); |
301 | goto out_free_irq; | 365 | goto out_free_irq; |
@@ -340,6 +404,7 @@ static int __devexit mpc5121_rtc_remove(struct platform_device *op) | |||
340 | 404 | ||
341 | static struct of_device_id mpc5121_rtc_match[] __devinitdata = { | 405 | static struct of_device_id mpc5121_rtc_match[] __devinitdata = { |
342 | { .compatible = "fsl,mpc5121-rtc", }, | 406 | { .compatible = "fsl,mpc5121-rtc", }, |
407 | { .compatible = "fsl,mpc5200-rtc", }, | ||
343 | {}, | 408 | {}, |
344 | }; | 409 | }; |
345 | 410 | ||
diff --git a/drivers/rtc/rtc-pm8xxx.c b/drivers/rtc/rtc-pm8xxx.c new file mode 100644 index 000000000000..d420e9d877e8 --- /dev/null +++ b/drivers/rtc/rtc-pm8xxx.c | |||
@@ -0,0 +1,550 @@ | |||
1 | /* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License version 2 and | ||
5 | * only version 2 as published by the Free Software Foundation. | ||
6 | * | ||
7 | * This program is distributed in the hope that it will be useful, | ||
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
10 | * GNU General Public License for more details. | ||
11 | */ | ||
12 | |||
13 | #include <linux/module.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/rtc.h> | ||
16 | #include <linux/pm.h> | ||
17 | #include <linux/slab.h> | ||
18 | #include <linux/spinlock.h> | ||
19 | |||
20 | #include <linux/mfd/pm8xxx/core.h> | ||
21 | #include <linux/mfd/pm8xxx/rtc.h> | ||
22 | |||
23 | |||
24 | /* RTC Register offsets from RTC CTRL REG */ | ||
25 | #define PM8XXX_ALARM_CTRL_OFFSET 0x01 | ||
26 | #define PM8XXX_RTC_WRITE_OFFSET 0x02 | ||
27 | #define PM8XXX_RTC_READ_OFFSET 0x06 | ||
28 | #define PM8XXX_ALARM_RW_OFFSET 0x0A | ||
29 | |||
30 | /* RTC_CTRL register bit fields */ | ||
31 | #define PM8xxx_RTC_ENABLE BIT(7) | ||
32 | #define PM8xxx_RTC_ALARM_ENABLE BIT(1) | ||
33 | #define PM8xxx_RTC_ALARM_CLEAR BIT(0) | ||
34 | |||
35 | #define NUM_8_BIT_RTC_REGS 0x4 | ||
36 | |||
37 | /** | ||
38 | * struct pm8xxx_rtc - rtc driver internal structure | ||
39 | * @rtc: rtc device for this driver. | ||
40 | * @rtc_alarm_irq: rtc alarm irq number. | ||
41 | * @rtc_base: address of rtc control register. | ||
42 | * @rtc_read_base: base address of read registers. | ||
43 | * @rtc_write_base: base address of write registers. | ||
44 | * @alarm_rw_base: base address of alarm registers. | ||
45 | * @ctrl_reg: rtc control register. | ||
46 | * @rtc_dev: device structure. | ||
47 | * @ctrl_reg_lock: spinlock protecting access to ctrl_reg. | ||
48 | */ | ||
49 | struct pm8xxx_rtc { | ||
50 | struct rtc_device *rtc; | ||
51 | int rtc_alarm_irq; | ||
52 | int rtc_base; | ||
53 | int rtc_read_base; | ||
54 | int rtc_write_base; | ||
55 | int alarm_rw_base; | ||
56 | u8 ctrl_reg; | ||
57 | struct device *rtc_dev; | ||
58 | spinlock_t ctrl_reg_lock; | ||
59 | }; | ||
60 | |||
61 | /* | ||
62 | * The RTC registers need to be read/written one byte at a time. This is a | ||
63 | * hardware limitation. | ||
64 | */ | ||
65 | static int pm8xxx_read_wrapper(struct pm8xxx_rtc *rtc_dd, u8 *rtc_val, | ||
66 | int base, int count) | ||
67 | { | ||
68 | int i, rc; | ||
69 | struct device *parent = rtc_dd->rtc_dev->parent; | ||
70 | |||
71 | for (i = 0; i < count; i++) { | ||
72 | rc = pm8xxx_readb(parent, base + i, &rtc_val[i]); | ||
73 | if (rc < 0) { | ||
74 | dev_err(rtc_dd->rtc_dev, "PMIC read failed\n"); | ||
75 | return rc; | ||
76 | } | ||
77 | } | ||
78 | |||
79 | return 0; | ||
80 | } | ||
81 | |||
82 | static int pm8xxx_write_wrapper(struct pm8xxx_rtc *rtc_dd, u8 *rtc_val, | ||
83 | int base, int count) | ||
84 | { | ||
85 | int i, rc; | ||
86 | struct device *parent = rtc_dd->rtc_dev->parent; | ||
87 | |||
88 | for (i = 0; i < count; i++) { | ||
89 | rc = pm8xxx_writeb(parent, base + i, rtc_val[i]); | ||
90 | if (rc < 0) { | ||
91 | dev_err(rtc_dd->rtc_dev, "PMIC write failed\n"); | ||
92 | return rc; | ||
93 | } | ||
94 | } | ||
95 | |||
96 | return 0; | ||
97 | } | ||
98 | |||
99 | /* | ||
100 | * Steps to write the RTC registers. | ||
101 | * 1. Disable alarm if enabled. | ||
102 | * 2. Write 0x00 to LSB. | ||
103 | * 3. Write Byte[1], Byte[2], Byte[3] then Byte[0]. | ||
104 | * 4. Enable alarm if disabled in step 1. | ||
105 | */ | ||
106 | static int pm8xxx_rtc_set_time(struct device *dev, struct rtc_time *tm) | ||
107 | { | ||
108 | int rc, i; | ||
109 | unsigned long secs, irq_flags; | ||
110 | u8 value[NUM_8_BIT_RTC_REGS], reg = 0, alarm_enabled = 0, ctrl_reg; | ||
111 | struct pm8xxx_rtc *rtc_dd = dev_get_drvdata(dev); | ||
112 | |||
113 | rtc_tm_to_time(tm, &secs); | ||
114 | |||
115 | for (i = 0; i < NUM_8_BIT_RTC_REGS; i++) { | ||
116 | value[i] = secs & 0xFF; | ||
117 | secs >>= 8; | ||
118 | } | ||
119 | |||
120 | dev_dbg(dev, "Seconds value to be written to RTC = %lu\n", secs); | ||
121 | |||
122 | spin_lock_irqsave(&rtc_dd->ctrl_reg_lock, irq_flags); | ||
123 | ctrl_reg = rtc_dd->ctrl_reg; | ||
124 | |||
125 | if (ctrl_reg & PM8xxx_RTC_ALARM_ENABLE) { | ||
126 | alarm_enabled = 1; | ||
127 | ctrl_reg &= ~PM8xxx_RTC_ALARM_ENABLE; | ||
128 | rc = pm8xxx_write_wrapper(rtc_dd, &ctrl_reg, rtc_dd->rtc_base, | ||
129 | 1); | ||
130 | if (rc < 0) { | ||
131 | dev_err(dev, "Write to RTC control register " | ||
132 | "failed\n"); | ||
133 | goto rtc_rw_fail; | ||
134 | } | ||
135 | rtc_dd->ctrl_reg = ctrl_reg; | ||
136 | } else | ||
137 | spin_unlock_irqrestore(&rtc_dd->ctrl_reg_lock, irq_flags); | ||
138 | |||
139 | /* Write 0 to Byte[0] */ | ||
140 | reg = 0; | ||
141 | rc = pm8xxx_write_wrapper(rtc_dd, ®, rtc_dd->rtc_write_base, 1); | ||
142 | if (rc < 0) { | ||
143 | dev_err(dev, "Write to RTC write data register failed\n"); | ||
144 | goto rtc_rw_fail; | ||
145 | } | ||
146 | |||
147 | /* Write Byte[1], Byte[2], Byte[3] */ | ||
148 | rc = pm8xxx_write_wrapper(rtc_dd, value + 1, | ||
149 | rtc_dd->rtc_write_base + 1, 3); | ||
150 | if (rc < 0) { | ||
151 | dev_err(dev, "Write to RTC write data register failed\n"); | ||
152 | goto rtc_rw_fail; | ||
153 | } | ||
154 | |||
155 | /* Write Byte[0] */ | ||
156 | rc = pm8xxx_write_wrapper(rtc_dd, value, rtc_dd->rtc_write_base, 1); | ||
157 | if (rc < 0) { | ||
158 | dev_err(dev, "Write to RTC write data register failed\n"); | ||
159 | goto rtc_rw_fail; | ||
160 | } | ||
161 | |||
162 | if (alarm_enabled) { | ||
163 | ctrl_reg |= PM8xxx_RTC_ALARM_ENABLE; | ||
164 | rc = pm8xxx_write_wrapper(rtc_dd, &ctrl_reg, rtc_dd->rtc_base, | ||
165 | 1); | ||
166 | if (rc < 0) { | ||
167 | dev_err(dev, "Write to RTC control register " | ||
168 | "failed\n"); | ||
169 | goto rtc_rw_fail; | ||
170 | } | ||
171 | rtc_dd->ctrl_reg = ctrl_reg; | ||
172 | } | ||
173 | |||
174 | rtc_rw_fail: | ||
175 | if (alarm_enabled) | ||
176 | spin_unlock_irqrestore(&rtc_dd->ctrl_reg_lock, irq_flags); | ||
177 | |||
178 | return rc; | ||
179 | } | ||
180 | |||
181 | static int pm8xxx_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
182 | { | ||
183 | int rc; | ||
184 | u8 value[NUM_8_BIT_RTC_REGS], reg; | ||
185 | unsigned long secs; | ||
186 | struct pm8xxx_rtc *rtc_dd = dev_get_drvdata(dev); | ||
187 | |||
188 | rc = pm8xxx_read_wrapper(rtc_dd, value, rtc_dd->rtc_read_base, | ||
189 | NUM_8_BIT_RTC_REGS); | ||
190 | if (rc < 0) { | ||
191 | dev_err(dev, "RTC read data register failed\n"); | ||
192 | return rc; | ||
193 | } | ||
194 | |||
195 | /* | ||
196 | * Read the LSB again and check if there has been a carry over. | ||
197 | * If there is, redo the read operation. | ||
198 | */ | ||
199 | rc = pm8xxx_read_wrapper(rtc_dd, ®, rtc_dd->rtc_read_base, 1); | ||
200 | if (rc < 0) { | ||
201 | dev_err(dev, "RTC read data register failed\n"); | ||
202 | return rc; | ||
203 | } | ||
204 | |||
205 | if (unlikely(reg < value[0])) { | ||
206 | rc = pm8xxx_read_wrapper(rtc_dd, value, | ||
207 | rtc_dd->rtc_read_base, NUM_8_BIT_RTC_REGS); | ||
208 | if (rc < 0) { | ||
209 | dev_err(dev, "RTC read data register failed\n"); | ||
210 | return rc; | ||
211 | } | ||
212 | } | ||
213 | |||
214 | secs = value[0] | (value[1] << 8) | (value[2] << 16) | (value[3] << 24); | ||
215 | |||
216 | rtc_time_to_tm(secs, tm); | ||
217 | |||
218 | rc = rtc_valid_tm(tm); | ||
219 | if (rc < 0) { | ||
220 | dev_err(dev, "Invalid time read from RTC\n"); | ||
221 | return rc; | ||
222 | } | ||
223 | |||
224 | dev_dbg(dev, "secs = %lu, h:m:s == %d:%d:%d, d/m/y = %d/%d/%d\n", | ||
225 | secs, tm->tm_hour, tm->tm_min, tm->tm_sec, | ||
226 | tm->tm_mday, tm->tm_mon, tm->tm_year); | ||
227 | |||
228 | return 0; | ||
229 | } | ||
230 | |||
231 | static int pm8xxx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) | ||
232 | { | ||
233 | int rc, i; | ||
234 | u8 value[NUM_8_BIT_RTC_REGS], ctrl_reg; | ||
235 | unsigned long secs, irq_flags; | ||
236 | struct pm8xxx_rtc *rtc_dd = dev_get_drvdata(dev); | ||
237 | |||
238 | rtc_tm_to_time(&alarm->time, &secs); | ||
239 | |||
240 | for (i = 0; i < NUM_8_BIT_RTC_REGS; i++) { | ||
241 | value[i] = secs & 0xFF; | ||
242 | secs >>= 8; | ||
243 | } | ||
244 | |||
245 | spin_lock_irqsave(&rtc_dd->ctrl_reg_lock, irq_flags); | ||
246 | |||
247 | rc = pm8xxx_write_wrapper(rtc_dd, value, rtc_dd->alarm_rw_base, | ||
248 | NUM_8_BIT_RTC_REGS); | ||
249 | if (rc < 0) { | ||
250 | dev_err(dev, "Write to RTC ALARM register failed\n"); | ||
251 | goto rtc_rw_fail; | ||
252 | } | ||
253 | |||
254 | ctrl_reg = rtc_dd->ctrl_reg; | ||
255 | ctrl_reg = alarm->enabled ? (ctrl_reg | PM8xxx_RTC_ALARM_ENABLE) : | ||
256 | (ctrl_reg & ~PM8xxx_RTC_ALARM_ENABLE); | ||
257 | |||
258 | rc = pm8xxx_write_wrapper(rtc_dd, &ctrl_reg, rtc_dd->rtc_base, 1); | ||
259 | if (rc < 0) { | ||
260 | dev_err(dev, "Write to RTC control register failed\n"); | ||
261 | goto rtc_rw_fail; | ||
262 | } | ||
263 | |||
264 | rtc_dd->ctrl_reg = ctrl_reg; | ||
265 | |||
266 | dev_dbg(dev, "Alarm Set for h:r:s=%d:%d:%d, d/m/y=%d/%d/%d\n", | ||
267 | alarm->time.tm_hour, alarm->time.tm_min, | ||
268 | alarm->time.tm_sec, alarm->time.tm_mday, | ||
269 | alarm->time.tm_mon, alarm->time.tm_year); | ||
270 | rtc_rw_fail: | ||
271 | spin_unlock_irqrestore(&rtc_dd->ctrl_reg_lock, irq_flags); | ||
272 | return rc; | ||
273 | } | ||
274 | |||
275 | static int pm8xxx_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) | ||
276 | { | ||
277 | int rc; | ||
278 | u8 value[NUM_8_BIT_RTC_REGS]; | ||
279 | unsigned long secs; | ||
280 | struct pm8xxx_rtc *rtc_dd = dev_get_drvdata(dev); | ||
281 | |||
282 | rc = pm8xxx_read_wrapper(rtc_dd, value, rtc_dd->alarm_rw_base, | ||
283 | NUM_8_BIT_RTC_REGS); | ||
284 | if (rc < 0) { | ||
285 | dev_err(dev, "RTC alarm time read failed\n"); | ||
286 | return rc; | ||
287 | } | ||
288 | |||
289 | secs = value[0] | (value[1] << 8) | (value[2] << 16) | (value[3] << 24); | ||
290 | |||
291 | rtc_time_to_tm(secs, &alarm->time); | ||
292 | |||
293 | rc = rtc_valid_tm(&alarm->time); | ||
294 | if (rc < 0) { | ||
295 | dev_err(dev, "Invalid alarm time read from RTC\n"); | ||
296 | return rc; | ||
297 | } | ||
298 | |||
299 | dev_dbg(dev, "Alarm set for - h:r:s=%d:%d:%d, d/m/y=%d/%d/%d\n", | ||
300 | alarm->time.tm_hour, alarm->time.tm_min, | ||
301 | alarm->time.tm_sec, alarm->time.tm_mday, | ||
302 | alarm->time.tm_mon, alarm->time.tm_year); | ||
303 | |||
304 | return 0; | ||
305 | } | ||
306 | |||
307 | static int pm8xxx_rtc_alarm_irq_enable(struct device *dev, unsigned int enable) | ||
308 | { | ||
309 | int rc; | ||
310 | unsigned long irq_flags; | ||
311 | struct pm8xxx_rtc *rtc_dd = dev_get_drvdata(dev); | ||
312 | u8 ctrl_reg; | ||
313 | |||
314 | spin_lock_irqsave(&rtc_dd->ctrl_reg_lock, irq_flags); | ||
315 | ctrl_reg = rtc_dd->ctrl_reg; | ||
316 | ctrl_reg = (enable) ? (ctrl_reg | PM8xxx_RTC_ALARM_ENABLE) : | ||
317 | (ctrl_reg & ~PM8xxx_RTC_ALARM_ENABLE); | ||
318 | |||
319 | rc = pm8xxx_write_wrapper(rtc_dd, &ctrl_reg, rtc_dd->rtc_base, 1); | ||
320 | if (rc < 0) { | ||
321 | dev_err(dev, "Write to RTC control register failed\n"); | ||
322 | goto rtc_rw_fail; | ||
323 | } | ||
324 | |||
325 | rtc_dd->ctrl_reg = ctrl_reg; | ||
326 | |||
327 | rtc_rw_fail: | ||
328 | spin_unlock_irqrestore(&rtc_dd->ctrl_reg_lock, irq_flags); | ||
329 | return rc; | ||
330 | } | ||
331 | |||
332 | static struct rtc_class_ops pm8xxx_rtc_ops = { | ||
333 | .read_time = pm8xxx_rtc_read_time, | ||
334 | .set_alarm = pm8xxx_rtc_set_alarm, | ||
335 | .read_alarm = pm8xxx_rtc_read_alarm, | ||
336 | .alarm_irq_enable = pm8xxx_rtc_alarm_irq_enable, | ||
337 | }; | ||
338 | |||
339 | static irqreturn_t pm8xxx_alarm_trigger(int irq, void *dev_id) | ||
340 | { | ||
341 | struct pm8xxx_rtc *rtc_dd = dev_id; | ||
342 | u8 ctrl_reg; | ||
343 | int rc; | ||
344 | unsigned long irq_flags; | ||
345 | |||
346 | rtc_update_irq(rtc_dd->rtc, 1, RTC_IRQF | RTC_AF); | ||
347 | |||
348 | spin_lock_irqsave(&rtc_dd->ctrl_reg_lock, irq_flags); | ||
349 | |||
350 | /* Clear the alarm enable bit */ | ||
351 | ctrl_reg = rtc_dd->ctrl_reg; | ||
352 | ctrl_reg &= ~PM8xxx_RTC_ALARM_ENABLE; | ||
353 | |||
354 | rc = pm8xxx_write_wrapper(rtc_dd, &ctrl_reg, rtc_dd->rtc_base, 1); | ||
355 | if (rc < 0) { | ||
356 | spin_unlock_irqrestore(&rtc_dd->ctrl_reg_lock, irq_flags); | ||
357 | dev_err(rtc_dd->rtc_dev, "Write to RTC control register " | ||
358 | "failed\n"); | ||
359 | goto rtc_alarm_handled; | ||
360 | } | ||
361 | |||
362 | rtc_dd->ctrl_reg = ctrl_reg; | ||
363 | spin_unlock_irqrestore(&rtc_dd->ctrl_reg_lock, irq_flags); | ||
364 | |||
365 | /* Clear RTC alarm register */ | ||
366 | rc = pm8xxx_read_wrapper(rtc_dd, &ctrl_reg, rtc_dd->rtc_base + | ||
367 | PM8XXX_ALARM_CTRL_OFFSET, 1); | ||
368 | if (rc < 0) { | ||
369 | dev_err(rtc_dd->rtc_dev, "RTC Alarm control register read " | ||
370 | "failed\n"); | ||
371 | goto rtc_alarm_handled; | ||
372 | } | ||
373 | |||
374 | ctrl_reg &= ~PM8xxx_RTC_ALARM_CLEAR; | ||
375 | rc = pm8xxx_write_wrapper(rtc_dd, &ctrl_reg, rtc_dd->rtc_base + | ||
376 | PM8XXX_ALARM_CTRL_OFFSET, 1); | ||
377 | if (rc < 0) | ||
378 | dev_err(rtc_dd->rtc_dev, "Write to RTC Alarm control register" | ||
379 | " failed\n"); | ||
380 | |||
381 | rtc_alarm_handled: | ||
382 | return IRQ_HANDLED; | ||
383 | } | ||
384 | |||
385 | static int __devinit pm8xxx_rtc_probe(struct platform_device *pdev) | ||
386 | { | ||
387 | int rc; | ||
388 | u8 ctrl_reg; | ||
389 | bool rtc_write_enable = false; | ||
390 | struct pm8xxx_rtc *rtc_dd; | ||
391 | struct resource *rtc_resource; | ||
392 | const struct pm8xxx_rtc_platform_data *pdata = | ||
393 | dev_get_platdata(&pdev->dev); | ||
394 | |||
395 | if (pdata != NULL) | ||
396 | rtc_write_enable = pdata->rtc_write_enable; | ||
397 | |||
398 | rtc_dd = kzalloc(sizeof(*rtc_dd), GFP_KERNEL); | ||
399 | if (rtc_dd == NULL) { | ||
400 | dev_err(&pdev->dev, "Unable to allocate memory!\n"); | ||
401 | return -ENOMEM; | ||
402 | } | ||
403 | |||
404 | /* Initialise spinlock to protect RTC control register */ | ||
405 | spin_lock_init(&rtc_dd->ctrl_reg_lock); | ||
406 | |||
407 | rtc_dd->rtc_alarm_irq = platform_get_irq(pdev, 0); | ||
408 | if (rtc_dd->rtc_alarm_irq < 0) { | ||
409 | dev_err(&pdev->dev, "Alarm IRQ resource absent!\n"); | ||
410 | rc = -ENXIO; | ||
411 | goto fail_rtc_enable; | ||
412 | } | ||
413 | |||
414 | rtc_resource = platform_get_resource_byname(pdev, IORESOURCE_IO, | ||
415 | "pmic_rtc_base"); | ||
416 | if (!(rtc_resource && rtc_resource->start)) { | ||
417 | dev_err(&pdev->dev, "RTC IO resource absent!\n"); | ||
418 | rc = -ENXIO; | ||
419 | goto fail_rtc_enable; | ||
420 | } | ||
421 | |||
422 | rtc_dd->rtc_base = rtc_resource->start; | ||
423 | |||
424 | /* Setup RTC register addresses */ | ||
425 | rtc_dd->rtc_write_base = rtc_dd->rtc_base + PM8XXX_RTC_WRITE_OFFSET; | ||
426 | rtc_dd->rtc_read_base = rtc_dd->rtc_base + PM8XXX_RTC_READ_OFFSET; | ||
427 | rtc_dd->alarm_rw_base = rtc_dd->rtc_base + PM8XXX_ALARM_RW_OFFSET; | ||
428 | |||
429 | rtc_dd->rtc_dev = &pdev->dev; | ||
430 | |||
431 | /* Check if the RTC is on, else turn it on */ | ||
432 | rc = pm8xxx_read_wrapper(rtc_dd, &ctrl_reg, rtc_dd->rtc_base, 1); | ||
433 | if (rc < 0) { | ||
434 | dev_err(&pdev->dev, "RTC control register read failed!\n"); | ||
435 | goto fail_rtc_enable; | ||
436 | } | ||
437 | |||
438 | if (!(ctrl_reg & PM8xxx_RTC_ENABLE)) { | ||
439 | ctrl_reg |= PM8xxx_RTC_ENABLE; | ||
440 | rc = pm8xxx_write_wrapper(rtc_dd, &ctrl_reg, rtc_dd->rtc_base, | ||
441 | 1); | ||
442 | if (rc < 0) { | ||
443 | dev_err(&pdev->dev, "Write to RTC control register " | ||
444 | "failed\n"); | ||
445 | goto fail_rtc_enable; | ||
446 | } | ||
447 | } | ||
448 | |||
449 | rtc_dd->ctrl_reg = ctrl_reg; | ||
450 | if (rtc_write_enable == true) | ||
451 | pm8xxx_rtc_ops.set_time = pm8xxx_rtc_set_time; | ||
452 | |||
453 | platform_set_drvdata(pdev, rtc_dd); | ||
454 | |||
455 | /* Register the RTC device */ | ||
456 | rtc_dd->rtc = rtc_device_register("pm8xxx_rtc", &pdev->dev, | ||
457 | &pm8xxx_rtc_ops, THIS_MODULE); | ||
458 | if (IS_ERR(rtc_dd->rtc)) { | ||
459 | dev_err(&pdev->dev, "%s: RTC registration failed (%ld)\n", | ||
460 | __func__, PTR_ERR(rtc_dd->rtc)); | ||
461 | rc = PTR_ERR(rtc_dd->rtc); | ||
462 | goto fail_rtc_enable; | ||
463 | } | ||
464 | |||
465 | /* Request the alarm IRQ */ | ||
466 | rc = request_any_context_irq(rtc_dd->rtc_alarm_irq, | ||
467 | pm8xxx_alarm_trigger, IRQF_TRIGGER_RISING, | ||
468 | "pm8xxx_rtc_alarm", rtc_dd); | ||
469 | if (rc < 0) { | ||
470 | dev_err(&pdev->dev, "Request IRQ failed (%d)\n", rc); | ||
471 | goto fail_req_irq; | ||
472 | } | ||
473 | |||
474 | device_init_wakeup(&pdev->dev, 1); | ||
475 | |||
476 | dev_dbg(&pdev->dev, "Probe success !!\n"); | ||
477 | |||
478 | return 0; | ||
479 | |||
480 | fail_req_irq: | ||
481 | rtc_device_unregister(rtc_dd->rtc); | ||
482 | fail_rtc_enable: | ||
483 | platform_set_drvdata(pdev, NULL); | ||
484 | kfree(rtc_dd); | ||
485 | return rc; | ||
486 | } | ||
487 | |||
488 | static int __devexit pm8xxx_rtc_remove(struct platform_device *pdev) | ||
489 | { | ||
490 | struct pm8xxx_rtc *rtc_dd = platform_get_drvdata(pdev); | ||
491 | |||
492 | device_init_wakeup(&pdev->dev, 0); | ||
493 | free_irq(rtc_dd->rtc_alarm_irq, rtc_dd); | ||
494 | rtc_device_unregister(rtc_dd->rtc); | ||
495 | platform_set_drvdata(pdev, NULL); | ||
496 | kfree(rtc_dd); | ||
497 | |||
498 | return 0; | ||
499 | } | ||
500 | |||
501 | #ifdef CONFIG_PM_SLEEP | ||
502 | static int pm8xxx_rtc_resume(struct device *dev) | ||
503 | { | ||
504 | struct pm8xxx_rtc *rtc_dd = dev_get_drvdata(dev); | ||
505 | |||
506 | if (device_may_wakeup(dev)) | ||
507 | disable_irq_wake(rtc_dd->rtc_alarm_irq); | ||
508 | |||
509 | return 0; | ||
510 | } | ||
511 | |||
512 | static int pm8xxx_rtc_suspend(struct device *dev) | ||
513 | { | ||
514 | struct pm8xxx_rtc *rtc_dd = dev_get_drvdata(dev); | ||
515 | |||
516 | if (device_may_wakeup(dev)) | ||
517 | enable_irq_wake(rtc_dd->rtc_alarm_irq); | ||
518 | |||
519 | return 0; | ||
520 | } | ||
521 | #endif | ||
522 | |||
523 | SIMPLE_DEV_PM_OPS(pm8xxx_rtc_pm_ops, pm8xxx_rtc_suspend, pm8xxx_rtc_resume); | ||
524 | |||
525 | static struct platform_driver pm8xxx_rtc_driver = { | ||
526 | .probe = pm8xxx_rtc_probe, | ||
527 | .remove = __devexit_p(pm8xxx_rtc_remove), | ||
528 | .driver = { | ||
529 | .name = PM8XXX_RTC_DEV_NAME, | ||
530 | .owner = THIS_MODULE, | ||
531 | .pm = &pm8xxx_rtc_pm_ops, | ||
532 | }, | ||
533 | }; | ||
534 | |||
535 | static int __init pm8xxx_rtc_init(void) | ||
536 | { | ||
537 | return platform_driver_register(&pm8xxx_rtc_driver); | ||
538 | } | ||
539 | module_init(pm8xxx_rtc_init); | ||
540 | |||
541 | static void __exit pm8xxx_rtc_exit(void) | ||
542 | { | ||
543 | platform_driver_unregister(&pm8xxx_rtc_driver); | ||
544 | } | ||
545 | module_exit(pm8xxx_rtc_exit); | ||
546 | |||
547 | MODULE_ALIAS("platform:rtc-pm8xxx"); | ||
548 | MODULE_DESCRIPTION("PMIC8xxx RTC driver"); | ||
549 | MODULE_LICENSE("GPL v2"); | ||
550 | MODULE_AUTHOR("Anirudh Ghayal <aghayal@codeaurora.org>"); | ||
diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c index 2a65e85e0f56..9329dbb9ebab 100644 --- a/drivers/rtc/rtc-s3c.c +++ b/drivers/rtc/rtc-s3c.c | |||
@@ -57,11 +57,13 @@ static irqreturn_t s3c_rtc_alarmirq(int irq, void *id) | |||
57 | { | 57 | { |
58 | struct rtc_device *rdev = id; | 58 | struct rtc_device *rdev = id; |
59 | 59 | ||
60 | clk_enable(rtc_clk); | ||
60 | rtc_update_irq(rdev, 1, RTC_AF | RTC_IRQF); | 61 | rtc_update_irq(rdev, 1, RTC_AF | RTC_IRQF); |
61 | 62 | ||
62 | if (s3c_rtc_cpu_type == TYPE_S3C64XX) | 63 | if (s3c_rtc_cpu_type == TYPE_S3C64XX) |
63 | writeb(S3C2410_INTP_ALM, s3c_rtc_base + S3C2410_INTP); | 64 | writeb(S3C2410_INTP_ALM, s3c_rtc_base + S3C2410_INTP); |
64 | 65 | ||
66 | clk_disable(rtc_clk); | ||
65 | return IRQ_HANDLED; | 67 | return IRQ_HANDLED; |
66 | } | 68 | } |
67 | 69 | ||
@@ -69,11 +71,13 @@ static irqreturn_t s3c_rtc_tickirq(int irq, void *id) | |||
69 | { | 71 | { |
70 | struct rtc_device *rdev = id; | 72 | struct rtc_device *rdev = id; |
71 | 73 | ||
74 | clk_enable(rtc_clk); | ||
72 | rtc_update_irq(rdev, 1, RTC_PF | RTC_IRQF); | 75 | rtc_update_irq(rdev, 1, RTC_PF | RTC_IRQF); |
73 | 76 | ||
74 | if (s3c_rtc_cpu_type == TYPE_S3C64XX) | 77 | if (s3c_rtc_cpu_type == TYPE_S3C64XX) |
75 | writeb(S3C2410_INTP_TIC, s3c_rtc_base + S3C2410_INTP); | 78 | writeb(S3C2410_INTP_TIC, s3c_rtc_base + S3C2410_INTP); |
76 | 79 | ||
80 | clk_disable(rtc_clk); | ||
77 | return IRQ_HANDLED; | 81 | return IRQ_HANDLED; |
78 | } | 82 | } |
79 | 83 | ||
@@ -84,12 +88,14 @@ static int s3c_rtc_setaie(struct device *dev, unsigned int enabled) | |||
84 | 88 | ||
85 | pr_debug("%s: aie=%d\n", __func__, enabled); | 89 | pr_debug("%s: aie=%d\n", __func__, enabled); |
86 | 90 | ||
91 | clk_enable(rtc_clk); | ||
87 | tmp = readb(s3c_rtc_base + S3C2410_RTCALM) & ~S3C2410_RTCALM_ALMEN; | 92 | tmp = readb(s3c_rtc_base + S3C2410_RTCALM) & ~S3C2410_RTCALM_ALMEN; |
88 | 93 | ||
89 | if (enabled) | 94 | if (enabled) |
90 | tmp |= S3C2410_RTCALM_ALMEN; | 95 | tmp |= S3C2410_RTCALM_ALMEN; |
91 | 96 | ||
92 | writeb(tmp, s3c_rtc_base + S3C2410_RTCALM); | 97 | writeb(tmp, s3c_rtc_base + S3C2410_RTCALM); |
98 | clk_disable(rtc_clk); | ||
93 | 99 | ||
94 | return 0; | 100 | return 0; |
95 | } | 101 | } |
@@ -103,6 +109,7 @@ static int s3c_rtc_setfreq(struct device *dev, int freq) | |||
103 | if (!is_power_of_2(freq)) | 109 | if (!is_power_of_2(freq)) |
104 | return -EINVAL; | 110 | return -EINVAL; |
105 | 111 | ||
112 | clk_enable(rtc_clk); | ||
106 | spin_lock_irq(&s3c_rtc_pie_lock); | 113 | spin_lock_irq(&s3c_rtc_pie_lock); |
107 | 114 | ||
108 | if (s3c_rtc_cpu_type == TYPE_S3C2410) { | 115 | if (s3c_rtc_cpu_type == TYPE_S3C2410) { |
@@ -114,6 +121,7 @@ static int s3c_rtc_setfreq(struct device *dev, int freq) | |||
114 | 121 | ||
115 | writel(tmp, s3c_rtc_base + S3C2410_TICNT); | 122 | writel(tmp, s3c_rtc_base + S3C2410_TICNT); |
116 | spin_unlock_irq(&s3c_rtc_pie_lock); | 123 | spin_unlock_irq(&s3c_rtc_pie_lock); |
124 | clk_disable(rtc_clk); | ||
117 | 125 | ||
118 | return 0; | 126 | return 0; |
119 | } | 127 | } |
@@ -125,6 +133,7 @@ static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm) | |||
125 | unsigned int have_retried = 0; | 133 | unsigned int have_retried = 0; |
126 | void __iomem *base = s3c_rtc_base; | 134 | void __iomem *base = s3c_rtc_base; |
127 | 135 | ||
136 | clk_enable(rtc_clk); | ||
128 | retry_get_time: | 137 | retry_get_time: |
129 | rtc_tm->tm_min = readb(base + S3C2410_RTCMIN); | 138 | rtc_tm->tm_min = readb(base + S3C2410_RTCMIN); |
130 | rtc_tm->tm_hour = readb(base + S3C2410_RTCHOUR); | 139 | rtc_tm->tm_hour = readb(base + S3C2410_RTCHOUR); |
@@ -157,6 +166,7 @@ static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm) | |||
157 | rtc_tm->tm_year += 100; | 166 | rtc_tm->tm_year += 100; |
158 | rtc_tm->tm_mon -= 1; | 167 | rtc_tm->tm_mon -= 1; |
159 | 168 | ||
169 | clk_disable(rtc_clk); | ||
160 | return rtc_valid_tm(rtc_tm); | 170 | return rtc_valid_tm(rtc_tm); |
161 | } | 171 | } |
162 | 172 | ||
@@ -165,6 +175,7 @@ static int s3c_rtc_settime(struct device *dev, struct rtc_time *tm) | |||
165 | void __iomem *base = s3c_rtc_base; | 175 | void __iomem *base = s3c_rtc_base; |
166 | int year = tm->tm_year - 100; | 176 | int year = tm->tm_year - 100; |
167 | 177 | ||
178 | clk_enable(rtc_clk); | ||
168 | pr_debug("set time %04d.%02d.%02d %02d:%02d:%02d\n", | 179 | pr_debug("set time %04d.%02d.%02d %02d:%02d:%02d\n", |
169 | 1900 + tm->tm_year, tm->tm_mon, tm->tm_mday, | 180 | 1900 + tm->tm_year, tm->tm_mon, tm->tm_mday, |
170 | tm->tm_hour, tm->tm_min, tm->tm_sec); | 181 | tm->tm_hour, tm->tm_min, tm->tm_sec); |
@@ -182,6 +193,7 @@ static int s3c_rtc_settime(struct device *dev, struct rtc_time *tm) | |||
182 | writeb(bin2bcd(tm->tm_mday), base + S3C2410_RTCDATE); | 193 | writeb(bin2bcd(tm->tm_mday), base + S3C2410_RTCDATE); |
183 | writeb(bin2bcd(tm->tm_mon + 1), base + S3C2410_RTCMON); | 194 | writeb(bin2bcd(tm->tm_mon + 1), base + S3C2410_RTCMON); |
184 | writeb(bin2bcd(year), base + S3C2410_RTCYEAR); | 195 | writeb(bin2bcd(year), base + S3C2410_RTCYEAR); |
196 | clk_disable(rtc_clk); | ||
185 | 197 | ||
186 | return 0; | 198 | return 0; |
187 | } | 199 | } |
@@ -192,6 +204,7 @@ static int s3c_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
192 | void __iomem *base = s3c_rtc_base; | 204 | void __iomem *base = s3c_rtc_base; |
193 | unsigned int alm_en; | 205 | unsigned int alm_en; |
194 | 206 | ||
207 | clk_enable(rtc_clk); | ||
195 | alm_tm->tm_sec = readb(base + S3C2410_ALMSEC); | 208 | alm_tm->tm_sec = readb(base + S3C2410_ALMSEC); |
196 | alm_tm->tm_min = readb(base + S3C2410_ALMMIN); | 209 | alm_tm->tm_min = readb(base + S3C2410_ALMMIN); |
197 | alm_tm->tm_hour = readb(base + S3C2410_ALMHOUR); | 210 | alm_tm->tm_hour = readb(base + S3C2410_ALMHOUR); |
@@ -243,6 +256,7 @@ static int s3c_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
243 | else | 256 | else |
244 | alm_tm->tm_year = -1; | 257 | alm_tm->tm_year = -1; |
245 | 258 | ||
259 | clk_disable(rtc_clk); | ||
246 | return 0; | 260 | return 0; |
247 | } | 261 | } |
248 | 262 | ||
@@ -252,6 +266,7 @@ static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
252 | void __iomem *base = s3c_rtc_base; | 266 | void __iomem *base = s3c_rtc_base; |
253 | unsigned int alrm_en; | 267 | unsigned int alrm_en; |
254 | 268 | ||
269 | clk_enable(rtc_clk); | ||
255 | pr_debug("s3c_rtc_setalarm: %d, %04d.%02d.%02d %02d:%02d:%02d\n", | 270 | pr_debug("s3c_rtc_setalarm: %d, %04d.%02d.%02d %02d:%02d:%02d\n", |
256 | alrm->enabled, | 271 | alrm->enabled, |
257 | 1900 + tm->tm_year, tm->tm_mon, tm->tm_mday, | 272 | 1900 + tm->tm_year, tm->tm_mon, tm->tm_mday, |
@@ -282,6 +297,7 @@ static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
282 | 297 | ||
283 | s3c_rtc_setaie(dev, alrm->enabled); | 298 | s3c_rtc_setaie(dev, alrm->enabled); |
284 | 299 | ||
300 | clk_disable(rtc_clk); | ||
285 | return 0; | 301 | return 0; |
286 | } | 302 | } |
287 | 303 | ||
@@ -289,6 +305,7 @@ static int s3c_rtc_proc(struct device *dev, struct seq_file *seq) | |||
289 | { | 305 | { |
290 | unsigned int ticnt; | 306 | unsigned int ticnt; |
291 | 307 | ||
308 | clk_enable(rtc_clk); | ||
292 | if (s3c_rtc_cpu_type == TYPE_S3C64XX) { | 309 | if (s3c_rtc_cpu_type == TYPE_S3C64XX) { |
293 | ticnt = readw(s3c_rtc_base + S3C2410_RTCCON); | 310 | ticnt = readw(s3c_rtc_base + S3C2410_RTCCON); |
294 | ticnt &= S3C64XX_RTCCON_TICEN; | 311 | ticnt &= S3C64XX_RTCCON_TICEN; |
@@ -298,6 +315,7 @@ static int s3c_rtc_proc(struct device *dev, struct seq_file *seq) | |||
298 | } | 315 | } |
299 | 316 | ||
300 | seq_printf(seq, "periodic_IRQ\t: %s\n", ticnt ? "yes" : "no"); | 317 | seq_printf(seq, "periodic_IRQ\t: %s\n", ticnt ? "yes" : "no"); |
318 | clk_disable(rtc_clk); | ||
301 | return 0; | 319 | return 0; |
302 | } | 320 | } |
303 | 321 | ||
@@ -360,6 +378,7 @@ static void s3c_rtc_enable(struct platform_device *pdev, int en) | |||
360 | if (s3c_rtc_base == NULL) | 378 | if (s3c_rtc_base == NULL) |
361 | return; | 379 | return; |
362 | 380 | ||
381 | clk_enable(rtc_clk); | ||
363 | if (!en) { | 382 | if (!en) { |
364 | tmp = readw(base + S3C2410_RTCCON); | 383 | tmp = readw(base + S3C2410_RTCCON); |
365 | if (s3c_rtc_cpu_type == TYPE_S3C64XX) | 384 | if (s3c_rtc_cpu_type == TYPE_S3C64XX) |
@@ -399,6 +418,7 @@ static void s3c_rtc_enable(struct platform_device *pdev, int en) | |||
399 | base + S3C2410_RTCCON); | 418 | base + S3C2410_RTCCON); |
400 | } | 419 | } |
401 | } | 420 | } |
421 | clk_disable(rtc_clk); | ||
402 | } | 422 | } |
403 | 423 | ||
404 | static int __devexit s3c_rtc_remove(struct platform_device *dev) | 424 | static int __devexit s3c_rtc_remove(struct platform_device *dev) |
@@ -410,7 +430,6 @@ static int __devexit s3c_rtc_remove(struct platform_device *dev) | |||
410 | 430 | ||
411 | s3c_rtc_setaie(&dev->dev, 0); | 431 | s3c_rtc_setaie(&dev->dev, 0); |
412 | 432 | ||
413 | clk_disable(rtc_clk); | ||
414 | clk_put(rtc_clk); | 433 | clk_put(rtc_clk); |
415 | rtc_clk = NULL; | 434 | rtc_clk = NULL; |
416 | 435 | ||
@@ -529,6 +548,8 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev) | |||
529 | 548 | ||
530 | s3c_rtc_setfreq(&pdev->dev, 1); | 549 | s3c_rtc_setfreq(&pdev->dev, 1); |
531 | 550 | ||
551 | clk_disable(rtc_clk); | ||
552 | |||
532 | return 0; | 553 | return 0; |
533 | 554 | ||
534 | err_nortc: | 555 | err_nortc: |
@@ -554,6 +575,7 @@ static int ticnt_save, ticnt_en_save; | |||
554 | 575 | ||
555 | static int s3c_rtc_suspend(struct platform_device *pdev, pm_message_t state) | 576 | static int s3c_rtc_suspend(struct platform_device *pdev, pm_message_t state) |
556 | { | 577 | { |
578 | clk_enable(rtc_clk); | ||
557 | /* save TICNT for anyone using periodic interrupts */ | 579 | /* save TICNT for anyone using periodic interrupts */ |
558 | ticnt_save = readb(s3c_rtc_base + S3C2410_TICNT); | 580 | ticnt_save = readb(s3c_rtc_base + S3C2410_TICNT); |
559 | if (s3c_rtc_cpu_type == TYPE_S3C64XX) { | 581 | if (s3c_rtc_cpu_type == TYPE_S3C64XX) { |
@@ -568,6 +590,7 @@ static int s3c_rtc_suspend(struct platform_device *pdev, pm_message_t state) | |||
568 | else | 590 | else |
569 | dev_err(&pdev->dev, "enable_irq_wake failed\n"); | 591 | dev_err(&pdev->dev, "enable_irq_wake failed\n"); |
570 | } | 592 | } |
593 | clk_disable(rtc_clk); | ||
571 | 594 | ||
572 | return 0; | 595 | return 0; |
573 | } | 596 | } |
@@ -576,6 +599,7 @@ static int s3c_rtc_resume(struct platform_device *pdev) | |||
576 | { | 599 | { |
577 | unsigned int tmp; | 600 | unsigned int tmp; |
578 | 601 | ||
602 | clk_enable(rtc_clk); | ||
579 | s3c_rtc_enable(pdev, 1); | 603 | s3c_rtc_enable(pdev, 1); |
580 | writeb(ticnt_save, s3c_rtc_base + S3C2410_TICNT); | 604 | writeb(ticnt_save, s3c_rtc_base + S3C2410_TICNT); |
581 | if (s3c_rtc_cpu_type == TYPE_S3C64XX && ticnt_en_save) { | 605 | if (s3c_rtc_cpu_type == TYPE_S3C64XX && ticnt_en_save) { |
@@ -587,6 +611,7 @@ static int s3c_rtc_resume(struct platform_device *pdev) | |||
587 | disable_irq_wake(s3c_rtc_alarmno); | 611 | disable_irq_wake(s3c_rtc_alarmno); |
588 | wake_en = false; | 612 | wake_en = false; |
589 | } | 613 | } |
614 | clk_disable(rtc_clk); | ||
590 | 615 | ||
591 | return 0; | 616 | return 0; |
592 | } | 617 | } |
diff --git a/drivers/rtc/rtc-tegra.c b/drivers/rtc/rtc-tegra.c index 2fc31aac3f4e..75259fe38602 100644 --- a/drivers/rtc/rtc-tegra.c +++ b/drivers/rtc/rtc-tegra.c | |||
@@ -343,7 +343,7 @@ static int __devinit tegra_rtc_probe(struct platform_device *pdev) | |||
343 | 343 | ||
344 | /* set context info. */ | 344 | /* set context info. */ |
345 | info->pdev = pdev; | 345 | info->pdev = pdev; |
346 | info->tegra_rtc_lock = __SPIN_LOCK_UNLOCKED(info->tegra_rtc_lock); | 346 | spin_lock_init(&info->tegra_rtc_lock); |
347 | 347 | ||
348 | platform_set_drvdata(pdev, info); | 348 | platform_set_drvdata(pdev, info); |
349 | 349 | ||
diff --git a/drivers/rtc/rtc-twl.c b/drivers/rtc/rtc-twl.c index f9a2799c44d6..9a81f778d6b2 100644 --- a/drivers/rtc/rtc-twl.c +++ b/drivers/rtc/rtc-twl.c | |||
@@ -275,7 +275,7 @@ static int twl_rtc_set_time(struct device *dev, struct rtc_time *tm) | |||
275 | goto out; | 275 | goto out; |
276 | 276 | ||
277 | save_control &= ~BIT_RTC_CTRL_REG_STOP_RTC_M; | 277 | save_control &= ~BIT_RTC_CTRL_REG_STOP_RTC_M; |
278 | twl_rtc_write_u8(save_control, REG_RTC_CTRL_REG); | 278 | ret = twl_rtc_write_u8(save_control, REG_RTC_CTRL_REG); |
279 | if (ret < 0) | 279 | if (ret < 0) |
280 | goto out; | 280 | goto out; |
281 | 281 | ||
diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig index 2d93c8d61ad5..1e54b8b7f698 100644 --- a/drivers/video/backlight/Kconfig +++ b/drivers/video/backlight/Kconfig | |||
@@ -117,6 +117,14 @@ config LCD_LD9040 | |||
117 | If you have an LD9040 Panel, say Y to enable its | 117 | If you have an LD9040 Panel, say Y to enable its |
118 | control driver. | 118 | control driver. |
119 | 119 | ||
120 | config LCD_AMS369FG06 | ||
121 | tristate "AMS369FG06 AMOLED LCD Driver" | ||
122 | depends on SPI && BACKLIGHT_CLASS_DEVICE | ||
123 | default n | ||
124 | help | ||
125 | If you have an AMS369FG06 AMOLED Panel, say Y to enable its | ||
126 | LCD control driver. | ||
127 | |||
120 | endif # LCD_CLASS_DEVICE | 128 | endif # LCD_CLASS_DEVICE |
121 | 129 | ||
122 | # | 130 | # |
diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile index ee72adb8786e..bf1dd92b7527 100644 --- a/drivers/video/backlight/Makefile +++ b/drivers/video/backlight/Makefile | |||
@@ -13,6 +13,7 @@ obj-$(CONFIG_LCD_TDO24M) += tdo24m.o | |||
13 | obj-$(CONFIG_LCD_TOSA) += tosa_lcd.o | 13 | obj-$(CONFIG_LCD_TOSA) += tosa_lcd.o |
14 | obj-$(CONFIG_LCD_S6E63M0) += s6e63m0.o | 14 | obj-$(CONFIG_LCD_S6E63M0) += s6e63m0.o |
15 | obj-$(CONFIG_LCD_LD9040) += ld9040.o | 15 | obj-$(CONFIG_LCD_LD9040) += ld9040.o |
16 | obj-$(CONFIG_LCD_AMS369FG06) += ams369fg06.o | ||
16 | 17 | ||
17 | obj-$(CONFIG_BACKLIGHT_CLASS_DEVICE) += backlight.o | 18 | obj-$(CONFIG_BACKLIGHT_CLASS_DEVICE) += backlight.o |
18 | obj-$(CONFIG_BACKLIGHT_ATMEL_PWM) += atmel-pwm-bl.o | 19 | obj-$(CONFIG_BACKLIGHT_ATMEL_PWM) += atmel-pwm-bl.o |
diff --git a/drivers/video/backlight/adp8860_bl.c b/drivers/video/backlight/adp8860_bl.c index d2a96a421ffd..183b6f639852 100644 --- a/drivers/video/backlight/adp8860_bl.c +++ b/drivers/video/backlight/adp8860_bl.c | |||
@@ -722,8 +722,7 @@ static int __devinit adp8860_probe(struct i2c_client *client, | |||
722 | goto out2; | 722 | goto out2; |
723 | } | 723 | } |
724 | 724 | ||
725 | bl->props.max_brightness = | 725 | bl->props.brightness = ADP8860_MAX_BRIGHTNESS; |
726 | bl->props.brightness = ADP8860_MAX_BRIGHTNESS; | ||
727 | 726 | ||
728 | data->bl = bl; | 727 | data->bl = bl; |
729 | 728 | ||
diff --git a/drivers/video/backlight/ams369fg06.c b/drivers/video/backlight/ams369fg06.c new file mode 100644 index 000000000000..9f0a491e2a05 --- /dev/null +++ b/drivers/video/backlight/ams369fg06.c | |||
@@ -0,0 +1,646 @@ | |||
1 | /* | ||
2 | * ams369fg06 AMOLED LCD panel driver. | ||
3 | * | ||
4 | * Copyright (c) 2011 Samsung Electronics Co., Ltd. | ||
5 | * Author: Jingoo Han <jg1.han@samsung.com> | ||
6 | * | ||
7 | * Derived from drivers/video/s6e63m0.c | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License as published by the | ||
11 | * Free Software Foundation; either version 2 of the License, or (at your | ||
12 | * option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License along | ||
20 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
21 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
22 | */ | ||
23 | |||
24 | #include <linux/wait.h> | ||
25 | #include <linux/fb.h> | ||
26 | #include <linux/delay.h> | ||
27 | #include <linux/gpio.h> | ||
28 | #include <linux/spi/spi.h> | ||
29 | #include <linux/lcd.h> | ||
30 | #include <linux/backlight.h> | ||
31 | |||
32 | #define SLEEPMSEC 0x1000 | ||
33 | #define ENDDEF 0x2000 | ||
34 | #define DEFMASK 0xFF00 | ||
35 | #define COMMAND_ONLY 0xFE | ||
36 | #define DATA_ONLY 0xFF | ||
37 | |||
38 | #define MAX_GAMMA_LEVEL 5 | ||
39 | #define GAMMA_TABLE_COUNT 21 | ||
40 | |||
41 | #define MIN_BRIGHTNESS 0 | ||
42 | #define MAX_BRIGHTNESS 255 | ||
43 | #define DEFAULT_BRIGHTNESS 150 | ||
44 | |||
45 | struct ams369fg06 { | ||
46 | struct device *dev; | ||
47 | struct spi_device *spi; | ||
48 | unsigned int power; | ||
49 | struct lcd_device *ld; | ||
50 | struct backlight_device *bd; | ||
51 | struct lcd_platform_data *lcd_pd; | ||
52 | }; | ||
53 | |||
54 | static const unsigned short seq_display_on[] = { | ||
55 | 0x14, 0x03, | ||
56 | ENDDEF, 0x0000 | ||
57 | }; | ||
58 | |||
59 | static const unsigned short seq_display_off[] = { | ||
60 | 0x14, 0x00, | ||
61 | ENDDEF, 0x0000 | ||
62 | }; | ||
63 | |||
64 | static const unsigned short seq_stand_by_on[] = { | ||
65 | 0x1D, 0xA1, | ||
66 | SLEEPMSEC, 200, | ||
67 | ENDDEF, 0x0000 | ||
68 | }; | ||
69 | |||
70 | static const unsigned short seq_stand_by_off[] = { | ||
71 | 0x1D, 0xA0, | ||
72 | SLEEPMSEC, 250, | ||
73 | ENDDEF, 0x0000 | ||
74 | }; | ||
75 | |||
76 | static const unsigned short seq_setting[] = { | ||
77 | 0x31, 0x08, | ||
78 | 0x32, 0x14, | ||
79 | 0x30, 0x02, | ||
80 | 0x27, 0x01, | ||
81 | 0x12, 0x08, | ||
82 | 0x13, 0x08, | ||
83 | 0x15, 0x00, | ||
84 | 0x16, 0x00, | ||
85 | |||
86 | 0xef, 0xd0, | ||
87 | DATA_ONLY, 0xe8, | ||
88 | |||
89 | 0x39, 0x44, | ||
90 | 0x40, 0x00, | ||
91 | 0x41, 0x3f, | ||
92 | 0x42, 0x2a, | ||
93 | 0x43, 0x27, | ||
94 | 0x44, 0x27, | ||
95 | 0x45, 0x1f, | ||
96 | 0x46, 0x44, | ||
97 | 0x50, 0x00, | ||
98 | 0x51, 0x00, | ||
99 | 0x52, 0x17, | ||
100 | 0x53, 0x24, | ||
101 | 0x54, 0x26, | ||
102 | 0x55, 0x1f, | ||
103 | 0x56, 0x43, | ||
104 | 0x60, 0x00, | ||
105 | 0x61, 0x3f, | ||
106 | 0x62, 0x2a, | ||
107 | 0x63, 0x25, | ||
108 | 0x64, 0x24, | ||
109 | 0x65, 0x1b, | ||
110 | 0x66, 0x5c, | ||
111 | |||
112 | 0x17, 0x22, | ||
113 | 0x18, 0x33, | ||
114 | 0x19, 0x03, | ||
115 | 0x1a, 0x01, | ||
116 | 0x22, 0xa4, | ||
117 | 0x23, 0x00, | ||
118 | 0x26, 0xa0, | ||
119 | |||
120 | 0x1d, 0xa0, | ||
121 | SLEEPMSEC, 300, | ||
122 | |||
123 | 0x14, 0x03, | ||
124 | |||
125 | ENDDEF, 0x0000 | ||
126 | }; | ||
127 | |||
128 | /* gamma value: 2.2 */ | ||
129 | static const unsigned int ams369fg06_22_250[] = { | ||
130 | 0x00, 0x3f, 0x2a, 0x27, 0x27, 0x1f, 0x44, | ||
131 | 0x00, 0x00, 0x17, 0x24, 0x26, 0x1f, 0x43, | ||
132 | 0x00, 0x3f, 0x2a, 0x25, 0x24, 0x1b, 0x5c, | ||
133 | }; | ||
134 | |||
135 | static const unsigned int ams369fg06_22_200[] = { | ||
136 | 0x00, 0x3f, 0x28, 0x29, 0x27, 0x21, 0x3e, | ||
137 | 0x00, 0x00, 0x10, 0x25, 0x27, 0x20, 0x3d, | ||
138 | 0x00, 0x3f, 0x28, 0x27, 0x25, 0x1d, 0x53, | ||
139 | }; | ||
140 | |||
141 | static const unsigned int ams369fg06_22_150[] = { | ||
142 | 0x00, 0x3f, 0x2d, 0x29, 0x28, 0x23, 0x37, | ||
143 | 0x00, 0x00, 0x0b, 0x25, 0x28, 0x22, 0x36, | ||
144 | 0x00, 0x3f, 0x2b, 0x28, 0x26, 0x1f, 0x4a, | ||
145 | }; | ||
146 | |||
147 | static const unsigned int ams369fg06_22_100[] = { | ||
148 | 0x00, 0x3f, 0x30, 0x2a, 0x2b, 0x24, 0x2f, | ||
149 | 0x00, 0x00, 0x00, 0x25, 0x29, 0x24, 0x2e, | ||
150 | 0x00, 0x3f, 0x2f, 0x29, 0x29, 0x21, 0x3f, | ||
151 | }; | ||
152 | |||
153 | static const unsigned int ams369fg06_22_50[] = { | ||
154 | 0x00, 0x3f, 0x3c, 0x2c, 0x2d, 0x27, 0x24, | ||
155 | 0x00, 0x00, 0x00, 0x22, 0x2a, 0x27, 0x23, | ||
156 | 0x00, 0x3f, 0x3b, 0x2c, 0x2b, 0x24, 0x31, | ||
157 | }; | ||
158 | |||
159 | struct ams369fg06_gamma { | ||
160 | unsigned int *gamma_22_table[MAX_GAMMA_LEVEL]; | ||
161 | }; | ||
162 | |||
163 | static struct ams369fg06_gamma gamma_table = { | ||
164 | .gamma_22_table[0] = (unsigned int *)&ams369fg06_22_50, | ||
165 | .gamma_22_table[1] = (unsigned int *)&ams369fg06_22_100, | ||
166 | .gamma_22_table[2] = (unsigned int *)&ams369fg06_22_150, | ||
167 | .gamma_22_table[3] = (unsigned int *)&ams369fg06_22_200, | ||
168 | .gamma_22_table[4] = (unsigned int *)&ams369fg06_22_250, | ||
169 | }; | ||
170 | |||
171 | static int ams369fg06_spi_write_byte(struct ams369fg06 *lcd, int addr, int data) | ||
172 | { | ||
173 | u16 buf[1]; | ||
174 | struct spi_message msg; | ||
175 | |||
176 | struct spi_transfer xfer = { | ||
177 | .len = 2, | ||
178 | .tx_buf = buf, | ||
179 | }; | ||
180 | |||
181 | buf[0] = (addr << 8) | data; | ||
182 | |||
183 | spi_message_init(&msg); | ||
184 | spi_message_add_tail(&xfer, &msg); | ||
185 | |||
186 | return spi_sync(lcd->spi, &msg); | ||
187 | } | ||
188 | |||
189 | static int ams369fg06_spi_write(struct ams369fg06 *lcd, unsigned char address, | ||
190 | unsigned char command) | ||
191 | { | ||
192 | int ret = 0; | ||
193 | |||
194 | if (address != DATA_ONLY) | ||
195 | ret = ams369fg06_spi_write_byte(lcd, 0x70, address); | ||
196 | if (command != COMMAND_ONLY) | ||
197 | ret = ams369fg06_spi_write_byte(lcd, 0x72, command); | ||
198 | |||
199 | return ret; | ||
200 | } | ||
201 | |||
202 | static int ams369fg06_panel_send_sequence(struct ams369fg06 *lcd, | ||
203 | const unsigned short *wbuf) | ||
204 | { | ||
205 | int ret = 0, i = 0; | ||
206 | |||
207 | while ((wbuf[i] & DEFMASK) != ENDDEF) { | ||
208 | if ((wbuf[i] & DEFMASK) != SLEEPMSEC) { | ||
209 | ret = ams369fg06_spi_write(lcd, wbuf[i], wbuf[i+1]); | ||
210 | if (ret) | ||
211 | break; | ||
212 | } else | ||
213 | mdelay(wbuf[i+1]); | ||
214 | i += 2; | ||
215 | } | ||
216 | |||
217 | return ret; | ||
218 | } | ||
219 | |||
220 | static int _ams369fg06_gamma_ctl(struct ams369fg06 *lcd, | ||
221 | const unsigned int *gamma) | ||
222 | { | ||
223 | unsigned int i = 0; | ||
224 | int ret = 0; | ||
225 | |||
226 | for (i = 0 ; i < GAMMA_TABLE_COUNT / 3; i++) { | ||
227 | ret = ams369fg06_spi_write(lcd, 0x40 + i, gamma[i]); | ||
228 | ret = ams369fg06_spi_write(lcd, 0x50 + i, gamma[i+7*1]); | ||
229 | ret = ams369fg06_spi_write(lcd, 0x60 + i, gamma[i+7*2]); | ||
230 | if (ret) { | ||
231 | dev_err(lcd->dev, "failed to set gamma table.\n"); | ||
232 | goto gamma_err; | ||
233 | } | ||
234 | } | ||
235 | |||
236 | gamma_err: | ||
237 | return ret; | ||
238 | } | ||
239 | |||
240 | static int ams369fg06_gamma_ctl(struct ams369fg06 *lcd, int brightness) | ||
241 | { | ||
242 | int ret = 0; | ||
243 | int gamma = 0; | ||
244 | |||
245 | if ((brightness >= 0) && (brightness <= 50)) | ||
246 | gamma = 0; | ||
247 | else if ((brightness > 50) && (brightness <= 100)) | ||
248 | gamma = 1; | ||
249 | else if ((brightness > 100) && (brightness <= 150)) | ||
250 | gamma = 2; | ||
251 | else if ((brightness > 150) && (brightness <= 200)) | ||
252 | gamma = 3; | ||
253 | else if ((brightness > 200) && (brightness <= 255)) | ||
254 | gamma = 4; | ||
255 | |||
256 | ret = _ams369fg06_gamma_ctl(lcd, gamma_table.gamma_22_table[gamma]); | ||
257 | |||
258 | return ret; | ||
259 | } | ||
260 | |||
261 | static int ams369fg06_ldi_init(struct ams369fg06 *lcd) | ||
262 | { | ||
263 | int ret, i; | ||
264 | static const unsigned short *init_seq[] = { | ||
265 | seq_setting, | ||
266 | seq_stand_by_off, | ||
267 | }; | ||
268 | |||
269 | for (i = 0; i < ARRAY_SIZE(init_seq); i++) { | ||
270 | ret = ams369fg06_panel_send_sequence(lcd, init_seq[i]); | ||
271 | if (ret) | ||
272 | break; | ||
273 | } | ||
274 | |||
275 | return ret; | ||
276 | } | ||
277 | |||
278 | static int ams369fg06_ldi_enable(struct ams369fg06 *lcd) | ||
279 | { | ||
280 | int ret, i; | ||
281 | static const unsigned short *init_seq[] = { | ||
282 | seq_stand_by_off, | ||
283 | seq_display_on, | ||
284 | }; | ||
285 | |||
286 | for (i = 0; i < ARRAY_SIZE(init_seq); i++) { | ||
287 | ret = ams369fg06_panel_send_sequence(lcd, init_seq[i]); | ||
288 | if (ret) | ||
289 | break; | ||
290 | } | ||
291 | |||
292 | return ret; | ||
293 | } | ||
294 | |||
295 | static int ams369fg06_ldi_disable(struct ams369fg06 *lcd) | ||
296 | { | ||
297 | int ret, i; | ||
298 | |||
299 | static const unsigned short *init_seq[] = { | ||
300 | seq_display_off, | ||
301 | seq_stand_by_on, | ||
302 | }; | ||
303 | |||
304 | for (i = 0; i < ARRAY_SIZE(init_seq); i++) { | ||
305 | ret = ams369fg06_panel_send_sequence(lcd, init_seq[i]); | ||
306 | if (ret) | ||
307 | break; | ||
308 | } | ||
309 | |||
310 | return ret; | ||
311 | } | ||
312 | |||
313 | static int ams369fg06_power_is_on(int power) | ||
314 | { | ||
315 | return ((power) <= FB_BLANK_NORMAL); | ||
316 | } | ||
317 | |||
318 | static int ams369fg06_power_on(struct ams369fg06 *lcd) | ||
319 | { | ||
320 | int ret = 0; | ||
321 | struct lcd_platform_data *pd = NULL; | ||
322 | struct backlight_device *bd = NULL; | ||
323 | |||
324 | pd = lcd->lcd_pd; | ||
325 | if (!pd) { | ||
326 | dev_err(lcd->dev, "platform data is NULL.\n"); | ||
327 | return -EFAULT; | ||
328 | } | ||
329 | |||
330 | bd = lcd->bd; | ||
331 | if (!bd) { | ||
332 | dev_err(lcd->dev, "backlight device is NULL.\n"); | ||
333 | return -EFAULT; | ||
334 | } | ||
335 | |||
336 | if (!pd->power_on) { | ||
337 | dev_err(lcd->dev, "power_on is NULL.\n"); | ||
338 | return -EFAULT; | ||
339 | } else { | ||
340 | pd->power_on(lcd->ld, 1); | ||
341 | mdelay(pd->power_on_delay); | ||
342 | } | ||
343 | |||
344 | if (!pd->reset) { | ||
345 | dev_err(lcd->dev, "reset is NULL.\n"); | ||
346 | return -EFAULT; | ||
347 | } else { | ||
348 | pd->reset(lcd->ld); | ||
349 | mdelay(pd->reset_delay); | ||
350 | } | ||
351 | |||
352 | ret = ams369fg06_ldi_init(lcd); | ||
353 | if (ret) { | ||
354 | dev_err(lcd->dev, "failed to initialize ldi.\n"); | ||
355 | return ret; | ||
356 | } | ||
357 | |||
358 | ret = ams369fg06_ldi_enable(lcd); | ||
359 | if (ret) { | ||
360 | dev_err(lcd->dev, "failed to enable ldi.\n"); | ||
361 | return ret; | ||
362 | } | ||
363 | |||
364 | /* set brightness to current value after power on or resume. */ | ||
365 | ret = ams369fg06_gamma_ctl(lcd, bd->props.brightness); | ||
366 | if (ret) { | ||
367 | dev_err(lcd->dev, "lcd gamma setting failed.\n"); | ||
368 | return ret; | ||
369 | } | ||
370 | |||
371 | return 0; | ||
372 | } | ||
373 | |||
374 | static int ams369fg06_power_off(struct ams369fg06 *lcd) | ||
375 | { | ||
376 | int ret = 0; | ||
377 | struct lcd_platform_data *pd = NULL; | ||
378 | |||
379 | pd = lcd->lcd_pd; | ||
380 | if (!pd) { | ||
381 | dev_err(lcd->dev, "platform data is NULL\n"); | ||
382 | return -EFAULT; | ||
383 | } | ||
384 | |||
385 | ret = ams369fg06_ldi_disable(lcd); | ||
386 | if (ret) { | ||
387 | dev_err(lcd->dev, "lcd setting failed.\n"); | ||
388 | return -EIO; | ||
389 | } | ||
390 | |||
391 | mdelay(pd->power_off_delay); | ||
392 | |||
393 | if (!pd->power_on) { | ||
394 | dev_err(lcd->dev, "power_on is NULL.\n"); | ||
395 | return -EFAULT; | ||
396 | } else | ||
397 | pd->power_on(lcd->ld, 0); | ||
398 | |||
399 | return 0; | ||
400 | } | ||
401 | |||
402 | static int ams369fg06_power(struct ams369fg06 *lcd, int power) | ||
403 | { | ||
404 | int ret = 0; | ||
405 | |||
406 | if (ams369fg06_power_is_on(power) && | ||
407 | !ams369fg06_power_is_on(lcd->power)) | ||
408 | ret = ams369fg06_power_on(lcd); | ||
409 | else if (!ams369fg06_power_is_on(power) && | ||
410 | ams369fg06_power_is_on(lcd->power)) | ||
411 | ret = ams369fg06_power_off(lcd); | ||
412 | |||
413 | if (!ret) | ||
414 | lcd->power = power; | ||
415 | |||
416 | return ret; | ||
417 | } | ||
418 | |||
419 | static int ams369fg06_get_power(struct lcd_device *ld) | ||
420 | { | ||
421 | struct ams369fg06 *lcd = lcd_get_data(ld); | ||
422 | |||
423 | return lcd->power; | ||
424 | } | ||
425 | |||
426 | static int ams369fg06_set_power(struct lcd_device *ld, int power) | ||
427 | { | ||
428 | struct ams369fg06 *lcd = lcd_get_data(ld); | ||
429 | |||
430 | if (power != FB_BLANK_UNBLANK && power != FB_BLANK_POWERDOWN && | ||
431 | power != FB_BLANK_NORMAL) { | ||
432 | dev_err(lcd->dev, "power value should be 0, 1 or 4.\n"); | ||
433 | return -EINVAL; | ||
434 | } | ||
435 | |||
436 | return ams369fg06_power(lcd, power); | ||
437 | } | ||
438 | |||
439 | static int ams369fg06_get_brightness(struct backlight_device *bd) | ||
440 | { | ||
441 | return bd->props.brightness; | ||
442 | } | ||
443 | |||
444 | static int ams369fg06_set_brightness(struct backlight_device *bd) | ||
445 | { | ||
446 | int ret = 0; | ||
447 | int brightness = bd->props.brightness; | ||
448 | struct ams369fg06 *lcd = dev_get_drvdata(&bd->dev); | ||
449 | |||
450 | if (brightness < MIN_BRIGHTNESS || | ||
451 | brightness > bd->props.max_brightness) { | ||
452 | dev_err(&bd->dev, "lcd brightness should be %d to %d.\n", | ||
453 | MIN_BRIGHTNESS, MAX_BRIGHTNESS); | ||
454 | return -EINVAL; | ||
455 | } | ||
456 | |||
457 | ret = ams369fg06_gamma_ctl(lcd, bd->props.brightness); | ||
458 | if (ret) { | ||
459 | dev_err(&bd->dev, "lcd brightness setting failed.\n"); | ||
460 | return -EIO; | ||
461 | } | ||
462 | |||
463 | return ret; | ||
464 | } | ||
465 | |||
466 | static struct lcd_ops ams369fg06_lcd_ops = { | ||
467 | .get_power = ams369fg06_get_power, | ||
468 | .set_power = ams369fg06_set_power, | ||
469 | }; | ||
470 | |||
471 | static const struct backlight_ops ams369fg06_backlight_ops = { | ||
472 | .get_brightness = ams369fg06_get_brightness, | ||
473 | .update_status = ams369fg06_set_brightness, | ||
474 | }; | ||
475 | |||
476 | static int __devinit ams369fg06_probe(struct spi_device *spi) | ||
477 | { | ||
478 | int ret = 0; | ||
479 | struct ams369fg06 *lcd = NULL; | ||
480 | struct lcd_device *ld = NULL; | ||
481 | struct backlight_device *bd = NULL; | ||
482 | struct backlight_properties props; | ||
483 | |||
484 | lcd = kzalloc(sizeof(struct ams369fg06), GFP_KERNEL); | ||
485 | if (!lcd) | ||
486 | return -ENOMEM; | ||
487 | |||
488 | /* ams369fg06 lcd panel uses 3-wire 16bits SPI Mode. */ | ||
489 | spi->bits_per_word = 16; | ||
490 | |||
491 | ret = spi_setup(spi); | ||
492 | if (ret < 0) { | ||
493 | dev_err(&spi->dev, "spi setup failed.\n"); | ||
494 | goto out_free_lcd; | ||
495 | } | ||
496 | |||
497 | lcd->spi = spi; | ||
498 | lcd->dev = &spi->dev; | ||
499 | |||
500 | lcd->lcd_pd = spi->dev.platform_data; | ||
501 | if (!lcd->lcd_pd) { | ||
502 | dev_err(&spi->dev, "platform data is NULL\n"); | ||
503 | goto out_free_lcd; | ||
504 | } | ||
505 | |||
506 | ld = lcd_device_register("ams369fg06", &spi->dev, lcd, | ||
507 | &ams369fg06_lcd_ops); | ||
508 | if (IS_ERR(ld)) { | ||
509 | ret = PTR_ERR(ld); | ||
510 | goto out_free_lcd; | ||
511 | } | ||
512 | |||
513 | lcd->ld = ld; | ||
514 | |||
515 | memset(&props, 0, sizeof(struct backlight_properties)); | ||
516 | props.type = BACKLIGHT_RAW; | ||
517 | props.max_brightness = MAX_BRIGHTNESS; | ||
518 | |||
519 | bd = backlight_device_register("ams369fg06-bl", &spi->dev, lcd, | ||
520 | &ams369fg06_backlight_ops, &props); | ||
521 | if (IS_ERR(bd)) { | ||
522 | ret = PTR_ERR(bd); | ||
523 | goto out_lcd_unregister; | ||
524 | } | ||
525 | |||
526 | bd->props.brightness = DEFAULT_BRIGHTNESS; | ||
527 | lcd->bd = bd; | ||
528 | |||
529 | if (!lcd->lcd_pd->lcd_enabled) { | ||
530 | /* | ||
531 | * if lcd panel was off from bootloader then | ||
532 | * current lcd status is powerdown and then | ||
533 | * it enables lcd panel. | ||
534 | */ | ||
535 | lcd->power = FB_BLANK_POWERDOWN; | ||
536 | |||
537 | ams369fg06_power(lcd, FB_BLANK_UNBLANK); | ||
538 | } else | ||
539 | lcd->power = FB_BLANK_UNBLANK; | ||
540 | |||
541 | dev_set_drvdata(&spi->dev, lcd); | ||
542 | |||
543 | dev_info(&spi->dev, "ams369fg06 panel driver has been probed.\n"); | ||
544 | |||
545 | return 0; | ||
546 | |||
547 | out_lcd_unregister: | ||
548 | lcd_device_unregister(ld); | ||
549 | out_free_lcd: | ||
550 | kfree(lcd); | ||
551 | return ret; | ||
552 | } | ||
553 | |||
554 | static int __devexit ams369fg06_remove(struct spi_device *spi) | ||
555 | { | ||
556 | struct ams369fg06 *lcd = dev_get_drvdata(&spi->dev); | ||
557 | |||
558 | ams369fg06_power(lcd, FB_BLANK_POWERDOWN); | ||
559 | backlight_device_unregister(lcd->bd); | ||
560 | lcd_device_unregister(lcd->ld); | ||
561 | kfree(lcd); | ||
562 | |||
563 | return 0; | ||
564 | } | ||
565 | |||
566 | #if defined(CONFIG_PM) | ||
567 | static unsigned int before_power; | ||
568 | |||
569 | static int ams369fg06_suspend(struct spi_device *spi, pm_message_t mesg) | ||
570 | { | ||
571 | int ret = 0; | ||
572 | struct ams369fg06 *lcd = dev_get_drvdata(&spi->dev); | ||
573 | |||
574 | dev_dbg(&spi->dev, "lcd->power = %d\n", lcd->power); | ||
575 | |||
576 | before_power = lcd->power; | ||
577 | |||
578 | /* | ||
579 | * when lcd panel is suspend, lcd panel becomes off | ||
580 | * regardless of status. | ||
581 | */ | ||
582 | ret = ams369fg06_power(lcd, FB_BLANK_POWERDOWN); | ||
583 | |||
584 | return ret; | ||
585 | } | ||
586 | |||
587 | static int ams369fg06_resume(struct spi_device *spi) | ||
588 | { | ||
589 | int ret = 0; | ||
590 | struct ams369fg06 *lcd = dev_get_drvdata(&spi->dev); | ||
591 | |||
592 | /* | ||
593 | * after suspended, if lcd panel status is FB_BLANK_UNBLANK | ||
594 | * (at that time, before_power is FB_BLANK_UNBLANK) then | ||
595 | * it changes that status to FB_BLANK_POWERDOWN to get lcd on. | ||
596 | */ | ||
597 | if (before_power == FB_BLANK_UNBLANK) | ||
598 | lcd->power = FB_BLANK_POWERDOWN; | ||
599 | |||
600 | dev_dbg(&spi->dev, "before_power = %d\n", before_power); | ||
601 | |||
602 | ret = ams369fg06_power(lcd, before_power); | ||
603 | |||
604 | return ret; | ||
605 | } | ||
606 | #else | ||
607 | #define ams369fg06_suspend NULL | ||
608 | #define ams369fg06_resume NULL | ||
609 | #endif | ||
610 | |||
611 | static void ams369fg06_shutdown(struct spi_device *spi) | ||
612 | { | ||
613 | struct ams369fg06 *lcd = dev_get_drvdata(&spi->dev); | ||
614 | |||
615 | ams369fg06_power(lcd, FB_BLANK_POWERDOWN); | ||
616 | } | ||
617 | |||
618 | static struct spi_driver ams369fg06_driver = { | ||
619 | .driver = { | ||
620 | .name = "ams369fg06", | ||
621 | .bus = &spi_bus_type, | ||
622 | .owner = THIS_MODULE, | ||
623 | }, | ||
624 | .probe = ams369fg06_probe, | ||
625 | .remove = __devexit_p(ams369fg06_remove), | ||
626 | .shutdown = ams369fg06_shutdown, | ||
627 | .suspend = ams369fg06_suspend, | ||
628 | .resume = ams369fg06_resume, | ||
629 | }; | ||
630 | |||
631 | static int __init ams369fg06_init(void) | ||
632 | { | ||
633 | return spi_register_driver(&ams369fg06_driver); | ||
634 | } | ||
635 | |||
636 | static void __exit ams369fg06_exit(void) | ||
637 | { | ||
638 | spi_unregister_driver(&ams369fg06_driver); | ||
639 | } | ||
640 | |||
641 | module_init(ams369fg06_init); | ||
642 | module_exit(ams369fg06_exit); | ||
643 | |||
644 | MODULE_AUTHOR("Jingoo Han <jg1.han@samsung.com>"); | ||
645 | MODULE_DESCRIPTION("ams369fg06 LCD Driver"); | ||
646 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/video/backlight/ld9040.c b/drivers/video/backlight/ld9040.c index 7281b2506a67..5934655eb1ff 100644 --- a/drivers/video/backlight/ld9040.c +++ b/drivers/video/backlight/ld9040.c | |||
@@ -668,6 +668,7 @@ static int ld9040_probe(struct spi_device *spi) | |||
668 | struct ld9040 *lcd = NULL; | 668 | struct ld9040 *lcd = NULL; |
669 | struct lcd_device *ld = NULL; | 669 | struct lcd_device *ld = NULL; |
670 | struct backlight_device *bd = NULL; | 670 | struct backlight_device *bd = NULL; |
671 | struct backlight_properties props; | ||
671 | 672 | ||
672 | lcd = kzalloc(sizeof(struct ld9040), GFP_KERNEL); | 673 | lcd = kzalloc(sizeof(struct ld9040), GFP_KERNEL); |
673 | if (!lcd) | 674 | if (!lcd) |
@@ -699,14 +700,17 @@ static int ld9040_probe(struct spi_device *spi) | |||
699 | 700 | ||
700 | lcd->ld = ld; | 701 | lcd->ld = ld; |
701 | 702 | ||
703 | memset(&props, 0, sizeof(struct backlight_properties)); | ||
704 | props.type = BACKLIGHT_RAW; | ||
705 | props.max_brightness = MAX_BRIGHTNESS; | ||
706 | |||
702 | bd = backlight_device_register("ld9040-bl", &spi->dev, | 707 | bd = backlight_device_register("ld9040-bl", &spi->dev, |
703 | lcd, &ld9040_backlight_ops, NULL); | 708 | lcd, &ld9040_backlight_ops, &props); |
704 | if (IS_ERR(ld)) { | 709 | if (IS_ERR(bd)) { |
705 | ret = PTR_ERR(ld); | 710 | ret = PTR_ERR(bd); |
706 | goto out_free_lcd; | 711 | goto out_unregister_lcd; |
707 | } | 712 | } |
708 | 713 | ||
709 | bd->props.max_brightness = MAX_BRIGHTNESS; | ||
710 | bd->props.brightness = MAX_BRIGHTNESS; | 714 | bd->props.brightness = MAX_BRIGHTNESS; |
711 | lcd->bd = bd; | 715 | lcd->bd = bd; |
712 | 716 | ||
@@ -731,6 +735,8 @@ static int ld9040_probe(struct spi_device *spi) | |||
731 | dev_info(&spi->dev, "ld9040 panel driver has been probed.\n"); | 735 | dev_info(&spi->dev, "ld9040 panel driver has been probed.\n"); |
732 | return 0; | 736 | return 0; |
733 | 737 | ||
738 | out_unregister_lcd: | ||
739 | lcd_device_unregister(lcd->ld); | ||
734 | out_free_lcd: | 740 | out_free_lcd: |
735 | kfree(lcd); | 741 | kfree(lcd); |
736 | return ret; | 742 | return ret; |
@@ -741,6 +747,7 @@ static int __devexit ld9040_remove(struct spi_device *spi) | |||
741 | struct ld9040 *lcd = dev_get_drvdata(&spi->dev); | 747 | struct ld9040 *lcd = dev_get_drvdata(&spi->dev); |
742 | 748 | ||
743 | ld9040_power(lcd, FB_BLANK_POWERDOWN); | 749 | ld9040_power(lcd, FB_BLANK_POWERDOWN); |
750 | backlight_device_unregister(lcd->bd); | ||
744 | lcd_device_unregister(lcd->ld); | 751 | lcd_device_unregister(lcd->ld); |
745 | kfree(lcd); | 752 | kfree(lcd); |
746 | 753 | ||
diff --git a/drivers/video/backlight/s6e63m0.c b/drivers/video/backlight/s6e63m0.c index 322040f686c2..694e5aab0d69 100644 --- a/drivers/video/backlight/s6e63m0.c +++ b/drivers/video/backlight/s6e63m0.c | |||
@@ -738,6 +738,7 @@ static int __devinit s6e63m0_probe(struct spi_device *spi) | |||
738 | struct s6e63m0 *lcd = NULL; | 738 | struct s6e63m0 *lcd = NULL; |
739 | struct lcd_device *ld = NULL; | 739 | struct lcd_device *ld = NULL; |
740 | struct backlight_device *bd = NULL; | 740 | struct backlight_device *bd = NULL; |
741 | struct backlight_properties props; | ||
741 | 742 | ||
742 | lcd = kzalloc(sizeof(struct s6e63m0), GFP_KERNEL); | 743 | lcd = kzalloc(sizeof(struct s6e63m0), GFP_KERNEL); |
743 | if (!lcd) | 744 | if (!lcd) |
@@ -769,16 +770,18 @@ static int __devinit s6e63m0_probe(struct spi_device *spi) | |||
769 | 770 | ||
770 | lcd->ld = ld; | 771 | lcd->ld = ld; |
771 | 772 | ||
773 | memset(&props, 0, sizeof(struct backlight_properties)); | ||
774 | props.type = BACKLIGHT_RAW; | ||
775 | props.max_brightness = MAX_BRIGHTNESS; | ||
776 | |||
772 | bd = backlight_device_register("s6e63m0bl-bl", &spi->dev, lcd, | 777 | bd = backlight_device_register("s6e63m0bl-bl", &spi->dev, lcd, |
773 | &s6e63m0_backlight_ops, NULL); | 778 | &s6e63m0_backlight_ops, &props); |
774 | if (IS_ERR(bd)) { | 779 | if (IS_ERR(bd)) { |
775 | ret = PTR_ERR(bd); | 780 | ret = PTR_ERR(bd); |
776 | goto out_lcd_unregister; | 781 | goto out_lcd_unregister; |
777 | } | 782 | } |
778 | 783 | ||
779 | bd->props.max_brightness = MAX_BRIGHTNESS; | ||
780 | bd->props.brightness = MAX_BRIGHTNESS; | 784 | bd->props.brightness = MAX_BRIGHTNESS; |
781 | bd->props.type = BACKLIGHT_RAW; | ||
782 | lcd->bd = bd; | 785 | lcd->bd = bd; |
783 | 786 | ||
784 | /* | 787 | /* |
@@ -840,7 +843,7 @@ static int __devexit s6e63m0_remove(struct spi_device *spi) | |||
840 | } | 843 | } |
841 | 844 | ||
842 | #if defined(CONFIG_PM) | 845 | #if defined(CONFIG_PM) |
843 | unsigned int before_power; | 846 | static unsigned int before_power; |
844 | 847 | ||
845 | static int s6e63m0_suspend(struct spi_device *spi, pm_message_t mesg) | 848 | static int s6e63m0_suspend(struct spi_device *spi, pm_message_t mesg) |
846 | { | 849 | { |
diff --git a/drivers/xen/Kconfig b/drivers/xen/Kconfig index 03bc471c3eed..f815283667af 100644 --- a/drivers/xen/Kconfig +++ b/drivers/xen/Kconfig | |||
@@ -26,6 +26,36 @@ config XEN_SELFBALLOONING | |||
26 | kernel boot parameter. Note that systems without a sufficiently | 26 | kernel boot parameter. Note that systems without a sufficiently |
27 | large swap device should not enable self-ballooning. | 27 | large swap device should not enable self-ballooning. |
28 | 28 | ||
29 | config XEN_BALLOON_MEMORY_HOTPLUG | ||
30 | bool "Memory hotplug support for Xen balloon driver" | ||
31 | default n | ||
32 | depends on XEN_BALLOON && MEMORY_HOTPLUG | ||
33 | help | ||
34 | Memory hotplug support for Xen balloon driver allows expanding memory | ||
35 | available for the system above limit declared at system startup. | ||
36 | It is very useful on critical systems which require long | ||
37 | run without rebooting. | ||
38 | |||
39 | Memory could be hotplugged in following steps: | ||
40 | |||
41 | 1) dom0: xl mem-max <domU> <maxmem> | ||
42 | where <maxmem> is >= requested memory size, | ||
43 | |||
44 | 2) dom0: xl mem-set <domU> <memory> | ||
45 | where <memory> is requested memory size; alternatively memory | ||
46 | could be added by writing proper value to | ||
47 | /sys/devices/system/xen_memory/xen_memory0/target or | ||
48 | /sys/devices/system/xen_memory/xen_memory0/target_kb on dumU, | ||
49 | |||
50 | 3) domU: for i in /sys/devices/system/memory/memory*/state; do \ | ||
51 | [ "`cat "$i"`" = offline ] && echo online > "$i"; done | ||
52 | |||
53 | Memory could be onlined automatically on domU by adding following line to udev rules: | ||
54 | |||
55 | SUBSYSTEM=="memory", ACTION=="add", RUN+="/bin/sh -c '[ -f /sys$devpath/state ] && echo online > /sys$devpath/state'" | ||
56 | |||
57 | In that case step 3 should be omitted. | ||
58 | |||
29 | config XEN_SCRUB_PAGES | 59 | config XEN_SCRUB_PAGES |
30 | bool "Scrub pages before returning them to system" | 60 | bool "Scrub pages before returning them to system" |
31 | depends on XEN_BALLOON | 61 | depends on XEN_BALLOON |
diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c index f54290baa3db..5dfd8f8ff07f 100644 --- a/drivers/xen/balloon.c +++ b/drivers/xen/balloon.c | |||
@@ -4,6 +4,12 @@ | |||
4 | * Copyright (c) 2003, B Dragovic | 4 | * Copyright (c) 2003, B Dragovic |
5 | * Copyright (c) 2003-2004, M Williamson, K Fraser | 5 | * Copyright (c) 2003-2004, M Williamson, K Fraser |
6 | * Copyright (c) 2005 Dan M. Smith, IBM Corporation | 6 | * Copyright (c) 2005 Dan M. Smith, IBM Corporation |
7 | * Copyright (c) 2010 Daniel Kiper | ||
8 | * | ||
9 | * Memory hotplug support was written by Daniel Kiper. Work on | ||
10 | * it was sponsored by Google under Google Summer of Code 2010 | ||
11 | * program. Jeremy Fitzhardinge from Citrix was the mentor for | ||
12 | * this project. | ||
7 | * | 13 | * |
8 | * This program is free software; you can redistribute it and/or | 14 | * This program is free software; you can redistribute it and/or |
9 | * modify it under the terms of the GNU General Public License version 2 | 15 | * modify it under the terms of the GNU General Public License version 2 |
@@ -40,6 +46,9 @@ | |||
40 | #include <linux/mutex.h> | 46 | #include <linux/mutex.h> |
41 | #include <linux/list.h> | 47 | #include <linux/list.h> |
42 | #include <linux/gfp.h> | 48 | #include <linux/gfp.h> |
49 | #include <linux/notifier.h> | ||
50 | #include <linux/memory.h> | ||
51 | #include <linux/memory_hotplug.h> | ||
43 | 52 | ||
44 | #include <asm/page.h> | 53 | #include <asm/page.h> |
45 | #include <asm/pgalloc.h> | 54 | #include <asm/pgalloc.h> |
@@ -194,6 +203,87 @@ static enum bp_state update_schedule(enum bp_state state) | |||
194 | return BP_EAGAIN; | 203 | return BP_EAGAIN; |
195 | } | 204 | } |
196 | 205 | ||
206 | #ifdef CONFIG_XEN_BALLOON_MEMORY_HOTPLUG | ||
207 | static long current_credit(void) | ||
208 | { | ||
209 | return balloon_stats.target_pages - balloon_stats.current_pages - | ||
210 | balloon_stats.hotplug_pages; | ||
211 | } | ||
212 | |||
213 | static bool balloon_is_inflated(void) | ||
214 | { | ||
215 | if (balloon_stats.balloon_low || balloon_stats.balloon_high || | ||
216 | balloon_stats.balloon_hotplug) | ||
217 | return true; | ||
218 | else | ||
219 | return false; | ||
220 | } | ||
221 | |||
222 | /* | ||
223 | * reserve_additional_memory() adds memory region of size >= credit above | ||
224 | * max_pfn. New region is section aligned and size is modified to be multiple | ||
225 | * of section size. Those features allow optimal use of address space and | ||
226 | * establish proper alignment when this function is called first time after | ||
227 | * boot (last section not fully populated at boot time contains unused memory | ||
228 | * pages with PG_reserved bit not set; online_pages_range() does not allow page | ||
229 | * onlining in whole range if first onlined page does not have PG_reserved | ||
230 | * bit set). Real size of added memory is established at page onlining stage. | ||
231 | */ | ||
232 | |||
233 | static enum bp_state reserve_additional_memory(long credit) | ||
234 | { | ||
235 | int nid, rc; | ||
236 | u64 hotplug_start_paddr; | ||
237 | unsigned long balloon_hotplug = credit; | ||
238 | |||
239 | hotplug_start_paddr = PFN_PHYS(SECTION_ALIGN_UP(max_pfn)); | ||
240 | balloon_hotplug = round_up(balloon_hotplug, PAGES_PER_SECTION); | ||
241 | nid = memory_add_physaddr_to_nid(hotplug_start_paddr); | ||
242 | |||
243 | rc = add_memory(nid, hotplug_start_paddr, balloon_hotplug << PAGE_SHIFT); | ||
244 | |||
245 | if (rc) { | ||
246 | pr_info("xen_balloon: %s: add_memory() failed: %i\n", __func__, rc); | ||
247 | return BP_EAGAIN; | ||
248 | } | ||
249 | |||
250 | balloon_hotplug -= credit; | ||
251 | |||
252 | balloon_stats.hotplug_pages += credit; | ||
253 | balloon_stats.balloon_hotplug = balloon_hotplug; | ||
254 | |||
255 | return BP_DONE; | ||
256 | } | ||
257 | |||
258 | static void xen_online_page(struct page *page) | ||
259 | { | ||
260 | __online_page_set_limits(page); | ||
261 | |||
262 | mutex_lock(&balloon_mutex); | ||
263 | |||
264 | __balloon_append(page); | ||
265 | |||
266 | if (balloon_stats.hotplug_pages) | ||
267 | --balloon_stats.hotplug_pages; | ||
268 | else | ||
269 | --balloon_stats.balloon_hotplug; | ||
270 | |||
271 | mutex_unlock(&balloon_mutex); | ||
272 | } | ||
273 | |||
274 | static int xen_memory_notifier(struct notifier_block *nb, unsigned long val, void *v) | ||
275 | { | ||
276 | if (val == MEM_ONLINE) | ||
277 | schedule_delayed_work(&balloon_worker, 0); | ||
278 | |||
279 | return NOTIFY_OK; | ||
280 | } | ||
281 | |||
282 | static struct notifier_block xen_memory_nb = { | ||
283 | .notifier_call = xen_memory_notifier, | ||
284 | .priority = 0 | ||
285 | }; | ||
286 | #else | ||
197 | static long current_credit(void) | 287 | static long current_credit(void) |
198 | { | 288 | { |
199 | unsigned long target = balloon_stats.target_pages; | 289 | unsigned long target = balloon_stats.target_pages; |
@@ -206,6 +296,21 @@ static long current_credit(void) | |||
206 | return target - balloon_stats.current_pages; | 296 | return target - balloon_stats.current_pages; |
207 | } | 297 | } |
208 | 298 | ||
299 | static bool balloon_is_inflated(void) | ||
300 | { | ||
301 | if (balloon_stats.balloon_low || balloon_stats.balloon_high) | ||
302 | return true; | ||
303 | else | ||
304 | return false; | ||
305 | } | ||
306 | |||
307 | static enum bp_state reserve_additional_memory(long credit) | ||
308 | { | ||
309 | balloon_stats.target_pages = balloon_stats.current_pages; | ||
310 | return BP_DONE; | ||
311 | } | ||
312 | #endif /* CONFIG_XEN_BALLOON_MEMORY_HOTPLUG */ | ||
313 | |||
209 | static enum bp_state increase_reservation(unsigned long nr_pages) | 314 | static enum bp_state increase_reservation(unsigned long nr_pages) |
210 | { | 315 | { |
211 | int rc; | 316 | int rc; |
@@ -217,6 +322,15 @@ static enum bp_state increase_reservation(unsigned long nr_pages) | |||
217 | .domid = DOMID_SELF | 322 | .domid = DOMID_SELF |
218 | }; | 323 | }; |
219 | 324 | ||
325 | #ifdef CONFIG_XEN_BALLOON_MEMORY_HOTPLUG | ||
326 | if (!balloon_stats.balloon_low && !balloon_stats.balloon_high) { | ||
327 | nr_pages = min(nr_pages, balloon_stats.balloon_hotplug); | ||
328 | balloon_stats.hotplug_pages += nr_pages; | ||
329 | balloon_stats.balloon_hotplug -= nr_pages; | ||
330 | return BP_DONE; | ||
331 | } | ||
332 | #endif | ||
333 | |||
220 | if (nr_pages > ARRAY_SIZE(frame_list)) | 334 | if (nr_pages > ARRAY_SIZE(frame_list)) |
221 | nr_pages = ARRAY_SIZE(frame_list); | 335 | nr_pages = ARRAY_SIZE(frame_list); |
222 | 336 | ||
@@ -279,6 +393,15 @@ static enum bp_state decrease_reservation(unsigned long nr_pages, gfp_t gfp) | |||
279 | .domid = DOMID_SELF | 393 | .domid = DOMID_SELF |
280 | }; | 394 | }; |
281 | 395 | ||
396 | #ifdef CONFIG_XEN_BALLOON_MEMORY_HOTPLUG | ||
397 | if (balloon_stats.hotplug_pages) { | ||
398 | nr_pages = min(nr_pages, balloon_stats.hotplug_pages); | ||
399 | balloon_stats.hotplug_pages -= nr_pages; | ||
400 | balloon_stats.balloon_hotplug += nr_pages; | ||
401 | return BP_DONE; | ||
402 | } | ||
403 | #endif | ||
404 | |||
282 | if (nr_pages > ARRAY_SIZE(frame_list)) | 405 | if (nr_pages > ARRAY_SIZE(frame_list)) |
283 | nr_pages = ARRAY_SIZE(frame_list); | 406 | nr_pages = ARRAY_SIZE(frame_list); |
284 | 407 | ||
@@ -340,8 +463,12 @@ static void balloon_process(struct work_struct *work) | |||
340 | do { | 463 | do { |
341 | credit = current_credit(); | 464 | credit = current_credit(); |
342 | 465 | ||
343 | if (credit > 0) | 466 | if (credit > 0) { |
344 | state = increase_reservation(credit); | 467 | if (balloon_is_inflated()) |
468 | state = increase_reservation(credit); | ||
469 | else | ||
470 | state = reserve_additional_memory(credit); | ||
471 | } | ||
345 | 472 | ||
346 | if (credit < 0) | 473 | if (credit < 0) |
347 | state = decrease_reservation(-credit, GFP_BALLOON); | 474 | state = decrease_reservation(-credit, GFP_BALLOON); |
@@ -448,6 +575,14 @@ static int __init balloon_init(void) | |||
448 | balloon_stats.retry_count = 1; | 575 | balloon_stats.retry_count = 1; |
449 | balloon_stats.max_retry_count = RETRY_UNLIMITED; | 576 | balloon_stats.max_retry_count = RETRY_UNLIMITED; |
450 | 577 | ||
578 | #ifdef CONFIG_XEN_BALLOON_MEMORY_HOTPLUG | ||
579 | balloon_stats.hotplug_pages = 0; | ||
580 | balloon_stats.balloon_hotplug = 0; | ||
581 | |||
582 | set_online_page_callback(&xen_online_page); | ||
583 | register_memory_notifier(&xen_memory_nb); | ||
584 | #endif | ||
585 | |||
451 | /* | 586 | /* |
452 | * Initialise the balloon with excess memory space. We need | 587 | * Initialise the balloon with excess memory space. We need |
453 | * to make sure we don't add memory which doesn't exist or | 588 | * to make sure we don't add memory which doesn't exist or |
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c index 0b686cec9976..87b6e0421c12 100644 --- a/fs/hugetlbfs/inode.c +++ b/fs/hugetlbfs/inode.c | |||
@@ -94,7 +94,7 @@ static int hugetlbfs_file_mmap(struct file *file, struct vm_area_struct *vma) | |||
94 | vma->vm_flags |= VM_HUGETLB | VM_RESERVED; | 94 | vma->vm_flags |= VM_HUGETLB | VM_RESERVED; |
95 | vma->vm_ops = &hugetlb_vm_ops; | 95 | vma->vm_ops = &hugetlb_vm_ops; |
96 | 96 | ||
97 | if (vma->vm_pgoff & ~(huge_page_mask(h) >> PAGE_SHIFT)) | 97 | if (vma->vm_pgoff & (~huge_page_mask(h) >> PAGE_SHIFT)) |
98 | return -EINVAL; | 98 | return -EINVAL; |
99 | 99 | ||
100 | vma_len = (loff_t)(vma->vm_end - vma->vm_start); | 100 | vma_len = (loff_t)(vma->vm_end - vma->vm_start); |
diff --git a/fs/proc/base.c b/fs/proc/base.c index 91fb655a5cbf..c9e3f650f23c 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
@@ -1118,10 +1118,9 @@ static ssize_t oom_adjust_write(struct file *file, const char __user *buf, | |||
1118 | * Warn that /proc/pid/oom_adj is deprecated, see | 1118 | * Warn that /proc/pid/oom_adj is deprecated, see |
1119 | * Documentation/feature-removal-schedule.txt. | 1119 | * Documentation/feature-removal-schedule.txt. |
1120 | */ | 1120 | */ |
1121 | printk_once(KERN_WARNING "%s (%d): /proc/%d/oom_adj is deprecated, " | 1121 | WARN_ONCE(1, "%s (%d): /proc/%d/oom_adj is deprecated, please use /proc/%d/oom_score_adj instead.\n", |
1122 | "please use /proc/%d/oom_score_adj instead.\n", | 1122 | current->comm, task_pid_nr(current), task_pid_nr(task), |
1123 | current->comm, task_pid_nr(current), | 1123 | task_pid_nr(task)); |
1124 | task_pid_nr(task), task_pid_nr(task)); | ||
1125 | task->signal->oom_adj = oom_adjust; | 1124 | task->signal->oom_adj = oom_adjust; |
1126 | /* | 1125 | /* |
1127 | * Scale /proc/pid/oom_score_adj appropriately ensuring that a maximum | 1126 | * Scale /proc/pid/oom_score_adj appropriately ensuring that a maximum |
diff --git a/fs/reiserfs/bitmap.c b/fs/reiserfs/bitmap.c index 483442e66ed6..d1aca1df4f92 100644 --- a/fs/reiserfs/bitmap.c +++ b/fs/reiserfs/bitmap.c | |||
@@ -214,7 +214,7 @@ static int scan_bitmap_block(struct reiserfs_transaction_handle *th, | |||
214 | } | 214 | } |
215 | /* otherwise we clear all bit were set ... */ | 215 | /* otherwise we clear all bit were set ... */ |
216 | while (--i >= *beg) | 216 | while (--i >= *beg) |
217 | reiserfs_test_and_clear_le_bit | 217 | reiserfs_clear_le_bit |
218 | (i, bh->b_data); | 218 | (i, bh->b_data); |
219 | reiserfs_restore_prepared_buffer(s, bh); | 219 | reiserfs_restore_prepared_buffer(s, bh); |
220 | *beg = org; | 220 | *beg = org; |
@@ -1222,15 +1222,11 @@ void reiserfs_cache_bitmap_metadata(struct super_block *sb, | |||
1222 | info->free_count = 0; | 1222 | info->free_count = 0; |
1223 | 1223 | ||
1224 | while (--cur >= (unsigned long *)bh->b_data) { | 1224 | while (--cur >= (unsigned long *)bh->b_data) { |
1225 | int i; | ||
1226 | |||
1227 | /* 0 and ~0 are special, we can optimize for them */ | 1225 | /* 0 and ~0 are special, we can optimize for them */ |
1228 | if (*cur == 0) | 1226 | if (*cur == 0) |
1229 | info->free_count += BITS_PER_LONG; | 1227 | info->free_count += BITS_PER_LONG; |
1230 | else if (*cur != ~0L) /* A mix, investigate */ | 1228 | else if (*cur != ~0L) /* A mix, investigate */ |
1231 | for (i = BITS_PER_LONG - 1; i >= 0; i--) | 1229 | info->free_count += BITS_PER_LONG - hweight_long(*cur); |
1232 | if (!reiserfs_test_le_bit(i, cur)) | ||
1233 | info->free_count++; | ||
1234 | } | 1230 | } |
1235 | } | 1231 | } |
1236 | 1232 | ||
diff --git a/fs/reiserfs/resize.c b/fs/reiserfs/resize.c index b3a94d20f0fc..b6b9b1fe33b0 100644 --- a/fs/reiserfs/resize.c +++ b/fs/reiserfs/resize.c | |||
@@ -136,7 +136,7 @@ int reiserfs_resize(struct super_block *s, unsigned long block_count_new) | |||
136 | return -EIO; | 136 | return -EIO; |
137 | } | 137 | } |
138 | memset(bh->b_data, 0, sb_blocksize(sb)); | 138 | memset(bh->b_data, 0, sb_blocksize(sb)); |
139 | reiserfs_test_and_set_le_bit(0, bh->b_data); | 139 | reiserfs_set_le_bit(0, bh->b_data); |
140 | reiserfs_cache_bitmap_metadata(s, bh, bitmap + i); | 140 | reiserfs_cache_bitmap_metadata(s, bh, bitmap + i); |
141 | 141 | ||
142 | set_buffer_uptodate(bh); | 142 | set_buffer_uptodate(bh); |
@@ -172,7 +172,7 @@ int reiserfs_resize(struct super_block *s, unsigned long block_count_new) | |||
172 | 172 | ||
173 | reiserfs_prepare_for_journal(s, bh, 1); | 173 | reiserfs_prepare_for_journal(s, bh, 1); |
174 | for (i = block_r; i < s->s_blocksize * 8; i++) | 174 | for (i = block_r; i < s->s_blocksize * 8; i++) |
175 | reiserfs_test_and_clear_le_bit(i, bh->b_data); | 175 | reiserfs_clear_le_bit(i, bh->b_data); |
176 | info->free_count += s->s_blocksize * 8 - block_r; | 176 | info->free_count += s->s_blocksize * 8 - block_r; |
177 | 177 | ||
178 | journal_mark_dirty(&th, s, bh); | 178 | journal_mark_dirty(&th, s, bh); |
@@ -190,7 +190,7 @@ int reiserfs_resize(struct super_block *s, unsigned long block_count_new) | |||
190 | 190 | ||
191 | reiserfs_prepare_for_journal(s, bh, 1); | 191 | reiserfs_prepare_for_journal(s, bh, 1); |
192 | for (i = block_r_new; i < s->s_blocksize * 8; i++) | 192 | for (i = block_r_new; i < s->s_blocksize * 8; i++) |
193 | reiserfs_test_and_set_le_bit(i, bh->b_data); | 193 | reiserfs_set_le_bit(i, bh->b_data); |
194 | journal_mark_dirty(&th, s, bh); | 194 | journal_mark_dirty(&th, s, bh); |
195 | brelse(bh); | 195 | brelse(bh); |
196 | 196 | ||
diff --git a/fs/splice.c b/fs/splice.c index aa866d309695..fa2defa8afcf 100644 --- a/fs/splice.c +++ b/fs/splice.c | |||
@@ -132,7 +132,7 @@ error: | |||
132 | return err; | 132 | return err; |
133 | } | 133 | } |
134 | 134 | ||
135 | static const struct pipe_buf_operations page_cache_pipe_buf_ops = { | 135 | const struct pipe_buf_operations page_cache_pipe_buf_ops = { |
136 | .can_merge = 0, | 136 | .can_merge = 0, |
137 | .map = generic_pipe_buf_map, | 137 | .map = generic_pipe_buf_map, |
138 | .unmap = generic_pipe_buf_unmap, | 138 | .unmap = generic_pipe_buf_unmap, |
@@ -264,7 +264,7 @@ ssize_t splice_to_pipe(struct pipe_inode_info *pipe, | |||
264 | return ret; | 264 | return ret; |
265 | } | 265 | } |
266 | 266 | ||
267 | static void spd_release_page(struct splice_pipe_desc *spd, unsigned int i) | 267 | void spd_release_page(struct splice_pipe_desc *spd, unsigned int i) |
268 | { | 268 | { |
269 | page_cache_release(spd->pages[i]); | 269 | page_cache_release(spd->pages[i]); |
270 | } | 270 | } |
diff --git a/include/asm-generic/system.h b/include/asm-generic/system.h index 4b0b9cbbfae5..215efa74f5a2 100644 --- a/include/asm-generic/system.h +++ b/include/asm-generic/system.h | |||
@@ -14,7 +14,6 @@ | |||
14 | #ifndef __ASM_GENERIC_SYSTEM_H | 14 | #ifndef __ASM_GENERIC_SYSTEM_H |
15 | #define __ASM_GENERIC_SYSTEM_H | 15 | #define __ASM_GENERIC_SYSTEM_H |
16 | 16 | ||
17 | #ifdef __KERNEL__ | ||
18 | #ifndef __ASSEMBLY__ | 17 | #ifndef __ASSEMBLY__ |
19 | 18 | ||
20 | #include <linux/types.h> | 19 | #include <linux/types.h> |
@@ -139,5 +138,4 @@ unsigned long __xchg(unsigned long x, volatile void *ptr, int size) | |||
139 | 138 | ||
140 | #endif /* !__ASSEMBLY__ */ | 139 | #endif /* !__ASSEMBLY__ */ |
141 | 140 | ||
142 | #endif /* __KERNEL__ */ | ||
143 | #endif /* __ASM_GENERIC_SYSTEM_H */ | 141 | #endif /* __ASM_GENERIC_SYSTEM_H */ |
diff --git a/include/linux/cpu.h b/include/linux/cpu.h index 5f09323ee880..b1a635acf72a 100644 --- a/include/linux/cpu.h +++ b/include/linux/cpu.h | |||
@@ -70,6 +70,39 @@ enum { | |||
70 | CPU_PRI_WORKQUEUE = 5, | 70 | CPU_PRI_WORKQUEUE = 5, |
71 | }; | 71 | }; |
72 | 72 | ||
73 | #define CPU_ONLINE 0x0002 /* CPU (unsigned)v is up */ | ||
74 | #define CPU_UP_PREPARE 0x0003 /* CPU (unsigned)v coming up */ | ||
75 | #define CPU_UP_CANCELED 0x0004 /* CPU (unsigned)v NOT coming up */ | ||
76 | #define CPU_DOWN_PREPARE 0x0005 /* CPU (unsigned)v going down */ | ||
77 | #define CPU_DOWN_FAILED 0x0006 /* CPU (unsigned)v NOT going down */ | ||
78 | #define CPU_DEAD 0x0007 /* CPU (unsigned)v dead */ | ||
79 | #define CPU_DYING 0x0008 /* CPU (unsigned)v not running any task, | ||
80 | * not handling interrupts, soon dead. | ||
81 | * Called on the dying cpu, interrupts | ||
82 | * are already disabled. Must not | ||
83 | * sleep, must not fail */ | ||
84 | #define CPU_POST_DEAD 0x0009 /* CPU (unsigned)v dead, cpu_hotplug | ||
85 | * lock is dropped */ | ||
86 | #define CPU_STARTING 0x000A /* CPU (unsigned)v soon running. | ||
87 | * Called on the new cpu, just before | ||
88 | * enabling interrupts. Must not sleep, | ||
89 | * must not fail */ | ||
90 | |||
91 | /* Used for CPU hotplug events occurring while tasks are frozen due to a suspend | ||
92 | * operation in progress | ||
93 | */ | ||
94 | #define CPU_TASKS_FROZEN 0x0010 | ||
95 | |||
96 | #define CPU_ONLINE_FROZEN (CPU_ONLINE | CPU_TASKS_FROZEN) | ||
97 | #define CPU_UP_PREPARE_FROZEN (CPU_UP_PREPARE | CPU_TASKS_FROZEN) | ||
98 | #define CPU_UP_CANCELED_FROZEN (CPU_UP_CANCELED | CPU_TASKS_FROZEN) | ||
99 | #define CPU_DOWN_PREPARE_FROZEN (CPU_DOWN_PREPARE | CPU_TASKS_FROZEN) | ||
100 | #define CPU_DOWN_FAILED_FROZEN (CPU_DOWN_FAILED | CPU_TASKS_FROZEN) | ||
101 | #define CPU_DEAD_FROZEN (CPU_DEAD | CPU_TASKS_FROZEN) | ||
102 | #define CPU_DYING_FROZEN (CPU_DYING | CPU_TASKS_FROZEN) | ||
103 | #define CPU_STARTING_FROZEN (CPU_STARTING | CPU_TASKS_FROZEN) | ||
104 | |||
105 | |||
73 | #ifdef CONFIG_SMP | 106 | #ifdef CONFIG_SMP |
74 | /* Need to know about CPUs going up/down? */ | 107 | /* Need to know about CPUs going up/down? */ |
75 | #if defined(CONFIG_HOTPLUG_CPU) || !defined(MODULE) | 108 | #if defined(CONFIG_HOTPLUG_CPU) || !defined(MODULE) |
diff --git a/include/linux/ctype.h b/include/linux/ctype.h index a3d6ee0044f9..8acfe312f947 100644 --- a/include/linux/ctype.h +++ b/include/linux/ctype.h | |||
@@ -52,4 +52,13 @@ static inline unsigned char __toupper(unsigned char c) | |||
52 | #define tolower(c) __tolower(c) | 52 | #define tolower(c) __tolower(c) |
53 | #define toupper(c) __toupper(c) | 53 | #define toupper(c) __toupper(c) |
54 | 54 | ||
55 | /* | ||
56 | * Fast implementation of tolower() for internal usage. Do not use in your | ||
57 | * code. | ||
58 | */ | ||
59 | static inline char _tolower(const char c) | ||
60 | { | ||
61 | return c | 0x20; | ||
62 | } | ||
63 | |||
55 | #endif | 64 | #endif |
diff --git a/include/linux/eeprom_93xx46.h b/include/linux/eeprom_93xx46.h new file mode 100644 index 000000000000..06791811e49d --- /dev/null +++ b/include/linux/eeprom_93xx46.h | |||
@@ -0,0 +1,18 @@ | |||
1 | /* | ||
2 | * Module: eeprom_93xx46 | ||
3 | * platform description for 93xx46 EEPROMs. | ||
4 | */ | ||
5 | |||
6 | struct eeprom_93xx46_platform_data { | ||
7 | unsigned char flags; | ||
8 | #define EE_ADDR8 0x01 /* 8 bit addr. cfg */ | ||
9 | #define EE_ADDR16 0x02 /* 16 bit addr. cfg */ | ||
10 | #define EE_READONLY 0x08 /* forbid writing */ | ||
11 | |||
12 | /* | ||
13 | * optional hooks to control additional logic | ||
14 | * before and after spi transfer. | ||
15 | */ | ||
16 | void (*prepare)(void *); | ||
17 | void (*finish)(void *); | ||
18 | }; | ||
diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h index 59225ef27d15..19644e0016bd 100644 --- a/include/linux/hugetlb.h +++ b/include/linux/hugetlb.h | |||
@@ -231,6 +231,9 @@ struct hstate { | |||
231 | struct huge_bootmem_page { | 231 | struct huge_bootmem_page { |
232 | struct list_head list; | 232 | struct list_head list; |
233 | struct hstate *hstate; | 233 | struct hstate *hstate; |
234 | #ifdef CONFIG_HIGHMEM | ||
235 | phys_addr_t phys; | ||
236 | #endif | ||
234 | }; | 237 | }; |
235 | 238 | ||
236 | struct page *alloc_huge_page_node(struct hstate *h, int nid); | 239 | struct page *alloc_huge_page_node(struct hstate *h, int nid); |
diff --git a/include/linux/ioport.h b/include/linux/ioport.h index e9bb22cba764..c2ebfe66177c 100644 --- a/include/linux/ioport.h +++ b/include/linux/ioport.h | |||
@@ -109,6 +109,36 @@ struct resource_list { | |||
109 | /* PCI control bits. Shares IORESOURCE_BITS with above PCI ROM. */ | 109 | /* PCI control bits. Shares IORESOURCE_BITS with above PCI ROM. */ |
110 | #define IORESOURCE_PCI_FIXED (1<<4) /* Do not move resource */ | 110 | #define IORESOURCE_PCI_FIXED (1<<4) /* Do not move resource */ |
111 | 111 | ||
112 | |||
113 | /* helpers to define resources */ | ||
114 | #define DEFINE_RES_NAMED(_start, _size, _name, _flags) \ | ||
115 | { \ | ||
116 | .start = (_start), \ | ||
117 | .end = (_start) + (_size) - 1, \ | ||
118 | .name = (_name), \ | ||
119 | .flags = (_flags), \ | ||
120 | } | ||
121 | |||
122 | #define DEFINE_RES_IO_NAMED(_start, _size, _name) \ | ||
123 | DEFINE_RES_NAMED((_start), (_size), (_name), IORESOURCE_IO) | ||
124 | #define DEFINE_RES_IO(_start, _size) \ | ||
125 | DEFINE_RES_IO_NAMED((_start), (_size), NULL) | ||
126 | |||
127 | #define DEFINE_RES_MEM_NAMED(_start, _size, _name) \ | ||
128 | DEFINE_RES_NAMED((_start), (_size), (_name), IORESOURCE_MEM) | ||
129 | #define DEFINE_RES_MEM(_start, _size) \ | ||
130 | DEFINE_RES_MEM_NAMED((_start), (_size), NULL) | ||
131 | |||
132 | #define DEFINE_RES_IRQ_NAMED(_irq, _name) \ | ||
133 | DEFINE_RES_NAMED((_irq), 1, (_name), IORESOURCE_IRQ) | ||
134 | #define DEFINE_RES_IRQ(_irq) \ | ||
135 | DEFINE_RES_IRQ_NAMED((_irq), NULL) | ||
136 | |||
137 | #define DEFINE_RES_DMA_NAMED(_dma, _name) \ | ||
138 | DEFINE_RES_NAMED((_dma), 1, (_name), IORESOURCE_DMA) | ||
139 | #define DEFINE_RES_DMA(_dma) \ | ||
140 | DEFINE_RES_DMA_NAMED((_dma), NULL) | ||
141 | |||
112 | /* PC/ISA/whatever - the normal PC address spaces: IO and memory */ | 142 | /* PC/ISA/whatever - the normal PC address spaces: IO and memory */ |
113 | extern struct resource ioport_resource; | 143 | extern struct resource ioport_resource; |
114 | extern struct resource iomem_resource; | 144 | extern struct resource iomem_resource; |
diff --git a/include/linux/kernel.h b/include/linux/kernel.h index 567a6f7bbeed..9a43ad792cfc 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h | |||
@@ -646,29 +646,6 @@ static inline void ftrace_dump(enum ftrace_dump_mode oops_dump_mode) { } | |||
646 | const typeof( ((type *)0)->member ) *__mptr = (ptr); \ | 646 | const typeof( ((type *)0)->member ) *__mptr = (ptr); \ |
647 | (type *)( (char *)__mptr - offsetof(type,member) );}) | 647 | (type *)( (char *)__mptr - offsetof(type,member) );}) |
648 | 648 | ||
649 | struct sysinfo; | ||
650 | extern int do_sysinfo(struct sysinfo *info); | ||
651 | |||
652 | #endif /* __KERNEL__ */ | ||
653 | |||
654 | #define SI_LOAD_SHIFT 16 | ||
655 | struct sysinfo { | ||
656 | long uptime; /* Seconds since boot */ | ||
657 | unsigned long loads[3]; /* 1, 5, and 15 minute load averages */ | ||
658 | unsigned long totalram; /* Total usable main memory size */ | ||
659 | unsigned long freeram; /* Available memory size */ | ||
660 | unsigned long sharedram; /* Amount of shared memory */ | ||
661 | unsigned long bufferram; /* Memory used by buffers */ | ||
662 | unsigned long totalswap; /* Total swap space size */ | ||
663 | unsigned long freeswap; /* swap space still available */ | ||
664 | unsigned short procs; /* Number of current processes */ | ||
665 | unsigned short pad; /* explicit padding for m68k */ | ||
666 | unsigned long totalhigh; /* Total high memory size */ | ||
667 | unsigned long freehigh; /* Available high memory size */ | ||
668 | unsigned int mem_unit; /* Memory unit size in bytes */ | ||
669 | char _f[20-2*sizeof(long)-sizeof(int)]; /* Padding: libc5 uses this.. */ | ||
670 | }; | ||
671 | |||
672 | #ifdef __CHECKER__ | 649 | #ifdef __CHECKER__ |
673 | #define BUILD_BUG_ON_NOT_POWER_OF_2(n) | 650 | #define BUILD_BUG_ON_NOT_POWER_OF_2(n) |
674 | #define BUILD_BUG_ON_ZERO(e) (0) | 651 | #define BUILD_BUG_ON_ZERO(e) (0) |
@@ -736,4 +713,27 @@ extern int __build_bug_on_failed; | |||
736 | # define REBUILD_DUE_TO_FTRACE_MCOUNT_RECORD | 713 | # define REBUILD_DUE_TO_FTRACE_MCOUNT_RECORD |
737 | #endif | 714 | #endif |
738 | 715 | ||
716 | struct sysinfo; | ||
717 | extern int do_sysinfo(struct sysinfo *info); | ||
718 | |||
719 | #endif /* __KERNEL__ */ | ||
720 | |||
721 | #define SI_LOAD_SHIFT 16 | ||
722 | struct sysinfo { | ||
723 | long uptime; /* Seconds since boot */ | ||
724 | unsigned long loads[3]; /* 1, 5, and 15 minute load averages */ | ||
725 | unsigned long totalram; /* Total usable main memory size */ | ||
726 | unsigned long freeram; /* Available memory size */ | ||
727 | unsigned long sharedram; /* Amount of shared memory */ | ||
728 | unsigned long bufferram; /* Memory used by buffers */ | ||
729 | unsigned long totalswap; /* Total swap space size */ | ||
730 | unsigned long freeswap; /* swap space still available */ | ||
731 | unsigned short procs; /* Number of current processes */ | ||
732 | unsigned short pad; /* explicit padding for m68k */ | ||
733 | unsigned long totalhigh; /* Total high memory size */ | ||
734 | unsigned long freehigh; /* Available high memory size */ | ||
735 | unsigned int mem_unit; /* Memory unit size in bytes */ | ||
736 | char _f[20-2*sizeof(long)-sizeof(int)]; /* Padding: libc5 uses this.. */ | ||
737 | }; | ||
738 | |||
739 | #endif | 739 | #endif |
diff --git a/include/linux/led-lm3530.h b/include/linux/led-lm3530.h index 58592fa67d24..8eb12357a110 100644 --- a/include/linux/led-lm3530.h +++ b/include/linux/led-lm3530.h | |||
@@ -84,6 +84,8 @@ enum lm3530_als_mode { | |||
84 | * @brt_ramp_rise: rate of rise of led current | 84 | * @brt_ramp_rise: rate of rise of led current |
85 | * @als1_resistor_sel: internal resistance from ALS1 input to ground | 85 | * @als1_resistor_sel: internal resistance from ALS1 input to ground |
86 | * @als2_resistor_sel: internal resistance from ALS2 input to ground | 86 | * @als2_resistor_sel: internal resistance from ALS2 input to ground |
87 | * @als_vmin: als input voltage calibrated for max brightness in mV | ||
88 | * @als_vmax: als input voltage calibrated for min brightness in mV | ||
87 | * @brt_val: brightness value (0-255) | 89 | * @brt_val: brightness value (0-255) |
88 | */ | 90 | */ |
89 | struct lm3530_platform_data { | 91 | struct lm3530_platform_data { |
@@ -101,6 +103,9 @@ struct lm3530_platform_data { | |||
101 | u8 als1_resistor_sel; | 103 | u8 als1_resistor_sel; |
102 | u8 als2_resistor_sel; | 104 | u8 als2_resistor_sel; |
103 | 105 | ||
106 | u32 als_vmin; | ||
107 | u32 als_vmax; | ||
108 | |||
104 | u8 brt_val; | 109 | u8 brt_val; |
105 | }; | 110 | }; |
106 | 111 | ||
diff --git a/include/linux/memory_hotplug.h b/include/linux/memory_hotplug.h index 8122018d3000..0b8e2a742600 100644 --- a/include/linux/memory_hotplug.h +++ b/include/linux/memory_hotplug.h | |||
@@ -68,12 +68,19 @@ static inline void zone_seqlock_init(struct zone *zone) | |||
68 | extern int zone_grow_free_lists(struct zone *zone, unsigned long new_nr_pages); | 68 | extern int zone_grow_free_lists(struct zone *zone, unsigned long new_nr_pages); |
69 | extern int zone_grow_waitqueues(struct zone *zone, unsigned long nr_pages); | 69 | extern int zone_grow_waitqueues(struct zone *zone, unsigned long nr_pages); |
70 | extern int add_one_highpage(struct page *page, int pfn, int bad_ppro); | 70 | extern int add_one_highpage(struct page *page, int pfn, int bad_ppro); |
71 | /* need some defines for these for archs that don't support it */ | ||
72 | extern void online_page(struct page *page); | ||
73 | /* VM interface that may be used by firmware interface */ | 71 | /* VM interface that may be used by firmware interface */ |
74 | extern int online_pages(unsigned long, unsigned long); | 72 | extern int online_pages(unsigned long, unsigned long); |
75 | extern void __offline_isolated_pages(unsigned long, unsigned long); | 73 | extern void __offline_isolated_pages(unsigned long, unsigned long); |
76 | 74 | ||
75 | typedef void (*online_page_callback_t)(struct page *page); | ||
76 | |||
77 | extern int set_online_page_callback(online_page_callback_t callback); | ||
78 | extern int restore_online_page_callback(online_page_callback_t callback); | ||
79 | |||
80 | extern void __online_page_set_limits(struct page *page); | ||
81 | extern void __online_page_increment_counters(struct page *page); | ||
82 | extern void __online_page_free(struct page *page); | ||
83 | |||
77 | #ifdef CONFIG_MEMORY_HOTREMOVE | 84 | #ifdef CONFIG_MEMORY_HOTREMOVE |
78 | extern bool is_pageblock_removable_nolock(struct page *page); | 85 | extern bool is_pageblock_removable_nolock(struct page *page); |
79 | #endif /* CONFIG_MEMORY_HOTREMOVE */ | 86 | #endif /* CONFIG_MEMORY_HOTREMOVE */ |
diff --git a/include/linux/mfd/pm8xxx/rtc.h b/include/linux/mfd/pm8xxx/rtc.h new file mode 100644 index 000000000000..14f1983eaecc --- /dev/null +++ b/include/linux/mfd/pm8xxx/rtc.h | |||
@@ -0,0 +1,25 @@ | |||
1 | /* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License version 2 and | ||
5 | * only version 2 as published by the Free Software Foundation. | ||
6 | * | ||
7 | * This program is distributed in the hope that it will be useful, | ||
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
10 | * GNU General Public License for more details. | ||
11 | */ | ||
12 | |||
13 | #ifndef __RTC_PM8XXX_H__ | ||
14 | #define __RTC_PM8XXX_H__ | ||
15 | |||
16 | #define PM8XXX_RTC_DEV_NAME "rtc-pm8xxx" | ||
17 | /** | ||
18 | * struct pm8xxx_rtc_pdata - RTC driver platform data | ||
19 | * @rtc_write_enable: variable stating RTC write capability | ||
20 | */ | ||
21 | struct pm8xxx_rtc_platform_data { | ||
22 | bool rtc_write_enable; | ||
23 | }; | ||
24 | |||
25 | #endif /* __RTC_PM8XXX_H__ */ | ||
diff --git a/include/linux/mm.h b/include/linux/mm.h index 8a45ad22a170..3172a1c0f08e 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h | |||
@@ -637,7 +637,7 @@ static inline pte_t maybe_mkwrite(pte_t pte, struct vm_area_struct *vma) | |||
637 | #define SECTIONS_MASK ((1UL << SECTIONS_WIDTH) - 1) | 637 | #define SECTIONS_MASK ((1UL << SECTIONS_WIDTH) - 1) |
638 | #define ZONEID_MASK ((1UL << ZONEID_SHIFT) - 1) | 638 | #define ZONEID_MASK ((1UL << ZONEID_SHIFT) - 1) |
639 | 639 | ||
640 | static inline enum zone_type page_zonenum(struct page *page) | 640 | static inline enum zone_type page_zonenum(const struct page *page) |
641 | { | 641 | { |
642 | return (page->flags >> ZONES_PGSHIFT) & ZONES_MASK; | 642 | return (page->flags >> ZONES_PGSHIFT) & ZONES_MASK; |
643 | } | 643 | } |
@@ -665,15 +665,15 @@ static inline int zone_to_nid(struct zone *zone) | |||
665 | } | 665 | } |
666 | 666 | ||
667 | #ifdef NODE_NOT_IN_PAGE_FLAGS | 667 | #ifdef NODE_NOT_IN_PAGE_FLAGS |
668 | extern int page_to_nid(struct page *page); | 668 | extern int page_to_nid(const struct page *page); |
669 | #else | 669 | #else |
670 | static inline int page_to_nid(struct page *page) | 670 | static inline int page_to_nid(const struct page *page) |
671 | { | 671 | { |
672 | return (page->flags >> NODES_PGSHIFT) & NODES_MASK; | 672 | return (page->flags >> NODES_PGSHIFT) & NODES_MASK; |
673 | } | 673 | } |
674 | #endif | 674 | #endif |
675 | 675 | ||
676 | static inline struct zone *page_zone(struct page *page) | 676 | static inline struct zone *page_zone(const struct page *page) |
677 | { | 677 | { |
678 | return &NODE_DATA(page_to_nid(page))->node_zones[page_zonenum(page)]; | 678 | return &NODE_DATA(page_to_nid(page))->node_zones[page_zonenum(page)]; |
679 | } | 679 | } |
@@ -718,9 +718,9 @@ static inline void set_page_links(struct page *page, enum zone_type zone, | |||
718 | */ | 718 | */ |
719 | #include <linux/vmstat.h> | 719 | #include <linux/vmstat.h> |
720 | 720 | ||
721 | static __always_inline void *lowmem_page_address(struct page *page) | 721 | static __always_inline void *lowmem_page_address(const struct page *page) |
722 | { | 722 | { |
723 | return __va(PFN_PHYS(page_to_pfn(page))); | 723 | return __va(PFN_PHYS(page_to_pfn((struct page *)page))); |
724 | } | 724 | } |
725 | 725 | ||
726 | #if defined(CONFIG_HIGHMEM) && !defined(WANT_PAGE_VIRTUAL) | 726 | #if defined(CONFIG_HIGHMEM) && !defined(WANT_PAGE_VIRTUAL) |
@@ -911,6 +911,8 @@ unsigned long unmap_vmas(struct mmu_gather *tlb, | |||
911 | * @pte_entry: if set, called for each non-empty PTE (4th-level) entry | 911 | * @pte_entry: if set, called for each non-empty PTE (4th-level) entry |
912 | * @pte_hole: if set, called for each hole at all levels | 912 | * @pte_hole: if set, called for each hole at all levels |
913 | * @hugetlb_entry: if set, called for each hugetlb entry | 913 | * @hugetlb_entry: if set, called for each hugetlb entry |
914 | * *Caution*: The caller must hold mmap_sem() if @hugetlb_entry | ||
915 | * is used. | ||
914 | * | 916 | * |
915 | * (see walk_page_range for more details) | 917 | * (see walk_page_range for more details) |
916 | */ | 918 | */ |
@@ -986,6 +988,8 @@ int get_user_pages(struct task_struct *tsk, struct mm_struct *mm, | |||
986 | int get_user_pages_fast(unsigned long start, int nr_pages, int write, | 988 | int get_user_pages_fast(unsigned long start, int nr_pages, int write, |
987 | struct page **pages); | 989 | struct page **pages); |
988 | struct page *get_dump_page(unsigned long addr); | 990 | struct page *get_dump_page(unsigned long addr); |
991 | extern int fixup_user_fault(struct task_struct *tsk, struct mm_struct *mm, | ||
992 | unsigned long address, unsigned int fault_flags); | ||
989 | 993 | ||
990 | extern int try_to_release_page(struct page * page, gfp_t gfp_mask); | 994 | extern int try_to_release_page(struct page * page, gfp_t gfp_mask); |
991 | extern void do_invalidatepage(struct page *page, unsigned long offset); | 995 | extern void do_invalidatepage(struct page *page, unsigned long offset); |
@@ -1409,8 +1413,7 @@ extern int do_munmap(struct mm_struct *, unsigned long, size_t); | |||
1409 | 1413 | ||
1410 | extern unsigned long do_brk(unsigned long, unsigned long); | 1414 | extern unsigned long do_brk(unsigned long, unsigned long); |
1411 | 1415 | ||
1412 | /* filemap.c */ | 1416 | /* truncate.c */ |
1413 | extern unsigned long page_unuse(struct page *); | ||
1414 | extern void truncate_inode_pages(struct address_space *, loff_t); | 1417 | extern void truncate_inode_pages(struct address_space *, loff_t); |
1415 | extern void truncate_inode_pages_range(struct address_space *, | 1418 | extern void truncate_inode_pages_range(struct address_space *, |
1416 | loff_t lstart, loff_t lend); | 1419 | loff_t lstart, loff_t lend); |
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 34f3abc6457a..ea6f4aa479d4 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h | |||
@@ -1521,6 +1521,39 @@ struct packet_type { | |||
1521 | 1521 | ||
1522 | #include <linux/notifier.h> | 1522 | #include <linux/notifier.h> |
1523 | 1523 | ||
1524 | /* netdevice notifier chain. Please remember to update the rtnetlink | ||
1525 | * notification exclusion list in rtnetlink_event() when adding new | ||
1526 | * types. | ||
1527 | */ | ||
1528 | #define NETDEV_UP 0x0001 /* For now you can't veto a device up/down */ | ||
1529 | #define NETDEV_DOWN 0x0002 | ||
1530 | #define NETDEV_REBOOT 0x0003 /* Tell a protocol stack a network interface | ||
1531 | detected a hardware crash and restarted | ||
1532 | - we can use this eg to kick tcp sessions | ||
1533 | once done */ | ||
1534 | #define NETDEV_CHANGE 0x0004 /* Notify device state change */ | ||
1535 | #define NETDEV_REGISTER 0x0005 | ||
1536 | #define NETDEV_UNREGISTER 0x0006 | ||
1537 | #define NETDEV_CHANGEMTU 0x0007 | ||
1538 | #define NETDEV_CHANGEADDR 0x0008 | ||
1539 | #define NETDEV_GOING_DOWN 0x0009 | ||
1540 | #define NETDEV_CHANGENAME 0x000A | ||
1541 | #define NETDEV_FEAT_CHANGE 0x000B | ||
1542 | #define NETDEV_BONDING_FAILOVER 0x000C | ||
1543 | #define NETDEV_PRE_UP 0x000D | ||
1544 | #define NETDEV_PRE_TYPE_CHANGE 0x000E | ||
1545 | #define NETDEV_POST_TYPE_CHANGE 0x000F | ||
1546 | #define NETDEV_POST_INIT 0x0010 | ||
1547 | #define NETDEV_UNREGISTER_BATCH 0x0011 | ||
1548 | #define NETDEV_RELEASE 0x0012 | ||
1549 | #define NETDEV_NOTIFY_PEERS 0x0013 | ||
1550 | #define NETDEV_JOIN 0x0014 | ||
1551 | |||
1552 | extern int register_netdevice_notifier(struct notifier_block *nb); | ||
1553 | extern int unregister_netdevice_notifier(struct notifier_block *nb); | ||
1554 | extern int call_netdevice_notifiers(unsigned long val, struct net_device *dev); | ||
1555 | |||
1556 | |||
1524 | extern rwlock_t dev_base_lock; /* Device list lock */ | 1557 | extern rwlock_t dev_base_lock; /* Device list lock */ |
1525 | 1558 | ||
1526 | 1559 | ||
@@ -1603,12 +1636,9 @@ static inline void unregister_netdevice(struct net_device *dev) | |||
1603 | extern int netdev_refcnt_read(const struct net_device *dev); | 1636 | extern int netdev_refcnt_read(const struct net_device *dev); |
1604 | extern void free_netdev(struct net_device *dev); | 1637 | extern void free_netdev(struct net_device *dev); |
1605 | extern void synchronize_net(void); | 1638 | extern void synchronize_net(void); |
1606 | extern int register_netdevice_notifier(struct notifier_block *nb); | ||
1607 | extern int unregister_netdevice_notifier(struct notifier_block *nb); | ||
1608 | extern int init_dummy_netdev(struct net_device *dev); | 1639 | extern int init_dummy_netdev(struct net_device *dev); |
1609 | extern void netdev_resync_ops(struct net_device *dev); | 1640 | extern void netdev_resync_ops(struct net_device *dev); |
1610 | 1641 | ||
1611 | extern int call_netdevice_notifiers(unsigned long val, struct net_device *dev); | ||
1612 | extern struct net_device *dev_get_by_index(struct net *net, int ifindex); | 1642 | extern struct net_device *dev_get_by_index(struct net *net, int ifindex); |
1613 | extern struct net_device *__dev_get_by_index(struct net *net, int ifindex); | 1643 | extern struct net_device *__dev_get_by_index(struct net *net, int ifindex); |
1614 | extern struct net_device *dev_get_by_index_rcu(struct net *net, int ifindex); | 1644 | extern struct net_device *dev_get_by_index_rcu(struct net *net, int ifindex); |
diff --git a/include/linux/notifier.h b/include/linux/notifier.h index c0688b0168b3..d65746efc954 100644 --- a/include/linux/notifier.h +++ b/include/linux/notifier.h | |||
@@ -185,80 +185,17 @@ static inline int notifier_to_errno(int ret) | |||
185 | * VC switch chains (for loadable kernel svgalib VC switch helpers) etc... | 185 | * VC switch chains (for loadable kernel svgalib VC switch helpers) etc... |
186 | */ | 186 | */ |
187 | 187 | ||
188 | /* netdevice notifier chain. Please remember to update the rtnetlink | 188 | /* CPU notfiers are defined in include/linux/cpu.h. */ |
189 | * notification exclusion list in rtnetlink_event() when adding new | ||
190 | * types. | ||
191 | */ | ||
192 | #define NETDEV_UP 0x0001 /* For now you can't veto a device up/down */ | ||
193 | #define NETDEV_DOWN 0x0002 | ||
194 | #define NETDEV_REBOOT 0x0003 /* Tell a protocol stack a network interface | ||
195 | detected a hardware crash and restarted | ||
196 | - we can use this eg to kick tcp sessions | ||
197 | once done */ | ||
198 | #define NETDEV_CHANGE 0x0004 /* Notify device state change */ | ||
199 | #define NETDEV_REGISTER 0x0005 | ||
200 | #define NETDEV_UNREGISTER 0x0006 | ||
201 | #define NETDEV_CHANGEMTU 0x0007 | ||
202 | #define NETDEV_CHANGEADDR 0x0008 | ||
203 | #define NETDEV_GOING_DOWN 0x0009 | ||
204 | #define NETDEV_CHANGENAME 0x000A | ||
205 | #define NETDEV_FEAT_CHANGE 0x000B | ||
206 | #define NETDEV_BONDING_FAILOVER 0x000C | ||
207 | #define NETDEV_PRE_UP 0x000D | ||
208 | #define NETDEV_PRE_TYPE_CHANGE 0x000E | ||
209 | #define NETDEV_POST_TYPE_CHANGE 0x000F | ||
210 | #define NETDEV_POST_INIT 0x0010 | ||
211 | #define NETDEV_UNREGISTER_BATCH 0x0011 | ||
212 | #define NETDEV_RELEASE 0x0012 | ||
213 | #define NETDEV_NOTIFY_PEERS 0x0013 | ||
214 | #define NETDEV_JOIN 0x0014 | ||
215 | |||
216 | #define SYS_DOWN 0x0001 /* Notify of system down */ | ||
217 | #define SYS_RESTART SYS_DOWN | ||
218 | #define SYS_HALT 0x0002 /* Notify of system halt */ | ||
219 | #define SYS_POWER_OFF 0x0003 /* Notify of system power off */ | ||
220 | 189 | ||
221 | #define NETLINK_URELEASE 0x0001 /* Unicast netlink socket released */ | 190 | /* netdevice notifiers are defined in include/linux/netdevice.h */ |
222 | 191 | ||
223 | #define CPU_ONLINE 0x0002 /* CPU (unsigned)v is up */ | 192 | /* reboot notifiers are defined in include/linux/reboot.h. */ |
224 | #define CPU_UP_PREPARE 0x0003 /* CPU (unsigned)v coming up */ | ||
225 | #define CPU_UP_CANCELED 0x0004 /* CPU (unsigned)v NOT coming up */ | ||
226 | #define CPU_DOWN_PREPARE 0x0005 /* CPU (unsigned)v going down */ | ||
227 | #define CPU_DOWN_FAILED 0x0006 /* CPU (unsigned)v NOT going down */ | ||
228 | #define CPU_DEAD 0x0007 /* CPU (unsigned)v dead */ | ||
229 | #define CPU_DYING 0x0008 /* CPU (unsigned)v not running any task, | ||
230 | * not handling interrupts, soon dead. | ||
231 | * Called on the dying cpu, interrupts | ||
232 | * are already disabled. Must not | ||
233 | * sleep, must not fail */ | ||
234 | #define CPU_POST_DEAD 0x0009 /* CPU (unsigned)v dead, cpu_hotplug | ||
235 | * lock is dropped */ | ||
236 | #define CPU_STARTING 0x000A /* CPU (unsigned)v soon running. | ||
237 | * Called on the new cpu, just before | ||
238 | * enabling interrupts. Must not sleep, | ||
239 | * must not fail */ | ||
240 | 193 | ||
241 | /* Used for CPU hotplug events occurring while tasks are frozen due to a suspend | 194 | /* Hibernation and suspend events are defined in include/linux/suspend.h. */ |
242 | * operation in progress | ||
243 | */ | ||
244 | #define CPU_TASKS_FROZEN 0x0010 | ||
245 | 195 | ||
246 | #define CPU_ONLINE_FROZEN (CPU_ONLINE | CPU_TASKS_FROZEN) | 196 | /* Virtual Terminal events are defined in include/linux/vt.h. */ |
247 | #define CPU_UP_PREPARE_FROZEN (CPU_UP_PREPARE | CPU_TASKS_FROZEN) | ||
248 | #define CPU_UP_CANCELED_FROZEN (CPU_UP_CANCELED | CPU_TASKS_FROZEN) | ||
249 | #define CPU_DOWN_PREPARE_FROZEN (CPU_DOWN_PREPARE | CPU_TASKS_FROZEN) | ||
250 | #define CPU_DOWN_FAILED_FROZEN (CPU_DOWN_FAILED | CPU_TASKS_FROZEN) | ||
251 | #define CPU_DEAD_FROZEN (CPU_DEAD | CPU_TASKS_FROZEN) | ||
252 | #define CPU_DYING_FROZEN (CPU_DYING | CPU_TASKS_FROZEN) | ||
253 | #define CPU_STARTING_FROZEN (CPU_STARTING | CPU_TASKS_FROZEN) | ||
254 | 197 | ||
255 | /* Hibernation and suspend events */ | 198 | #define NETLINK_URELEASE 0x0001 /* Unicast netlink socket released */ |
256 | #define PM_HIBERNATION_PREPARE 0x0001 /* Going to hibernate */ | ||
257 | #define PM_POST_HIBERNATION 0x0002 /* Hibernation finished */ | ||
258 | #define PM_SUSPEND_PREPARE 0x0003 /* Going to suspend the system */ | ||
259 | #define PM_POST_SUSPEND 0x0004 /* Suspend finished */ | ||
260 | #define PM_RESTORE_PREPARE 0x0005 /* Going to restore a saved image */ | ||
261 | #define PM_POST_RESTORE 0x0006 /* Restore failed */ | ||
262 | 199 | ||
263 | /* Console keyboard events. | 200 | /* Console keyboard events. |
264 | * Note: KBD_KEYCODE is always sent before KBD_UNBOUND_KEYCODE, KBD_UNICODE and | 201 | * Note: KBD_KEYCODE is always sent before KBD_UNBOUND_KEYCODE, KBD_UNICODE and |
@@ -271,12 +208,5 @@ static inline int notifier_to_errno(int ret) | |||
271 | 208 | ||
272 | extern struct blocking_notifier_head reboot_notifier_list; | 209 | extern struct blocking_notifier_head reboot_notifier_list; |
273 | 210 | ||
274 | /* Virtual Terminal events. */ | ||
275 | #define VT_ALLOCATE 0x0001 /* Console got allocated */ | ||
276 | #define VT_DEALLOCATE 0x0002 /* Console will be deallocated */ | ||
277 | #define VT_WRITE 0x0003 /* A char got output */ | ||
278 | #define VT_UPDATE 0x0004 /* A bigger update occurred */ | ||
279 | #define VT_PREWRITE 0x0005 /* A char is about to be written to the console */ | ||
280 | |||
281 | #endif /* __KERNEL__ */ | 211 | #endif /* __KERNEL__ */ |
282 | #endif /* _LINUX_NOTIFIER_H */ | 212 | #endif /* _LINUX_NOTIFIER_H */ |
diff --git a/include/linux/oom.h b/include/linux/oom.h index 4952fb874ad3..13b7b02e599a 100644 --- a/include/linux/oom.h +++ b/include/linux/oom.h | |||
@@ -64,10 +64,6 @@ static inline void oom_killer_enable(void) | |||
64 | oom_killer_disabled = false; | 64 | oom_killer_disabled = false; |
65 | } | 65 | } |
66 | 66 | ||
67 | /* The badness from the OOM killer */ | ||
68 | extern unsigned long badness(struct task_struct *p, struct mem_cgroup *mem, | ||
69 | const nodemask_t *nodemask, unsigned long uptime); | ||
70 | |||
71 | extern struct task_struct *find_lock_task_mm(struct task_struct *p); | 67 | extern struct task_struct *find_lock_task_mm(struct task_struct *p); |
72 | 68 | ||
73 | /* sysctls */ | 69 | /* sysctls */ |
diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h index 6081493db68f..3e5a1b189a41 100644 --- a/include/linux/page-flags.h +++ b/include/linux/page-flags.h | |||
@@ -135,7 +135,7 @@ enum pageflags { | |||
135 | * Macros to create function definitions for page flags | 135 | * Macros to create function definitions for page flags |
136 | */ | 136 | */ |
137 | #define TESTPAGEFLAG(uname, lname) \ | 137 | #define TESTPAGEFLAG(uname, lname) \ |
138 | static inline int Page##uname(struct page *page) \ | 138 | static inline int Page##uname(const struct page *page) \ |
139 | { return test_bit(PG_##lname, &page->flags); } | 139 | { return test_bit(PG_##lname, &page->flags); } |
140 | 140 | ||
141 | #define SETPAGEFLAG(uname, lname) \ | 141 | #define SETPAGEFLAG(uname, lname) \ |
@@ -173,7 +173,7 @@ static inline int __TestClearPage##uname(struct page *page) \ | |||
173 | __SETPAGEFLAG(uname, lname) __CLEARPAGEFLAG(uname, lname) | 173 | __SETPAGEFLAG(uname, lname) __CLEARPAGEFLAG(uname, lname) |
174 | 174 | ||
175 | #define PAGEFLAG_FALSE(uname) \ | 175 | #define PAGEFLAG_FALSE(uname) \ |
176 | static inline int Page##uname(struct page *page) \ | 176 | static inline int Page##uname(const struct page *page) \ |
177 | { return 0; } | 177 | { return 0; } |
178 | 178 | ||
179 | #define TESTSCFLAG(uname, lname) \ | 179 | #define TESTSCFLAG(uname, lname) \ |
diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h index 8e38d4c140ff..cfaaa6949b8b 100644 --- a/include/linux/pagemap.h +++ b/include/linux/pagemap.h | |||
@@ -255,26 +255,24 @@ static inline struct page *grab_cache_page(struct address_space *mapping, | |||
255 | extern struct page * grab_cache_page_nowait(struct address_space *mapping, | 255 | extern struct page * grab_cache_page_nowait(struct address_space *mapping, |
256 | pgoff_t index); | 256 | pgoff_t index); |
257 | extern struct page * read_cache_page_async(struct address_space *mapping, | 257 | extern struct page * read_cache_page_async(struct address_space *mapping, |
258 | pgoff_t index, filler_t *filler, | 258 | pgoff_t index, filler_t *filler, void *data); |
259 | void *data); | ||
260 | extern struct page * read_cache_page(struct address_space *mapping, | 259 | extern struct page * read_cache_page(struct address_space *mapping, |
261 | pgoff_t index, filler_t *filler, | 260 | pgoff_t index, filler_t *filler, void *data); |
262 | void *data); | ||
263 | extern struct page * read_cache_page_gfp(struct address_space *mapping, | 261 | extern struct page * read_cache_page_gfp(struct address_space *mapping, |
264 | pgoff_t index, gfp_t gfp_mask); | 262 | pgoff_t index, gfp_t gfp_mask); |
265 | extern int read_cache_pages(struct address_space *mapping, | 263 | extern int read_cache_pages(struct address_space *mapping, |
266 | struct list_head *pages, filler_t *filler, void *data); | 264 | struct list_head *pages, filler_t *filler, void *data); |
267 | 265 | ||
268 | static inline struct page *read_mapping_page_async( | 266 | static inline struct page *read_mapping_page_async( |
269 | struct address_space *mapping, | 267 | struct address_space *mapping, |
270 | pgoff_t index, void *data) | 268 | pgoff_t index, void *data) |
271 | { | 269 | { |
272 | filler_t *filler = (filler_t *)mapping->a_ops->readpage; | 270 | filler_t *filler = (filler_t *)mapping->a_ops->readpage; |
273 | return read_cache_page_async(mapping, index, filler, data); | 271 | return read_cache_page_async(mapping, index, filler, data); |
274 | } | 272 | } |
275 | 273 | ||
276 | static inline struct page *read_mapping_page(struct address_space *mapping, | 274 | static inline struct page *read_mapping_page(struct address_space *mapping, |
277 | pgoff_t index, void *data) | 275 | pgoff_t index, void *data) |
278 | { | 276 | { |
279 | filler_t *filler = (filler_t *)mapping->a_ops->readpage; | 277 | filler_t *filler = (filler_t *)mapping->a_ops->readpage; |
280 | return read_cache_page(mapping, index, filler, data); | 278 | return read_cache_page(mapping, index, filler, data); |
diff --git a/include/linux/platform_data/fsa9480.h b/include/linux/platform_data/fsa9480.h new file mode 100644 index 000000000000..72dddcb4bed1 --- /dev/null +++ b/include/linux/platform_data/fsa9480.h | |||
@@ -0,0 +1,27 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2010 Samsung Electronics | ||
3 | * Minkyu Kang <mk7.kang@samsung.com> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License version 2 as | ||
7 | * published by the Free Software Foundation. | ||
8 | */ | ||
9 | |||
10 | #ifndef _FSA9480_H_ | ||
11 | #define _FSA9480_H_ | ||
12 | |||
13 | #define FSA9480_ATTACHED 1 | ||
14 | #define FSA9480_DETACHED 0 | ||
15 | |||
16 | struct fsa9480_platform_data { | ||
17 | void (*cfg_gpio) (void); | ||
18 | void (*usb_cb) (u8 attached); | ||
19 | void (*uart_cb) (u8 attached); | ||
20 | void (*charger_cb) (u8 attached); | ||
21 | void (*jig_cb) (u8 attached); | ||
22 | void (*reset_cb) (void); | ||
23 | void (*usb_power) (u8 on); | ||
24 | int wakeup; | ||
25 | }; | ||
26 | |||
27 | #endif /* _FSA9480_H_ */ | ||
diff --git a/include/linux/poison.h b/include/linux/poison.h index 2110a81c5e2a..79159de0e341 100644 --- a/include/linux/poison.h +++ b/include/linux/poison.h | |||
@@ -40,6 +40,12 @@ | |||
40 | #define RED_INACTIVE 0x09F911029D74E35BULL /* when obj is inactive */ | 40 | #define RED_INACTIVE 0x09F911029D74E35BULL /* when obj is inactive */ |
41 | #define RED_ACTIVE 0xD84156C5635688C0ULL /* when obj is active */ | 41 | #define RED_ACTIVE 0xD84156C5635688C0ULL /* when obj is active */ |
42 | 42 | ||
43 | #ifdef CONFIG_PHYS_ADDR_T_64BIT | ||
44 | #define MEMBLOCK_INACTIVE 0x3a84fb0144c9e71bULL | ||
45 | #else | ||
46 | #define MEMBLOCK_INACTIVE 0x44c9e71bUL | ||
47 | #endif | ||
48 | |||
43 | #define SLUB_RED_INACTIVE 0xbb | 49 | #define SLUB_RED_INACTIVE 0xbb |
44 | #define SLUB_RED_ACTIVE 0xcc | 50 | #define SLUB_RED_ACTIVE 0xcc |
45 | 51 | ||
diff --git a/include/linux/reboot.h b/include/linux/reboot.h index 3005d5a7fce5..e0879a70e830 100644 --- a/include/linux/reboot.h +++ b/include/linux/reboot.h | |||
@@ -39,6 +39,11 @@ | |||
39 | 39 | ||
40 | #include <linux/notifier.h> | 40 | #include <linux/notifier.h> |
41 | 41 | ||
42 | #define SYS_DOWN 0x0001 /* Notify of system down */ | ||
43 | #define SYS_RESTART SYS_DOWN | ||
44 | #define SYS_HALT 0x0002 /* Notify of system halt */ | ||
45 | #define SYS_POWER_OFF 0x0003 /* Notify of system power off */ | ||
46 | |||
42 | extern int register_reboot_notifier(struct notifier_block *); | 47 | extern int register_reboot_notifier(struct notifier_block *); |
43 | extern int unregister_reboot_notifier(struct notifier_block *); | 48 | extern int unregister_reboot_notifier(struct notifier_block *); |
44 | 49 | ||
diff --git a/include/linux/reiserfs_fs.h b/include/linux/reiserfs_fs.h index eca75df00fed..96d465f8d3e6 100644 --- a/include/linux/reiserfs_fs.h +++ b/include/linux/reiserfs_fs.h | |||
@@ -2332,7 +2332,9 @@ __u32 keyed_hash(const signed char *msg, int len); | |||
2332 | __u32 yura_hash(const signed char *msg, int len); | 2332 | __u32 yura_hash(const signed char *msg, int len); |
2333 | __u32 r5_hash(const signed char *msg, int len); | 2333 | __u32 r5_hash(const signed char *msg, int len); |
2334 | 2334 | ||
2335 | #define reiserfs_set_le_bit __set_bit_le | ||
2335 | #define reiserfs_test_and_set_le_bit __test_and_set_bit_le | 2336 | #define reiserfs_test_and_set_le_bit __test_and_set_bit_le |
2337 | #define reiserfs_clear_le_bit __clear_bit_le | ||
2336 | #define reiserfs_test_and_clear_le_bit __test_and_clear_bit_le | 2338 | #define reiserfs_test_and_clear_le_bit __test_and_clear_bit_le |
2337 | #define reiserfs_test_le_bit test_bit_le | 2339 | #define reiserfs_test_le_bit test_bit_le |
2338 | #define reiserfs_find_next_zero_le_bit find_next_zero_bit_le | 2340 | #define reiserfs_find_next_zero_le_bit find_next_zero_bit_le |
diff --git a/include/linux/splice.h b/include/linux/splice.h index 997c3b4c212b..26e5b613deda 100644 --- a/include/linux/splice.h +++ b/include/linux/splice.h | |||
@@ -88,5 +88,7 @@ extern ssize_t splice_direct_to_actor(struct file *, struct splice_desc *, | |||
88 | extern int splice_grow_spd(struct pipe_inode_info *, struct splice_pipe_desc *); | 88 | extern int splice_grow_spd(struct pipe_inode_info *, struct splice_pipe_desc *); |
89 | extern void splice_shrink_spd(struct pipe_inode_info *, | 89 | extern void splice_shrink_spd(struct pipe_inode_info *, |
90 | struct splice_pipe_desc *); | 90 | struct splice_pipe_desc *); |
91 | extern void spd_release_page(struct splice_pipe_desc *, unsigned int); | ||
91 | 92 | ||
93 | extern const struct pipe_buf_operations page_cache_pipe_buf_ops; | ||
92 | #endif | 94 | #endif |
diff --git a/include/linux/suspend.h b/include/linux/suspend.h index e1e3742733be..6bbcef22e105 100644 --- a/include/linux/suspend.h +++ b/include/linux/suspend.h | |||
@@ -268,6 +268,14 @@ static inline int hibernate(void) { return -ENOSYS; } | |||
268 | static inline bool system_entering_hibernation(void) { return false; } | 268 | static inline bool system_entering_hibernation(void) { return false; } |
269 | #endif /* CONFIG_HIBERNATION */ | 269 | #endif /* CONFIG_HIBERNATION */ |
270 | 270 | ||
271 | /* Hibernation and suspend events */ | ||
272 | #define PM_HIBERNATION_PREPARE 0x0001 /* Going to hibernate */ | ||
273 | #define PM_POST_HIBERNATION 0x0002 /* Hibernation finished */ | ||
274 | #define PM_SUSPEND_PREPARE 0x0003 /* Going to suspend the system */ | ||
275 | #define PM_POST_SUSPEND 0x0004 /* Suspend finished */ | ||
276 | #define PM_RESTORE_PREPARE 0x0005 /* Going to restore a saved image */ | ||
277 | #define PM_POST_RESTORE 0x0006 /* Restore failed */ | ||
278 | |||
271 | #ifdef CONFIG_PM_SLEEP | 279 | #ifdef CONFIG_PM_SLEEP |
272 | void save_processor_state(void); | 280 | void save_processor_state(void); |
273 | void restore_processor_state(void); | 281 | void restore_processor_state(void); |
diff --git a/include/linux/vt.h b/include/linux/vt.h index d5dd0bc408fd..30a8dd9c83ff 100644 --- a/include/linux/vt.h +++ b/include/linux/vt.h | |||
@@ -86,6 +86,13 @@ struct vt_setactivate { | |||
86 | 86 | ||
87 | #ifdef __KERNEL__ | 87 | #ifdef __KERNEL__ |
88 | 88 | ||
89 | /* Virtual Terminal events. */ | ||
90 | #define VT_ALLOCATE 0x0001 /* Console got allocated */ | ||
91 | #define VT_DEALLOCATE 0x0002 /* Console will be deallocated */ | ||
92 | #define VT_WRITE 0x0003 /* A char got output */ | ||
93 | #define VT_UPDATE 0x0004 /* A bigger update occurred */ | ||
94 | #define VT_PREWRITE 0x0005 /* A char is about to be written to the console */ | ||
95 | |||
89 | #ifdef CONFIG_VT_CONSOLE | 96 | #ifdef CONFIG_VT_CONSOLE |
90 | 97 | ||
91 | extern int vt_kmsg_redirect(int new); | 98 | extern int vt_kmsg_redirect(int new); |
diff --git a/include/xen/balloon.h b/include/xen/balloon.h index 4076ed72afbd..76f7538bb339 100644 --- a/include/xen/balloon.h +++ b/include/xen/balloon.h | |||
@@ -15,6 +15,10 @@ struct balloon_stats { | |||
15 | unsigned long max_schedule_delay; | 15 | unsigned long max_schedule_delay; |
16 | unsigned long retry_count; | 16 | unsigned long retry_count; |
17 | unsigned long max_retry_count; | 17 | unsigned long max_retry_count; |
18 | #ifdef CONFIG_XEN_BALLOON_MEMORY_HOTPLUG | ||
19 | unsigned long hotplug_pages; | ||
20 | unsigned long balloon_hotplug; | ||
21 | #endif | ||
18 | }; | 22 | }; |
19 | 23 | ||
20 | extern struct balloon_stats balloon_stats; | 24 | extern struct balloon_stats balloon_stats; |
diff --git a/init/Kconfig b/init/Kconfig index e20aa3112240..d62778390e55 100644 --- a/init/Kconfig +++ b/init/Kconfig | |||
@@ -673,7 +673,7 @@ config CGROUP_MEM_RES_CTLR_SWAP | |||
673 | be careful about enabling this. When memory resource controller | 673 | be careful about enabling this. When memory resource controller |
674 | is disabled by boot option, this will be automatically disabled and | 674 | is disabled by boot option, this will be automatically disabled and |
675 | there will be no overhead from this. Even when you set this config=y, | 675 | there will be no overhead from this. Even when you set this config=y, |
676 | if boot option "noswapaccount" is set, swap will not be accounted. | 676 | if boot option "swapaccount=0" is set, swap will not be accounted. |
677 | Now, memory usage of swap_cgroup is 2 bytes per entry. If swap page | 677 | Now, memory usage of swap_cgroup is 2 bytes per entry. If swap page |
678 | size is 4096bytes, 512k per 1Gbytes of swap. | 678 | size is 4096bytes, 512k per 1Gbytes of swap. |
679 | config CGROUP_MEM_RES_CTLR_SWAP_ENABLED | 679 | config CGROUP_MEM_RES_CTLR_SWAP_ENABLED |
@@ -688,7 +688,7 @@ config CGROUP_MEM_RES_CTLR_SWAP_ENABLED | |||
688 | parameter should have this option unselected. | 688 | parameter should have this option unselected. |
689 | For those who want to have the feature enabled by default should | 689 | For those who want to have the feature enabled by default should |
690 | select this option (if, for some reason, they need to disable it | 690 | select this option (if, for some reason, they need to disable it |
691 | then noswapaccount does the trick). | 691 | then swapaccount=0 does the trick). |
692 | 692 | ||
693 | config CGROUP_PERF | 693 | config CGROUP_PERF |
694 | bool "Enable perf_event per-cpu per-container group (cgroup) monitoring" | 694 | bool "Enable perf_event per-cpu per-container group (cgroup) monitoring" |
diff --git a/init/calibrate.c b/init/calibrate.c index aae2f40fea4c..24df7976816c 100644 --- a/init/calibrate.c +++ b/init/calibrate.c | |||
@@ -9,6 +9,7 @@ | |||
9 | #include <linux/init.h> | 9 | #include <linux/init.h> |
10 | #include <linux/timex.h> | 10 | #include <linux/timex.h> |
11 | #include <linux/smp.h> | 11 | #include <linux/smp.h> |
12 | #include <linux/percpu.h> | ||
12 | 13 | ||
13 | unsigned long lpj_fine; | 14 | unsigned long lpj_fine; |
14 | unsigned long preset_lpj; | 15 | unsigned long preset_lpj; |
@@ -243,12 +244,19 @@ recalibrate: | |||
243 | return lpj; | 244 | return lpj; |
244 | } | 245 | } |
245 | 246 | ||
247 | static DEFINE_PER_CPU(unsigned long, cpu_loops_per_jiffy) = { 0 }; | ||
248 | |||
246 | void __cpuinit calibrate_delay(void) | 249 | void __cpuinit calibrate_delay(void) |
247 | { | 250 | { |
248 | unsigned long lpj; | 251 | unsigned long lpj; |
249 | static bool printed; | 252 | static bool printed; |
253 | int this_cpu = smp_processor_id(); | ||
250 | 254 | ||
251 | if (preset_lpj) { | 255 | if (per_cpu(cpu_loops_per_jiffy, this_cpu)) { |
256 | lpj = per_cpu(cpu_loops_per_jiffy, this_cpu); | ||
257 | pr_info("Calibrating delay loop (skipped) " | ||
258 | "already calibrated this CPU"); | ||
259 | } else if (preset_lpj) { | ||
252 | lpj = preset_lpj; | 260 | lpj = preset_lpj; |
253 | if (!printed) | 261 | if (!printed) |
254 | pr_info("Calibrating delay loop (skipped) " | 262 | pr_info("Calibrating delay loop (skipped) " |
@@ -266,6 +274,7 @@ void __cpuinit calibrate_delay(void) | |||
266 | pr_info("Calibrating delay loop... "); | 274 | pr_info("Calibrating delay loop... "); |
267 | lpj = calibrate_delay_converge(); | 275 | lpj = calibrate_delay_converge(); |
268 | } | 276 | } |
277 | per_cpu(cpu_loops_per_jiffy, this_cpu) = lpj; | ||
269 | if (!printed) | 278 | if (!printed) |
270 | pr_cont("%lu.%02lu BogoMIPS (lpj=%lu)\n", | 279 | pr_cont("%lu.%02lu BogoMIPS (lpj=%lu)\n", |
271 | lpj/(500000/HZ), | 280 | lpj/(500000/HZ), |
@@ -1450,15 +1450,24 @@ SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops, | |||
1450 | } | 1450 | } |
1451 | 1451 | ||
1452 | sma = sem_lock(ns, semid); | 1452 | sma = sem_lock(ns, semid); |
1453 | |||
1454 | /* | ||
1455 | * Wait until it's guaranteed that no wakeup_sem_queue_do() is ongoing. | ||
1456 | */ | ||
1457 | error = get_queue_result(&queue); | ||
1458 | |||
1459 | /* | ||
1460 | * Array removed? If yes, leave without sem_unlock(). | ||
1461 | */ | ||
1453 | if (IS_ERR(sma)) { | 1462 | if (IS_ERR(sma)) { |
1454 | error = -EIDRM; | 1463 | error = -EIDRM; |
1455 | goto out_free; | 1464 | goto out_free; |
1456 | } | 1465 | } |
1457 | 1466 | ||
1458 | error = get_queue_result(&queue); | ||
1459 | 1467 | ||
1460 | /* | 1468 | /* |
1461 | * If queue.status != -EINTR we are woken up by another process | 1469 | * If queue.status != -EINTR we are woken up by another process. |
1470 | * Leave without unlink_queue(), but with sem_unlock(). | ||
1462 | */ | 1471 | */ |
1463 | 1472 | ||
1464 | if (error != -EINTR) { | 1473 | if (error != -EINTR) { |
diff --git a/kernel/configs.c b/kernel/configs.c index b4066b44a99d..42e8fa075eed 100644 --- a/kernel/configs.c +++ b/kernel/configs.c | |||
@@ -92,8 +92,8 @@ static void __exit ikconfig_cleanup(void) | |||
92 | module_init(ikconfig_init); | 92 | module_init(ikconfig_init); |
93 | module_exit(ikconfig_cleanup); | 93 | module_exit(ikconfig_cleanup); |
94 | 94 | ||
95 | #endif /* CONFIG_IKCONFIG_PROC */ | ||
96 | |||
95 | MODULE_LICENSE("GPL"); | 97 | MODULE_LICENSE("GPL"); |
96 | MODULE_AUTHOR("Randy Dunlap"); | 98 | MODULE_AUTHOR("Randy Dunlap"); |
97 | MODULE_DESCRIPTION("Echo the kernel .config file used to build the kernel"); | 99 | MODULE_DESCRIPTION("Echo the kernel .config file used to build the kernel"); |
98 | |||
99 | #endif /* CONFIG_IKCONFIG_PROC */ | ||
diff --git a/kernel/futex.c b/kernel/futex.c index 3fbc76cbb9aa..0a308970c24a 100644 --- a/kernel/futex.c +++ b/kernel/futex.c | |||
@@ -355,8 +355,8 @@ static int fault_in_user_writeable(u32 __user *uaddr) | |||
355 | int ret; | 355 | int ret; |
356 | 356 | ||
357 | down_read(&mm->mmap_sem); | 357 | down_read(&mm->mmap_sem); |
358 | ret = get_user_pages(current, mm, (unsigned long)uaddr, | 358 | ret = fixup_user_fault(current, mm, (unsigned long)uaddr, |
359 | 1, 1, 0, NULL, NULL); | 359 | FAULT_FLAG_WRITE); |
360 | up_read(&mm->mmap_sem); | 360 | up_read(&mm->mmap_sem); |
361 | 361 | ||
362 | return ret < 0 ? ret : 0; | 362 | return ret < 0 ? ret : 0; |
diff --git a/kernel/irq/devres.c b/kernel/irq/devres.c index 1ef4ffcdfa55..bd8e788d71e0 100644 --- a/kernel/irq/devres.c +++ b/kernel/irq/devres.c | |||
@@ -87,8 +87,8 @@ void devm_free_irq(struct device *dev, unsigned int irq, void *dev_id) | |||
87 | { | 87 | { |
88 | struct irq_devres match_data = { irq, dev_id }; | 88 | struct irq_devres match_data = { irq, dev_id }; |
89 | 89 | ||
90 | free_irq(irq, dev_id); | ||
91 | WARN_ON(devres_destroy(dev, devm_irq_release, devm_irq_match, | 90 | WARN_ON(devres_destroy(dev, devm_irq_release, devm_irq_match, |
92 | &match_data)); | 91 | &match_data)); |
92 | free_irq(irq, dev_id); | ||
93 | } | 93 | } |
94 | EXPORT_SYMBOL(devm_free_irq); | 94 | EXPORT_SYMBOL(devm_free_irq); |
diff --git a/kernel/notifier.c b/kernel/notifier.c index 2488ba7eb568..8d7b435806c9 100644 --- a/kernel/notifier.c +++ b/kernel/notifier.c | |||
@@ -525,37 +525,6 @@ void srcu_init_notifier_head(struct srcu_notifier_head *nh) | |||
525 | } | 525 | } |
526 | EXPORT_SYMBOL_GPL(srcu_init_notifier_head); | 526 | EXPORT_SYMBOL_GPL(srcu_init_notifier_head); |
527 | 527 | ||
528 | /** | ||
529 | * register_reboot_notifier - Register function to be called at reboot time | ||
530 | * @nb: Info about notifier function to be called | ||
531 | * | ||
532 | * Registers a function with the list of functions | ||
533 | * to be called at reboot time. | ||
534 | * | ||
535 | * Currently always returns zero, as blocking_notifier_chain_register() | ||
536 | * always returns zero. | ||
537 | */ | ||
538 | int register_reboot_notifier(struct notifier_block *nb) | ||
539 | { | ||
540 | return blocking_notifier_chain_register(&reboot_notifier_list, nb); | ||
541 | } | ||
542 | EXPORT_SYMBOL(register_reboot_notifier); | ||
543 | |||
544 | /** | ||
545 | * unregister_reboot_notifier - Unregister previously registered reboot notifier | ||
546 | * @nb: Hook to be unregistered | ||
547 | * | ||
548 | * Unregisters a previously registered reboot | ||
549 | * notifier function. | ||
550 | * | ||
551 | * Returns zero on success, or %-ENOENT on failure. | ||
552 | */ | ||
553 | int unregister_reboot_notifier(struct notifier_block *nb) | ||
554 | { | ||
555 | return blocking_notifier_chain_unregister(&reboot_notifier_list, nb); | ||
556 | } | ||
557 | EXPORT_SYMBOL(unregister_reboot_notifier); | ||
558 | |||
559 | static ATOMIC_NOTIFIER_HEAD(die_chain); | 528 | static ATOMIC_NOTIFIER_HEAD(die_chain); |
560 | 529 | ||
561 | int notrace __kprobes notify_die(enum die_val val, const char *str, | 530 | int notrace __kprobes notify_die(enum die_val val, const char *str, |
diff --git a/kernel/sys.c b/kernel/sys.c index e4128b278f23..a101ba36c444 100644 --- a/kernel/sys.c +++ b/kernel/sys.c | |||
@@ -8,7 +8,6 @@ | |||
8 | #include <linux/mm.h> | 8 | #include <linux/mm.h> |
9 | #include <linux/utsname.h> | 9 | #include <linux/utsname.h> |
10 | #include <linux/mman.h> | 10 | #include <linux/mman.h> |
11 | #include <linux/notifier.h> | ||
12 | #include <linux/reboot.h> | 11 | #include <linux/reboot.h> |
13 | #include <linux/prctl.h> | 12 | #include <linux/prctl.h> |
14 | #include <linux/highuid.h> | 13 | #include <linux/highuid.h> |
@@ -320,6 +319,37 @@ void kernel_restart_prepare(char *cmd) | |||
320 | } | 319 | } |
321 | 320 | ||
322 | /** | 321 | /** |
322 | * register_reboot_notifier - Register function to be called at reboot time | ||
323 | * @nb: Info about notifier function to be called | ||
324 | * | ||
325 | * Registers a function with the list of functions | ||
326 | * to be called at reboot time. | ||
327 | * | ||
328 | * Currently always returns zero, as blocking_notifier_chain_register() | ||
329 | * always returns zero. | ||
330 | */ | ||
331 | int register_reboot_notifier(struct notifier_block *nb) | ||
332 | { | ||
333 | return blocking_notifier_chain_register(&reboot_notifier_list, nb); | ||
334 | } | ||
335 | EXPORT_SYMBOL(register_reboot_notifier); | ||
336 | |||
337 | /** | ||
338 | * unregister_reboot_notifier - Unregister previously registered reboot notifier | ||
339 | * @nb: Hook to be unregistered | ||
340 | * | ||
341 | * Unregisters a previously registered reboot | ||
342 | * notifier function. | ||
343 | * | ||
344 | * Returns zero on success, or %-ENOENT on failure. | ||
345 | */ | ||
346 | int unregister_reboot_notifier(struct notifier_block *nb) | ||
347 | { | ||
348 | return blocking_notifier_chain_unregister(&reboot_notifier_list, nb); | ||
349 | } | ||
350 | EXPORT_SYMBOL(unregister_reboot_notifier); | ||
351 | |||
352 | /** | ||
323 | * kernel_restart - reboot the system | 353 | * kernel_restart - reboot the system |
324 | * @cmd: pointer to buffer containing command to execute for restart | 354 | * @cmd: pointer to buffer containing command to execute for restart |
325 | * or %NULL | 355 | * or %NULL |
diff --git a/lib/devres.c b/lib/devres.c index 6efddf53b90c..7c0e953a7486 100644 --- a/lib/devres.c +++ b/lib/devres.c | |||
@@ -79,9 +79,9 @@ EXPORT_SYMBOL(devm_ioremap_nocache); | |||
79 | */ | 79 | */ |
80 | void devm_iounmap(struct device *dev, void __iomem *addr) | 80 | void devm_iounmap(struct device *dev, void __iomem *addr) |
81 | { | 81 | { |
82 | iounmap(addr); | ||
83 | WARN_ON(devres_destroy(dev, devm_ioremap_release, devm_ioremap_match, | 82 | WARN_ON(devres_destroy(dev, devm_ioremap_release, devm_ioremap_match, |
84 | (void *)addr)); | 83 | (void *)addr)); |
84 | iounmap(addr); | ||
85 | } | 85 | } |
86 | EXPORT_SYMBOL(devm_iounmap); | 86 | EXPORT_SYMBOL(devm_iounmap); |
87 | 87 | ||
diff --git a/lib/kstrtox.c b/lib/kstrtox.c index 2dbae88090ac..5e066759f551 100644 --- a/lib/kstrtox.c +++ b/lib/kstrtox.c | |||
@@ -19,11 +19,6 @@ | |||
19 | #include <linux/types.h> | 19 | #include <linux/types.h> |
20 | #include <asm/uaccess.h> | 20 | #include <asm/uaccess.h> |
21 | 21 | ||
22 | static inline char _tolower(const char c) | ||
23 | { | ||
24 | return c | 0x20; | ||
25 | } | ||
26 | |||
27 | static int _kstrtoull(const char *s, unsigned int base, unsigned long long *res) | 22 | static int _kstrtoull(const char *s, unsigned int base, unsigned long long *res) |
28 | { | 23 | { |
29 | unsigned long long acc; | 24 | unsigned long long acc; |
@@ -1,6 +1,7 @@ | |||
1 | #include <linux/kernel.h> | 1 | #include <linux/kernel.h> |
2 | #include <linux/gcd.h> | 2 | #include <linux/gcd.h> |
3 | #include <linux/module.h> | 3 | #include <linux/module.h> |
4 | #include <linux/lcm.h> | ||
4 | 5 | ||
5 | /* Lowest common multiple */ | 6 | /* Lowest common multiple */ |
6 | unsigned long lcm(unsigned long a, unsigned long b) | 7 | unsigned long lcm(unsigned long a, unsigned long b) |
diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 75bace7acefb..d7222a9c8267 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c | |||
@@ -31,13 +31,10 @@ | |||
31 | #include <asm/div64.h> | 31 | #include <asm/div64.h> |
32 | #include <asm/sections.h> /* for dereference_function_descriptor() */ | 32 | #include <asm/sections.h> /* for dereference_function_descriptor() */ |
33 | 33 | ||
34 | /* Works only for digits and letters, but small and fast */ | ||
35 | #define TOLOWER(x) ((x) | 0x20) | ||
36 | |||
37 | static unsigned int simple_guess_base(const char *cp) | 34 | static unsigned int simple_guess_base(const char *cp) |
38 | { | 35 | { |
39 | if (cp[0] == '0') { | 36 | if (cp[0] == '0') { |
40 | if (TOLOWER(cp[1]) == 'x' && isxdigit(cp[2])) | 37 | if (_tolower(cp[1]) == 'x' && isxdigit(cp[2])) |
41 | return 16; | 38 | return 16; |
42 | else | 39 | else |
43 | return 8; | 40 | return 8; |
@@ -59,13 +56,13 @@ unsigned long long simple_strtoull(const char *cp, char **endp, unsigned int bas | |||
59 | if (!base) | 56 | if (!base) |
60 | base = simple_guess_base(cp); | 57 | base = simple_guess_base(cp); |
61 | 58 | ||
62 | if (base == 16 && cp[0] == '0' && TOLOWER(cp[1]) == 'x') | 59 | if (base == 16 && cp[0] == '0' && _tolower(cp[1]) == 'x') |
63 | cp += 2; | 60 | cp += 2; |
64 | 61 | ||
65 | while (isxdigit(*cp)) { | 62 | while (isxdigit(*cp)) { |
66 | unsigned int value; | 63 | unsigned int value; |
67 | 64 | ||
68 | value = isdigit(*cp) ? *cp - '0' : TOLOWER(*cp) - 'a' + 10; | 65 | value = isdigit(*cp) ? *cp - '0' : _tolower(*cp) - 'a' + 10; |
69 | if (value >= base) | 66 | if (value >= base) |
70 | break; | 67 | break; |
71 | result = result * base + value; | 68 | result = result * base + value; |
@@ -1036,8 +1033,8 @@ precision: | |||
1036 | qualifier: | 1033 | qualifier: |
1037 | /* get the conversion qualifier */ | 1034 | /* get the conversion qualifier */ |
1038 | spec->qualifier = -1; | 1035 | spec->qualifier = -1; |
1039 | if (*fmt == 'h' || TOLOWER(*fmt) == 'l' || | 1036 | if (*fmt == 'h' || _tolower(*fmt) == 'l' || |
1040 | TOLOWER(*fmt) == 'z' || *fmt == 't') { | 1037 | _tolower(*fmt) == 'z' || *fmt == 't') { |
1041 | spec->qualifier = *fmt++; | 1038 | spec->qualifier = *fmt++; |
1042 | if (unlikely(spec->qualifier == *fmt)) { | 1039 | if (unlikely(spec->qualifier == *fmt)) { |
1043 | if (spec->qualifier == 'l') { | 1040 | if (spec->qualifier == 'l') { |
@@ -1104,7 +1101,7 @@ qualifier: | |||
1104 | spec->type = FORMAT_TYPE_LONG; | 1101 | spec->type = FORMAT_TYPE_LONG; |
1105 | else | 1102 | else |
1106 | spec->type = FORMAT_TYPE_ULONG; | 1103 | spec->type = FORMAT_TYPE_ULONG; |
1107 | } else if (TOLOWER(spec->qualifier) == 'z') { | 1104 | } else if (_tolower(spec->qualifier) == 'z') { |
1108 | spec->type = FORMAT_TYPE_SIZE_T; | 1105 | spec->type = FORMAT_TYPE_SIZE_T; |
1109 | } else if (spec->qualifier == 't') { | 1106 | } else if (spec->qualifier == 't') { |
1110 | spec->type = FORMAT_TYPE_PTRDIFF; | 1107 | spec->type = FORMAT_TYPE_PTRDIFF; |
@@ -1262,7 +1259,7 @@ int vsnprintf(char *buf, size_t size, const char *fmt, va_list args) | |||
1262 | if (qualifier == 'l') { | 1259 | if (qualifier == 'l') { |
1263 | long *ip = va_arg(args, long *); | 1260 | long *ip = va_arg(args, long *); |
1264 | *ip = (str - buf); | 1261 | *ip = (str - buf); |
1265 | } else if (TOLOWER(qualifier) == 'z') { | 1262 | } else if (_tolower(qualifier) == 'z') { |
1266 | size_t *ip = va_arg(args, size_t *); | 1263 | size_t *ip = va_arg(args, size_t *); |
1267 | *ip = (str - buf); | 1264 | *ip = (str - buf); |
1268 | } else { | 1265 | } else { |
@@ -1549,7 +1546,7 @@ do { \ | |||
1549 | void *skip_arg; | 1546 | void *skip_arg; |
1550 | if (qualifier == 'l') | 1547 | if (qualifier == 'l') |
1551 | skip_arg = va_arg(args, long *); | 1548 | skip_arg = va_arg(args, long *); |
1552 | else if (TOLOWER(qualifier) == 'z') | 1549 | else if (_tolower(qualifier) == 'z') |
1553 | skip_arg = va_arg(args, size_t *); | 1550 | skip_arg = va_arg(args, size_t *); |
1554 | else | 1551 | else |
1555 | skip_arg = va_arg(args, int *); | 1552 | skip_arg = va_arg(args, int *); |
@@ -1855,8 +1852,8 @@ int vsscanf(const char *buf, const char *fmt, va_list args) | |||
1855 | 1852 | ||
1856 | /* get conversion qualifier */ | 1853 | /* get conversion qualifier */ |
1857 | qualifier = -1; | 1854 | qualifier = -1; |
1858 | if (*fmt == 'h' || TOLOWER(*fmt) == 'l' || | 1855 | if (*fmt == 'h' || _tolower(*fmt) == 'l' || |
1859 | TOLOWER(*fmt) == 'z') { | 1856 | _tolower(*fmt) == 'z') { |
1860 | qualifier = *fmt++; | 1857 | qualifier = *fmt++; |
1861 | if (unlikely(qualifier == *fmt)) { | 1858 | if (unlikely(qualifier == *fmt)) { |
1862 | if (qualifier == 'h') { | 1859 | if (qualifier == 'h') { |
diff --git a/mm/backing-dev.c b/mm/backing-dev.c index 2ef0dc9e7f39..8290b1e88257 100644 --- a/mm/backing-dev.c +++ b/mm/backing-dev.c | |||
@@ -606,6 +606,7 @@ static void bdi_prune_sb(struct backing_dev_info *bdi) | |||
606 | void bdi_unregister(struct backing_dev_info *bdi) | 606 | void bdi_unregister(struct backing_dev_info *bdi) |
607 | { | 607 | { |
608 | if (bdi->dev) { | 608 | if (bdi->dev) { |
609 | bdi_set_min_ratio(bdi, 0); | ||
609 | trace_writeback_bdi_unregister(bdi); | 610 | trace_writeback_bdi_unregister(bdi); |
610 | bdi_prune_sb(bdi); | 611 | bdi_prune_sb(bdi); |
611 | del_timer_sync(&bdi->wb.wakeup_timer); | 612 | del_timer_sync(&bdi->wb.wakeup_timer); |
diff --git a/mm/dmapool.c b/mm/dmapool.c index 03bf3bb4519a..fbb58e346888 100644 --- a/mm/dmapool.c +++ b/mm/dmapool.c | |||
@@ -500,7 +500,7 @@ void dmam_pool_destroy(struct dma_pool *pool) | |||
500 | { | 500 | { |
501 | struct device *dev = pool->dev; | 501 | struct device *dev = pool->dev; |
502 | 502 | ||
503 | dma_pool_destroy(pool); | ||
504 | WARN_ON(devres_destroy(dev, dmam_pool_release, dmam_pool_match, pool)); | 503 | WARN_ON(devres_destroy(dev, dmam_pool_release, dmam_pool_match, pool)); |
504 | dma_pool_destroy(pool); | ||
505 | } | 505 | } |
506 | EXPORT_SYMBOL(dmam_pool_destroy); | 506 | EXPORT_SYMBOL(dmam_pool_destroy); |
diff --git a/mm/filemap.c b/mm/filemap.c index f820e600f1ad..10a171113273 100644 --- a/mm/filemap.c +++ b/mm/filemap.c | |||
@@ -128,6 +128,7 @@ void __delete_from_page_cache(struct page *page) | |||
128 | 128 | ||
129 | radix_tree_delete(&mapping->page_tree, page->index); | 129 | radix_tree_delete(&mapping->page_tree, page->index); |
130 | page->mapping = NULL; | 130 | page->mapping = NULL; |
131 | /* Leave page->index set: truncation lookup relies upon it */ | ||
131 | mapping->nrpages--; | 132 | mapping->nrpages--; |
132 | __dec_zone_page_state(page, NR_FILE_PAGES); | 133 | __dec_zone_page_state(page, NR_FILE_PAGES); |
133 | if (PageSwapBacked(page)) | 134 | if (PageSwapBacked(page)) |
@@ -483,6 +484,7 @@ int add_to_page_cache_locked(struct page *page, struct address_space *mapping, | |||
483 | spin_unlock_irq(&mapping->tree_lock); | 484 | spin_unlock_irq(&mapping->tree_lock); |
484 | } else { | 485 | } else { |
485 | page->mapping = NULL; | 486 | page->mapping = NULL; |
487 | /* Leave page->index set: truncation relies upon it */ | ||
486 | spin_unlock_irq(&mapping->tree_lock); | 488 | spin_unlock_irq(&mapping->tree_lock); |
487 | mem_cgroup_uncharge_cache_page(page); | 489 | mem_cgroup_uncharge_cache_page(page); |
488 | page_cache_release(page); | 490 | page_cache_release(page); |
@@ -1792,7 +1794,7 @@ EXPORT_SYMBOL(generic_file_readonly_mmap); | |||
1792 | 1794 | ||
1793 | static struct page *__read_cache_page(struct address_space *mapping, | 1795 | static struct page *__read_cache_page(struct address_space *mapping, |
1794 | pgoff_t index, | 1796 | pgoff_t index, |
1795 | int (*filler)(void *,struct page*), | 1797 | int (*filler)(void *, struct page *), |
1796 | void *data, | 1798 | void *data, |
1797 | gfp_t gfp) | 1799 | gfp_t gfp) |
1798 | { | 1800 | { |
@@ -1823,7 +1825,7 @@ repeat: | |||
1823 | 1825 | ||
1824 | static struct page *do_read_cache_page(struct address_space *mapping, | 1826 | static struct page *do_read_cache_page(struct address_space *mapping, |
1825 | pgoff_t index, | 1827 | pgoff_t index, |
1826 | int (*filler)(void *,struct page*), | 1828 | int (*filler)(void *, struct page *), |
1827 | void *data, | 1829 | void *data, |
1828 | gfp_t gfp) | 1830 | gfp_t gfp) |
1829 | 1831 | ||
@@ -1863,7 +1865,7 @@ out: | |||
1863 | * @mapping: the page's address_space | 1865 | * @mapping: the page's address_space |
1864 | * @index: the page index | 1866 | * @index: the page index |
1865 | * @filler: function to perform the read | 1867 | * @filler: function to perform the read |
1866 | * @data: destination for read data | 1868 | * @data: first arg to filler(data, page) function, often left as NULL |
1867 | * | 1869 | * |
1868 | * Same as read_cache_page, but don't wait for page to become unlocked | 1870 | * Same as read_cache_page, but don't wait for page to become unlocked |
1869 | * after submitting it to the filler. | 1871 | * after submitting it to the filler. |
@@ -1875,7 +1877,7 @@ out: | |||
1875 | */ | 1877 | */ |
1876 | struct page *read_cache_page_async(struct address_space *mapping, | 1878 | struct page *read_cache_page_async(struct address_space *mapping, |
1877 | pgoff_t index, | 1879 | pgoff_t index, |
1878 | int (*filler)(void *,struct page*), | 1880 | int (*filler)(void *, struct page *), |
1879 | void *data) | 1881 | void *data) |
1880 | { | 1882 | { |
1881 | return do_read_cache_page(mapping, index, filler, data, mapping_gfp_mask(mapping)); | 1883 | return do_read_cache_page(mapping, index, filler, data, mapping_gfp_mask(mapping)); |
@@ -1923,7 +1925,7 @@ EXPORT_SYMBOL(read_cache_page_gfp); | |||
1923 | * @mapping: the page's address_space | 1925 | * @mapping: the page's address_space |
1924 | * @index: the page index | 1926 | * @index: the page index |
1925 | * @filler: function to perform the read | 1927 | * @filler: function to perform the read |
1926 | * @data: destination for read data | 1928 | * @data: first arg to filler(data, page) function, often left as NULL |
1927 | * | 1929 | * |
1928 | * Read into the page cache. If a page already exists, and PageUptodate() is | 1930 | * Read into the page cache. If a page already exists, and PageUptodate() is |
1929 | * not set, try to fill the page then wait for it to become unlocked. | 1931 | * not set, try to fill the page then wait for it to become unlocked. |
@@ -1932,7 +1934,7 @@ EXPORT_SYMBOL(read_cache_page_gfp); | |||
1932 | */ | 1934 | */ |
1933 | struct page *read_cache_page(struct address_space *mapping, | 1935 | struct page *read_cache_page(struct address_space *mapping, |
1934 | pgoff_t index, | 1936 | pgoff_t index, |
1935 | int (*filler)(void *,struct page*), | 1937 | int (*filler)(void *, struct page *), |
1936 | void *data) | 1938 | void *data) |
1937 | { | 1939 | { |
1938 | return wait_on_page_read(read_cache_page_async(mapping, index, filler, data)); | 1940 | return wait_on_page_read(read_cache_page_async(mapping, index, filler, data)); |
diff --git a/mm/huge_memory.c b/mm/huge_memory.c index 81532f297fd2..e2d1587be269 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c | |||
@@ -1596,14 +1596,13 @@ void __khugepaged_exit(struct mm_struct *mm) | |||
1596 | list_del(&mm_slot->mm_node); | 1596 | list_del(&mm_slot->mm_node); |
1597 | free = 1; | 1597 | free = 1; |
1598 | } | 1598 | } |
1599 | spin_unlock(&khugepaged_mm_lock); | ||
1599 | 1600 | ||
1600 | if (free) { | 1601 | if (free) { |
1601 | spin_unlock(&khugepaged_mm_lock); | ||
1602 | clear_bit(MMF_VM_HUGEPAGE, &mm->flags); | 1602 | clear_bit(MMF_VM_HUGEPAGE, &mm->flags); |
1603 | free_mm_slot(mm_slot); | 1603 | free_mm_slot(mm_slot); |
1604 | mmdrop(mm); | 1604 | mmdrop(mm); |
1605 | } else if (mm_slot) { | 1605 | } else if (mm_slot) { |
1606 | spin_unlock(&khugepaged_mm_lock); | ||
1607 | /* | 1606 | /* |
1608 | * This is required to serialize against | 1607 | * This is required to serialize against |
1609 | * khugepaged_test_exit() (which is guaranteed to run | 1608 | * khugepaged_test_exit() (which is guaranteed to run |
@@ -1614,8 +1613,7 @@ void __khugepaged_exit(struct mm_struct *mm) | |||
1614 | */ | 1613 | */ |
1615 | down_write(&mm->mmap_sem); | 1614 | down_write(&mm->mmap_sem); |
1616 | up_write(&mm->mmap_sem); | 1615 | up_write(&mm->mmap_sem); |
1617 | } else | 1616 | } |
1618 | spin_unlock(&khugepaged_mm_lock); | ||
1619 | } | 1617 | } |
1620 | 1618 | ||
1621 | static void release_pte_page(struct page *page) | 1619 | static void release_pte_page(struct page *page) |
diff --git a/mm/hugetlb.c b/mm/hugetlb.c index bfcf153bc829..dae27ba3be2c 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c | |||
@@ -24,7 +24,7 @@ | |||
24 | 24 | ||
25 | #include <asm/page.h> | 25 | #include <asm/page.h> |
26 | #include <asm/pgtable.h> | 26 | #include <asm/pgtable.h> |
27 | #include <asm/io.h> | 27 | #include <linux/io.h> |
28 | 28 | ||
29 | #include <linux/hugetlb.h> | 29 | #include <linux/hugetlb.h> |
30 | #include <linux/node.h> | 30 | #include <linux/node.h> |
@@ -62,10 +62,10 @@ static DEFINE_SPINLOCK(hugetlb_lock); | |||
62 | * must either hold the mmap_sem for write, or the mmap_sem for read and | 62 | * must either hold the mmap_sem for write, or the mmap_sem for read and |
63 | * the hugetlb_instantiation mutex: | 63 | * the hugetlb_instantiation mutex: |
64 | * | 64 | * |
65 | * down_write(&mm->mmap_sem); | 65 | * down_write(&mm->mmap_sem); |
66 | * or | 66 | * or |
67 | * down_read(&mm->mmap_sem); | 67 | * down_read(&mm->mmap_sem); |
68 | * mutex_lock(&hugetlb_instantiation_mutex); | 68 | * mutex_lock(&hugetlb_instantiation_mutex); |
69 | */ | 69 | */ |
70 | struct file_region { | 70 | struct file_region { |
71 | struct list_head link; | 71 | struct list_head link; |
@@ -503,9 +503,10 @@ static void update_and_free_page(struct hstate *h, struct page *page) | |||
503 | h->nr_huge_pages--; | 503 | h->nr_huge_pages--; |
504 | h->nr_huge_pages_node[page_to_nid(page)]--; | 504 | h->nr_huge_pages_node[page_to_nid(page)]--; |
505 | for (i = 0; i < pages_per_huge_page(h); i++) { | 505 | for (i = 0; i < pages_per_huge_page(h); i++) { |
506 | page[i].flags &= ~(1 << PG_locked | 1 << PG_error | 1 << PG_referenced | | 506 | page[i].flags &= ~(1 << PG_locked | 1 << PG_error | |
507 | 1 << PG_dirty | 1 << PG_active | 1 << PG_reserved | | 507 | 1 << PG_referenced | 1 << PG_dirty | |
508 | 1 << PG_private | 1<< PG_writeback); | 508 | 1 << PG_active | 1 << PG_reserved | |
509 | 1 << PG_private | 1 << PG_writeback); | ||
509 | } | 510 | } |
510 | set_compound_page_dtor(page, NULL); | 511 | set_compound_page_dtor(page, NULL); |
511 | set_page_refcounted(page); | 512 | set_page_refcounted(page); |
@@ -591,7 +592,6 @@ int PageHuge(struct page *page) | |||
591 | 592 | ||
592 | return dtor == free_huge_page; | 593 | return dtor == free_huge_page; |
593 | } | 594 | } |
594 | |||
595 | EXPORT_SYMBOL_GPL(PageHuge); | 595 | EXPORT_SYMBOL_GPL(PageHuge); |
596 | 596 | ||
597 | static struct page *alloc_fresh_huge_page_node(struct hstate *h, int nid) | 597 | static struct page *alloc_fresh_huge_page_node(struct hstate *h, int nid) |
@@ -1105,8 +1105,16 @@ static void __init gather_bootmem_prealloc(void) | |||
1105 | struct huge_bootmem_page *m; | 1105 | struct huge_bootmem_page *m; |
1106 | 1106 | ||
1107 | list_for_each_entry(m, &huge_boot_pages, list) { | 1107 | list_for_each_entry(m, &huge_boot_pages, list) { |
1108 | struct page *page = virt_to_page(m); | ||
1109 | struct hstate *h = m->hstate; | 1108 | struct hstate *h = m->hstate; |
1109 | struct page *page; | ||
1110 | |||
1111 | #ifdef CONFIG_HIGHMEM | ||
1112 | page = pfn_to_page(m->phys >> PAGE_SHIFT); | ||
1113 | free_bootmem_late((unsigned long)m, | ||
1114 | sizeof(struct huge_bootmem_page)); | ||
1115 | #else | ||
1116 | page = virt_to_page(m); | ||
1117 | #endif | ||
1110 | __ClearPageReserved(page); | 1118 | __ClearPageReserved(page); |
1111 | WARN_ON(page_count(page) != 1); | 1119 | WARN_ON(page_count(page) != 1); |
1112 | prep_compound_huge_page(page, h->order); | 1120 | prep_compound_huge_page(page, h->order); |
@@ -2124,9 +2132,8 @@ static void set_huge_ptep_writable(struct vm_area_struct *vma, | |||
2124 | pte_t entry; | 2132 | pte_t entry; |
2125 | 2133 | ||
2126 | entry = pte_mkwrite(pte_mkdirty(huge_ptep_get(ptep))); | 2134 | entry = pte_mkwrite(pte_mkdirty(huge_ptep_get(ptep))); |
2127 | if (huge_ptep_set_access_flags(vma, address, ptep, entry, 1)) { | 2135 | if (huge_ptep_set_access_flags(vma, address, ptep, entry, 1)) |
2128 | update_mmu_cache(vma, address, ptep); | 2136 | update_mmu_cache(vma, address, ptep); |
2129 | } | ||
2130 | } | 2137 | } |
2131 | 2138 | ||
2132 | 2139 | ||
@@ -2181,9 +2188,9 @@ static int is_hugetlb_entry_migration(pte_t pte) | |||
2181 | if (huge_pte_none(pte) || pte_present(pte)) | 2188 | if (huge_pte_none(pte) || pte_present(pte)) |
2182 | return 0; | 2189 | return 0; |
2183 | swp = pte_to_swp_entry(pte); | 2190 | swp = pte_to_swp_entry(pte); |
2184 | if (non_swap_entry(swp) && is_migration_entry(swp)) { | 2191 | if (non_swap_entry(swp) && is_migration_entry(swp)) |
2185 | return 1; | 2192 | return 1; |
2186 | } else | 2193 | else |
2187 | return 0; | 2194 | return 0; |
2188 | } | 2195 | } |
2189 | 2196 | ||
@@ -2194,9 +2201,9 @@ static int is_hugetlb_entry_hwpoisoned(pte_t pte) | |||
2194 | if (huge_pte_none(pte) || pte_present(pte)) | 2201 | if (huge_pte_none(pte) || pte_present(pte)) |
2195 | return 0; | 2202 | return 0; |
2196 | swp = pte_to_swp_entry(pte); | 2203 | swp = pte_to_swp_entry(pte); |
2197 | if (non_swap_entry(swp) && is_hwpoison_entry(swp)) { | 2204 | if (non_swap_entry(swp) && is_hwpoison_entry(swp)) |
2198 | return 1; | 2205 | return 1; |
2199 | } else | 2206 | else |
2200 | return 0; | 2207 | return 0; |
2201 | } | 2208 | } |
2202 | 2209 | ||
@@ -2559,7 +2566,7 @@ retry: | |||
2559 | * So we need to block hugepage fault by PG_hwpoison bit check. | 2566 | * So we need to block hugepage fault by PG_hwpoison bit check. |
2560 | */ | 2567 | */ |
2561 | if (unlikely(PageHWPoison(page))) { | 2568 | if (unlikely(PageHWPoison(page))) { |
2562 | ret = VM_FAULT_HWPOISON | | 2569 | ret = VM_FAULT_HWPOISON | |
2563 | VM_FAULT_SET_HINDEX(h - hstates); | 2570 | VM_FAULT_SET_HINDEX(h - hstates); |
2564 | goto backout_unlocked; | 2571 | goto backout_unlocked; |
2565 | } | 2572 | } |
@@ -2627,7 +2634,7 @@ int hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma, | |||
2627 | migration_entry_wait(mm, (pmd_t *)ptep, address); | 2634 | migration_entry_wait(mm, (pmd_t *)ptep, address); |
2628 | return 0; | 2635 | return 0; |
2629 | } else if (unlikely(is_hugetlb_entry_hwpoisoned(entry))) | 2636 | } else if (unlikely(is_hugetlb_entry_hwpoisoned(entry))) |
2630 | return VM_FAULT_HWPOISON_LARGE | | 2637 | return VM_FAULT_HWPOISON_LARGE | |
2631 | VM_FAULT_SET_HINDEX(h - hstates); | 2638 | VM_FAULT_SET_HINDEX(h - hstates); |
2632 | } | 2639 | } |
2633 | 2640 | ||
diff --git a/mm/memblock.c b/mm/memblock.c index a0562d1a6ad4..ccbf97339592 100644 --- a/mm/memblock.c +++ b/mm/memblock.c | |||
@@ -758,9 +758,9 @@ void __init memblock_analyze(void) | |||
758 | 758 | ||
759 | /* Check marker in the unused last array entry */ | 759 | /* Check marker in the unused last array entry */ |
760 | WARN_ON(memblock_memory_init_regions[INIT_MEMBLOCK_REGIONS].base | 760 | WARN_ON(memblock_memory_init_regions[INIT_MEMBLOCK_REGIONS].base |
761 | != (phys_addr_t)RED_INACTIVE); | 761 | != MEMBLOCK_INACTIVE); |
762 | WARN_ON(memblock_reserved_init_regions[INIT_MEMBLOCK_REGIONS].base | 762 | WARN_ON(memblock_reserved_init_regions[INIT_MEMBLOCK_REGIONS].base |
763 | != (phys_addr_t)RED_INACTIVE); | 763 | != MEMBLOCK_INACTIVE); |
764 | 764 | ||
765 | memblock.memory_size = 0; | 765 | memblock.memory_size = 0; |
766 | 766 | ||
@@ -786,8 +786,8 @@ void __init memblock_init(void) | |||
786 | memblock.reserved.max = INIT_MEMBLOCK_REGIONS; | 786 | memblock.reserved.max = INIT_MEMBLOCK_REGIONS; |
787 | 787 | ||
788 | /* Write a marker in the unused last array entry */ | 788 | /* Write a marker in the unused last array entry */ |
789 | memblock.memory.regions[INIT_MEMBLOCK_REGIONS].base = (phys_addr_t)RED_INACTIVE; | 789 | memblock.memory.regions[INIT_MEMBLOCK_REGIONS].base = MEMBLOCK_INACTIVE; |
790 | memblock.reserved.regions[INIT_MEMBLOCK_REGIONS].base = (phys_addr_t)RED_INACTIVE; | 790 | memblock.reserved.regions[INIT_MEMBLOCK_REGIONS].base = MEMBLOCK_INACTIVE; |
791 | 791 | ||
792 | /* Create a dummy zero size MEMBLOCK which will get coalesced away later. | 792 | /* Create a dummy zero size MEMBLOCK which will get coalesced away later. |
793 | * This simplifies the memblock_add() code below... | 793 | * This simplifies the memblock_add() code below... |
diff --git a/mm/memory.c b/mm/memory.c index 9b8a01d941cb..a56e3ba816b2 100644 --- a/mm/memory.c +++ b/mm/memory.c | |||
@@ -1290,13 +1290,6 @@ static unsigned long unmap_page_range(struct mmu_gather *tlb, | |||
1290 | return addr; | 1290 | return addr; |
1291 | } | 1291 | } |
1292 | 1292 | ||
1293 | #ifdef CONFIG_PREEMPT | ||
1294 | # define ZAP_BLOCK_SIZE (8 * PAGE_SIZE) | ||
1295 | #else | ||
1296 | /* No preempt: go for improved straight-line efficiency */ | ||
1297 | # define ZAP_BLOCK_SIZE (1024 * PAGE_SIZE) | ||
1298 | #endif | ||
1299 | |||
1300 | /** | 1293 | /** |
1301 | * unmap_vmas - unmap a range of memory covered by a list of vma's | 1294 | * unmap_vmas - unmap a range of memory covered by a list of vma's |
1302 | * @tlb: address of the caller's struct mmu_gather | 1295 | * @tlb: address of the caller's struct mmu_gather |
@@ -1310,10 +1303,6 @@ static unsigned long unmap_page_range(struct mmu_gather *tlb, | |||
1310 | * | 1303 | * |
1311 | * Unmap all pages in the vma list. | 1304 | * Unmap all pages in the vma list. |
1312 | * | 1305 | * |
1313 | * We aim to not hold locks for too long (for scheduling latency reasons). | ||
1314 | * So zap pages in ZAP_BLOCK_SIZE bytecounts. This means we need to | ||
1315 | * return the ending mmu_gather to the caller. | ||
1316 | * | ||
1317 | * Only addresses between `start' and `end' will be unmapped. | 1306 | * Only addresses between `start' and `end' will be unmapped. |
1318 | * | 1307 | * |
1319 | * The VMA list must be sorted in ascending virtual address order. | 1308 | * The VMA list must be sorted in ascending virtual address order. |
@@ -1816,7 +1805,63 @@ next_page: | |||
1816 | } | 1805 | } |
1817 | EXPORT_SYMBOL(__get_user_pages); | 1806 | EXPORT_SYMBOL(__get_user_pages); |
1818 | 1807 | ||
1819 | /** | 1808 | /* |
1809 | * fixup_user_fault() - manually resolve a user page fault | ||
1810 | * @tsk: the task_struct to use for page fault accounting, or | ||
1811 | * NULL if faults are not to be recorded. | ||
1812 | * @mm: mm_struct of target mm | ||
1813 | * @address: user address | ||
1814 | * @fault_flags:flags to pass down to handle_mm_fault() | ||
1815 | * | ||
1816 | * This is meant to be called in the specific scenario where for locking reasons | ||
1817 | * we try to access user memory in atomic context (within a pagefault_disable() | ||
1818 | * section), this returns -EFAULT, and we want to resolve the user fault before | ||
1819 | * trying again. | ||
1820 | * | ||
1821 | * Typically this is meant to be used by the futex code. | ||
1822 | * | ||
1823 | * The main difference with get_user_pages() is that this function will | ||
1824 | * unconditionally call handle_mm_fault() which will in turn perform all the | ||
1825 | * necessary SW fixup of the dirty and young bits in the PTE, while | ||
1826 | * handle_mm_fault() only guarantees to update these in the struct page. | ||
1827 | * | ||
1828 | * This is important for some architectures where those bits also gate the | ||
1829 | * access permission to the page because they are maintained in software. On | ||
1830 | * such architectures, gup() will not be enough to make a subsequent access | ||
1831 | * succeed. | ||
1832 | * | ||
1833 | * This should be called with the mm_sem held for read. | ||
1834 | */ | ||
1835 | int fixup_user_fault(struct task_struct *tsk, struct mm_struct *mm, | ||
1836 | unsigned long address, unsigned int fault_flags) | ||
1837 | { | ||
1838 | struct vm_area_struct *vma; | ||
1839 | int ret; | ||
1840 | |||
1841 | vma = find_extend_vma(mm, address); | ||
1842 | if (!vma || address < vma->vm_start) | ||
1843 | return -EFAULT; | ||
1844 | |||
1845 | ret = handle_mm_fault(mm, vma, address, fault_flags); | ||
1846 | if (ret & VM_FAULT_ERROR) { | ||
1847 | if (ret & VM_FAULT_OOM) | ||
1848 | return -ENOMEM; | ||
1849 | if (ret & (VM_FAULT_HWPOISON | VM_FAULT_HWPOISON_LARGE)) | ||
1850 | return -EHWPOISON; | ||
1851 | if (ret & VM_FAULT_SIGBUS) | ||
1852 | return -EFAULT; | ||
1853 | BUG(); | ||
1854 | } | ||
1855 | if (tsk) { | ||
1856 | if (ret & VM_FAULT_MAJOR) | ||
1857 | tsk->maj_flt++; | ||
1858 | else | ||
1859 | tsk->min_flt++; | ||
1860 | } | ||
1861 | return 0; | ||
1862 | } | ||
1863 | |||
1864 | /* | ||
1820 | * get_user_pages() - pin user pages in memory | 1865 | * get_user_pages() - pin user pages in memory |
1821 | * @tsk: the task_struct to use for page fault accounting, or | 1866 | * @tsk: the task_struct to use for page fault accounting, or |
1822 | * NULL if faults are not to be recorded. | 1867 | * NULL if faults are not to be recorded. |
@@ -3104,14 +3149,34 @@ static int __do_fault(struct mm_struct *mm, struct vm_area_struct *vma, | |||
3104 | pte_t *page_table; | 3149 | pte_t *page_table; |
3105 | spinlock_t *ptl; | 3150 | spinlock_t *ptl; |
3106 | struct page *page; | 3151 | struct page *page; |
3152 | struct page *cow_page; | ||
3107 | pte_t entry; | 3153 | pte_t entry; |
3108 | int anon = 0; | 3154 | int anon = 0; |
3109 | int charged = 0; | ||
3110 | struct page *dirty_page = NULL; | 3155 | struct page *dirty_page = NULL; |
3111 | struct vm_fault vmf; | 3156 | struct vm_fault vmf; |
3112 | int ret; | 3157 | int ret; |
3113 | int page_mkwrite = 0; | 3158 | int page_mkwrite = 0; |
3114 | 3159 | ||
3160 | /* | ||
3161 | * If we do COW later, allocate page befor taking lock_page() | ||
3162 | * on the file cache page. This will reduce lock holding time. | ||
3163 | */ | ||
3164 | if ((flags & FAULT_FLAG_WRITE) && !(vma->vm_flags & VM_SHARED)) { | ||
3165 | |||
3166 | if (unlikely(anon_vma_prepare(vma))) | ||
3167 | return VM_FAULT_OOM; | ||
3168 | |||
3169 | cow_page = alloc_page_vma(GFP_HIGHUSER_MOVABLE, vma, address); | ||
3170 | if (!cow_page) | ||
3171 | return VM_FAULT_OOM; | ||
3172 | |||
3173 | if (mem_cgroup_newpage_charge(cow_page, mm, GFP_KERNEL)) { | ||
3174 | page_cache_release(cow_page); | ||
3175 | return VM_FAULT_OOM; | ||
3176 | } | ||
3177 | } else | ||
3178 | cow_page = NULL; | ||
3179 | |||
3115 | vmf.virtual_address = (void __user *)(address & PAGE_MASK); | 3180 | vmf.virtual_address = (void __user *)(address & PAGE_MASK); |
3116 | vmf.pgoff = pgoff; | 3181 | vmf.pgoff = pgoff; |
3117 | vmf.flags = flags; | 3182 | vmf.flags = flags; |
@@ -3120,12 +3185,13 @@ static int __do_fault(struct mm_struct *mm, struct vm_area_struct *vma, | |||
3120 | ret = vma->vm_ops->fault(vma, &vmf); | 3185 | ret = vma->vm_ops->fault(vma, &vmf); |
3121 | if (unlikely(ret & (VM_FAULT_ERROR | VM_FAULT_NOPAGE | | 3186 | if (unlikely(ret & (VM_FAULT_ERROR | VM_FAULT_NOPAGE | |
3122 | VM_FAULT_RETRY))) | 3187 | VM_FAULT_RETRY))) |
3123 | return ret; | 3188 | goto uncharge_out; |
3124 | 3189 | ||
3125 | if (unlikely(PageHWPoison(vmf.page))) { | 3190 | if (unlikely(PageHWPoison(vmf.page))) { |
3126 | if (ret & VM_FAULT_LOCKED) | 3191 | if (ret & VM_FAULT_LOCKED) |
3127 | unlock_page(vmf.page); | 3192 | unlock_page(vmf.page); |
3128 | return VM_FAULT_HWPOISON; | 3193 | ret = VM_FAULT_HWPOISON; |
3194 | goto uncharge_out; | ||
3129 | } | 3195 | } |
3130 | 3196 | ||
3131 | /* | 3197 | /* |
@@ -3143,23 +3209,8 @@ static int __do_fault(struct mm_struct *mm, struct vm_area_struct *vma, | |||
3143 | page = vmf.page; | 3209 | page = vmf.page; |
3144 | if (flags & FAULT_FLAG_WRITE) { | 3210 | if (flags & FAULT_FLAG_WRITE) { |
3145 | if (!(vma->vm_flags & VM_SHARED)) { | 3211 | if (!(vma->vm_flags & VM_SHARED)) { |
3212 | page = cow_page; | ||
3146 | anon = 1; | 3213 | anon = 1; |
3147 | if (unlikely(anon_vma_prepare(vma))) { | ||
3148 | ret = VM_FAULT_OOM; | ||
3149 | goto out; | ||
3150 | } | ||
3151 | page = alloc_page_vma(GFP_HIGHUSER_MOVABLE, | ||
3152 | vma, address); | ||
3153 | if (!page) { | ||
3154 | ret = VM_FAULT_OOM; | ||
3155 | goto out; | ||
3156 | } | ||
3157 | if (mem_cgroup_newpage_charge(page, mm, GFP_KERNEL)) { | ||
3158 | ret = VM_FAULT_OOM; | ||
3159 | page_cache_release(page); | ||
3160 | goto out; | ||
3161 | } | ||
3162 | charged = 1; | ||
3163 | copy_user_highpage(page, vmf.page, address, vma); | 3214 | copy_user_highpage(page, vmf.page, address, vma); |
3164 | __SetPageUptodate(page); | 3215 | __SetPageUptodate(page); |
3165 | } else { | 3216 | } else { |
@@ -3228,8 +3279,8 @@ static int __do_fault(struct mm_struct *mm, struct vm_area_struct *vma, | |||
3228 | /* no need to invalidate: a not-present page won't be cached */ | 3279 | /* no need to invalidate: a not-present page won't be cached */ |
3229 | update_mmu_cache(vma, address, page_table); | 3280 | update_mmu_cache(vma, address, page_table); |
3230 | } else { | 3281 | } else { |
3231 | if (charged) | 3282 | if (cow_page) |
3232 | mem_cgroup_uncharge_page(page); | 3283 | mem_cgroup_uncharge_page(cow_page); |
3233 | if (anon) | 3284 | if (anon) |
3234 | page_cache_release(page); | 3285 | page_cache_release(page); |
3235 | else | 3286 | else |
@@ -3238,7 +3289,6 @@ static int __do_fault(struct mm_struct *mm, struct vm_area_struct *vma, | |||
3238 | 3289 | ||
3239 | pte_unmap_unlock(page_table, ptl); | 3290 | pte_unmap_unlock(page_table, ptl); |
3240 | 3291 | ||
3241 | out: | ||
3242 | if (dirty_page) { | 3292 | if (dirty_page) { |
3243 | struct address_space *mapping = page->mapping; | 3293 | struct address_space *mapping = page->mapping; |
3244 | 3294 | ||
@@ -3268,6 +3318,13 @@ out: | |||
3268 | unwritable_page: | 3318 | unwritable_page: |
3269 | page_cache_release(page); | 3319 | page_cache_release(page); |
3270 | return ret; | 3320 | return ret; |
3321 | uncharge_out: | ||
3322 | /* fs's fault handler get error */ | ||
3323 | if (cow_page) { | ||
3324 | mem_cgroup_uncharge_page(cow_page); | ||
3325 | page_cache_release(cow_page); | ||
3326 | } | ||
3327 | return ret; | ||
3271 | } | 3328 | } |
3272 | 3329 | ||
3273 | static int do_linear_fault(struct mm_struct *mm, struct vm_area_struct *vma, | 3330 | static int do_linear_fault(struct mm_struct *mm, struct vm_area_struct *vma, |
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c index c46887b5a11e..6e7d8b21dbfa 100644 --- a/mm/memory_hotplug.c +++ b/mm/memory_hotplug.c | |||
@@ -34,6 +34,17 @@ | |||
34 | 34 | ||
35 | #include "internal.h" | 35 | #include "internal.h" |
36 | 36 | ||
37 | /* | ||
38 | * online_page_callback contains pointer to current page onlining function. | ||
39 | * Initially it is generic_online_page(). If it is required it could be | ||
40 | * changed by calling set_online_page_callback() for callback registration | ||
41 | * and restore_online_page_callback() for generic callback restore. | ||
42 | */ | ||
43 | |||
44 | static void generic_online_page(struct page *page); | ||
45 | |||
46 | static online_page_callback_t online_page_callback = generic_online_page; | ||
47 | |||
37 | DEFINE_MUTEX(mem_hotplug_mutex); | 48 | DEFINE_MUTEX(mem_hotplug_mutex); |
38 | 49 | ||
39 | void lock_memory_hotplug(void) | 50 | void lock_memory_hotplug(void) |
@@ -361,23 +372,74 @@ int __remove_pages(struct zone *zone, unsigned long phys_start_pfn, | |||
361 | } | 372 | } |
362 | EXPORT_SYMBOL_GPL(__remove_pages); | 373 | EXPORT_SYMBOL_GPL(__remove_pages); |
363 | 374 | ||
364 | void online_page(struct page *page) | 375 | int set_online_page_callback(online_page_callback_t callback) |
376 | { | ||
377 | int rc = -EINVAL; | ||
378 | |||
379 | lock_memory_hotplug(); | ||
380 | |||
381 | if (online_page_callback == generic_online_page) { | ||
382 | online_page_callback = callback; | ||
383 | rc = 0; | ||
384 | } | ||
385 | |||
386 | unlock_memory_hotplug(); | ||
387 | |||
388 | return rc; | ||
389 | } | ||
390 | EXPORT_SYMBOL_GPL(set_online_page_callback); | ||
391 | |||
392 | int restore_online_page_callback(online_page_callback_t callback) | ||
393 | { | ||
394 | int rc = -EINVAL; | ||
395 | |||
396 | lock_memory_hotplug(); | ||
397 | |||
398 | if (online_page_callback == callback) { | ||
399 | online_page_callback = generic_online_page; | ||
400 | rc = 0; | ||
401 | } | ||
402 | |||
403 | unlock_memory_hotplug(); | ||
404 | |||
405 | return rc; | ||
406 | } | ||
407 | EXPORT_SYMBOL_GPL(restore_online_page_callback); | ||
408 | |||
409 | void __online_page_set_limits(struct page *page) | ||
365 | { | 410 | { |
366 | unsigned long pfn = page_to_pfn(page); | 411 | unsigned long pfn = page_to_pfn(page); |
367 | 412 | ||
368 | totalram_pages++; | ||
369 | if (pfn >= num_physpages) | 413 | if (pfn >= num_physpages) |
370 | num_physpages = pfn + 1; | 414 | num_physpages = pfn + 1; |
415 | } | ||
416 | EXPORT_SYMBOL_GPL(__online_page_set_limits); | ||
417 | |||
418 | void __online_page_increment_counters(struct page *page) | ||
419 | { | ||
420 | totalram_pages++; | ||
371 | 421 | ||
372 | #ifdef CONFIG_HIGHMEM | 422 | #ifdef CONFIG_HIGHMEM |
373 | if (PageHighMem(page)) | 423 | if (PageHighMem(page)) |
374 | totalhigh_pages++; | 424 | totalhigh_pages++; |
375 | #endif | 425 | #endif |
426 | } | ||
427 | EXPORT_SYMBOL_GPL(__online_page_increment_counters); | ||
376 | 428 | ||
429 | void __online_page_free(struct page *page) | ||
430 | { | ||
377 | ClearPageReserved(page); | 431 | ClearPageReserved(page); |
378 | init_page_count(page); | 432 | init_page_count(page); |
379 | __free_page(page); | 433 | __free_page(page); |
380 | } | 434 | } |
435 | EXPORT_SYMBOL_GPL(__online_page_free); | ||
436 | |||
437 | static void generic_online_page(struct page *page) | ||
438 | { | ||
439 | __online_page_set_limits(page); | ||
440 | __online_page_increment_counters(page); | ||
441 | __online_page_free(page); | ||
442 | } | ||
381 | 443 | ||
382 | static int online_pages_range(unsigned long start_pfn, unsigned long nr_pages, | 444 | static int online_pages_range(unsigned long start_pfn, unsigned long nr_pages, |
383 | void *arg) | 445 | void *arg) |
@@ -388,7 +450,7 @@ static int online_pages_range(unsigned long start_pfn, unsigned long nr_pages, | |||
388 | if (PageReserved(pfn_to_page(start_pfn))) | 450 | if (PageReserved(pfn_to_page(start_pfn))) |
389 | for (i = 0; i < nr_pages; i++) { | 451 | for (i = 0; i < nr_pages; i++) { |
390 | page = pfn_to_page(start_pfn + i); | 452 | page = pfn_to_page(start_pfn + i); |
391 | online_page(page); | 453 | (*online_page_callback)(page); |
392 | onlined_pages++; | 454 | onlined_pages++; |
393 | } | 455 | } |
394 | *(unsigned long *)arg = onlined_pages; | 456 | *(unsigned long *)arg = onlined_pages; |
@@ -122,9 +122,17 @@ int __vm_enough_memory(struct mm_struct *mm, long pages, int cap_sys_admin) | |||
122 | return 0; | 122 | return 0; |
123 | 123 | ||
124 | if (sysctl_overcommit_memory == OVERCOMMIT_GUESS) { | 124 | if (sysctl_overcommit_memory == OVERCOMMIT_GUESS) { |
125 | unsigned long n; | 125 | free = global_page_state(NR_FREE_PAGES); |
126 | free += global_page_state(NR_FILE_PAGES); | ||
127 | |||
128 | /* | ||
129 | * shmem pages shouldn't be counted as free in this | ||
130 | * case, they can't be purged, only swapped out, and | ||
131 | * that won't affect the overall amount of available | ||
132 | * memory in the system. | ||
133 | */ | ||
134 | free -= global_page_state(NR_SHMEM); | ||
126 | 135 | ||
127 | free = global_page_state(NR_FILE_PAGES); | ||
128 | free += nr_swap_pages; | 136 | free += nr_swap_pages; |
129 | 137 | ||
130 | /* | 138 | /* |
@@ -136,34 +144,18 @@ int __vm_enough_memory(struct mm_struct *mm, long pages, int cap_sys_admin) | |||
136 | free += global_page_state(NR_SLAB_RECLAIMABLE); | 144 | free += global_page_state(NR_SLAB_RECLAIMABLE); |
137 | 145 | ||
138 | /* | 146 | /* |
139 | * Leave the last 3% for root | ||
140 | */ | ||
141 | if (!cap_sys_admin) | ||
142 | free -= free / 32; | ||
143 | |||
144 | if (free > pages) | ||
145 | return 0; | ||
146 | |||
147 | /* | ||
148 | * nr_free_pages() is very expensive on large systems, | ||
149 | * only call if we're about to fail. | ||
150 | */ | ||
151 | n = nr_free_pages(); | ||
152 | |||
153 | /* | ||
154 | * Leave reserved pages. The pages are not for anonymous pages. | 147 | * Leave reserved pages. The pages are not for anonymous pages. |
155 | */ | 148 | */ |
156 | if (n <= totalreserve_pages) | 149 | if (free <= totalreserve_pages) |
157 | goto error; | 150 | goto error; |
158 | else | 151 | else |
159 | n -= totalreserve_pages; | 152 | free -= totalreserve_pages; |
160 | 153 | ||
161 | /* | 154 | /* |
162 | * Leave the last 3% for root | 155 | * Leave the last 3% for root |
163 | */ | 156 | */ |
164 | if (!cap_sys_admin) | 157 | if (!cap_sys_admin) |
165 | n -= n / 32; | 158 | free -= free / 32; |
166 | free += n; | ||
167 | 159 | ||
168 | if (free > pages) | 160 | if (free > pages) |
169 | return 0; | 161 | return 0; |
diff --git a/mm/nommu.c b/mm/nommu.c index 5c5c2d4b1807..4358032566e9 100644 --- a/mm/nommu.c +++ b/mm/nommu.c | |||
@@ -1884,9 +1884,17 @@ int __vm_enough_memory(struct mm_struct *mm, long pages, int cap_sys_admin) | |||
1884 | return 0; | 1884 | return 0; |
1885 | 1885 | ||
1886 | if (sysctl_overcommit_memory == OVERCOMMIT_GUESS) { | 1886 | if (sysctl_overcommit_memory == OVERCOMMIT_GUESS) { |
1887 | unsigned long n; | 1887 | free = global_page_state(NR_FREE_PAGES); |
1888 | free += global_page_state(NR_FILE_PAGES); | ||
1889 | |||
1890 | /* | ||
1891 | * shmem pages shouldn't be counted as free in this | ||
1892 | * case, they can't be purged, only swapped out, and | ||
1893 | * that won't affect the overall amount of available | ||
1894 | * memory in the system. | ||
1895 | */ | ||
1896 | free -= global_page_state(NR_SHMEM); | ||
1888 | 1897 | ||
1889 | free = global_page_state(NR_FILE_PAGES); | ||
1890 | free += nr_swap_pages; | 1898 | free += nr_swap_pages; |
1891 | 1899 | ||
1892 | /* | 1900 | /* |
@@ -1898,34 +1906,18 @@ int __vm_enough_memory(struct mm_struct *mm, long pages, int cap_sys_admin) | |||
1898 | free += global_page_state(NR_SLAB_RECLAIMABLE); | 1906 | free += global_page_state(NR_SLAB_RECLAIMABLE); |
1899 | 1907 | ||
1900 | /* | 1908 | /* |
1901 | * Leave the last 3% for root | ||
1902 | */ | ||
1903 | if (!cap_sys_admin) | ||
1904 | free -= free / 32; | ||
1905 | |||
1906 | if (free > pages) | ||
1907 | return 0; | ||
1908 | |||
1909 | /* | ||
1910 | * nr_free_pages() is very expensive on large systems, | ||
1911 | * only call if we're about to fail. | ||
1912 | */ | ||
1913 | n = nr_free_pages(); | ||
1914 | |||
1915 | /* | ||
1916 | * Leave reserved pages. The pages are not for anonymous pages. | 1909 | * Leave reserved pages. The pages are not for anonymous pages. |
1917 | */ | 1910 | */ |
1918 | if (n <= totalreserve_pages) | 1911 | if (free <= totalreserve_pages) |
1919 | goto error; | 1912 | goto error; |
1920 | else | 1913 | else |
1921 | n -= totalreserve_pages; | 1914 | free -= totalreserve_pages; |
1922 | 1915 | ||
1923 | /* | 1916 | /* |
1924 | * Leave the last 3% for root | 1917 | * Leave the last 3% for root |
1925 | */ | 1918 | */ |
1926 | if (!cap_sys_admin) | 1919 | if (!cap_sys_admin) |
1927 | n -= n / 32; | 1920 | free -= free / 32; |
1928 | free += n; | ||
1929 | 1921 | ||
1930 | if (free > pages) | 1922 | if (free > pages) |
1931 | return 0; | 1923 | return 0; |
diff --git a/mm/oom_kill.c b/mm/oom_kill.c index b0be989d4365..eafff89b3dd6 100644 --- a/mm/oom_kill.c +++ b/mm/oom_kill.c | |||
@@ -487,7 +487,7 @@ static int oom_kill_process(struct task_struct *p, gfp_t gfp_mask, int order, | |||
487 | 487 | ||
488 | /* | 488 | /* |
489 | * If any of p's children has a different mm and is eligible for kill, | 489 | * If any of p's children has a different mm and is eligible for kill, |
490 | * the one with the highest badness() score is sacrificed for its | 490 | * the one with the highest oom_badness() score is sacrificed for its |
491 | * parent. This attempts to lose the minimal amount of work done while | 491 | * parent. This attempts to lose the minimal amount of work done while |
492 | * still freeing memory. | 492 | * still freeing memory. |
493 | */ | 493 | */ |
diff --git a/mm/page-writeback.c b/mm/page-writeback.c index 31f698862420..d8767b381b9c 100644 --- a/mm/page-writeback.c +++ b/mm/page-writeback.c | |||
@@ -1141,7 +1141,6 @@ EXPORT_SYMBOL(account_page_dirtied); | |||
1141 | void account_page_writeback(struct page *page) | 1141 | void account_page_writeback(struct page *page) |
1142 | { | 1142 | { |
1143 | inc_zone_page_state(page, NR_WRITEBACK); | 1143 | inc_zone_page_state(page, NR_WRITEBACK); |
1144 | inc_zone_page_state(page, NR_WRITTEN); | ||
1145 | } | 1144 | } |
1146 | EXPORT_SYMBOL(account_page_writeback); | 1145 | EXPORT_SYMBOL(account_page_writeback); |
1147 | 1146 | ||
@@ -1358,8 +1357,10 @@ int test_clear_page_writeback(struct page *page) | |||
1358 | } else { | 1357 | } else { |
1359 | ret = TestClearPageWriteback(page); | 1358 | ret = TestClearPageWriteback(page); |
1360 | } | 1359 | } |
1361 | if (ret) | 1360 | if (ret) { |
1362 | dec_zone_page_state(page, NR_WRITEBACK); | 1361 | dec_zone_page_state(page, NR_WRITEBACK); |
1362 | inc_zone_page_state(page, NR_WRITTEN); | ||
1363 | } | ||
1363 | return ret; | 1364 | return ret; |
1364 | } | 1365 | } |
1365 | 1366 | ||
@@ -1405,10 +1406,6 @@ EXPORT_SYMBOL(test_set_page_writeback); | |||
1405 | */ | 1406 | */ |
1406 | int mapping_tagged(struct address_space *mapping, int tag) | 1407 | int mapping_tagged(struct address_space *mapping, int tag) |
1407 | { | 1408 | { |
1408 | int ret; | 1409 | return radix_tree_tagged(&mapping->page_tree, tag); |
1409 | rcu_read_lock(); | ||
1410 | ret = radix_tree_tagged(&mapping->page_tree, tag); | ||
1411 | rcu_read_unlock(); | ||
1412 | return ret; | ||
1413 | } | 1410 | } |
1414 | EXPORT_SYMBOL(mapping_tagged); | 1411 | EXPORT_SYMBOL(mapping_tagged); |
diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 9119faae6e6a..094472377d81 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c | |||
@@ -1616,6 +1616,21 @@ static void zlc_mark_zone_full(struct zonelist *zonelist, struct zoneref *z) | |||
1616 | set_bit(i, zlc->fullzones); | 1616 | set_bit(i, zlc->fullzones); |
1617 | } | 1617 | } |
1618 | 1618 | ||
1619 | /* | ||
1620 | * clear all zones full, called after direct reclaim makes progress so that | ||
1621 | * a zone that was recently full is not skipped over for up to a second | ||
1622 | */ | ||
1623 | static void zlc_clear_zones_full(struct zonelist *zonelist) | ||
1624 | { | ||
1625 | struct zonelist_cache *zlc; /* cached zonelist speedup info */ | ||
1626 | |||
1627 | zlc = zonelist->zlcache_ptr; | ||
1628 | if (!zlc) | ||
1629 | return; | ||
1630 | |||
1631 | bitmap_zero(zlc->fullzones, MAX_ZONES_PER_ZONELIST); | ||
1632 | } | ||
1633 | |||
1619 | #else /* CONFIG_NUMA */ | 1634 | #else /* CONFIG_NUMA */ |
1620 | 1635 | ||
1621 | static nodemask_t *zlc_setup(struct zonelist *zonelist, int alloc_flags) | 1636 | static nodemask_t *zlc_setup(struct zonelist *zonelist, int alloc_flags) |
@@ -1632,6 +1647,10 @@ static int zlc_zone_worth_trying(struct zonelist *zonelist, struct zoneref *z, | |||
1632 | static void zlc_mark_zone_full(struct zonelist *zonelist, struct zoneref *z) | 1647 | static void zlc_mark_zone_full(struct zonelist *zonelist, struct zoneref *z) |
1633 | { | 1648 | { |
1634 | } | 1649 | } |
1650 | |||
1651 | static void zlc_clear_zones_full(struct zonelist *zonelist) | ||
1652 | { | ||
1653 | } | ||
1635 | #endif /* CONFIG_NUMA */ | 1654 | #endif /* CONFIG_NUMA */ |
1636 | 1655 | ||
1637 | /* | 1656 | /* |
@@ -1664,7 +1683,7 @@ zonelist_scan: | |||
1664 | continue; | 1683 | continue; |
1665 | if ((alloc_flags & ALLOC_CPUSET) && | 1684 | if ((alloc_flags & ALLOC_CPUSET) && |
1666 | !cpuset_zone_allowed_softwall(zone, gfp_mask)) | 1685 | !cpuset_zone_allowed_softwall(zone, gfp_mask)) |
1667 | goto try_next_zone; | 1686 | continue; |
1668 | 1687 | ||
1669 | BUILD_BUG_ON(ALLOC_NO_WATERMARKS < NR_WMARK); | 1688 | BUILD_BUG_ON(ALLOC_NO_WATERMARKS < NR_WMARK); |
1670 | if (!(alloc_flags & ALLOC_NO_WATERMARKS)) { | 1689 | if (!(alloc_flags & ALLOC_NO_WATERMARKS)) { |
@@ -1676,17 +1695,36 @@ zonelist_scan: | |||
1676 | classzone_idx, alloc_flags)) | 1695 | classzone_idx, alloc_flags)) |
1677 | goto try_this_zone; | 1696 | goto try_this_zone; |
1678 | 1697 | ||
1698 | if (NUMA_BUILD && !did_zlc_setup && nr_online_nodes > 1) { | ||
1699 | /* | ||
1700 | * we do zlc_setup if there are multiple nodes | ||
1701 | * and before considering the first zone allowed | ||
1702 | * by the cpuset. | ||
1703 | */ | ||
1704 | allowednodes = zlc_setup(zonelist, alloc_flags); | ||
1705 | zlc_active = 1; | ||
1706 | did_zlc_setup = 1; | ||
1707 | } | ||
1708 | |||
1679 | if (zone_reclaim_mode == 0) | 1709 | if (zone_reclaim_mode == 0) |
1680 | goto this_zone_full; | 1710 | goto this_zone_full; |
1681 | 1711 | ||
1712 | /* | ||
1713 | * As we may have just activated ZLC, check if the first | ||
1714 | * eligible zone has failed zone_reclaim recently. | ||
1715 | */ | ||
1716 | if (NUMA_BUILD && zlc_active && | ||
1717 | !zlc_zone_worth_trying(zonelist, z, allowednodes)) | ||
1718 | continue; | ||
1719 | |||
1682 | ret = zone_reclaim(zone, gfp_mask, order); | 1720 | ret = zone_reclaim(zone, gfp_mask, order); |
1683 | switch (ret) { | 1721 | switch (ret) { |
1684 | case ZONE_RECLAIM_NOSCAN: | 1722 | case ZONE_RECLAIM_NOSCAN: |
1685 | /* did not scan */ | 1723 | /* did not scan */ |
1686 | goto try_next_zone; | 1724 | continue; |
1687 | case ZONE_RECLAIM_FULL: | 1725 | case ZONE_RECLAIM_FULL: |
1688 | /* scanned but unreclaimable */ | 1726 | /* scanned but unreclaimable */ |
1689 | goto this_zone_full; | 1727 | continue; |
1690 | default: | 1728 | default: |
1691 | /* did we reclaim enough */ | 1729 | /* did we reclaim enough */ |
1692 | if (!zone_watermark_ok(zone, order, mark, | 1730 | if (!zone_watermark_ok(zone, order, mark, |
@@ -1703,16 +1741,6 @@ try_this_zone: | |||
1703 | this_zone_full: | 1741 | this_zone_full: |
1704 | if (NUMA_BUILD) | 1742 | if (NUMA_BUILD) |
1705 | zlc_mark_zone_full(zonelist, z); | 1743 | zlc_mark_zone_full(zonelist, z); |
1706 | try_next_zone: | ||
1707 | if (NUMA_BUILD && !did_zlc_setup && nr_online_nodes > 1) { | ||
1708 | /* | ||
1709 | * we do zlc_setup after the first zone is tried but only | ||
1710 | * if there are multiple nodes make it worthwhile | ||
1711 | */ | ||
1712 | allowednodes = zlc_setup(zonelist, alloc_flags); | ||
1713 | zlc_active = 1; | ||
1714 | did_zlc_setup = 1; | ||
1715 | } | ||
1716 | } | 1744 | } |
1717 | 1745 | ||
1718 | if (unlikely(NUMA_BUILD && page == NULL && zlc_active)) { | 1746 | if (unlikely(NUMA_BUILD && page == NULL && zlc_active)) { |
@@ -1954,6 +1982,10 @@ __alloc_pages_direct_reclaim(gfp_t gfp_mask, unsigned int order, | |||
1954 | if (unlikely(!(*did_some_progress))) | 1982 | if (unlikely(!(*did_some_progress))) |
1955 | return NULL; | 1983 | return NULL; |
1956 | 1984 | ||
1985 | /* After successful reclaim, reconsider all zones for allocation */ | ||
1986 | if (NUMA_BUILD) | ||
1987 | zlc_clear_zones_full(zonelist); | ||
1988 | |||
1957 | retry: | 1989 | retry: |
1958 | page = get_page_from_freelist(gfp_mask, nodemask, order, | 1990 | page = get_page_from_freelist(gfp_mask, nodemask, order, |
1959 | zonelist, high_zoneidx, | 1991 | zonelist, high_zoneidx, |
diff --git a/mm/page_cgroup.c b/mm/page_cgroup.c index 53bffc6c293e..39d216d535ea 100644 --- a/mm/page_cgroup.c +++ b/mm/page_cgroup.c | |||
@@ -225,8 +225,8 @@ int __meminit online_page_cgroup(unsigned long start_pfn, | |||
225 | unsigned long start, end, pfn; | 225 | unsigned long start, end, pfn; |
226 | int fail = 0; | 226 | int fail = 0; |
227 | 227 | ||
228 | start = start_pfn & ~(PAGES_PER_SECTION - 1); | 228 | start = SECTION_ALIGN_DOWN(start_pfn); |
229 | end = ALIGN(start_pfn + nr_pages, PAGES_PER_SECTION); | 229 | end = SECTION_ALIGN_UP(start_pfn + nr_pages); |
230 | 230 | ||
231 | if (nid == -1) { | 231 | if (nid == -1) { |
232 | /* | 232 | /* |
@@ -258,8 +258,8 @@ int __meminit offline_page_cgroup(unsigned long start_pfn, | |||
258 | { | 258 | { |
259 | unsigned long start, end, pfn; | 259 | unsigned long start, end, pfn; |
260 | 260 | ||
261 | start = start_pfn & ~(PAGES_PER_SECTION - 1); | 261 | start = SECTION_ALIGN_DOWN(start_pfn); |
262 | end = ALIGN(start_pfn + nr_pages, PAGES_PER_SECTION); | 262 | end = SECTION_ALIGN_UP(start_pfn + nr_pages); |
263 | 263 | ||
264 | for (pfn = start; pfn < end; pfn += PAGES_PER_SECTION) | 264 | for (pfn = start; pfn < end; pfn += PAGES_PER_SECTION) |
265 | __free_page_cgroup(pfn); | 265 | __free_page_cgroup(pfn); |
@@ -537,7 +537,7 @@ int swap_cgroup_swapon(int type, unsigned long max_pages) | |||
537 | nomem: | 537 | nomem: |
538 | printk(KERN_INFO "couldn't allocate enough memory for swap_cgroup.\n"); | 538 | printk(KERN_INFO "couldn't allocate enough memory for swap_cgroup.\n"); |
539 | printk(KERN_INFO | 539 | printk(KERN_INFO |
540 | "swap_cgroup can be disabled by noswapaccount boot option\n"); | 540 | "swap_cgroup can be disabled by swapaccount=0 boot option\n"); |
541 | return -ENOMEM; | 541 | return -ENOMEM; |
542 | } | 542 | } |
543 | 543 | ||
diff --git a/mm/pagewalk.c b/mm/pagewalk.c index c3450d533611..2f5cf10ff660 100644 --- a/mm/pagewalk.c +++ b/mm/pagewalk.c | |||
@@ -126,7 +126,39 @@ static int walk_hugetlb_range(struct vm_area_struct *vma, | |||
126 | 126 | ||
127 | return 0; | 127 | return 0; |
128 | } | 128 | } |
129 | #endif | 129 | |
130 | static struct vm_area_struct* hugetlb_vma(unsigned long addr, struct mm_walk *walk) | ||
131 | { | ||
132 | struct vm_area_struct *vma; | ||
133 | |||
134 | /* We don't need vma lookup at all. */ | ||
135 | if (!walk->hugetlb_entry) | ||
136 | return NULL; | ||
137 | |||
138 | VM_BUG_ON(!rwsem_is_locked(&walk->mm->mmap_sem)); | ||
139 | vma = find_vma(walk->mm, addr); | ||
140 | if (vma && vma->vm_start <= addr && is_vm_hugetlb_page(vma)) | ||
141 | return vma; | ||
142 | |||
143 | return NULL; | ||
144 | } | ||
145 | |||
146 | #else /* CONFIG_HUGETLB_PAGE */ | ||
147 | static struct vm_area_struct* hugetlb_vma(unsigned long addr, struct mm_walk *walk) | ||
148 | { | ||
149 | return NULL; | ||
150 | } | ||
151 | |||
152 | static int walk_hugetlb_range(struct vm_area_struct *vma, | ||
153 | unsigned long addr, unsigned long end, | ||
154 | struct mm_walk *walk) | ||
155 | { | ||
156 | return 0; | ||
157 | } | ||
158 | |||
159 | #endif /* CONFIG_HUGETLB_PAGE */ | ||
160 | |||
161 | |||
130 | 162 | ||
131 | /** | 163 | /** |
132 | * walk_page_range - walk a memory map's page tables with a callback | 164 | * walk_page_range - walk a memory map's page tables with a callback |
@@ -144,11 +176,15 @@ static int walk_hugetlb_range(struct vm_area_struct *vma, | |||
144 | * associated range, and a copy of the original mm_walk for access to | 176 | * associated range, and a copy of the original mm_walk for access to |
145 | * the ->private or ->mm fields. | 177 | * the ->private or ->mm fields. |
146 | * | 178 | * |
147 | * No locks are taken, but the bottom level iterator will map PTE | 179 | * Usually no locks are taken, but splitting transparent huge page may |
180 | * take page table lock. And the bottom level iterator will map PTE | ||
148 | * directories from highmem if necessary. | 181 | * directories from highmem if necessary. |
149 | * | 182 | * |
150 | * If any callback returns a non-zero value, the walk is aborted and | 183 | * If any callback returns a non-zero value, the walk is aborted and |
151 | * the return value is propagated back to the caller. Otherwise 0 is returned. | 184 | * the return value is propagated back to the caller. Otherwise 0 is returned. |
185 | * | ||
186 | * walk->mm->mmap_sem must be held for at least read if walk->hugetlb_entry | ||
187 | * is !NULL. | ||
152 | */ | 188 | */ |
153 | int walk_page_range(unsigned long addr, unsigned long end, | 189 | int walk_page_range(unsigned long addr, unsigned long end, |
154 | struct mm_walk *walk) | 190 | struct mm_walk *walk) |
@@ -165,18 +201,17 @@ int walk_page_range(unsigned long addr, unsigned long end, | |||
165 | 201 | ||
166 | pgd = pgd_offset(walk->mm, addr); | 202 | pgd = pgd_offset(walk->mm, addr); |
167 | do { | 203 | do { |
168 | struct vm_area_struct *uninitialized_var(vma); | 204 | struct vm_area_struct *vma; |
169 | 205 | ||
170 | next = pgd_addr_end(addr, end); | 206 | next = pgd_addr_end(addr, end); |
171 | 207 | ||
172 | #ifdef CONFIG_HUGETLB_PAGE | ||
173 | /* | 208 | /* |
174 | * handle hugetlb vma individually because pagetable walk for | 209 | * handle hugetlb vma individually because pagetable walk for |
175 | * the hugetlb page is dependent on the architecture and | 210 | * the hugetlb page is dependent on the architecture and |
176 | * we can't handled it in the same manner as non-huge pages. | 211 | * we can't handled it in the same manner as non-huge pages. |
177 | */ | 212 | */ |
178 | vma = find_vma(walk->mm, addr); | 213 | vma = hugetlb_vma(addr, walk); |
179 | if (vma && is_vm_hugetlb_page(vma)) { | 214 | if (vma) { |
180 | if (vma->vm_end < next) | 215 | if (vma->vm_end < next) |
181 | next = vma->vm_end; | 216 | next = vma->vm_end; |
182 | /* | 217 | /* |
@@ -189,7 +224,7 @@ int walk_page_range(unsigned long addr, unsigned long end, | |||
189 | pgd = pgd_offset(walk->mm, next); | 224 | pgd = pgd_offset(walk->mm, next); |
190 | continue; | 225 | continue; |
191 | } | 226 | } |
192 | #endif | 227 | |
193 | if (pgd_none_or_clear_bad(pgd)) { | 228 | if (pgd_none_or_clear_bad(pgd)) { |
194 | if (walk->pte_hole) | 229 | if (walk->pte_hole) |
195 | err = walk->pte_hole(addr, next, walk); | 230 | err = walk->pte_hole(addr, next, walk); |
diff --git a/mm/shmem.c b/mm/shmem.c index 3e519798b522..5cc21f8b4cd3 100644 --- a/mm/shmem.c +++ b/mm/shmem.c | |||
@@ -51,6 +51,7 @@ static struct vfsmount *shm_mnt; | |||
51 | #include <linux/shmem_fs.h> | 51 | #include <linux/shmem_fs.h> |
52 | #include <linux/writeback.h> | 52 | #include <linux/writeback.h> |
53 | #include <linux/blkdev.h> | 53 | #include <linux/blkdev.h> |
54 | #include <linux/splice.h> | ||
54 | #include <linux/security.h> | 55 | #include <linux/security.h> |
55 | #include <linux/swapops.h> | 56 | #include <linux/swapops.h> |
56 | #include <linux/mempolicy.h> | 57 | #include <linux/mempolicy.h> |
@@ -126,8 +127,15 @@ static unsigned long shmem_default_max_inodes(void) | |||
126 | } | 127 | } |
127 | #endif | 128 | #endif |
128 | 129 | ||
129 | static int shmem_getpage(struct inode *inode, unsigned long idx, | 130 | static int shmem_getpage_gfp(struct inode *inode, pgoff_t index, |
130 | struct page **pagep, enum sgp_type sgp, int *type); | 131 | struct page **pagep, enum sgp_type sgp, gfp_t gfp, int *fault_type); |
132 | |||
133 | static inline int shmem_getpage(struct inode *inode, pgoff_t index, | ||
134 | struct page **pagep, enum sgp_type sgp, int *fault_type) | ||
135 | { | ||
136 | return shmem_getpage_gfp(inode, index, pagep, sgp, | ||
137 | mapping_gfp_mask(inode->i_mapping), fault_type); | ||
138 | } | ||
131 | 139 | ||
132 | static inline struct page *shmem_dir_alloc(gfp_t gfp_mask) | 140 | static inline struct page *shmem_dir_alloc(gfp_t gfp_mask) |
133 | { | 141 | { |
@@ -241,9 +249,7 @@ static void shmem_free_blocks(struct inode *inode, long pages) | |||
241 | struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb); | 249 | struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb); |
242 | if (sbinfo->max_blocks) { | 250 | if (sbinfo->max_blocks) { |
243 | percpu_counter_add(&sbinfo->used_blocks, -pages); | 251 | percpu_counter_add(&sbinfo->used_blocks, -pages); |
244 | spin_lock(&inode->i_lock); | ||
245 | inode->i_blocks -= pages*BLOCKS_PER_PAGE; | 252 | inode->i_blocks -= pages*BLOCKS_PER_PAGE; |
246 | spin_unlock(&inode->i_lock); | ||
247 | } | 253 | } |
248 | } | 254 | } |
249 | 255 | ||
@@ -405,10 +411,12 @@ static void shmem_swp_set(struct shmem_inode_info *info, swp_entry_t *entry, uns | |||
405 | * @info: info structure for the inode | 411 | * @info: info structure for the inode |
406 | * @index: index of the page to find | 412 | * @index: index of the page to find |
407 | * @sgp: check and recheck i_size? skip allocation? | 413 | * @sgp: check and recheck i_size? skip allocation? |
414 | * @gfp: gfp mask to use for any page allocation | ||
408 | * | 415 | * |
409 | * If the entry does not exist, allocate it. | 416 | * If the entry does not exist, allocate it. |
410 | */ | 417 | */ |
411 | static swp_entry_t *shmem_swp_alloc(struct shmem_inode_info *info, unsigned long index, enum sgp_type sgp) | 418 | static swp_entry_t *shmem_swp_alloc(struct shmem_inode_info *info, |
419 | unsigned long index, enum sgp_type sgp, gfp_t gfp) | ||
412 | { | 420 | { |
413 | struct inode *inode = &info->vfs_inode; | 421 | struct inode *inode = &info->vfs_inode; |
414 | struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb); | 422 | struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb); |
@@ -432,13 +440,11 @@ static swp_entry_t *shmem_swp_alloc(struct shmem_inode_info *info, unsigned long | |||
432 | sbinfo->max_blocks - 1) >= 0) | 440 | sbinfo->max_blocks - 1) >= 0) |
433 | return ERR_PTR(-ENOSPC); | 441 | return ERR_PTR(-ENOSPC); |
434 | percpu_counter_inc(&sbinfo->used_blocks); | 442 | percpu_counter_inc(&sbinfo->used_blocks); |
435 | spin_lock(&inode->i_lock); | ||
436 | inode->i_blocks += BLOCKS_PER_PAGE; | 443 | inode->i_blocks += BLOCKS_PER_PAGE; |
437 | spin_unlock(&inode->i_lock); | ||
438 | } | 444 | } |
439 | 445 | ||
440 | spin_unlock(&info->lock); | 446 | spin_unlock(&info->lock); |
441 | page = shmem_dir_alloc(mapping_gfp_mask(inode->i_mapping)); | 447 | page = shmem_dir_alloc(gfp); |
442 | spin_lock(&info->lock); | 448 | spin_lock(&info->lock); |
443 | 449 | ||
444 | if (!page) { | 450 | if (!page) { |
@@ -966,20 +972,7 @@ found: | |||
966 | error = add_to_page_cache_locked(page, mapping, idx, GFP_NOWAIT); | 972 | error = add_to_page_cache_locked(page, mapping, idx, GFP_NOWAIT); |
967 | /* which does mem_cgroup_uncharge_cache_page on error */ | 973 | /* which does mem_cgroup_uncharge_cache_page on error */ |
968 | 974 | ||
969 | if (error == -EEXIST) { | 975 | if (error != -ENOMEM) { |
970 | struct page *filepage = find_get_page(mapping, idx); | ||
971 | error = 1; | ||
972 | if (filepage) { | ||
973 | /* | ||
974 | * There might be a more uptodate page coming down | ||
975 | * from a stacked writepage: forget our swappage if so. | ||
976 | */ | ||
977 | if (PageUptodate(filepage)) | ||
978 | error = 0; | ||
979 | page_cache_release(filepage); | ||
980 | } | ||
981 | } | ||
982 | if (!error) { | ||
983 | delete_from_swap_cache(page); | 976 | delete_from_swap_cache(page); |
984 | set_page_dirty(page); | 977 | set_page_dirty(page); |
985 | info->flags |= SHMEM_PAGEIN; | 978 | info->flags |= SHMEM_PAGEIN; |
@@ -1066,16 +1059,17 @@ static int shmem_writepage(struct page *page, struct writeback_control *wbc) | |||
1066 | /* | 1059 | /* |
1067 | * shmem_backing_dev_info's capabilities prevent regular writeback or | 1060 | * shmem_backing_dev_info's capabilities prevent regular writeback or |
1068 | * sync from ever calling shmem_writepage; but a stacking filesystem | 1061 | * sync from ever calling shmem_writepage; but a stacking filesystem |
1069 | * may use the ->writepage of its underlying filesystem, in which case | 1062 | * might use ->writepage of its underlying filesystem, in which case |
1070 | * tmpfs should write out to swap only in response to memory pressure, | 1063 | * tmpfs should write out to swap only in response to memory pressure, |
1071 | * and not for the writeback threads or sync. However, in those cases, | 1064 | * and not for the writeback threads or sync. |
1072 | * we do still want to check if there's a redundant swappage to be | ||
1073 | * discarded. | ||
1074 | */ | 1065 | */ |
1075 | if (wbc->for_reclaim) | 1066 | if (!wbc->for_reclaim) { |
1076 | swap = get_swap_page(); | 1067 | WARN_ON_ONCE(1); /* Still happens? Tell us about it! */ |
1077 | else | 1068 | goto redirty; |
1078 | swap.val = 0; | 1069 | } |
1070 | swap = get_swap_page(); | ||
1071 | if (!swap.val) | ||
1072 | goto redirty; | ||
1079 | 1073 | ||
1080 | /* | 1074 | /* |
1081 | * Add inode to shmem_unuse()'s list of swapped-out inodes, | 1075 | * Add inode to shmem_unuse()'s list of swapped-out inodes, |
@@ -1086,15 +1080,12 @@ static int shmem_writepage(struct page *page, struct writeback_control *wbc) | |||
1086 | * we've taken the spinlock, because shmem_unuse_inode() will | 1080 | * we've taken the spinlock, because shmem_unuse_inode() will |
1087 | * prune a !swapped inode from the swaplist under both locks. | 1081 | * prune a !swapped inode from the swaplist under both locks. |
1088 | */ | 1082 | */ |
1089 | if (swap.val) { | 1083 | mutex_lock(&shmem_swaplist_mutex); |
1090 | mutex_lock(&shmem_swaplist_mutex); | 1084 | if (list_empty(&info->swaplist)) |
1091 | if (list_empty(&info->swaplist)) | 1085 | list_add_tail(&info->swaplist, &shmem_swaplist); |
1092 | list_add_tail(&info->swaplist, &shmem_swaplist); | ||
1093 | } | ||
1094 | 1086 | ||
1095 | spin_lock(&info->lock); | 1087 | spin_lock(&info->lock); |
1096 | if (swap.val) | 1088 | mutex_unlock(&shmem_swaplist_mutex); |
1097 | mutex_unlock(&shmem_swaplist_mutex); | ||
1098 | 1089 | ||
1099 | if (index >= info->next_index) { | 1090 | if (index >= info->next_index) { |
1100 | BUG_ON(!(info->flags & SHMEM_TRUNCATE)); | 1091 | BUG_ON(!(info->flags & SHMEM_TRUNCATE)); |
@@ -1102,16 +1093,13 @@ static int shmem_writepage(struct page *page, struct writeback_control *wbc) | |||
1102 | } | 1093 | } |
1103 | entry = shmem_swp_entry(info, index, NULL); | 1094 | entry = shmem_swp_entry(info, index, NULL); |
1104 | if (entry->val) { | 1095 | if (entry->val) { |
1105 | /* | 1096 | WARN_ON_ONCE(1); /* Still happens? Tell us about it! */ |
1106 | * The more uptodate page coming down from a stacked | ||
1107 | * writepage should replace our old swappage. | ||
1108 | */ | ||
1109 | free_swap_and_cache(*entry); | 1097 | free_swap_and_cache(*entry); |
1110 | shmem_swp_set(info, entry, 0); | 1098 | shmem_swp_set(info, entry, 0); |
1111 | } | 1099 | } |
1112 | shmem_recalc_inode(inode); | 1100 | shmem_recalc_inode(inode); |
1113 | 1101 | ||
1114 | if (swap.val && add_to_swap_cache(page, swap, GFP_ATOMIC) == 0) { | 1102 | if (add_to_swap_cache(page, swap, GFP_ATOMIC) == 0) { |
1115 | delete_from_page_cache(page); | 1103 | delete_from_page_cache(page); |
1116 | shmem_swp_set(info, entry, swap.val); | 1104 | shmem_swp_set(info, entry, swap.val); |
1117 | shmem_swp_unmap(entry); | 1105 | shmem_swp_unmap(entry); |
@@ -1228,92 +1216,83 @@ static inline struct mempolicy *shmem_get_sbmpol(struct shmem_sb_info *sbinfo) | |||
1228 | #endif | 1216 | #endif |
1229 | 1217 | ||
1230 | /* | 1218 | /* |
1231 | * shmem_getpage - either get the page from swap or allocate a new one | 1219 | * shmem_getpage_gfp - find page in cache, or get from swap, or allocate |
1232 | * | 1220 | * |
1233 | * If we allocate a new one we do not mark it dirty. That's up to the | 1221 | * If we allocate a new one we do not mark it dirty. That's up to the |
1234 | * vm. If we swap it in we mark it dirty since we also free the swap | 1222 | * vm. If we swap it in we mark it dirty since we also free the swap |
1235 | * entry since a page cannot live in both the swap and page cache | 1223 | * entry since a page cannot live in both the swap and page cache |
1236 | */ | 1224 | */ |
1237 | static int shmem_getpage(struct inode *inode, unsigned long idx, | 1225 | static int shmem_getpage_gfp(struct inode *inode, pgoff_t idx, |
1238 | struct page **pagep, enum sgp_type sgp, int *type) | 1226 | struct page **pagep, enum sgp_type sgp, gfp_t gfp, int *fault_type) |
1239 | { | 1227 | { |
1240 | struct address_space *mapping = inode->i_mapping; | 1228 | struct address_space *mapping = inode->i_mapping; |
1241 | struct shmem_inode_info *info = SHMEM_I(inode); | 1229 | struct shmem_inode_info *info = SHMEM_I(inode); |
1242 | struct shmem_sb_info *sbinfo; | 1230 | struct shmem_sb_info *sbinfo; |
1243 | struct page *filepage = *pagep; | 1231 | struct page *page; |
1244 | struct page *swappage; | ||
1245 | struct page *prealloc_page = NULL; | 1232 | struct page *prealloc_page = NULL; |
1246 | swp_entry_t *entry; | 1233 | swp_entry_t *entry; |
1247 | swp_entry_t swap; | 1234 | swp_entry_t swap; |
1248 | gfp_t gfp; | ||
1249 | int error; | 1235 | int error; |
1236 | int ret; | ||
1250 | 1237 | ||
1251 | if (idx >= SHMEM_MAX_INDEX) | 1238 | if (idx >= SHMEM_MAX_INDEX) |
1252 | return -EFBIG; | 1239 | return -EFBIG; |
1253 | |||
1254 | if (type) | ||
1255 | *type = 0; | ||
1256 | |||
1257 | /* | ||
1258 | * Normally, filepage is NULL on entry, and either found | ||
1259 | * uptodate immediately, or allocated and zeroed, or read | ||
1260 | * in under swappage, which is then assigned to filepage. | ||
1261 | * But shmem_readpage (required for splice) passes in a locked | ||
1262 | * filepage, which may be found not uptodate by other callers | ||
1263 | * too, and may need to be copied from the swappage read in. | ||
1264 | */ | ||
1265 | repeat: | 1240 | repeat: |
1266 | if (!filepage) | 1241 | page = find_lock_page(mapping, idx); |
1267 | filepage = find_lock_page(mapping, idx); | 1242 | if (page) { |
1268 | if (filepage && PageUptodate(filepage)) | ||
1269 | goto done; | ||
1270 | gfp = mapping_gfp_mask(mapping); | ||
1271 | if (!filepage) { | ||
1272 | /* | 1243 | /* |
1273 | * Try to preload while we can wait, to not make a habit of | 1244 | * Once we can get the page lock, it must be uptodate: |
1274 | * draining atomic reserves; but don't latch on to this cpu. | 1245 | * if there were an error in reading back from swap, |
1246 | * the page would not be inserted into the filecache. | ||
1275 | */ | 1247 | */ |
1276 | error = radix_tree_preload(gfp & ~__GFP_HIGHMEM); | 1248 | BUG_ON(!PageUptodate(page)); |
1277 | if (error) | 1249 | goto done; |
1278 | goto failed; | 1250 | } |
1279 | radix_tree_preload_end(); | 1251 | |
1280 | if (sgp != SGP_READ && !prealloc_page) { | 1252 | /* |
1281 | /* We don't care if this fails */ | 1253 | * Try to preload while we can wait, to not make a habit of |
1282 | prealloc_page = shmem_alloc_page(gfp, info, idx); | 1254 | * draining atomic reserves; but don't latch on to this cpu. |
1283 | if (prealloc_page) { | 1255 | */ |
1284 | if (mem_cgroup_cache_charge(prealloc_page, | 1256 | error = radix_tree_preload(gfp & GFP_RECLAIM_MASK); |
1285 | current->mm, GFP_KERNEL)) { | 1257 | if (error) |
1286 | page_cache_release(prealloc_page); | 1258 | goto out; |
1287 | prealloc_page = NULL; | 1259 | radix_tree_preload_end(); |
1288 | } | 1260 | |
1261 | if (sgp != SGP_READ && !prealloc_page) { | ||
1262 | prealloc_page = shmem_alloc_page(gfp, info, idx); | ||
1263 | if (prealloc_page) { | ||
1264 | SetPageSwapBacked(prealloc_page); | ||
1265 | if (mem_cgroup_cache_charge(prealloc_page, | ||
1266 | current->mm, GFP_KERNEL)) { | ||
1267 | page_cache_release(prealloc_page); | ||
1268 | prealloc_page = NULL; | ||
1289 | } | 1269 | } |
1290 | } | 1270 | } |
1291 | } | 1271 | } |
1292 | error = 0; | ||
1293 | 1272 | ||
1294 | spin_lock(&info->lock); | 1273 | spin_lock(&info->lock); |
1295 | shmem_recalc_inode(inode); | 1274 | shmem_recalc_inode(inode); |
1296 | entry = shmem_swp_alloc(info, idx, sgp); | 1275 | entry = shmem_swp_alloc(info, idx, sgp, gfp); |
1297 | if (IS_ERR(entry)) { | 1276 | if (IS_ERR(entry)) { |
1298 | spin_unlock(&info->lock); | 1277 | spin_unlock(&info->lock); |
1299 | error = PTR_ERR(entry); | 1278 | error = PTR_ERR(entry); |
1300 | goto failed; | 1279 | goto out; |
1301 | } | 1280 | } |
1302 | swap = *entry; | 1281 | swap = *entry; |
1303 | 1282 | ||
1304 | if (swap.val) { | 1283 | if (swap.val) { |
1305 | /* Look it up and read it in.. */ | 1284 | /* Look it up and read it in.. */ |
1306 | swappage = lookup_swap_cache(swap); | 1285 | page = lookup_swap_cache(swap); |
1307 | if (!swappage) { | 1286 | if (!page) { |
1308 | shmem_swp_unmap(entry); | 1287 | shmem_swp_unmap(entry); |
1309 | spin_unlock(&info->lock); | 1288 | spin_unlock(&info->lock); |
1310 | /* here we actually do the io */ | 1289 | /* here we actually do the io */ |
1311 | if (type) | 1290 | if (fault_type) |
1312 | *type |= VM_FAULT_MAJOR; | 1291 | *fault_type |= VM_FAULT_MAJOR; |
1313 | swappage = shmem_swapin(swap, gfp, info, idx); | 1292 | page = shmem_swapin(swap, gfp, info, idx); |
1314 | if (!swappage) { | 1293 | if (!page) { |
1315 | spin_lock(&info->lock); | 1294 | spin_lock(&info->lock); |
1316 | entry = shmem_swp_alloc(info, idx, sgp); | 1295 | entry = shmem_swp_alloc(info, idx, sgp, gfp); |
1317 | if (IS_ERR(entry)) | 1296 | if (IS_ERR(entry)) |
1318 | error = PTR_ERR(entry); | 1297 | error = PTR_ERR(entry); |
1319 | else { | 1298 | else { |
@@ -1323,62 +1302,42 @@ repeat: | |||
1323 | } | 1302 | } |
1324 | spin_unlock(&info->lock); | 1303 | spin_unlock(&info->lock); |
1325 | if (error) | 1304 | if (error) |
1326 | goto failed; | 1305 | goto out; |
1327 | goto repeat; | 1306 | goto repeat; |
1328 | } | 1307 | } |
1329 | wait_on_page_locked(swappage); | 1308 | wait_on_page_locked(page); |
1330 | page_cache_release(swappage); | 1309 | page_cache_release(page); |
1331 | goto repeat; | 1310 | goto repeat; |
1332 | } | 1311 | } |
1333 | 1312 | ||
1334 | /* We have to do this with page locked to prevent races */ | 1313 | /* We have to do this with page locked to prevent races */ |
1335 | if (!trylock_page(swappage)) { | 1314 | if (!trylock_page(page)) { |
1336 | shmem_swp_unmap(entry); | 1315 | shmem_swp_unmap(entry); |
1337 | spin_unlock(&info->lock); | 1316 | spin_unlock(&info->lock); |
1338 | wait_on_page_locked(swappage); | 1317 | wait_on_page_locked(page); |
1339 | page_cache_release(swappage); | 1318 | page_cache_release(page); |
1340 | goto repeat; | 1319 | goto repeat; |
1341 | } | 1320 | } |
1342 | if (PageWriteback(swappage)) { | 1321 | if (PageWriteback(page)) { |
1343 | shmem_swp_unmap(entry); | 1322 | shmem_swp_unmap(entry); |
1344 | spin_unlock(&info->lock); | 1323 | spin_unlock(&info->lock); |
1345 | wait_on_page_writeback(swappage); | 1324 | wait_on_page_writeback(page); |
1346 | unlock_page(swappage); | 1325 | unlock_page(page); |
1347 | page_cache_release(swappage); | 1326 | page_cache_release(page); |
1348 | goto repeat; | 1327 | goto repeat; |
1349 | } | 1328 | } |
1350 | if (!PageUptodate(swappage)) { | 1329 | if (!PageUptodate(page)) { |
1351 | shmem_swp_unmap(entry); | 1330 | shmem_swp_unmap(entry); |
1352 | spin_unlock(&info->lock); | 1331 | spin_unlock(&info->lock); |
1353 | unlock_page(swappage); | 1332 | unlock_page(page); |
1354 | page_cache_release(swappage); | 1333 | page_cache_release(page); |
1355 | error = -EIO; | 1334 | error = -EIO; |
1356 | goto failed; | 1335 | goto out; |
1357 | } | 1336 | } |
1358 | 1337 | ||
1359 | if (filepage) { | 1338 | error = add_to_page_cache_locked(page, mapping, |
1360 | shmem_swp_set(info, entry, 0); | 1339 | idx, GFP_NOWAIT); |
1361 | shmem_swp_unmap(entry); | 1340 | if (error) { |
1362 | delete_from_swap_cache(swappage); | ||
1363 | spin_unlock(&info->lock); | ||
1364 | copy_highpage(filepage, swappage); | ||
1365 | unlock_page(swappage); | ||
1366 | page_cache_release(swappage); | ||
1367 | flush_dcache_page(filepage); | ||
1368 | SetPageUptodate(filepage); | ||
1369 | set_page_dirty(filepage); | ||
1370 | swap_free(swap); | ||
1371 | } else if (!(error = add_to_page_cache_locked(swappage, mapping, | ||
1372 | idx, GFP_NOWAIT))) { | ||
1373 | info->flags |= SHMEM_PAGEIN; | ||
1374 | shmem_swp_set(info, entry, 0); | ||
1375 | shmem_swp_unmap(entry); | ||
1376 | delete_from_swap_cache(swappage); | ||
1377 | spin_unlock(&info->lock); | ||
1378 | filepage = swappage; | ||
1379 | set_page_dirty(filepage); | ||
1380 | swap_free(swap); | ||
1381 | } else { | ||
1382 | shmem_swp_unmap(entry); | 1341 | shmem_swp_unmap(entry); |
1383 | spin_unlock(&info->lock); | 1342 | spin_unlock(&info->lock); |
1384 | if (error == -ENOMEM) { | 1343 | if (error == -ENOMEM) { |
@@ -1387,32 +1346,38 @@ repeat: | |||
1387 | * call memcg's OOM if needed. | 1346 | * call memcg's OOM if needed. |
1388 | */ | 1347 | */ |
1389 | error = mem_cgroup_shmem_charge_fallback( | 1348 | error = mem_cgroup_shmem_charge_fallback( |
1390 | swappage, | 1349 | page, current->mm, gfp); |
1391 | current->mm, | ||
1392 | gfp); | ||
1393 | if (error) { | 1350 | if (error) { |
1394 | unlock_page(swappage); | 1351 | unlock_page(page); |
1395 | page_cache_release(swappage); | 1352 | page_cache_release(page); |
1396 | goto failed; | 1353 | goto out; |
1397 | } | 1354 | } |
1398 | } | 1355 | } |
1399 | unlock_page(swappage); | 1356 | unlock_page(page); |
1400 | page_cache_release(swappage); | 1357 | page_cache_release(page); |
1401 | goto repeat; | 1358 | goto repeat; |
1402 | } | 1359 | } |
1403 | } else if (sgp == SGP_READ && !filepage) { | 1360 | |
1361 | info->flags |= SHMEM_PAGEIN; | ||
1362 | shmem_swp_set(info, entry, 0); | ||
1404 | shmem_swp_unmap(entry); | 1363 | shmem_swp_unmap(entry); |
1405 | filepage = find_get_page(mapping, idx); | 1364 | delete_from_swap_cache(page); |
1406 | if (filepage && | 1365 | spin_unlock(&info->lock); |
1407 | (!PageUptodate(filepage) || !trylock_page(filepage))) { | 1366 | set_page_dirty(page); |
1367 | swap_free(swap); | ||
1368 | |||
1369 | } else if (sgp == SGP_READ) { | ||
1370 | shmem_swp_unmap(entry); | ||
1371 | page = find_get_page(mapping, idx); | ||
1372 | if (page && !trylock_page(page)) { | ||
1408 | spin_unlock(&info->lock); | 1373 | spin_unlock(&info->lock); |
1409 | wait_on_page_locked(filepage); | 1374 | wait_on_page_locked(page); |
1410 | page_cache_release(filepage); | 1375 | page_cache_release(page); |
1411 | filepage = NULL; | ||
1412 | goto repeat; | 1376 | goto repeat; |
1413 | } | 1377 | } |
1414 | spin_unlock(&info->lock); | 1378 | spin_unlock(&info->lock); |
1415 | } else { | 1379 | |
1380 | } else if (prealloc_page) { | ||
1416 | shmem_swp_unmap(entry); | 1381 | shmem_swp_unmap(entry); |
1417 | sbinfo = SHMEM_SB(inode->i_sb); | 1382 | sbinfo = SHMEM_SB(inode->i_sb); |
1418 | if (sbinfo->max_blocks) { | 1383 | if (sbinfo->max_blocks) { |
@@ -1421,126 +1386,86 @@ repeat: | |||
1421 | shmem_acct_block(info->flags)) | 1386 | shmem_acct_block(info->flags)) |
1422 | goto nospace; | 1387 | goto nospace; |
1423 | percpu_counter_inc(&sbinfo->used_blocks); | 1388 | percpu_counter_inc(&sbinfo->used_blocks); |
1424 | spin_lock(&inode->i_lock); | ||
1425 | inode->i_blocks += BLOCKS_PER_PAGE; | 1389 | inode->i_blocks += BLOCKS_PER_PAGE; |
1426 | spin_unlock(&inode->i_lock); | ||
1427 | } else if (shmem_acct_block(info->flags)) | 1390 | } else if (shmem_acct_block(info->flags)) |
1428 | goto nospace; | 1391 | goto nospace; |
1429 | 1392 | ||
1430 | if (!filepage) { | 1393 | page = prealloc_page; |
1431 | int ret; | 1394 | prealloc_page = NULL; |
1432 | |||
1433 | if (!prealloc_page) { | ||
1434 | spin_unlock(&info->lock); | ||
1435 | filepage = shmem_alloc_page(gfp, info, idx); | ||
1436 | if (!filepage) { | ||
1437 | shmem_unacct_blocks(info->flags, 1); | ||
1438 | shmem_free_blocks(inode, 1); | ||
1439 | error = -ENOMEM; | ||
1440 | goto failed; | ||
1441 | } | ||
1442 | SetPageSwapBacked(filepage); | ||
1443 | 1395 | ||
1444 | /* | 1396 | entry = shmem_swp_alloc(info, idx, sgp, gfp); |
1445 | * Precharge page while we can wait, compensate | 1397 | if (IS_ERR(entry)) |
1446 | * after | 1398 | error = PTR_ERR(entry); |
1447 | */ | 1399 | else { |
1448 | error = mem_cgroup_cache_charge(filepage, | 1400 | swap = *entry; |
1449 | current->mm, GFP_KERNEL); | 1401 | shmem_swp_unmap(entry); |
1450 | if (error) { | 1402 | } |
1451 | page_cache_release(filepage); | 1403 | ret = error || swap.val; |
1452 | shmem_unacct_blocks(info->flags, 1); | 1404 | if (ret) |
1453 | shmem_free_blocks(inode, 1); | 1405 | mem_cgroup_uncharge_cache_page(page); |
1454 | filepage = NULL; | 1406 | else |
1455 | goto failed; | 1407 | ret = add_to_page_cache_lru(page, mapping, |
1456 | } | ||
1457 | |||
1458 | spin_lock(&info->lock); | ||
1459 | } else { | ||
1460 | filepage = prealloc_page; | ||
1461 | prealloc_page = NULL; | ||
1462 | SetPageSwapBacked(filepage); | ||
1463 | } | ||
1464 | |||
1465 | entry = shmem_swp_alloc(info, idx, sgp); | ||
1466 | if (IS_ERR(entry)) | ||
1467 | error = PTR_ERR(entry); | ||
1468 | else { | ||
1469 | swap = *entry; | ||
1470 | shmem_swp_unmap(entry); | ||
1471 | } | ||
1472 | ret = error || swap.val; | ||
1473 | if (ret) | ||
1474 | mem_cgroup_uncharge_cache_page(filepage); | ||
1475 | else | ||
1476 | ret = add_to_page_cache_lru(filepage, mapping, | ||
1477 | idx, GFP_NOWAIT); | 1408 | idx, GFP_NOWAIT); |
1478 | /* | 1409 | /* |
1479 | * At add_to_page_cache_lru() failure, uncharge will | 1410 | * At add_to_page_cache_lru() failure, |
1480 | * be done automatically. | 1411 | * uncharge will be done automatically. |
1481 | */ | 1412 | */ |
1482 | if (ret) { | 1413 | if (ret) { |
1483 | spin_unlock(&info->lock); | 1414 | shmem_unacct_blocks(info->flags, 1); |
1484 | page_cache_release(filepage); | 1415 | shmem_free_blocks(inode, 1); |
1485 | shmem_unacct_blocks(info->flags, 1); | 1416 | spin_unlock(&info->lock); |
1486 | shmem_free_blocks(inode, 1); | 1417 | page_cache_release(page); |
1487 | filepage = NULL; | 1418 | if (error) |
1488 | if (error) | 1419 | goto out; |
1489 | goto failed; | 1420 | goto repeat; |
1490 | goto repeat; | ||
1491 | } | ||
1492 | info->flags |= SHMEM_PAGEIN; | ||
1493 | } | 1421 | } |
1494 | 1422 | ||
1423 | info->flags |= SHMEM_PAGEIN; | ||
1495 | info->alloced++; | 1424 | info->alloced++; |
1496 | spin_unlock(&info->lock); | 1425 | spin_unlock(&info->lock); |
1497 | clear_highpage(filepage); | 1426 | clear_highpage(page); |
1498 | flush_dcache_page(filepage); | 1427 | flush_dcache_page(page); |
1499 | SetPageUptodate(filepage); | 1428 | SetPageUptodate(page); |
1500 | if (sgp == SGP_DIRTY) | 1429 | if (sgp == SGP_DIRTY) |
1501 | set_page_dirty(filepage); | 1430 | set_page_dirty(page); |
1431 | |||
1432 | } else { | ||
1433 | spin_unlock(&info->lock); | ||
1434 | error = -ENOMEM; | ||
1435 | goto out; | ||
1502 | } | 1436 | } |
1503 | done: | 1437 | done: |
1504 | *pagep = filepage; | 1438 | *pagep = page; |
1505 | error = 0; | 1439 | error = 0; |
1506 | goto out; | 1440 | out: |
1441 | if (prealloc_page) { | ||
1442 | mem_cgroup_uncharge_cache_page(prealloc_page); | ||
1443 | page_cache_release(prealloc_page); | ||
1444 | } | ||
1445 | return error; | ||
1507 | 1446 | ||
1508 | nospace: | 1447 | nospace: |
1509 | /* | 1448 | /* |
1510 | * Perhaps the page was brought in from swap between find_lock_page | 1449 | * Perhaps the page was brought in from swap between find_lock_page |
1511 | * and taking info->lock? We allow for that at add_to_page_cache_lru, | 1450 | * and taking info->lock? We allow for that at add_to_page_cache_lru, |
1512 | * but must also avoid reporting a spurious ENOSPC while working on a | 1451 | * but must also avoid reporting a spurious ENOSPC while working on a |
1513 | * full tmpfs. (When filepage has been passed in to shmem_getpage, it | 1452 | * full tmpfs. |
1514 | * is already in page cache, which prevents this race from occurring.) | ||
1515 | */ | 1453 | */ |
1516 | if (!filepage) { | 1454 | page = find_get_page(mapping, idx); |
1517 | struct page *page = find_get_page(mapping, idx); | ||
1518 | if (page) { | ||
1519 | spin_unlock(&info->lock); | ||
1520 | page_cache_release(page); | ||
1521 | goto repeat; | ||
1522 | } | ||
1523 | } | ||
1524 | spin_unlock(&info->lock); | 1455 | spin_unlock(&info->lock); |
1525 | error = -ENOSPC; | 1456 | if (page) { |
1526 | failed: | 1457 | page_cache_release(page); |
1527 | if (*pagep != filepage) { | 1458 | goto repeat; |
1528 | unlock_page(filepage); | ||
1529 | page_cache_release(filepage); | ||
1530 | } | ||
1531 | out: | ||
1532 | if (prealloc_page) { | ||
1533 | mem_cgroup_uncharge_cache_page(prealloc_page); | ||
1534 | page_cache_release(prealloc_page); | ||
1535 | } | 1459 | } |
1536 | return error; | 1460 | error = -ENOSPC; |
1461 | goto out; | ||
1537 | } | 1462 | } |
1538 | 1463 | ||
1539 | static int shmem_fault(struct vm_area_struct *vma, struct vm_fault *vmf) | 1464 | static int shmem_fault(struct vm_area_struct *vma, struct vm_fault *vmf) |
1540 | { | 1465 | { |
1541 | struct inode *inode = vma->vm_file->f_path.dentry->d_inode; | 1466 | struct inode *inode = vma->vm_file->f_path.dentry->d_inode; |
1542 | int error; | 1467 | int error; |
1543 | int ret; | 1468 | int ret = VM_FAULT_LOCKED; |
1544 | 1469 | ||
1545 | if (((loff_t)vmf->pgoff << PAGE_CACHE_SHIFT) >= i_size_read(inode)) | 1470 | if (((loff_t)vmf->pgoff << PAGE_CACHE_SHIFT) >= i_size_read(inode)) |
1546 | return VM_FAULT_SIGBUS; | 1471 | return VM_FAULT_SIGBUS; |
@@ -1548,11 +1473,12 @@ static int shmem_fault(struct vm_area_struct *vma, struct vm_fault *vmf) | |||
1548 | error = shmem_getpage(inode, vmf->pgoff, &vmf->page, SGP_CACHE, &ret); | 1473 | error = shmem_getpage(inode, vmf->pgoff, &vmf->page, SGP_CACHE, &ret); |
1549 | if (error) | 1474 | if (error) |
1550 | return ((error == -ENOMEM) ? VM_FAULT_OOM : VM_FAULT_SIGBUS); | 1475 | return ((error == -ENOMEM) ? VM_FAULT_OOM : VM_FAULT_SIGBUS); |
1476 | |||
1551 | if (ret & VM_FAULT_MAJOR) { | 1477 | if (ret & VM_FAULT_MAJOR) { |
1552 | count_vm_event(PGMAJFAULT); | 1478 | count_vm_event(PGMAJFAULT); |
1553 | mem_cgroup_count_vm_event(vma->vm_mm, PGMAJFAULT); | 1479 | mem_cgroup_count_vm_event(vma->vm_mm, PGMAJFAULT); |
1554 | } | 1480 | } |
1555 | return ret | VM_FAULT_LOCKED; | 1481 | return ret; |
1556 | } | 1482 | } |
1557 | 1483 | ||
1558 | #ifdef CONFIG_NUMA | 1484 | #ifdef CONFIG_NUMA |
@@ -1669,19 +1595,6 @@ static struct inode *shmem_get_inode(struct super_block *sb, const struct inode | |||
1669 | static const struct inode_operations shmem_symlink_inode_operations; | 1595 | static const struct inode_operations shmem_symlink_inode_operations; |
1670 | static const struct inode_operations shmem_symlink_inline_operations; | 1596 | static const struct inode_operations shmem_symlink_inline_operations; |
1671 | 1597 | ||
1672 | /* | ||
1673 | * Normally tmpfs avoids the use of shmem_readpage and shmem_write_begin; | ||
1674 | * but providing them allows a tmpfs file to be used for splice, sendfile, and | ||
1675 | * below the loop driver, in the generic fashion that many filesystems support. | ||
1676 | */ | ||
1677 | static int shmem_readpage(struct file *file, struct page *page) | ||
1678 | { | ||
1679 | struct inode *inode = page->mapping->host; | ||
1680 | int error = shmem_getpage(inode, page->index, &page, SGP_CACHE, NULL); | ||
1681 | unlock_page(page); | ||
1682 | return error; | ||
1683 | } | ||
1684 | |||
1685 | static int | 1598 | static int |
1686 | shmem_write_begin(struct file *file, struct address_space *mapping, | 1599 | shmem_write_begin(struct file *file, struct address_space *mapping, |
1687 | loff_t pos, unsigned len, unsigned flags, | 1600 | loff_t pos, unsigned len, unsigned flags, |
@@ -1689,7 +1602,6 @@ shmem_write_begin(struct file *file, struct address_space *mapping, | |||
1689 | { | 1602 | { |
1690 | struct inode *inode = mapping->host; | 1603 | struct inode *inode = mapping->host; |
1691 | pgoff_t index = pos >> PAGE_CACHE_SHIFT; | 1604 | pgoff_t index = pos >> PAGE_CACHE_SHIFT; |
1692 | *pagep = NULL; | ||
1693 | return shmem_getpage(inode, index, pagep, SGP_WRITE, NULL); | 1605 | return shmem_getpage(inode, index, pagep, SGP_WRITE, NULL); |
1694 | } | 1606 | } |
1695 | 1607 | ||
@@ -1846,6 +1758,119 @@ static ssize_t shmem_file_aio_read(struct kiocb *iocb, | |||
1846 | return retval; | 1758 | return retval; |
1847 | } | 1759 | } |
1848 | 1760 | ||
1761 | static ssize_t shmem_file_splice_read(struct file *in, loff_t *ppos, | ||
1762 | struct pipe_inode_info *pipe, size_t len, | ||
1763 | unsigned int flags) | ||
1764 | { | ||
1765 | struct address_space *mapping = in->f_mapping; | ||
1766 | struct inode *inode = mapping->host; | ||
1767 | unsigned int loff, nr_pages, req_pages; | ||
1768 | struct page *pages[PIPE_DEF_BUFFERS]; | ||
1769 | struct partial_page partial[PIPE_DEF_BUFFERS]; | ||
1770 | struct page *page; | ||
1771 | pgoff_t index, end_index; | ||
1772 | loff_t isize, left; | ||
1773 | int error, page_nr; | ||
1774 | struct splice_pipe_desc spd = { | ||
1775 | .pages = pages, | ||
1776 | .partial = partial, | ||
1777 | .flags = flags, | ||
1778 | .ops = &page_cache_pipe_buf_ops, | ||
1779 | .spd_release = spd_release_page, | ||
1780 | }; | ||
1781 | |||
1782 | isize = i_size_read(inode); | ||
1783 | if (unlikely(*ppos >= isize)) | ||
1784 | return 0; | ||
1785 | |||
1786 | left = isize - *ppos; | ||
1787 | if (unlikely(left < len)) | ||
1788 | len = left; | ||
1789 | |||
1790 | if (splice_grow_spd(pipe, &spd)) | ||
1791 | return -ENOMEM; | ||
1792 | |||
1793 | index = *ppos >> PAGE_CACHE_SHIFT; | ||
1794 | loff = *ppos & ~PAGE_CACHE_MASK; | ||
1795 | req_pages = (len + loff + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; | ||
1796 | nr_pages = min(req_pages, pipe->buffers); | ||
1797 | |||
1798 | spd.nr_pages = find_get_pages_contig(mapping, index, | ||
1799 | nr_pages, spd.pages); | ||
1800 | index += spd.nr_pages; | ||
1801 | error = 0; | ||
1802 | |||
1803 | while (spd.nr_pages < nr_pages) { | ||
1804 | error = shmem_getpage(inode, index, &page, SGP_CACHE, NULL); | ||
1805 | if (error) | ||
1806 | break; | ||
1807 | unlock_page(page); | ||
1808 | spd.pages[spd.nr_pages++] = page; | ||
1809 | index++; | ||
1810 | } | ||
1811 | |||
1812 | index = *ppos >> PAGE_CACHE_SHIFT; | ||
1813 | nr_pages = spd.nr_pages; | ||
1814 | spd.nr_pages = 0; | ||
1815 | |||
1816 | for (page_nr = 0; page_nr < nr_pages; page_nr++) { | ||
1817 | unsigned int this_len; | ||
1818 | |||
1819 | if (!len) | ||
1820 | break; | ||
1821 | |||
1822 | this_len = min_t(unsigned long, len, PAGE_CACHE_SIZE - loff); | ||
1823 | page = spd.pages[page_nr]; | ||
1824 | |||
1825 | if (!PageUptodate(page) || page->mapping != mapping) { | ||
1826 | error = shmem_getpage(inode, index, &page, | ||
1827 | SGP_CACHE, NULL); | ||
1828 | if (error) | ||
1829 | break; | ||
1830 | unlock_page(page); | ||
1831 | page_cache_release(spd.pages[page_nr]); | ||
1832 | spd.pages[page_nr] = page; | ||
1833 | } | ||
1834 | |||
1835 | isize = i_size_read(inode); | ||
1836 | end_index = (isize - 1) >> PAGE_CACHE_SHIFT; | ||
1837 | if (unlikely(!isize || index > end_index)) | ||
1838 | break; | ||
1839 | |||
1840 | if (end_index == index) { | ||
1841 | unsigned int plen; | ||
1842 | |||
1843 | plen = ((isize - 1) & ~PAGE_CACHE_MASK) + 1; | ||
1844 | if (plen <= loff) | ||
1845 | break; | ||
1846 | |||
1847 | this_len = min(this_len, plen - loff); | ||
1848 | len = this_len; | ||
1849 | } | ||
1850 | |||
1851 | spd.partial[page_nr].offset = loff; | ||
1852 | spd.partial[page_nr].len = this_len; | ||
1853 | len -= this_len; | ||
1854 | loff = 0; | ||
1855 | spd.nr_pages++; | ||
1856 | index++; | ||
1857 | } | ||
1858 | |||
1859 | while (page_nr < nr_pages) | ||
1860 | page_cache_release(spd.pages[page_nr++]); | ||
1861 | |||
1862 | if (spd.nr_pages) | ||
1863 | error = splice_to_pipe(pipe, &spd); | ||
1864 | |||
1865 | splice_shrink_spd(pipe, &spd); | ||
1866 | |||
1867 | if (error > 0) { | ||
1868 | *ppos += error; | ||
1869 | file_accessed(in); | ||
1870 | } | ||
1871 | return error; | ||
1872 | } | ||
1873 | |||
1849 | static int shmem_statfs(struct dentry *dentry, struct kstatfs *buf) | 1874 | static int shmem_statfs(struct dentry *dentry, struct kstatfs *buf) |
1850 | { | 1875 | { |
1851 | struct shmem_sb_info *sbinfo = SHMEM_SB(dentry->d_sb); | 1876 | struct shmem_sb_info *sbinfo = SHMEM_SB(dentry->d_sb); |
@@ -2006,7 +2031,7 @@ static int shmem_symlink(struct inode *dir, struct dentry *dentry, const char *s | |||
2006 | int error; | 2031 | int error; |
2007 | int len; | 2032 | int len; |
2008 | struct inode *inode; | 2033 | struct inode *inode; |
2009 | struct page *page = NULL; | 2034 | struct page *page; |
2010 | char *kaddr; | 2035 | char *kaddr; |
2011 | struct shmem_inode_info *info; | 2036 | struct shmem_inode_info *info; |
2012 | 2037 | ||
@@ -2684,7 +2709,6 @@ static const struct address_space_operations shmem_aops = { | |||
2684 | .writepage = shmem_writepage, | 2709 | .writepage = shmem_writepage, |
2685 | .set_page_dirty = __set_page_dirty_no_writeback, | 2710 | .set_page_dirty = __set_page_dirty_no_writeback, |
2686 | #ifdef CONFIG_TMPFS | 2711 | #ifdef CONFIG_TMPFS |
2687 | .readpage = shmem_readpage, | ||
2688 | .write_begin = shmem_write_begin, | 2712 | .write_begin = shmem_write_begin, |
2689 | .write_end = shmem_write_end, | 2713 | .write_end = shmem_write_end, |
2690 | #endif | 2714 | #endif |
@@ -2701,7 +2725,7 @@ static const struct file_operations shmem_file_operations = { | |||
2701 | .aio_read = shmem_file_aio_read, | 2725 | .aio_read = shmem_file_aio_read, |
2702 | .aio_write = generic_file_aio_write, | 2726 | .aio_write = generic_file_aio_write, |
2703 | .fsync = noop_fsync, | 2727 | .fsync = noop_fsync, |
2704 | .splice_read = generic_file_splice_read, | 2728 | .splice_read = shmem_file_splice_read, |
2705 | .splice_write = generic_file_splice_write, | 2729 | .splice_write = generic_file_splice_write, |
2706 | #endif | 2730 | #endif |
2707 | }; | 2731 | }; |
@@ -3042,13 +3066,29 @@ int shmem_zero_setup(struct vm_area_struct *vma) | |||
3042 | * suit tmpfs, since it may have pages in swapcache, and needs to find those | 3066 | * suit tmpfs, since it may have pages in swapcache, and needs to find those |
3043 | * for itself; although drivers/gpu/drm i915 and ttm rely upon this support. | 3067 | * for itself; although drivers/gpu/drm i915 and ttm rely upon this support. |
3044 | * | 3068 | * |
3045 | * Provide a stub for those callers to start using now, then later | 3069 | * i915_gem_object_get_pages_gtt() mixes __GFP_NORETRY | __GFP_NOWARN in |
3046 | * flesh it out to call shmem_getpage() with additional gfp mask, when | 3070 | * with the mapping_gfp_mask(), to avoid OOMing the machine unnecessarily. |
3047 | * shmem_file_splice_read() is added and shmem_readpage() is removed. | ||
3048 | */ | 3071 | */ |
3049 | struct page *shmem_read_mapping_page_gfp(struct address_space *mapping, | 3072 | struct page *shmem_read_mapping_page_gfp(struct address_space *mapping, |
3050 | pgoff_t index, gfp_t gfp) | 3073 | pgoff_t index, gfp_t gfp) |
3051 | { | 3074 | { |
3075 | #ifdef CONFIG_SHMEM | ||
3076 | struct inode *inode = mapping->host; | ||
3077 | struct page *page; | ||
3078 | int error; | ||
3079 | |||
3080 | BUG_ON(mapping->a_ops != &shmem_aops); | ||
3081 | error = shmem_getpage_gfp(inode, index, &page, SGP_CACHE, gfp, NULL); | ||
3082 | if (error) | ||
3083 | page = ERR_PTR(error); | ||
3084 | else | ||
3085 | unlock_page(page); | ||
3086 | return page; | ||
3087 | #else | ||
3088 | /* | ||
3089 | * The tiny !SHMEM case uses ramfs without swap | ||
3090 | */ | ||
3052 | return read_cache_page_gfp(mapping, index, gfp); | 3091 | return read_cache_page_gfp(mapping, index, gfp); |
3092 | #endif | ||
3053 | } | 3093 | } |
3054 | EXPORT_SYMBOL_GPL(shmem_read_mapping_page_gfp); | 3094 | EXPORT_SYMBOL_GPL(shmem_read_mapping_page_gfp); |
diff --git a/mm/sparse.c b/mm/sparse.c index aa64b12831a2..858e1dff9b2a 100644 --- a/mm/sparse.c +++ b/mm/sparse.c | |||
@@ -40,7 +40,7 @@ static u8 section_to_node_table[NR_MEM_SECTIONS] __cacheline_aligned; | |||
40 | static u16 section_to_node_table[NR_MEM_SECTIONS] __cacheline_aligned; | 40 | static u16 section_to_node_table[NR_MEM_SECTIONS] __cacheline_aligned; |
41 | #endif | 41 | #endif |
42 | 42 | ||
43 | int page_to_nid(struct page *page) | 43 | int page_to_nid(const struct page *page) |
44 | { | 44 | { |
45 | return section_to_node_table[page_to_section(page)]; | 45 | return section_to_node_table[page_to_section(page)]; |
46 | } | 46 | } |
diff --git a/mm/thrash.c b/mm/thrash.c index fabf2d0f5169..e53f7d02c17c 100644 --- a/mm/thrash.c +++ b/mm/thrash.c | |||
@@ -6,7 +6,7 @@ | |||
6 | * Released under the GPL, see the file COPYING for details. | 6 | * Released under the GPL, see the file COPYING for details. |
7 | * | 7 | * |
8 | * Simple token based thrashing protection, using the algorithm | 8 | * Simple token based thrashing protection, using the algorithm |
9 | * described in: http://www.cs.wm.edu/~sjiang/token.pdf | 9 | * described in: http://www.cse.ohio-state.edu/hpcs/WWW/HTML/publications/abs05-1.html |
10 | * | 10 | * |
11 | * Sep 2006, Ashwin Chaugule <ashwin.chaugule@celunite.com> | 11 | * Sep 2006, Ashwin Chaugule <ashwin.chaugule@celunite.com> |
12 | * Improved algorithm to pass token: | 12 | * Improved algorithm to pass token: |
@@ -30,8 +30,6 @@ | |||
30 | static DEFINE_SPINLOCK(swap_token_lock); | 30 | static DEFINE_SPINLOCK(swap_token_lock); |
31 | struct mm_struct *swap_token_mm; | 31 | struct mm_struct *swap_token_mm; |
32 | struct mem_cgroup *swap_token_memcg; | 32 | struct mem_cgroup *swap_token_memcg; |
33 | static unsigned int global_faults; | ||
34 | static unsigned int last_aging; | ||
35 | 33 | ||
36 | #ifdef CONFIG_CGROUP_MEM_RES_CTLR | 34 | #ifdef CONFIG_CGROUP_MEM_RES_CTLR |
37 | static struct mem_cgroup *swap_token_memcg_from_mm(struct mm_struct *mm) | 35 | static struct mem_cgroup *swap_token_memcg_from_mm(struct mm_struct *mm) |
@@ -55,6 +53,8 @@ void grab_swap_token(struct mm_struct *mm) | |||
55 | { | 53 | { |
56 | int current_interval; | 54 | int current_interval; |
57 | unsigned int old_prio = mm->token_priority; | 55 | unsigned int old_prio = mm->token_priority; |
56 | static unsigned int global_faults; | ||
57 | static unsigned int last_aging; | ||
58 | 58 | ||
59 | global_faults++; | 59 | global_faults++; |
60 | 60 | ||
@@ -67,6 +67,17 @@ void grab_swap_token(struct mm_struct *mm) | |||
67 | if (!swap_token_mm) | 67 | if (!swap_token_mm) |
68 | goto replace_token; | 68 | goto replace_token; |
69 | 69 | ||
70 | /* | ||
71 | * Usually, we don't need priority aging because long interval faults | ||
72 | * makes priority decrease quickly. But there is one exception. If the | ||
73 | * token owner task is sleeping, it never make long interval faults. | ||
74 | * Thus, we need a priority aging mechanism instead. The requirements | ||
75 | * of priority aging are | ||
76 | * 1) An aging interval is reasonable enough long. Too short aging | ||
77 | * interval makes quick swap token lost and decrease performance. | ||
78 | * 2) The swap token owner task have to get priority aging even if | ||
79 | * it's under sleep. | ||
80 | */ | ||
70 | if ((global_faults - last_aging) > TOKEN_AGING_INTERVAL) { | 81 | if ((global_faults - last_aging) > TOKEN_AGING_INTERVAL) { |
71 | swap_token_mm->token_priority /= 2; | 82 | swap_token_mm->token_priority /= 2; |
72 | last_aging = global_faults; | 83 | last_aging = global_faults; |
diff --git a/mm/truncate.c b/mm/truncate.c index 003c6c685fc8..232eb2736a79 100644 --- a/mm/truncate.c +++ b/mm/truncate.c | |||
@@ -199,9 +199,6 @@ int invalidate_inode_page(struct page *page) | |||
199 | * The first pass will remove most pages, so the search cost of the second pass | 199 | * The first pass will remove most pages, so the search cost of the second pass |
200 | * is low. | 200 | * is low. |
201 | * | 201 | * |
202 | * When looking at page->index outside the page lock we need to be careful to | ||
203 | * copy it into a local to avoid races (it could change at any time). | ||
204 | * | ||
205 | * We pass down the cache-hot hint to the page freeing code. Even if the | 202 | * We pass down the cache-hot hint to the page freeing code. Even if the |
206 | * mapping is large, it is probably the case that the final pages are the most | 203 | * mapping is large, it is probably the case that the final pages are the most |
207 | * recently touched, and freeing happens in ascending file offset order. | 204 | * recently touched, and freeing happens in ascending file offset order. |
@@ -210,10 +207,10 @@ void truncate_inode_pages_range(struct address_space *mapping, | |||
210 | loff_t lstart, loff_t lend) | 207 | loff_t lstart, loff_t lend) |
211 | { | 208 | { |
212 | const pgoff_t start = (lstart + PAGE_CACHE_SIZE-1) >> PAGE_CACHE_SHIFT; | 209 | const pgoff_t start = (lstart + PAGE_CACHE_SIZE-1) >> PAGE_CACHE_SHIFT; |
213 | pgoff_t end; | ||
214 | const unsigned partial = lstart & (PAGE_CACHE_SIZE - 1); | 210 | const unsigned partial = lstart & (PAGE_CACHE_SIZE - 1); |
215 | struct pagevec pvec; | 211 | struct pagevec pvec; |
216 | pgoff_t next; | 212 | pgoff_t index; |
213 | pgoff_t end; | ||
217 | int i; | 214 | int i; |
218 | 215 | ||
219 | cleancache_flush_inode(mapping); | 216 | cleancache_flush_inode(mapping); |
@@ -224,24 +221,21 @@ void truncate_inode_pages_range(struct address_space *mapping, | |||
224 | end = (lend >> PAGE_CACHE_SHIFT); | 221 | end = (lend >> PAGE_CACHE_SHIFT); |
225 | 222 | ||
226 | pagevec_init(&pvec, 0); | 223 | pagevec_init(&pvec, 0); |
227 | next = start; | 224 | index = start; |
228 | while (next <= end && | 225 | while (index <= end && pagevec_lookup(&pvec, mapping, index, |
229 | pagevec_lookup(&pvec, mapping, next, PAGEVEC_SIZE)) { | 226 | min(end - index, (pgoff_t)PAGEVEC_SIZE - 1) + 1)) { |
230 | mem_cgroup_uncharge_start(); | 227 | mem_cgroup_uncharge_start(); |
231 | for (i = 0; i < pagevec_count(&pvec); i++) { | 228 | for (i = 0; i < pagevec_count(&pvec); i++) { |
232 | struct page *page = pvec.pages[i]; | 229 | struct page *page = pvec.pages[i]; |
233 | pgoff_t page_index = page->index; | ||
234 | 230 | ||
235 | if (page_index > end) { | 231 | /* We rely upon deletion not changing page->index */ |
236 | next = page_index; | 232 | index = page->index; |
233 | if (index > end) | ||
237 | break; | 234 | break; |
238 | } | ||
239 | 235 | ||
240 | if (page_index > next) | ||
241 | next = page_index; | ||
242 | next++; | ||
243 | if (!trylock_page(page)) | 236 | if (!trylock_page(page)) |
244 | continue; | 237 | continue; |
238 | WARN_ON(page->index != index); | ||
245 | if (PageWriteback(page)) { | 239 | if (PageWriteback(page)) { |
246 | unlock_page(page); | 240 | unlock_page(page); |
247 | continue; | 241 | continue; |
@@ -252,6 +246,7 @@ void truncate_inode_pages_range(struct address_space *mapping, | |||
252 | pagevec_release(&pvec); | 246 | pagevec_release(&pvec); |
253 | mem_cgroup_uncharge_end(); | 247 | mem_cgroup_uncharge_end(); |
254 | cond_resched(); | 248 | cond_resched(); |
249 | index++; | ||
255 | } | 250 | } |
256 | 251 | ||
257 | if (partial) { | 252 | if (partial) { |
@@ -264,16 +259,17 @@ void truncate_inode_pages_range(struct address_space *mapping, | |||
264 | } | 259 | } |
265 | } | 260 | } |
266 | 261 | ||
267 | next = start; | 262 | index = start; |
268 | for ( ; ; ) { | 263 | for ( ; ; ) { |
269 | cond_resched(); | 264 | cond_resched(); |
270 | if (!pagevec_lookup(&pvec, mapping, next, PAGEVEC_SIZE)) { | 265 | if (!pagevec_lookup(&pvec, mapping, index, |
271 | if (next == start) | 266 | min(end - index, (pgoff_t)PAGEVEC_SIZE - 1) + 1)) { |
267 | if (index == start) | ||
272 | break; | 268 | break; |
273 | next = start; | 269 | index = start; |
274 | continue; | 270 | continue; |
275 | } | 271 | } |
276 | if (pvec.pages[0]->index > end) { | 272 | if (index == start && pvec.pages[0]->index > end) { |
277 | pagevec_release(&pvec); | 273 | pagevec_release(&pvec); |
278 | break; | 274 | break; |
279 | } | 275 | } |
@@ -281,18 +277,20 @@ void truncate_inode_pages_range(struct address_space *mapping, | |||
281 | for (i = 0; i < pagevec_count(&pvec); i++) { | 277 | for (i = 0; i < pagevec_count(&pvec); i++) { |
282 | struct page *page = pvec.pages[i]; | 278 | struct page *page = pvec.pages[i]; |
283 | 279 | ||
284 | if (page->index > end) | 280 | /* We rely upon deletion not changing page->index */ |
281 | index = page->index; | ||
282 | if (index > end) | ||
285 | break; | 283 | break; |
284 | |||
286 | lock_page(page); | 285 | lock_page(page); |
286 | WARN_ON(page->index != index); | ||
287 | wait_on_page_writeback(page); | 287 | wait_on_page_writeback(page); |
288 | truncate_inode_page(mapping, page); | 288 | truncate_inode_page(mapping, page); |
289 | if (page->index > next) | ||
290 | next = page->index; | ||
291 | next++; | ||
292 | unlock_page(page); | 289 | unlock_page(page); |
293 | } | 290 | } |
294 | pagevec_release(&pvec); | 291 | pagevec_release(&pvec); |
295 | mem_cgroup_uncharge_end(); | 292 | mem_cgroup_uncharge_end(); |
293 | index++; | ||
296 | } | 294 | } |
297 | cleancache_flush_inode(mapping); | 295 | cleancache_flush_inode(mapping); |
298 | } | 296 | } |
@@ -333,35 +331,26 @@ unsigned long invalidate_mapping_pages(struct address_space *mapping, | |||
333 | pgoff_t start, pgoff_t end) | 331 | pgoff_t start, pgoff_t end) |
334 | { | 332 | { |
335 | struct pagevec pvec; | 333 | struct pagevec pvec; |
336 | pgoff_t next = start; | 334 | pgoff_t index = start; |
337 | unsigned long ret; | 335 | unsigned long ret; |
338 | unsigned long count = 0; | 336 | unsigned long count = 0; |
339 | int i; | 337 | int i; |
340 | 338 | ||
341 | pagevec_init(&pvec, 0); | 339 | pagevec_init(&pvec, 0); |
342 | while (next <= end && | 340 | while (index <= end && pagevec_lookup(&pvec, mapping, index, |
343 | pagevec_lookup(&pvec, mapping, next, PAGEVEC_SIZE)) { | 341 | min(end - index, (pgoff_t)PAGEVEC_SIZE - 1) + 1)) { |
344 | mem_cgroup_uncharge_start(); | 342 | mem_cgroup_uncharge_start(); |
345 | for (i = 0; i < pagevec_count(&pvec); i++) { | 343 | for (i = 0; i < pagevec_count(&pvec); i++) { |
346 | struct page *page = pvec.pages[i]; | 344 | struct page *page = pvec.pages[i]; |
347 | pgoff_t index; | ||
348 | int lock_failed; | ||
349 | |||
350 | lock_failed = !trylock_page(page); | ||
351 | 345 | ||
352 | /* | 346 | /* We rely upon deletion not changing page->index */ |
353 | * We really shouldn't be looking at the ->index of an | ||
354 | * unlocked page. But we're not allowed to lock these | ||
355 | * pages. So we rely upon nobody altering the ->index | ||
356 | * of this (pinned-by-us) page. | ||
357 | */ | ||
358 | index = page->index; | 347 | index = page->index; |
359 | if (index > next) | 348 | if (index > end) |
360 | next = index; | 349 | break; |
361 | next++; | ||
362 | if (lock_failed) | ||
363 | continue; | ||
364 | 350 | ||
351 | if (!trylock_page(page)) | ||
352 | continue; | ||
353 | WARN_ON(page->index != index); | ||
365 | ret = invalidate_inode_page(page); | 354 | ret = invalidate_inode_page(page); |
366 | unlock_page(page); | 355 | unlock_page(page); |
367 | /* | 356 | /* |
@@ -371,12 +360,11 @@ unsigned long invalidate_mapping_pages(struct address_space *mapping, | |||
371 | if (!ret) | 360 | if (!ret) |
372 | deactivate_page(page); | 361 | deactivate_page(page); |
373 | count += ret; | 362 | count += ret; |
374 | if (next > end) | ||
375 | break; | ||
376 | } | 363 | } |
377 | pagevec_release(&pvec); | 364 | pagevec_release(&pvec); |
378 | mem_cgroup_uncharge_end(); | 365 | mem_cgroup_uncharge_end(); |
379 | cond_resched(); | 366 | cond_resched(); |
367 | index++; | ||
380 | } | 368 | } |
381 | return count; | 369 | return count; |
382 | } | 370 | } |
@@ -442,37 +430,32 @@ int invalidate_inode_pages2_range(struct address_space *mapping, | |||
442 | pgoff_t start, pgoff_t end) | 430 | pgoff_t start, pgoff_t end) |
443 | { | 431 | { |
444 | struct pagevec pvec; | 432 | struct pagevec pvec; |
445 | pgoff_t next; | 433 | pgoff_t index; |
446 | int i; | 434 | int i; |
447 | int ret = 0; | 435 | int ret = 0; |
448 | int ret2 = 0; | 436 | int ret2 = 0; |
449 | int did_range_unmap = 0; | 437 | int did_range_unmap = 0; |
450 | int wrapped = 0; | ||
451 | 438 | ||
452 | cleancache_flush_inode(mapping); | 439 | cleancache_flush_inode(mapping); |
453 | pagevec_init(&pvec, 0); | 440 | pagevec_init(&pvec, 0); |
454 | next = start; | 441 | index = start; |
455 | while (next <= end && !wrapped && | 442 | while (index <= end && pagevec_lookup(&pvec, mapping, index, |
456 | pagevec_lookup(&pvec, mapping, next, | 443 | min(end - index, (pgoff_t)PAGEVEC_SIZE - 1) + 1)) { |
457 | min(end - next, (pgoff_t)PAGEVEC_SIZE - 1) + 1)) { | ||
458 | mem_cgroup_uncharge_start(); | 444 | mem_cgroup_uncharge_start(); |
459 | for (i = 0; i < pagevec_count(&pvec); i++) { | 445 | for (i = 0; i < pagevec_count(&pvec); i++) { |
460 | struct page *page = pvec.pages[i]; | 446 | struct page *page = pvec.pages[i]; |
461 | pgoff_t page_index; | 447 | |
448 | /* We rely upon deletion not changing page->index */ | ||
449 | index = page->index; | ||
450 | if (index > end) | ||
451 | break; | ||
462 | 452 | ||
463 | lock_page(page); | 453 | lock_page(page); |
454 | WARN_ON(page->index != index); | ||
464 | if (page->mapping != mapping) { | 455 | if (page->mapping != mapping) { |
465 | unlock_page(page); | 456 | unlock_page(page); |
466 | continue; | 457 | continue; |
467 | } | 458 | } |
468 | page_index = page->index; | ||
469 | next = page_index + 1; | ||
470 | if (next == 0) | ||
471 | wrapped = 1; | ||
472 | if (page_index > end) { | ||
473 | unlock_page(page); | ||
474 | break; | ||
475 | } | ||
476 | wait_on_page_writeback(page); | 459 | wait_on_page_writeback(page); |
477 | if (page_mapped(page)) { | 460 | if (page_mapped(page)) { |
478 | if (!did_range_unmap) { | 461 | if (!did_range_unmap) { |
@@ -480,9 +463,9 @@ int invalidate_inode_pages2_range(struct address_space *mapping, | |||
480 | * Zap the rest of the file in one hit. | 463 | * Zap the rest of the file in one hit. |
481 | */ | 464 | */ |
482 | unmap_mapping_range(mapping, | 465 | unmap_mapping_range(mapping, |
483 | (loff_t)page_index<<PAGE_CACHE_SHIFT, | 466 | (loff_t)index << PAGE_CACHE_SHIFT, |
484 | (loff_t)(end - page_index + 1) | 467 | (loff_t)(1 + end - index) |
485 | << PAGE_CACHE_SHIFT, | 468 | << PAGE_CACHE_SHIFT, |
486 | 0); | 469 | 0); |
487 | did_range_unmap = 1; | 470 | did_range_unmap = 1; |
488 | } else { | 471 | } else { |
@@ -490,8 +473,8 @@ int invalidate_inode_pages2_range(struct address_space *mapping, | |||
490 | * Just zap this page | 473 | * Just zap this page |
491 | */ | 474 | */ |
492 | unmap_mapping_range(mapping, | 475 | unmap_mapping_range(mapping, |
493 | (loff_t)page_index<<PAGE_CACHE_SHIFT, | 476 | (loff_t)index << PAGE_CACHE_SHIFT, |
494 | PAGE_CACHE_SIZE, 0); | 477 | PAGE_CACHE_SIZE, 0); |
495 | } | 478 | } |
496 | } | 479 | } |
497 | BUG_ON(page_mapped(page)); | 480 | BUG_ON(page_mapped(page)); |
@@ -507,6 +490,7 @@ int invalidate_inode_pages2_range(struct address_space *mapping, | |||
507 | pagevec_release(&pvec); | 490 | pagevec_release(&pvec); |
508 | mem_cgroup_uncharge_end(); | 491 | mem_cgroup_uncharge_end(); |
509 | cond_resched(); | 492 | cond_resched(); |
493 | index++; | ||
510 | } | 494 | } |
511 | cleancache_flush_inode(mapping); | 495 | cleancache_flush_inode(mapping); |
512 | return ret; | 496 | return ret; |
@@ -531,8 +515,8 @@ EXPORT_SYMBOL_GPL(invalidate_inode_pages2); | |||
531 | /** | 515 | /** |
532 | * truncate_pagecache - unmap and remove pagecache that has been truncated | 516 | * truncate_pagecache - unmap and remove pagecache that has been truncated |
533 | * @inode: inode | 517 | * @inode: inode |
534 | * @old: old file offset | 518 | * @oldsize: old file size |
535 | * @new: new file offset | 519 | * @newsize: new file size |
536 | * | 520 | * |
537 | * inode's new i_size must already be written before truncate_pagecache | 521 | * inode's new i_size must already be written before truncate_pagecache |
538 | * is called. | 522 | * is called. |
@@ -544,9 +528,10 @@ EXPORT_SYMBOL_GPL(invalidate_inode_pages2); | |||
544 | * situations such as writepage being called for a page that has already | 528 | * situations such as writepage being called for a page that has already |
545 | * had its underlying blocks deallocated. | 529 | * had its underlying blocks deallocated. |
546 | */ | 530 | */ |
547 | void truncate_pagecache(struct inode *inode, loff_t old, loff_t new) | 531 | void truncate_pagecache(struct inode *inode, loff_t oldsize, loff_t newsize) |
548 | { | 532 | { |
549 | struct address_space *mapping = inode->i_mapping; | 533 | struct address_space *mapping = inode->i_mapping; |
534 | loff_t holebegin = round_up(newsize, PAGE_SIZE); | ||
550 | 535 | ||
551 | /* | 536 | /* |
552 | * unmap_mapping_range is called twice, first simply for | 537 | * unmap_mapping_range is called twice, first simply for |
@@ -557,9 +542,9 @@ void truncate_pagecache(struct inode *inode, loff_t old, loff_t new) | |||
557 | * truncate_inode_pages finishes, hence the second | 542 | * truncate_inode_pages finishes, hence the second |
558 | * unmap_mapping_range call must be made for correctness. | 543 | * unmap_mapping_range call must be made for correctness. |
559 | */ | 544 | */ |
560 | unmap_mapping_range(mapping, new + PAGE_SIZE - 1, 0, 1); | 545 | unmap_mapping_range(mapping, holebegin, 0, 1); |
561 | truncate_inode_pages(mapping, new); | 546 | truncate_inode_pages(mapping, newsize); |
562 | unmap_mapping_range(mapping, new + PAGE_SIZE - 1, 0, 1); | 547 | unmap_mapping_range(mapping, holebegin, 0, 1); |
563 | } | 548 | } |
564 | EXPORT_SYMBOL(truncate_pagecache); | 549 | EXPORT_SYMBOL(truncate_pagecache); |
565 | 550 | ||
@@ -589,29 +574,31 @@ EXPORT_SYMBOL(truncate_setsize); | |||
589 | /** | 574 | /** |
590 | * vmtruncate - unmap mappings "freed" by truncate() syscall | 575 | * vmtruncate - unmap mappings "freed" by truncate() syscall |
591 | * @inode: inode of the file used | 576 | * @inode: inode of the file used |
592 | * @offset: file offset to start truncating | 577 | * @newsize: file offset to start truncating |
593 | * | 578 | * |
594 | * This function is deprecated and truncate_setsize or truncate_pagecache | 579 | * This function is deprecated and truncate_setsize or truncate_pagecache |
595 | * should be used instead, together with filesystem specific block truncation. | 580 | * should be used instead, together with filesystem specific block truncation. |
596 | */ | 581 | */ |
597 | int vmtruncate(struct inode *inode, loff_t offset) | 582 | int vmtruncate(struct inode *inode, loff_t newsize) |
598 | { | 583 | { |
599 | int error; | 584 | int error; |
600 | 585 | ||
601 | error = inode_newsize_ok(inode, offset); | 586 | error = inode_newsize_ok(inode, newsize); |
602 | if (error) | 587 | if (error) |
603 | return error; | 588 | return error; |
604 | 589 | ||
605 | truncate_setsize(inode, offset); | 590 | truncate_setsize(inode, newsize); |
606 | if (inode->i_op->truncate) | 591 | if (inode->i_op->truncate) |
607 | inode->i_op->truncate(inode); | 592 | inode->i_op->truncate(inode); |
608 | return 0; | 593 | return 0; |
609 | } | 594 | } |
610 | EXPORT_SYMBOL(vmtruncate); | 595 | EXPORT_SYMBOL(vmtruncate); |
611 | 596 | ||
612 | int vmtruncate_range(struct inode *inode, loff_t offset, loff_t end) | 597 | int vmtruncate_range(struct inode *inode, loff_t lstart, loff_t lend) |
613 | { | 598 | { |
614 | struct address_space *mapping = inode->i_mapping; | 599 | struct address_space *mapping = inode->i_mapping; |
600 | loff_t holebegin = round_up(lstart, PAGE_SIZE); | ||
601 | loff_t holelen = 1 + lend - holebegin; | ||
615 | 602 | ||
616 | /* | 603 | /* |
617 | * If the underlying filesystem is not going to provide | 604 | * If the underlying filesystem is not going to provide |
@@ -623,10 +610,10 @@ int vmtruncate_range(struct inode *inode, loff_t offset, loff_t end) | |||
623 | 610 | ||
624 | mutex_lock(&inode->i_mutex); | 611 | mutex_lock(&inode->i_mutex); |
625 | inode_dio_wait(inode); | 612 | inode_dio_wait(inode); |
626 | unmap_mapping_range(mapping, offset, (end - offset), 1); | 613 | unmap_mapping_range(mapping, holebegin, holelen, 1); |
627 | inode->i_op->truncate_range(inode, offset, end); | 614 | inode->i_op->truncate_range(inode, lstart, lend); |
628 | /* unmap again to remove racily COWed private pages */ | 615 | /* unmap again to remove racily COWed private pages */ |
629 | unmap_mapping_range(mapping, offset, (end - offset), 1); | 616 | unmap_mapping_range(mapping, holebegin, holelen, 1); |
630 | mutex_unlock(&inode->i_mutex); | 617 | mutex_unlock(&inode->i_mutex); |
631 | 618 | ||
632 | return 0; | 619 | return 0; |
diff --git a/net/rds/page.c b/net/rds/page.c index d8acdebe3c7c..b82d63e77b03 100644 --- a/net/rds/page.c +++ b/net/rds/page.c | |||
@@ -32,6 +32,7 @@ | |||
32 | */ | 32 | */ |
33 | #include <linux/highmem.h> | 33 | #include <linux/highmem.h> |
34 | #include <linux/gfp.h> | 34 | #include <linux/gfp.h> |
35 | #include <linux/cpu.h> | ||
35 | 36 | ||
36 | #include "rds.h" | 37 | #include "rds.h" |
37 | 38 | ||
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index b0aa2c680593..9d761c95eca2 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl | |||
@@ -10,7 +10,7 @@ use strict; | |||
10 | my $P = $0; | 10 | my $P = $0; |
11 | $P =~ s@.*/@@g; | 11 | $P =~ s@.*/@@g; |
12 | 12 | ||
13 | my $V = '0.31'; | 13 | my $V = '0.32'; |
14 | 14 | ||
15 | use Getopt::Long qw(:config no_auto_abbrev); | 15 | use Getopt::Long qw(:config no_auto_abbrev); |
16 | 16 | ||
@@ -26,9 +26,13 @@ my $check = 0; | |||
26 | my $summary = 1; | 26 | my $summary = 1; |
27 | my $mailback = 0; | 27 | my $mailback = 0; |
28 | my $summary_file = 0; | 28 | my $summary_file = 0; |
29 | my $show_types = 0; | ||
29 | my $root; | 30 | my $root; |
30 | my %debug; | 31 | my %debug; |
32 | my %ignore_type = (); | ||
33 | my @ignore = (); | ||
31 | my $help = 0; | 34 | my $help = 0; |
35 | my $configuration_file = ".checkpatch.conf"; | ||
32 | 36 | ||
33 | sub help { | 37 | sub help { |
34 | my ($exitcode) = @_; | 38 | my ($exitcode) = @_; |
@@ -46,6 +50,8 @@ Options: | |||
46 | --terse one line per report | 50 | --terse one line per report |
47 | -f, --file treat FILE as regular source file | 51 | -f, --file treat FILE as regular source file |
48 | --subjective, --strict enable more subjective tests | 52 | --subjective, --strict enable more subjective tests |
53 | --ignore TYPE(,TYPE2...) ignore various comma separated message types | ||
54 | --show-types show the message "types" in the output | ||
49 | --root=PATH PATH to the kernel tree root | 55 | --root=PATH PATH to the kernel tree root |
50 | --no-summary suppress the per-file summary | 56 | --no-summary suppress the per-file summary |
51 | --mailback only produce a report in case of warnings/errors | 57 | --mailback only produce a report in case of warnings/errors |
@@ -63,6 +69,32 @@ EOM | |||
63 | exit($exitcode); | 69 | exit($exitcode); |
64 | } | 70 | } |
65 | 71 | ||
72 | my $conf = which_conf($configuration_file); | ||
73 | if (-f $conf) { | ||
74 | my @conf_args; | ||
75 | open(my $conffile, '<', "$conf") | ||
76 | or warn "$P: Can't find a readable $configuration_file file $!\n"; | ||
77 | |||
78 | while (<$conffile>) { | ||
79 | my $line = $_; | ||
80 | |||
81 | $line =~ s/\s*\n?$//g; | ||
82 | $line =~ s/^\s*//g; | ||
83 | $line =~ s/\s+/ /g; | ||
84 | |||
85 | next if ($line =~ m/^\s*#/); | ||
86 | next if ($line =~ m/^\s*$/); | ||
87 | |||
88 | my @words = split(" ", $line); | ||
89 | foreach my $word (@words) { | ||
90 | last if ($word =~ m/^#/); | ||
91 | push (@conf_args, $word); | ||
92 | } | ||
93 | } | ||
94 | close($conffile); | ||
95 | unshift(@ARGV, @conf_args) if @conf_args; | ||
96 | } | ||
97 | |||
66 | GetOptions( | 98 | GetOptions( |
67 | 'q|quiet+' => \$quiet, | 99 | 'q|quiet+' => \$quiet, |
68 | 'tree!' => \$tree, | 100 | 'tree!' => \$tree, |
@@ -73,6 +105,8 @@ GetOptions( | |||
73 | 'f|file!' => \$file, | 105 | 'f|file!' => \$file, |
74 | 'subjective!' => \$check, | 106 | 'subjective!' => \$check, |
75 | 'strict!' => \$check, | 107 | 'strict!' => \$check, |
108 | 'ignore=s' => \@ignore, | ||
109 | 'show-types!' => \$show_types, | ||
76 | 'root=s' => \$root, | 110 | 'root=s' => \$root, |
77 | 'summary!' => \$summary, | 111 | 'summary!' => \$summary, |
78 | 'mailback!' => \$mailback, | 112 | 'mailback!' => \$mailback, |
@@ -93,6 +127,19 @@ if ($#ARGV < 0) { | |||
93 | exit(1); | 127 | exit(1); |
94 | } | 128 | } |
95 | 129 | ||
130 | @ignore = split(/,/, join(',',@ignore)); | ||
131 | foreach my $word (@ignore) { | ||
132 | $word =~ s/\s*\n?$//g; | ||
133 | $word =~ s/^\s*//g; | ||
134 | $word =~ s/\s+/ /g; | ||
135 | $word =~ tr/[a-z]/[A-Z]/; | ||
136 | |||
137 | next if ($word =~ m/^\s*#/); | ||
138 | next if ($word =~ m/^\s*$/); | ||
139 | |||
140 | $ignore_type{$word}++; | ||
141 | } | ||
142 | |||
96 | my $dbg_values = 0; | 143 | my $dbg_values = 0; |
97 | my $dbg_possible = 0; | 144 | my $dbg_possible = 0; |
98 | my $dbg_type = 0; | 145 | my $dbg_type = 0; |
@@ -145,7 +192,8 @@ our $Sparse = qr{ | |||
145 | __must_check| | 192 | __must_check| |
146 | __init_refok| | 193 | __init_refok| |
147 | __kprobes| | 194 | __kprobes| |
148 | __ref | 195 | __ref| |
196 | __rcu | ||
149 | }x; | 197 | }x; |
150 | 198 | ||
151 | # Notes to $Attribute: | 199 | # Notes to $Attribute: |
@@ -209,13 +257,23 @@ our $typeTypedefs = qr{(?x: | |||
209 | )}; | 257 | )}; |
210 | 258 | ||
211 | our $logFunctions = qr{(?x: | 259 | our $logFunctions = qr{(?x: |
212 | printk| | 260 | printk(?:_ratelimited|_once|)| |
213 | [a-z]+_(emerg|alert|crit|err|warning|warn|notice|info|debug|dbg|vdbg|devel|cont|WARN)| | 261 | [a-z0-9]+_(?:printk|emerg|alert|crit|err|warning|warn|notice|info|debug|dbg|vdbg|devel|cont|WARN)(?:_ratelimited|_once|)| |
214 | WARN| | 262 | WARN(?:_RATELIMIT|_ONCE|)| |
215 | panic| | 263 | panic| |
216 | MODULE_[A-Z_]+ | 264 | MODULE_[A-Z_]+ |
217 | )}; | 265 | )}; |
218 | 266 | ||
267 | our $signature_tags = qr{(?xi: | ||
268 | Signed-off-by:| | ||
269 | Acked-by:| | ||
270 | Tested-by:| | ||
271 | Reviewed-by:| | ||
272 | Reported-by:| | ||
273 | To:| | ||
274 | Cc: | ||
275 | )}; | ||
276 | |||
219 | our @typeList = ( | 277 | our @typeList = ( |
220 | qr{void}, | 278 | qr{void}, |
221 | qr{(?:unsigned\s+)?char}, | 279 | qr{(?:unsigned\s+)?char}, |
@@ -268,6 +326,20 @@ sub build_types { | |||
268 | } | 326 | } |
269 | build_types(); | 327 | build_types(); |
270 | 328 | ||
329 | our $match_balanced_parentheses = qr/(\((?:[^\(\)]+|(-1))*\))/; | ||
330 | |||
331 | our $Typecast = qr{\s*(\(\s*$NonptrType\s*\)){0,1}\s*}; | ||
332 | our $LvalOrFunc = qr{($Lval)\s*($match_balanced_parentheses{0,1})\s*}; | ||
333 | |||
334 | sub deparenthesize { | ||
335 | my ($string) = @_; | ||
336 | return "" if (!defined($string)); | ||
337 | $string =~ s@^\s*\(\s*@@g; | ||
338 | $string =~ s@\s*\)\s*$@@g; | ||
339 | $string =~ s@\s+@ @g; | ||
340 | return $string; | ||
341 | } | ||
342 | |||
271 | $chk_signoff = 0 if ($file); | 343 | $chk_signoff = 0 if ($file); |
272 | 344 | ||
273 | my @dep_includes = (); | 345 | my @dep_includes = (); |
@@ -339,6 +411,88 @@ sub top_of_kernel_tree { | |||
339 | } | 411 | } |
340 | } | 412 | } |
341 | return 1; | 413 | return 1; |
414 | } | ||
415 | |||
416 | sub parse_email { | ||
417 | my ($formatted_email) = @_; | ||
418 | |||
419 | my $name = ""; | ||
420 | my $address = ""; | ||
421 | my $comment = ""; | ||
422 | |||
423 | if ($formatted_email =~ /^(.*)<(\S+\@\S+)>(.*)$/) { | ||
424 | $name = $1; | ||
425 | $address = $2; | ||
426 | $comment = $3 if defined $3; | ||
427 | } elsif ($formatted_email =~ /^\s*<(\S+\@\S+)>(.*)$/) { | ||
428 | $address = $1; | ||
429 | $comment = $2 if defined $2; | ||
430 | } elsif ($formatted_email =~ /(\S+\@\S+)(.*)$/) { | ||
431 | $address = $1; | ||
432 | $comment = $2 if defined $2; | ||
433 | $formatted_email =~ s/$address.*$//; | ||
434 | $name = $formatted_email; | ||
435 | $name =~ s/^\s+|\s+$//g; | ||
436 | $name =~ s/^\"|\"$//g; | ||
437 | # If there's a name left after stripping spaces and | ||
438 | # leading quotes, and the address doesn't have both | ||
439 | # leading and trailing angle brackets, the address | ||
440 | # is invalid. ie: | ||
441 | # "joe smith joe@smith.com" bad | ||
442 | # "joe smith <joe@smith.com" bad | ||
443 | if ($name ne "" && $address !~ /^<[^>]+>$/) { | ||
444 | $name = ""; | ||
445 | $address = ""; | ||
446 | $comment = ""; | ||
447 | } | ||
448 | } | ||
449 | |||
450 | $name =~ s/^\s+|\s+$//g; | ||
451 | $name =~ s/^\"|\"$//g; | ||
452 | $address =~ s/^\s+|\s+$//g; | ||
453 | $address =~ s/^\<|\>$//g; | ||
454 | |||
455 | if ($name =~ /[^\w \-]/i) { ##has "must quote" chars | ||
456 | $name =~ s/(?<!\\)"/\\"/g; ##escape quotes | ||
457 | $name = "\"$name\""; | ||
458 | } | ||
459 | |||
460 | return ($name, $address, $comment); | ||
461 | } | ||
462 | |||
463 | sub format_email { | ||
464 | my ($name, $address) = @_; | ||
465 | |||
466 | my $formatted_email; | ||
467 | |||
468 | $name =~ s/^\s+|\s+$//g; | ||
469 | $name =~ s/^\"|\"$//g; | ||
470 | $address =~ s/^\s+|\s+$//g; | ||
471 | |||
472 | if ($name =~ /[^\w \-]/i) { ##has "must quote" chars | ||
473 | $name =~ s/(?<!\\)"/\\"/g; ##escape quotes | ||
474 | $name = "\"$name\""; | ||
475 | } | ||
476 | |||
477 | if ("$name" eq "") { | ||
478 | $formatted_email = "$address"; | ||
479 | } else { | ||
480 | $formatted_email = "$name <$address>"; | ||
481 | } | ||
482 | |||
483 | return $formatted_email; | ||
484 | } | ||
485 | |||
486 | sub which_conf { | ||
487 | my ($conf) = @_; | ||
488 | |||
489 | foreach my $path (split(/:/, ".:$ENV{HOME}:.scripts")) { | ||
490 | if (-e "$path/$conf") { | ||
491 | return "$path/$conf"; | ||
492 | } | ||
493 | } | ||
494 | |||
495 | return ""; | ||
342 | } | 496 | } |
343 | 497 | ||
344 | sub expand_tabs { | 498 | sub expand_tabs { |
@@ -1086,12 +1240,21 @@ sub possible { | |||
1086 | 1240 | ||
1087 | my $prefix = ''; | 1241 | my $prefix = ''; |
1088 | 1242 | ||
1243 | sub show_type { | ||
1244 | return !defined $ignore_type{$_[0]}; | ||
1245 | } | ||
1246 | |||
1089 | sub report { | 1247 | sub report { |
1090 | if (defined $tst_only && $_[0] !~ /\Q$tst_only\E/) { | 1248 | if (!show_type($_[1]) || |
1249 | (defined $tst_only && $_[2] !~ /\Q$tst_only\E/)) { | ||
1091 | return 0; | 1250 | return 0; |
1092 | } | 1251 | } |
1093 | my $line = $prefix . $_[0]; | 1252 | my $line; |
1094 | 1253 | if ($show_types) { | |
1254 | $line = "$prefix$_[0]:$_[1]: $_[2]\n"; | ||
1255 | } else { | ||
1256 | $line = "$prefix$_[0]: $_[2]\n"; | ||
1257 | } | ||
1095 | $line = (split('\n', $line))[0] . "\n" if ($terse); | 1258 | $line = (split('\n', $line))[0] . "\n" if ($terse); |
1096 | 1259 | ||
1097 | push(our @report, $line); | 1260 | push(our @report, $line); |
@@ -1101,20 +1264,21 @@ sub report { | |||
1101 | sub report_dump { | 1264 | sub report_dump { |
1102 | our @report; | 1265 | our @report; |
1103 | } | 1266 | } |
1267 | |||
1104 | sub ERROR { | 1268 | sub ERROR { |
1105 | if (report("ERROR: $_[0]\n")) { | 1269 | if (report("ERROR", $_[0], $_[1])) { |
1106 | our $clean = 0; | 1270 | our $clean = 0; |
1107 | our $cnt_error++; | 1271 | our $cnt_error++; |
1108 | } | 1272 | } |
1109 | } | 1273 | } |
1110 | sub WARN { | 1274 | sub WARN { |
1111 | if (report("WARNING: $_[0]\n")) { | 1275 | if (report("WARNING", $_[0], $_[1])) { |
1112 | our $clean = 0; | 1276 | our $clean = 0; |
1113 | our $cnt_warn++; | 1277 | our $cnt_warn++; |
1114 | } | 1278 | } |
1115 | } | 1279 | } |
1116 | sub CHK { | 1280 | sub CHK { |
1117 | if ($check && report("CHECK: $_[0]\n")) { | 1281 | if ($check && report("CHECK", $_[0], $_[1])) { |
1118 | our $clean = 0; | 1282 | our $clean = 0; |
1119 | our $cnt_chk++; | 1283 | our $cnt_chk++; |
1120 | } | 1284 | } |
@@ -1143,7 +1307,8 @@ sub check_absolute_file { | |||
1143 | 1307 | ||
1144 | ##print "prefix<$prefix>\n"; | 1308 | ##print "prefix<$prefix>\n"; |
1145 | if ($prefix ne ".../") { | 1309 | if ($prefix ne ".../") { |
1146 | WARN("use relative pathname instead of absolute in changelog text\n" . $herecurr); | 1310 | WARN("USE_RELATIVE_PATH", |
1311 | "use relative pathname instead of absolute in changelog text\n" . $herecurr); | ||
1147 | } | 1312 | } |
1148 | } | 1313 | } |
1149 | 1314 | ||
@@ -1340,11 +1505,13 @@ sub process { | |||
1340 | $p1_prefix = $1; | 1505 | $p1_prefix = $1; |
1341 | if (!$file && $tree && $p1_prefix ne '' && | 1506 | if (!$file && $tree && $p1_prefix ne '' && |
1342 | -e "$root/$p1_prefix") { | 1507 | -e "$root/$p1_prefix") { |
1343 | WARN("patch prefix '$p1_prefix' exists, appears to be a -p0 patch\n"); | 1508 | WARN("PATCH_PREFIX", |
1509 | "patch prefix '$p1_prefix' exists, appears to be a -p0 patch\n"); | ||
1344 | } | 1510 | } |
1345 | 1511 | ||
1346 | if ($realfile =~ m@^include/asm/@) { | 1512 | if ($realfile =~ m@^include/asm/@) { |
1347 | ERROR("do not modify files in include/asm, change architecture specific files in include/asm-<architecture>\n" . "$here$rawline\n"); | 1513 | ERROR("MODIFIED_INCLUDE_ASM", |
1514 | "do not modify files in include/asm, change architecture specific files in include/asm-<architecture>\n" . "$here$rawline\n"); | ||
1348 | } | 1515 | } |
1349 | next; | 1516 | next; |
1350 | } | 1517 | } |
@@ -1361,27 +1528,61 @@ sub process { | |||
1361 | if ($line =~ /^new (file )?mode.*[7531]\d{0,2}$/) { | 1528 | if ($line =~ /^new (file )?mode.*[7531]\d{0,2}$/) { |
1362 | my $permhere = $here . "FILE: $realfile\n"; | 1529 | my $permhere = $here . "FILE: $realfile\n"; |
1363 | if ($realfile =~ /(Makefile|Kconfig|\.c|\.h|\.S|\.tmpl)$/) { | 1530 | if ($realfile =~ /(Makefile|Kconfig|\.c|\.h|\.S|\.tmpl)$/) { |
1364 | ERROR("do not set execute permissions for source files\n" . $permhere); | 1531 | ERROR("EXECUTE_PERMISSIONS", |
1532 | "do not set execute permissions for source files\n" . $permhere); | ||
1365 | } | 1533 | } |
1366 | } | 1534 | } |
1367 | 1535 | ||
1368 | #check the patch for a signoff: | 1536 | # Check the patch for a signoff: |
1369 | if ($line =~ /^\s*signed-off-by:/i) { | 1537 | if ($line =~ /^\s*signed-off-by:/i) { |
1370 | # This is a signoff, if ugly, so do not double report. | ||
1371 | $signoff++; | 1538 | $signoff++; |
1372 | if (!($line =~ /^\s*Signed-off-by:/)) { | 1539 | } |
1373 | WARN("Signed-off-by: is the preferred form\n" . | 1540 | |
1374 | $herecurr); | 1541 | # Check signature styles |
1542 | if ($line =~ /^(\s*)($signature_tags)(\s*)(.*)/) { | ||
1543 | my $space_before = $1; | ||
1544 | my $sign_off = $2; | ||
1545 | my $space_after = $3; | ||
1546 | my $email = $4; | ||
1547 | my $ucfirst_sign_off = ucfirst(lc($sign_off)); | ||
1548 | |||
1549 | if (defined $space_before && $space_before ne "") { | ||
1550 | WARN("BAD_SIGN_OFF", | ||
1551 | "Do not use whitespace before $ucfirst_sign_off\n" . $herecurr); | ||
1375 | } | 1552 | } |
1376 | if ($line =~ /^\s*signed-off-by:\S/i) { | 1553 | if ($sign_off =~ /-by:$/i && $sign_off ne $ucfirst_sign_off) { |
1377 | WARN("space required after Signed-off-by:\n" . | 1554 | WARN("BAD_SIGN_OFF", |
1378 | $herecurr); | 1555 | "'$ucfirst_sign_off' is the preferred signature form\n" . $herecurr); |
1556 | } | ||
1557 | if (!defined $space_after || $space_after ne " ") { | ||
1558 | WARN("BAD_SIGN_OFF", | ||
1559 | "Use a single space after $ucfirst_sign_off\n" . $herecurr); | ||
1560 | } | ||
1561 | |||
1562 | my ($email_name, $email_address, $comment) = parse_email($email); | ||
1563 | my $suggested_email = format_email(($email_name, $email_address)); | ||
1564 | if ($suggested_email eq "") { | ||
1565 | ERROR("BAD_SIGN_OFF", | ||
1566 | "Unrecognized email address: '$email'\n" . $herecurr); | ||
1567 | } else { | ||
1568 | my $dequoted = $suggested_email; | ||
1569 | $dequoted =~ s/^"//; | ||
1570 | $dequoted =~ s/" </ </; | ||
1571 | # Don't force email to have quotes | ||
1572 | # Allow just an angle bracketed address | ||
1573 | if ("$dequoted$comment" ne $email && | ||
1574 | "<$email_address>$comment" ne $email && | ||
1575 | "$suggested_email$comment" ne $email) { | ||
1576 | WARN("BAD_SIGN_OFF", | ||
1577 | "email address '$email' might be better as '$suggested_email$comment'\n" . $herecurr); | ||
1578 | } | ||
1379 | } | 1579 | } |
1380 | } | 1580 | } |
1381 | 1581 | ||
1382 | # Check for wrappage within a valid hunk of the file | 1582 | # Check for wrappage within a valid hunk of the file |
1383 | if ($realcnt != 0 && $line !~ m{^(?:\+|-| |\\ No newline|$)}) { | 1583 | if ($realcnt != 0 && $line !~ m{^(?:\+|-| |\\ No newline|$)}) { |
1384 | ERROR("patch seems to be corrupt (line wrapped?)\n" . | 1584 | ERROR("CORRUPTED_PATCH", |
1585 | "patch seems to be corrupt (line wrapped?)\n" . | ||
1385 | $herecurr) if (!$emitted_corrupt++); | 1586 | $herecurr) if (!$emitted_corrupt++); |
1386 | } | 1587 | } |
1387 | 1588 | ||
@@ -1408,7 +1609,8 @@ sub process { | |||
1408 | my $ptr = substr($blank, 0, length($utf8_prefix)) . "^"; | 1609 | my $ptr = substr($blank, 0, length($utf8_prefix)) . "^"; |
1409 | my $hereptr = "$hereline$ptr\n"; | 1610 | my $hereptr = "$hereline$ptr\n"; |
1410 | 1611 | ||
1411 | ERROR("Invalid UTF-8, patch and commit message should be encoded in UTF-8\n" . $hereptr); | 1612 | CHK("INVALID_UTF8", |
1613 | "Invalid UTF-8, patch and commit message should be encoded in UTF-8\n" . $hereptr); | ||
1412 | } | 1614 | } |
1413 | 1615 | ||
1414 | # ignore non-hunk lines and lines being removed | 1616 | # ignore non-hunk lines and lines being removed |
@@ -1417,11 +1619,13 @@ sub process { | |||
1417 | #trailing whitespace | 1619 | #trailing whitespace |
1418 | if ($line =~ /^\+.*\015/) { | 1620 | if ($line =~ /^\+.*\015/) { |
1419 | my $herevet = "$here\n" . cat_vet($rawline) . "\n"; | 1621 | my $herevet = "$here\n" . cat_vet($rawline) . "\n"; |
1420 | ERROR("DOS line endings\n" . $herevet); | 1622 | ERROR("DOS_LINE_ENDINGS", |
1623 | "DOS line endings\n" . $herevet); | ||
1421 | 1624 | ||
1422 | } elsif ($rawline =~ /^\+.*\S\s+$/ || $rawline =~ /^\+\s+$/) { | 1625 | } elsif ($rawline =~ /^\+.*\S\s+$/ || $rawline =~ /^\+\s+$/) { |
1423 | my $herevet = "$here\n" . cat_vet($rawline) . "\n"; | 1626 | my $herevet = "$here\n" . cat_vet($rawline) . "\n"; |
1424 | ERROR("trailing whitespace\n" . $herevet); | 1627 | ERROR("TRAILING_WHITESPACE", |
1628 | "trailing whitespace\n" . $herevet); | ||
1425 | $rpt_cleaners = 1; | 1629 | $rpt_cleaners = 1; |
1426 | } | 1630 | } |
1427 | 1631 | ||
@@ -1452,7 +1656,8 @@ sub process { | |||
1452 | } | 1656 | } |
1453 | $length++; | 1657 | $length++; |
1454 | } | 1658 | } |
1455 | WARN("please write a paragraph that describes the config symbol fully\n" . $herecurr) if ($is_end && $length < 4); | 1659 | WARN("CONFIG_DESCRIPTION", |
1660 | "please write a paragraph that describes the config symbol fully\n" . $herecurr) if ($is_end && $length < 4); | ||
1456 | #print "is_end<$is_end> length<$length>\n"; | 1661 | #print "is_end<$is_end> length<$length>\n"; |
1457 | } | 1662 | } |
1458 | 1663 | ||
@@ -1466,28 +1671,33 @@ sub process { | |||
1466 | $line =~ /^\+\s*"[^"]*"\s*(?:\s*|,|\)\s*;)\s*$/) && | 1671 | $line =~ /^\+\s*"[^"]*"\s*(?:\s*|,|\)\s*;)\s*$/) && |
1467 | $length > 80) | 1672 | $length > 80) |
1468 | { | 1673 | { |
1469 | WARN("line over 80 characters\n" . $herecurr); | 1674 | WARN("LONG_LINE", |
1675 | "line over 80 characters\n" . $herecurr); | ||
1470 | } | 1676 | } |
1471 | 1677 | ||
1472 | # check for spaces before a quoted newline | 1678 | # check for spaces before a quoted newline |
1473 | if ($rawline =~ /^.*\".*\s\\n/) { | 1679 | if ($rawline =~ /^.*\".*\s\\n/) { |
1474 | WARN("unnecessary whitespace before a quoted newline\n" . $herecurr); | 1680 | WARN("QUOTED_WHITESPACE_BEFORE_NEWLINE", |
1681 | "unnecessary whitespace before a quoted newline\n" . $herecurr); | ||
1475 | } | 1682 | } |
1476 | 1683 | ||
1477 | # check for adding lines without a newline. | 1684 | # check for adding lines without a newline. |
1478 | if ($line =~ /^\+/ && defined $lines[$linenr] && $lines[$linenr] =~ /^\\ No newline at end of file/) { | 1685 | if ($line =~ /^\+/ && defined $lines[$linenr] && $lines[$linenr] =~ /^\\ No newline at end of file/) { |
1479 | WARN("adding a line without newline at end of file\n" . $herecurr); | 1686 | WARN("MISSING_EOF_NEWLINE", |
1687 | "adding a line without newline at end of file\n" . $herecurr); | ||
1480 | } | 1688 | } |
1481 | 1689 | ||
1482 | # Blackfin: use hi/lo macros | 1690 | # Blackfin: use hi/lo macros |
1483 | if ($realfile =~ m@arch/blackfin/.*\.S$@) { | 1691 | if ($realfile =~ m@arch/blackfin/.*\.S$@) { |
1484 | if ($line =~ /\.[lL][[:space:]]*=.*&[[:space:]]*0x[fF][fF][fF][fF]/) { | 1692 | if ($line =~ /\.[lL][[:space:]]*=.*&[[:space:]]*0x[fF][fF][fF][fF]/) { |
1485 | my $herevet = "$here\n" . cat_vet($line) . "\n"; | 1693 | my $herevet = "$here\n" . cat_vet($line) . "\n"; |
1486 | ERROR("use the LO() macro, not (... & 0xFFFF)\n" . $herevet); | 1694 | ERROR("LO_MACRO", |
1695 | "use the LO() macro, not (... & 0xFFFF)\n" . $herevet); | ||
1487 | } | 1696 | } |
1488 | if ($line =~ /\.[hH][[:space:]]*=.*>>[[:space:]]*16/) { | 1697 | if ($line =~ /\.[hH][[:space:]]*=.*>>[[:space:]]*16/) { |
1489 | my $herevet = "$here\n" . cat_vet($line) . "\n"; | 1698 | my $herevet = "$here\n" . cat_vet($line) . "\n"; |
1490 | ERROR("use the HI() macro, not (... >> 16)\n" . $herevet); | 1699 | ERROR("HI_MACRO", |
1700 | "use the HI() macro, not (... >> 16)\n" . $herevet); | ||
1491 | } | 1701 | } |
1492 | } | 1702 | } |
1493 | 1703 | ||
@@ -1499,14 +1709,16 @@ sub process { | |||
1499 | if ($rawline =~ /^\+\s* \t\s*\S/ || | 1709 | if ($rawline =~ /^\+\s* \t\s*\S/ || |
1500 | $rawline =~ /^\+\s* \s*/) { | 1710 | $rawline =~ /^\+\s* \s*/) { |
1501 | my $herevet = "$here\n" . cat_vet($rawline) . "\n"; | 1711 | my $herevet = "$here\n" . cat_vet($rawline) . "\n"; |
1502 | ERROR("code indent should use tabs where possible\n" . $herevet); | 1712 | ERROR("CODE_INDENT", |
1713 | "code indent should use tabs where possible\n" . $herevet); | ||
1503 | $rpt_cleaners = 1; | 1714 | $rpt_cleaners = 1; |
1504 | } | 1715 | } |
1505 | 1716 | ||
1506 | # check for space before tabs. | 1717 | # check for space before tabs. |
1507 | if ($rawline =~ /^\+/ && $rawline =~ / \t/) { | 1718 | if ($rawline =~ /^\+/ && $rawline =~ / \t/) { |
1508 | my $herevet = "$here\n" . cat_vet($rawline) . "\n"; | 1719 | my $herevet = "$here\n" . cat_vet($rawline) . "\n"; |
1509 | WARN("please, no space before tabs\n" . $herevet); | 1720 | WARN("SPACE_BEFORE_TAB", |
1721 | "please, no space before tabs\n" . $herevet); | ||
1510 | } | 1722 | } |
1511 | 1723 | ||
1512 | # check for spaces at the beginning of a line. | 1724 | # check for spaces at the beginning of a line. |
@@ -1516,7 +1728,8 @@ sub process { | |||
1516 | # 3) hanging labels | 1728 | # 3) hanging labels |
1517 | if ($rawline =~ /^\+ / && $line !~ /\+ *(?:$;|#|$Ident:)/) { | 1729 | if ($rawline =~ /^\+ / && $line !~ /\+ *(?:$;|#|$Ident:)/) { |
1518 | my $herevet = "$here\n" . cat_vet($rawline) . "\n"; | 1730 | my $herevet = "$here\n" . cat_vet($rawline) . "\n"; |
1519 | WARN("please, no spaces at the start of a line\n" . $herevet); | 1731 | WARN("LEADING_SPACE", |
1732 | "please, no spaces at the start of a line\n" . $herevet); | ||
1520 | } | 1733 | } |
1521 | 1734 | ||
1522 | # check we are in a valid C source file if not then ignore this hunk | 1735 | # check we are in a valid C source file if not then ignore this hunk |
@@ -1524,17 +1737,20 @@ sub process { | |||
1524 | 1737 | ||
1525 | # check for RCS/CVS revision markers | 1738 | # check for RCS/CVS revision markers |
1526 | if ($rawline =~ /^\+.*\$(Revision|Log|Id)(?:\$|)/) { | 1739 | if ($rawline =~ /^\+.*\$(Revision|Log|Id)(?:\$|)/) { |
1527 | WARN("CVS style keyword markers, these will _not_ be updated\n". $herecurr); | 1740 | WARN("CVS_KEYWORD", |
1741 | "CVS style keyword markers, these will _not_ be updated\n". $herecurr); | ||
1528 | } | 1742 | } |
1529 | 1743 | ||
1530 | # Blackfin: don't use __builtin_bfin_[cs]sync | 1744 | # Blackfin: don't use __builtin_bfin_[cs]sync |
1531 | if ($line =~ /__builtin_bfin_csync/) { | 1745 | if ($line =~ /__builtin_bfin_csync/) { |
1532 | my $herevet = "$here\n" . cat_vet($line) . "\n"; | 1746 | my $herevet = "$here\n" . cat_vet($line) . "\n"; |
1533 | ERROR("use the CSYNC() macro in asm/blackfin.h\n" . $herevet); | 1747 | ERROR("CSYNC", |
1748 | "use the CSYNC() macro in asm/blackfin.h\n" . $herevet); | ||
1534 | } | 1749 | } |
1535 | if ($line =~ /__builtin_bfin_ssync/) { | 1750 | if ($line =~ /__builtin_bfin_ssync/) { |
1536 | my $herevet = "$here\n" . cat_vet($line) . "\n"; | 1751 | my $herevet = "$here\n" . cat_vet($line) . "\n"; |
1537 | ERROR("use the SSYNC() macro in asm/blackfin.h\n" . $herevet); | 1752 | ERROR("SSYNC", |
1753 | "use the SSYNC() macro in asm/blackfin.h\n" . $herevet); | ||
1538 | } | 1754 | } |
1539 | 1755 | ||
1540 | # Check for potential 'bare' types | 1756 | # Check for potential 'bare' types |
@@ -1623,7 +1839,8 @@ sub process { | |||
1623 | } | 1839 | } |
1624 | } | 1840 | } |
1625 | if ($err ne '') { | 1841 | if ($err ne '') { |
1626 | ERROR("switch and case should be at the same indent\n$hereline$err"); | 1842 | ERROR("SWITCH_CASE_INDENT_LEVEL", |
1843 | "switch and case should be at the same indent\n$hereline$err"); | ||
1627 | } | 1844 | } |
1628 | } | 1845 | } |
1629 | 1846 | ||
@@ -1651,7 +1868,8 @@ sub process { | |||
1651 | #print "pre<$pre_ctx>\nline<$line>\nctx<$ctx>\nnext<$lines[$ctx_ln - 1]>\n"; | 1868 | #print "pre<$pre_ctx>\nline<$line>\nctx<$ctx>\nnext<$lines[$ctx_ln - 1]>\n"; |
1652 | 1869 | ||
1653 | if ($ctx !~ /{\s*/ && defined($lines[$ctx_ln -1]) && $lines[$ctx_ln - 1] =~ /^\+\s*{/) { | 1870 | if ($ctx !~ /{\s*/ && defined($lines[$ctx_ln -1]) && $lines[$ctx_ln - 1] =~ /^\+\s*{/) { |
1654 | ERROR("that open brace { should be on the previous line\n" . | 1871 | ERROR("OPEN_BRACE", |
1872 | "that open brace { should be on the previous line\n" . | ||
1655 | "$here\n$ctx\n$rawlines[$ctx_ln - 1]\n"); | 1873 | "$here\n$ctx\n$rawlines[$ctx_ln - 1]\n"); |
1656 | } | 1874 | } |
1657 | if ($level == 0 && $pre_ctx !~ /}\s*while\s*\($/ && | 1875 | if ($level == 0 && $pre_ctx !~ /}\s*while\s*\($/ && |
@@ -1660,7 +1878,8 @@ sub process { | |||
1660 | { | 1878 | { |
1661 | my ($nlength, $nindent) = line_stats($lines[$ctx_ln - 1]); | 1879 | my ($nlength, $nindent) = line_stats($lines[$ctx_ln - 1]); |
1662 | if ($nindent > $indent) { | 1880 | if ($nindent > $indent) { |
1663 | WARN("trailing semicolon indicates no statements, indent implies otherwise\n" . | 1881 | WARN("TRAILING_SEMICOLON", |
1882 | "trailing semicolon indicates no statements, indent implies otherwise\n" . | ||
1664 | "$here\n$ctx\n$rawlines[$ctx_ln - 1]\n"); | 1883 | "$here\n$ctx\n$rawlines[$ctx_ln - 1]\n"); |
1665 | } | 1884 | } |
1666 | } | 1885 | } |
@@ -1748,7 +1967,8 @@ sub process { | |||
1748 | 1967 | ||
1749 | if ($check && (($sindent % 8) != 0 || | 1968 | if ($check && (($sindent % 8) != 0 || |
1750 | ($sindent <= $indent && $s ne ''))) { | 1969 | ($sindent <= $indent && $s ne ''))) { |
1751 | WARN("suspect code indent for conditional statements ($indent, $sindent)\n" . $herecurr . "$stat_real\n"); | 1970 | WARN("SUSPECT_CODE_INDENT", |
1971 | "suspect code indent for conditional statements ($indent, $sindent)\n" . $herecurr . "$stat_real\n"); | ||
1752 | } | 1972 | } |
1753 | } | 1973 | } |
1754 | 1974 | ||
@@ -1771,18 +1991,22 @@ sub process { | |||
1771 | # TEST: allow direct testing of the type matcher. | 1991 | # TEST: allow direct testing of the type matcher. |
1772 | if ($dbg_type) { | 1992 | if ($dbg_type) { |
1773 | if ($line =~ /^.\s*$Declare\s*$/) { | 1993 | if ($line =~ /^.\s*$Declare\s*$/) { |
1774 | ERROR("TEST: is type\n" . $herecurr); | 1994 | ERROR("TEST_TYPE", |
1995 | "TEST: is type\n" . $herecurr); | ||
1775 | } elsif ($dbg_type > 1 && $line =~ /^.+($Declare)/) { | 1996 | } elsif ($dbg_type > 1 && $line =~ /^.+($Declare)/) { |
1776 | ERROR("TEST: is not type ($1 is)\n". $herecurr); | 1997 | ERROR("TEST_NOT_TYPE", |
1998 | "TEST: is not type ($1 is)\n". $herecurr); | ||
1777 | } | 1999 | } |
1778 | next; | 2000 | next; |
1779 | } | 2001 | } |
1780 | # TEST: allow direct testing of the attribute matcher. | 2002 | # TEST: allow direct testing of the attribute matcher. |
1781 | if ($dbg_attr) { | 2003 | if ($dbg_attr) { |
1782 | if ($line =~ /^.\s*$Modifier\s*$/) { | 2004 | if ($line =~ /^.\s*$Modifier\s*$/) { |
1783 | ERROR("TEST: is attr\n" . $herecurr); | 2005 | ERROR("TEST_ATTR", |
2006 | "TEST: is attr\n" . $herecurr); | ||
1784 | } elsif ($dbg_attr > 1 && $line =~ /^.+($Modifier)/) { | 2007 | } elsif ($dbg_attr > 1 && $line =~ /^.+($Modifier)/) { |
1785 | ERROR("TEST: is not attr ($1 is)\n". $herecurr); | 2008 | ERROR("TEST_NOT_ATTR", |
2009 | "TEST: is not attr ($1 is)\n". $herecurr); | ||
1786 | } | 2010 | } |
1787 | next; | 2011 | next; |
1788 | } | 2012 | } |
@@ -1790,7 +2014,8 @@ sub process { | |||
1790 | # check for initialisation to aggregates open brace on the next line | 2014 | # check for initialisation to aggregates open brace on the next line |
1791 | if ($line =~ /^.\s*{/ && | 2015 | if ($line =~ /^.\s*{/ && |
1792 | $prevline =~ /(?:^|[^=])=\s*$/) { | 2016 | $prevline =~ /(?:^|[^=])=\s*$/) { |
1793 | ERROR("that open brace { should be on the previous line\n" . $hereprev); | 2017 | ERROR("OPEN_BRACE", |
2018 | "that open brace { should be on the previous line\n" . $hereprev); | ||
1794 | } | 2019 | } |
1795 | 2020 | ||
1796 | # | 2021 | # |
@@ -1801,14 +2026,16 @@ sub process { | |||
1801 | if ($rawline =~ m{^.\s*\#\s*include\s+[<"](.*)[">]}) { | 2026 | if ($rawline =~ m{^.\s*\#\s*include\s+[<"](.*)[">]}) { |
1802 | my $path = $1; | 2027 | my $path = $1; |
1803 | if ($path =~ m{//}) { | 2028 | if ($path =~ m{//}) { |
1804 | ERROR("malformed #include filename\n" . | 2029 | ERROR("MALFORMED_INCLUDE", |
2030 | "malformed #include filename\n" . | ||
1805 | $herecurr); | 2031 | $herecurr); |
1806 | } | 2032 | } |
1807 | } | 2033 | } |
1808 | 2034 | ||
1809 | # no C99 // comments | 2035 | # no C99 // comments |
1810 | if ($line =~ m{//}) { | 2036 | if ($line =~ m{//}) { |
1811 | ERROR("do not use C99 // comments\n" . $herecurr); | 2037 | ERROR("C99_COMMENTS", |
2038 | "do not use C99 // comments\n" . $herecurr); | ||
1812 | } | 2039 | } |
1813 | # Remove C99 comments. | 2040 | # Remove C99 comments. |
1814 | $line =~ s@//.*@@; | 2041 | $line =~ s@//.*@@; |
@@ -1855,35 +2082,41 @@ sub process { | |||
1855 | } | 2082 | } |
1856 | if (defined $suppress_export{$linenr} && | 2083 | if (defined $suppress_export{$linenr} && |
1857 | $suppress_export{$linenr} == 2) { | 2084 | $suppress_export{$linenr} == 2) { |
1858 | WARN("EXPORT_SYMBOL(foo); should immediately follow its function/variable\n" . $herecurr); | 2085 | WARN("EXPORT_SYMBOL", |
2086 | "EXPORT_SYMBOL(foo); should immediately follow its function/variable\n" . $herecurr); | ||
1859 | } | 2087 | } |
1860 | 2088 | ||
1861 | # check for global initialisers. | 2089 | # check for global initialisers. |
1862 | if ($line =~ /^.$Type\s*$Ident\s*(?:\s+$Modifier)*\s*=\s*(0|NULL|false)\s*;/) { | 2090 | if ($line =~ /^.$Type\s*$Ident\s*(?:\s+$Modifier)*\s*=\s*(0|NULL|false)\s*;/) { |
1863 | ERROR("do not initialise globals to 0 or NULL\n" . | 2091 | ERROR("GLOBAL_INITIALISERS", |
2092 | "do not initialise globals to 0 or NULL\n" . | ||
1864 | $herecurr); | 2093 | $herecurr); |
1865 | } | 2094 | } |
1866 | # check for static initialisers. | 2095 | # check for static initialisers. |
1867 | if ($line =~ /\bstatic\s.*=\s*(0|NULL|false)\s*;/) { | 2096 | if ($line =~ /\bstatic\s.*=\s*(0|NULL|false)\s*;/) { |
1868 | ERROR("do not initialise statics to 0 or NULL\n" . | 2097 | ERROR("INITIALISED_STATIC", |
2098 | "do not initialise statics to 0 or NULL\n" . | ||
1869 | $herecurr); | 2099 | $herecurr); |
1870 | } | 2100 | } |
1871 | 2101 | ||
1872 | # check for static const char * arrays. | 2102 | # check for static const char * arrays. |
1873 | if ($line =~ /\bstatic\s+const\s+char\s*\*\s*(\w+)\s*\[\s*\]\s*=\s*/) { | 2103 | if ($line =~ /\bstatic\s+const\s+char\s*\*\s*(\w+)\s*\[\s*\]\s*=\s*/) { |
1874 | WARN("static const char * array should probably be static const char * const\n" . | 2104 | WARN("STATIC_CONST_CHAR_ARRAY", |
2105 | "static const char * array should probably be static const char * const\n" . | ||
1875 | $herecurr); | 2106 | $herecurr); |
1876 | } | 2107 | } |
1877 | 2108 | ||
1878 | # check for static char foo[] = "bar" declarations. | 2109 | # check for static char foo[] = "bar" declarations. |
1879 | if ($line =~ /\bstatic\s+char\s+(\w+)\s*\[\s*\]\s*=\s*"/) { | 2110 | if ($line =~ /\bstatic\s+char\s+(\w+)\s*\[\s*\]\s*=\s*"/) { |
1880 | WARN("static char array declaration should probably be static const char\n" . | 2111 | WARN("STATIC_CONST_CHAR_ARRAY", |
2112 | "static char array declaration should probably be static const char\n" . | ||
1881 | $herecurr); | 2113 | $herecurr); |
1882 | } | 2114 | } |
1883 | 2115 | ||
1884 | # check for declarations of struct pci_device_id | 2116 | # check for declarations of struct pci_device_id |
1885 | if ($line =~ /\bstruct\s+pci_device_id\s+\w+\s*\[\s*\]\s*\=\s*\{/) { | 2117 | if ($line =~ /\bstruct\s+pci_device_id\s+\w+\s*\[\s*\]\s*\=\s*\{/) { |
1886 | WARN("Use DEFINE_PCI_DEVICE_TABLE for struct pci_device_id\n" . $herecurr); | 2118 | WARN("DEFINE_PCI_DEVICE_TABLE", |
2119 | "Use DEFINE_PCI_DEVICE_TABLE for struct pci_device_id\n" . $herecurr); | ||
1887 | } | 2120 | } |
1888 | 2121 | ||
1889 | # check for new typedefs, only function parameters and sparse annotations | 2122 | # check for new typedefs, only function parameters and sparse annotations |
@@ -1893,7 +2126,8 @@ sub process { | |||
1893 | $line !~ /\btypedef\s+$Type\s+$Ident\s*\(/ && | 2126 | $line !~ /\btypedef\s+$Type\s+$Ident\s*\(/ && |
1894 | $line !~ /\b$typeTypedefs\b/ && | 2127 | $line !~ /\b$typeTypedefs\b/ && |
1895 | $line !~ /\b__bitwise(?:__|)\b/) { | 2128 | $line !~ /\b__bitwise(?:__|)\b/) { |
1896 | WARN("do not add new typedefs\n" . $herecurr); | 2129 | WARN("NEW_TYPEDEFS", |
2130 | "do not add new typedefs\n" . $herecurr); | ||
1897 | } | 2131 | } |
1898 | 2132 | ||
1899 | # * goes on variable not on type | 2133 | # * goes on variable not on type |
@@ -1911,7 +2145,8 @@ sub process { | |||
1911 | 2145 | ||
1912 | #print "from<$from> to<$to>\n"; | 2146 | #print "from<$from> to<$to>\n"; |
1913 | if ($from ne $to) { | 2147 | if ($from ne $to) { |
1914 | ERROR("\"(foo$from)\" should be \"(foo$to)\"\n" . $herecurr); | 2148 | ERROR("POINTER_LOCATION", |
2149 | "\"(foo$from)\" should be \"(foo$to)\"\n" . $herecurr); | ||
1915 | } | 2150 | } |
1916 | } elsif ($line =~ m{\b$NonptrType(\s*(?:$Modifier\b\s*|\*\s*)+)($Ident)}) { | 2151 | } elsif ($line =~ m{\b$NonptrType(\s*(?:$Modifier\b\s*|\*\s*)+)($Ident)}) { |
1917 | my ($from, $to, $ident) = ($1, $1, $2); | 2152 | my ($from, $to, $ident) = ($1, $1, $2); |
@@ -1928,7 +2163,8 @@ sub process { | |||
1928 | 2163 | ||
1929 | #print "from<$from> to<$to> ident<$ident>\n"; | 2164 | #print "from<$from> to<$to> ident<$ident>\n"; |
1930 | if ($from ne $to && $ident !~ /^$Modifier$/) { | 2165 | if ($from ne $to && $ident !~ /^$Modifier$/) { |
1931 | ERROR("\"foo${from}bar\" should be \"foo${to}bar\"\n" . $herecurr); | 2166 | ERROR("POINTER_LOCATION", |
2167 | "\"foo${from}bar\" should be \"foo${to}bar\"\n" . $herecurr); | ||
1932 | } | 2168 | } |
1933 | } | 2169 | } |
1934 | 2170 | ||
@@ -1940,12 +2176,14 @@ sub process { | |||
1940 | # } | 2176 | # } |
1941 | 2177 | ||
1942 | if ($line =~ /\bLINUX_VERSION_CODE\b/) { | 2178 | if ($line =~ /\bLINUX_VERSION_CODE\b/) { |
1943 | WARN("LINUX_VERSION_CODE should be avoided, code should be for the version to which it is merged\n" . $herecurr); | 2179 | WARN("LINUX_VERSION_CODE", |
2180 | "LINUX_VERSION_CODE should be avoided, code should be for the version to which it is merged\n" . $herecurr); | ||
1944 | } | 2181 | } |
1945 | 2182 | ||
1946 | # check for uses of printk_ratelimit | 2183 | # check for uses of printk_ratelimit |
1947 | if ($line =~ /\bprintk_ratelimit\s*\(/) { | 2184 | if ($line =~ /\bprintk_ratelimit\s*\(/) { |
1948 | WARN("Prefer printk_ratelimited or pr_<level>_ratelimited to printk_ratelimit\n" . $herecurr); | 2185 | WARN("PRINTK_RATELIMITED", |
2186 | "Prefer printk_ratelimited or pr_<level>_ratelimited to printk_ratelimit\n" . $herecurr); | ||
1949 | } | 2187 | } |
1950 | 2188 | ||
1951 | # printk should use KERN_* levels. Note that follow on printk's on the | 2189 | # printk should use KERN_* levels. Note that follow on printk's on the |
@@ -1967,7 +2205,8 @@ sub process { | |||
1967 | } | 2205 | } |
1968 | } | 2206 | } |
1969 | if ($ok == 0) { | 2207 | if ($ok == 0) { |
1970 | WARN("printk() should include KERN_ facility level\n" . $herecurr); | 2208 | WARN("PRINTK_WITHOUT_KERN_LEVEL", |
2209 | "printk() should include KERN_ facility level\n" . $herecurr); | ||
1971 | } | 2210 | } |
1972 | } | 2211 | } |
1973 | 2212 | ||
@@ -1975,18 +2214,21 @@ sub process { | |||
1975 | # or if closed on same line | 2214 | # or if closed on same line |
1976 | if (($line=~/$Type\s*$Ident\(.*\).*\s{/) and | 2215 | if (($line=~/$Type\s*$Ident\(.*\).*\s{/) and |
1977 | !($line=~/\#\s*define.*do\s{/) and !($line=~/}/)) { | 2216 | !($line=~/\#\s*define.*do\s{/) and !($line=~/}/)) { |
1978 | ERROR("open brace '{' following function declarations go on the next line\n" . $herecurr); | 2217 | ERROR("OPEN_BRACE", |
2218 | "open brace '{' following function declarations go on the next line\n" . $herecurr); | ||
1979 | } | 2219 | } |
1980 | 2220 | ||
1981 | # open braces for enum, union and struct go on the same line. | 2221 | # open braces for enum, union and struct go on the same line. |
1982 | if ($line =~ /^.\s*{/ && | 2222 | if ($line =~ /^.\s*{/ && |
1983 | $prevline =~ /^.\s*(?:typedef\s+)?(enum|union|struct)(?:\s+$Ident)?\s*$/) { | 2223 | $prevline =~ /^.\s*(?:typedef\s+)?(enum|union|struct)(?:\s+$Ident)?\s*$/) { |
1984 | ERROR("open brace '{' following $1 go on the same line\n" . $hereprev); | 2224 | ERROR("OPEN_BRACE", |
2225 | "open brace '{' following $1 go on the same line\n" . $hereprev); | ||
1985 | } | 2226 | } |
1986 | 2227 | ||
1987 | # missing space after union, struct or enum definition | 2228 | # missing space after union, struct or enum definition |
1988 | if ($line =~ /^.\s*(?:typedef\s+)?(enum|union|struct)(?:\s+$Ident)?(?:\s+$Ident)?[=\{]/) { | 2229 | if ($line =~ /^.\s*(?:typedef\s+)?(enum|union|struct)(?:\s+$Ident)?(?:\s+$Ident)?[=\{]/) { |
1989 | WARN("missing space after $1 definition\n" . $herecurr); | 2230 | WARN("SPACING", |
2231 | "missing space after $1 definition\n" . $herecurr); | ||
1990 | } | 2232 | } |
1991 | 2233 | ||
1992 | # check for spacing round square brackets; allowed: | 2234 | # check for spacing round square brackets; allowed: |
@@ -1998,7 +2240,8 @@ sub process { | |||
1998 | if ($prefix !~ /$Type\s+$/ && | 2240 | if ($prefix !~ /$Type\s+$/ && |
1999 | ($where != 0 || $prefix !~ /^.\s+$/) && | 2241 | ($where != 0 || $prefix !~ /^.\s+$/) && |
2000 | $prefix !~ /{\s+$/) { | 2242 | $prefix !~ /{\s+$/) { |
2001 | ERROR("space prohibited before open square bracket '['\n" . $herecurr); | 2243 | ERROR("BRACKET_SPACE", |
2244 | "space prohibited before open square bracket '['\n" . $herecurr); | ||
2002 | } | 2245 | } |
2003 | } | 2246 | } |
2004 | 2247 | ||
@@ -2029,7 +2272,8 @@ sub process { | |||
2029 | } elsif ($ctx =~ /$Type$/) { | 2272 | } elsif ($ctx =~ /$Type$/) { |
2030 | 2273 | ||
2031 | } else { | 2274 | } else { |
2032 | WARN("space prohibited between function name and open parenthesis '('\n" . $herecurr); | 2275 | WARN("SPACING", |
2276 | "space prohibited between function name and open parenthesis '('\n" . $herecurr); | ||
2033 | } | 2277 | } |
2034 | } | 2278 | } |
2035 | # Check operator spacing. | 2279 | # Check operator spacing. |
@@ -2103,7 +2347,8 @@ sub process { | |||
2103 | } elsif ($op eq ';') { | 2347 | } elsif ($op eq ';') { |
2104 | if ($ctx !~ /.x[WEBC]/ && | 2348 | if ($ctx !~ /.x[WEBC]/ && |
2105 | $cc !~ /^\\/ && $cc !~ /^;/) { | 2349 | $cc !~ /^\\/ && $cc !~ /^;/) { |
2106 | ERROR("space required after that '$op' $at\n" . $hereptr); | 2350 | ERROR("SPACING", |
2351 | "space required after that '$op' $at\n" . $hereptr); | ||
2107 | } | 2352 | } |
2108 | 2353 | ||
2109 | # // is a comment | 2354 | # // is a comment |
@@ -2114,13 +2359,15 @@ sub process { | |||
2114 | # : when part of a bitfield | 2359 | # : when part of a bitfield |
2115 | } elsif ($op eq '->' || $opv eq ':B') { | 2360 | } elsif ($op eq '->' || $opv eq ':B') { |
2116 | if ($ctx =~ /Wx.|.xW/) { | 2361 | if ($ctx =~ /Wx.|.xW/) { |
2117 | ERROR("spaces prohibited around that '$op' $at\n" . $hereptr); | 2362 | ERROR("SPACING", |
2363 | "spaces prohibited around that '$op' $at\n" . $hereptr); | ||
2118 | } | 2364 | } |
2119 | 2365 | ||
2120 | # , must have a space on the right. | 2366 | # , must have a space on the right. |
2121 | } elsif ($op eq ',') { | 2367 | } elsif ($op eq ',') { |
2122 | if ($ctx !~ /.x[WEC]/ && $cc !~ /^}/) { | 2368 | if ($ctx !~ /.x[WEC]/ && $cc !~ /^}/) { |
2123 | ERROR("space required after that '$op' $at\n" . $hereptr); | 2369 | ERROR("SPACING", |
2370 | "space required after that '$op' $at\n" . $hereptr); | ||
2124 | } | 2371 | } |
2125 | 2372 | ||
2126 | # '*' as part of a type definition -- reported already. | 2373 | # '*' as part of a type definition -- reported already. |
@@ -2134,26 +2381,31 @@ sub process { | |||
2134 | $opv eq '*U' || $opv eq '-U' || | 2381 | $opv eq '*U' || $opv eq '-U' || |
2135 | $opv eq '&U' || $opv eq '&&U') { | 2382 | $opv eq '&U' || $opv eq '&&U') { |
2136 | if ($ctx !~ /[WEBC]x./ && $ca !~ /(?:\)|!|~|\*|-|\&|\||\+\+|\-\-|\{)$/) { | 2383 | if ($ctx !~ /[WEBC]x./ && $ca !~ /(?:\)|!|~|\*|-|\&|\||\+\+|\-\-|\{)$/) { |
2137 | ERROR("space required before that '$op' $at\n" . $hereptr); | 2384 | ERROR("SPACING", |
2385 | "space required before that '$op' $at\n" . $hereptr); | ||
2138 | } | 2386 | } |
2139 | if ($op eq '*' && $cc =~/\s*$Modifier\b/) { | 2387 | if ($op eq '*' && $cc =~/\s*$Modifier\b/) { |
2140 | # A unary '*' may be const | 2388 | # A unary '*' may be const |
2141 | 2389 | ||
2142 | } elsif ($ctx =~ /.xW/) { | 2390 | } elsif ($ctx =~ /.xW/) { |
2143 | ERROR("space prohibited after that '$op' $at\n" . $hereptr); | 2391 | ERROR("SPACING", |
2392 | "space prohibited after that '$op' $at\n" . $hereptr); | ||
2144 | } | 2393 | } |
2145 | 2394 | ||
2146 | # unary ++ and unary -- are allowed no space on one side. | 2395 | # unary ++ and unary -- are allowed no space on one side. |
2147 | } elsif ($op eq '++' or $op eq '--') { | 2396 | } elsif ($op eq '++' or $op eq '--') { |
2148 | if ($ctx !~ /[WEOBC]x[^W]/ && $ctx !~ /[^W]x[WOBEC]/) { | 2397 | if ($ctx !~ /[WEOBC]x[^W]/ && $ctx !~ /[^W]x[WOBEC]/) { |
2149 | ERROR("space required one side of that '$op' $at\n" . $hereptr); | 2398 | ERROR("SPACING", |
2399 | "space required one side of that '$op' $at\n" . $hereptr); | ||
2150 | } | 2400 | } |
2151 | if ($ctx =~ /Wx[BE]/ || | 2401 | if ($ctx =~ /Wx[BE]/ || |
2152 | ($ctx =~ /Wx./ && $cc =~ /^;/)) { | 2402 | ($ctx =~ /Wx./ && $cc =~ /^;/)) { |
2153 | ERROR("space prohibited before that '$op' $at\n" . $hereptr); | 2403 | ERROR("SPACING", |
2404 | "space prohibited before that '$op' $at\n" . $hereptr); | ||
2154 | } | 2405 | } |
2155 | if ($ctx =~ /ExW/) { | 2406 | if ($ctx =~ /ExW/) { |
2156 | ERROR("space prohibited after that '$op' $at\n" . $hereptr); | 2407 | ERROR("SPACING", |
2408 | "space prohibited after that '$op' $at\n" . $hereptr); | ||
2157 | } | 2409 | } |
2158 | 2410 | ||
2159 | 2411 | ||
@@ -2165,7 +2417,8 @@ sub process { | |||
2165 | $op eq '%') | 2417 | $op eq '%') |
2166 | { | 2418 | { |
2167 | if ($ctx =~ /Wx[^WCE]|[^WCE]xW/) { | 2419 | if ($ctx =~ /Wx[^WCE]|[^WCE]xW/) { |
2168 | ERROR("need consistent spacing around '$op' $at\n" . | 2420 | ERROR("SPACING", |
2421 | "need consistent spacing around '$op' $at\n" . | ||
2169 | $hereptr); | 2422 | $hereptr); |
2170 | } | 2423 | } |
2171 | 2424 | ||
@@ -2173,7 +2426,8 @@ sub process { | |||
2173 | # terminating a case value or a label. | 2426 | # terminating a case value or a label. |
2174 | } elsif ($opv eq ':C' || $opv eq ':L') { | 2427 | } elsif ($opv eq ':C' || $opv eq ':L') { |
2175 | if ($ctx =~ /Wx./) { | 2428 | if ($ctx =~ /Wx./) { |
2176 | ERROR("space prohibited before that '$op' $at\n" . $hereptr); | 2429 | ERROR("SPACING", |
2430 | "space prohibited before that '$op' $at\n" . $hereptr); | ||
2177 | } | 2431 | } |
2178 | 2432 | ||
2179 | # All the others need spaces both sides. | 2433 | # All the others need spaces both sides. |
@@ -2196,7 +2450,8 @@ sub process { | |||
2196 | } | 2450 | } |
2197 | 2451 | ||
2198 | if ($ok == 0) { | 2452 | if ($ok == 0) { |
2199 | ERROR("spaces required around that '$op' $at\n" . $hereptr); | 2453 | ERROR("SPACING", |
2454 | "spaces required around that '$op' $at\n" . $hereptr); | ||
2200 | } | 2455 | } |
2201 | } | 2456 | } |
2202 | $off += length($elements[$n + 1]); | 2457 | $off += length($elements[$n + 1]); |
@@ -2205,7 +2460,8 @@ sub process { | |||
2205 | 2460 | ||
2206 | # check for multiple assignments | 2461 | # check for multiple assignments |
2207 | if ($line =~ /^.\s*$Lval\s*=\s*$Lval\s*=(?!=)/) { | 2462 | if ($line =~ /^.\s*$Lval\s*=\s*$Lval\s*=(?!=)/) { |
2208 | CHK("multiple assignments should be avoided\n" . $herecurr); | 2463 | CHK("MULTIPLE_ASSIGNMENTS", |
2464 | "multiple assignments should be avoided\n" . $herecurr); | ||
2209 | } | 2465 | } |
2210 | 2466 | ||
2211 | ## # check for multiple declarations, allowing for a function declaration | 2467 | ## # check for multiple declarations, allowing for a function declaration |
@@ -2219,45 +2475,53 @@ sub process { | |||
2219 | ## while ($ln =~ s/\([^\(\)]*\)//g) { | 2475 | ## while ($ln =~ s/\([^\(\)]*\)//g) { |
2220 | ## } | 2476 | ## } |
2221 | ## if ($ln =~ /,/) { | 2477 | ## if ($ln =~ /,/) { |
2222 | ## WARN("declaring multiple variables together should be avoided\n" . $herecurr); | 2478 | ## WARN("MULTIPLE_DECLARATION", |
2479 | ## "declaring multiple variables together should be avoided\n" . $herecurr); | ||
2223 | ## } | 2480 | ## } |
2224 | ## } | 2481 | ## } |
2225 | 2482 | ||
2226 | #need space before brace following if, while, etc | 2483 | #need space before brace following if, while, etc |
2227 | if (($line =~ /\(.*\){/ && $line !~ /\($Type\){/) || | 2484 | if (($line =~ /\(.*\){/ && $line !~ /\($Type\){/) || |
2228 | $line =~ /do{/) { | 2485 | $line =~ /do{/) { |
2229 | ERROR("space required before the open brace '{'\n" . $herecurr); | 2486 | ERROR("SPACING", |
2487 | "space required before the open brace '{'\n" . $herecurr); | ||
2230 | } | 2488 | } |
2231 | 2489 | ||
2232 | # closing brace should have a space following it when it has anything | 2490 | # closing brace should have a space following it when it has anything |
2233 | # on the line | 2491 | # on the line |
2234 | if ($line =~ /}(?!(?:,|;|\)))\S/) { | 2492 | if ($line =~ /}(?!(?:,|;|\)))\S/) { |
2235 | ERROR("space required after that close brace '}'\n" . $herecurr); | 2493 | ERROR("SPACING", |
2494 | "space required after that close brace '}'\n" . $herecurr); | ||
2236 | } | 2495 | } |
2237 | 2496 | ||
2238 | # check spacing on square brackets | 2497 | # check spacing on square brackets |
2239 | if ($line =~ /\[\s/ && $line !~ /\[\s*$/) { | 2498 | if ($line =~ /\[\s/ && $line !~ /\[\s*$/) { |
2240 | ERROR("space prohibited after that open square bracket '['\n" . $herecurr); | 2499 | ERROR("SPACING", |
2500 | "space prohibited after that open square bracket '['\n" . $herecurr); | ||
2241 | } | 2501 | } |
2242 | if ($line =~ /\s\]/) { | 2502 | if ($line =~ /\s\]/) { |
2243 | ERROR("space prohibited before that close square bracket ']'\n" . $herecurr); | 2503 | ERROR("SPACING", |
2504 | "space prohibited before that close square bracket ']'\n" . $herecurr); | ||
2244 | } | 2505 | } |
2245 | 2506 | ||
2246 | # check spacing on parentheses | 2507 | # check spacing on parentheses |
2247 | if ($line =~ /\(\s/ && $line !~ /\(\s*(?:\\)?$/ && | 2508 | if ($line =~ /\(\s/ && $line !~ /\(\s*(?:\\)?$/ && |
2248 | $line !~ /for\s*\(\s+;/) { | 2509 | $line !~ /for\s*\(\s+;/) { |
2249 | ERROR("space prohibited after that open parenthesis '('\n" . $herecurr); | 2510 | ERROR("SPACING", |
2511 | "space prohibited after that open parenthesis '('\n" . $herecurr); | ||
2250 | } | 2512 | } |
2251 | if ($line =~ /(\s+)\)/ && $line !~ /^.\s*\)/ && | 2513 | if ($line =~ /(\s+)\)/ && $line !~ /^.\s*\)/ && |
2252 | $line !~ /for\s*\(.*;\s+\)/ && | 2514 | $line !~ /for\s*\(.*;\s+\)/ && |
2253 | $line !~ /:\s+\)/) { | 2515 | $line !~ /:\s+\)/) { |
2254 | ERROR("space prohibited before that close parenthesis ')'\n" . $herecurr); | 2516 | ERROR("SPACING", |
2517 | "space prohibited before that close parenthesis ')'\n" . $herecurr); | ||
2255 | } | 2518 | } |
2256 | 2519 | ||
2257 | #goto labels aren't indented, allow a single space however | 2520 | #goto labels aren't indented, allow a single space however |
2258 | if ($line=~/^.\s+[A-Za-z\d_]+:(?![0-9]+)/ and | 2521 | if ($line=~/^.\s+[A-Za-z\d_]+:(?![0-9]+)/ and |
2259 | !($line=~/^. [A-Za-z\d_]+:/) and !($line=~/^.\s+default:/)) { | 2522 | !($line=~/^. [A-Za-z\d_]+:/) and !($line=~/^.\s+default:/)) { |
2260 | WARN("labels should not be indented\n" . $herecurr); | 2523 | WARN("INDENTED_LABEL", |
2524 | "labels should not be indented\n" . $herecurr); | ||
2261 | } | 2525 | } |
2262 | 2526 | ||
2263 | # Return is not a function. | 2527 | # Return is not a function. |
@@ -2276,23 +2540,47 @@ sub process { | |||
2276 | } | 2540 | } |
2277 | #print "value<$value>\n"; | 2541 | #print "value<$value>\n"; |
2278 | if ($value =~ /^\s*(?:$Ident|-?$Constant)\s*$/) { | 2542 | if ($value =~ /^\s*(?:$Ident|-?$Constant)\s*$/) { |
2279 | ERROR("return is not a function, parentheses are not required\n" . $herecurr); | 2543 | ERROR("RETURN_PARENTHESES", |
2544 | "return is not a function, parentheses are not required\n" . $herecurr); | ||
2280 | 2545 | ||
2281 | } elsif ($spacing !~ /\s+/) { | 2546 | } elsif ($spacing !~ /\s+/) { |
2282 | ERROR("space required before the open parenthesis '('\n" . $herecurr); | 2547 | ERROR("SPACING", |
2548 | "space required before the open parenthesis '('\n" . $herecurr); | ||
2283 | } | 2549 | } |
2284 | } | 2550 | } |
2285 | # Return of what appears to be an errno should normally be -'ve | 2551 | # Return of what appears to be an errno should normally be -'ve |
2286 | if ($line =~ /^.\s*return\s*(E[A-Z]*)\s*;/) { | 2552 | if ($line =~ /^.\s*return\s*(E[A-Z]*)\s*;/) { |
2287 | my $name = $1; | 2553 | my $name = $1; |
2288 | if ($name ne 'EOF' && $name ne 'ERROR') { | 2554 | if ($name ne 'EOF' && $name ne 'ERROR') { |
2289 | WARN("return of an errno should typically be -ve (return -$1)\n" . $herecurr); | 2555 | WARN("USE_NEGATIVE_ERRNO", |
2556 | "return of an errno should typically be -ve (return -$1)\n" . $herecurr); | ||
2557 | } | ||
2558 | } | ||
2559 | |||
2560 | # typecasts on min/max could be min_t/max_t | ||
2561 | if ($line =~ /^\+(?:.*?)\b(min|max)\s*\($Typecast{0,1}($LvalOrFunc)\s*,\s*$Typecast{0,1}($LvalOrFunc)\s*\)/) { | ||
2562 | if (defined $2 || defined $8) { | ||
2563 | my $call = $1; | ||
2564 | my $cast1 = deparenthesize($2); | ||
2565 | my $arg1 = $3; | ||
2566 | my $cast2 = deparenthesize($8); | ||
2567 | my $arg2 = $9; | ||
2568 | my $cast; | ||
2569 | |||
2570 | if ($cast1 ne "" && $cast2 ne "") { | ||
2571 | $cast = "$cast1 or $cast2"; | ||
2572 | } elsif ($cast1 ne "") { | ||
2573 | $cast = $cast1; | ||
2574 | } else { | ||
2575 | $cast = $cast2; | ||
2576 | } | ||
2577 | WARN("$call() should probably be ${call}_t($cast, $arg1, $arg2)\n" . $herecurr); | ||
2290 | } | 2578 | } |
2291 | } | 2579 | } |
2292 | 2580 | ||
2293 | # Need a space before open parenthesis after if, while etc | 2581 | # Need a space before open parenthesis after if, while etc |
2294 | if ($line=~/\b(if|while|for|switch)\(/) { | 2582 | if ($line=~/\b(if|while|for|switch)\(/) { |
2295 | ERROR("space required before the open parenthesis '('\n" . $herecurr); | 2583 | ERROR("SPACING", "space required before the open parenthesis '('\n" . $herecurr); |
2296 | } | 2584 | } |
2297 | 2585 | ||
2298 | # Check for illegal assignment in if conditional -- and check for trailing | 2586 | # Check for illegal assignment in if conditional -- and check for trailing |
@@ -2320,7 +2608,8 @@ sub process { | |||
2320 | my ($s, $c) = ($stat, $cond); | 2608 | my ($s, $c) = ($stat, $cond); |
2321 | 2609 | ||
2322 | if ($c =~ /\bif\s*\(.*[^<>!=]=[^=].*/s) { | 2610 | if ($c =~ /\bif\s*\(.*[^<>!=]=[^=].*/s) { |
2323 | ERROR("do not use assignment in if condition\n" . $herecurr); | 2611 | ERROR("ASSIGN_IN_IF", |
2612 | "do not use assignment in if condition\n" . $herecurr); | ||
2324 | } | 2613 | } |
2325 | 2614 | ||
2326 | # Find out what is on the end of the line after the | 2615 | # Find out what is on the end of the line after the |
@@ -2342,7 +2631,8 @@ sub process { | |||
2342 | $stat_real = "[...]\n$stat_real"; | 2631 | $stat_real = "[...]\n$stat_real"; |
2343 | } | 2632 | } |
2344 | 2633 | ||
2345 | ERROR("trailing statements should be on next line\n" . $herecurr . $stat_real); | 2634 | ERROR("TRAILING_STATEMENTS", |
2635 | "trailing statements should be on next line\n" . $herecurr . $stat_real); | ||
2346 | } | 2636 | } |
2347 | } | 2637 | } |
2348 | 2638 | ||
@@ -2358,7 +2648,8 @@ sub process { | |||
2358 | (?:\&\&|\|\||\)|\]) | 2648 | (?:\&\&|\|\||\)|\]) |
2359 | )/x) | 2649 | )/x) |
2360 | { | 2650 | { |
2361 | WARN("boolean test with hexadecimal, perhaps just 1 \& or \|?\n" . $herecurr); | 2651 | WARN("HEXADECIMAL_BOOLEAN_TEST", |
2652 | "boolean test with hexadecimal, perhaps just 1 \& or \|?\n" . $herecurr); | ||
2362 | } | 2653 | } |
2363 | 2654 | ||
2364 | # if and else should not have general statements after it | 2655 | # if and else should not have general statements after it |
@@ -2366,12 +2657,14 @@ sub process { | |||
2366 | my $s = $1; | 2657 | my $s = $1; |
2367 | $s =~ s/$;//g; # Remove any comments | 2658 | $s =~ s/$;//g; # Remove any comments |
2368 | if ($s !~ /^\s*(?:\sif|(?:{|)\s*\\?\s*$)/) { | 2659 | if ($s !~ /^\s*(?:\sif|(?:{|)\s*\\?\s*$)/) { |
2369 | ERROR("trailing statements should be on next line\n" . $herecurr); | 2660 | ERROR("TRAILING_STATEMENTS", |
2661 | "trailing statements should be on next line\n" . $herecurr); | ||
2370 | } | 2662 | } |
2371 | } | 2663 | } |
2372 | # if should not continue a brace | 2664 | # if should not continue a brace |
2373 | if ($line =~ /}\s*if\b/) { | 2665 | if ($line =~ /}\s*if\b/) { |
2374 | ERROR("trailing statements should be on next line\n" . | 2666 | ERROR("TRAILING_STATEMENTS", |
2667 | "trailing statements should be on next line\n" . | ||
2375 | $herecurr); | 2668 | $herecurr); |
2376 | } | 2669 | } |
2377 | # case and default should not have general statements after them | 2670 | # case and default should not have general statements after them |
@@ -2381,14 +2674,16 @@ sub process { | |||
2381 | \s*return\s+ | 2674 | \s*return\s+ |
2382 | )/xg) | 2675 | )/xg) |
2383 | { | 2676 | { |
2384 | ERROR("trailing statements should be on next line\n" . $herecurr); | 2677 | ERROR("TRAILING_STATEMENTS", |
2678 | "trailing statements should be on next line\n" . $herecurr); | ||
2385 | } | 2679 | } |
2386 | 2680 | ||
2387 | # Check for }<nl>else {, these must be at the same | 2681 | # Check for }<nl>else {, these must be at the same |
2388 | # indent level to be relevant to each other. | 2682 | # indent level to be relevant to each other. |
2389 | if ($prevline=~/}\s*$/ and $line=~/^.\s*else\s*/ and | 2683 | if ($prevline=~/}\s*$/ and $line=~/^.\s*else\s*/ and |
2390 | $previndent == $indent) { | 2684 | $previndent == $indent) { |
2391 | ERROR("else should follow close brace '}'\n" . $hereprev); | 2685 | ERROR("ELSE_AFTER_BRACE", |
2686 | "else should follow close brace '}'\n" . $hereprev); | ||
2392 | } | 2687 | } |
2393 | 2688 | ||
2394 | if ($prevline=~/}\s*$/ and $line=~/^.\s*while\s*/ and | 2689 | if ($prevline=~/}\s*$/ and $line=~/^.\s*while\s*/ and |
@@ -2401,7 +2696,8 @@ sub process { | |||
2401 | $s =~ s/\n.*//g; | 2696 | $s =~ s/\n.*//g; |
2402 | 2697 | ||
2403 | if ($s =~ /^\s*;/) { | 2698 | if ($s =~ /^\s*;/) { |
2404 | ERROR("while should follow close brace '}'\n" . $hereprev); | 2699 | ERROR("WHILE_AFTER_BRACE", |
2700 | "while should follow close brace '}'\n" . $hereprev); | ||
2405 | } | 2701 | } |
2406 | } | 2702 | } |
2407 | 2703 | ||
@@ -2414,7 +2710,8 @@ sub process { | |||
2414 | 2710 | ||
2415 | #no spaces allowed after \ in define | 2711 | #no spaces allowed after \ in define |
2416 | if ($line=~/\#\s*define.*\\\s$/) { | 2712 | if ($line=~/\#\s*define.*\\\s$/) { |
2417 | WARN("Whitepspace after \\ makes next lines useless\n" . $herecurr); | 2713 | WARN("WHITESPACE_AFTER_LINE_CONTINUATION", |
2714 | "Whitepspace after \\ makes next lines useless\n" . $herecurr); | ||
2418 | } | 2715 | } |
2419 | 2716 | ||
2420 | #warn if <asm/foo.h> is #included and <linux/foo.h> is available (uses RAW line) | 2717 | #warn if <asm/foo.h> is #included and <linux/foo.h> is available (uses RAW line) |
@@ -2426,9 +2723,11 @@ sub process { | |||
2426 | $1 !~ /$allowed_asm_includes/) | 2723 | $1 !~ /$allowed_asm_includes/) |
2427 | { | 2724 | { |
2428 | if ($realfile =~ m{^arch/}) { | 2725 | if ($realfile =~ m{^arch/}) { |
2429 | CHK("Consider using #include <linux/$file> instead of <asm/$file>\n" . $herecurr); | 2726 | CHK("ARCH_INCLUDE_LINUX", |
2727 | "Consider using #include <linux/$file> instead of <asm/$file>\n" . $herecurr); | ||
2430 | } else { | 2728 | } else { |
2431 | WARN("Use #include <linux/$file> instead of <asm/$file>\n" . $herecurr); | 2729 | WARN("INCLUDE_LINUX", |
2730 | "Use #include <linux/$file> instead of <asm/$file>\n" . $herecurr); | ||
2432 | } | 2731 | } |
2433 | } | 2732 | } |
2434 | } | 2733 | } |
@@ -2512,7 +2811,8 @@ sub process { | |||
2512 | if ($rest !~ /while\s*\(/ && | 2811 | if ($rest !~ /while\s*\(/ && |
2513 | $dstat !~ /$exceptions/) | 2812 | $dstat !~ /$exceptions/) |
2514 | { | 2813 | { |
2515 | ERROR("Macros with multiple statements should be enclosed in a do - while loop\n" . "$here\n$ctx\n"); | 2814 | ERROR("MULTISTATEMENT_MACRO_USE_DO_WHILE", |
2815 | "Macros with multiple statements should be enclosed in a do - while loop\n" . "$here\n$ctx\n"); | ||
2516 | } | 2816 | } |
2517 | 2817 | ||
2518 | } elsif ($ctx !~ /;/) { | 2818 | } elsif ($ctx !~ /;/) { |
@@ -2522,7 +2822,8 @@ sub process { | |||
2522 | $dstat !~ /^\.$Ident\s*=/ && | 2822 | $dstat !~ /^\.$Ident\s*=/ && |
2523 | $dstat =~ /$Operators/) | 2823 | $dstat =~ /$Operators/) |
2524 | { | 2824 | { |
2525 | ERROR("Macros with complex values should be enclosed in parenthesis\n" . "$here\n$ctx\n"); | 2825 | ERROR("COMPLEX_MACRO", |
2826 | "Macros with complex values should be enclosed in parenthesis\n" . "$here\n$ctx\n"); | ||
2526 | } | 2827 | } |
2527 | } | 2828 | } |
2528 | } | 2829 | } |
@@ -2533,7 +2834,8 @@ sub process { | |||
2533 | # ALIGN(...) | 2834 | # ALIGN(...) |
2534 | # VMLINUX_SYMBOL(...) | 2835 | # VMLINUX_SYMBOL(...) |
2535 | if ($realfile eq 'vmlinux.lds.h' && $line =~ /(?:(?:^|\s)$Ident\s*=|=\s*$Ident(?:\s|$))/) { | 2836 | if ($realfile eq 'vmlinux.lds.h' && $line =~ /(?:(?:^|\s)$Ident\s*=|=\s*$Ident(?:\s|$))/) { |
2536 | WARN("vmlinux.lds.h needs VMLINUX_SYMBOL() around C-visible symbols\n" . $herecurr); | 2837 | WARN("MISSING_VMLINUX_SYMBOL", |
2838 | "vmlinux.lds.h needs VMLINUX_SYMBOL() around C-visible symbols\n" . $herecurr); | ||
2537 | } | 2839 | } |
2538 | 2840 | ||
2539 | # check for redundant bracing round if etc | 2841 | # check for redundant bracing round if etc |
@@ -2581,7 +2883,8 @@ sub process { | |||
2581 | } | 2883 | } |
2582 | } | 2884 | } |
2583 | if ($seen && !$allowed) { | 2885 | if ($seen && !$allowed) { |
2584 | WARN("braces {} are not necessary for any arm of this statement\n" . $herectx); | 2886 | WARN("BRACES", |
2887 | "braces {} are not necessary for any arm of this statement\n" . $herectx); | ||
2585 | } | 2888 | } |
2586 | } | 2889 | } |
2587 | } | 2890 | } |
@@ -2635,33 +2938,38 @@ sub process { | |||
2635 | $herectx .= raw_line($linenr, $n) . "\n";; | 2938 | $herectx .= raw_line($linenr, $n) . "\n";; |
2636 | } | 2939 | } |
2637 | 2940 | ||
2638 | WARN("braces {} are not necessary for single statement blocks\n" . $herectx); | 2941 | WARN("BRACES", |
2942 | "braces {} are not necessary for single statement blocks\n" . $herectx); | ||
2639 | } | 2943 | } |
2640 | } | 2944 | } |
2641 | 2945 | ||
2642 | # don't include deprecated include files (uses RAW line) | 2946 | # don't include deprecated include files (uses RAW line) |
2643 | for my $inc (@dep_includes) { | 2947 | for my $inc (@dep_includes) { |
2644 | if ($rawline =~ m@^.\s*\#\s*include\s*\<$inc>@) { | 2948 | if ($rawline =~ m@^.\s*\#\s*include\s*\<$inc>@) { |
2645 | ERROR("Don't use <$inc>: see Documentation/feature-removal-schedule.txt\n" . $herecurr); | 2949 | ERROR("DEPRECATED_INCLUDE", |
2950 | "Don't use <$inc>: see Documentation/feature-removal-schedule.txt\n" . $herecurr); | ||
2646 | } | 2951 | } |
2647 | } | 2952 | } |
2648 | 2953 | ||
2649 | # don't use deprecated functions | 2954 | # don't use deprecated functions |
2650 | for my $func (@dep_functions) { | 2955 | for my $func (@dep_functions) { |
2651 | if ($line =~ /\b$func\b/) { | 2956 | if ($line =~ /\b$func\b/) { |
2652 | ERROR("Don't use $func(): see Documentation/feature-removal-schedule.txt\n" . $herecurr); | 2957 | ERROR("DEPRECATED_FUNCTION", |
2958 | "Don't use $func(): see Documentation/feature-removal-schedule.txt\n" . $herecurr); | ||
2653 | } | 2959 | } |
2654 | } | 2960 | } |
2655 | 2961 | ||
2656 | # no volatiles please | 2962 | # no volatiles please |
2657 | my $asm_volatile = qr{\b(__asm__|asm)\s+(__volatile__|volatile)\b}; | 2963 | my $asm_volatile = qr{\b(__asm__|asm)\s+(__volatile__|volatile)\b}; |
2658 | if ($line =~ /\bvolatile\b/ && $line !~ /$asm_volatile/) { | 2964 | if ($line =~ /\bvolatile\b/ && $line !~ /$asm_volatile/) { |
2659 | WARN("Use of volatile is usually wrong: see Documentation/volatile-considered-harmful.txt\n" . $herecurr); | 2965 | WARN("VOLATILE", |
2966 | "Use of volatile is usually wrong: see Documentation/volatile-considered-harmful.txt\n" . $herecurr); | ||
2660 | } | 2967 | } |
2661 | 2968 | ||
2662 | # warn about #if 0 | 2969 | # warn about #if 0 |
2663 | if ($line =~ /^.\s*\#\s*if\s+0\b/) { | 2970 | if ($line =~ /^.\s*\#\s*if\s+0\b/) { |
2664 | CHK("if this code is redundant consider removing it\n" . | 2971 | CHK("REDUNDANT_CODE", |
2972 | "if this code is redundant consider removing it\n" . | ||
2665 | $herecurr); | 2973 | $herecurr); |
2666 | } | 2974 | } |
2667 | 2975 | ||
@@ -2669,14 +2977,16 @@ sub process { | |||
2669 | if ($prevline =~ /\bif\s*\(([^\)]*)\)/) { | 2977 | if ($prevline =~ /\bif\s*\(([^\)]*)\)/) { |
2670 | my $expr = $1; | 2978 | my $expr = $1; |
2671 | if ($line =~ /\bkfree\(\Q$expr\E\);/) { | 2979 | if ($line =~ /\bkfree\(\Q$expr\E\);/) { |
2672 | WARN("kfree(NULL) is safe this check is probably not required\n" . $hereprev); | 2980 | WARN("NEEDLESS_KFREE", |
2981 | "kfree(NULL) is safe this check is probably not required\n" . $hereprev); | ||
2673 | } | 2982 | } |
2674 | } | 2983 | } |
2675 | # check for needless usb_free_urb() checks | 2984 | # check for needless usb_free_urb() checks |
2676 | if ($prevline =~ /\bif\s*\(([^\)]*)\)/) { | 2985 | if ($prevline =~ /\bif\s*\(([^\)]*)\)/) { |
2677 | my $expr = $1; | 2986 | my $expr = $1; |
2678 | if ($line =~ /\busb_free_urb\(\Q$expr\E\);/) { | 2987 | if ($line =~ /\busb_free_urb\(\Q$expr\E\);/) { |
2679 | WARN("usb_free_urb(NULL) is safe this check is probably not required\n" . $hereprev); | 2988 | WARN("NEEDLESS_USB_FREE_URB", |
2989 | "usb_free_urb(NULL) is safe this check is probably not required\n" . $hereprev); | ||
2680 | } | 2990 | } |
2681 | } | 2991 | } |
2682 | 2992 | ||
@@ -2684,14 +2994,16 @@ sub process { | |||
2684 | if ($line =~ /\budelay\s*\(\s*(\w+)\s*\)/) { | 2994 | if ($line =~ /\budelay\s*\(\s*(\w+)\s*\)/) { |
2685 | # ignore udelay's < 10, however | 2995 | # ignore udelay's < 10, however |
2686 | if (! (($1 =~ /(\d+)/) && ($1 < 10)) ) { | 2996 | if (! (($1 =~ /(\d+)/) && ($1 < 10)) ) { |
2687 | CHK("usleep_range is preferred over udelay; see Documentation/timers/timers-howto.txt\n" . $line); | 2997 | CHK("USLEEP_RANGE", |
2998 | "usleep_range is preferred over udelay; see Documentation/timers/timers-howto.txt\n" . $line); | ||
2688 | } | 2999 | } |
2689 | } | 3000 | } |
2690 | 3001 | ||
2691 | # warn about unexpectedly long msleep's | 3002 | # warn about unexpectedly long msleep's |
2692 | if ($line =~ /\bmsleep\s*\((\d+)\);/) { | 3003 | if ($line =~ /\bmsleep\s*\((\d+)\);/) { |
2693 | if ($1 < 20) { | 3004 | if ($1 < 20) { |
2694 | WARN("msleep < 20ms can sleep for up to 20ms; see Documentation/timers/timers-howto.txt\n" . $line); | 3005 | WARN("MSLEEP", |
3006 | "msleep < 20ms can sleep for up to 20ms; see Documentation/timers/timers-howto.txt\n" . $line); | ||
2695 | } | 3007 | } |
2696 | } | 3008 | } |
2697 | 3009 | ||
@@ -2704,7 +3016,8 @@ sub process { | |||
2704 | 3016 | ||
2705 | # warn about spacing in #ifdefs | 3017 | # warn about spacing in #ifdefs |
2706 | if ($line =~ /^.\s*\#\s*(ifdef|ifndef|elif)\s\s+/) { | 3018 | if ($line =~ /^.\s*\#\s*(ifdef|ifndef|elif)\s\s+/) { |
2707 | ERROR("exactly one space required after that #$1\n" . $herecurr); | 3019 | ERROR("SPACING", |
3020 | "exactly one space required after that #$1\n" . $herecurr); | ||
2708 | } | 3021 | } |
2709 | 3022 | ||
2710 | # check for spinlock_t definitions without a comment. | 3023 | # check for spinlock_t definitions without a comment. |
@@ -2712,50 +3025,65 @@ sub process { | |||
2712 | $line =~ /^.\s*(DEFINE_MUTEX)\s*\(/) { | 3025 | $line =~ /^.\s*(DEFINE_MUTEX)\s*\(/) { |
2713 | my $which = $1; | 3026 | my $which = $1; |
2714 | if (!ctx_has_comment($first_line, $linenr)) { | 3027 | if (!ctx_has_comment($first_line, $linenr)) { |
2715 | CHK("$1 definition without comment\n" . $herecurr); | 3028 | CHK("UNCOMMENTED_DEFINITION", |
3029 | "$1 definition without comment\n" . $herecurr); | ||
2716 | } | 3030 | } |
2717 | } | 3031 | } |
2718 | # check for memory barriers without a comment. | 3032 | # check for memory barriers without a comment. |
2719 | if ($line =~ /\b(mb|rmb|wmb|read_barrier_depends|smp_mb|smp_rmb|smp_wmb|smp_read_barrier_depends)\(/) { | 3033 | if ($line =~ /\b(mb|rmb|wmb|read_barrier_depends|smp_mb|smp_rmb|smp_wmb|smp_read_barrier_depends)\(/) { |
2720 | if (!ctx_has_comment($first_line, $linenr)) { | 3034 | if (!ctx_has_comment($first_line, $linenr)) { |
2721 | CHK("memory barrier without comment\n" . $herecurr); | 3035 | CHK("MEMORY_BARRIER", |
3036 | "memory barrier without comment\n" . $herecurr); | ||
2722 | } | 3037 | } |
2723 | } | 3038 | } |
2724 | # check of hardware specific defines | 3039 | # check of hardware specific defines |
2725 | if ($line =~ m@^.\s*\#\s*if.*\b(__i386__|__powerpc64__|__sun__|__s390x__)\b@ && $realfile !~ m@include/asm-@) { | 3040 | if ($line =~ m@^.\s*\#\s*if.*\b(__i386__|__powerpc64__|__sun__|__s390x__)\b@ && $realfile !~ m@include/asm-@) { |
2726 | CHK("architecture specific defines should be avoided\n" . $herecurr); | 3041 | CHK("ARCH_DEFINES", |
3042 | "architecture specific defines should be avoided\n" . $herecurr); | ||
2727 | } | 3043 | } |
2728 | 3044 | ||
2729 | # Check that the storage class is at the beginning of a declaration | 3045 | # Check that the storage class is at the beginning of a declaration |
2730 | if ($line =~ /\b$Storage\b/ && $line !~ /^.\s*$Storage\b/) { | 3046 | if ($line =~ /\b$Storage\b/ && $line !~ /^.\s*$Storage\b/) { |
2731 | WARN("storage class should be at the beginning of the declaration\n" . $herecurr) | 3047 | WARN("STORAGE_CLASS", |
3048 | "storage class should be at the beginning of the declaration\n" . $herecurr) | ||
2732 | } | 3049 | } |
2733 | 3050 | ||
2734 | # check the location of the inline attribute, that it is between | 3051 | # check the location of the inline attribute, that it is between |
2735 | # storage class and type. | 3052 | # storage class and type. |
2736 | if ($line =~ /\b$Type\s+$Inline\b/ || | 3053 | if ($line =~ /\b$Type\s+$Inline\b/ || |
2737 | $line =~ /\b$Inline\s+$Storage\b/) { | 3054 | $line =~ /\b$Inline\s+$Storage\b/) { |
2738 | ERROR("inline keyword should sit between storage class and type\n" . $herecurr); | 3055 | ERROR("INLINE_LOCATION", |
3056 | "inline keyword should sit between storage class and type\n" . $herecurr); | ||
2739 | } | 3057 | } |
2740 | 3058 | ||
2741 | # Check for __inline__ and __inline, prefer inline | 3059 | # Check for __inline__ and __inline, prefer inline |
2742 | if ($line =~ /\b(__inline__|__inline)\b/) { | 3060 | if ($line =~ /\b(__inline__|__inline)\b/) { |
2743 | WARN("plain inline is preferred over $1\n" . $herecurr); | 3061 | WARN("INLINE", |
3062 | "plain inline is preferred over $1\n" . $herecurr); | ||
2744 | } | 3063 | } |
2745 | 3064 | ||
2746 | # Check for __attribute__ packed, prefer __packed | 3065 | # Check for __attribute__ packed, prefer __packed |
2747 | if ($line =~ /\b__attribute__\s*\(\s*\(.*\bpacked\b/) { | 3066 | if ($line =~ /\b__attribute__\s*\(\s*\(.*\bpacked\b/) { |
2748 | WARN("__packed is preferred over __attribute__((packed))\n" . $herecurr); | 3067 | WARN("PREFER_PACKED", |
3068 | "__packed is preferred over __attribute__((packed))\n" . $herecurr); | ||
3069 | } | ||
3070 | |||
3071 | # Check for __attribute__ aligned, prefer __aligned | ||
3072 | if ($line =~ /\b__attribute__\s*\(\s*\(.*aligned/) { | ||
3073 | WARN("PREFER_ALIGNED", | ||
3074 | "__aligned(size) is preferred over __attribute__((aligned(size)))\n" . $herecurr); | ||
2749 | } | 3075 | } |
2750 | 3076 | ||
2751 | # check for sizeof(&) | 3077 | # check for sizeof(&) |
2752 | if ($line =~ /\bsizeof\s*\(\s*\&/) { | 3078 | if ($line =~ /\bsizeof\s*\(\s*\&/) { |
2753 | WARN("sizeof(& should be avoided\n" . $herecurr); | 3079 | WARN("SIZEOF_ADDRESS", |
3080 | "sizeof(& should be avoided\n" . $herecurr); | ||
2754 | } | 3081 | } |
2755 | 3082 | ||
2756 | # check for line continuations in quoted strings with odd counts of " | 3083 | # check for line continuations in quoted strings with odd counts of " |
2757 | if ($rawline =~ /\\$/ && $rawline =~ tr/"/"/ % 2) { | 3084 | if ($rawline =~ /\\$/ && $rawline =~ tr/"/"/ % 2) { |
2758 | WARN("Avoid line continuations in quoted strings\n" . $herecurr); | 3085 | WARN("LINE_CONTINUATIONS", |
3086 | "Avoid line continuations in quoted strings\n" . $herecurr); | ||
2759 | } | 3087 | } |
2760 | 3088 | ||
2761 | # check for new externs in .c files. | 3089 | # check for new externs in .c files. |
@@ -2772,17 +3100,20 @@ sub process { | |||
2772 | if ($s =~ /^\s*;/ && | 3100 | if ($s =~ /^\s*;/ && |
2773 | $function_name ne 'uninitialized_var') | 3101 | $function_name ne 'uninitialized_var') |
2774 | { | 3102 | { |
2775 | WARN("externs should be avoided in .c files\n" . $herecurr); | 3103 | WARN("AVOID_EXTERNS", |
3104 | "externs should be avoided in .c files\n" . $herecurr); | ||
2776 | } | 3105 | } |
2777 | 3106 | ||
2778 | if ($paren_space =~ /\n/) { | 3107 | if ($paren_space =~ /\n/) { |
2779 | WARN("arguments for function declarations should follow identifier\n" . $herecurr); | 3108 | WARN("FUNCTION_ARGUMENTS", |
3109 | "arguments for function declarations should follow identifier\n" . $herecurr); | ||
2780 | } | 3110 | } |
2781 | 3111 | ||
2782 | } elsif ($realfile =~ /\.c$/ && defined $stat && | 3112 | } elsif ($realfile =~ /\.c$/ && defined $stat && |
2783 | $stat =~ /^.\s*extern\s+/) | 3113 | $stat =~ /^.\s*extern\s+/) |
2784 | { | 3114 | { |
2785 | WARN("externs should be avoided in .c files\n" . $herecurr); | 3115 | WARN("AVOID_EXTERNS", |
3116 | "externs should be avoided in .c files\n" . $herecurr); | ||
2786 | } | 3117 | } |
2787 | 3118 | ||
2788 | # checks for new __setup's | 3119 | # checks for new __setup's |
@@ -2790,37 +3121,44 @@ sub process { | |||
2790 | my $name = $1; | 3121 | my $name = $1; |
2791 | 3122 | ||
2792 | if (!grep(/$name/, @setup_docs)) { | 3123 | if (!grep(/$name/, @setup_docs)) { |
2793 | CHK("__setup appears un-documented -- check Documentation/kernel-parameters.txt\n" . $herecurr); | 3124 | CHK("UNDOCUMENTED_SETUP", |
3125 | "__setup appears un-documented -- check Documentation/kernel-parameters.txt\n" . $herecurr); | ||
2794 | } | 3126 | } |
2795 | } | 3127 | } |
2796 | 3128 | ||
2797 | # check for pointless casting of kmalloc return | 3129 | # check for pointless casting of kmalloc return |
2798 | if ($line =~ /\*\s*\)\s*[kv][czm]alloc(_node){0,1}\b/) { | 3130 | if ($line =~ /\*\s*\)\s*[kv][czm]alloc(_node){0,1}\b/) { |
2799 | WARN("unnecessary cast may hide bugs, see http://c-faq.com/malloc/mallocnocast.html\n" . $herecurr); | 3131 | WARN("UNNECESSARY_CASTS", |
3132 | "unnecessary cast may hide bugs, see http://c-faq.com/malloc/mallocnocast.html\n" . $herecurr); | ||
2800 | } | 3133 | } |
2801 | 3134 | ||
2802 | # check for multiple semicolons | 3135 | # check for multiple semicolons |
2803 | if ($line =~ /;\s*;\s*$/) { | 3136 | if ($line =~ /;\s*;\s*$/) { |
2804 | WARN("Statements terminations use 1 semicolon\n" . $herecurr); | 3137 | WARN("ONE_SEMICOLON", |
3138 | "Statements terminations use 1 semicolon\n" . $herecurr); | ||
2805 | } | 3139 | } |
2806 | 3140 | ||
2807 | # check for gcc specific __FUNCTION__ | 3141 | # check for gcc specific __FUNCTION__ |
2808 | if ($line =~ /__FUNCTION__/) { | 3142 | if ($line =~ /__FUNCTION__/) { |
2809 | WARN("__func__ should be used instead of gcc specific __FUNCTION__\n" . $herecurr); | 3143 | WARN("USE_FUNC", |
3144 | "__func__ should be used instead of gcc specific __FUNCTION__\n" . $herecurr); | ||
2810 | } | 3145 | } |
2811 | 3146 | ||
2812 | # check for semaphores initialized locked | 3147 | # check for semaphores initialized locked |
2813 | if ($line =~ /^.\s*sema_init.+,\W?0\W?\)/) { | 3148 | if ($line =~ /^.\s*sema_init.+,\W?0\W?\)/) { |
2814 | WARN("consider using a completion\n" . $herecurr); | 3149 | WARN("CONSIDER_COMPLETION", |
3150 | "consider using a completion\n" . $herecurr); | ||
2815 | 3151 | ||
2816 | } | 3152 | } |
2817 | # recommend kstrto* over simple_strto* | 3153 | # recommend kstrto* over simple_strto* |
2818 | if ($line =~ /\bsimple_(strto.*?)\s*\(/) { | 3154 | if ($line =~ /\bsimple_(strto.*?)\s*\(/) { |
2819 | WARN("consider using kstrto* in preference to simple_$1\n" . $herecurr); | 3155 | WARN("CONSIDER_KSTRTO", |
3156 | "consider using kstrto* in preference to simple_$1\n" . $herecurr); | ||
2820 | } | 3157 | } |
2821 | # check for __initcall(), use device_initcall() explicitly please | 3158 | # check for __initcall(), use device_initcall() explicitly please |
2822 | if ($line =~ /^.\s*__initcall\s*\(/) { | 3159 | if ($line =~ /^.\s*__initcall\s*\(/) { |
2823 | WARN("please use device_initcall() instead of __initcall()\n" . $herecurr); | 3160 | WARN("USE_DEVICE_INITCALL", |
3161 | "please use device_initcall() instead of __initcall()\n" . $herecurr); | ||
2824 | } | 3162 | } |
2825 | # check for various ops structs, ensure they are const. | 3163 | # check for various ops structs, ensure they are const. |
2826 | my $struct_ops = qr{acpi_dock_ops| | 3164 | my $struct_ops = qr{acpi_dock_ops| |
@@ -2862,7 +3200,8 @@ sub process { | |||
2862 | wd_ops}x; | 3200 | wd_ops}x; |
2863 | if ($line !~ /\bconst\b/ && | 3201 | if ($line !~ /\bconst\b/ && |
2864 | $line =~ /\bstruct\s+($struct_ops)\b/) { | 3202 | $line =~ /\bstruct\s+($struct_ops)\b/) { |
2865 | WARN("struct $1 should normally be const\n" . | 3203 | WARN("CONST_STRUCT", |
3204 | "struct $1 should normally be const\n" . | ||
2866 | $herecurr); | 3205 | $herecurr); |
2867 | } | 3206 | } |
2868 | 3207 | ||
@@ -2875,7 +3214,8 @@ sub process { | |||
2875 | $line !~ /\[[^\]]*\.\.\.[^\]]*NR_CPUS[^\]]*\]/ && | 3214 | $line !~ /\[[^\]]*\.\.\.[^\]]*NR_CPUS[^\]]*\]/ && |
2876 | $line !~ /\[[^\]]*NR_CPUS[^\]]*\.\.\.[^\]]*\]/) | 3215 | $line !~ /\[[^\]]*NR_CPUS[^\]]*\.\.\.[^\]]*\]/) |
2877 | { | 3216 | { |
2878 | WARN("usage of NR_CPUS is often wrong - consider using cpu_possible(), num_possible_cpus(), for_each_possible_cpu(), etc\n" . $herecurr); | 3217 | WARN("NR_CPUS", |
3218 | "usage of NR_CPUS is often wrong - consider using cpu_possible(), num_possible_cpus(), for_each_possible_cpu(), etc\n" . $herecurr); | ||
2879 | } | 3219 | } |
2880 | 3220 | ||
2881 | # check for %L{u,d,i} in strings | 3221 | # check for %L{u,d,i} in strings |
@@ -2884,7 +3224,8 @@ sub process { | |||
2884 | $string = substr($rawline, $-[1], $+[1] - $-[1]); | 3224 | $string = substr($rawline, $-[1], $+[1] - $-[1]); |
2885 | $string =~ s/%%/__/g; | 3225 | $string =~ s/%%/__/g; |
2886 | if ($string =~ /(?<!%)%L[udi]/) { | 3226 | if ($string =~ /(?<!%)%L[udi]/) { |
2887 | WARN("\%Ld/%Lu are not-standard C, use %lld/%llu\n" . $herecurr); | 3227 | WARN("PRINTF_L", |
3228 | "\%Ld/%Lu are not-standard C, use %lld/%llu\n" . $herecurr); | ||
2888 | last; | 3229 | last; |
2889 | } | 3230 | } |
2890 | } | 3231 | } |
@@ -2892,9 +3233,11 @@ sub process { | |||
2892 | # whine mightly about in_atomic | 3233 | # whine mightly about in_atomic |
2893 | if ($line =~ /\bin_atomic\s*\(/) { | 3234 | if ($line =~ /\bin_atomic\s*\(/) { |
2894 | if ($realfile =~ m@^drivers/@) { | 3235 | if ($realfile =~ m@^drivers/@) { |
2895 | ERROR("do not use in_atomic in drivers\n" . $herecurr); | 3236 | ERROR("IN_ATOMIC", |
3237 | "do not use in_atomic in drivers\n" . $herecurr); | ||
2896 | } elsif ($realfile !~ m@^kernel/@) { | 3238 | } elsif ($realfile !~ m@^kernel/@) { |
2897 | WARN("use of in_atomic() is incorrect outside core kernel code\n" . $herecurr); | 3239 | WARN("IN_ATOMIC", |
3240 | "use of in_atomic() is incorrect outside core kernel code\n" . $herecurr); | ||
2898 | } | 3241 | } |
2899 | } | 3242 | } |
2900 | 3243 | ||
@@ -2904,18 +3247,21 @@ sub process { | |||
2904 | if ($realfile !~ m@^kernel/lockdep@ && | 3247 | if ($realfile !~ m@^kernel/lockdep@ && |
2905 | $realfile !~ m@^include/linux/lockdep@ && | 3248 | $realfile !~ m@^include/linux/lockdep@ && |
2906 | $realfile !~ m@^drivers/base/core@) { | 3249 | $realfile !~ m@^drivers/base/core@) { |
2907 | ERROR("lockdep_no_validate class is reserved for device->mutex.\n" . $herecurr); | 3250 | ERROR("LOCKDEP", |
3251 | "lockdep_no_validate class is reserved for device->mutex.\n" . $herecurr); | ||
2908 | } | 3252 | } |
2909 | } | 3253 | } |
2910 | 3254 | ||
2911 | if ($line =~ /debugfs_create_file.*S_IWUGO/ || | 3255 | if ($line =~ /debugfs_create_file.*S_IWUGO/ || |
2912 | $line =~ /DEVICE_ATTR.*S_IWUGO/ ) { | 3256 | $line =~ /DEVICE_ATTR.*S_IWUGO/ ) { |
2913 | WARN("Exporting world writable files is usually an error. Consider more restrictive permissions.\n" . $herecurr); | 3257 | WARN("EXPORTED_WORLD_WRITABLE", |
3258 | "Exporting world writable files is usually an error. Consider more restrictive permissions.\n" . $herecurr); | ||
2914 | } | 3259 | } |
2915 | 3260 | ||
2916 | # Check for memset with swapped arguments | 3261 | # Check for memset with swapped arguments |
2917 | if ($line =~ /memset.*\,(\ |)(0x|)0(\ |0|)\);/) { | 3262 | if ($line =~ /memset.*\,(\ |)(0x|)0(\ |0|)\);/) { |
2918 | ERROR("memset size is 3rd argument, not the second.\n" . $herecurr); | 3263 | ERROR("MEMSET", |
3264 | "memset size is 3rd argument, not the second.\n" . $herecurr); | ||
2919 | } | 3265 | } |
2920 | } | 3266 | } |
2921 | 3267 | ||
@@ -2938,10 +3284,12 @@ sub process { | |||
2938 | } | 3284 | } |
2939 | 3285 | ||
2940 | if (!$is_patch) { | 3286 | if (!$is_patch) { |
2941 | ERROR("Does not appear to be a unified-diff format patch\n"); | 3287 | ERROR("NOT_UNIFIED_DIFF", |
3288 | "Does not appear to be a unified-diff format patch\n"); | ||
2942 | } | 3289 | } |
2943 | if ($is_patch && $chk_signoff && $signoff == 0) { | 3290 | if ($is_patch && $chk_signoff && $signoff == 0) { |
2944 | ERROR("Missing Signed-off-by: line(s)\n"); | 3291 | ERROR("MISSING_SIGN_OFF", |
3292 | "Missing Signed-off-by: line(s)\n"); | ||
2945 | } | 3293 | } |
2946 | 3294 | ||
2947 | print report_dump(); | 3295 | print report_dump(); |
@@ -2963,13 +3311,25 @@ sub process { | |||
2963 | } | 3311 | } |
2964 | } | 3312 | } |
2965 | 3313 | ||
3314 | if (keys %ignore_type) { | ||
3315 | print "NOTE: Ignored message types:"; | ||
3316 | foreach my $ignore (sort keys %ignore_type) { | ||
3317 | print " $ignore"; | ||
3318 | } | ||
3319 | print "\n"; | ||
3320 | print "\n" if ($quiet == 0); | ||
3321 | } | ||
3322 | |||
2966 | if ($clean == 1 && $quiet == 0) { | 3323 | if ($clean == 1 && $quiet == 0) { |
2967 | print "$vname has no obvious style problems and is ready for submission.\n" | 3324 | print "$vname has no obvious style problems and is ready for submission.\n" |
2968 | } | 3325 | } |
2969 | if ($clean == 0 && $quiet == 0) { | 3326 | if ($clean == 0 && $quiet == 0) { |
2970 | print "$vname has style problems, please review. If any of these errors\n"; | 3327 | print << "EOM"; |
2971 | print "are false positives report them to the maintainer, see\n"; | 3328 | $vname has style problems, please review. |
2972 | print "CHECKPATCH in MAINTAINERS.\n"; | 3329 | |
3330 | If any of these errors are false positives, please report | ||
3331 | them to the maintainer, see CHECKPATCH in MAINTAINERS. | ||
3332 | EOM | ||
2973 | } | 3333 | } |
2974 | 3334 | ||
2975 | return $clean; | 3335 | return $clean; |
diff --git a/scripts/get_maintainer.pl b/scripts/get_maintainer.pl index d29a8d75cb22..eb2f1e64edf7 100755 --- a/scripts/get_maintainer.pl +++ b/scripts/get_maintainer.pl | |||
@@ -328,7 +328,8 @@ sub read_mailmap { | |||
328 | # name1 <mail1> <mail2> | 328 | # name1 <mail1> <mail2> |
329 | # name1 <mail1> name2 <mail2> | 329 | # name1 <mail1> name2 <mail2> |
330 | # (see man git-shortlog) | 330 | # (see man git-shortlog) |
331 | if (/^(.+)<(.+)>$/) { | 331 | |
332 | if (/^([^<]+)<([^>]+)>$/) { | ||
332 | my $real_name = $1; | 333 | my $real_name = $1; |
333 | my $address = $2; | 334 | my $address = $2; |
334 | 335 | ||
@@ -336,13 +337,13 @@ sub read_mailmap { | |||
336 | ($real_name, $address) = parse_email("$real_name <$address>"); | 337 | ($real_name, $address) = parse_email("$real_name <$address>"); |
337 | $mailmap->{names}->{$address} = $real_name; | 338 | $mailmap->{names}->{$address} = $real_name; |
338 | 339 | ||
339 | } elsif (/^<([^\s]+)>\s*<([^\s]+)>$/) { | 340 | } elsif (/^<([^>]+)>\s*<([^>]+)>$/) { |
340 | my $real_address = $1; | 341 | my $real_address = $1; |
341 | my $wrong_address = $2; | 342 | my $wrong_address = $2; |
342 | 343 | ||
343 | $mailmap->{addresses}->{$wrong_address} = $real_address; | 344 | $mailmap->{addresses}->{$wrong_address} = $real_address; |
344 | 345 | ||
345 | } elsif (/^(.+)<([^\s]+)>\s*<([^\s]+)>$/) { | 346 | } elsif (/^(.+)<([^>]+)>\s*<([^>]+)>$/) { |
346 | my $real_name = $1; | 347 | my $real_name = $1; |
347 | my $real_address = $2; | 348 | my $real_address = $2; |
348 | my $wrong_address = $3; | 349 | my $wrong_address = $3; |
@@ -353,7 +354,7 @@ sub read_mailmap { | |||
353 | $mailmap->{names}->{$wrong_address} = $real_name; | 354 | $mailmap->{names}->{$wrong_address} = $real_name; |
354 | $mailmap->{addresses}->{$wrong_address} = $real_address; | 355 | $mailmap->{addresses}->{$wrong_address} = $real_address; |
355 | 356 | ||
356 | } elsif (/^(.+)<([^\s]+)>\s*([^\s].*)<([^\s]+)>$/) { | 357 | } elsif (/^(.+)<([^>]+)>\s*(.+)\s*<([^>]+)>$/) { |
357 | my $real_name = $1; | 358 | my $real_name = $1; |
358 | my $real_address = $2; | 359 | my $real_address = $2; |
359 | my $wrong_name = $3; | 360 | my $wrong_name = $3; |