diff options
166 files changed, 3044 insertions, 1875 deletions
diff --git a/Documentation/ABI/testing/sysfs-class-rtc-rtc0-device-rtc_calibration b/Documentation/ABI/testing/sysfs-class-rtc-rtc0-device-rtc_calibration new file mode 100644 index 000000000000..4cf1e72222d9 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-class-rtc-rtc0-device-rtc_calibration | |||
@@ -0,0 +1,12 @@ | |||
1 | What: Attribute for calibrating ST-Ericsson AB8500 Real Time Clock | ||
2 | Date: Oct 2011 | ||
3 | KernelVersion: 3.0 | ||
4 | Contact: Mark Godfrey <mark.godfrey@stericsson.com> | ||
5 | Description: The rtc_calibration attribute allows the userspace to | ||
6 | calibrate the AB8500.s 32KHz Real Time Clock. | ||
7 | Every 60 seconds the AB8500 will correct the RTC's value | ||
8 | by adding to it the value of this attribute. | ||
9 | The range of the attribute is -127 to +127 in units of | ||
10 | 30.5 micro-seconds (half-parts-per-million of the 32KHz clock) | ||
11 | Users: The /vendor/st-ericsson/base_utilities/core/rtc_calibration | ||
12 | daemon uses this interface. | ||
diff --git a/Documentation/devicetree/bindings/rtc/twl-rtc.txt b/Documentation/devicetree/bindings/rtc/twl-rtc.txt new file mode 100644 index 000000000000..596e0c97be7a --- /dev/null +++ b/Documentation/devicetree/bindings/rtc/twl-rtc.txt | |||
@@ -0,0 +1,12 @@ | |||
1 | * TI twl RTC | ||
2 | |||
3 | The TWL family (twl4030/6030) contains a RTC. | ||
4 | |||
5 | Required properties: | ||
6 | - compatible : Should be twl4030-rtc | ||
7 | |||
8 | Examples: | ||
9 | |||
10 | rtc@0 { | ||
11 | compatible = "ti,twl4030-rtc"; | ||
12 | }; | ||
diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt index 0ec91f03422e..12fee132fbe2 100644 --- a/Documentation/filesystems/proc.txt +++ b/Documentation/filesystems/proc.txt | |||
@@ -41,6 +41,8 @@ Table of Contents | |||
41 | 3.5 /proc/<pid>/mountinfo - Information about mounts | 41 | 3.5 /proc/<pid>/mountinfo - Information about mounts |
42 | 3.6 /proc/<pid>/comm & /proc/<pid>/task/<tid>/comm | 42 | 3.6 /proc/<pid>/comm & /proc/<pid>/task/<tid>/comm |
43 | 43 | ||
44 | 4 Configuring procfs | ||
45 | 4.1 Mount options | ||
44 | 46 | ||
45 | ------------------------------------------------------------------------------ | 47 | ------------------------------------------------------------------------------ |
46 | Preface | 48 | Preface |
@@ -1542,3 +1544,40 @@ a task to set its own or one of its thread siblings comm value. The comm value | |||
1542 | is limited in size compared to the cmdline value, so writing anything longer | 1544 | is limited in size compared to the cmdline value, so writing anything longer |
1543 | then the kernel's TASK_COMM_LEN (currently 16 chars) will result in a truncated | 1545 | then the kernel's TASK_COMM_LEN (currently 16 chars) will result in a truncated |
1544 | comm value. | 1546 | comm value. |
1547 | |||
1548 | |||
1549 | ------------------------------------------------------------------------------ | ||
1550 | Configuring procfs | ||
1551 | ------------------------------------------------------------------------------ | ||
1552 | |||
1553 | 4.1 Mount options | ||
1554 | --------------------- | ||
1555 | |||
1556 | The following mount options are supported: | ||
1557 | |||
1558 | hidepid= Set /proc/<pid>/ access mode. | ||
1559 | gid= Set the group authorized to learn processes information. | ||
1560 | |||
1561 | hidepid=0 means classic mode - everybody may access all /proc/<pid>/ directories | ||
1562 | (default). | ||
1563 | |||
1564 | hidepid=1 means users may not access any /proc/<pid>/ directories but their | ||
1565 | own. Sensitive files like cmdline, sched*, status are now protected against | ||
1566 | other users. This makes it impossible to learn whether any user runs | ||
1567 | specific program (given the program doesn't reveal itself by its behaviour). | ||
1568 | As an additional bonus, as /proc/<pid>/cmdline is unaccessible for other users, | ||
1569 | poorly written programs passing sensitive information via program arguments are | ||
1570 | now protected against local eavesdroppers. | ||
1571 | |||
1572 | hidepid=2 means hidepid=1 plus all /proc/<pid>/ will be fully invisible to other | ||
1573 | users. It doesn't mean that it hides a fact whether a process with a specific | ||
1574 | pid value exists (it can be learned by other means, e.g. by "kill -0 $PID"), | ||
1575 | but it hides process' uid and gid, which may be learned by stat()'ing | ||
1576 | /proc/<pid>/ otherwise. It greatly complicates an intruder's task of gathering | ||
1577 | information about running processes, whether some daemon runs with elevated | ||
1578 | privileges, whether other user runs some sensitive program, whether other users | ||
1579 | run any program at all, etc. | ||
1580 | |||
1581 | gid= defines a group authorized to learn processes information otherwise | ||
1582 | prohibited by hidepid=. If you use some daemon like identd which needs to learn | ||
1583 | information about processes information, just add identd to this group. | ||
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 73baff1e0c70..c92b1532f05a 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt | |||
@@ -628,6 +628,25 @@ bytes respectively. Such letter suffixes can also be entirely omitted. | |||
628 | no_debug_objects | 628 | no_debug_objects |
629 | [KNL] Disable object debugging | 629 | [KNL] Disable object debugging |
630 | 630 | ||
631 | debug_guardpage_minorder= | ||
632 | [KNL] When CONFIG_DEBUG_PAGEALLOC is set, this | ||
633 | parameter allows control of the order of pages that will | ||
634 | be intentionally kept free (and hence protected) by the | ||
635 | buddy allocator. Bigger value increase the probability | ||
636 | of catching random memory corruption, but reduce the | ||
637 | amount of memory for normal system use. The maximum | ||
638 | possible value is MAX_ORDER/2. Setting this parameter | ||
639 | to 1 or 2 should be enough to identify most random | ||
640 | memory corruption problems caused by bugs in kernel or | ||
641 | driver code when a CPU writes to (or reads from) a | ||
642 | random memory location. Note that there exists a class | ||
643 | of memory corruptions problems caused by buggy H/W or | ||
644 | F/W or by drivers badly programing DMA (basically when | ||
645 | memory is written at bus level and the CPU MMU is | ||
646 | bypassed) which are not detectable by | ||
647 | CONFIG_DEBUG_PAGEALLOC, hence this option will not help | ||
648 | tracking down these problems. | ||
649 | |||
631 | debugpat [X86] Enable PAT debugging | 650 | debugpat [X86] Enable PAT debugging |
632 | 651 | ||
633 | decnet.addr= [HW,NET] | 652 | decnet.addr= [HW,NET] |
diff --git a/Documentation/trace/events-kmem.txt b/Documentation/trace/events-kmem.txt index aa82ee4a5a87..194800410061 100644 --- a/Documentation/trace/events-kmem.txt +++ b/Documentation/trace/events-kmem.txt | |||
@@ -40,8 +40,8 @@ but the call_site can usually be used to extrapolate that information. | |||
40 | ================== | 40 | ================== |
41 | mm_page_alloc page=%p pfn=%lu order=%d migratetype=%d gfp_flags=%s | 41 | mm_page_alloc page=%p pfn=%lu order=%d migratetype=%d gfp_flags=%s |
42 | mm_page_alloc_zone_locked page=%p pfn=%lu order=%u migratetype=%d cpu=%d percpu_refill=%d | 42 | mm_page_alloc_zone_locked page=%p pfn=%lu order=%u migratetype=%d cpu=%d percpu_refill=%d |
43 | mm_page_free_direct page=%p pfn=%lu order=%d | 43 | mm_page_free page=%p pfn=%lu order=%d |
44 | mm_pagevec_free page=%p pfn=%lu order=%d cold=%d | 44 | mm_page_free_batched page=%p pfn=%lu order=%d cold=%d |
45 | 45 | ||
46 | These four events deal with page allocation and freeing. mm_page_alloc is | 46 | These four events deal with page allocation and freeing. mm_page_alloc is |
47 | a simple indicator of page allocator activity. Pages may be allocated from | 47 | a simple indicator of page allocator activity. Pages may be allocated from |
@@ -53,13 +53,13 @@ amounts of activity imply high activity on the zone->lock. Taking this lock | |||
53 | impairs performance by disabling interrupts, dirtying cache lines between | 53 | impairs performance by disabling interrupts, dirtying cache lines between |
54 | CPUs and serialising many CPUs. | 54 | CPUs and serialising many CPUs. |
55 | 55 | ||
56 | When a page is freed directly by the caller, the mm_page_free_direct event | 56 | When a page is freed directly by the caller, the only mm_page_free event |
57 | is triggered. Significant amounts of activity here could indicate that the | 57 | is triggered. Significant amounts of activity here could indicate that the |
58 | callers should be batching their activities. | 58 | callers should be batching their activities. |
59 | 59 | ||
60 | When pages are freed using a pagevec, the mm_pagevec_free is | 60 | When pages are freed in batch, the also mm_page_free_batched is triggered. |
61 | triggered. Broadly speaking, pages are taken off the LRU lock in bulk and | 61 | Broadly speaking, pages are taken off the LRU lock in bulk and |
62 | freed in batch with a pagevec. Significant amounts of activity here could | 62 | freed in batch with a page list. Significant amounts of activity here could |
63 | indicate that the system is under memory pressure and can also indicate | 63 | indicate that the system is under memory pressure and can also indicate |
64 | contention on the zone->lru_lock. | 64 | contention on the zone->lru_lock. |
65 | 65 | ||
diff --git a/Documentation/trace/postprocess/trace-pagealloc-postprocess.pl b/Documentation/trace/postprocess/trace-pagealloc-postprocess.pl index 7df50e8cf4d9..0a120aae33ce 100644 --- a/Documentation/trace/postprocess/trace-pagealloc-postprocess.pl +++ b/Documentation/trace/postprocess/trace-pagealloc-postprocess.pl | |||
@@ -17,8 +17,8 @@ use Getopt::Long; | |||
17 | 17 | ||
18 | # Tracepoint events | 18 | # Tracepoint events |
19 | use constant MM_PAGE_ALLOC => 1; | 19 | use constant MM_PAGE_ALLOC => 1; |
20 | use constant MM_PAGE_FREE_DIRECT => 2; | 20 | use constant MM_PAGE_FREE => 2; |
21 | use constant MM_PAGEVEC_FREE => 3; | 21 | use constant MM_PAGE_FREE_BATCHED => 3; |
22 | use constant MM_PAGE_PCPU_DRAIN => 4; | 22 | use constant MM_PAGE_PCPU_DRAIN => 4; |
23 | use constant MM_PAGE_ALLOC_ZONE_LOCKED => 5; | 23 | use constant MM_PAGE_ALLOC_ZONE_LOCKED => 5; |
24 | use constant MM_PAGE_ALLOC_EXTFRAG => 6; | 24 | use constant MM_PAGE_ALLOC_EXTFRAG => 6; |
@@ -223,10 +223,10 @@ EVENT_PROCESS: | |||
223 | # Perl Switch() sucks majorly | 223 | # Perl Switch() sucks majorly |
224 | if ($tracepoint eq "mm_page_alloc") { | 224 | if ($tracepoint eq "mm_page_alloc") { |
225 | $perprocesspid{$process_pid}->{MM_PAGE_ALLOC}++; | 225 | $perprocesspid{$process_pid}->{MM_PAGE_ALLOC}++; |
226 | } elsif ($tracepoint eq "mm_page_free_direct") { | 226 | } elsif ($tracepoint eq "mm_page_free") { |
227 | $perprocesspid{$process_pid}->{MM_PAGE_FREE_DIRECT}++; | 227 | $perprocesspid{$process_pid}->{MM_PAGE_FREE}++ |
228 | } elsif ($tracepoint eq "mm_pagevec_free") { | 228 | } elsif ($tracepoint eq "mm_page_free_batched") { |
229 | $perprocesspid{$process_pid}->{MM_PAGEVEC_FREE}++; | 229 | $perprocesspid{$process_pid}->{MM_PAGE_FREE_BATCHED}++; |
230 | } elsif ($tracepoint eq "mm_page_pcpu_drain") { | 230 | } elsif ($tracepoint eq "mm_page_pcpu_drain") { |
231 | $perprocesspid{$process_pid}->{MM_PAGE_PCPU_DRAIN}++; | 231 | $perprocesspid{$process_pid}->{MM_PAGE_PCPU_DRAIN}++; |
232 | $perprocesspid{$process_pid}->{STATE_PCPU_PAGES_DRAINED}++; | 232 | $perprocesspid{$process_pid}->{STATE_PCPU_PAGES_DRAINED}++; |
@@ -336,8 +336,8 @@ sub dump_stats { | |||
336 | $process_pid, | 336 | $process_pid, |
337 | $stats{$process_pid}->{MM_PAGE_ALLOC}, | 337 | $stats{$process_pid}->{MM_PAGE_ALLOC}, |
338 | $stats{$process_pid}->{MM_PAGE_ALLOC_ZONE_LOCKED}, | 338 | $stats{$process_pid}->{MM_PAGE_ALLOC_ZONE_LOCKED}, |
339 | $stats{$process_pid}->{MM_PAGE_FREE_DIRECT}, | 339 | $stats{$process_pid}->{MM_PAGE_FREE}, |
340 | $stats{$process_pid}->{MM_PAGEVEC_FREE}, | 340 | $stats{$process_pid}->{MM_PAGE_FREE_BATCHED}, |
341 | $stats{$process_pid}->{MM_PAGE_PCPU_DRAIN}, | 341 | $stats{$process_pid}->{MM_PAGE_PCPU_DRAIN}, |
342 | $stats{$process_pid}->{HIGH_PCPU_DRAINS}, | 342 | $stats{$process_pid}->{HIGH_PCPU_DRAINS}, |
343 | $stats{$process_pid}->{HIGH_PCPU_REFILLS}, | 343 | $stats{$process_pid}->{HIGH_PCPU_REFILLS}, |
@@ -364,8 +364,8 @@ sub aggregate_perprocesspid() { | |||
364 | 364 | ||
365 | $perprocess{$process}->{MM_PAGE_ALLOC} += $perprocesspid{$process_pid}->{MM_PAGE_ALLOC}; | 365 | $perprocess{$process}->{MM_PAGE_ALLOC} += $perprocesspid{$process_pid}->{MM_PAGE_ALLOC}; |
366 | $perprocess{$process}->{MM_PAGE_ALLOC_ZONE_LOCKED} += $perprocesspid{$process_pid}->{MM_PAGE_ALLOC_ZONE_LOCKED}; | 366 | $perprocess{$process}->{MM_PAGE_ALLOC_ZONE_LOCKED} += $perprocesspid{$process_pid}->{MM_PAGE_ALLOC_ZONE_LOCKED}; |
367 | $perprocess{$process}->{MM_PAGE_FREE_DIRECT} += $perprocesspid{$process_pid}->{MM_PAGE_FREE_DIRECT}; | 367 | $perprocess{$process}->{MM_PAGE_FREE} += $perprocesspid{$process_pid}->{MM_PAGE_FREE}; |
368 | $perprocess{$process}->{MM_PAGEVEC_FREE} += $perprocesspid{$process_pid}->{MM_PAGEVEC_FREE}; | 368 | $perprocess{$process}->{MM_PAGE_FREE_BATCHED} += $perprocesspid{$process_pid}->{MM_PAGE_FREE_BATCHED}; |
369 | $perprocess{$process}->{MM_PAGE_PCPU_DRAIN} += $perprocesspid{$process_pid}->{MM_PAGE_PCPU_DRAIN}; | 369 | $perprocess{$process}->{MM_PAGE_PCPU_DRAIN} += $perprocesspid{$process_pid}->{MM_PAGE_PCPU_DRAIN}; |
370 | $perprocess{$process}->{HIGH_PCPU_DRAINS} += $perprocesspid{$process_pid}->{HIGH_PCPU_DRAINS}; | 370 | $perprocess{$process}->{HIGH_PCPU_DRAINS} += $perprocesspid{$process_pid}->{HIGH_PCPU_DRAINS}; |
371 | $perprocess{$process}->{HIGH_PCPU_REFILLS} += $perprocesspid{$process_pid}->{HIGH_PCPU_REFILLS}; | 371 | $perprocess{$process}->{HIGH_PCPU_REFILLS} += $perprocesspid{$process_pid}->{HIGH_PCPU_REFILLS}; |
diff --git a/Documentation/trace/tracepoint-analysis.txt b/Documentation/trace/tracepoint-analysis.txt index 87bee3c129ba..058cc6c9dc56 100644 --- a/Documentation/trace/tracepoint-analysis.txt +++ b/Documentation/trace/tracepoint-analysis.txt | |||
@@ -93,14 +93,14 @@ By specifying the -a switch and analysing sleep, the system-wide events | |||
93 | for a duration of time can be examined. | 93 | for a duration of time can be examined. |
94 | 94 | ||
95 | $ perf stat -a \ | 95 | $ perf stat -a \ |
96 | -e kmem:mm_page_alloc -e kmem:mm_page_free_direct \ | 96 | -e kmem:mm_page_alloc -e kmem:mm_page_free \ |
97 | -e kmem:mm_pagevec_free \ | 97 | -e kmem:mm_page_free_batched \ |
98 | sleep 10 | 98 | sleep 10 |
99 | Performance counter stats for 'sleep 10': | 99 | Performance counter stats for 'sleep 10': |
100 | 100 | ||
101 | 9630 kmem:mm_page_alloc | 101 | 9630 kmem:mm_page_alloc |
102 | 2143 kmem:mm_page_free_direct | 102 | 2143 kmem:mm_page_free |
103 | 7424 kmem:mm_pagevec_free | 103 | 7424 kmem:mm_page_free_batched |
104 | 104 | ||
105 | 10.002577764 seconds time elapsed | 105 | 10.002577764 seconds time elapsed |
106 | 106 | ||
@@ -119,15 +119,15 @@ basis using set_ftrace_pid. | |||
119 | Events can be activated and tracked for the duration of a process on a local | 119 | Events can be activated and tracked for the duration of a process on a local |
120 | basis using PCL such as follows. | 120 | basis using PCL such as follows. |
121 | 121 | ||
122 | $ perf stat -e kmem:mm_page_alloc -e kmem:mm_page_free_direct \ | 122 | $ perf stat -e kmem:mm_page_alloc -e kmem:mm_page_free \ |
123 | -e kmem:mm_pagevec_free ./hackbench 10 | 123 | -e kmem:mm_page_free_batched ./hackbench 10 |
124 | Time: 0.909 | 124 | Time: 0.909 |
125 | 125 | ||
126 | Performance counter stats for './hackbench 10': | 126 | Performance counter stats for './hackbench 10': |
127 | 127 | ||
128 | 17803 kmem:mm_page_alloc | 128 | 17803 kmem:mm_page_alloc |
129 | 12398 kmem:mm_page_free_direct | 129 | 12398 kmem:mm_page_free |
130 | 4827 kmem:mm_pagevec_free | 130 | 4827 kmem:mm_page_free_batched |
131 | 131 | ||
132 | 0.973913387 seconds time elapsed | 132 | 0.973913387 seconds time elapsed |
133 | 133 | ||
@@ -146,8 +146,8 @@ to know what the standard deviation is. By and large, this is left to the | |||
146 | performance analyst to do it by hand. In the event that the discrete event | 146 | performance analyst to do it by hand. In the event that the discrete event |
147 | occurrences are useful to the performance analyst, then perf can be used. | 147 | occurrences are useful to the performance analyst, then perf can be used. |
148 | 148 | ||
149 | $ perf stat --repeat 5 -e kmem:mm_page_alloc -e kmem:mm_page_free_direct | 149 | $ perf stat --repeat 5 -e kmem:mm_page_alloc -e kmem:mm_page_free |
150 | -e kmem:mm_pagevec_free ./hackbench 10 | 150 | -e kmem:mm_page_free_batched ./hackbench 10 |
151 | Time: 0.890 | 151 | Time: 0.890 |
152 | Time: 0.895 | 152 | Time: 0.895 |
153 | Time: 0.915 | 153 | Time: 0.915 |
@@ -157,8 +157,8 @@ occurrences are useful to the performance analyst, then perf can be used. | |||
157 | Performance counter stats for './hackbench 10' (5 runs): | 157 | Performance counter stats for './hackbench 10' (5 runs): |
158 | 158 | ||
159 | 16630 kmem:mm_page_alloc ( +- 3.542% ) | 159 | 16630 kmem:mm_page_alloc ( +- 3.542% ) |
160 | 11486 kmem:mm_page_free_direct ( +- 4.771% ) | 160 | 11486 kmem:mm_page_free ( +- 4.771% ) |
161 | 4730 kmem:mm_pagevec_free ( +- 2.325% ) | 161 | 4730 kmem:mm_page_free_batched ( +- 2.325% ) |
162 | 162 | ||
163 | 0.982653002 seconds time elapsed ( +- 1.448% ) | 163 | 0.982653002 seconds time elapsed ( +- 1.448% ) |
164 | 164 | ||
@@ -168,15 +168,15 @@ aggregation of discrete events, then a script would need to be developed. | |||
168 | Using --repeat, it is also possible to view how events are fluctuating over | 168 | Using --repeat, it is also possible to view how events are fluctuating over |
169 | time on a system-wide basis using -a and sleep. | 169 | time on a system-wide basis using -a and sleep. |
170 | 170 | ||
171 | $ perf stat -e kmem:mm_page_alloc -e kmem:mm_page_free_direct \ | 171 | $ perf stat -e kmem:mm_page_alloc -e kmem:mm_page_free \ |
172 | -e kmem:mm_pagevec_free \ | 172 | -e kmem:mm_page_free_batched \ |
173 | -a --repeat 10 \ | 173 | -a --repeat 10 \ |
174 | sleep 1 | 174 | sleep 1 |
175 | Performance counter stats for 'sleep 1' (10 runs): | 175 | Performance counter stats for 'sleep 1' (10 runs): |
176 | 176 | ||
177 | 1066 kmem:mm_page_alloc ( +- 26.148% ) | 177 | 1066 kmem:mm_page_alloc ( +- 26.148% ) |
178 | 182 kmem:mm_page_free_direct ( +- 5.464% ) | 178 | 182 kmem:mm_page_free ( +- 5.464% ) |
179 | 890 kmem:mm_pagevec_free ( +- 30.079% ) | 179 | 890 kmem:mm_page_free_batched ( +- 30.079% ) |
180 | 180 | ||
181 | 1.002251757 seconds time elapsed ( +- 0.005% ) | 181 | 1.002251757 seconds time elapsed ( +- 0.005% ) |
182 | 182 | ||
@@ -220,8 +220,8 @@ were generating events within the kernel. To begin this sort of analysis, the | |||
220 | data must be recorded. At the time of writing, this required root: | 220 | data must be recorded. At the time of writing, this required root: |
221 | 221 | ||
222 | $ perf record -c 1 \ | 222 | $ perf record -c 1 \ |
223 | -e kmem:mm_page_alloc -e kmem:mm_page_free_direct \ | 223 | -e kmem:mm_page_alloc -e kmem:mm_page_free \ |
224 | -e kmem:mm_pagevec_free \ | 224 | -e kmem:mm_page_free_batched \ |
225 | ./hackbench 10 | 225 | ./hackbench 10 |
226 | Time: 0.894 | 226 | Time: 0.894 |
227 | [ perf record: Captured and wrote 0.733 MB perf.data (~32010 samples) ] | 227 | [ perf record: Captured and wrote 0.733 MB perf.data (~32010 samples) ] |
@@ -260,8 +260,8 @@ noticed that X was generating an insane amount of page allocations so let's look | |||
260 | at it: | 260 | at it: |
261 | 261 | ||
262 | $ perf record -c 1 -f \ | 262 | $ perf record -c 1 -f \ |
263 | -e kmem:mm_page_alloc -e kmem:mm_page_free_direct \ | 263 | -e kmem:mm_page_alloc -e kmem:mm_page_free \ |
264 | -e kmem:mm_pagevec_free \ | 264 | -e kmem:mm_page_free_batched \ |
265 | -p `pidof X` | 265 | -p `pidof X` |
266 | 266 | ||
267 | This was interrupted after a few seconds and | 267 | This was interrupted after a few seconds and |
diff --git a/MAINTAINERS b/MAINTAINERS index a2883a283698..0460f6550e4b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -342,7 +342,7 @@ S: Supported | |||
342 | F: drivers/mfd/adp5520.c | 342 | F: drivers/mfd/adp5520.c |
343 | F: drivers/video/backlight/adp5520_bl.c | 343 | F: drivers/video/backlight/adp5520_bl.c |
344 | F: drivers/leds/leds-adp5520.c | 344 | F: drivers/leds/leds-adp5520.c |
345 | F: drivers/gpio/adp5520-gpio.c | 345 | F: drivers/gpio/gpio-adp5520.c |
346 | F: drivers/input/keyboard/adp5520-keys.c | 346 | F: drivers/input/keyboard/adp5520-keys.c |
347 | 347 | ||
348 | ADP5588 QWERTY KEYPAD AND IO EXPANDER DRIVER (ADP5588/ADP5587) | 348 | ADP5588 QWERTY KEYPAD AND IO EXPANDER DRIVER (ADP5588/ADP5587) |
@@ -351,7 +351,7 @@ L: device-drivers-devel@blackfin.uclinux.org | |||
351 | W: http://wiki.analog.com/ADP5588 | 351 | W: http://wiki.analog.com/ADP5588 |
352 | S: Supported | 352 | S: Supported |
353 | F: drivers/input/keyboard/adp5588-keys.c | 353 | F: drivers/input/keyboard/adp5588-keys.c |
354 | F: drivers/gpio/adp5588-gpio.c | 354 | F: drivers/gpio/gpio-adp5588.c |
355 | 355 | ||
356 | ADP8860 BACKLIGHT DRIVER (ADP8860/ADP8861/ADP8863) | 356 | ADP8860 BACKLIGHT DRIVER (ADP8860/ADP8861/ADP8863) |
357 | M: Michael Hennerich <michael.hennerich@analog.com> | 357 | M: Michael Hennerich <michael.hennerich@analog.com> |
@@ -914,7 +914,6 @@ M: Lennert Buytenhek <kernel@wantstofly.org> | |||
914 | M: Nicolas Pitre <nico@fluxnic.net> | 914 | M: Nicolas Pitre <nico@fluxnic.net> |
915 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) | 915 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) |
916 | S: Odd Fixes | 916 | S: Odd Fixes |
917 | F: arch/arm/mach-loki/ | ||
918 | F: arch/arm/mach-kirkwood/ | 917 | F: arch/arm/mach-kirkwood/ |
919 | F: arch/arm/mach-mv78xx0/ | 918 | F: arch/arm/mach-mv78xx0/ |
920 | F: arch/arm/mach-orion5x/ | 919 | F: arch/arm/mach-orion5x/ |
@@ -1076,8 +1075,8 @@ L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) | |||
1076 | S: Maintained | 1075 | S: Maintained |
1077 | F: arch/arm/mach-s5pv210/mach-aquila.c | 1076 | F: arch/arm/mach-s5pv210/mach-aquila.c |
1078 | F: arch/arm/mach-s5pv210/mach-goni.c | 1077 | F: arch/arm/mach-s5pv210/mach-goni.c |
1079 | F: arch/arm/mach-exynos4/mach-universal_c210.c | 1078 | F: arch/arm/mach-exynos/mach-universal_c210.c |
1080 | F: arch/arm/mach-exynos4/mach-nuri.c | 1079 | F: arch/arm/mach-exynos/mach-nuri.c |
1081 | 1080 | ||
1082 | ARM/SAMSUNG S5P SERIES FIMC SUPPORT | 1081 | ARM/SAMSUNG S5P SERIES FIMC SUPPORT |
1083 | M: Kyungmin Park <kyungmin.park@samsung.com> | 1082 | M: Kyungmin Park <kyungmin.park@samsung.com> |
@@ -1105,7 +1104,6 @@ M: Tomasz Stanislawski <t.stanislaws@samsung.com> | |||
1105 | L: linux-arm-kernel@lists.infradead.org | 1104 | L: linux-arm-kernel@lists.infradead.org |
1106 | L: linux-media@vger.kernel.org | 1105 | L: linux-media@vger.kernel.org |
1107 | S: Maintained | 1106 | S: Maintained |
1108 | F: arch/arm/plat-s5p/dev-tv.c | ||
1109 | F: drivers/media/video/s5p-tv/ | 1107 | F: drivers/media/video/s5p-tv/ |
1110 | 1108 | ||
1111 | ARM/SHMOBILE ARM ARCHITECTURE | 1109 | ARM/SHMOBILE ARM ARCHITECTURE |
@@ -1140,14 +1138,13 @@ L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) | |||
1140 | W: http://www.mcuos.com | 1138 | W: http://www.mcuos.com |
1141 | S: Maintained | 1139 | S: Maintained |
1142 | F: arch/arm/mach-w90x900/ | 1140 | F: arch/arm/mach-w90x900/ |
1143 | F: arch/arm/mach-nuc93x/ | ||
1144 | F: drivers/input/keyboard/w90p910_keypad.c | 1141 | F: drivers/input/keyboard/w90p910_keypad.c |
1145 | F: drivers/input/touchscreen/w90p910_ts.c | 1142 | F: drivers/input/touchscreen/w90p910_ts.c |
1146 | F: drivers/watchdog/nuc900_wdt.c | 1143 | F: drivers/watchdog/nuc900_wdt.c |
1147 | F: drivers/net/ethernet/nuvoton/w90p910_ether.c | 1144 | F: drivers/net/ethernet/nuvoton/w90p910_ether.c |
1148 | F: drivers/mtd/nand/nuc900_nand.c | 1145 | F: drivers/mtd/nand/nuc900_nand.c |
1149 | F: drivers/rtc/rtc-nuc900.c | 1146 | F: drivers/rtc/rtc-nuc900.c |
1150 | F: drivers/spi/spi_nuc900.c | 1147 | F: drivers/spi/spi-nuc900.c |
1151 | F: drivers/usb/host/ehci-w90x900.c | 1148 | F: drivers/usb/host/ehci-w90x900.c |
1152 | F: drivers/video/nuc900fb.c | 1149 | F: drivers/video/nuc900fb.c |
1153 | 1150 | ||
@@ -1172,7 +1169,6 @@ L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) | |||
1172 | S: Maintained | 1169 | S: Maintained |
1173 | F: arch/arm/mach-ux500/ | 1170 | F: arch/arm/mach-ux500/ |
1174 | F: drivers/dma/ste_dma40* | 1171 | F: drivers/dma/ste_dma40* |
1175 | F: drivers/mfd/ab3550* | ||
1176 | F: drivers/mfd/abx500* | 1172 | F: drivers/mfd/abx500* |
1177 | F: drivers/mfd/ab8500* | 1173 | F: drivers/mfd/ab8500* |
1178 | F: drivers/mfd/stmpe* | 1174 | F: drivers/mfd/stmpe* |
@@ -1352,7 +1348,7 @@ F: drivers/net/ethernet/cadence/ | |||
1352 | ATMEL SPI DRIVER | 1348 | ATMEL SPI DRIVER |
1353 | M: Nicolas Ferre <nicolas.ferre@atmel.com> | 1349 | M: Nicolas Ferre <nicolas.ferre@atmel.com> |
1354 | S: Supported | 1350 | S: Supported |
1355 | F: drivers/spi/atmel_spi.* | 1351 | F: drivers/spi/spi-atmel.* |
1356 | 1352 | ||
1357 | ATMEL USBA UDC DRIVER | 1353 | ATMEL USBA UDC DRIVER |
1358 | M: Nicolas Ferre <nicolas.ferre@atmel.com> | 1354 | M: Nicolas Ferre <nicolas.ferre@atmel.com> |
@@ -1491,7 +1487,7 @@ M: Sonic Zhang <sonic.zhang@analog.com> | |||
1491 | L: uclinux-dist-devel@blackfin.uclinux.org | 1487 | L: uclinux-dist-devel@blackfin.uclinux.org |
1492 | W: http://blackfin.uclinux.org | 1488 | W: http://blackfin.uclinux.org |
1493 | S: Supported | 1489 | S: Supported |
1494 | F: drivers/tty/serial/bfin_5xx.c | 1490 | F: drivers/tty/serial/bfin_uart.c |
1495 | 1491 | ||
1496 | BLACKFIN WATCHDOG DRIVER | 1492 | BLACKFIN WATCHDOG DRIVER |
1497 | M: Mike Frysinger <vapier.adi@gmail.com> | 1493 | M: Mike Frysinger <vapier.adi@gmail.com> |
@@ -1621,7 +1617,7 @@ BT8XXGPIO DRIVER | |||
1621 | M: Michael Buesch <m@bues.ch> | 1617 | M: Michael Buesch <m@bues.ch> |
1622 | W: http://bu3sch.de/btgpio.php | 1618 | W: http://bu3sch.de/btgpio.php |
1623 | S: Maintained | 1619 | S: Maintained |
1624 | F: drivers/gpio/bt8xxgpio.c | 1620 | F: drivers/gpio/gpio-bt8xx.c |
1625 | 1621 | ||
1626 | BTRFS FILE SYSTEM | 1622 | BTRFS FILE SYSTEM |
1627 | M: Chris Mason <chris.mason@oracle.com> | 1623 | M: Chris Mason <chris.mason@oracle.com> |
@@ -1662,7 +1658,7 @@ L: linux-media@vger.kernel.org | |||
1662 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git | 1658 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git |
1663 | S: Maintained | 1659 | S: Maintained |
1664 | F: Documentation/video4linux/cafe_ccic | 1660 | F: Documentation/video4linux/cafe_ccic |
1665 | F: drivers/media/video/cafe_ccic* | 1661 | F: drivers/media/video/marvell-ccic/ |
1666 | 1662 | ||
1667 | CAIF NETWORK LAYER | 1663 | CAIF NETWORK LAYER |
1668 | M: Sjur Braendeland <sjur.brandeland@stericsson.com> | 1664 | M: Sjur Braendeland <sjur.brandeland@stericsson.com> |
@@ -2100,7 +2096,7 @@ DAVICOM FAST ETHERNET (DMFE) NETWORK DRIVER | |||
2100 | L: netdev@vger.kernel.org | 2096 | L: netdev@vger.kernel.org |
2101 | S: Orphan | 2097 | S: Orphan |
2102 | F: Documentation/networking/dmfe.txt | 2098 | F: Documentation/networking/dmfe.txt |
2103 | F: drivers/net/ethernet/tulip/dmfe.c | 2099 | F: drivers/net/ethernet/dec/tulip/dmfe.c |
2104 | 2100 | ||
2105 | DC390/AM53C974 SCSI driver | 2101 | DC390/AM53C974 SCSI driver |
2106 | M: Kurt Garloff <garloff@suse.de> | 2102 | M: Kurt Garloff <garloff@suse.de> |
@@ -2173,6 +2169,13 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git | |||
2173 | S: Maintained | 2169 | S: Maintained |
2174 | F: drivers/usb/dwc3/ | 2170 | F: drivers/usb/dwc3/ |
2175 | 2171 | ||
2172 | DEVICE FREQUENCY (DEVFREQ) | ||
2173 | M: MyungJoo Ham <myungjoo.ham@samsung.com> | ||
2174 | M: Kyungmin Park <kyungmin.park@samsung.com> | ||
2175 | L: linux-kernel@vger.kernel.org | ||
2176 | S: Maintained | ||
2177 | F: drivers/devfreq/ | ||
2178 | |||
2176 | DEVICE NUMBER REGISTRY | 2179 | DEVICE NUMBER REGISTRY |
2177 | M: Torben Mathiasen <device@lanana.org> | 2180 | M: Torben Mathiasen <device@lanana.org> |
2178 | W: http://lanana.org/docs/device-list/index.html | 2181 | W: http://lanana.org/docs/device-list/index.html |
@@ -2910,7 +2913,7 @@ GRETH 10/100/1G Ethernet MAC device driver | |||
2910 | M: Kristoffer Glembo <kristoffer@gaisler.com> | 2913 | M: Kristoffer Glembo <kristoffer@gaisler.com> |
2911 | L: netdev@vger.kernel.org | 2914 | L: netdev@vger.kernel.org |
2912 | S: Maintained | 2915 | S: Maintained |
2913 | F: drivers/net/greth* | 2916 | F: drivers/net/ethernet/aeroflex/ |
2914 | 2917 | ||
2915 | GSPCA FINEPIX SUBDRIVER | 2918 | GSPCA FINEPIX SUBDRIVER |
2916 | M: Frank Zago <frank@zago.net> | 2919 | M: Frank Zago <frank@zago.net> |
@@ -3860,8 +3863,7 @@ L: keyrings@linux-nfs.org | |||
3860 | S: Supported | 3863 | S: Supported |
3861 | F: Documentation/security/keys-trusted-encrypted.txt | 3864 | F: Documentation/security/keys-trusted-encrypted.txt |
3862 | F: include/keys/encrypted-type.h | 3865 | F: include/keys/encrypted-type.h |
3863 | F: security/keys/encrypted.c | 3866 | F: security/keys/encrypted-keys/ |
3864 | F: security/keys/encrypted.h | ||
3865 | 3867 | ||
3866 | KGDB / KDB /debug_core | 3868 | KGDB / KDB /debug_core |
3867 | M: Jason Wessel <jason.wessel@windriver.com> | 3869 | M: Jason Wessel <jason.wessel@windriver.com> |
@@ -5313,7 +5315,7 @@ T: git git://git.linaro.org/people/ycmiao/pxa-linux.git | |||
5313 | S: Maintained | 5315 | S: Maintained |
5314 | F: arch/arm/mach-pxa/ | 5316 | F: arch/arm/mach-pxa/ |
5315 | F: drivers/pcmcia/pxa2xx* | 5317 | F: drivers/pcmcia/pxa2xx* |
5316 | F: drivers/spi/pxa2xx* | 5318 | F: drivers/spi/spi-pxa2xx* |
5317 | F: drivers/usb/gadget/pxa2* | 5319 | F: drivers/usb/gadget/pxa2* |
5318 | F: include/sound/pxa2xx-lib.h | 5320 | F: include/sound/pxa2xx-lib.h |
5319 | F: sound/arm/pxa* | 5321 | F: sound/arm/pxa* |
@@ -5795,13 +5797,14 @@ L: linux-mmc@vger.kernel.org | |||
5795 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc.git | 5797 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc.git |
5796 | S: Maintained | 5798 | S: Maintained |
5797 | F: drivers/mmc/host/sdhci.* | 5799 | F: drivers/mmc/host/sdhci.* |
5800 | F: drivers/mmc/host/sdhci-pltfm.[ch] | ||
5798 | 5801 | ||
5799 | SECURE DIGITAL HOST CONTROLLER INTERFACE, OPEN FIRMWARE BINDINGS (SDHCI-OF) | 5802 | SECURE DIGITAL HOST CONTROLLER INTERFACE, OPEN FIRMWARE BINDINGS (SDHCI-OF) |
5800 | M: Anton Vorontsov <avorontsov@ru.mvista.com> | 5803 | M: Anton Vorontsov <avorontsov@ru.mvista.com> |
5801 | L: linuxppc-dev@lists.ozlabs.org | 5804 | L: linuxppc-dev@lists.ozlabs.org |
5802 | L: linux-mmc@vger.kernel.org | 5805 | L: linux-mmc@vger.kernel.org |
5803 | S: Maintained | 5806 | S: Maintained |
5804 | F: drivers/mmc/host/sdhci-of.* | 5807 | F: drivers/mmc/host/sdhci-pltfm.[ch] |
5805 | 5808 | ||
5806 | SECURE DIGITAL HOST CONTROLLER INTERFACE (SDHCI) SAMSUNG DRIVER | 5809 | SECURE DIGITAL HOST CONTROLLER INTERFACE (SDHCI) SAMSUNG DRIVER |
5807 | M: Ben Dooks <ben-linux@fluff.org> | 5810 | M: Ben Dooks <ben-linux@fluff.org> |
@@ -6180,9 +6183,7 @@ M: Viresh Kumar <viresh.kumar@st.com> | |||
6180 | W: http://www.st.com/spear | 6183 | W: http://www.st.com/spear |
6181 | S: Maintained | 6184 | S: Maintained |
6182 | F: arch/arm/mach-spear*/clock.c | 6185 | F: arch/arm/mach-spear*/clock.c |
6183 | F: arch/arm/mach-spear*/include/mach/clkdev.h | ||
6184 | F: arch/arm/plat-spear/clock.c | 6186 | F: arch/arm/plat-spear/clock.c |
6185 | F: arch/arm/plat-spear/include/plat/clkdev.h | ||
6186 | F: arch/arm/plat-spear/include/plat/clock.h | 6187 | F: arch/arm/plat-spear/include/plat/clock.h |
6187 | 6188 | ||
6188 | SPEAR PAD MULTIPLEXING SUPPORT | 6189 | SPEAR PAD MULTIPLEXING SUPPORT |
@@ -6306,7 +6307,7 @@ STAGING - LIRC (LINUX INFRARED REMOTE CONTROL) DRIVERS | |||
6306 | M: Jarod Wilson <jarod@wilsonet.com> | 6307 | M: Jarod Wilson <jarod@wilsonet.com> |
6307 | W: http://www.lirc.org/ | 6308 | W: http://www.lirc.org/ |
6308 | S: Odd Fixes | 6309 | S: Odd Fixes |
6309 | F: drivers/staging/lirc/ | 6310 | F: drivers/staging/media/lirc/ |
6310 | 6311 | ||
6311 | STAGING - NVIDIA COMPLIANT EMBEDDED CONTROLLER INTERFACE (nvec) | 6312 | STAGING - NVIDIA COMPLIANT EMBEDDED CONTROLLER INTERFACE (nvec) |
6312 | M: Julian Andres Klode <jak@jak-linux.org> | 6313 | M: Julian Andres Klode <jak@jak-linux.org> |
@@ -6342,7 +6343,7 @@ F: drivers/staging/sm7xx/ | |||
6342 | STAGING - SOFTLOGIC 6x10 MPEG CODEC | 6343 | STAGING - SOFTLOGIC 6x10 MPEG CODEC |
6343 | M: Ben Collins <bcollins@bluecherry.net> | 6344 | M: Ben Collins <bcollins@bluecherry.net> |
6344 | S: Odd Fixes | 6345 | S: Odd Fixes |
6345 | F: drivers/staging/solo6x10/ | 6346 | F: drivers/staging/media/solo6x10/ |
6346 | 6347 | ||
6347 | STAGING - SPEAKUP CONSOLE SPEECH DRIVER | 6348 | STAGING - SPEAKUP CONSOLE SPEECH DRIVER |
6348 | M: William Hubbs <w.d.hubbs@gmail.com> | 6349 | M: William Hubbs <w.d.hubbs@gmail.com> |
@@ -6645,7 +6646,7 @@ TULIP NETWORK DRIVERS | |||
6645 | M: Grant Grundler <grundler@parisc-linux.org> | 6646 | M: Grant Grundler <grundler@parisc-linux.org> |
6646 | L: netdev@vger.kernel.org | 6647 | L: netdev@vger.kernel.org |
6647 | S: Maintained | 6648 | S: Maintained |
6648 | F: drivers/net/ethernet/tulip/ | 6649 | F: drivers/net/ethernet/dec/tulip/ |
6649 | 6650 | ||
6650 | TUN/TAP driver | 6651 | TUN/TAP driver |
6651 | M: Maxim Krasnyansky <maxk@qualcomm.com> | 6652 | M: Maxim Krasnyansky <maxk@qualcomm.com> |
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 9d66dfc33a5a..98a6459cd398 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig | |||
@@ -16,6 +16,7 @@ config ARM | |||
16 | select HAVE_FTRACE_MCOUNT_RECORD if (!XIP_KERNEL) | 16 | select HAVE_FTRACE_MCOUNT_RECORD if (!XIP_KERNEL) |
17 | select HAVE_DYNAMIC_FTRACE if (!XIP_KERNEL) | 17 | select HAVE_DYNAMIC_FTRACE if (!XIP_KERNEL) |
18 | select HAVE_FUNCTION_GRAPH_TRACER if (!THUMB2_KERNEL) | 18 | select HAVE_FUNCTION_GRAPH_TRACER if (!THUMB2_KERNEL) |
19 | select ARCH_BINFMT_ELF_RANDOMIZE_PIE | ||
19 | select HAVE_GENERIC_DMA_COHERENT | 20 | select HAVE_GENERIC_DMA_COHERENT |
20 | select HAVE_KERNEL_GZIP | 21 | select HAVE_KERNEL_GZIP |
21 | select HAVE_KERNEL_LZO | 22 | select HAVE_KERNEL_LZO |
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index a7636d3ddc6a..c529cfe52c53 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig | |||
@@ -16,6 +16,7 @@ config MIPS | |||
16 | select HAVE_FUNCTION_GRAPH_TRACER | 16 | select HAVE_FUNCTION_GRAPH_TRACER |
17 | select HAVE_KPROBES | 17 | select HAVE_KPROBES |
18 | select HAVE_KRETPROBES | 18 | select HAVE_KRETPROBES |
19 | select ARCH_BINFMT_ELF_RANDOMIZE_PIE | ||
19 | select RTC_LIB if !MACH_LOONGSON | 20 | select RTC_LIB if !MACH_LOONGSON |
20 | select GENERIC_ATOMIC64 if !64BIT | 21 | select GENERIC_ATOMIC64 if !64BIT |
21 | select HAVE_DMA_ATTRS | 22 | select HAVE_DMA_ATTRS |
diff --git a/arch/sparc/include/asm/signal.h b/arch/sparc/include/asm/signal.h index e49b828a2471..aa42fe30d5b9 100644 --- a/arch/sparc/include/asm/signal.h +++ b/arch/sparc/include/asm/signal.h | |||
@@ -143,10 +143,11 @@ struct sigstack { | |||
143 | #define SA_ONSTACK _SV_SSTACK | 143 | #define SA_ONSTACK _SV_SSTACK |
144 | #define SA_RESTART _SV_INTR | 144 | #define SA_RESTART _SV_INTR |
145 | #define SA_ONESHOT _SV_RESET | 145 | #define SA_ONESHOT _SV_RESET |
146 | #define SA_NOMASK 0x20u | 146 | #define SA_NODEFER 0x20u |
147 | #define SA_NOCLDWAIT 0x100u | 147 | #define SA_NOCLDWAIT 0x100u |
148 | #define SA_SIGINFO 0x200u | 148 | #define SA_SIGINFO 0x200u |
149 | 149 | ||
150 | #define SA_NOMASK SA_NODEFER | ||
150 | 151 | ||
151 | #define SIG_BLOCK 0x01 /* for blocking signals */ | 152 | #define SIG_BLOCK 0x01 /* for blocking signals */ |
152 | #define SIG_UNBLOCK 0x02 /* for unblocking signals */ | 153 | #define SIG_UNBLOCK 0x02 /* for unblocking signals */ |
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 1d2a69dd36d8..d6ddc0bfe36a 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig | |||
@@ -62,6 +62,7 @@ config X86 | |||
62 | select ANON_INODES | 62 | select ANON_INODES |
63 | select HAVE_ARCH_KMEMCHECK | 63 | select HAVE_ARCH_KMEMCHECK |
64 | select HAVE_USER_RETURN_NOTIFIER | 64 | select HAVE_USER_RETURN_NOTIFIER |
65 | select ARCH_BINFMT_ELF_RANDOMIZE_PIE | ||
65 | select HAVE_ARCH_JUMP_LABEL | 66 | select HAVE_ARCH_JUMP_LABEL |
66 | select HAVE_TEXT_POKE_SMP | 67 | select HAVE_TEXT_POKE_SMP |
67 | select HAVE_GENERIC_HARDIRQS | 68 | select HAVE_GENERIC_HARDIRQS |
diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c index 54ddaeb221c1..46a01bdc27e2 100644 --- a/arch/x86/kernel/signal.c +++ b/arch/x86/kernel/signal.c | |||
@@ -682,7 +682,6 @@ static int | |||
682 | handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, | 682 | handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, |
683 | struct pt_regs *regs) | 683 | struct pt_regs *regs) |
684 | { | 684 | { |
685 | sigset_t blocked; | ||
686 | int ret; | 685 | int ret; |
687 | 686 | ||
688 | /* Are we from a system call? */ | 687 | /* Are we from a system call? */ |
@@ -733,10 +732,7 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, | |||
733 | */ | 732 | */ |
734 | regs->flags &= ~X86_EFLAGS_TF; | 733 | regs->flags &= ~X86_EFLAGS_TF; |
735 | 734 | ||
736 | sigorsets(&blocked, ¤t->blocked, &ka->sa.sa_mask); | 735 | block_sigmask(ka, sig); |
737 | if (!(ka->sa.sa_flags & SA_NODEFER)) | ||
738 | sigaddset(&blocked, sig); | ||
739 | set_current_blocked(&blocked); | ||
740 | 736 | ||
741 | tracehook_signal_handler(sig, info, ka, regs, | 737 | tracehook_signal_handler(sig, info, ka, regs, |
742 | test_thread_flag(TIF_SINGLESTEP)); | 738 | test_thread_flag(TIF_SINGLESTEP)); |
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index 1b75a56ebd08..897a77dfa9d7 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig | |||
@@ -388,6 +388,14 @@ config LEDS_RENESAS_TPU | |||
388 | pin function. The latter to support brightness control. | 388 | pin function. The latter to support brightness control. |
389 | Brightness control is supported but hardware blinking is not. | 389 | Brightness control is supported but hardware blinking is not. |
390 | 390 | ||
391 | config LEDS_TCA6507 | ||
392 | tristate "LED Support for TCA6507 I2C chip" | ||
393 | depends on LEDS_CLASS && I2C | ||
394 | help | ||
395 | This option enables support for LEDs connected to TC6507 | ||
396 | LED driver chips accessed via the I2C bus. | ||
397 | Driver support brightness control and hardware-assisted blinking. | ||
398 | |||
391 | config LEDS_TRIGGERS | 399 | config LEDS_TRIGGERS |
392 | bool "LED Trigger support" | 400 | bool "LED Trigger support" |
393 | depends on LEDS_CLASS | 401 | depends on LEDS_CLASS |
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile index e4f6bf568880..5c9dc4b000d5 100644 --- a/drivers/leds/Makefile +++ b/drivers/leds/Makefile | |||
@@ -25,6 +25,7 @@ obj-$(CONFIG_LEDS_GPIO) += leds-gpio.o | |||
25 | obj-$(CONFIG_LEDS_LP3944) += leds-lp3944.o | 25 | obj-$(CONFIG_LEDS_LP3944) += leds-lp3944.o |
26 | obj-$(CONFIG_LEDS_LP5521) += leds-lp5521.o | 26 | obj-$(CONFIG_LEDS_LP5521) += leds-lp5521.o |
27 | obj-$(CONFIG_LEDS_LP5523) += leds-lp5523.o | 27 | obj-$(CONFIG_LEDS_LP5523) += leds-lp5523.o |
28 | obj-$(CONFIG_LEDS_TCA6507) += leds-tca6507.o | ||
28 | obj-$(CONFIG_LEDS_CLEVO_MAIL) += leds-clevo-mail.o | 29 | obj-$(CONFIG_LEDS_CLEVO_MAIL) += leds-clevo-mail.o |
29 | obj-$(CONFIG_LEDS_HP6XX) += leds-hp6xx.o | 30 | obj-$(CONFIG_LEDS_HP6XX) += leds-hp6xx.o |
30 | obj-$(CONFIG_LEDS_FSG) += leds-fsg.o | 31 | obj-$(CONFIG_LEDS_FSG) += leds-fsg.o |
diff --git a/drivers/leds/leds-88pm860x.c b/drivers/leds/leds-88pm860x.c index 0810604dc701..4ca00624bd18 100644 --- a/drivers/leds/leds-88pm860x.c +++ b/drivers/leds/leds-88pm860x.c | |||
@@ -238,17 +238,7 @@ static struct platform_driver pm860x_led_driver = { | |||
238 | .remove = pm860x_led_remove, | 238 | .remove = pm860x_led_remove, |
239 | }; | 239 | }; |
240 | 240 | ||
241 | static int __devinit pm860x_led_init(void) | 241 | module_platform_driver(pm860x_led_driver); |
242 | { | ||
243 | return platform_driver_register(&pm860x_led_driver); | ||
244 | } | ||
245 | module_init(pm860x_led_init); | ||
246 | |||
247 | static void __devexit pm860x_led_exit(void) | ||
248 | { | ||
249 | platform_driver_unregister(&pm860x_led_driver); | ||
250 | } | ||
251 | module_exit(pm860x_led_exit); | ||
252 | 242 | ||
253 | MODULE_DESCRIPTION("LED driver for Marvell PM860x"); | 243 | MODULE_DESCRIPTION("LED driver for Marvell PM860x"); |
254 | MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>"); | 244 | MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>"); |
diff --git a/drivers/leds/leds-adp5520.c b/drivers/leds/leds-adp5520.c index 7ba4c7b5b97e..b1400db3f839 100644 --- a/drivers/leds/leds-adp5520.c +++ b/drivers/leds/leds-adp5520.c | |||
@@ -213,17 +213,7 @@ static struct platform_driver adp5520_led_driver = { | |||
213 | .remove = __devexit_p(adp5520_led_remove), | 213 | .remove = __devexit_p(adp5520_led_remove), |
214 | }; | 214 | }; |
215 | 215 | ||
216 | static int __init adp5520_led_init(void) | 216 | module_platform_driver(adp5520_led_driver); |
217 | { | ||
218 | return platform_driver_register(&adp5520_led_driver); | ||
219 | } | ||
220 | module_init(adp5520_led_init); | ||
221 | |||
222 | static void __exit adp5520_led_exit(void) | ||
223 | { | ||
224 | platform_driver_unregister(&adp5520_led_driver); | ||
225 | } | ||
226 | module_exit(adp5520_led_exit); | ||
227 | 217 | ||
228 | MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); | 218 | MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); |
229 | MODULE_DESCRIPTION("LEDS ADP5520(01) Driver"); | 219 | MODULE_DESCRIPTION("LEDS ADP5520(01) Driver"); |
diff --git a/drivers/leds/leds-ams-delta.c b/drivers/leds/leds-ams-delta.c index 8c00937bf7e7..07428357c83f 100644 --- a/drivers/leds/leds-ams-delta.c +++ b/drivers/leds/leds-ams-delta.c | |||
@@ -118,18 +118,7 @@ static struct platform_driver ams_delta_led_driver = { | |||
118 | }, | 118 | }, |
119 | }; | 119 | }; |
120 | 120 | ||
121 | static int __init ams_delta_led_init(void) | 121 | module_platform_driver(ams_delta_led_driver); |
122 | { | ||
123 | return platform_driver_register(&ams_delta_led_driver); | ||
124 | } | ||
125 | |||
126 | static void __exit ams_delta_led_exit(void) | ||
127 | { | ||
128 | platform_driver_unregister(&ams_delta_led_driver); | ||
129 | } | ||
130 | |||
131 | module_init(ams_delta_led_init); | ||
132 | module_exit(ams_delta_led_exit); | ||
133 | 122 | ||
134 | MODULE_AUTHOR("Jonathan McDowell <noodles@earth.li>"); | 123 | MODULE_AUTHOR("Jonathan McDowell <noodles@earth.li>"); |
135 | MODULE_DESCRIPTION("Amstrad Delta LED driver"); | 124 | MODULE_DESCRIPTION("Amstrad Delta LED driver"); |
diff --git a/drivers/leds/leds-asic3.c b/drivers/leds/leds-asic3.c index 48d9fe61bdfc..525a92492837 100644 --- a/drivers/leds/leds-asic3.c +++ b/drivers/leds/leds-asic3.c | |||
@@ -179,21 +179,9 @@ static struct platform_driver asic3_led_driver = { | |||
179 | }, | 179 | }, |
180 | }; | 180 | }; |
181 | 181 | ||
182 | MODULE_ALIAS("platform:leds-asic3"); | 182 | module_platform_driver(asic3_led_driver); |
183 | |||
184 | static int __init asic3_led_init(void) | ||
185 | { | ||
186 | return platform_driver_register(&asic3_led_driver); | ||
187 | } | ||
188 | |||
189 | static void __exit asic3_led_exit(void) | ||
190 | { | ||
191 | platform_driver_unregister(&asic3_led_driver); | ||
192 | } | ||
193 | |||
194 | module_init(asic3_led_init); | ||
195 | module_exit(asic3_led_exit); | ||
196 | 183 | ||
197 | MODULE_AUTHOR("Paul Parsons <lost.distance@yahoo.com>"); | 184 | MODULE_AUTHOR("Paul Parsons <lost.distance@yahoo.com>"); |
198 | MODULE_DESCRIPTION("HTC ASIC3 LED driver"); | 185 | MODULE_DESCRIPTION("HTC ASIC3 LED driver"); |
199 | MODULE_LICENSE("GPL"); | 186 | MODULE_LICENSE("GPL"); |
187 | MODULE_ALIAS("platform:leds-asic3"); | ||
diff --git a/drivers/leds/leds-atmel-pwm.c b/drivers/leds/leds-atmel-pwm.c index 109c875ea233..800243b6037e 100644 --- a/drivers/leds/leds-atmel-pwm.c +++ b/drivers/leds/leds-atmel-pwm.c | |||
@@ -134,29 +134,18 @@ static int __exit pwmled_remove(struct platform_device *pdev) | |||
134 | return 0; | 134 | return 0; |
135 | } | 135 | } |
136 | 136 | ||
137 | /* work with hotplug and coldplug */ | ||
138 | MODULE_ALIAS("platform:leds-atmel-pwm"); | ||
139 | |||
140 | static struct platform_driver pwmled_driver = { | 137 | static struct platform_driver pwmled_driver = { |
141 | .driver = { | 138 | .driver = { |
142 | .name = "leds-atmel-pwm", | 139 | .name = "leds-atmel-pwm", |
143 | .owner = THIS_MODULE, | 140 | .owner = THIS_MODULE, |
144 | }, | 141 | }, |
145 | /* REVISIT add suspend() and resume() methods */ | 142 | /* REVISIT add suspend() and resume() methods */ |
143 | .probe = pwmled_probe, | ||
146 | .remove = __exit_p(pwmled_remove), | 144 | .remove = __exit_p(pwmled_remove), |
147 | }; | 145 | }; |
148 | 146 | ||
149 | static int __init modinit(void) | 147 | module_platform_driver(pwmled_driver); |
150 | { | ||
151 | return platform_driver_probe(&pwmled_driver, pwmled_probe); | ||
152 | } | ||
153 | module_init(modinit); | ||
154 | |||
155 | static void __exit modexit(void) | ||
156 | { | ||
157 | platform_driver_unregister(&pwmled_driver); | ||
158 | } | ||
159 | module_exit(modexit); | ||
160 | 148 | ||
161 | MODULE_DESCRIPTION("Driver for LEDs with PWM-controlled brightness"); | 149 | MODULE_DESCRIPTION("Driver for LEDs with PWM-controlled brightness"); |
162 | MODULE_LICENSE("GPL"); | 150 | MODULE_LICENSE("GPL"); |
151 | MODULE_ALIAS("platform:leds-atmel-pwm"); | ||
diff --git a/drivers/leds/leds-bd2802.c b/drivers/leds/leds-bd2802.c index ea2185531f82..591cbdf5a046 100644 --- a/drivers/leds/leds-bd2802.c +++ b/drivers/leds/leds-bd2802.c | |||
@@ -688,8 +688,7 @@ static int __devinit bd2802_probe(struct i2c_client *client, | |||
688 | i2c_set_clientdata(client, led); | 688 | i2c_set_clientdata(client, led); |
689 | 689 | ||
690 | /* Configure RESET GPIO (L: RESET, H: RESET cancel) */ | 690 | /* Configure RESET GPIO (L: RESET, H: RESET cancel) */ |
691 | gpio_request(pdata->reset_gpio, "RGB_RESETB"); | 691 | gpio_request_one(pdata->reset_gpio, GPIOF_OUT_INIT_HIGH, "RGB_RESETB"); |
692 | gpio_direction_output(pdata->reset_gpio, 1); | ||
693 | 692 | ||
694 | /* Tacss = min 0.1ms */ | 693 | /* Tacss = min 0.1ms */ |
695 | udelay(100); | 694 | udelay(100); |
@@ -813,17 +812,7 @@ static struct i2c_driver bd2802_i2c_driver = { | |||
813 | .id_table = bd2802_id, | 812 | .id_table = bd2802_id, |
814 | }; | 813 | }; |
815 | 814 | ||
816 | static int __init bd2802_init(void) | 815 | module_i2c_driver(bd2802_i2c_driver); |
817 | { | ||
818 | return i2c_add_driver(&bd2802_i2c_driver); | ||
819 | } | ||
820 | module_init(bd2802_init); | ||
821 | |||
822 | static void __exit bd2802_exit(void) | ||
823 | { | ||
824 | i2c_del_driver(&bd2802_i2c_driver); | ||
825 | } | ||
826 | module_exit(bd2802_exit); | ||
827 | 816 | ||
828 | MODULE_AUTHOR("Kim Kyuwon <q1.kim@samsung.com>"); | 817 | MODULE_AUTHOR("Kim Kyuwon <q1.kim@samsung.com>"); |
829 | MODULE_DESCRIPTION("BD2802 LED driver"); | 818 | MODULE_DESCRIPTION("BD2802 LED driver"); |
diff --git a/drivers/leds/leds-cobalt-qube.c b/drivers/leds/leds-cobalt-qube.c index da5fb016b1a5..6a8725cc7b4d 100644 --- a/drivers/leds/leds-cobalt-qube.c +++ b/drivers/leds/leds-cobalt-qube.c | |||
@@ -75,9 +75,6 @@ static int __devexit cobalt_qube_led_remove(struct platform_device *pdev) | |||
75 | return 0; | 75 | return 0; |
76 | } | 76 | } |
77 | 77 | ||
78 | /* work with hotplug and coldplug */ | ||
79 | MODULE_ALIAS("platform:cobalt-qube-leds"); | ||
80 | |||
81 | static struct platform_driver cobalt_qube_led_driver = { | 78 | static struct platform_driver cobalt_qube_led_driver = { |
82 | .probe = cobalt_qube_led_probe, | 79 | .probe = cobalt_qube_led_probe, |
83 | .remove = __devexit_p(cobalt_qube_led_remove), | 80 | .remove = __devexit_p(cobalt_qube_led_remove), |
@@ -87,19 +84,9 @@ static struct platform_driver cobalt_qube_led_driver = { | |||
87 | }, | 84 | }, |
88 | }; | 85 | }; |
89 | 86 | ||
90 | static int __init cobalt_qube_led_init(void) | 87 | module_platform_driver(cobalt_qube_led_driver); |
91 | { | ||
92 | return platform_driver_register(&cobalt_qube_led_driver); | ||
93 | } | ||
94 | |||
95 | static void __exit cobalt_qube_led_exit(void) | ||
96 | { | ||
97 | platform_driver_unregister(&cobalt_qube_led_driver); | ||
98 | } | ||
99 | |||
100 | module_init(cobalt_qube_led_init); | ||
101 | module_exit(cobalt_qube_led_exit); | ||
102 | 88 | ||
103 | MODULE_LICENSE("GPL"); | 89 | MODULE_LICENSE("GPL"); |
104 | MODULE_DESCRIPTION("Front LED support for Cobalt Server"); | 90 | MODULE_DESCRIPTION("Front LED support for Cobalt Server"); |
105 | MODULE_AUTHOR("Florian Fainelli <florian@openwrt.org>"); | 91 | MODULE_AUTHOR("Florian Fainelli <florian@openwrt.org>"); |
92 | MODULE_ALIAS("platform:cobalt-qube-leds"); | ||
diff --git a/drivers/leds/leds-da903x.c b/drivers/leds/leds-da903x.c index f28931cf6781..d9cd73ebd6c4 100644 --- a/drivers/leds/leds-da903x.c +++ b/drivers/leds/leds-da903x.c | |||
@@ -158,17 +158,7 @@ static struct platform_driver da903x_led_driver = { | |||
158 | .remove = __devexit_p(da903x_led_remove), | 158 | .remove = __devexit_p(da903x_led_remove), |
159 | }; | 159 | }; |
160 | 160 | ||
161 | static int __init da903x_led_init(void) | 161 | module_platform_driver(da903x_led_driver); |
162 | { | ||
163 | return platform_driver_register(&da903x_led_driver); | ||
164 | } | ||
165 | module_init(da903x_led_init); | ||
166 | |||
167 | static void __exit da903x_led_exit(void) | ||
168 | { | ||
169 | platform_driver_unregister(&da903x_led_driver); | ||
170 | } | ||
171 | module_exit(da903x_led_exit); | ||
172 | 162 | ||
173 | MODULE_DESCRIPTION("LEDs driver for Dialog Semiconductor DA9030/DA9034"); | 163 | MODULE_DESCRIPTION("LEDs driver for Dialog Semiconductor DA9030/DA9034"); |
174 | MODULE_AUTHOR("Eric Miao <eric.miao@marvell.com>" | 164 | MODULE_AUTHOR("Eric Miao <eric.miao@marvell.com>" |
diff --git a/drivers/leds/leds-dac124s085.c b/drivers/leds/leds-dac124s085.c index 31cf0d60a9a5..d56c14269ff0 100644 --- a/drivers/leds/leds-dac124s085.c +++ b/drivers/leds/leds-dac124s085.c | |||
@@ -131,18 +131,7 @@ static struct spi_driver dac124s085_driver = { | |||
131 | }, | 131 | }, |
132 | }; | 132 | }; |
133 | 133 | ||
134 | static int __init dac124s085_leds_init(void) | 134 | module_spi_driver(dac124s085_driver); |
135 | { | ||
136 | return spi_register_driver(&dac124s085_driver); | ||
137 | } | ||
138 | |||
139 | static void __exit dac124s085_leds_exit(void) | ||
140 | { | ||
141 | spi_unregister_driver(&dac124s085_driver); | ||
142 | } | ||
143 | |||
144 | module_init(dac124s085_leds_init); | ||
145 | module_exit(dac124s085_leds_exit); | ||
146 | 135 | ||
147 | MODULE_AUTHOR("Guennadi Liakhovetski <lg@denx.de>"); | 136 | MODULE_AUTHOR("Guennadi Liakhovetski <lg@denx.de>"); |
148 | MODULE_DESCRIPTION("DAC124S085 LED driver"); | 137 | MODULE_DESCRIPTION("DAC124S085 LED driver"); |
diff --git a/drivers/leds/leds-fsg.c b/drivers/leds/leds-fsg.c index 49aceffaa5b6..b9053fa6e253 100644 --- a/drivers/leds/leds-fsg.c +++ b/drivers/leds/leds-fsg.c | |||
@@ -224,20 +224,7 @@ static struct platform_driver fsg_led_driver = { | |||
224 | }, | 224 | }, |
225 | }; | 225 | }; |
226 | 226 | ||
227 | 227 | module_platform_driver(fsg_led_driver); | |
228 | static int __init fsg_led_init(void) | ||
229 | { | ||
230 | return platform_driver_register(&fsg_led_driver); | ||
231 | } | ||
232 | |||
233 | static void __exit fsg_led_exit(void) | ||
234 | { | ||
235 | platform_driver_unregister(&fsg_led_driver); | ||
236 | } | ||
237 | |||
238 | |||
239 | module_init(fsg_led_init); | ||
240 | module_exit(fsg_led_exit); | ||
241 | 228 | ||
242 | MODULE_AUTHOR("Rod Whitby <rod@whitby.id.au>"); | 229 | MODULE_AUTHOR("Rod Whitby <rod@whitby.id.au>"); |
243 | MODULE_DESCRIPTION("Freecom FSG-3 LED driver"); | 230 | MODULE_DESCRIPTION("Freecom FSG-3 LED driver"); |
diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c index 399a86f2013a..7df74cb97e70 100644 --- a/drivers/leds/leds-gpio.c +++ b/drivers/leds/leds-gpio.c | |||
@@ -293,21 +293,9 @@ static struct platform_driver gpio_led_driver = { | |||
293 | }, | 293 | }, |
294 | }; | 294 | }; |
295 | 295 | ||
296 | MODULE_ALIAS("platform:leds-gpio"); | 296 | module_platform_driver(gpio_led_driver); |
297 | |||
298 | static int __init gpio_led_init(void) | ||
299 | { | ||
300 | return platform_driver_register(&gpio_led_driver); | ||
301 | } | ||
302 | |||
303 | static void __exit gpio_led_exit(void) | ||
304 | { | ||
305 | platform_driver_unregister(&gpio_led_driver); | ||
306 | } | ||
307 | |||
308 | module_init(gpio_led_init); | ||
309 | module_exit(gpio_led_exit); | ||
310 | 297 | ||
311 | MODULE_AUTHOR("Raphael Assenat <raph@8d.com>, Trent Piepho <tpiepho@freescale.com>"); | 298 | MODULE_AUTHOR("Raphael Assenat <raph@8d.com>, Trent Piepho <tpiepho@freescale.com>"); |
312 | MODULE_DESCRIPTION("GPIO LED driver"); | 299 | MODULE_DESCRIPTION("GPIO LED driver"); |
313 | MODULE_LICENSE("GPL"); | 300 | MODULE_LICENSE("GPL"); |
301 | MODULE_ALIAS("platform:leds-gpio"); | ||
diff --git a/drivers/leds/leds-hp6xx.c b/drivers/leds/leds-hp6xx.c index bcfbd3a60eab..366b6055e330 100644 --- a/drivers/leds/leds-hp6xx.c +++ b/drivers/leds/leds-hp6xx.c | |||
@@ -79,9 +79,6 @@ static int hp6xxled_remove(struct platform_device *pdev) | |||
79 | return 0; | 79 | return 0; |
80 | } | 80 | } |
81 | 81 | ||
82 | /* work with hotplug and coldplug */ | ||
83 | MODULE_ALIAS("platform:hp6xx-led"); | ||
84 | |||
85 | static struct platform_driver hp6xxled_driver = { | 82 | static struct platform_driver hp6xxled_driver = { |
86 | .probe = hp6xxled_probe, | 83 | .probe = hp6xxled_probe, |
87 | .remove = hp6xxled_remove, | 84 | .remove = hp6xxled_remove, |
@@ -91,19 +88,9 @@ static struct platform_driver hp6xxled_driver = { | |||
91 | }, | 88 | }, |
92 | }; | 89 | }; |
93 | 90 | ||
94 | static int __init hp6xxled_init(void) | 91 | module_platform_driver(hp6xxled_driver); |
95 | { | ||
96 | return platform_driver_register(&hp6xxled_driver); | ||
97 | } | ||
98 | |||
99 | static void __exit hp6xxled_exit(void) | ||
100 | { | ||
101 | platform_driver_unregister(&hp6xxled_driver); | ||
102 | } | ||
103 | |||
104 | module_init(hp6xxled_init); | ||
105 | module_exit(hp6xxled_exit); | ||
106 | 92 | ||
107 | MODULE_AUTHOR("Kristoffer Ericson <kristoffer.ericson@gmail.com>"); | 93 | MODULE_AUTHOR("Kristoffer Ericson <kristoffer.ericson@gmail.com>"); |
108 | MODULE_DESCRIPTION("HP Jornada 6xx LED driver"); | 94 | MODULE_DESCRIPTION("HP Jornada 6xx LED driver"); |
109 | MODULE_LICENSE("GPL"); | 95 | MODULE_LICENSE("GPL"); |
96 | MODULE_ALIAS("platform:hp6xx-led"); | ||
diff --git a/drivers/leds/leds-lm3530.c b/drivers/leds/leds-lm3530.c index 0630e4f4b286..45e6878d7374 100644 --- a/drivers/leds/leds-lm3530.c +++ b/drivers/leds/leds-lm3530.c | |||
@@ -457,18 +457,7 @@ static struct i2c_driver lm3530_i2c_driver = { | |||
457 | }, | 457 | }, |
458 | }; | 458 | }; |
459 | 459 | ||
460 | static int __init lm3530_init(void) | 460 | module_i2c_driver(lm3530_i2c_driver); |
461 | { | ||
462 | return i2c_add_driver(&lm3530_i2c_driver); | ||
463 | } | ||
464 | |||
465 | static void __exit lm3530_exit(void) | ||
466 | { | ||
467 | i2c_del_driver(&lm3530_i2c_driver); | ||
468 | } | ||
469 | |||
470 | module_init(lm3530_init); | ||
471 | module_exit(lm3530_exit); | ||
472 | 461 | ||
473 | MODULE_DESCRIPTION("Back Light driver for LM3530"); | 462 | MODULE_DESCRIPTION("Back Light driver for LM3530"); |
474 | MODULE_LICENSE("GPL v2"); | 463 | MODULE_LICENSE("GPL v2"); |
diff --git a/drivers/leds/leds-lp3944.c b/drivers/leds/leds-lp3944.c index 9010c054615e..b8f9f0a5d431 100644 --- a/drivers/leds/leds-lp3944.c +++ b/drivers/leds/leds-lp3944.c | |||
@@ -453,18 +453,7 @@ static struct i2c_driver lp3944_driver = { | |||
453 | .id_table = lp3944_id, | 453 | .id_table = lp3944_id, |
454 | }; | 454 | }; |
455 | 455 | ||
456 | static int __init lp3944_module_init(void) | 456 | module_i2c_driver(lp3944_driver); |
457 | { | ||
458 | return i2c_add_driver(&lp3944_driver); | ||
459 | } | ||
460 | |||
461 | static void __exit lp3944_module_exit(void) | ||
462 | { | ||
463 | i2c_del_driver(&lp3944_driver); | ||
464 | } | ||
465 | |||
466 | module_init(lp3944_module_init); | ||
467 | module_exit(lp3944_module_exit); | ||
468 | 457 | ||
469 | MODULE_AUTHOR("Antonio Ospite <ospite@studenti.unina.it>"); | 458 | MODULE_AUTHOR("Antonio Ospite <ospite@studenti.unina.it>"); |
470 | MODULE_DESCRIPTION("LP3944 Fun Light Chip"); | 459 | MODULE_DESCRIPTION("LP3944 Fun Light Chip"); |
diff --git a/drivers/leds/leds-lp5521.c b/drivers/leds/leds-lp5521.c index cb641f1b3342..d62a7982a5e6 100644 --- a/drivers/leds/leds-lp5521.c +++ b/drivers/leds/leds-lp5521.c | |||
@@ -797,25 +797,7 @@ static struct i2c_driver lp5521_driver = { | |||
797 | .id_table = lp5521_id, | 797 | .id_table = lp5521_id, |
798 | }; | 798 | }; |
799 | 799 | ||
800 | static int __init lp5521_init(void) | 800 | module_i2c_driver(lp5521_driver); |
801 | { | ||
802 | int ret; | ||
803 | |||
804 | ret = i2c_add_driver(&lp5521_driver); | ||
805 | |||
806 | if (ret < 0) | ||
807 | printk(KERN_ALERT "Adding lp5521 driver failed\n"); | ||
808 | |||
809 | return ret; | ||
810 | } | ||
811 | |||
812 | static void __exit lp5521_exit(void) | ||
813 | { | ||
814 | i2c_del_driver(&lp5521_driver); | ||
815 | } | ||
816 | |||
817 | module_init(lp5521_init); | ||
818 | module_exit(lp5521_exit); | ||
819 | 801 | ||
820 | MODULE_AUTHOR("Mathias Nyman, Yuri Zaporozhets, Samu Onkalo"); | 802 | MODULE_AUTHOR("Mathias Nyman, Yuri Zaporozhets, Samu Onkalo"); |
821 | MODULE_DESCRIPTION("LP5521 LED engine"); | 803 | MODULE_DESCRIPTION("LP5521 LED engine"); |
diff --git a/drivers/leds/leds-lp5523.c b/drivers/leds/leds-lp5523.c index 5971e309b234..73e791ae7259 100644 --- a/drivers/leds/leds-lp5523.c +++ b/drivers/leds/leds-lp5523.c | |||
@@ -870,8 +870,6 @@ static int __devinit lp5523_init_led(struct lp5523_led *led, struct device *dev, | |||
870 | return 0; | 870 | return 0; |
871 | } | 871 | } |
872 | 872 | ||
873 | static struct i2c_driver lp5523_driver; | ||
874 | |||
875 | static int __devinit lp5523_probe(struct i2c_client *client, | 873 | static int __devinit lp5523_probe(struct i2c_client *client, |
876 | const struct i2c_device_id *id) | 874 | const struct i2c_device_id *id) |
877 | { | 875 | { |
@@ -1021,25 +1019,7 @@ static struct i2c_driver lp5523_driver = { | |||
1021 | .id_table = lp5523_id, | 1019 | .id_table = lp5523_id, |
1022 | }; | 1020 | }; |
1023 | 1021 | ||
1024 | static int __init lp5523_init(void) | 1022 | module_i2c_driver(lp5523_driver); |
1025 | { | ||
1026 | int ret; | ||
1027 | |||
1028 | ret = i2c_add_driver(&lp5523_driver); | ||
1029 | |||
1030 | if (ret < 0) | ||
1031 | printk(KERN_ALERT "Adding lp5523 driver failed\n"); | ||
1032 | |||
1033 | return ret; | ||
1034 | } | ||
1035 | |||
1036 | static void __exit lp5523_exit(void) | ||
1037 | { | ||
1038 | i2c_del_driver(&lp5523_driver); | ||
1039 | } | ||
1040 | |||
1041 | module_init(lp5523_init); | ||
1042 | module_exit(lp5523_exit); | ||
1043 | 1023 | ||
1044 | MODULE_AUTHOR("Mathias Nyman <mathias.nyman@nokia.com>"); | 1024 | MODULE_AUTHOR("Mathias Nyman <mathias.nyman@nokia.com>"); |
1045 | MODULE_DESCRIPTION("LP5523 LED engine"); | 1025 | MODULE_DESCRIPTION("LP5523 LED engine"); |
diff --git a/drivers/leds/leds-lt3593.c b/drivers/leds/leds-lt3593.c index 53f67b8ce55d..e311a96c4469 100644 --- a/drivers/leds/leds-lt3593.c +++ b/drivers/leds/leds-lt3593.c | |||
@@ -199,21 +199,9 @@ static struct platform_driver lt3593_led_driver = { | |||
199 | }, | 199 | }, |
200 | }; | 200 | }; |
201 | 201 | ||
202 | MODULE_ALIAS("platform:leds-lt3593"); | 202 | module_platform_driver(lt3593_led_driver); |
203 | |||
204 | static int __init lt3593_led_init(void) | ||
205 | { | ||
206 | return platform_driver_register(<3593_led_driver); | ||
207 | } | ||
208 | |||
209 | static void __exit lt3593_led_exit(void) | ||
210 | { | ||
211 | platform_driver_unregister(<3593_led_driver); | ||
212 | } | ||
213 | |||
214 | module_init(lt3593_led_init); | ||
215 | module_exit(lt3593_led_exit); | ||
216 | 203 | ||
217 | MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>"); | 204 | MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>"); |
218 | MODULE_DESCRIPTION("LED driver for LT3593 controllers"); | 205 | MODULE_DESCRIPTION("LED driver for LT3593 controllers"); |
219 | MODULE_LICENSE("GPL"); | 206 | MODULE_LICENSE("GPL"); |
207 | MODULE_ALIAS("platform:leds-lt3593"); | ||
diff --git a/drivers/leds/leds-mc13783.c b/drivers/leds/leds-mc13783.c index b3393a9f2139..8bc491541550 100644 --- a/drivers/leds/leds-mc13783.c +++ b/drivers/leds/leds-mc13783.c | |||
@@ -275,7 +275,7 @@ static int __devinit mc13783_led_probe(struct platform_device *pdev) | |||
275 | return -ENODEV; | 275 | return -ENODEV; |
276 | } | 276 | } |
277 | 277 | ||
278 | if (pdata->num_leds < 1 || pdata->num_leds > MC13783_LED_MAX) { | 278 | if (pdata->num_leds < 1 || pdata->num_leds > (MC13783_LED_MAX + 1)) { |
279 | dev_err(&pdev->dev, "Invalid led count %d\n", pdata->num_leds); | 279 | dev_err(&pdev->dev, "Invalid led count %d\n", pdata->num_leds); |
280 | return -EINVAL; | 280 | return -EINVAL; |
281 | } | 281 | } |
@@ -385,17 +385,7 @@ static struct platform_driver mc13783_led_driver = { | |||
385 | .remove = __devexit_p(mc13783_led_remove), | 385 | .remove = __devexit_p(mc13783_led_remove), |
386 | }; | 386 | }; |
387 | 387 | ||
388 | static int __init mc13783_led_init(void) | 388 | module_platform_driver(mc13783_led_driver); |
389 | { | ||
390 | return platform_driver_register(&mc13783_led_driver); | ||
391 | } | ||
392 | module_init(mc13783_led_init); | ||
393 | |||
394 | static void __exit mc13783_led_exit(void) | ||
395 | { | ||
396 | platform_driver_unregister(&mc13783_led_driver); | ||
397 | } | ||
398 | module_exit(mc13783_led_exit); | ||
399 | 389 | ||
400 | MODULE_DESCRIPTION("LEDs driver for Freescale MC13783 PMIC"); | 390 | MODULE_DESCRIPTION("LEDs driver for Freescale MC13783 PMIC"); |
401 | MODULE_AUTHOR("Philippe Retornaz <philippe.retornaz@epfl.ch>"); | 391 | MODULE_AUTHOR("Philippe Retornaz <philippe.retornaz@epfl.ch>"); |
diff --git a/drivers/leds/leds-netxbig.c b/drivers/leds/leds-netxbig.c index f2e51c134399..d8433f2d53bc 100644 --- a/drivers/leds/leds-netxbig.c +++ b/drivers/leds/leds-netxbig.c | |||
@@ -81,35 +81,23 @@ static int __devinit gpio_ext_init(struct netxbig_gpio_ext *gpio_ext) | |||
81 | 81 | ||
82 | /* Configure address GPIOs. */ | 82 | /* Configure address GPIOs. */ |
83 | for (i = 0; i < gpio_ext->num_addr; i++) { | 83 | for (i = 0; i < gpio_ext->num_addr; i++) { |
84 | err = gpio_request(gpio_ext->addr[i], "GPIO extension addr"); | 84 | err = gpio_request_one(gpio_ext->addr[i], GPIOF_OUT_INIT_LOW, |
85 | "GPIO extension addr"); | ||
85 | if (err) | 86 | if (err) |
86 | goto err_free_addr; | 87 | goto err_free_addr; |
87 | err = gpio_direction_output(gpio_ext->addr[i], 0); | ||
88 | if (err) { | ||
89 | gpio_free(gpio_ext->addr[i]); | ||
90 | goto err_free_addr; | ||
91 | } | ||
92 | } | 88 | } |
93 | /* Configure data GPIOs. */ | 89 | /* Configure data GPIOs. */ |
94 | for (i = 0; i < gpio_ext->num_data; i++) { | 90 | for (i = 0; i < gpio_ext->num_data; i++) { |
95 | err = gpio_request(gpio_ext->data[i], "GPIO extension data"); | 91 | err = gpio_request_one(gpio_ext->data[i], GPIOF_OUT_INIT_LOW, |
92 | "GPIO extension data"); | ||
96 | if (err) | 93 | if (err) |
97 | goto err_free_data; | 94 | goto err_free_data; |
98 | err = gpio_direction_output(gpio_ext->data[i], 0); | ||
99 | if (err) { | ||
100 | gpio_free(gpio_ext->data[i]); | ||
101 | goto err_free_data; | ||
102 | } | ||
103 | } | 95 | } |
104 | /* Configure "enable select" GPIO. */ | 96 | /* Configure "enable select" GPIO. */ |
105 | err = gpio_request(gpio_ext->enable, "GPIO extension enable"); | 97 | err = gpio_request_one(gpio_ext->enable, GPIOF_OUT_INIT_LOW, |
98 | "GPIO extension enable"); | ||
106 | if (err) | 99 | if (err) |
107 | goto err_free_data; | 100 | goto err_free_data; |
108 | err = gpio_direction_output(gpio_ext->enable, 0); | ||
109 | if (err) { | ||
110 | gpio_free(gpio_ext->enable); | ||
111 | goto err_free_data; | ||
112 | } | ||
113 | 101 | ||
114 | return 0; | 102 | return 0; |
115 | 103 | ||
@@ -429,21 +417,10 @@ static struct platform_driver netxbig_led_driver = { | |||
429 | .owner = THIS_MODULE, | 417 | .owner = THIS_MODULE, |
430 | }, | 418 | }, |
431 | }; | 419 | }; |
432 | MODULE_ALIAS("platform:leds-netxbig"); | ||
433 | 420 | ||
434 | static int __init netxbig_led_init(void) | 421 | module_platform_driver(netxbig_led_driver); |
435 | { | ||
436 | return platform_driver_register(&netxbig_led_driver); | ||
437 | } | ||
438 | |||
439 | static void __exit netxbig_led_exit(void) | ||
440 | { | ||
441 | platform_driver_unregister(&netxbig_led_driver); | ||
442 | } | ||
443 | |||
444 | module_init(netxbig_led_init); | ||
445 | module_exit(netxbig_led_exit); | ||
446 | 422 | ||
447 | MODULE_AUTHOR("Simon Guinot <sguinot@lacie.com>"); | 423 | MODULE_AUTHOR("Simon Guinot <sguinot@lacie.com>"); |
448 | MODULE_DESCRIPTION("LED driver for LaCie xBig Network boards"); | 424 | MODULE_DESCRIPTION("LED driver for LaCie xBig Network boards"); |
449 | MODULE_LICENSE("GPL"); | 425 | MODULE_LICENSE("GPL"); |
426 | MODULE_ALIAS("platform:leds-netxbig"); | ||
diff --git a/drivers/leds/leds-ns2.c b/drivers/leds/leds-ns2.c index 37b7d0cfe586..2f0a14421a73 100644 --- a/drivers/leds/leds-ns2.c +++ b/drivers/leds/leds-ns2.c | |||
@@ -323,21 +323,10 @@ static struct platform_driver ns2_led_driver = { | |||
323 | .owner = THIS_MODULE, | 323 | .owner = THIS_MODULE, |
324 | }, | 324 | }, |
325 | }; | 325 | }; |
326 | MODULE_ALIAS("platform:leds-ns2"); | ||
327 | |||
328 | static int __init ns2_led_init(void) | ||
329 | { | ||
330 | return platform_driver_register(&ns2_led_driver); | ||
331 | } | ||
332 | 326 | ||
333 | static void __exit ns2_led_exit(void) | 327 | module_platform_driver(ns2_led_driver); |
334 | { | ||
335 | platform_driver_unregister(&ns2_led_driver); | ||
336 | } | ||
337 | |||
338 | module_init(ns2_led_init); | ||
339 | module_exit(ns2_led_exit); | ||
340 | 328 | ||
341 | MODULE_AUTHOR("Simon Guinot <sguinot@lacie.com>"); | 329 | MODULE_AUTHOR("Simon Guinot <sguinot@lacie.com>"); |
342 | MODULE_DESCRIPTION("Network Space v2 LED driver"); | 330 | MODULE_DESCRIPTION("Network Space v2 LED driver"); |
343 | MODULE_LICENSE("GPL"); | 331 | MODULE_LICENSE("GPL"); |
332 | MODULE_ALIAS("platform:leds-ns2"); | ||
diff --git a/drivers/leds/leds-pca9532.c b/drivers/leds/leds-pca9532.c index a2c874623e35..ceccab44b5b8 100644 --- a/drivers/leds/leds-pca9532.c +++ b/drivers/leds/leds-pca9532.c | |||
@@ -489,20 +489,8 @@ static int pca9532_remove(struct i2c_client *client) | |||
489 | return 0; | 489 | return 0; |
490 | } | 490 | } |
491 | 491 | ||
492 | static int __init pca9532_init(void) | 492 | module_i2c_driver(pca9532_driver); |
493 | { | ||
494 | return i2c_add_driver(&pca9532_driver); | ||
495 | } | ||
496 | |||
497 | static void __exit pca9532_exit(void) | ||
498 | { | ||
499 | i2c_del_driver(&pca9532_driver); | ||
500 | } | ||
501 | 493 | ||
502 | MODULE_AUTHOR("Riku Voipio"); | 494 | MODULE_AUTHOR("Riku Voipio"); |
503 | MODULE_LICENSE("GPL"); | 495 | MODULE_LICENSE("GPL"); |
504 | MODULE_DESCRIPTION("PCA 9532 LED dimmer"); | 496 | MODULE_DESCRIPTION("PCA 9532 LED dimmer"); |
505 | |||
506 | module_init(pca9532_init); | ||
507 | module_exit(pca9532_exit); | ||
508 | |||
diff --git a/drivers/leds/leds-pca955x.c b/drivers/leds/leds-pca955x.c index 66aa3e8e786f..dcc3bc3d38db 100644 --- a/drivers/leds/leds-pca955x.c +++ b/drivers/leds/leds-pca955x.c | |||
@@ -371,18 +371,7 @@ static struct i2c_driver pca955x_driver = { | |||
371 | .id_table = pca955x_id, | 371 | .id_table = pca955x_id, |
372 | }; | 372 | }; |
373 | 373 | ||
374 | static int __init pca955x_leds_init(void) | 374 | module_i2c_driver(pca955x_driver); |
375 | { | ||
376 | return i2c_add_driver(&pca955x_driver); | ||
377 | } | ||
378 | |||
379 | static void __exit pca955x_leds_exit(void) | ||
380 | { | ||
381 | i2c_del_driver(&pca955x_driver); | ||
382 | } | ||
383 | |||
384 | module_init(pca955x_leds_init); | ||
385 | module_exit(pca955x_leds_exit); | ||
386 | 375 | ||
387 | MODULE_AUTHOR("Nate Case <ncase@xes-inc.com>"); | 376 | MODULE_AUTHOR("Nate Case <ncase@xes-inc.com>"); |
388 | MODULE_DESCRIPTION("PCA955x LED driver"); | 377 | MODULE_DESCRIPTION("PCA955x LED driver"); |
diff --git a/drivers/leds/leds-pwm.c b/drivers/leds/leds-pwm.c index 666daf77872e..3ed92f34bd44 100644 --- a/drivers/leds/leds-pwm.c +++ b/drivers/leds/leds-pwm.c | |||
@@ -135,18 +135,7 @@ static struct platform_driver led_pwm_driver = { | |||
135 | }, | 135 | }, |
136 | }; | 136 | }; |
137 | 137 | ||
138 | static int __init led_pwm_init(void) | 138 | module_platform_driver(led_pwm_driver); |
139 | { | ||
140 | return platform_driver_register(&led_pwm_driver); | ||
141 | } | ||
142 | |||
143 | static void __exit led_pwm_exit(void) | ||
144 | { | ||
145 | platform_driver_unregister(&led_pwm_driver); | ||
146 | } | ||
147 | |||
148 | module_init(led_pwm_init); | ||
149 | module_exit(led_pwm_exit); | ||
150 | 139 | ||
151 | MODULE_AUTHOR("Luotao Fu <l.fu@pengutronix.de>"); | 140 | MODULE_AUTHOR("Luotao Fu <l.fu@pengutronix.de>"); |
152 | MODULE_DESCRIPTION("PWM LED driver for PXA"); | 141 | MODULE_DESCRIPTION("PWM LED driver for PXA"); |
diff --git a/drivers/leds/leds-rb532.c b/drivers/leds/leds-rb532.c index c3525f37f73d..a7815b6cd856 100644 --- a/drivers/leds/leds-rb532.c +++ b/drivers/leds/leds-rb532.c | |||
@@ -57,21 +57,9 @@ static struct platform_driver rb532_led_driver = { | |||
57 | }, | 57 | }, |
58 | }; | 58 | }; |
59 | 59 | ||
60 | static int __init rb532_led_init(void) | 60 | module_platform_driver(rb532_led_driver); |
61 | { | ||
62 | return platform_driver_register(&rb532_led_driver); | ||
63 | } | ||
64 | |||
65 | static void __exit rb532_led_exit(void) | ||
66 | { | ||
67 | platform_driver_unregister(&rb532_led_driver); | ||
68 | } | ||
69 | |||
70 | module_init(rb532_led_init); | ||
71 | module_exit(rb532_led_exit); | ||
72 | |||
73 | MODULE_ALIAS("platform:rb532-led"); | ||
74 | 61 | ||
75 | MODULE_LICENSE("GPL"); | 62 | MODULE_LICENSE("GPL"); |
76 | MODULE_DESCRIPTION("User LED support for Routerboard532"); | 63 | MODULE_DESCRIPTION("User LED support for Routerboard532"); |
77 | MODULE_AUTHOR("Phil Sutter <n0-1@freewrt.org>"); | 64 | MODULE_AUTHOR("Phil Sutter <n0-1@freewrt.org>"); |
65 | MODULE_ALIAS("platform:rb532-led"); | ||
diff --git a/drivers/leds/leds-regulator.c b/drivers/leds/leds-regulator.c index 8497f56f8e46..df7e963bddd3 100644 --- a/drivers/leds/leds-regulator.c +++ b/drivers/leds/leds-regulator.c | |||
@@ -229,17 +229,7 @@ static struct platform_driver regulator_led_driver = { | |||
229 | .remove = __devexit_p(regulator_led_remove), | 229 | .remove = __devexit_p(regulator_led_remove), |
230 | }; | 230 | }; |
231 | 231 | ||
232 | static int __init regulator_led_init(void) | 232 | module_platform_driver(regulator_led_driver); |
233 | { | ||
234 | return platform_driver_register(®ulator_led_driver); | ||
235 | } | ||
236 | module_init(regulator_led_init); | ||
237 | |||
238 | static void __exit regulator_led_exit(void) | ||
239 | { | ||
240 | platform_driver_unregister(®ulator_led_driver); | ||
241 | } | ||
242 | module_exit(regulator_led_exit); | ||
243 | 233 | ||
244 | MODULE_AUTHOR("Antonio Ospite <ospite@studenti.unina.it>"); | 234 | MODULE_AUTHOR("Antonio Ospite <ospite@studenti.unina.it>"); |
245 | MODULE_DESCRIPTION("Regulator driven LED driver"); | 235 | MODULE_DESCRIPTION("Regulator driven LED driver"); |
diff --git a/drivers/leds/leds-renesas-tpu.c b/drivers/leds/leds-renesas-tpu.c index 3ee540eb127e..32fe337d5c68 100644 --- a/drivers/leds/leds-renesas-tpu.c +++ b/drivers/leds/leds-renesas-tpu.c | |||
@@ -339,18 +339,7 @@ static struct platform_driver r_tpu_device_driver = { | |||
339 | } | 339 | } |
340 | }; | 340 | }; |
341 | 341 | ||
342 | static int __init r_tpu_init(void) | 342 | module_platform_driver(r_tpu_device_driver); |
343 | { | ||
344 | return platform_driver_register(&r_tpu_device_driver); | ||
345 | } | ||
346 | |||
347 | static void __exit r_tpu_exit(void) | ||
348 | { | ||
349 | platform_driver_unregister(&r_tpu_device_driver); | ||
350 | } | ||
351 | |||
352 | module_init(r_tpu_init); | ||
353 | module_exit(r_tpu_exit); | ||
354 | 343 | ||
355 | MODULE_AUTHOR("Magnus Damm"); | 344 | MODULE_AUTHOR("Magnus Damm"); |
356 | MODULE_DESCRIPTION("Renesas TPU LED Driver"); | 345 | MODULE_DESCRIPTION("Renesas TPU LED Driver"); |
diff --git a/drivers/leds/leds-s3c24xx.c b/drivers/leds/leds-s3c24xx.c index 29f8b0f0e2c6..bd0a5ed49c42 100644 --- a/drivers/leds/leds-s3c24xx.c +++ b/drivers/leds/leds-s3c24xx.c | |||
@@ -121,18 +121,7 @@ static struct platform_driver s3c24xx_led_driver = { | |||
121 | }, | 121 | }, |
122 | }; | 122 | }; |
123 | 123 | ||
124 | static int __init s3c24xx_led_init(void) | 124 | module_platform_driver(s3c24xx_led_driver); |
125 | { | ||
126 | return platform_driver_register(&s3c24xx_led_driver); | ||
127 | } | ||
128 | |||
129 | static void __exit s3c24xx_led_exit(void) | ||
130 | { | ||
131 | platform_driver_unregister(&s3c24xx_led_driver); | ||
132 | } | ||
133 | |||
134 | module_init(s3c24xx_led_init); | ||
135 | module_exit(s3c24xx_led_exit); | ||
136 | 125 | ||
137 | MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>"); | 126 | MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>"); |
138 | MODULE_DESCRIPTION("S3C24XX LED driver"); | 127 | MODULE_DESCRIPTION("S3C24XX LED driver"); |
diff --git a/drivers/leds/leds-tca6507.c b/drivers/leds/leds-tca6507.c new file mode 100644 index 000000000000..133f89fb7071 --- /dev/null +++ b/drivers/leds/leds-tca6507.c | |||
@@ -0,0 +1,779 @@ | |||
1 | /* | ||
2 | * leds-tca6507 | ||
3 | * | ||
4 | * The TCA6507 is a programmable LED controller that can drive 7 | ||
5 | * separate lines either by holding them low, or by pulsing them | ||
6 | * with modulated width. | ||
7 | * The modulation can be varied in a simple pattern to produce a blink or | ||
8 | * double-blink. | ||
9 | * | ||
10 | * This driver can configure each line either as a 'GPIO' which is out-only | ||
11 | * (no pull-up) or as an LED with variable brightness and hardware-assisted | ||
12 | * blinking. | ||
13 | * | ||
14 | * Apart from OFF and ON there are three programmable brightness levels which | ||
15 | * can be programmed from 0 to 15 and indicate how many 500usec intervals in | ||
16 | * each 8msec that the led is 'on'. The levels are named MASTER, BANK0 and | ||
17 | * BANK1. | ||
18 | * | ||
19 | * There are two different blink rates that can be programmed, each with | ||
20 | * separate time for rise, on, fall, off and second-off. Thus if 3 or more | ||
21 | * different non-trivial rates are required, software must be used for the extra | ||
22 | * rates. The two different blink rates must align with the two levels BANK0 and | ||
23 | * BANK1. | ||
24 | * This driver does not support double-blink so 'second-off' always matches | ||
25 | * 'off'. | ||
26 | * | ||
27 | * Only 16 different times can be programmed in a roughly logarithmic scale from | ||
28 | * 64ms to 16320ms. To be precise the possible times are: | ||
29 | * 0, 64, 128, 192, 256, 384, 512, 768, | ||
30 | * 1024, 1536, 2048, 3072, 4096, 5760, 8128, 16320 | ||
31 | * | ||
32 | * Times that cannot be closely matched with these must be | ||
33 | * handled in software. This driver allows 12.5% error in matching. | ||
34 | * | ||
35 | * This driver does not allow rise/fall rates to be set explicitly. When trying | ||
36 | * to match a given 'on' or 'off' period, an appropriate pair of 'change' and | ||
37 | * 'hold' times are chosen to get a close match. If the target delay is even, | ||
38 | * the 'change' number will be the smaller; if odd, the 'hold' number will be | ||
39 | * the smaller. | ||
40 | |||
41 | * Choosing pairs of delays with 12.5% errors allows us to match delays in the | ||
42 | * ranges: 56-72, 112-144, 168-216, 224-27504, 28560-36720. | ||
43 | * 26% of the achievable sums can be matched by multiple pairings. For example | ||
44 | * 1536 == 1536+0, 1024+512, or 768+768. This driver will always choose the | ||
45 | * pairing with the least maximum - 768+768 in this case. Other pairings are | ||
46 | * not available. | ||
47 | * | ||
48 | * Access to the 3 levels and 2 blinks are on a first-come, first-served basis. | ||
49 | * Access can be shared by multiple leds if they have the same level and | ||
50 | * either same blink rates, or some don't blink. | ||
51 | * When a led changes, it relinquishes access and tries again, so it might | ||
52 | * lose access to hardware blink. | ||
53 | * If a blink engine cannot be allocated, software blink is used. | ||
54 | * If the desired brightness cannot be allocated, the closest available non-zero | ||
55 | * brightness is used. As 'full' is always available, the worst case would be | ||
56 | * to have two different blink rates at '1', with Max at '2', then other leds | ||
57 | * will have to choose between '2' and '16'. Hopefully this is not likely. | ||
58 | * | ||
59 | * Each bank (BANK0 and BANK1) has two usage counts - LEDs using the brightness | ||
60 | * and LEDs using the blink. It can only be reprogrammed when the appropriate | ||
61 | * counter is zero. The MASTER level has a single usage count. | ||
62 | * | ||
63 | * Each Led has programmable 'on' and 'off' time as milliseconds. With each | ||
64 | * there is a flag saying if it was explicitly requested or defaulted. | ||
65 | * Similarly the banks know if each time was explicit or a default. Defaults | ||
66 | * are permitted to be changed freely - they are not recognised when matching. | ||
67 | * | ||
68 | * | ||
69 | * An led-tca6507 device must be provided with platform data. This data | ||
70 | * lists for each output: the name, default trigger, and whether the signal | ||
71 | * is being used as a GPiO rather than an led. 'struct led_plaform_data' | ||
72 | * is used for this. If 'name' is NULL, the output isn't used. If 'flags' | ||
73 | * is TCA6507_MAKE_CPIO, the output is a GPO. | ||
74 | * The "struct led_platform_data" can be embedded in a | ||
75 | * "struct tca6507_platform_data" which adds a 'gpio_base' for the GPiOs, | ||
76 | * and a 'setup' callback which is called once the GPiOs are available. | ||
77 | * | ||
78 | */ | ||
79 | |||
80 | #include <linux/module.h> | ||
81 | #include <linux/slab.h> | ||
82 | #include <linux/leds.h> | ||
83 | #include <linux/err.h> | ||
84 | #include <linux/i2c.h> | ||
85 | #include <linux/gpio.h> | ||
86 | #include <linux/workqueue.h> | ||
87 | #include <linux/leds-tca6507.h> | ||
88 | |||
89 | /* LED select registers determine the source that drives LED outputs */ | ||
90 | #define TCA6507_LS_LED_OFF 0x0 /* Output HI-Z (off) */ | ||
91 | #define TCA6507_LS_LED_OFF1 0x1 /* Output HI-Z (off) - not used */ | ||
92 | #define TCA6507_LS_LED_PWM0 0x2 /* Output LOW with Bank0 rate */ | ||
93 | #define TCA6507_LS_LED_PWM1 0x3 /* Output LOW with Bank1 rate */ | ||
94 | #define TCA6507_LS_LED_ON 0x4 /* Output LOW (on) */ | ||
95 | #define TCA6507_LS_LED_MIR 0x5 /* Output LOW with Master Intensity */ | ||
96 | #define TCA6507_LS_BLINK0 0x6 /* Blink at Bank0 rate */ | ||
97 | #define TCA6507_LS_BLINK1 0x7 /* Blink at Bank1 rate */ | ||
98 | |||
99 | enum { | ||
100 | BANK0, | ||
101 | BANK1, | ||
102 | MASTER, | ||
103 | }; | ||
104 | static int bank_source[3] = { | ||
105 | TCA6507_LS_LED_PWM0, | ||
106 | TCA6507_LS_LED_PWM1, | ||
107 | TCA6507_LS_LED_MIR, | ||
108 | }; | ||
109 | static int blink_source[2] = { | ||
110 | TCA6507_LS_BLINK0, | ||
111 | TCA6507_LS_BLINK1, | ||
112 | }; | ||
113 | |||
114 | /* PWM registers */ | ||
115 | #define TCA6507_REG_CNT 11 | ||
116 | |||
117 | /* | ||
118 | * 0x00, 0x01, 0x02 encode the TCA6507_LS_* values, each output | ||
119 | * owns one bit in each register | ||
120 | */ | ||
121 | #define TCA6507_FADE_ON 0x03 | ||
122 | #define TCA6507_FULL_ON 0x04 | ||
123 | #define TCA6507_FADE_OFF 0x05 | ||
124 | #define TCA6507_FIRST_OFF 0x06 | ||
125 | #define TCA6507_SECOND_OFF 0x07 | ||
126 | #define TCA6507_MAX_INTENSITY 0x08 | ||
127 | #define TCA6507_MASTER_INTENSITY 0x09 | ||
128 | #define TCA6507_INITIALIZE 0x0A | ||
129 | |||
130 | #define INIT_CODE 0x8 | ||
131 | |||
132 | #define TIMECODES 16 | ||
133 | static int time_codes[TIMECODES] = { | ||
134 | 0, 64, 128, 192, 256, 384, 512, 768, | ||
135 | 1024, 1536, 2048, 3072, 4096, 5760, 8128, 16320 | ||
136 | }; | ||
137 | |||
138 | /* Convert an led.brightness level (0..255) to a TCA6507 level (0..15) */ | ||
139 | static inline int TO_LEVEL(int brightness) | ||
140 | { | ||
141 | return brightness >> 4; | ||
142 | } | ||
143 | |||
144 | /* ...and convert back */ | ||
145 | static inline int TO_BRIGHT(int level) | ||
146 | { | ||
147 | if (level) | ||
148 | return (level << 4) | 0xf; | ||
149 | return 0; | ||
150 | } | ||
151 | |||
152 | #define NUM_LEDS 7 | ||
153 | struct tca6507_chip { | ||
154 | int reg_set; /* One bit per register where | ||
155 | * a '1' means the register | ||
156 | * should be written */ | ||
157 | u8 reg_file[TCA6507_REG_CNT]; | ||
158 | /* Bank 2 is Master Intensity and doesn't use times */ | ||
159 | struct bank { | ||
160 | int level; | ||
161 | int ontime, offtime; | ||
162 | int on_dflt, off_dflt; | ||
163 | int time_use, level_use; | ||
164 | } bank[3]; | ||
165 | struct i2c_client *client; | ||
166 | struct work_struct work; | ||
167 | spinlock_t lock; | ||
168 | |||
169 | struct tca6507_led { | ||
170 | struct tca6507_chip *chip; | ||
171 | struct led_classdev led_cdev; | ||
172 | int num; | ||
173 | int ontime, offtime; | ||
174 | int on_dflt, off_dflt; | ||
175 | int bank; /* Bank used, or -1 */ | ||
176 | int blink; /* Set if hardware-blinking */ | ||
177 | } leds[NUM_LEDS]; | ||
178 | #ifdef CONFIG_GPIOLIB | ||
179 | struct gpio_chip gpio; | ||
180 | const char *gpio_name[NUM_LEDS]; | ||
181 | int gpio_map[NUM_LEDS]; | ||
182 | #endif | ||
183 | }; | ||
184 | |||
185 | static const struct i2c_device_id tca6507_id[] = { | ||
186 | { "tca6507" }, | ||
187 | { } | ||
188 | }; | ||
189 | MODULE_DEVICE_TABLE(i2c, tca6507_id); | ||
190 | |||
191 | static int choose_times(int msec, int *c1p, int *c2p) | ||
192 | { | ||
193 | /* | ||
194 | * Choose two timecodes which add to 'msec' as near as possible. | ||
195 | * The first returned is the 'on' or 'off' time. The second is to be | ||
196 | * used as a 'fade-on' or 'fade-off' time. If 'msec' is even, | ||
197 | * the first will not be smaller than the second. If 'msec' is odd, | ||
198 | * the first will not be larger than the second. | ||
199 | * If we cannot get a sum within 1/8 of 'msec' fail with -EINVAL, | ||
200 | * otherwise return the sum that was achieved, plus 1 if the first is | ||
201 | * smaller. | ||
202 | * If two possibilities are equally good (e.g. 512+0, 256+256), choose | ||
203 | * the first pair so there is more change-time visible (i.e. it is | ||
204 | * softer). | ||
205 | */ | ||
206 | int c1, c2; | ||
207 | int tmax = msec * 9 / 8; | ||
208 | int tmin = msec * 7 / 8; | ||
209 | int diff = 65536; | ||
210 | |||
211 | /* We start at '1' to ensure we never even think of choosing a | ||
212 | * total time of '0'. | ||
213 | */ | ||
214 | for (c1 = 1; c1 < TIMECODES; c1++) { | ||
215 | int t = time_codes[c1]; | ||
216 | if (t*2 < tmin) | ||
217 | continue; | ||
218 | if (t > tmax) | ||
219 | break; | ||
220 | for (c2 = 0; c2 <= c1; c2++) { | ||
221 | int tt = t + time_codes[c2]; | ||
222 | int d; | ||
223 | if (tt < tmin) | ||
224 | continue; | ||
225 | if (tt > tmax) | ||
226 | break; | ||
227 | /* This works! */ | ||
228 | d = abs(msec - tt); | ||
229 | if (d >= diff) | ||
230 | continue; | ||
231 | /* Best yet */ | ||
232 | *c1p = c1; | ||
233 | *c2p = c2; | ||
234 | diff = d; | ||
235 | if (d == 0) | ||
236 | return msec; | ||
237 | } | ||
238 | } | ||
239 | if (diff < 65536) { | ||
240 | int actual; | ||
241 | if (msec & 1) { | ||
242 | c1 = *c2p; | ||
243 | *c2p = *c1p; | ||
244 | *c1p = c1; | ||
245 | } | ||
246 | actual = time_codes[*c1p] + time_codes[*c2p]; | ||
247 | if (*c1p < *c2p) | ||
248 | return actual + 1; | ||
249 | else | ||
250 | return actual; | ||
251 | } | ||
252 | /* No close match */ | ||
253 | return -EINVAL; | ||
254 | } | ||
255 | |||
256 | /* | ||
257 | * Update the register file with the appropriate 3-bit state for | ||
258 | * the given led. | ||
259 | */ | ||
260 | static void set_select(struct tca6507_chip *tca, int led, int val) | ||
261 | { | ||
262 | int mask = (1 << led); | ||
263 | int bit; | ||
264 | |||
265 | for (bit = 0; bit < 3; bit++) { | ||
266 | int n = tca->reg_file[bit] & ~mask; | ||
267 | if (val & (1 << bit)) | ||
268 | n |= mask; | ||
269 | if (tca->reg_file[bit] != n) { | ||
270 | tca->reg_file[bit] = n; | ||
271 | tca->reg_set |= (1 << bit); | ||
272 | } | ||
273 | } | ||
274 | } | ||
275 | |||
276 | /* Update the register file with the appropriate 4-bit code for | ||
277 | * one bank or other. This can be used for timers, for levels, or | ||
278 | * for initialisation. | ||
279 | */ | ||
280 | static void set_code(struct tca6507_chip *tca, int reg, int bank, int new) | ||
281 | { | ||
282 | int mask = 0xF; | ||
283 | int n; | ||
284 | if (bank) { | ||
285 | mask <<= 4; | ||
286 | new <<= 4; | ||
287 | } | ||
288 | n = tca->reg_file[reg] & ~mask; | ||
289 | n |= new; | ||
290 | if (tca->reg_file[reg] != n) { | ||
291 | tca->reg_file[reg] = n; | ||
292 | tca->reg_set |= 1 << reg; | ||
293 | } | ||
294 | } | ||
295 | |||
296 | /* Update brightness level. */ | ||
297 | static void set_level(struct tca6507_chip *tca, int bank, int level) | ||
298 | { | ||
299 | switch (bank) { | ||
300 | case BANK0: | ||
301 | case BANK1: | ||
302 | set_code(tca, TCA6507_MAX_INTENSITY, bank, level); | ||
303 | break; | ||
304 | case MASTER: | ||
305 | set_code(tca, TCA6507_MASTER_INTENSITY, 0, level); | ||
306 | break; | ||
307 | } | ||
308 | tca->bank[bank].level = level; | ||
309 | } | ||
310 | |||
311 | /* Record all relevant time code for a given bank */ | ||
312 | static void set_times(struct tca6507_chip *tca, int bank) | ||
313 | { | ||
314 | int c1, c2; | ||
315 | int result; | ||
316 | |||
317 | result = choose_times(tca->bank[bank].ontime, &c1, &c2); | ||
318 | dev_dbg(&tca->client->dev, | ||
319 | "Chose on times %d(%d) %d(%d) for %dms\n", c1, time_codes[c1], | ||
320 | c2, time_codes[c2], tca->bank[bank].ontime); | ||
321 | set_code(tca, TCA6507_FADE_ON, bank, c2); | ||
322 | set_code(tca, TCA6507_FULL_ON, bank, c1); | ||
323 | tca->bank[bank].ontime = result; | ||
324 | |||
325 | result = choose_times(tca->bank[bank].offtime, &c1, &c2); | ||
326 | dev_dbg(&tca->client->dev, | ||
327 | "Chose off times %d(%d) %d(%d) for %dms\n", c1, time_codes[c1], | ||
328 | c2, time_codes[c2], tca->bank[bank].offtime); | ||
329 | set_code(tca, TCA6507_FADE_OFF, bank, c2); | ||
330 | set_code(tca, TCA6507_FIRST_OFF, bank, c1); | ||
331 | set_code(tca, TCA6507_SECOND_OFF, bank, c1); | ||
332 | tca->bank[bank].offtime = result; | ||
333 | |||
334 | set_code(tca, TCA6507_INITIALIZE, bank, INIT_CODE); | ||
335 | } | ||
336 | |||
337 | /* Write all needed register of tca6507 */ | ||
338 | |||
339 | static void tca6507_work(struct work_struct *work) | ||
340 | { | ||
341 | struct tca6507_chip *tca = container_of(work, struct tca6507_chip, | ||
342 | work); | ||
343 | struct i2c_client *cl = tca->client; | ||
344 | int set; | ||
345 | u8 file[TCA6507_REG_CNT]; | ||
346 | int r; | ||
347 | |||
348 | spin_lock_irq(&tca->lock); | ||
349 | set = tca->reg_set; | ||
350 | memcpy(file, tca->reg_file, TCA6507_REG_CNT); | ||
351 | tca->reg_set = 0; | ||
352 | spin_unlock_irq(&tca->lock); | ||
353 | |||
354 | for (r = 0; r < TCA6507_REG_CNT; r++) | ||
355 | if (set & (1<<r)) | ||
356 | i2c_smbus_write_byte_data(cl, r, file[r]); | ||
357 | } | ||
358 | |||
359 | static void led_release(struct tca6507_led *led) | ||
360 | { | ||
361 | /* If led owns any resource, release it. */ | ||
362 | struct tca6507_chip *tca = led->chip; | ||
363 | if (led->bank >= 0) { | ||
364 | struct bank *b = tca->bank + led->bank; | ||
365 | if (led->blink) | ||
366 | b->time_use--; | ||
367 | b->level_use--; | ||
368 | } | ||
369 | led->blink = 0; | ||
370 | led->bank = -1; | ||
371 | } | ||
372 | |||
373 | static int led_prepare(struct tca6507_led *led) | ||
374 | { | ||
375 | /* Assign this led to a bank, configuring that bank if necessary. */ | ||
376 | int level = TO_LEVEL(led->led_cdev.brightness); | ||
377 | struct tca6507_chip *tca = led->chip; | ||
378 | int c1, c2; | ||
379 | int i; | ||
380 | struct bank *b; | ||
381 | int need_init = 0; | ||
382 | |||
383 | led->led_cdev.brightness = TO_BRIGHT(level); | ||
384 | if (level == 0) { | ||
385 | set_select(tca, led->num, TCA6507_LS_LED_OFF); | ||
386 | return 0; | ||
387 | } | ||
388 | |||
389 | if (led->ontime == 0 || led->offtime == 0) { | ||
390 | /* | ||
391 | * Just set the brightness, choosing first usable bank. | ||
392 | * If none perfect, choose best. | ||
393 | * Count backwards so we check MASTER bank first | ||
394 | * to avoid wasting a timer. | ||
395 | */ | ||
396 | int best = -1;/* full-on */ | ||
397 | int diff = 15-level; | ||
398 | |||
399 | if (level == 15) { | ||
400 | set_select(tca, led->num, TCA6507_LS_LED_ON); | ||
401 | return 0; | ||
402 | } | ||
403 | |||
404 | for (i = MASTER; i >= BANK0; i--) { | ||
405 | int d; | ||
406 | if (tca->bank[i].level == level || | ||
407 | tca->bank[i].level_use == 0) { | ||
408 | best = i; | ||
409 | break; | ||
410 | } | ||
411 | d = abs(level - tca->bank[i].level); | ||
412 | if (d < diff) { | ||
413 | diff = d; | ||
414 | best = i; | ||
415 | } | ||
416 | } | ||
417 | if (best == -1) { | ||
418 | /* Best brightness is full-on */ | ||
419 | set_select(tca, led->num, TCA6507_LS_LED_ON); | ||
420 | led->led_cdev.brightness = LED_FULL; | ||
421 | return 0; | ||
422 | } | ||
423 | |||
424 | if (!tca->bank[best].level_use) | ||
425 | set_level(tca, best, level); | ||
426 | |||
427 | tca->bank[best].level_use++; | ||
428 | led->bank = best; | ||
429 | set_select(tca, led->num, bank_source[best]); | ||
430 | led->led_cdev.brightness = TO_BRIGHT(tca->bank[best].level); | ||
431 | return 0; | ||
432 | } | ||
433 | |||
434 | /* | ||
435 | * We have on/off time so we need to try to allocate a timing bank. | ||
436 | * First check if times are compatible with hardware and give up if | ||
437 | * not. | ||
438 | */ | ||
439 | if (choose_times(led->ontime, &c1, &c2) < 0) | ||
440 | return -EINVAL; | ||
441 | if (choose_times(led->offtime, &c1, &c2) < 0) | ||
442 | return -EINVAL; | ||
443 | |||
444 | for (i = BANK0; i <= BANK1; i++) { | ||
445 | if (tca->bank[i].level_use == 0) | ||
446 | /* not in use - it is ours! */ | ||
447 | break; | ||
448 | if (tca->bank[i].level != level) | ||
449 | /* Incompatible level - skip */ | ||
450 | /* FIX: if timer matches we maybe should consider | ||
451 | * this anyway... | ||
452 | */ | ||
453 | continue; | ||
454 | |||
455 | if (tca->bank[i].time_use == 0) | ||
456 | /* Timer not in use, and level matches - use it */ | ||
457 | break; | ||
458 | |||
459 | if (!(tca->bank[i].on_dflt || | ||
460 | led->on_dflt || | ||
461 | tca->bank[i].ontime == led->ontime)) | ||
462 | /* on time is incompatible */ | ||
463 | continue; | ||
464 | |||
465 | if (!(tca->bank[i].off_dflt || | ||
466 | led->off_dflt || | ||
467 | tca->bank[i].offtime == led->offtime)) | ||
468 | /* off time is incompatible */ | ||
469 | continue; | ||
470 | |||
471 | /* looks like a suitable match */ | ||
472 | break; | ||
473 | } | ||
474 | |||
475 | if (i > BANK1) | ||
476 | /* Nothing matches - how sad */ | ||
477 | return -EINVAL; | ||
478 | |||
479 | b = &tca->bank[i]; | ||
480 | if (b->level_use == 0) | ||
481 | set_level(tca, i, level); | ||
482 | b->level_use++; | ||
483 | led->bank = i; | ||
484 | |||
485 | if (b->on_dflt || | ||
486 | !led->on_dflt || | ||
487 | b->time_use == 0) { | ||
488 | b->ontime = led->ontime; | ||
489 | b->on_dflt = led->on_dflt; | ||
490 | need_init = 1; | ||
491 | } | ||
492 | |||
493 | if (b->off_dflt || | ||
494 | !led->off_dflt || | ||
495 | b->time_use == 0) { | ||
496 | b->offtime = led->offtime; | ||
497 | b->off_dflt = led->off_dflt; | ||
498 | need_init = 1; | ||
499 | } | ||
500 | |||
501 | if (need_init) | ||
502 | set_times(tca, i); | ||
503 | |||
504 | led->ontime = b->ontime; | ||
505 | led->offtime = b->offtime; | ||
506 | |||
507 | b->time_use++; | ||
508 | led->blink = 1; | ||
509 | led->led_cdev.brightness = TO_BRIGHT(b->level); | ||
510 | set_select(tca, led->num, blink_source[i]); | ||
511 | return 0; | ||
512 | } | ||
513 | |||
514 | static int led_assign(struct tca6507_led *led) | ||
515 | { | ||
516 | struct tca6507_chip *tca = led->chip; | ||
517 | int err; | ||
518 | unsigned long flags; | ||
519 | |||
520 | spin_lock_irqsave(&tca->lock, flags); | ||
521 | led_release(led); | ||
522 | err = led_prepare(led); | ||
523 | if (err) { | ||
524 | /* | ||
525 | * Can only fail on timer setup. In that case we need to | ||
526 | * re-establish as steady level. | ||
527 | */ | ||
528 | led->ontime = 0; | ||
529 | led->offtime = 0; | ||
530 | led_prepare(led); | ||
531 | } | ||
532 | spin_unlock_irqrestore(&tca->lock, flags); | ||
533 | |||
534 | if (tca->reg_set) | ||
535 | schedule_work(&tca->work); | ||
536 | return err; | ||
537 | } | ||
538 | |||
539 | static void tca6507_brightness_set(struct led_classdev *led_cdev, | ||
540 | enum led_brightness brightness) | ||
541 | { | ||
542 | struct tca6507_led *led = container_of(led_cdev, struct tca6507_led, | ||
543 | led_cdev); | ||
544 | led->led_cdev.brightness = brightness; | ||
545 | led->ontime = 0; | ||
546 | led->offtime = 0; | ||
547 | led_assign(led); | ||
548 | } | ||
549 | |||
550 | static int tca6507_blink_set(struct led_classdev *led_cdev, | ||
551 | unsigned long *delay_on, | ||
552 | unsigned long *delay_off) | ||
553 | { | ||
554 | struct tca6507_led *led = container_of(led_cdev, struct tca6507_led, | ||
555 | led_cdev); | ||
556 | |||
557 | if (*delay_on == 0) | ||
558 | led->on_dflt = 1; | ||
559 | else if (delay_on != &led_cdev->blink_delay_on) | ||
560 | led->on_dflt = 0; | ||
561 | led->ontime = *delay_on; | ||
562 | |||
563 | if (*delay_off == 0) | ||
564 | led->off_dflt = 1; | ||
565 | else if (delay_off != &led_cdev->blink_delay_off) | ||
566 | led->off_dflt = 0; | ||
567 | led->offtime = *delay_off; | ||
568 | |||
569 | if (led->ontime == 0) | ||
570 | led->ontime = 512; | ||
571 | if (led->offtime == 0) | ||
572 | led->offtime = 512; | ||
573 | |||
574 | if (led->led_cdev.brightness == LED_OFF) | ||
575 | led->led_cdev.brightness = LED_FULL; | ||
576 | if (led_assign(led) < 0) { | ||
577 | led->ontime = 0; | ||
578 | led->offtime = 0; | ||
579 | led->led_cdev.brightness = LED_OFF; | ||
580 | return -EINVAL; | ||
581 | } | ||
582 | *delay_on = led->ontime; | ||
583 | *delay_off = led->offtime; | ||
584 | return 0; | ||
585 | } | ||
586 | |||
587 | #ifdef CONFIG_GPIOLIB | ||
588 | static void tca6507_gpio_set_value(struct gpio_chip *gc, | ||
589 | unsigned offset, int val) | ||
590 | { | ||
591 | struct tca6507_chip *tca = container_of(gc, struct tca6507_chip, gpio); | ||
592 | unsigned long flags; | ||
593 | |||
594 | spin_lock_irqsave(&tca->lock, flags); | ||
595 | /* | ||
596 | * 'OFF' is floating high, and 'ON' is pulled down, so it has the | ||
597 | * inverse sense of 'val'. | ||
598 | */ | ||
599 | set_select(tca, tca->gpio_map[offset], | ||
600 | val ? TCA6507_LS_LED_OFF : TCA6507_LS_LED_ON); | ||
601 | spin_unlock_irqrestore(&tca->lock, flags); | ||
602 | if (tca->reg_set) | ||
603 | schedule_work(&tca->work); | ||
604 | } | ||
605 | |||
606 | static int tca6507_gpio_direction_output(struct gpio_chip *gc, | ||
607 | unsigned offset, int val) | ||
608 | { | ||
609 | tca6507_gpio_set_value(gc, offset, val); | ||
610 | return 0; | ||
611 | } | ||
612 | |||
613 | static int tca6507_probe_gpios(struct i2c_client *client, | ||
614 | struct tca6507_chip *tca, | ||
615 | struct tca6507_platform_data *pdata) | ||
616 | { | ||
617 | int err; | ||
618 | int i = 0; | ||
619 | int gpios = 0; | ||
620 | |||
621 | for (i = 0; i < NUM_LEDS; i++) | ||
622 | if (pdata->leds.leds[i].name && pdata->leds.leds[i].flags) { | ||
623 | /* Configure as a gpio */ | ||
624 | tca->gpio_name[gpios] = pdata->leds.leds[i].name; | ||
625 | tca->gpio_map[gpios] = i; | ||
626 | gpios++; | ||
627 | } | ||
628 | |||
629 | if (!gpios) | ||
630 | return 0; | ||
631 | |||
632 | tca->gpio.label = "gpio-tca6507"; | ||
633 | tca->gpio.names = tca->gpio_name; | ||
634 | tca->gpio.ngpio = gpios; | ||
635 | tca->gpio.base = pdata->gpio_base; | ||
636 | tca->gpio.owner = THIS_MODULE; | ||
637 | tca->gpio.direction_output = tca6507_gpio_direction_output; | ||
638 | tca->gpio.set = tca6507_gpio_set_value; | ||
639 | tca->gpio.dev = &client->dev; | ||
640 | err = gpiochip_add(&tca->gpio); | ||
641 | if (err) { | ||
642 | tca->gpio.ngpio = 0; | ||
643 | return err; | ||
644 | } | ||
645 | if (pdata->setup) | ||
646 | pdata->setup(tca->gpio.base, tca->gpio.ngpio); | ||
647 | return 0; | ||
648 | } | ||
649 | |||
650 | static void tca6507_remove_gpio(struct tca6507_chip *tca) | ||
651 | { | ||
652 | if (tca->gpio.ngpio) { | ||
653 | int err = gpiochip_remove(&tca->gpio); | ||
654 | dev_err(&tca->client->dev, "%s failed, %d\n", | ||
655 | "gpiochip_remove()", err); | ||
656 | } | ||
657 | } | ||
658 | #else /* CONFIG_GPIOLIB */ | ||
659 | static int tca6507_probe_gpios(struct i2c_client *client, | ||
660 | struct tca6507_chip *tca, | ||
661 | struct tca6507_platform_data *pdata) | ||
662 | { | ||
663 | return 0; | ||
664 | } | ||
665 | static void tca6507_remove_gpio(struct tca6507_chip *tca) | ||
666 | { | ||
667 | } | ||
668 | #endif /* CONFIG_GPIOLIB */ | ||
669 | |||
670 | static int __devinit tca6507_probe(struct i2c_client *client, | ||
671 | const struct i2c_device_id *id) | ||
672 | { | ||
673 | struct tca6507_chip *tca; | ||
674 | struct i2c_adapter *adapter; | ||
675 | struct tca6507_platform_data *pdata; | ||
676 | int err; | ||
677 | int i = 0; | ||
678 | |||
679 | adapter = to_i2c_adapter(client->dev.parent); | ||
680 | pdata = client->dev.platform_data; | ||
681 | |||
682 | if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) | ||
683 | return -EIO; | ||
684 | |||
685 | if (!pdata || pdata->leds.num_leds != NUM_LEDS) { | ||
686 | dev_err(&client->dev, "Need %d entries in platform-data list\n", | ||
687 | NUM_LEDS); | ||
688 | return -ENODEV; | ||
689 | } | ||
690 | err = -ENOMEM; | ||
691 | tca = kzalloc(sizeof(*tca), GFP_KERNEL); | ||
692 | if (!tca) | ||
693 | goto exit; | ||
694 | |||
695 | tca->client = client; | ||
696 | INIT_WORK(&tca->work, tca6507_work); | ||
697 | spin_lock_init(&tca->lock); | ||
698 | i2c_set_clientdata(client, tca); | ||
699 | |||
700 | for (i = 0; i < NUM_LEDS; i++) { | ||
701 | struct tca6507_led *l = tca->leds + i; | ||
702 | |||
703 | l->chip = tca; | ||
704 | l->num = i; | ||
705 | if (pdata->leds.leds[i].name && !pdata->leds.leds[i].flags) { | ||
706 | l->led_cdev.name = pdata->leds.leds[i].name; | ||
707 | l->led_cdev.default_trigger | ||
708 | = pdata->leds.leds[i].default_trigger; | ||
709 | l->led_cdev.brightness_set = tca6507_brightness_set; | ||
710 | l->led_cdev.blink_set = tca6507_blink_set; | ||
711 | l->bank = -1; | ||
712 | err = led_classdev_register(&client->dev, | ||
713 | &l->led_cdev); | ||
714 | if (err < 0) | ||
715 | goto exit; | ||
716 | } | ||
717 | } | ||
718 | err = tca6507_probe_gpios(client, tca, pdata); | ||
719 | if (err) | ||
720 | goto exit; | ||
721 | /* set all registers to known state - zero */ | ||
722 | tca->reg_set = 0x7f; | ||
723 | schedule_work(&tca->work); | ||
724 | |||
725 | return 0; | ||
726 | exit: | ||
727 | while (i--) | ||
728 | if (tca->leds[i].led_cdev.name) | ||
729 | led_classdev_unregister(&tca->leds[i].led_cdev); | ||
730 | cancel_work_sync(&tca->work); | ||
731 | i2c_set_clientdata(client, NULL); | ||
732 | kfree(tca); | ||
733 | return err; | ||
734 | } | ||
735 | |||
736 | static int __devexit tca6507_remove(struct i2c_client *client) | ||
737 | { | ||
738 | int i; | ||
739 | struct tca6507_chip *tca = i2c_get_clientdata(client); | ||
740 | struct tca6507_led *tca_leds = tca->leds; | ||
741 | |||
742 | for (i = 0; i < NUM_LEDS; i++) { | ||
743 | if (tca_leds[i].led_cdev.name) | ||
744 | led_classdev_unregister(&tca_leds[i].led_cdev); | ||
745 | } | ||
746 | tca6507_remove_gpio(tca); | ||
747 | cancel_work_sync(&tca->work); | ||
748 | i2c_set_clientdata(client, NULL); | ||
749 | kfree(tca); | ||
750 | |||
751 | return 0; | ||
752 | } | ||
753 | |||
754 | static struct i2c_driver tca6507_driver = { | ||
755 | .driver = { | ||
756 | .name = "leds-tca6507", | ||
757 | .owner = THIS_MODULE, | ||
758 | }, | ||
759 | .probe = tca6507_probe, | ||
760 | .remove = __devexit_p(tca6507_remove), | ||
761 | .id_table = tca6507_id, | ||
762 | }; | ||
763 | |||
764 | static int __init tca6507_leds_init(void) | ||
765 | { | ||
766 | return i2c_add_driver(&tca6507_driver); | ||
767 | } | ||
768 | |||
769 | static void __exit tca6507_leds_exit(void) | ||
770 | { | ||
771 | i2c_del_driver(&tca6507_driver); | ||
772 | } | ||
773 | |||
774 | module_init(tca6507_leds_init); | ||
775 | module_exit(tca6507_leds_exit); | ||
776 | |||
777 | MODULE_AUTHOR("NeilBrown <neilb@suse.de>"); | ||
778 | MODULE_DESCRIPTION("TCA6507 LED/GPO driver"); | ||
779 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/leds/leds-wm831x-status.c b/drivers/leds/leds-wm831x-status.c index b1eb34c3e81f..74a24cf897c3 100644 --- a/drivers/leds/leds-wm831x-status.c +++ b/drivers/leds/leds-wm831x-status.c | |||
@@ -237,7 +237,8 @@ static int wm831x_status_probe(struct platform_device *pdev) | |||
237 | goto err; | 237 | goto err; |
238 | } | 238 | } |
239 | 239 | ||
240 | drvdata = kzalloc(sizeof(struct wm831x_status), GFP_KERNEL); | 240 | drvdata = devm_kzalloc(&pdev->dev, sizeof(struct wm831x_status), |
241 | GFP_KERNEL); | ||
241 | if (!drvdata) | 242 | if (!drvdata) |
242 | return -ENOMEM; | 243 | return -ENOMEM; |
243 | dev_set_drvdata(&pdev->dev, drvdata); | 244 | dev_set_drvdata(&pdev->dev, drvdata); |
@@ -300,7 +301,6 @@ static int wm831x_status_probe(struct platform_device *pdev) | |||
300 | 301 | ||
301 | err_led: | 302 | err_led: |
302 | led_classdev_unregister(&drvdata->cdev); | 303 | led_classdev_unregister(&drvdata->cdev); |
303 | kfree(drvdata); | ||
304 | err: | 304 | err: |
305 | return ret; | 305 | return ret; |
306 | } | 306 | } |
@@ -311,7 +311,6 @@ static int wm831x_status_remove(struct platform_device *pdev) | |||
311 | 311 | ||
312 | device_remove_file(drvdata->cdev.dev, &dev_attr_src); | 312 | device_remove_file(drvdata->cdev.dev, &dev_attr_src); |
313 | led_classdev_unregister(&drvdata->cdev); | 313 | led_classdev_unregister(&drvdata->cdev); |
314 | kfree(drvdata); | ||
315 | 314 | ||
316 | return 0; | 315 | return 0; |
317 | } | 316 | } |
@@ -325,17 +324,7 @@ static struct platform_driver wm831x_status_driver = { | |||
325 | .remove = wm831x_status_remove, | 324 | .remove = wm831x_status_remove, |
326 | }; | 325 | }; |
327 | 326 | ||
328 | static int __devinit wm831x_status_init(void) | 327 | module_platform_driver(wm831x_status_driver); |
329 | { | ||
330 | return platform_driver_register(&wm831x_status_driver); | ||
331 | } | ||
332 | module_init(wm831x_status_init); | ||
333 | |||
334 | static void wm831x_status_exit(void) | ||
335 | { | ||
336 | platform_driver_unregister(&wm831x_status_driver); | ||
337 | } | ||
338 | module_exit(wm831x_status_exit); | ||
339 | 328 | ||
340 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); | 329 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); |
341 | MODULE_DESCRIPTION("WM831x status LED driver"); | 330 | MODULE_DESCRIPTION("WM831x status LED driver"); |
diff --git a/drivers/leds/leds-wm8350.c b/drivers/leds/leds-wm8350.c index 4a1276578352..918d4baff1c7 100644 --- a/drivers/leds/leds-wm8350.c +++ b/drivers/leds/leds-wm8350.c | |||
@@ -227,7 +227,7 @@ static int wm8350_led_probe(struct platform_device *pdev) | |||
227 | goto err_isink; | 227 | goto err_isink; |
228 | } | 228 | } |
229 | 229 | ||
230 | led = kzalloc(sizeof(*led), GFP_KERNEL); | 230 | led = devm_kzalloc(&pdev->dev, sizeof(*led), GFP_KERNEL); |
231 | if (led == NULL) { | 231 | if (led == NULL) { |
232 | ret = -ENOMEM; | 232 | ret = -ENOMEM; |
233 | goto err_dcdc; | 233 | goto err_dcdc; |
@@ -259,12 +259,10 @@ static int wm8350_led_probe(struct platform_device *pdev) | |||
259 | 259 | ||
260 | ret = led_classdev_register(&pdev->dev, &led->cdev); | 260 | ret = led_classdev_register(&pdev->dev, &led->cdev); |
261 | if (ret < 0) | 261 | if (ret < 0) |
262 | goto err_led; | 262 | goto err_dcdc; |
263 | 263 | ||
264 | return 0; | 264 | return 0; |
265 | 265 | ||
266 | err_led: | ||
267 | kfree(led); | ||
268 | err_dcdc: | 266 | err_dcdc: |
269 | regulator_put(dcdc); | 267 | regulator_put(dcdc); |
270 | err_isink: | 268 | err_isink: |
@@ -281,7 +279,6 @@ static int wm8350_led_remove(struct platform_device *pdev) | |||
281 | wm8350_led_disable(led); | 279 | wm8350_led_disable(led); |
282 | regulator_put(led->dcdc); | 280 | regulator_put(led->dcdc); |
283 | regulator_put(led->isink); | 281 | regulator_put(led->isink); |
284 | kfree(led); | ||
285 | return 0; | 282 | return 0; |
286 | } | 283 | } |
287 | 284 | ||
@@ -295,17 +292,7 @@ static struct platform_driver wm8350_led_driver = { | |||
295 | .shutdown = wm8350_led_shutdown, | 292 | .shutdown = wm8350_led_shutdown, |
296 | }; | 293 | }; |
297 | 294 | ||
298 | static int __devinit wm8350_led_init(void) | 295 | module_platform_driver(wm8350_led_driver); |
299 | { | ||
300 | return platform_driver_register(&wm8350_led_driver); | ||
301 | } | ||
302 | module_init(wm8350_led_init); | ||
303 | |||
304 | static void wm8350_led_exit(void) | ||
305 | { | ||
306 | platform_driver_unregister(&wm8350_led_driver); | ||
307 | } | ||
308 | module_exit(wm8350_led_exit); | ||
309 | 296 | ||
310 | MODULE_AUTHOR("Mark Brown"); | 297 | MODULE_AUTHOR("Mark Brown"); |
311 | MODULE_DESCRIPTION("WM8350 LED driver"); | 298 | MODULE_DESCRIPTION("WM8350 LED driver"); |
diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index 8e286259a007..8a1c031391d6 100644 --- a/drivers/rtc/interface.c +++ b/drivers/rtc/interface.c | |||
@@ -228,11 +228,11 @@ int __rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) | |||
228 | alarm->time.tm_hour = now.tm_hour; | 228 | alarm->time.tm_hour = now.tm_hour; |
229 | 229 | ||
230 | /* For simplicity, only support date rollover for now */ | 230 | /* For simplicity, only support date rollover for now */ |
231 | if (alarm->time.tm_mday == -1) { | 231 | if (alarm->time.tm_mday < 1 || alarm->time.tm_mday > 31) { |
232 | alarm->time.tm_mday = now.tm_mday; | 232 | alarm->time.tm_mday = now.tm_mday; |
233 | missing = day; | 233 | missing = day; |
234 | } | 234 | } |
235 | if (alarm->time.tm_mon == -1) { | 235 | if ((unsigned)alarm->time.tm_mon >= 12) { |
236 | alarm->time.tm_mon = now.tm_mon; | 236 | alarm->time.tm_mon = now.tm_mon; |
237 | if (missing == none) | 237 | if (missing == none) |
238 | missing = month; | 238 | missing = month; |
diff --git a/drivers/rtc/rtc-88pm860x.c b/drivers/rtc/rtc-88pm860x.c index 64b847b7f970..f04761e6622d 100644 --- a/drivers/rtc/rtc-88pm860x.c +++ b/drivers/rtc/rtc-88pm860x.c | |||
@@ -410,17 +410,7 @@ static struct platform_driver pm860x_rtc_driver = { | |||
410 | .remove = __devexit_p(pm860x_rtc_remove), | 410 | .remove = __devexit_p(pm860x_rtc_remove), |
411 | }; | 411 | }; |
412 | 412 | ||
413 | static int __init pm860x_rtc_init(void) | 413 | module_platform_driver(pm860x_rtc_driver); |
414 | { | ||
415 | return platform_driver_register(&pm860x_rtc_driver); | ||
416 | } | ||
417 | module_init(pm860x_rtc_init); | ||
418 | |||
419 | static void __exit pm860x_rtc_exit(void) | ||
420 | { | ||
421 | platform_driver_unregister(&pm860x_rtc_driver); | ||
422 | } | ||
423 | module_exit(pm860x_rtc_exit); | ||
424 | 414 | ||
425 | MODULE_DESCRIPTION("Marvell 88PM860x RTC driver"); | 415 | MODULE_DESCRIPTION("Marvell 88PM860x RTC driver"); |
426 | MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>"); | 416 | MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>"); |
diff --git a/drivers/rtc/rtc-ab8500.c b/drivers/rtc/rtc-ab8500.c index e346705aae92..a0a9810adf0b 100644 --- a/drivers/rtc/rtc-ab8500.c +++ b/drivers/rtc/rtc-ab8500.c | |||
@@ -90,7 +90,7 @@ static int ab8500_rtc_read_time(struct device *dev, struct rtc_time *tm) | |||
90 | 90 | ||
91 | /* Early AB8500 chips will not clear the rtc read request bit */ | 91 | /* Early AB8500 chips will not clear the rtc read request bit */ |
92 | if (abx500_get_chip_id(dev) == 0) { | 92 | if (abx500_get_chip_id(dev) == 0) { |
93 | msleep(1); | 93 | usleep_range(1000, 1000); |
94 | } else { | 94 | } else { |
95 | /* Wait for some cycles after enabling the rtc read in ab8500 */ | 95 | /* Wait for some cycles after enabling the rtc read in ab8500 */ |
96 | while (time_before(jiffies, timeout)) { | 96 | while (time_before(jiffies, timeout)) { |
@@ -102,7 +102,7 @@ static int ab8500_rtc_read_time(struct device *dev, struct rtc_time *tm) | |||
102 | if (!(value & RTC_READ_REQUEST)) | 102 | if (!(value & RTC_READ_REQUEST)) |
103 | break; | 103 | break; |
104 | 104 | ||
105 | msleep(1); | 105 | usleep_range(1000, 5000); |
106 | } | 106 | } |
107 | } | 107 | } |
108 | 108 | ||
@@ -258,6 +258,109 @@ static int ab8500_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) | |||
258 | return ab8500_rtc_irq_enable(dev, alarm->enabled); | 258 | return ab8500_rtc_irq_enable(dev, alarm->enabled); |
259 | } | 259 | } |
260 | 260 | ||
261 | |||
262 | static int ab8500_rtc_set_calibration(struct device *dev, int calibration) | ||
263 | { | ||
264 | int retval; | ||
265 | u8 rtccal = 0; | ||
266 | |||
267 | /* | ||
268 | * Check that the calibration value (which is in units of 0.5 | ||
269 | * parts-per-million) is in the AB8500's range for RtcCalibration | ||
270 | * register. -128 (0x80) is not permitted because the AB8500 uses | ||
271 | * a sign-bit rather than two's complement, so 0x80 is just another | ||
272 | * representation of zero. | ||
273 | */ | ||
274 | if ((calibration < -127) || (calibration > 127)) { | ||
275 | dev_err(dev, "RtcCalibration value outside permitted range\n"); | ||
276 | return -EINVAL; | ||
277 | } | ||
278 | |||
279 | /* | ||
280 | * The AB8500 uses sign (in bit7) and magnitude (in bits0-7) | ||
281 | * so need to convert to this sort of representation before writing | ||
282 | * into RtcCalibration register... | ||
283 | */ | ||
284 | if (calibration >= 0) | ||
285 | rtccal = 0x7F & calibration; | ||
286 | else | ||
287 | rtccal = ~(calibration - 1) | 0x80; | ||
288 | |||
289 | retval = abx500_set_register_interruptible(dev, AB8500_RTC, | ||
290 | AB8500_RTC_CALIB_REG, rtccal); | ||
291 | |||
292 | return retval; | ||
293 | } | ||
294 | |||
295 | static int ab8500_rtc_get_calibration(struct device *dev, int *calibration) | ||
296 | { | ||
297 | int retval; | ||
298 | u8 rtccal = 0; | ||
299 | |||
300 | retval = abx500_get_register_interruptible(dev, AB8500_RTC, | ||
301 | AB8500_RTC_CALIB_REG, &rtccal); | ||
302 | if (retval >= 0) { | ||
303 | /* | ||
304 | * The AB8500 uses sign (in bit7) and magnitude (in bits0-7) | ||
305 | * so need to convert value from RtcCalibration register into | ||
306 | * a two's complement signed value... | ||
307 | */ | ||
308 | if (rtccal & 0x80) | ||
309 | *calibration = 0 - (rtccal & 0x7F); | ||
310 | else | ||
311 | *calibration = 0x7F & rtccal; | ||
312 | } | ||
313 | |||
314 | return retval; | ||
315 | } | ||
316 | |||
317 | static ssize_t ab8500_sysfs_store_rtc_calibration(struct device *dev, | ||
318 | struct device_attribute *attr, | ||
319 | const char *buf, size_t count) | ||
320 | { | ||
321 | int retval; | ||
322 | int calibration = 0; | ||
323 | |||
324 | if (sscanf(buf, " %i ", &calibration) != 1) { | ||
325 | dev_err(dev, "Failed to store RTC calibration attribute\n"); | ||
326 | return -EINVAL; | ||
327 | } | ||
328 | |||
329 | retval = ab8500_rtc_set_calibration(dev, calibration); | ||
330 | |||
331 | return retval ? retval : count; | ||
332 | } | ||
333 | |||
334 | static ssize_t ab8500_sysfs_show_rtc_calibration(struct device *dev, | ||
335 | struct device_attribute *attr, char *buf) | ||
336 | { | ||
337 | int retval = 0; | ||
338 | int calibration = 0; | ||
339 | |||
340 | retval = ab8500_rtc_get_calibration(dev, &calibration); | ||
341 | if (retval < 0) { | ||
342 | dev_err(dev, "Failed to read RTC calibration attribute\n"); | ||
343 | sprintf(buf, "0\n"); | ||
344 | return retval; | ||
345 | } | ||
346 | |||
347 | return sprintf(buf, "%d\n", calibration); | ||
348 | } | ||
349 | |||
350 | static DEVICE_ATTR(rtc_calibration, S_IRUGO | S_IWUSR, | ||
351 | ab8500_sysfs_show_rtc_calibration, | ||
352 | ab8500_sysfs_store_rtc_calibration); | ||
353 | |||
354 | static int ab8500_sysfs_rtc_register(struct device *dev) | ||
355 | { | ||
356 | return device_create_file(dev, &dev_attr_rtc_calibration); | ||
357 | } | ||
358 | |||
359 | static void ab8500_sysfs_rtc_unregister(struct device *dev) | ||
360 | { | ||
361 | device_remove_file(dev, &dev_attr_rtc_calibration); | ||
362 | } | ||
363 | |||
261 | static irqreturn_t rtc_alarm_handler(int irq, void *data) | 364 | static irqreturn_t rtc_alarm_handler(int irq, void *data) |
262 | { | 365 | { |
263 | struct rtc_device *rtc = data; | 366 | struct rtc_device *rtc = data; |
@@ -295,7 +398,7 @@ static int __devinit ab8500_rtc_probe(struct platform_device *pdev) | |||
295 | return err; | 398 | return err; |
296 | 399 | ||
297 | /* Wait for reset by the PorRtc */ | 400 | /* Wait for reset by the PorRtc */ |
298 | msleep(1); | 401 | usleep_range(1000, 5000); |
299 | 402 | ||
300 | err = abx500_get_register_interruptible(&pdev->dev, AB8500_RTC, | 403 | err = abx500_get_register_interruptible(&pdev->dev, AB8500_RTC, |
301 | AB8500_RTC_STAT_REG, &rtc_ctrl); | 404 | AB8500_RTC_STAT_REG, &rtc_ctrl); |
@@ -308,6 +411,8 @@ static int __devinit ab8500_rtc_probe(struct platform_device *pdev) | |||
308 | return -ENODEV; | 411 | return -ENODEV; |
309 | } | 412 | } |
310 | 413 | ||
414 | device_init_wakeup(&pdev->dev, true); | ||
415 | |||
311 | rtc = rtc_device_register("ab8500-rtc", &pdev->dev, &ab8500_rtc_ops, | 416 | rtc = rtc_device_register("ab8500-rtc", &pdev->dev, &ab8500_rtc_ops, |
312 | THIS_MODULE); | 417 | THIS_MODULE); |
313 | if (IS_ERR(rtc)) { | 418 | if (IS_ERR(rtc)) { |
@@ -316,8 +421,8 @@ static int __devinit ab8500_rtc_probe(struct platform_device *pdev) | |||
316 | return err; | 421 | return err; |
317 | } | 422 | } |
318 | 423 | ||
319 | err = request_threaded_irq(irq, NULL, rtc_alarm_handler, 0, | 424 | err = request_threaded_irq(irq, NULL, rtc_alarm_handler, |
320 | "ab8500-rtc", rtc); | 425 | IRQF_NO_SUSPEND, "ab8500-rtc", rtc); |
321 | if (err < 0) { | 426 | if (err < 0) { |
322 | rtc_device_unregister(rtc); | 427 | rtc_device_unregister(rtc); |
323 | return err; | 428 | return err; |
@@ -325,6 +430,13 @@ static int __devinit ab8500_rtc_probe(struct platform_device *pdev) | |||
325 | 430 | ||
326 | platform_set_drvdata(pdev, rtc); | 431 | platform_set_drvdata(pdev, rtc); |
327 | 432 | ||
433 | |||
434 | err = ab8500_sysfs_rtc_register(&pdev->dev); | ||
435 | if (err) { | ||
436 | dev_err(&pdev->dev, "sysfs RTC failed to register\n"); | ||
437 | return err; | ||
438 | } | ||
439 | |||
328 | return 0; | 440 | return 0; |
329 | } | 441 | } |
330 | 442 | ||
@@ -333,6 +445,8 @@ static int __devexit ab8500_rtc_remove(struct platform_device *pdev) | |||
333 | struct rtc_device *rtc = platform_get_drvdata(pdev); | 445 | struct rtc_device *rtc = platform_get_drvdata(pdev); |
334 | int irq = platform_get_irq_byname(pdev, "ALARM"); | 446 | int irq = platform_get_irq_byname(pdev, "ALARM"); |
335 | 447 | ||
448 | ab8500_sysfs_rtc_unregister(&pdev->dev); | ||
449 | |||
336 | free_irq(irq, rtc); | 450 | free_irq(irq, rtc); |
337 | rtc_device_unregister(rtc); | 451 | rtc_device_unregister(rtc); |
338 | platform_set_drvdata(pdev, NULL); | 452 | platform_set_drvdata(pdev, NULL); |
@@ -349,18 +463,8 @@ static struct platform_driver ab8500_rtc_driver = { | |||
349 | .remove = __devexit_p(ab8500_rtc_remove), | 463 | .remove = __devexit_p(ab8500_rtc_remove), |
350 | }; | 464 | }; |
351 | 465 | ||
352 | static int __init ab8500_rtc_init(void) | 466 | module_platform_driver(ab8500_rtc_driver); |
353 | { | ||
354 | return platform_driver_register(&ab8500_rtc_driver); | ||
355 | } | ||
356 | |||
357 | static void __exit ab8500_rtc_exit(void) | ||
358 | { | ||
359 | platform_driver_unregister(&ab8500_rtc_driver); | ||
360 | } | ||
361 | 467 | ||
362 | module_init(ab8500_rtc_init); | ||
363 | module_exit(ab8500_rtc_exit); | ||
364 | MODULE_AUTHOR("Virupax Sadashivpetimath <virupax.sadashivpetimath@stericsson.com>"); | 468 | MODULE_AUTHOR("Virupax Sadashivpetimath <virupax.sadashivpetimath@stericsson.com>"); |
365 | MODULE_DESCRIPTION("AB8500 RTC Driver"); | 469 | MODULE_DESCRIPTION("AB8500 RTC Driver"); |
366 | MODULE_LICENSE("GPL v2"); | 470 | MODULE_LICENSE("GPL v2"); |
diff --git a/drivers/rtc/rtc-bfin.c b/drivers/rtc/rtc-bfin.c index 90d866272c8e..abfc1a0c07d9 100644 --- a/drivers/rtc/rtc-bfin.c +++ b/drivers/rtc/rtc-bfin.c | |||
@@ -456,18 +456,7 @@ static struct platform_driver bfin_rtc_driver = { | |||
456 | .resume = bfin_rtc_resume, | 456 | .resume = bfin_rtc_resume, |
457 | }; | 457 | }; |
458 | 458 | ||
459 | static int __init bfin_rtc_init(void) | 459 | module_platform_driver(bfin_rtc_driver); |
460 | { | ||
461 | return platform_driver_register(&bfin_rtc_driver); | ||
462 | } | ||
463 | |||
464 | static void __exit bfin_rtc_exit(void) | ||
465 | { | ||
466 | platform_driver_unregister(&bfin_rtc_driver); | ||
467 | } | ||
468 | |||
469 | module_init(bfin_rtc_init); | ||
470 | module_exit(bfin_rtc_exit); | ||
471 | 460 | ||
472 | MODULE_DESCRIPTION("Blackfin On-Chip Real Time Clock Driver"); | 461 | MODULE_DESCRIPTION("Blackfin On-Chip Real Time Clock Driver"); |
473 | MODULE_AUTHOR("Mike Frysinger <vapier@gentoo.org>"); | 462 | MODULE_AUTHOR("Mike Frysinger <vapier@gentoo.org>"); |
diff --git a/drivers/rtc/rtc-bq4802.c b/drivers/rtc/rtc-bq4802.c index 128270ce355d..bf612ef22941 100644 --- a/drivers/rtc/rtc-bq4802.c +++ b/drivers/rtc/rtc-bq4802.c | |||
@@ -218,15 +218,4 @@ static struct platform_driver bq4802_driver = { | |||
218 | .remove = __devexit_p(bq4802_remove), | 218 | .remove = __devexit_p(bq4802_remove), |
219 | }; | 219 | }; |
220 | 220 | ||
221 | static int __init bq4802_init(void) | 221 | module_platform_driver(bq4802_driver); |
222 | { | ||
223 | return platform_driver_register(&bq4802_driver); | ||
224 | } | ||
225 | |||
226 | static void __exit bq4802_exit(void) | ||
227 | { | ||
228 | platform_driver_unregister(&bq4802_driver); | ||
229 | } | ||
230 | |||
231 | module_init(bq4802_init); | ||
232 | module_exit(bq4802_exit); | ||
diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index 05beb6c1ca79..d7782aa09943 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c | |||
@@ -164,7 +164,7 @@ static inline unsigned char cmos_read_bank2(unsigned char addr) | |||
164 | static inline void cmos_write_bank2(unsigned char val, unsigned char addr) | 164 | static inline void cmos_write_bank2(unsigned char val, unsigned char addr) |
165 | { | 165 | { |
166 | outb(addr, RTC_PORT(2)); | 166 | outb(addr, RTC_PORT(2)); |
167 | outb(val, RTC_PORT(2)); | 167 | outb(val, RTC_PORT(3)); |
168 | } | 168 | } |
169 | 169 | ||
170 | #else | 170 | #else |
diff --git a/drivers/rtc/rtc-dm355evm.c b/drivers/rtc/rtc-dm355evm.c index 2322c43af201..d4457afcba89 100644 --- a/drivers/rtc/rtc-dm355evm.c +++ b/drivers/rtc/rtc-dm355evm.c | |||
@@ -161,16 +161,6 @@ static struct platform_driver rtc_dm355evm_driver = { | |||
161 | }, | 161 | }, |
162 | }; | 162 | }; |
163 | 163 | ||
164 | static int __init dm355evm_rtc_init(void) | 164 | module_platform_driver(rtc_dm355evm_driver); |
165 | { | ||
166 | return platform_driver_register(&rtc_dm355evm_driver); | ||
167 | } | ||
168 | module_init(dm355evm_rtc_init); | ||
169 | |||
170 | static void __exit dm355evm_rtc_exit(void) | ||
171 | { | ||
172 | platform_driver_unregister(&rtc_dm355evm_driver); | ||
173 | } | ||
174 | module_exit(dm355evm_rtc_exit); | ||
175 | 165 | ||
176 | MODULE_LICENSE("GPL"); | 166 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/rtc/rtc-ds1286.c b/drivers/rtc/rtc-ds1286.c index 68e6caf25496..990c3ff489bf 100644 --- a/drivers/rtc/rtc-ds1286.c +++ b/drivers/rtc/rtc-ds1286.c | |||
@@ -396,21 +396,10 @@ static struct platform_driver ds1286_platform_driver = { | |||
396 | .remove = __devexit_p(ds1286_remove), | 396 | .remove = __devexit_p(ds1286_remove), |
397 | }; | 397 | }; |
398 | 398 | ||
399 | static int __init ds1286_init(void) | 399 | module_platform_driver(ds1286_platform_driver); |
400 | { | ||
401 | return platform_driver_register(&ds1286_platform_driver); | ||
402 | } | ||
403 | |||
404 | static void __exit ds1286_exit(void) | ||
405 | { | ||
406 | platform_driver_unregister(&ds1286_platform_driver); | ||
407 | } | ||
408 | 400 | ||
409 | MODULE_AUTHOR("Thomas Bogendoerfer <tsbogend@alpha.franken.de>"); | 401 | MODULE_AUTHOR("Thomas Bogendoerfer <tsbogend@alpha.franken.de>"); |
410 | MODULE_DESCRIPTION("DS1286 RTC driver"); | 402 | MODULE_DESCRIPTION("DS1286 RTC driver"); |
411 | MODULE_LICENSE("GPL"); | 403 | MODULE_LICENSE("GPL"); |
412 | MODULE_VERSION(DRV_VERSION); | 404 | MODULE_VERSION(DRV_VERSION); |
413 | MODULE_ALIAS("platform:rtc-ds1286"); | 405 | MODULE_ALIAS("platform:rtc-ds1286"); |
414 | |||
415 | module_init(ds1286_init); | ||
416 | module_exit(ds1286_exit); | ||
diff --git a/drivers/rtc/rtc-ds1511.c b/drivers/rtc/rtc-ds1511.c index 586c244a05d8..761f36bc83a9 100644 --- a/drivers/rtc/rtc-ds1511.c +++ b/drivers/rtc/rtc-ds1511.c | |||
@@ -580,20 +580,7 @@ static struct platform_driver ds1511_rtc_driver = { | |||
580 | }, | 580 | }, |
581 | }; | 581 | }; |
582 | 582 | ||
583 | static int __init | 583 | module_platform_driver(ds1511_rtc_driver); |
584 | ds1511_rtc_init(void) | ||
585 | { | ||
586 | return platform_driver_register(&ds1511_rtc_driver); | ||
587 | } | ||
588 | |||
589 | static void __exit | ||
590 | ds1511_rtc_exit(void) | ||
591 | { | ||
592 | platform_driver_unregister(&ds1511_rtc_driver); | ||
593 | } | ||
594 | |||
595 | module_init(ds1511_rtc_init); | ||
596 | module_exit(ds1511_rtc_exit); | ||
597 | 584 | ||
598 | MODULE_AUTHOR("Andrew Sharp <andy.sharp@lsi.com>"); | 585 | MODULE_AUTHOR("Andrew Sharp <andy.sharp@lsi.com>"); |
599 | MODULE_DESCRIPTION("Dallas DS1511 RTC driver"); | 586 | MODULE_DESCRIPTION("Dallas DS1511 RTC driver"); |
diff --git a/drivers/rtc/rtc-ds1553.c b/drivers/rtc/rtc-ds1553.c index 1350029044e6..6f0a1b530f2e 100644 --- a/drivers/rtc/rtc-ds1553.c +++ b/drivers/rtc/rtc-ds1553.c | |||
@@ -361,18 +361,7 @@ static struct platform_driver ds1553_rtc_driver = { | |||
361 | }, | 361 | }, |
362 | }; | 362 | }; |
363 | 363 | ||
364 | static __init int ds1553_init(void) | 364 | module_platform_driver(ds1553_rtc_driver); |
365 | { | ||
366 | return platform_driver_register(&ds1553_rtc_driver); | ||
367 | } | ||
368 | |||
369 | static __exit void ds1553_exit(void) | ||
370 | { | ||
371 | platform_driver_unregister(&ds1553_rtc_driver); | ||
372 | } | ||
373 | |||
374 | module_init(ds1553_init); | ||
375 | module_exit(ds1553_exit); | ||
376 | 365 | ||
377 | MODULE_AUTHOR("Atsushi Nemoto <anemo@mba.ocn.ne.jp>"); | 366 | MODULE_AUTHOR("Atsushi Nemoto <anemo@mba.ocn.ne.jp>"); |
378 | MODULE_DESCRIPTION("Dallas DS1553 RTC driver"); | 367 | MODULE_DESCRIPTION("Dallas DS1553 RTC driver"); |
diff --git a/drivers/rtc/rtc-ds1742.c b/drivers/rtc/rtc-ds1742.c index e3e0f92b60f0..76112667c507 100644 --- a/drivers/rtc/rtc-ds1742.c +++ b/drivers/rtc/rtc-ds1742.c | |||
@@ -240,18 +240,7 @@ static struct platform_driver ds1742_rtc_driver = { | |||
240 | }, | 240 | }, |
241 | }; | 241 | }; |
242 | 242 | ||
243 | static __init int ds1742_init(void) | 243 | module_platform_driver(ds1742_rtc_driver); |
244 | { | ||
245 | return platform_driver_register(&ds1742_rtc_driver); | ||
246 | } | ||
247 | |||
248 | static __exit void ds1742_exit(void) | ||
249 | { | ||
250 | platform_driver_unregister(&ds1742_rtc_driver); | ||
251 | } | ||
252 | |||
253 | module_init(ds1742_init); | ||
254 | module_exit(ds1742_exit); | ||
255 | 244 | ||
256 | MODULE_AUTHOR("Atsushi Nemoto <anemo@mba.ocn.ne.jp>"); | 245 | MODULE_AUTHOR("Atsushi Nemoto <anemo@mba.ocn.ne.jp>"); |
257 | MODULE_DESCRIPTION("Dallas DS1742 RTC driver"); | 246 | MODULE_DESCRIPTION("Dallas DS1742 RTC driver"); |
diff --git a/drivers/rtc/rtc-jz4740.c b/drivers/rtc/rtc-jz4740.c index b6473631d182..05ab227eeff7 100644 --- a/drivers/rtc/rtc-jz4740.c +++ b/drivers/rtc/rtc-jz4740.c | |||
@@ -345,7 +345,7 @@ static const struct dev_pm_ops jz4740_pm_ops = { | |||
345 | #define JZ4740_RTC_PM_OPS NULL | 345 | #define JZ4740_RTC_PM_OPS NULL |
346 | #endif /* CONFIG_PM */ | 346 | #endif /* CONFIG_PM */ |
347 | 347 | ||
348 | struct platform_driver jz4740_rtc_driver = { | 348 | static struct platform_driver jz4740_rtc_driver = { |
349 | .probe = jz4740_rtc_probe, | 349 | .probe = jz4740_rtc_probe, |
350 | .remove = __devexit_p(jz4740_rtc_remove), | 350 | .remove = __devexit_p(jz4740_rtc_remove), |
351 | .driver = { | 351 | .driver = { |
@@ -355,17 +355,7 @@ struct platform_driver jz4740_rtc_driver = { | |||
355 | }, | 355 | }, |
356 | }; | 356 | }; |
357 | 357 | ||
358 | static int __init jz4740_rtc_init(void) | 358 | module_platform_driver(jz4740_rtc_driver); |
359 | { | ||
360 | return platform_driver_register(&jz4740_rtc_driver); | ||
361 | } | ||
362 | module_init(jz4740_rtc_init); | ||
363 | |||
364 | static void __exit jz4740_rtc_exit(void) | ||
365 | { | ||
366 | platform_driver_unregister(&jz4740_rtc_driver); | ||
367 | } | ||
368 | module_exit(jz4740_rtc_exit); | ||
369 | 359 | ||
370 | MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); | 360 | MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); |
371 | MODULE_LICENSE("GPL"); | 361 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/rtc/rtc-lpc32xx.c b/drivers/rtc/rtc-lpc32xx.c index ae16250c762f..ecc1713b2b4f 100644 --- a/drivers/rtc/rtc-lpc32xx.c +++ b/drivers/rtc/rtc-lpc32xx.c | |||
@@ -396,17 +396,7 @@ static struct platform_driver lpc32xx_rtc_driver = { | |||
396 | }, | 396 | }, |
397 | }; | 397 | }; |
398 | 398 | ||
399 | static int __init lpc32xx_rtc_init(void) | 399 | module_platform_driver(lpc32xx_rtc_driver); |
400 | { | ||
401 | return platform_driver_register(&lpc32xx_rtc_driver); | ||
402 | } | ||
403 | module_init(lpc32xx_rtc_init); | ||
404 | |||
405 | static void __exit lpc32xx_rtc_exit(void) | ||
406 | { | ||
407 | platform_driver_unregister(&lpc32xx_rtc_driver); | ||
408 | } | ||
409 | module_exit(lpc32xx_rtc_exit); | ||
410 | 400 | ||
411 | MODULE_AUTHOR("Kevin Wells <wellsk40@gmail.com"); | 401 | MODULE_AUTHOR("Kevin Wells <wellsk40@gmail.com"); |
412 | MODULE_DESCRIPTION("RTC driver for the LPC32xx SoC"); | 402 | MODULE_DESCRIPTION("RTC driver for the LPC32xx SoC"); |
diff --git a/drivers/rtc/rtc-m41t93.c b/drivers/rtc/rtc-m41t93.c index 7317d3b9a3d5..ef71132ff205 100644 --- a/drivers/rtc/rtc-m41t93.c +++ b/drivers/rtc/rtc-m41t93.c | |||
@@ -200,7 +200,6 @@ static int __devexit m41t93_remove(struct spi_device *spi) | |||
200 | static struct spi_driver m41t93_driver = { | 200 | static struct spi_driver m41t93_driver = { |
201 | .driver = { | 201 | .driver = { |
202 | .name = "rtc-m41t93", | 202 | .name = "rtc-m41t93", |
203 | .bus = &spi_bus_type, | ||
204 | .owner = THIS_MODULE, | 203 | .owner = THIS_MODULE, |
205 | }, | 204 | }, |
206 | .probe = m41t93_probe, | 205 | .probe = m41t93_probe, |
diff --git a/drivers/rtc/rtc-m41t94.c b/drivers/rtc/rtc-m41t94.c index e259ed76ae85..2a4721f61797 100644 --- a/drivers/rtc/rtc-m41t94.c +++ b/drivers/rtc/rtc-m41t94.c | |||
@@ -147,7 +147,6 @@ static int __devexit m41t94_remove(struct spi_device *spi) | |||
147 | static struct spi_driver m41t94_driver = { | 147 | static struct spi_driver m41t94_driver = { |
148 | .driver = { | 148 | .driver = { |
149 | .name = "rtc-m41t94", | 149 | .name = "rtc-m41t94", |
150 | .bus = &spi_bus_type, | ||
151 | .owner = THIS_MODULE, | 150 | .owner = THIS_MODULE, |
152 | }, | 151 | }, |
153 | .probe = m41t94_probe, | 152 | .probe = m41t94_probe, |
diff --git a/drivers/rtc/rtc-m48t35.c b/drivers/rtc/rtc-m48t35.c index 8e2a24e33ed6..f9e3b3583733 100644 --- a/drivers/rtc/rtc-m48t35.c +++ b/drivers/rtc/rtc-m48t35.c | |||
@@ -216,21 +216,10 @@ static struct platform_driver m48t35_platform_driver = { | |||
216 | .remove = __devexit_p(m48t35_remove), | 216 | .remove = __devexit_p(m48t35_remove), |
217 | }; | 217 | }; |
218 | 218 | ||
219 | static int __init m48t35_init(void) | 219 | module_platform_driver(m48t35_platform_driver); |
220 | { | ||
221 | return platform_driver_register(&m48t35_platform_driver); | ||
222 | } | ||
223 | |||
224 | static void __exit m48t35_exit(void) | ||
225 | { | ||
226 | platform_driver_unregister(&m48t35_platform_driver); | ||
227 | } | ||
228 | 220 | ||
229 | MODULE_AUTHOR("Thomas Bogendoerfer <tsbogend@alpha.franken.de>"); | 221 | MODULE_AUTHOR("Thomas Bogendoerfer <tsbogend@alpha.franken.de>"); |
230 | MODULE_DESCRIPTION("M48T35 RTC driver"); | 222 | MODULE_DESCRIPTION("M48T35 RTC driver"); |
231 | MODULE_LICENSE("GPL"); | 223 | MODULE_LICENSE("GPL"); |
232 | MODULE_VERSION(DRV_VERSION); | 224 | MODULE_VERSION(DRV_VERSION); |
233 | MODULE_ALIAS("platform:rtc-m48t35"); | 225 | MODULE_ALIAS("platform:rtc-m48t35"); |
234 | |||
235 | module_init(m48t35_init); | ||
236 | module_exit(m48t35_exit); | ||
diff --git a/drivers/rtc/rtc-m48t59.c b/drivers/rtc/rtc-m48t59.c index 28365388fb6c..30ebfec9fd2b 100644 --- a/drivers/rtc/rtc-m48t59.c +++ b/drivers/rtc/rtc-m48t59.c | |||
@@ -530,18 +530,7 @@ static struct platform_driver m48t59_rtc_driver = { | |||
530 | .remove = __devexit_p(m48t59_rtc_remove), | 530 | .remove = __devexit_p(m48t59_rtc_remove), |
531 | }; | 531 | }; |
532 | 532 | ||
533 | static int __init m48t59_rtc_init(void) | 533 | module_platform_driver(m48t59_rtc_driver); |
534 | { | ||
535 | return platform_driver_register(&m48t59_rtc_driver); | ||
536 | } | ||
537 | |||
538 | static void __exit m48t59_rtc_exit(void) | ||
539 | { | ||
540 | platform_driver_unregister(&m48t59_rtc_driver); | ||
541 | } | ||
542 | |||
543 | module_init(m48t59_rtc_init); | ||
544 | module_exit(m48t59_rtc_exit); | ||
545 | 534 | ||
546 | MODULE_AUTHOR("Mark Zhan <rongkai.zhan@windriver.com>"); | 535 | MODULE_AUTHOR("Mark Zhan <rongkai.zhan@windriver.com>"); |
547 | MODULE_DESCRIPTION("M48T59/M48T02/M48T08 RTC driver"); | 536 | MODULE_DESCRIPTION("M48T59/M48T02/M48T08 RTC driver"); |
diff --git a/drivers/rtc/rtc-m48t86.c b/drivers/rtc/rtc-m48t86.c index f981287d582b..863fb3363aa6 100644 --- a/drivers/rtc/rtc-m48t86.c +++ b/drivers/rtc/rtc-m48t86.c | |||
@@ -185,21 +185,10 @@ static struct platform_driver m48t86_rtc_platform_driver = { | |||
185 | .remove = __devexit_p(m48t86_rtc_remove), | 185 | .remove = __devexit_p(m48t86_rtc_remove), |
186 | }; | 186 | }; |
187 | 187 | ||
188 | static int __init m48t86_rtc_init(void) | 188 | module_platform_driver(m48t86_rtc_platform_driver); |
189 | { | ||
190 | return platform_driver_register(&m48t86_rtc_platform_driver); | ||
191 | } | ||
192 | |||
193 | static void __exit m48t86_rtc_exit(void) | ||
194 | { | ||
195 | platform_driver_unregister(&m48t86_rtc_platform_driver); | ||
196 | } | ||
197 | 189 | ||
198 | MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>"); | 190 | MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>"); |
199 | MODULE_DESCRIPTION("M48T86 RTC driver"); | 191 | MODULE_DESCRIPTION("M48T86 RTC driver"); |
200 | MODULE_LICENSE("GPL"); | 192 | MODULE_LICENSE("GPL"); |
201 | MODULE_VERSION(DRV_VERSION); | 193 | MODULE_VERSION(DRV_VERSION); |
202 | MODULE_ALIAS("platform:rtc-m48t86"); | 194 | MODULE_ALIAS("platform:rtc-m48t86"); |
203 | |||
204 | module_init(m48t86_rtc_init); | ||
205 | module_exit(m48t86_rtc_exit); | ||
diff --git a/drivers/rtc/rtc-max6902.c b/drivers/rtc/rtc-max6902.c index 0ec3f588a255..1f6b3cc58e8a 100644 --- a/drivers/rtc/rtc-max6902.c +++ b/drivers/rtc/rtc-max6902.c | |||
@@ -154,7 +154,6 @@ static int __devexit max6902_remove(struct spi_device *spi) | |||
154 | static struct spi_driver max6902_driver = { | 154 | static struct spi_driver max6902_driver = { |
155 | .driver = { | 155 | .driver = { |
156 | .name = "rtc-max6902", | 156 | .name = "rtc-max6902", |
157 | .bus = &spi_bus_type, | ||
158 | .owner = THIS_MODULE, | 157 | .owner = THIS_MODULE, |
159 | }, | 158 | }, |
160 | .probe = max6902_probe, | 159 | .probe = max6902_probe, |
diff --git a/drivers/rtc/rtc-max8925.c b/drivers/rtc/rtc-max8925.c index 3bc046f427e0..4a5529346b47 100644 --- a/drivers/rtc/rtc-max8925.c +++ b/drivers/rtc/rtc-max8925.c | |||
@@ -299,17 +299,7 @@ static struct platform_driver max8925_rtc_driver = { | |||
299 | .remove = __devexit_p(max8925_rtc_remove), | 299 | .remove = __devexit_p(max8925_rtc_remove), |
300 | }; | 300 | }; |
301 | 301 | ||
302 | static int __init max8925_rtc_init(void) | 302 | module_platform_driver(max8925_rtc_driver); |
303 | { | ||
304 | return platform_driver_register(&max8925_rtc_driver); | ||
305 | } | ||
306 | module_init(max8925_rtc_init); | ||
307 | |||
308 | static void __exit max8925_rtc_exit(void) | ||
309 | { | ||
310 | platform_driver_unregister(&max8925_rtc_driver); | ||
311 | } | ||
312 | module_exit(max8925_rtc_exit); | ||
313 | 303 | ||
314 | MODULE_DESCRIPTION("Maxim MAX8925 RTC driver"); | 304 | MODULE_DESCRIPTION("Maxim MAX8925 RTC driver"); |
315 | MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>"); | 305 | MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>"); |
diff --git a/drivers/rtc/rtc-max8998.c b/drivers/rtc/rtc-max8998.c index 2e48aa604273..7196f438c089 100644 --- a/drivers/rtc/rtc-max8998.c +++ b/drivers/rtc/rtc-max8998.c | |||
@@ -327,17 +327,7 @@ static struct platform_driver max8998_rtc_driver = { | |||
327 | .id_table = max8998_rtc_id, | 327 | .id_table = max8998_rtc_id, |
328 | }; | 328 | }; |
329 | 329 | ||
330 | static int __init max8998_rtc_init(void) | 330 | module_platform_driver(max8998_rtc_driver); |
331 | { | ||
332 | return platform_driver_register(&max8998_rtc_driver); | ||
333 | } | ||
334 | module_init(max8998_rtc_init); | ||
335 | |||
336 | static void __exit max8998_rtc_exit(void) | ||
337 | { | ||
338 | platform_driver_unregister(&max8998_rtc_driver); | ||
339 | } | ||
340 | module_exit(max8998_rtc_exit); | ||
341 | 331 | ||
342 | MODULE_AUTHOR("Minkyu Kang <mk7.kang@samsung.com>"); | 332 | MODULE_AUTHOR("Minkyu Kang <mk7.kang@samsung.com>"); |
343 | MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>"); | 333 | MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>"); |
diff --git a/drivers/rtc/rtc-mc13xxx.c b/drivers/rtc/rtc-mc13xxx.c index 9d0c3b478d55..546f6850bffb 100644 --- a/drivers/rtc/rtc-mc13xxx.c +++ b/drivers/rtc/rtc-mc13xxx.c | |||
@@ -399,7 +399,7 @@ static int __exit mc13xxx_rtc_remove(struct platform_device *pdev) | |||
399 | return 0; | 399 | return 0; |
400 | } | 400 | } |
401 | 401 | ||
402 | const struct platform_device_id mc13xxx_rtc_idtable[] = { | 402 | static const struct platform_device_id mc13xxx_rtc_idtable[] = { |
403 | { | 403 | { |
404 | .name = "mc13783-rtc", | 404 | .name = "mc13783-rtc", |
405 | }, { | 405 | }, { |
diff --git a/drivers/rtc/rtc-mpc5121.c b/drivers/rtc/rtc-mpc5121.c index da60915818b6..9d3caccfc250 100644 --- a/drivers/rtc/rtc-mpc5121.c +++ b/drivers/rtc/rtc-mpc5121.c | |||
@@ -418,17 +418,7 @@ static struct platform_driver mpc5121_rtc_driver = { | |||
418 | .remove = __devexit_p(mpc5121_rtc_remove), | 418 | .remove = __devexit_p(mpc5121_rtc_remove), |
419 | }; | 419 | }; |
420 | 420 | ||
421 | static int __init mpc5121_rtc_init(void) | 421 | module_platform_driver(mpc5121_rtc_driver); |
422 | { | ||
423 | return platform_driver_register(&mpc5121_rtc_driver); | ||
424 | } | ||
425 | module_init(mpc5121_rtc_init); | ||
426 | |||
427 | static void __exit mpc5121_rtc_exit(void) | ||
428 | { | ||
429 | platform_driver_unregister(&mpc5121_rtc_driver); | ||
430 | } | ||
431 | module_exit(mpc5121_rtc_exit); | ||
432 | 422 | ||
433 | MODULE_LICENSE("GPL"); | 423 | MODULE_LICENSE("GPL"); |
434 | MODULE_AUTHOR("John Rigby <jcrigby@gmail.com>"); | 424 | MODULE_AUTHOR("John Rigby <jcrigby@gmail.com>"); |
diff --git a/drivers/rtc/rtc-mrst.c b/drivers/rtc/rtc-mrst.c index bb21f443fb70..6cd6c7235344 100644 --- a/drivers/rtc/rtc-mrst.c +++ b/drivers/rtc/rtc-mrst.c | |||
@@ -537,18 +537,7 @@ static struct platform_driver vrtc_mrst_platform_driver = { | |||
537 | } | 537 | } |
538 | }; | 538 | }; |
539 | 539 | ||
540 | static int __init vrtc_mrst_init(void) | 540 | module_platform_driver(vrtc_mrst_platform_driver); |
541 | { | ||
542 | return platform_driver_register(&vrtc_mrst_platform_driver); | ||
543 | } | ||
544 | |||
545 | static void __exit vrtc_mrst_exit(void) | ||
546 | { | ||
547 | platform_driver_unregister(&vrtc_mrst_platform_driver); | ||
548 | } | ||
549 | |||
550 | module_init(vrtc_mrst_init); | ||
551 | module_exit(vrtc_mrst_exit); | ||
552 | 541 | ||
553 | MODULE_AUTHOR("Jacob Pan; Feng Tang"); | 542 | MODULE_AUTHOR("Jacob Pan; Feng Tang"); |
554 | MODULE_DESCRIPTION("Driver for Moorestown virtual RTC"); | 543 | MODULE_DESCRIPTION("Driver for Moorestown virtual RTC"); |
diff --git a/drivers/rtc/rtc-mxc.c b/drivers/rtc/rtc-mxc.c index 39e41fbdf08b..5e1d64ee5228 100644 --- a/drivers/rtc/rtc-mxc.c +++ b/drivers/rtc/rtc-mxc.c | |||
@@ -155,7 +155,6 @@ static int rtc_update_alarm(struct device *dev, struct rtc_time *alrm) | |||
155 | { | 155 | { |
156 | struct rtc_time alarm_tm, now_tm; | 156 | struct rtc_time alarm_tm, now_tm; |
157 | unsigned long now, time; | 157 | unsigned long now, time; |
158 | int ret; | ||
159 | struct platform_device *pdev = to_platform_device(dev); | 158 | struct platform_device *pdev = to_platform_device(dev); |
160 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | 159 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); |
161 | void __iomem *ioaddr = pdata->ioaddr; | 160 | void __iomem *ioaddr = pdata->ioaddr; |
@@ -168,21 +167,33 @@ static int rtc_update_alarm(struct device *dev, struct rtc_time *alrm) | |||
168 | alarm_tm.tm_hour = alrm->tm_hour; | 167 | alarm_tm.tm_hour = alrm->tm_hour; |
169 | alarm_tm.tm_min = alrm->tm_min; | 168 | alarm_tm.tm_min = alrm->tm_min; |
170 | alarm_tm.tm_sec = alrm->tm_sec; | 169 | alarm_tm.tm_sec = alrm->tm_sec; |
171 | rtc_tm_to_time(&now_tm, &now); | ||
172 | rtc_tm_to_time(&alarm_tm, &time); | 170 | rtc_tm_to_time(&alarm_tm, &time); |
173 | 171 | ||
174 | if (time < now) { | ||
175 | time += 60 * 60 * 24; | ||
176 | rtc_time_to_tm(time, &alarm_tm); | ||
177 | } | ||
178 | |||
179 | ret = rtc_tm_to_time(&alarm_tm, &time); | ||
180 | |||
181 | /* clear all the interrupt status bits */ | 172 | /* clear all the interrupt status bits */ |
182 | writew(readw(ioaddr + RTC_RTCISR), ioaddr + RTC_RTCISR); | 173 | writew(readw(ioaddr + RTC_RTCISR), ioaddr + RTC_RTCISR); |
183 | set_alarm_or_time(dev, MXC_RTC_ALARM, time); | 174 | set_alarm_or_time(dev, MXC_RTC_ALARM, time); |
184 | 175 | ||
185 | return ret; | 176 | return 0; |
177 | } | ||
178 | |||
179 | static void mxc_rtc_irq_enable(struct device *dev, unsigned int bit, | ||
180 | unsigned int enabled) | ||
181 | { | ||
182 | struct platform_device *pdev = to_platform_device(dev); | ||
183 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | ||
184 | void __iomem *ioaddr = pdata->ioaddr; | ||
185 | u32 reg; | ||
186 | |||
187 | spin_lock_irq(&pdata->rtc->irq_lock); | ||
188 | reg = readw(ioaddr + RTC_RTCIENR); | ||
189 | |||
190 | if (enabled) | ||
191 | reg |= bit; | ||
192 | else | ||
193 | reg &= ~bit; | ||
194 | |||
195 | writew(reg, ioaddr + RTC_RTCIENR); | ||
196 | spin_unlock_irq(&pdata->rtc->irq_lock); | ||
186 | } | 197 | } |
187 | 198 | ||
188 | /* This function is the RTC interrupt service routine. */ | 199 | /* This function is the RTC interrupt service routine. */ |
@@ -199,13 +210,12 @@ static irqreturn_t mxc_rtc_interrupt(int irq, void *dev_id) | |||
199 | /* clear interrupt sources */ | 210 | /* clear interrupt sources */ |
200 | writew(status, ioaddr + RTC_RTCISR); | 211 | writew(status, ioaddr + RTC_RTCISR); |
201 | 212 | ||
202 | /* clear alarm interrupt if it has occurred */ | ||
203 | if (status & RTC_ALM_BIT) | ||
204 | status &= ~RTC_ALM_BIT; | ||
205 | |||
206 | /* update irq data & counter */ | 213 | /* update irq data & counter */ |
207 | if (status & RTC_ALM_BIT) | 214 | if (status & RTC_ALM_BIT) { |
208 | events |= (RTC_AF | RTC_IRQF); | 215 | events |= (RTC_AF | RTC_IRQF); |
216 | /* RTC alarm should be one-shot */ | ||
217 | mxc_rtc_irq_enable(&pdev->dev, RTC_ALM_BIT, 0); | ||
218 | } | ||
209 | 219 | ||
210 | if (status & RTC_1HZ_BIT) | 220 | if (status & RTC_1HZ_BIT) |
211 | events |= (RTC_UF | RTC_IRQF); | 221 | events |= (RTC_UF | RTC_IRQF); |
@@ -213,9 +223,6 @@ static irqreturn_t mxc_rtc_interrupt(int irq, void *dev_id) | |||
213 | if (status & PIT_ALL_ON) | 223 | if (status & PIT_ALL_ON) |
214 | events |= (RTC_PF | RTC_IRQF); | 224 | events |= (RTC_PF | RTC_IRQF); |
215 | 225 | ||
216 | if ((status & RTC_ALM_BIT) && rtc_valid_tm(&pdata->g_rtc_alarm)) | ||
217 | rtc_update_alarm(&pdev->dev, &pdata->g_rtc_alarm); | ||
218 | |||
219 | rtc_update_irq(pdata->rtc, 1, events); | 226 | rtc_update_irq(pdata->rtc, 1, events); |
220 | spin_unlock_irq(&pdata->rtc->irq_lock); | 227 | spin_unlock_irq(&pdata->rtc->irq_lock); |
221 | 228 | ||
@@ -242,26 +249,6 @@ static void mxc_rtc_release(struct device *dev) | |||
242 | spin_unlock_irq(&pdata->rtc->irq_lock); | 249 | spin_unlock_irq(&pdata->rtc->irq_lock); |
243 | } | 250 | } |
244 | 251 | ||
245 | static void mxc_rtc_irq_enable(struct device *dev, unsigned int bit, | ||
246 | unsigned int enabled) | ||
247 | { | ||
248 | struct platform_device *pdev = to_platform_device(dev); | ||
249 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | ||
250 | void __iomem *ioaddr = pdata->ioaddr; | ||
251 | u32 reg; | ||
252 | |||
253 | spin_lock_irq(&pdata->rtc->irq_lock); | ||
254 | reg = readw(ioaddr + RTC_RTCIENR); | ||
255 | |||
256 | if (enabled) | ||
257 | reg |= bit; | ||
258 | else | ||
259 | reg &= ~bit; | ||
260 | |||
261 | writew(reg, ioaddr + RTC_RTCIENR); | ||
262 | spin_unlock_irq(&pdata->rtc->irq_lock); | ||
263 | } | ||
264 | |||
265 | static int mxc_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) | 252 | static int mxc_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) |
266 | { | 253 | { |
267 | mxc_rtc_irq_enable(dev, RTC_ALM_BIT, enabled); | 254 | mxc_rtc_irq_enable(dev, RTC_ALM_BIT, enabled); |
@@ -290,6 +277,17 @@ static int mxc_rtc_read_time(struct device *dev, struct rtc_time *tm) | |||
290 | */ | 277 | */ |
291 | static int mxc_rtc_set_mmss(struct device *dev, unsigned long time) | 278 | static int mxc_rtc_set_mmss(struct device *dev, unsigned long time) |
292 | { | 279 | { |
280 | /* | ||
281 | * TTC_DAYR register is 9-bit in MX1 SoC, save time and day of year only | ||
282 | */ | ||
283 | if (cpu_is_mx1()) { | ||
284 | struct rtc_time tm; | ||
285 | |||
286 | rtc_time_to_tm(time, &tm); | ||
287 | tm.tm_year = 70; | ||
288 | rtc_tm_to_time(&tm, &time); | ||
289 | } | ||
290 | |||
293 | /* Avoid roll-over from reading the different registers */ | 291 | /* Avoid roll-over from reading the different registers */ |
294 | do { | 292 | do { |
295 | set_alarm_or_time(dev, MXC_RTC_TIME, time); | 293 | set_alarm_or_time(dev, MXC_RTC_TIME, time); |
@@ -324,21 +322,7 @@ static int mxc_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
324 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | 322 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); |
325 | int ret; | 323 | int ret; |
326 | 324 | ||
327 | if (rtc_valid_tm(&alrm->time)) { | 325 | ret = rtc_update_alarm(dev, &alrm->time); |
328 | if (alrm->time.tm_sec > 59 || | ||
329 | alrm->time.tm_hour > 23 || | ||
330 | alrm->time.tm_min > 59) | ||
331 | return -EINVAL; | ||
332 | |||
333 | ret = rtc_update_alarm(dev, &alrm->time); | ||
334 | } else { | ||
335 | ret = rtc_valid_tm(&alrm->time); | ||
336 | if (ret) | ||
337 | return ret; | ||
338 | |||
339 | ret = rtc_update_alarm(dev, &alrm->time); | ||
340 | } | ||
341 | |||
342 | if (ret) | 326 | if (ret) |
343 | return ret; | 327 | return ret; |
344 | 328 | ||
@@ -424,6 +408,9 @@ static int __init mxc_rtc_probe(struct platform_device *pdev) | |||
424 | pdata->irq = -1; | 408 | pdata->irq = -1; |
425 | } | 409 | } |
426 | 410 | ||
411 | if (pdata->irq >=0) | ||
412 | device_init_wakeup(&pdev->dev, 1); | ||
413 | |||
427 | rtc = rtc_device_register(pdev->name, &pdev->dev, &mxc_rtc_ops, | 414 | rtc = rtc_device_register(pdev->name, &pdev->dev, &mxc_rtc_ops, |
428 | THIS_MODULE); | 415 | THIS_MODULE); |
429 | if (IS_ERR(rtc)) { | 416 | if (IS_ERR(rtc)) { |
@@ -459,9 +446,39 @@ static int __exit mxc_rtc_remove(struct platform_device *pdev) | |||
459 | return 0; | 446 | return 0; |
460 | } | 447 | } |
461 | 448 | ||
449 | #ifdef CONFIG_PM | ||
450 | static int mxc_rtc_suspend(struct device *dev) | ||
451 | { | ||
452 | struct rtc_plat_data *pdata = dev_get_drvdata(dev); | ||
453 | |||
454 | if (device_may_wakeup(dev)) | ||
455 | enable_irq_wake(pdata->irq); | ||
456 | |||
457 | return 0; | ||
458 | } | ||
459 | |||
460 | static int mxc_rtc_resume(struct device *dev) | ||
461 | { | ||
462 | struct rtc_plat_data *pdata = dev_get_drvdata(dev); | ||
463 | |||
464 | if (device_may_wakeup(dev)) | ||
465 | disable_irq_wake(pdata->irq); | ||
466 | |||
467 | return 0; | ||
468 | } | ||
469 | |||
470 | static struct dev_pm_ops mxc_rtc_pm_ops = { | ||
471 | .suspend = mxc_rtc_suspend, | ||
472 | .resume = mxc_rtc_resume, | ||
473 | }; | ||
474 | #endif | ||
475 | |||
462 | static struct platform_driver mxc_rtc_driver = { | 476 | static struct platform_driver mxc_rtc_driver = { |
463 | .driver = { | 477 | .driver = { |
464 | .name = "mxc_rtc", | 478 | .name = "mxc_rtc", |
479 | #ifdef CONFIG_PM | ||
480 | .pm = &mxc_rtc_pm_ops, | ||
481 | #endif | ||
465 | .owner = THIS_MODULE, | 482 | .owner = THIS_MODULE, |
466 | }, | 483 | }, |
467 | .remove = __exit_p(mxc_rtc_remove), | 484 | .remove = __exit_p(mxc_rtc_remove), |
diff --git a/drivers/rtc/rtc-pcf2123.c b/drivers/rtc/rtc-pcf2123.c index 2ee3bbf7e5ea..b46c4004d8fe 100644 --- a/drivers/rtc/rtc-pcf2123.c +++ b/drivers/rtc/rtc-pcf2123.c | |||
@@ -340,7 +340,6 @@ static int __devexit pcf2123_remove(struct spi_device *spi) | |||
340 | static struct spi_driver pcf2123_driver = { | 340 | static struct spi_driver pcf2123_driver = { |
341 | .driver = { | 341 | .driver = { |
342 | .name = "rtc-pcf2123", | 342 | .name = "rtc-pcf2123", |
343 | .bus = &spi_bus_type, | ||
344 | .owner = THIS_MODULE, | 343 | .owner = THIS_MODULE, |
345 | }, | 344 | }, |
346 | .probe = pcf2123_probe, | 345 | .probe = pcf2123_probe, |
diff --git a/drivers/rtc/rtc-pcf50633.c b/drivers/rtc/rtc-pcf50633.c index 0c423892923c..a20202f9ee57 100644 --- a/drivers/rtc/rtc-pcf50633.c +++ b/drivers/rtc/rtc-pcf50633.c | |||
@@ -294,17 +294,7 @@ static struct platform_driver pcf50633_rtc_driver = { | |||
294 | .remove = __devexit_p(pcf50633_rtc_remove), | 294 | .remove = __devexit_p(pcf50633_rtc_remove), |
295 | }; | 295 | }; |
296 | 296 | ||
297 | static int __init pcf50633_rtc_init(void) | 297 | module_platform_driver(pcf50633_rtc_driver); |
298 | { | ||
299 | return platform_driver_register(&pcf50633_rtc_driver); | ||
300 | } | ||
301 | module_init(pcf50633_rtc_init); | ||
302 | |||
303 | static void __exit pcf50633_rtc_exit(void) | ||
304 | { | ||
305 | platform_driver_unregister(&pcf50633_rtc_driver); | ||
306 | } | ||
307 | module_exit(pcf50633_rtc_exit); | ||
308 | 298 | ||
309 | MODULE_DESCRIPTION("PCF50633 RTC driver"); | 299 | MODULE_DESCRIPTION("PCF50633 RTC driver"); |
310 | MODULE_AUTHOR("Balaji Rao <balajirrao@openmoko.org>"); | 300 | MODULE_AUTHOR("Balaji Rao <balajirrao@openmoko.org>"); |
diff --git a/drivers/rtc/rtc-pm8xxx.c b/drivers/rtc/rtc-pm8xxx.c index d420e9d877e8..9f1d6bcbdf6c 100644 --- a/drivers/rtc/rtc-pm8xxx.c +++ b/drivers/rtc/rtc-pm8xxx.c | |||
@@ -532,17 +532,7 @@ static struct platform_driver pm8xxx_rtc_driver = { | |||
532 | }, | 532 | }, |
533 | }; | 533 | }; |
534 | 534 | ||
535 | static int __init pm8xxx_rtc_init(void) | 535 | module_platform_driver(pm8xxx_rtc_driver); |
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 | 536 | ||
547 | MODULE_ALIAS("platform:rtc-pm8xxx"); | 537 | MODULE_ALIAS("platform:rtc-pm8xxx"); |
548 | MODULE_DESCRIPTION("PMIC8xxx RTC driver"); | 538 | MODULE_DESCRIPTION("PMIC8xxx RTC driver"); |
diff --git a/drivers/rtc/rtc-rs5c348.c b/drivers/rtc/rtc-rs5c348.c index 971bc8e08da6..ce2ca8523ddd 100644 --- a/drivers/rtc/rtc-rs5c348.c +++ b/drivers/rtc/rtc-rs5c348.c | |||
@@ -229,7 +229,6 @@ static int __devexit rs5c348_remove(struct spi_device *spi) | |||
229 | static struct spi_driver rs5c348_driver = { | 229 | static struct spi_driver rs5c348_driver = { |
230 | .driver = { | 230 | .driver = { |
231 | .name = "rtc-rs5c348", | 231 | .name = "rtc-rs5c348", |
232 | .bus = &spi_bus_type, | ||
233 | .owner = THIS_MODULE, | 232 | .owner = THIS_MODULE, |
234 | }, | 233 | }, |
235 | .probe = rs5c348_probe, | 234 | .probe = rs5c348_probe, |
diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c index 175067a17c46..aef40bd2957b 100644 --- a/drivers/rtc/rtc-s3c.c +++ b/drivers/rtc/rtc-s3c.c | |||
@@ -673,21 +673,7 @@ static struct platform_driver s3c_rtc_driver = { | |||
673 | }, | 673 | }, |
674 | }; | 674 | }; |
675 | 675 | ||
676 | static char __initdata banner[] = "S3C24XX RTC, (c) 2004,2006 Simtec Electronics\n"; | 676 | module_platform_driver(s3c_rtc_driver); |
677 | |||
678 | static int __init s3c_rtc_init(void) | ||
679 | { | ||
680 | printk(banner); | ||
681 | return platform_driver_register(&s3c_rtc_driver); | ||
682 | } | ||
683 | |||
684 | static void __exit s3c_rtc_exit(void) | ||
685 | { | ||
686 | platform_driver_unregister(&s3c_rtc_driver); | ||
687 | } | ||
688 | |||
689 | module_init(s3c_rtc_init); | ||
690 | module_exit(s3c_rtc_exit); | ||
691 | 677 | ||
692 | MODULE_DESCRIPTION("Samsung S3C RTC Driver"); | 678 | MODULE_DESCRIPTION("Samsung S3C RTC Driver"); |
693 | MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>"); | 679 | MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>"); |
diff --git a/drivers/rtc/rtc-sa1100.c b/drivers/rtc/rtc-sa1100.c index fc1ffe97fca1..4595d3e645a7 100644 --- a/drivers/rtc/rtc-sa1100.c +++ b/drivers/rtc/rtc-sa1100.c | |||
@@ -435,18 +435,7 @@ static struct platform_driver sa1100_rtc_driver = { | |||
435 | }, | 435 | }, |
436 | }; | 436 | }; |
437 | 437 | ||
438 | static int __init sa1100_rtc_init(void) | 438 | module_platform_driver(sa1100_rtc_driver); |
439 | { | ||
440 | return platform_driver_register(&sa1100_rtc_driver); | ||
441 | } | ||
442 | |||
443 | static void __exit sa1100_rtc_exit(void) | ||
444 | { | ||
445 | platform_driver_unregister(&sa1100_rtc_driver); | ||
446 | } | ||
447 | |||
448 | module_init(sa1100_rtc_init); | ||
449 | module_exit(sa1100_rtc_exit); | ||
450 | 439 | ||
451 | MODULE_AUTHOR("Richard Purdie <rpurdie@rpsys.net>"); | 440 | MODULE_AUTHOR("Richard Purdie <rpurdie@rpsys.net>"); |
452 | MODULE_DESCRIPTION("SA11x0/PXA2xx Realtime Clock Driver (RTC)"); | 441 | MODULE_DESCRIPTION("SA11x0/PXA2xx Realtime Clock Driver (RTC)"); |
diff --git a/drivers/rtc/rtc-spear.c b/drivers/rtc/rtc-spear.c index 893bac2bb21b..19a28a671a8e 100644 --- a/drivers/rtc/rtc-spear.c +++ b/drivers/rtc/rtc-spear.c | |||
@@ -516,17 +516,7 @@ static struct platform_driver spear_rtc_driver = { | |||
516 | }, | 516 | }, |
517 | }; | 517 | }; |
518 | 518 | ||
519 | static int __init rtc_init(void) | 519 | module_platform_driver(spear_rtc_driver); |
520 | { | ||
521 | return platform_driver_register(&spear_rtc_driver); | ||
522 | } | ||
523 | module_init(rtc_init); | ||
524 | |||
525 | static void __exit rtc_exit(void) | ||
526 | { | ||
527 | platform_driver_unregister(&spear_rtc_driver); | ||
528 | } | ||
529 | module_exit(rtc_exit); | ||
530 | 520 | ||
531 | MODULE_ALIAS("platform:rtc-spear"); | 521 | MODULE_ALIAS("platform:rtc-spear"); |
532 | MODULE_AUTHOR("Rajeev Kumar <rajeev-dlh.kumar@st.com>"); | 522 | MODULE_AUTHOR("Rajeev Kumar <rajeev-dlh.kumar@st.com>"); |
diff --git a/drivers/rtc/rtc-stk17ta8.c b/drivers/rtc/rtc-stk17ta8.c index ed3e9b599031..7621116bd20d 100644 --- a/drivers/rtc/rtc-stk17ta8.c +++ b/drivers/rtc/rtc-stk17ta8.c | |||
@@ -370,18 +370,7 @@ static struct platform_driver stk17ta8_rtc_driver = { | |||
370 | }, | 370 | }, |
371 | }; | 371 | }; |
372 | 372 | ||
373 | static __init int stk17ta8_init(void) | 373 | module_platform_driver(stk17ta8_rtc_driver); |
374 | { | ||
375 | return platform_driver_register(&stk17ta8_rtc_driver); | ||
376 | } | ||
377 | |||
378 | static __exit void stk17ta8_exit(void) | ||
379 | { | ||
380 | platform_driver_unregister(&stk17ta8_rtc_driver); | ||
381 | } | ||
382 | |||
383 | module_init(stk17ta8_init); | ||
384 | module_exit(stk17ta8_exit); | ||
385 | 374 | ||
386 | MODULE_AUTHOR("Thomas Hommel <thomas.hommel@ge.com>"); | 375 | MODULE_AUTHOR("Thomas Hommel <thomas.hommel@ge.com>"); |
387 | MODULE_DESCRIPTION("Simtek STK17TA8 RTC driver"); | 376 | MODULE_DESCRIPTION("Simtek STK17TA8 RTC driver"); |
diff --git a/drivers/rtc/rtc-stmp3xxx.c b/drivers/rtc/rtc-stmp3xxx.c index 7315068daa59..10287865e330 100644 --- a/drivers/rtc/rtc-stmp3xxx.c +++ b/drivers/rtc/rtc-stmp3xxx.c | |||
@@ -276,18 +276,7 @@ static struct platform_driver stmp3xxx_rtcdrv = { | |||
276 | }, | 276 | }, |
277 | }; | 277 | }; |
278 | 278 | ||
279 | static int __init stmp3xxx_rtc_init(void) | 279 | module_platform_driver(stmp3xxx_rtcdrv); |
280 | { | ||
281 | return platform_driver_register(&stmp3xxx_rtcdrv); | ||
282 | } | ||
283 | |||
284 | static void __exit stmp3xxx_rtc_exit(void) | ||
285 | { | ||
286 | platform_driver_unregister(&stmp3xxx_rtcdrv); | ||
287 | } | ||
288 | |||
289 | module_init(stmp3xxx_rtc_init); | ||
290 | module_exit(stmp3xxx_rtc_exit); | ||
291 | 280 | ||
292 | MODULE_DESCRIPTION("STMP3xxx RTC Driver"); | 281 | MODULE_DESCRIPTION("STMP3xxx RTC Driver"); |
293 | MODULE_AUTHOR("dmitry pervushin <dpervushin@embeddedalley.com> and " | 282 | MODULE_AUTHOR("dmitry pervushin <dpervushin@embeddedalley.com> and " |
diff --git a/drivers/rtc/rtc-twl.c b/drivers/rtc/rtc-twl.c index 20687d55e7a7..d43b4f6eb4e4 100644 --- a/drivers/rtc/rtc-twl.c +++ b/drivers/rtc/rtc-twl.c | |||
@@ -550,6 +550,11 @@ static int twl_rtc_resume(struct platform_device *pdev) | |||
550 | #define twl_rtc_resume NULL | 550 | #define twl_rtc_resume NULL |
551 | #endif | 551 | #endif |
552 | 552 | ||
553 | static const struct of_device_id twl_rtc_of_match[] = { | ||
554 | {.compatible = "ti,twl4030-rtc", }, | ||
555 | { }, | ||
556 | }; | ||
557 | MODULE_DEVICE_TABLE(of, twl_rtc_of_match); | ||
553 | MODULE_ALIAS("platform:twl_rtc"); | 558 | MODULE_ALIAS("platform:twl_rtc"); |
554 | 559 | ||
555 | static struct platform_driver twl4030rtc_driver = { | 560 | static struct platform_driver twl4030rtc_driver = { |
@@ -559,8 +564,9 @@ static struct platform_driver twl4030rtc_driver = { | |||
559 | .suspend = twl_rtc_suspend, | 564 | .suspend = twl_rtc_suspend, |
560 | .resume = twl_rtc_resume, | 565 | .resume = twl_rtc_resume, |
561 | .driver = { | 566 | .driver = { |
562 | .owner = THIS_MODULE, | 567 | .owner = THIS_MODULE, |
563 | .name = "twl_rtc", | 568 | .name = "twl_rtc", |
569 | .of_match_table = twl_rtc_of_match, | ||
564 | }, | 570 | }, |
565 | }; | 571 | }; |
566 | 572 | ||
diff --git a/drivers/rtc/rtc-v3020.c b/drivers/rtc/rtc-v3020.c index f71c3ce18036..bca5d677bc85 100644 --- a/drivers/rtc/rtc-v3020.c +++ b/drivers/rtc/rtc-v3020.c | |||
@@ -393,18 +393,7 @@ static struct platform_driver rtc_device_driver = { | |||
393 | }, | 393 | }, |
394 | }; | 394 | }; |
395 | 395 | ||
396 | static __init int v3020_init(void) | 396 | module_platform_driver(rtc_device_driver); |
397 | { | ||
398 | return platform_driver_register(&rtc_device_driver); | ||
399 | } | ||
400 | |||
401 | static __exit void v3020_exit(void) | ||
402 | { | ||
403 | platform_driver_unregister(&rtc_device_driver); | ||
404 | } | ||
405 | |||
406 | module_init(v3020_init); | ||
407 | module_exit(v3020_exit); | ||
408 | 397 | ||
409 | MODULE_DESCRIPTION("V3020 RTC"); | 398 | MODULE_DESCRIPTION("V3020 RTC"); |
410 | MODULE_AUTHOR("Raphael Assenat"); | 399 | MODULE_AUTHOR("Raphael Assenat"); |
diff --git a/drivers/rtc/rtc-vr41xx.c b/drivers/rtc/rtc-vr41xx.c index c5698cda366a..fcbfdda2993b 100644 --- a/drivers/rtc/rtc-vr41xx.c +++ b/drivers/rtc/rtc-vr41xx.c | |||
@@ -405,15 +405,4 @@ static struct platform_driver rtc_platform_driver = { | |||
405 | }, | 405 | }, |
406 | }; | 406 | }; |
407 | 407 | ||
408 | static int __init vr41xx_rtc_init(void) | 408 | module_platform_driver(rtc_platform_driver); |
409 | { | ||
410 | return platform_driver_register(&rtc_platform_driver); | ||
411 | } | ||
412 | |||
413 | static void __exit vr41xx_rtc_exit(void) | ||
414 | { | ||
415 | platform_driver_unregister(&rtc_platform_driver); | ||
416 | } | ||
417 | |||
418 | module_init(vr41xx_rtc_init); | ||
419 | module_exit(vr41xx_rtc_exit); | ||
diff --git a/drivers/rtc/rtc-vt8500.c b/drivers/rtc/rtc-vt8500.c index f93f412423c6..9e94fb147c26 100644 --- a/drivers/rtc/rtc-vt8500.c +++ b/drivers/rtc/rtc-vt8500.c | |||
@@ -311,17 +311,7 @@ static struct platform_driver vt8500_rtc_driver = { | |||
311 | }, | 311 | }, |
312 | }; | 312 | }; |
313 | 313 | ||
314 | static int __init vt8500_rtc_init(void) | 314 | module_platform_driver(vt8500_rtc_driver); |
315 | { | ||
316 | return platform_driver_register(&vt8500_rtc_driver); | ||
317 | } | ||
318 | module_init(vt8500_rtc_init); | ||
319 | |||
320 | static void __exit vt8500_rtc_exit(void) | ||
321 | { | ||
322 | platform_driver_unregister(&vt8500_rtc_driver); | ||
323 | } | ||
324 | module_exit(vt8500_rtc_exit); | ||
325 | 315 | ||
326 | MODULE_AUTHOR("Alexey Charkov <alchark@gmail.com>"); | 316 | MODULE_AUTHOR("Alexey Charkov <alchark@gmail.com>"); |
327 | MODULE_DESCRIPTION("VIA VT8500 SoC Realtime Clock Driver (RTC)"); | 317 | MODULE_DESCRIPTION("VIA VT8500 SoC Realtime Clock Driver (RTC)"); |
diff --git a/drivers/rtc/rtc-wm831x.c b/drivers/rtc/rtc-wm831x.c index bdc909bd56da..3b6e6a67e765 100644 --- a/drivers/rtc/rtc-wm831x.c +++ b/drivers/rtc/rtc-wm831x.c | |||
@@ -324,15 +324,6 @@ static irqreturn_t wm831x_alm_irq(int irq, void *data) | |||
324 | return IRQ_HANDLED; | 324 | return IRQ_HANDLED; |
325 | } | 325 | } |
326 | 326 | ||
327 | static irqreturn_t wm831x_per_irq(int irq, void *data) | ||
328 | { | ||
329 | struct wm831x_rtc *wm831x_rtc = data; | ||
330 | |||
331 | rtc_update_irq(wm831x_rtc->rtc, 1, RTC_IRQF | RTC_UF); | ||
332 | |||
333 | return IRQ_HANDLED; | ||
334 | } | ||
335 | |||
336 | static const struct rtc_class_ops wm831x_rtc_ops = { | 327 | static const struct rtc_class_ops wm831x_rtc_ops = { |
337 | .read_time = wm831x_rtc_readtime, | 328 | .read_time = wm831x_rtc_readtime, |
338 | .set_mmss = wm831x_rtc_set_mmss, | 329 | .set_mmss = wm831x_rtc_set_mmss, |
@@ -405,11 +396,10 @@ static int wm831x_rtc_probe(struct platform_device *pdev) | |||
405 | { | 396 | { |
406 | struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent); | 397 | struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent); |
407 | struct wm831x_rtc *wm831x_rtc; | 398 | struct wm831x_rtc *wm831x_rtc; |
408 | int per_irq = platform_get_irq_byname(pdev, "PER"); | ||
409 | int alm_irq = platform_get_irq_byname(pdev, "ALM"); | 399 | int alm_irq = platform_get_irq_byname(pdev, "ALM"); |
410 | int ret = 0; | 400 | int ret = 0; |
411 | 401 | ||
412 | wm831x_rtc = kzalloc(sizeof(*wm831x_rtc), GFP_KERNEL); | 402 | wm831x_rtc = devm_kzalloc(&pdev->dev, sizeof(*wm831x_rtc), GFP_KERNEL); |
413 | if (wm831x_rtc == NULL) | 403 | if (wm831x_rtc == NULL) |
414 | return -ENOMEM; | 404 | return -ENOMEM; |
415 | 405 | ||
@@ -433,14 +423,6 @@ static int wm831x_rtc_probe(struct platform_device *pdev) | |||
433 | goto err; | 423 | goto err; |
434 | } | 424 | } |
435 | 425 | ||
436 | ret = request_threaded_irq(per_irq, NULL, wm831x_per_irq, | ||
437 | IRQF_TRIGGER_RISING, "RTC period", | ||
438 | wm831x_rtc); | ||
439 | if (ret != 0) { | ||
440 | dev_err(&pdev->dev, "Failed to request periodic IRQ %d: %d\n", | ||
441 | per_irq, ret); | ||
442 | } | ||
443 | |||
444 | ret = request_threaded_irq(alm_irq, NULL, wm831x_alm_irq, | 426 | ret = request_threaded_irq(alm_irq, NULL, wm831x_alm_irq, |
445 | IRQF_TRIGGER_RISING, "RTC alarm", | 427 | IRQF_TRIGGER_RISING, "RTC alarm", |
446 | wm831x_rtc); | 428 | wm831x_rtc); |
@@ -452,20 +434,16 @@ static int wm831x_rtc_probe(struct platform_device *pdev) | |||
452 | return 0; | 434 | return 0; |
453 | 435 | ||
454 | err: | 436 | err: |
455 | kfree(wm831x_rtc); | ||
456 | return ret; | 437 | return ret; |
457 | } | 438 | } |
458 | 439 | ||
459 | static int __devexit wm831x_rtc_remove(struct platform_device *pdev) | 440 | static int __devexit wm831x_rtc_remove(struct platform_device *pdev) |
460 | { | 441 | { |
461 | struct wm831x_rtc *wm831x_rtc = platform_get_drvdata(pdev); | 442 | struct wm831x_rtc *wm831x_rtc = platform_get_drvdata(pdev); |
462 | int per_irq = platform_get_irq_byname(pdev, "PER"); | ||
463 | int alm_irq = platform_get_irq_byname(pdev, "ALM"); | 443 | int alm_irq = platform_get_irq_byname(pdev, "ALM"); |
464 | 444 | ||
465 | free_irq(alm_irq, wm831x_rtc); | 445 | free_irq(alm_irq, wm831x_rtc); |
466 | free_irq(per_irq, wm831x_rtc); | ||
467 | rtc_device_unregister(wm831x_rtc->rtc); | 446 | rtc_device_unregister(wm831x_rtc->rtc); |
468 | kfree(wm831x_rtc); | ||
469 | 447 | ||
470 | return 0; | 448 | return 0; |
471 | } | 449 | } |
@@ -490,17 +468,7 @@ static struct platform_driver wm831x_rtc_driver = { | |||
490 | }, | 468 | }, |
491 | }; | 469 | }; |
492 | 470 | ||
493 | static int __init wm831x_rtc_init(void) | 471 | module_platform_driver(wm831x_rtc_driver); |
494 | { | ||
495 | return platform_driver_register(&wm831x_rtc_driver); | ||
496 | } | ||
497 | module_init(wm831x_rtc_init); | ||
498 | |||
499 | static void __exit wm831x_rtc_exit(void) | ||
500 | { | ||
501 | platform_driver_unregister(&wm831x_rtc_driver); | ||
502 | } | ||
503 | module_exit(wm831x_rtc_exit); | ||
504 | 472 | ||
505 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); | 473 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); |
506 | MODULE_DESCRIPTION("RTC driver for the WM831x series PMICs"); | 474 | MODULE_DESCRIPTION("RTC driver for the WM831x series PMICs"); |
diff --git a/drivers/rtc/rtc-wm8350.c b/drivers/rtc/rtc-wm8350.c index 66421426e404..c2e52d15abb2 100644 --- a/drivers/rtc/rtc-wm8350.c +++ b/drivers/rtc/rtc-wm8350.c | |||
@@ -486,17 +486,7 @@ static struct platform_driver wm8350_rtc_driver = { | |||
486 | }, | 486 | }, |
487 | }; | 487 | }; |
488 | 488 | ||
489 | static int __init wm8350_rtc_init(void) | 489 | module_platform_driver(wm8350_rtc_driver); |
490 | { | ||
491 | return platform_driver_register(&wm8350_rtc_driver); | ||
492 | } | ||
493 | module_init(wm8350_rtc_init); | ||
494 | |||
495 | static void __exit wm8350_rtc_exit(void) | ||
496 | { | ||
497 | platform_driver_unregister(&wm8350_rtc_driver); | ||
498 | } | ||
499 | module_exit(wm8350_rtc_exit); | ||
500 | 490 | ||
501 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); | 491 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); |
502 | MODULE_DESCRIPTION("RTC driver for the WM8350"); | 492 | MODULE_DESCRIPTION("RTC driver for the WM8350"); |
diff --git a/drivers/video/backlight/88pm860x_bl.c b/drivers/video/backlight/88pm860x_bl.c index 1105fa1ed7f4..a1376dc73d71 100644 --- a/drivers/video/backlight/88pm860x_bl.c +++ b/drivers/video/backlight/88pm860x_bl.c | |||
@@ -270,17 +270,7 @@ static struct platform_driver pm860x_backlight_driver = { | |||
270 | .remove = pm860x_backlight_remove, | 270 | .remove = pm860x_backlight_remove, |
271 | }; | 271 | }; |
272 | 272 | ||
273 | static int __init pm860x_backlight_init(void) | 273 | module_platform_driver(pm860x_backlight_driver); |
274 | { | ||
275 | return platform_driver_register(&pm860x_backlight_driver); | ||
276 | } | ||
277 | module_init(pm860x_backlight_init); | ||
278 | |||
279 | static void __exit pm860x_backlight_exit(void) | ||
280 | { | ||
281 | platform_driver_unregister(&pm860x_backlight_driver); | ||
282 | } | ||
283 | module_exit(pm860x_backlight_exit); | ||
284 | 274 | ||
285 | MODULE_DESCRIPTION("Backlight Driver for Marvell Semiconductor 88PM8606"); | 275 | MODULE_DESCRIPTION("Backlight Driver for Marvell Semiconductor 88PM8606"); |
286 | MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>"); | 276 | MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>"); |
diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig index 278aeaa92505..681b36929fe4 100644 --- a/drivers/video/backlight/Kconfig +++ b/drivers/video/backlight/Kconfig | |||
@@ -280,14 +280,6 @@ config BACKLIGHT_WM831X | |||
280 | If you have a backlight driven by the ISINK and DCDC of a | 280 | If you have a backlight driven by the ISINK and DCDC of a |
281 | WM831x PMIC say y to enable the backlight driver for it. | 281 | WM831x PMIC say y to enable the backlight driver for it. |
282 | 282 | ||
283 | config BACKLIGHT_ADX | ||
284 | tristate "Avionic Design Xanthos Backlight Driver" | ||
285 | depends on ARCH_PXA_ADX | ||
286 | default y | ||
287 | help | ||
288 | Say Y to enable the backlight driver on Avionic Design Xanthos-based | ||
289 | boards. | ||
290 | |||
291 | config BACKLIGHT_ADP5520 | 283 | config BACKLIGHT_ADP5520 |
292 | tristate "Backlight Driver for ADP5520/ADP5501 using WLED" | 284 | tristate "Backlight Driver for ADP5520/ADP5501 using WLED" |
293 | depends on PMIC_ADP5520 | 285 | depends on PMIC_ADP5520 |
diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile index fdd1fc4b2770..af5cf654ec7c 100644 --- a/drivers/video/backlight/Makefile +++ b/drivers/video/backlight/Makefile | |||
@@ -32,7 +32,6 @@ obj-$(CONFIG_BACKLIGHT_APPLE) += apple_bl.o | |||
32 | obj-$(CONFIG_BACKLIGHT_TOSA) += tosa_bl.o | 32 | obj-$(CONFIG_BACKLIGHT_TOSA) += tosa_bl.o |
33 | obj-$(CONFIG_BACKLIGHT_SAHARA) += kb3886_bl.o | 33 | obj-$(CONFIG_BACKLIGHT_SAHARA) += kb3886_bl.o |
34 | obj-$(CONFIG_BACKLIGHT_WM831X) += wm831x_bl.o | 34 | obj-$(CONFIG_BACKLIGHT_WM831X) += wm831x_bl.o |
35 | obj-$(CONFIG_BACKLIGHT_ADX) += adx_bl.o | ||
36 | obj-$(CONFIG_BACKLIGHT_ADP5520) += adp5520_bl.o | 35 | obj-$(CONFIG_BACKLIGHT_ADP5520) += adp5520_bl.o |
37 | obj-$(CONFIG_BACKLIGHT_ADP8860) += adp8860_bl.o | 36 | obj-$(CONFIG_BACKLIGHT_ADP8860) += adp8860_bl.o |
38 | obj-$(CONFIG_BACKLIGHT_ADP8870) += adp8870_bl.o | 37 | obj-$(CONFIG_BACKLIGHT_ADP8870) += adp8870_bl.o |
diff --git a/drivers/video/backlight/adp5520_bl.c b/drivers/video/backlight/adp5520_bl.c index dfb763e9147f..2e630bf1164c 100644 --- a/drivers/video/backlight/adp5520_bl.c +++ b/drivers/video/backlight/adp5520_bl.c | |||
@@ -384,17 +384,7 @@ static struct platform_driver adp5520_bl_driver = { | |||
384 | .resume = adp5520_bl_resume, | 384 | .resume = adp5520_bl_resume, |
385 | }; | 385 | }; |
386 | 386 | ||
387 | static int __init adp5520_bl_init(void) | 387 | module_platform_driver(adp5520_bl_driver); |
388 | { | ||
389 | return platform_driver_register(&adp5520_bl_driver); | ||
390 | } | ||
391 | module_init(adp5520_bl_init); | ||
392 | |||
393 | static void __exit adp5520_bl_exit(void) | ||
394 | { | ||
395 | platform_driver_unregister(&adp5520_bl_driver); | ||
396 | } | ||
397 | module_exit(adp5520_bl_exit); | ||
398 | 388 | ||
399 | MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); | 389 | MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); |
400 | MODULE_DESCRIPTION("ADP5520(01) Backlight Driver"); | 390 | MODULE_DESCRIPTION("ADP5520(01) Backlight Driver"); |
diff --git a/drivers/video/backlight/adx_bl.c b/drivers/video/backlight/adx_bl.c deleted file mode 100644 index c861c41af442..000000000000 --- a/drivers/video/backlight/adx_bl.c +++ /dev/null | |||
@@ -1,182 +0,0 @@ | |||
1 | /* | ||
2 | * linux/drivers/video/backlight/adx.c | ||
3 | * | ||
4 | * Copyright (C) 2009 Avionic Design GmbH | ||
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 | * Written by Thierry Reding <thierry.reding@avionic-design.de> | ||
11 | */ | ||
12 | |||
13 | #include <linux/backlight.h> | ||
14 | #include <linux/fb.h> | ||
15 | #include <linux/gfp.h> | ||
16 | #include <linux/io.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/platform_device.h> | ||
19 | |||
20 | /* register definitions */ | ||
21 | #define ADX_BACKLIGHT_CONTROL 0x00 | ||
22 | #define ADX_BACKLIGHT_CONTROL_ENABLE (1 << 0) | ||
23 | #define ADX_BACKLIGHT_BRIGHTNESS 0x08 | ||
24 | #define ADX_BACKLIGHT_STATUS 0x10 | ||
25 | #define ADX_BACKLIGHT_ERROR 0x18 | ||
26 | |||
27 | struct adxbl { | ||
28 | void __iomem *base; | ||
29 | }; | ||
30 | |||
31 | static int adx_backlight_update_status(struct backlight_device *bldev) | ||
32 | { | ||
33 | struct adxbl *bl = bl_get_data(bldev); | ||
34 | u32 value; | ||
35 | |||
36 | value = bldev->props.brightness; | ||
37 | writel(value, bl->base + ADX_BACKLIGHT_BRIGHTNESS); | ||
38 | |||
39 | value = readl(bl->base + ADX_BACKLIGHT_CONTROL); | ||
40 | |||
41 | if (bldev->props.state & BL_CORE_FBBLANK) | ||
42 | value &= ~ADX_BACKLIGHT_CONTROL_ENABLE; | ||
43 | else | ||
44 | value |= ADX_BACKLIGHT_CONTROL_ENABLE; | ||
45 | |||
46 | writel(value, bl->base + ADX_BACKLIGHT_CONTROL); | ||
47 | |||
48 | return 0; | ||
49 | } | ||
50 | |||
51 | static int adx_backlight_get_brightness(struct backlight_device *bldev) | ||
52 | { | ||
53 | struct adxbl *bl = bl_get_data(bldev); | ||
54 | u32 brightness; | ||
55 | |||
56 | brightness = readl(bl->base + ADX_BACKLIGHT_BRIGHTNESS); | ||
57 | return brightness & 0xff; | ||
58 | } | ||
59 | |||
60 | static int adx_backlight_check_fb(struct backlight_device *bldev, struct fb_info *fb) | ||
61 | { | ||
62 | return 1; | ||
63 | } | ||
64 | |||
65 | static const struct backlight_ops adx_backlight_ops = { | ||
66 | .options = 0, | ||
67 | .update_status = adx_backlight_update_status, | ||
68 | .get_brightness = adx_backlight_get_brightness, | ||
69 | .check_fb = adx_backlight_check_fb, | ||
70 | }; | ||
71 | |||
72 | static int __devinit adx_backlight_probe(struct platform_device *pdev) | ||
73 | { | ||
74 | struct backlight_properties props; | ||
75 | struct backlight_device *bldev; | ||
76 | struct resource *res; | ||
77 | struct adxbl *bl; | ||
78 | int ret = 0; | ||
79 | |||
80 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
81 | if (!res) { | ||
82 | ret = -ENXIO; | ||
83 | goto out; | ||
84 | } | ||
85 | |||
86 | res = devm_request_mem_region(&pdev->dev, res->start, | ||
87 | resource_size(res), res->name); | ||
88 | if (!res) { | ||
89 | ret = -ENXIO; | ||
90 | goto out; | ||
91 | } | ||
92 | |||
93 | bl = devm_kzalloc(&pdev->dev, sizeof(*bl), GFP_KERNEL); | ||
94 | if (!bl) { | ||
95 | ret = -ENOMEM; | ||
96 | goto out; | ||
97 | } | ||
98 | |||
99 | bl->base = devm_ioremap_nocache(&pdev->dev, res->start, | ||
100 | resource_size(res)); | ||
101 | if (!bl->base) { | ||
102 | ret = -ENXIO; | ||
103 | goto out; | ||
104 | } | ||
105 | |||
106 | memset(&props, 0, sizeof(struct backlight_properties)); | ||
107 | props.type = BACKLIGHT_RAW; | ||
108 | props.max_brightness = 0xff; | ||
109 | bldev = backlight_device_register(dev_name(&pdev->dev), &pdev->dev, | ||
110 | bl, &adx_backlight_ops, &props); | ||
111 | if (IS_ERR(bldev)) { | ||
112 | ret = PTR_ERR(bldev); | ||
113 | goto out; | ||
114 | } | ||
115 | |||
116 | bldev->props.brightness = 0xff; | ||
117 | bldev->props.power = FB_BLANK_UNBLANK; | ||
118 | |||
119 | platform_set_drvdata(pdev, bldev); | ||
120 | |||
121 | out: | ||
122 | return ret; | ||
123 | } | ||
124 | |||
125 | static int __devexit adx_backlight_remove(struct platform_device *pdev) | ||
126 | { | ||
127 | struct backlight_device *bldev; | ||
128 | int ret = 0; | ||
129 | |||
130 | bldev = platform_get_drvdata(pdev); | ||
131 | bldev->props.power = FB_BLANK_UNBLANK; | ||
132 | bldev->props.brightness = 0xff; | ||
133 | backlight_update_status(bldev); | ||
134 | backlight_device_unregister(bldev); | ||
135 | platform_set_drvdata(pdev, NULL); | ||
136 | |||
137 | return ret; | ||
138 | } | ||
139 | |||
140 | #ifdef CONFIG_PM | ||
141 | static int adx_backlight_suspend(struct platform_device *pdev, | ||
142 | pm_message_t state) | ||
143 | { | ||
144 | return 0; | ||
145 | } | ||
146 | |||
147 | static int adx_backlight_resume(struct platform_device *pdev) | ||
148 | { | ||
149 | return 0; | ||
150 | } | ||
151 | #else | ||
152 | #define adx_backlight_suspend NULL | ||
153 | #define adx_backlight_resume NULL | ||
154 | #endif | ||
155 | |||
156 | static struct platform_driver adx_backlight_driver = { | ||
157 | .probe = adx_backlight_probe, | ||
158 | .remove = __devexit_p(adx_backlight_remove), | ||
159 | .suspend = adx_backlight_suspend, | ||
160 | .resume = adx_backlight_resume, | ||
161 | .driver = { | ||
162 | .name = "adx-backlight", | ||
163 | .owner = THIS_MODULE, | ||
164 | }, | ||
165 | }; | ||
166 | |||
167 | static int __init adx_backlight_init(void) | ||
168 | { | ||
169 | return platform_driver_register(&adx_backlight_driver); | ||
170 | } | ||
171 | |||
172 | static void __exit adx_backlight_exit(void) | ||
173 | { | ||
174 | platform_driver_unregister(&adx_backlight_driver); | ||
175 | } | ||
176 | |||
177 | module_init(adx_backlight_init); | ||
178 | module_exit(adx_backlight_exit); | ||
179 | |||
180 | MODULE_AUTHOR("Thierry Reding <thierry.reding@avionic-design.de>"); | ||
181 | MODULE_DESCRIPTION("Avionic Design Xanthos Backlight Driver"); | ||
182 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/video/backlight/backlight.c b/drivers/video/backlight/backlight.c index 7363c1b169e8..bf5b1ece7160 100644 --- a/drivers/video/backlight/backlight.c +++ b/drivers/video/backlight/backlight.c | |||
@@ -102,7 +102,7 @@ static void backlight_generate_event(struct backlight_device *bd, | |||
102 | } | 102 | } |
103 | 103 | ||
104 | static ssize_t backlight_show_power(struct device *dev, | 104 | static ssize_t backlight_show_power(struct device *dev, |
105 | struct device_attribute *attr,char *buf) | 105 | struct device_attribute *attr, char *buf) |
106 | { | 106 | { |
107 | struct backlight_device *bd = to_backlight_device(dev); | 107 | struct backlight_device *bd = to_backlight_device(dev); |
108 | 108 | ||
@@ -116,7 +116,7 @@ static ssize_t backlight_store_power(struct device *dev, | |||
116 | struct backlight_device *bd = to_backlight_device(dev); | 116 | struct backlight_device *bd = to_backlight_device(dev); |
117 | unsigned long power; | 117 | unsigned long power; |
118 | 118 | ||
119 | rc = strict_strtoul(buf, 0, &power); | 119 | rc = kstrtoul(buf, 0, &power); |
120 | if (rc) | 120 | if (rc) |
121 | return rc; | 121 | return rc; |
122 | 122 | ||
@@ -150,7 +150,7 @@ static ssize_t backlight_store_brightness(struct device *dev, | |||
150 | struct backlight_device *bd = to_backlight_device(dev); | 150 | struct backlight_device *bd = to_backlight_device(dev); |
151 | unsigned long brightness; | 151 | unsigned long brightness; |
152 | 152 | ||
153 | rc = strict_strtoul(buf, 0, &brightness); | 153 | rc = kstrtoul(buf, 0, &brightness); |
154 | if (rc) | 154 | if (rc) |
155 | return rc; | 155 | return rc; |
156 | 156 | ||
diff --git a/drivers/video/backlight/da903x_bl.c b/drivers/video/backlight/da903x_bl.c index d68f14bbb687..abb4a06268f1 100644 --- a/drivers/video/backlight/da903x_bl.c +++ b/drivers/video/backlight/da903x_bl.c | |||
@@ -199,17 +199,7 @@ static struct platform_driver da903x_backlight_driver = { | |||
199 | .remove = da903x_backlight_remove, | 199 | .remove = da903x_backlight_remove, |
200 | }; | 200 | }; |
201 | 201 | ||
202 | static int __init da903x_backlight_init(void) | 202 | module_platform_driver(da903x_backlight_driver); |
203 | { | ||
204 | return platform_driver_register(&da903x_backlight_driver); | ||
205 | } | ||
206 | module_init(da903x_backlight_init); | ||
207 | |||
208 | static void __exit da903x_backlight_exit(void) | ||
209 | { | ||
210 | platform_driver_unregister(&da903x_backlight_driver); | ||
211 | } | ||
212 | module_exit(da903x_backlight_exit); | ||
213 | 203 | ||
214 | MODULE_DESCRIPTION("Backlight Driver for Dialog Semiconductor DA9030/DA9034"); | 204 | MODULE_DESCRIPTION("Backlight Driver for Dialog Semiconductor DA9030/DA9034"); |
215 | MODULE_AUTHOR("Eric Miao <eric.miao@marvell.com>" | 205 | MODULE_AUTHOR("Eric Miao <eric.miao@marvell.com>" |
diff --git a/drivers/video/backlight/ep93xx_bl.c b/drivers/video/backlight/ep93xx_bl.c index c74a6f4baa12..b62b8b9063b5 100644 --- a/drivers/video/backlight/ep93xx_bl.c +++ b/drivers/video/backlight/ep93xx_bl.c | |||
@@ -13,7 +13,6 @@ | |||
13 | 13 | ||
14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
15 | #include <linux/platform_device.h> | 15 | #include <linux/platform_device.h> |
16 | #include <linux/module.h> | ||
17 | #include <linux/io.h> | 16 | #include <linux/io.h> |
18 | #include <linux/fb.h> | 17 | #include <linux/fb.h> |
19 | #include <linux/backlight.h> | 18 | #include <linux/backlight.h> |
@@ -144,17 +143,7 @@ static struct platform_driver ep93xxbl_driver = { | |||
144 | .resume = ep93xxbl_resume, | 143 | .resume = ep93xxbl_resume, |
145 | }; | 144 | }; |
146 | 145 | ||
147 | static int __init ep93xxbl_init(void) | 146 | module_platform_driver(ep93xxbl_driver); |
148 | { | ||
149 | return platform_driver_register(&ep93xxbl_driver); | ||
150 | } | ||
151 | module_init(ep93xxbl_init); | ||
152 | |||
153 | static void __exit ep93xxbl_exit(void) | ||
154 | { | ||
155 | platform_driver_unregister(&ep93xxbl_driver); | ||
156 | } | ||
157 | module_exit(ep93xxbl_exit); | ||
158 | 147 | ||
159 | MODULE_DESCRIPTION("EP93xx Backlight Driver"); | 148 | MODULE_DESCRIPTION("EP93xx Backlight Driver"); |
160 | MODULE_AUTHOR("H Hartley Sweeten <hsweeten@visionengravers.com>"); | 149 | MODULE_AUTHOR("H Hartley Sweeten <hsweeten@visionengravers.com>"); |
diff --git a/drivers/video/backlight/generic_bl.c b/drivers/video/backlight/generic_bl.c index adb191466d64..9ce6170c1860 100644 --- a/drivers/video/backlight/generic_bl.c +++ b/drivers/video/backlight/generic_bl.c | |||
@@ -132,18 +132,7 @@ static struct platform_driver genericbl_driver = { | |||
132 | }, | 132 | }, |
133 | }; | 133 | }; |
134 | 134 | ||
135 | static int __init genericbl_init(void) | 135 | module_platform_driver(genericbl_driver); |
136 | { | ||
137 | return platform_driver_register(&genericbl_driver); | ||
138 | } | ||
139 | |||
140 | static void __exit genericbl_exit(void) | ||
141 | { | ||
142 | platform_driver_unregister(&genericbl_driver); | ||
143 | } | ||
144 | |||
145 | module_init(genericbl_init); | ||
146 | module_exit(genericbl_exit); | ||
147 | 136 | ||
148 | MODULE_AUTHOR("Richard Purdie <rpurdie@rpsys.net>"); | 137 | MODULE_AUTHOR("Richard Purdie <rpurdie@rpsys.net>"); |
149 | MODULE_DESCRIPTION("Generic Backlight Driver"); | 138 | MODULE_DESCRIPTION("Generic Backlight Driver"); |
diff --git a/drivers/video/backlight/jornada720_bl.c b/drivers/video/backlight/jornada720_bl.c index de65d80159be..2f8af5d786ab 100644 --- a/drivers/video/backlight/jornada720_bl.c +++ b/drivers/video/backlight/jornada720_bl.c | |||
@@ -147,19 +147,8 @@ static struct platform_driver jornada_bl_driver = { | |||
147 | }, | 147 | }, |
148 | }; | 148 | }; |
149 | 149 | ||
150 | static int __init jornada_bl_init(void) | 150 | module_platform_driver(jornada_bl_driver); |
151 | { | ||
152 | return platform_driver_register(&jornada_bl_driver); | ||
153 | } | ||
154 | |||
155 | static void __exit jornada_bl_exit(void) | ||
156 | { | ||
157 | platform_driver_unregister(&jornada_bl_driver); | ||
158 | } | ||
159 | 151 | ||
160 | MODULE_AUTHOR("Kristoffer Ericson <kristoffer.ericson>"); | 152 | MODULE_AUTHOR("Kristoffer Ericson <kristoffer.ericson>"); |
161 | MODULE_DESCRIPTION("HP Jornada 710/720/728 Backlight driver"); | 153 | MODULE_DESCRIPTION("HP Jornada 710/720/728 Backlight driver"); |
162 | MODULE_LICENSE("GPL"); | 154 | MODULE_LICENSE("GPL"); |
163 | |||
164 | module_init(jornada_bl_init); | ||
165 | module_exit(jornada_bl_exit); | ||
diff --git a/drivers/video/backlight/jornada720_lcd.c b/drivers/video/backlight/jornada720_lcd.c index d2ff658b4144..22d231a17e3c 100644 --- a/drivers/video/backlight/jornada720_lcd.c +++ b/drivers/video/backlight/jornada720_lcd.c | |||
@@ -135,19 +135,8 @@ static struct platform_driver jornada_lcd_driver = { | |||
135 | }, | 135 | }, |
136 | }; | 136 | }; |
137 | 137 | ||
138 | static int __init jornada_lcd_init(void) | 138 | module_platform_driver(jornada_lcd_driver); |
139 | { | ||
140 | return platform_driver_register(&jornada_lcd_driver); | ||
141 | } | ||
142 | |||
143 | static void __exit jornada_lcd_exit(void) | ||
144 | { | ||
145 | platform_driver_unregister(&jornada_lcd_driver); | ||
146 | } | ||
147 | 139 | ||
148 | MODULE_AUTHOR("Kristoffer Ericson <kristoffer.ericson@gmail.com>"); | 140 | MODULE_AUTHOR("Kristoffer Ericson <kristoffer.ericson@gmail.com>"); |
149 | MODULE_DESCRIPTION("HP Jornada 710/720/728 LCD driver"); | 141 | MODULE_DESCRIPTION("HP Jornada 710/720/728 LCD driver"); |
150 | MODULE_LICENSE("GPL"); | 142 | MODULE_LICENSE("GPL"); |
151 | |||
152 | module_init(jornada_lcd_init); | ||
153 | module_exit(jornada_lcd_exit); | ||
diff --git a/drivers/video/backlight/lcd.c b/drivers/video/backlight/lcd.c index 71a11cadffc4..79c1b0d609a8 100644 --- a/drivers/video/backlight/lcd.c +++ b/drivers/video/backlight/lcd.c | |||
@@ -97,19 +97,16 @@ static ssize_t lcd_store_power(struct device *dev, | |||
97 | struct device_attribute *attr, const char *buf, size_t count) | 97 | struct device_attribute *attr, const char *buf, size_t count) |
98 | { | 98 | { |
99 | int rc = -ENXIO; | 99 | int rc = -ENXIO; |
100 | char *endp; | ||
101 | struct lcd_device *ld = to_lcd_device(dev); | 100 | struct lcd_device *ld = to_lcd_device(dev); |
102 | int power = simple_strtoul(buf, &endp, 0); | 101 | unsigned long power; |
103 | size_t size = endp - buf; | ||
104 | 102 | ||
105 | if (isspace(*endp)) | 103 | rc = kstrtoul(buf, 0, &power); |
106 | size++; | 104 | if (rc) |
107 | if (size != count) | 105 | return rc; |
108 | return -EINVAL; | ||
109 | 106 | ||
110 | mutex_lock(&ld->ops_lock); | 107 | mutex_lock(&ld->ops_lock); |
111 | if (ld->ops && ld->ops->set_power) { | 108 | if (ld->ops && ld->ops->set_power) { |
112 | pr_debug("lcd: set power to %d\n", power); | 109 | pr_debug("lcd: set power to %lu\n", power); |
113 | ld->ops->set_power(ld, power); | 110 | ld->ops->set_power(ld, power); |
114 | rc = count; | 111 | rc = count; |
115 | } | 112 | } |
@@ -136,19 +133,16 @@ static ssize_t lcd_store_contrast(struct device *dev, | |||
136 | struct device_attribute *attr, const char *buf, size_t count) | 133 | struct device_attribute *attr, const char *buf, size_t count) |
137 | { | 134 | { |
138 | int rc = -ENXIO; | 135 | int rc = -ENXIO; |
139 | char *endp; | ||
140 | struct lcd_device *ld = to_lcd_device(dev); | 136 | struct lcd_device *ld = to_lcd_device(dev); |
141 | int contrast = simple_strtoul(buf, &endp, 0); | 137 | unsigned long contrast; |
142 | size_t size = endp - buf; | ||
143 | 138 | ||
144 | if (isspace(*endp)) | 139 | rc = kstrtoul(buf, 0, &contrast); |
145 | size++; | 140 | if (rc) |
146 | if (size != count) | 141 | return rc; |
147 | return -EINVAL; | ||
148 | 142 | ||
149 | mutex_lock(&ld->ops_lock); | 143 | mutex_lock(&ld->ops_lock); |
150 | if (ld->ops && ld->ops->set_contrast) { | 144 | if (ld->ops && ld->ops->set_contrast) { |
151 | pr_debug("lcd: set contrast to %d\n", contrast); | 145 | pr_debug("lcd: set contrast to %lu\n", contrast); |
152 | ld->ops->set_contrast(ld, contrast); | 146 | ld->ops->set_contrast(ld, contrast); |
153 | rc = count; | 147 | rc = count; |
154 | } | 148 | } |
diff --git a/drivers/video/backlight/ld9040.c b/drivers/video/backlight/ld9040.c index da9a5ce0ccb8..78dafc0c8fc5 100644 --- a/drivers/video/backlight/ld9040.c +++ b/drivers/video/backlight/ld9040.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <linux/lcd.h> | 31 | #include <linux/lcd.h> |
32 | #include <linux/backlight.h> | 32 | #include <linux/backlight.h> |
33 | #include <linux/module.h> | 33 | #include <linux/module.h> |
34 | #include <linux/regulator/consumer.h> | ||
34 | 35 | ||
35 | #include "ld9040_gamma.h" | 36 | #include "ld9040_gamma.h" |
36 | 37 | ||
@@ -53,8 +54,51 @@ struct ld9040 { | |||
53 | struct lcd_device *ld; | 54 | struct lcd_device *ld; |
54 | struct backlight_device *bd; | 55 | struct backlight_device *bd; |
55 | struct lcd_platform_data *lcd_pd; | 56 | struct lcd_platform_data *lcd_pd; |
57 | |||
58 | struct mutex lock; | ||
59 | bool enabled; | ||
60 | }; | ||
61 | |||
62 | static struct regulator_bulk_data supplies[] = { | ||
63 | { .supply = "vdd3", }, | ||
64 | { .supply = "vci", }, | ||
56 | }; | 65 | }; |
57 | 66 | ||
67 | static void ld9040_regulator_enable(struct ld9040 *lcd) | ||
68 | { | ||
69 | int ret = 0; | ||
70 | struct lcd_platform_data *pd = NULL; | ||
71 | |||
72 | pd = lcd->lcd_pd; | ||
73 | mutex_lock(&lcd->lock); | ||
74 | if (!lcd->enabled) { | ||
75 | ret = regulator_bulk_enable(ARRAY_SIZE(supplies), supplies); | ||
76 | if (ret) | ||
77 | goto out; | ||
78 | |||
79 | lcd->enabled = true; | ||
80 | } | ||
81 | mdelay(pd->power_on_delay); | ||
82 | out: | ||
83 | mutex_unlock(&lcd->lock); | ||
84 | } | ||
85 | |||
86 | static void ld9040_regulator_disable(struct ld9040 *lcd) | ||
87 | { | ||
88 | int ret = 0; | ||
89 | |||
90 | mutex_lock(&lcd->lock); | ||
91 | if (lcd->enabled) { | ||
92 | ret = regulator_bulk_disable(ARRAY_SIZE(supplies), supplies); | ||
93 | if (ret) | ||
94 | goto out; | ||
95 | |||
96 | lcd->enabled = false; | ||
97 | } | ||
98 | out: | ||
99 | mutex_unlock(&lcd->lock); | ||
100 | } | ||
101 | |||
58 | static const unsigned short seq_swreset[] = { | 102 | static const unsigned short seq_swreset[] = { |
59 | 0x01, COMMAND_ONLY, | 103 | 0x01, COMMAND_ONLY, |
60 | ENDDEF, 0x00 | 104 | ENDDEF, 0x00 |
@@ -532,13 +576,8 @@ static int ld9040_power_on(struct ld9040 *lcd) | |||
532 | return -EFAULT; | 576 | return -EFAULT; |
533 | } | 577 | } |
534 | 578 | ||
535 | if (!pd->power_on) { | 579 | /* lcd power on */ |
536 | dev_err(lcd->dev, "power_on is NULL.\n"); | 580 | ld9040_regulator_enable(lcd); |
537 | return -EFAULT; | ||
538 | } else { | ||
539 | pd->power_on(lcd->ld, 1); | ||
540 | mdelay(pd->power_on_delay); | ||
541 | } | ||
542 | 581 | ||
543 | if (!pd->reset) { | 582 | if (!pd->reset) { |
544 | dev_err(lcd->dev, "reset is NULL.\n"); | 583 | dev_err(lcd->dev, "reset is NULL.\n"); |
@@ -582,11 +621,8 @@ static int ld9040_power_off(struct ld9040 *lcd) | |||
582 | 621 | ||
583 | mdelay(pd->power_off_delay); | 622 | mdelay(pd->power_off_delay); |
584 | 623 | ||
585 | if (!pd->power_on) { | 624 | /* lcd power off */ |
586 | dev_err(lcd->dev, "power_on is NULL.\n"); | 625 | ld9040_regulator_disable(lcd); |
587 | return -EFAULT; | ||
588 | } else | ||
589 | pd->power_on(lcd->ld, 0); | ||
590 | 626 | ||
591 | return 0; | 627 | return 0; |
592 | } | 628 | } |
@@ -693,6 +729,14 @@ static int ld9040_probe(struct spi_device *spi) | |||
693 | goto out_free_lcd; | 729 | goto out_free_lcd; |
694 | } | 730 | } |
695 | 731 | ||
732 | mutex_init(&lcd->lock); | ||
733 | |||
734 | ret = regulator_bulk_get(lcd->dev, ARRAY_SIZE(supplies), supplies); | ||
735 | if (ret) { | ||
736 | dev_err(lcd->dev, "Failed to get regulators: %d\n", ret); | ||
737 | goto out_free_lcd; | ||
738 | } | ||
739 | |||
696 | ld = lcd_device_register("ld9040", &spi->dev, lcd, &ld9040_lcd_ops); | 740 | ld = lcd_device_register("ld9040", &spi->dev, lcd, &ld9040_lcd_ops); |
697 | if (IS_ERR(ld)) { | 741 | if (IS_ERR(ld)) { |
698 | ret = PTR_ERR(ld); | 742 | ret = PTR_ERR(ld); |
@@ -739,6 +783,8 @@ static int ld9040_probe(struct spi_device *spi) | |||
739 | out_unregister_lcd: | 783 | out_unregister_lcd: |
740 | lcd_device_unregister(lcd->ld); | 784 | lcd_device_unregister(lcd->ld); |
741 | out_free_lcd: | 785 | out_free_lcd: |
786 | regulator_bulk_free(ARRAY_SIZE(supplies), supplies); | ||
787 | |||
742 | kfree(lcd); | 788 | kfree(lcd); |
743 | return ret; | 789 | return ret; |
744 | } | 790 | } |
@@ -750,6 +796,7 @@ static int __devexit ld9040_remove(struct spi_device *spi) | |||
750 | ld9040_power(lcd, FB_BLANK_POWERDOWN); | 796 | ld9040_power(lcd, FB_BLANK_POWERDOWN); |
751 | backlight_device_unregister(lcd->bd); | 797 | backlight_device_unregister(lcd->bd); |
752 | lcd_device_unregister(lcd->ld); | 798 | lcd_device_unregister(lcd->ld); |
799 | regulator_bulk_free(ARRAY_SIZE(supplies), supplies); | ||
753 | kfree(lcd); | 800 | kfree(lcd); |
754 | 801 | ||
755 | return 0; | 802 | return 0; |
diff --git a/drivers/video/backlight/max8925_bl.c b/drivers/video/backlight/max8925_bl.c index 7bbc802560ea..c915e3b53886 100644 --- a/drivers/video/backlight/max8925_bl.c +++ b/drivers/video/backlight/max8925_bl.c | |||
@@ -188,17 +188,7 @@ static struct platform_driver max8925_backlight_driver = { | |||
188 | .remove = __devexit_p(max8925_backlight_remove), | 188 | .remove = __devexit_p(max8925_backlight_remove), |
189 | }; | 189 | }; |
190 | 190 | ||
191 | static int __init max8925_backlight_init(void) | 191 | module_platform_driver(max8925_backlight_driver); |
192 | { | ||
193 | return platform_driver_register(&max8925_backlight_driver); | ||
194 | } | ||
195 | module_init(max8925_backlight_init); | ||
196 | |||
197 | static void __exit max8925_backlight_exit(void) | ||
198 | { | ||
199 | platform_driver_unregister(&max8925_backlight_driver); | ||
200 | }; | ||
201 | module_exit(max8925_backlight_exit); | ||
202 | 192 | ||
203 | MODULE_DESCRIPTION("Backlight Driver for Maxim MAX8925"); | 193 | MODULE_DESCRIPTION("Backlight Driver for Maxim MAX8925"); |
204 | MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>"); | 194 | MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>"); |
diff --git a/drivers/video/backlight/omap1_bl.c b/drivers/video/backlight/omap1_bl.c index 08d26a72394c..d8cde277ec83 100644 --- a/drivers/video/backlight/omap1_bl.c +++ b/drivers/video/backlight/omap1_bl.c | |||
@@ -195,18 +195,7 @@ static struct platform_driver omapbl_driver = { | |||
195 | }, | 195 | }, |
196 | }; | 196 | }; |
197 | 197 | ||
198 | static int __init omapbl_init(void) | 198 | module_platform_driver(omapbl_driver); |
199 | { | ||
200 | return platform_driver_register(&omapbl_driver); | ||
201 | } | ||
202 | |||
203 | static void __exit omapbl_exit(void) | ||
204 | { | ||
205 | platform_driver_unregister(&omapbl_driver); | ||
206 | } | ||
207 | |||
208 | module_init(omapbl_init); | ||
209 | module_exit(omapbl_exit); | ||
210 | 199 | ||
211 | MODULE_AUTHOR("Andrzej Zaborowski <balrog@zabor.org>"); | 200 | MODULE_AUTHOR("Andrzej Zaborowski <balrog@zabor.org>"); |
212 | MODULE_DESCRIPTION("OMAP LCD Backlight driver"); | 201 | MODULE_DESCRIPTION("OMAP LCD Backlight driver"); |
diff --git a/drivers/video/backlight/pcf50633-backlight.c b/drivers/video/backlight/pcf50633-backlight.c index ef5628d60563..13e88b71daec 100644 --- a/drivers/video/backlight/pcf50633-backlight.c +++ b/drivers/video/backlight/pcf50633-backlight.c | |||
@@ -173,17 +173,7 @@ static struct platform_driver pcf50633_bl_driver = { | |||
173 | }, | 173 | }, |
174 | }; | 174 | }; |
175 | 175 | ||
176 | static int __init pcf50633_bl_init(void) | 176 | module_platform_driver(pcf50633_bl_driver); |
177 | { | ||
178 | return platform_driver_register(&pcf50633_bl_driver); | ||
179 | } | ||
180 | module_init(pcf50633_bl_init); | ||
181 | |||
182 | static void __exit pcf50633_bl_exit(void) | ||
183 | { | ||
184 | platform_driver_unregister(&pcf50633_bl_driver); | ||
185 | } | ||
186 | module_exit(pcf50633_bl_exit); | ||
187 | 177 | ||
188 | MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); | 178 | MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); |
189 | MODULE_DESCRIPTION("PCF50633 backlight driver"); | 179 | MODULE_DESCRIPTION("PCF50633 backlight driver"); |
diff --git a/drivers/video/backlight/platform_lcd.c b/drivers/video/backlight/platform_lcd.c index 302330acf628..f0bf491ed087 100644 --- a/drivers/video/backlight/platform_lcd.c +++ b/drivers/video/backlight/platform_lcd.c | |||
@@ -85,7 +85,8 @@ static int __devinit platform_lcd_probe(struct platform_device *pdev) | |||
85 | return -EINVAL; | 85 | return -EINVAL; |
86 | } | 86 | } |
87 | 87 | ||
88 | plcd = kzalloc(sizeof(struct platform_lcd), GFP_KERNEL); | 88 | plcd = devm_kzalloc(&pdev->dev, sizeof(struct platform_lcd), |
89 | GFP_KERNEL); | ||
89 | if (!plcd) { | 90 | if (!plcd) { |
90 | dev_err(dev, "no memory for state\n"); | 91 | dev_err(dev, "no memory for state\n"); |
91 | return -ENOMEM; | 92 | return -ENOMEM; |
@@ -98,7 +99,7 @@ static int __devinit platform_lcd_probe(struct platform_device *pdev) | |||
98 | if (IS_ERR(plcd->lcd)) { | 99 | if (IS_ERR(plcd->lcd)) { |
99 | dev_err(dev, "cannot register lcd device\n"); | 100 | dev_err(dev, "cannot register lcd device\n"); |
100 | err = PTR_ERR(plcd->lcd); | 101 | err = PTR_ERR(plcd->lcd); |
101 | goto err_mem; | 102 | goto err; |
102 | } | 103 | } |
103 | 104 | ||
104 | platform_set_drvdata(pdev, plcd); | 105 | platform_set_drvdata(pdev, plcd); |
@@ -106,8 +107,7 @@ static int __devinit platform_lcd_probe(struct platform_device *pdev) | |||
106 | 107 | ||
107 | return 0; | 108 | return 0; |
108 | 109 | ||
109 | err_mem: | 110 | err: |
110 | kfree(plcd); | ||
111 | return err; | 111 | return err; |
112 | } | 112 | } |
113 | 113 | ||
@@ -116,7 +116,6 @@ static int __devexit platform_lcd_remove(struct platform_device *pdev) | |||
116 | struct platform_lcd *plcd = platform_get_drvdata(pdev); | 116 | struct platform_lcd *plcd = platform_get_drvdata(pdev); |
117 | 117 | ||
118 | lcd_device_unregister(plcd->lcd); | 118 | lcd_device_unregister(plcd->lcd); |
119 | kfree(plcd); | ||
120 | 119 | ||
121 | return 0; | 120 | return 0; |
122 | } | 121 | } |
@@ -157,18 +156,7 @@ static struct platform_driver platform_lcd_driver = { | |||
157 | .resume = platform_lcd_resume, | 156 | .resume = platform_lcd_resume, |
158 | }; | 157 | }; |
159 | 158 | ||
160 | static int __init platform_lcd_init(void) | 159 | module_platform_driver(platform_lcd_driver); |
161 | { | ||
162 | return platform_driver_register(&platform_lcd_driver); | ||
163 | } | ||
164 | |||
165 | static void __exit platform_lcd_cleanup(void) | ||
166 | { | ||
167 | platform_driver_unregister(&platform_lcd_driver); | ||
168 | } | ||
169 | |||
170 | module_init(platform_lcd_init); | ||
171 | module_exit(platform_lcd_cleanup); | ||
172 | 160 | ||
173 | MODULE_AUTHOR("Ben Dooks <ben-linux@fluff.org>"); | 161 | MODULE_AUTHOR("Ben Dooks <ben-linux@fluff.org>"); |
174 | MODULE_LICENSE("GPL v2"); | 162 | MODULE_LICENSE("GPL v2"); |
diff --git a/drivers/video/backlight/pwm_bl.c b/drivers/video/backlight/pwm_bl.c index 8b5b2a4124c7..7496d04e1d3c 100644 --- a/drivers/video/backlight/pwm_bl.c +++ b/drivers/video/backlight/pwm_bl.c | |||
@@ -169,10 +169,9 @@ static int pwm_backlight_remove(struct platform_device *pdev) | |||
169 | } | 169 | } |
170 | 170 | ||
171 | #ifdef CONFIG_PM | 171 | #ifdef CONFIG_PM |
172 | static int pwm_backlight_suspend(struct platform_device *pdev, | 172 | static int pwm_backlight_suspend(struct device *dev) |
173 | pm_message_t state) | ||
174 | { | 173 | { |
175 | struct backlight_device *bl = platform_get_drvdata(pdev); | 174 | struct backlight_device *bl = dev_get_drvdata(dev); |
176 | struct pwm_bl_data *pb = dev_get_drvdata(&bl->dev); | 175 | struct pwm_bl_data *pb = dev_get_drvdata(&bl->dev); |
177 | 176 | ||
178 | if (pb->notify) | 177 | if (pb->notify) |
@@ -184,40 +183,32 @@ static int pwm_backlight_suspend(struct platform_device *pdev, | |||
184 | return 0; | 183 | return 0; |
185 | } | 184 | } |
186 | 185 | ||
187 | static int pwm_backlight_resume(struct platform_device *pdev) | 186 | static int pwm_backlight_resume(struct device *dev) |
188 | { | 187 | { |
189 | struct backlight_device *bl = platform_get_drvdata(pdev); | 188 | struct backlight_device *bl = dev_get_drvdata(dev); |
190 | 189 | ||
191 | backlight_update_status(bl); | 190 | backlight_update_status(bl); |
192 | return 0; | 191 | return 0; |
193 | } | 192 | } |
194 | #else | 193 | |
195 | #define pwm_backlight_suspend NULL | 194 | static SIMPLE_DEV_PM_OPS(pwm_backlight_pm_ops, pwm_backlight_suspend, |
196 | #define pwm_backlight_resume NULL | 195 | pwm_backlight_resume); |
196 | |||
197 | #endif | 197 | #endif |
198 | 198 | ||
199 | static struct platform_driver pwm_backlight_driver = { | 199 | static struct platform_driver pwm_backlight_driver = { |
200 | .driver = { | 200 | .driver = { |
201 | .name = "pwm-backlight", | 201 | .name = "pwm-backlight", |
202 | .owner = THIS_MODULE, | 202 | .owner = THIS_MODULE, |
203 | #ifdef CONFIG_PM | ||
204 | .pm = &pwm_backlight_pm_ops, | ||
205 | #endif | ||
203 | }, | 206 | }, |
204 | .probe = pwm_backlight_probe, | 207 | .probe = pwm_backlight_probe, |
205 | .remove = pwm_backlight_remove, | 208 | .remove = pwm_backlight_remove, |
206 | .suspend = pwm_backlight_suspend, | ||
207 | .resume = pwm_backlight_resume, | ||
208 | }; | 209 | }; |
209 | 210 | ||
210 | static int __init pwm_backlight_init(void) | 211 | module_platform_driver(pwm_backlight_driver); |
211 | { | ||
212 | return platform_driver_register(&pwm_backlight_driver); | ||
213 | } | ||
214 | module_init(pwm_backlight_init); | ||
215 | |||
216 | static void __exit pwm_backlight_exit(void) | ||
217 | { | ||
218 | platform_driver_unregister(&pwm_backlight_driver); | ||
219 | } | ||
220 | module_exit(pwm_backlight_exit); | ||
221 | 212 | ||
222 | MODULE_DESCRIPTION("PWM based Backlight Driver"); | 213 | MODULE_DESCRIPTION("PWM based Backlight Driver"); |
223 | MODULE_LICENSE("GPL"); | 214 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/video/backlight/wm831x_bl.c b/drivers/video/backlight/wm831x_bl.c index fbe9e9316f3b..4e915f5eca99 100644 --- a/drivers/video/backlight/wm831x_bl.c +++ b/drivers/video/backlight/wm831x_bl.c | |||
@@ -236,17 +236,7 @@ static struct platform_driver wm831x_backlight_driver = { | |||
236 | .remove = wm831x_backlight_remove, | 236 | .remove = wm831x_backlight_remove, |
237 | }; | 237 | }; |
238 | 238 | ||
239 | static int __init wm831x_backlight_init(void) | 239 | module_platform_driver(wm831x_backlight_driver); |
240 | { | ||
241 | return platform_driver_register(&wm831x_backlight_driver); | ||
242 | } | ||
243 | module_init(wm831x_backlight_init); | ||
244 | |||
245 | static void __exit wm831x_backlight_exit(void) | ||
246 | { | ||
247 | platform_driver_unregister(&wm831x_backlight_driver); | ||
248 | } | ||
249 | module_exit(wm831x_backlight_exit); | ||
250 | 240 | ||
251 | MODULE_DESCRIPTION("Backlight Driver for WM831x PMICs"); | 241 | MODULE_DESCRIPTION("Backlight Driver for WM831x PMICs"); |
252 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com"); | 242 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com"); |
diff --git a/fs/Kconfig.binfmt b/fs/Kconfig.binfmt index 79e2ca7973b7..e95d1b64082c 100644 --- a/fs/Kconfig.binfmt +++ b/fs/Kconfig.binfmt | |||
@@ -27,6 +27,9 @@ config COMPAT_BINFMT_ELF | |||
27 | bool | 27 | bool |
28 | depends on COMPAT && BINFMT_ELF | 28 | depends on COMPAT && BINFMT_ELF |
29 | 29 | ||
30 | config ARCH_BINFMT_ELF_RANDOMIZE_PIE | ||
31 | bool | ||
32 | |||
30 | config BINFMT_ELF_FDPIC | 33 | config BINFMT_ELF_FDPIC |
31 | bool "Kernel support for FDPIC ELF binaries" | 34 | bool "Kernel support for FDPIC ELF binaries" |
32 | default y | 35 | default y |
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index 21ac5ee4b43f..bcb884e2d613 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c | |||
@@ -794,7 +794,7 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs) | |||
794 | * default mmap base, as well as whatever program they | 794 | * default mmap base, as well as whatever program they |
795 | * might try to exec. This is because the brk will | 795 | * might try to exec. This is because the brk will |
796 | * follow the loader, and is not movable. */ | 796 | * follow the loader, and is not movable. */ |
797 | #if defined(CONFIG_X86) || defined(CONFIG_ARM) | 797 | #ifdef CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE |
798 | /* Memory randomization might have been switched off | 798 | /* Memory randomization might have been switched off |
799 | * in runtime via sysctl. | 799 | * in runtime via sysctl. |
800 | * If that is the case, retain the original non-zero | 800 | * If that is the case, retain the original non-zero |
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index 97fbe939c050..20375e6691c3 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c | |||
@@ -1081,7 +1081,7 @@ static noinline int prepare_pages(struct btrfs_root *root, struct file *file, | |||
1081 | again: | 1081 | again: |
1082 | for (i = 0; i < num_pages; i++) { | 1082 | for (i = 0; i < num_pages; i++) { |
1083 | pages[i] = find_or_create_page(inode->i_mapping, index + i, | 1083 | pages[i] = find_or_create_page(inode->i_mapping, index + i, |
1084 | mask); | 1084 | mask | __GFP_WRITE); |
1085 | if (!pages[i]) { | 1085 | if (!pages[i]) { |
1086 | faili = i - 1; | 1086 | faili = i - 1; |
1087 | err = -ENOMEM; | 1087 | err = -ENOMEM; |
@@ -59,6 +59,8 @@ | |||
59 | #include <asm/uaccess.h> | 59 | #include <asm/uaccess.h> |
60 | #include <asm/mmu_context.h> | 60 | #include <asm/mmu_context.h> |
61 | #include <asm/tlb.h> | 61 | #include <asm/tlb.h> |
62 | |||
63 | #include <trace/events/task.h> | ||
62 | #include "internal.h" | 64 | #include "internal.h" |
63 | 65 | ||
64 | int core_uses_pid; | 66 | int core_uses_pid; |
@@ -1054,6 +1056,8 @@ void set_task_comm(struct task_struct *tsk, char *buf) | |||
1054 | { | 1056 | { |
1055 | task_lock(tsk); | 1057 | task_lock(tsk); |
1056 | 1058 | ||
1059 | trace_task_rename(tsk, buf); | ||
1060 | |||
1057 | /* | 1061 | /* |
1058 | * Threads may access current->comm without holding | 1062 | * Threads may access current->comm without holding |
1059 | * the task lock, so write the string carefully. | 1063 | * the task lock, so write the string carefully. |
diff --git a/fs/inode.c b/fs/inode.c index 87535753ab04..4fa4f0916af9 100644 --- a/fs/inode.c +++ b/fs/inode.c | |||
@@ -776,6 +776,8 @@ void prune_icache_sb(struct super_block *sb, int nr_to_scan) | |||
776 | else | 776 | else |
777 | __count_vm_events(PGINODESTEAL, reap); | 777 | __count_vm_events(PGINODESTEAL, reap); |
778 | spin_unlock(&sb->s_inode_lru_lock); | 778 | spin_unlock(&sb->s_inode_lru_lock); |
779 | if (current->reclaim_state) | ||
780 | current->reclaim_state->reclaimed_slab += reap; | ||
779 | 781 | ||
780 | dispose_list(&freeable); | 782 | dispose_list(&freeable); |
781 | } | 783 | } |
diff --git a/fs/proc/base.c b/fs/proc/base.c index a1dddda999f2..8173dfd89cb2 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
@@ -83,9 +83,11 @@ | |||
83 | #include <linux/pid_namespace.h> | 83 | #include <linux/pid_namespace.h> |
84 | #include <linux/fs_struct.h> | 84 | #include <linux/fs_struct.h> |
85 | #include <linux/slab.h> | 85 | #include <linux/slab.h> |
86 | #include <linux/flex_array.h> | ||
86 | #ifdef CONFIG_HARDWALL | 87 | #ifdef CONFIG_HARDWALL |
87 | #include <asm/hardwall.h> | 88 | #include <asm/hardwall.h> |
88 | #endif | 89 | #endif |
90 | #include <trace/events/oom.h> | ||
89 | #include "internal.h" | 91 | #include "internal.h" |
90 | 92 | ||
91 | /* NOTE: | 93 | /* NOTE: |
@@ -133,6 +135,8 @@ struct pid_entry { | |||
133 | NULL, &proc_single_file_operations, \ | 135 | NULL, &proc_single_file_operations, \ |
134 | { .proc_show = show } ) | 136 | { .proc_show = show } ) |
135 | 137 | ||
138 | static int proc_fd_permission(struct inode *inode, int mask); | ||
139 | |||
136 | /* | 140 | /* |
137 | * Count the number of hardlinks for the pid_entry table, excluding the . | 141 | * Count the number of hardlinks for the pid_entry table, excluding the . |
138 | * and .. links. | 142 | * and .. links. |
@@ -165,9 +169,9 @@ static int get_task_root(struct task_struct *task, struct path *root) | |||
165 | return result; | 169 | return result; |
166 | } | 170 | } |
167 | 171 | ||
168 | static int proc_cwd_link(struct inode *inode, struct path *path) | 172 | static int proc_cwd_link(struct dentry *dentry, struct path *path) |
169 | { | 173 | { |
170 | struct task_struct *task = get_proc_task(inode); | 174 | struct task_struct *task = get_proc_task(dentry->d_inode); |
171 | int result = -ENOENT; | 175 | int result = -ENOENT; |
172 | 176 | ||
173 | if (task) { | 177 | if (task) { |
@@ -182,9 +186,9 @@ static int proc_cwd_link(struct inode *inode, struct path *path) | |||
182 | return result; | 186 | return result; |
183 | } | 187 | } |
184 | 188 | ||
185 | static int proc_root_link(struct inode *inode, struct path *path) | 189 | static int proc_root_link(struct dentry *dentry, struct path *path) |
186 | { | 190 | { |
187 | struct task_struct *task = get_proc_task(inode); | 191 | struct task_struct *task = get_proc_task(dentry->d_inode); |
188 | int result = -ENOENT; | 192 | int result = -ENOENT; |
189 | 193 | ||
190 | if (task) { | 194 | if (task) { |
@@ -627,6 +631,50 @@ int proc_setattr(struct dentry *dentry, struct iattr *attr) | |||
627 | return 0; | 631 | return 0; |
628 | } | 632 | } |
629 | 633 | ||
634 | /* | ||
635 | * May current process learn task's sched/cmdline info (for hide_pid_min=1) | ||
636 | * or euid/egid (for hide_pid_min=2)? | ||
637 | */ | ||
638 | static bool has_pid_permissions(struct pid_namespace *pid, | ||
639 | struct task_struct *task, | ||
640 | int hide_pid_min) | ||
641 | { | ||
642 | if (pid->hide_pid < hide_pid_min) | ||
643 | return true; | ||
644 | if (in_group_p(pid->pid_gid)) | ||
645 | return true; | ||
646 | return ptrace_may_access(task, PTRACE_MODE_READ); | ||
647 | } | ||
648 | |||
649 | |||
650 | static int proc_pid_permission(struct inode *inode, int mask) | ||
651 | { | ||
652 | struct pid_namespace *pid = inode->i_sb->s_fs_info; | ||
653 | struct task_struct *task; | ||
654 | bool has_perms; | ||
655 | |||
656 | task = get_proc_task(inode); | ||
657 | has_perms = has_pid_permissions(pid, task, 1); | ||
658 | put_task_struct(task); | ||
659 | |||
660 | if (!has_perms) { | ||
661 | if (pid->hide_pid == 2) { | ||
662 | /* | ||
663 | * Let's make getdents(), stat(), and open() | ||
664 | * consistent with each other. If a process | ||
665 | * may not stat() a file, it shouldn't be seen | ||
666 | * in procfs at all. | ||
667 | */ | ||
668 | return -ENOENT; | ||
669 | } | ||
670 | |||
671 | return -EPERM; | ||
672 | } | ||
673 | return generic_permission(inode, mask); | ||
674 | } | ||
675 | |||
676 | |||
677 | |||
630 | static const struct inode_operations proc_def_inode_operations = { | 678 | static const struct inode_operations proc_def_inode_operations = { |
631 | .setattr = proc_setattr, | 679 | .setattr = proc_setattr, |
632 | }; | 680 | }; |
@@ -1010,6 +1058,7 @@ static ssize_t oom_adjust_write(struct file *file, const char __user *buf, | |||
1010 | else | 1058 | else |
1011 | task->signal->oom_score_adj = (oom_adjust * OOM_SCORE_ADJ_MAX) / | 1059 | task->signal->oom_score_adj = (oom_adjust * OOM_SCORE_ADJ_MAX) / |
1012 | -OOM_DISABLE; | 1060 | -OOM_DISABLE; |
1061 | trace_oom_score_adj_update(task); | ||
1013 | err_sighand: | 1062 | err_sighand: |
1014 | unlock_task_sighand(task, &flags); | 1063 | unlock_task_sighand(task, &flags); |
1015 | err_task_lock: | 1064 | err_task_lock: |
@@ -1097,6 +1146,7 @@ static ssize_t oom_score_adj_write(struct file *file, const char __user *buf, | |||
1097 | task->signal->oom_score_adj = oom_score_adj; | 1146 | task->signal->oom_score_adj = oom_score_adj; |
1098 | if (has_capability_noaudit(current, CAP_SYS_RESOURCE)) | 1147 | if (has_capability_noaudit(current, CAP_SYS_RESOURCE)) |
1099 | task->signal->oom_score_adj_min = oom_score_adj; | 1148 | task->signal->oom_score_adj_min = oom_score_adj; |
1149 | trace_oom_score_adj_update(task); | ||
1100 | /* | 1150 | /* |
1101 | * Scale /proc/pid/oom_adj appropriately ensuring that OOM_DISABLE is | 1151 | * Scale /proc/pid/oom_adj appropriately ensuring that OOM_DISABLE is |
1102 | * always attainable. | 1152 | * always attainable. |
@@ -1453,13 +1503,13 @@ static const struct file_operations proc_pid_set_comm_operations = { | |||
1453 | .release = single_release, | 1503 | .release = single_release, |
1454 | }; | 1504 | }; |
1455 | 1505 | ||
1456 | static int proc_exe_link(struct inode *inode, struct path *exe_path) | 1506 | static int proc_exe_link(struct dentry *dentry, struct path *exe_path) |
1457 | { | 1507 | { |
1458 | struct task_struct *task; | 1508 | struct task_struct *task; |
1459 | struct mm_struct *mm; | 1509 | struct mm_struct *mm; |
1460 | struct file *exe_file; | 1510 | struct file *exe_file; |
1461 | 1511 | ||
1462 | task = get_proc_task(inode); | 1512 | task = get_proc_task(dentry->d_inode); |
1463 | if (!task) | 1513 | if (!task) |
1464 | return -ENOENT; | 1514 | return -ENOENT; |
1465 | mm = get_task_mm(task); | 1515 | mm = get_task_mm(task); |
@@ -1489,7 +1539,7 @@ static void *proc_pid_follow_link(struct dentry *dentry, struct nameidata *nd) | |||
1489 | if (!proc_fd_access_allowed(inode)) | 1539 | if (!proc_fd_access_allowed(inode)) |
1490 | goto out; | 1540 | goto out; |
1491 | 1541 | ||
1492 | error = PROC_I(inode)->op.proc_get_link(inode, &nd->path); | 1542 | error = PROC_I(inode)->op.proc_get_link(dentry, &nd->path); |
1493 | out: | 1543 | out: |
1494 | return ERR_PTR(error); | 1544 | return ERR_PTR(error); |
1495 | } | 1545 | } |
@@ -1528,7 +1578,7 @@ static int proc_pid_readlink(struct dentry * dentry, char __user * buffer, int b | |||
1528 | if (!proc_fd_access_allowed(inode)) | 1578 | if (!proc_fd_access_allowed(inode)) |
1529 | goto out; | 1579 | goto out; |
1530 | 1580 | ||
1531 | error = PROC_I(inode)->op.proc_get_link(inode, &path); | 1581 | error = PROC_I(inode)->op.proc_get_link(dentry, &path); |
1532 | if (error) | 1582 | if (error) |
1533 | goto out; | 1583 | goto out; |
1534 | 1584 | ||
@@ -1609,6 +1659,7 @@ int pid_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) | |||
1609 | struct inode *inode = dentry->d_inode; | 1659 | struct inode *inode = dentry->d_inode; |
1610 | struct task_struct *task; | 1660 | struct task_struct *task; |
1611 | const struct cred *cred; | 1661 | const struct cred *cred; |
1662 | struct pid_namespace *pid = dentry->d_sb->s_fs_info; | ||
1612 | 1663 | ||
1613 | generic_fillattr(inode, stat); | 1664 | generic_fillattr(inode, stat); |
1614 | 1665 | ||
@@ -1617,6 +1668,14 @@ int pid_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) | |||
1617 | stat->gid = 0; | 1668 | stat->gid = 0; |
1618 | task = pid_task(proc_pid(inode), PIDTYPE_PID); | 1669 | task = pid_task(proc_pid(inode), PIDTYPE_PID); |
1619 | if (task) { | 1670 | if (task) { |
1671 | if (!has_pid_permissions(pid, task, 2)) { | ||
1672 | rcu_read_unlock(); | ||
1673 | /* | ||
1674 | * This doesn't prevent learning whether PID exists, | ||
1675 | * it only makes getattr() consistent with readdir(). | ||
1676 | */ | ||
1677 | return -ENOENT; | ||
1678 | } | ||
1620 | if ((inode->i_mode == (S_IFDIR|S_IRUGO|S_IXUGO)) || | 1679 | if ((inode->i_mode == (S_IFDIR|S_IRUGO|S_IXUGO)) || |
1621 | task_dumpable(task)) { | 1680 | task_dumpable(task)) { |
1622 | cred = __task_cred(task); | 1681 | cred = __task_cred(task); |
@@ -1820,9 +1879,9 @@ static int proc_fd_info(struct inode *inode, struct path *path, char *info) | |||
1820 | return -ENOENT; | 1879 | return -ENOENT; |
1821 | } | 1880 | } |
1822 | 1881 | ||
1823 | static int proc_fd_link(struct inode *inode, struct path *path) | 1882 | static int proc_fd_link(struct dentry *dentry, struct path *path) |
1824 | { | 1883 | { |
1825 | return proc_fd_info(inode, path, NULL); | 1884 | return proc_fd_info(dentry->d_inode, path, NULL); |
1826 | } | 1885 | } |
1827 | 1886 | ||
1828 | static int tid_fd_revalidate(struct dentry *dentry, struct nameidata *nd) | 1887 | static int tid_fd_revalidate(struct dentry *dentry, struct nameidata *nd) |
@@ -2043,6 +2102,355 @@ static const struct file_operations proc_fd_operations = { | |||
2043 | .llseek = default_llseek, | 2102 | .llseek = default_llseek, |
2044 | }; | 2103 | }; |
2045 | 2104 | ||
2105 | #ifdef CONFIG_CHECKPOINT_RESTORE | ||
2106 | |||
2107 | /* | ||
2108 | * dname_to_vma_addr - maps a dentry name into two unsigned longs | ||
2109 | * which represent vma start and end addresses. | ||
2110 | */ | ||
2111 | static int dname_to_vma_addr(struct dentry *dentry, | ||
2112 | unsigned long *start, unsigned long *end) | ||
2113 | { | ||
2114 | if (sscanf(dentry->d_name.name, "%lx-%lx", start, end) != 2) | ||
2115 | return -EINVAL; | ||
2116 | |||
2117 | return 0; | ||
2118 | } | ||
2119 | |||
2120 | static int map_files_d_revalidate(struct dentry *dentry, struct nameidata *nd) | ||
2121 | { | ||
2122 | unsigned long vm_start, vm_end; | ||
2123 | bool exact_vma_exists = false; | ||
2124 | struct mm_struct *mm = NULL; | ||
2125 | struct task_struct *task; | ||
2126 | const struct cred *cred; | ||
2127 | struct inode *inode; | ||
2128 | int status = 0; | ||
2129 | |||
2130 | if (nd && nd->flags & LOOKUP_RCU) | ||
2131 | return -ECHILD; | ||
2132 | |||
2133 | if (!capable(CAP_SYS_ADMIN)) { | ||
2134 | status = -EACCES; | ||
2135 | goto out_notask; | ||
2136 | } | ||
2137 | |||
2138 | inode = dentry->d_inode; | ||
2139 | task = get_proc_task(inode); | ||
2140 | if (!task) | ||
2141 | goto out_notask; | ||
2142 | |||
2143 | if (!ptrace_may_access(task, PTRACE_MODE_READ)) | ||
2144 | goto out; | ||
2145 | |||
2146 | mm = get_task_mm(task); | ||
2147 | if (!mm) | ||
2148 | goto out; | ||
2149 | |||
2150 | if (!dname_to_vma_addr(dentry, &vm_start, &vm_end)) { | ||
2151 | down_read(&mm->mmap_sem); | ||
2152 | exact_vma_exists = !!find_exact_vma(mm, vm_start, vm_end); | ||
2153 | up_read(&mm->mmap_sem); | ||
2154 | } | ||
2155 | |||
2156 | mmput(mm); | ||
2157 | |||
2158 | if (exact_vma_exists) { | ||
2159 | if (task_dumpable(task)) { | ||
2160 | rcu_read_lock(); | ||
2161 | cred = __task_cred(task); | ||
2162 | inode->i_uid = cred->euid; | ||
2163 | inode->i_gid = cred->egid; | ||
2164 | rcu_read_unlock(); | ||
2165 | } else { | ||
2166 | inode->i_uid = 0; | ||
2167 | inode->i_gid = 0; | ||
2168 | } | ||
2169 | security_task_to_inode(task, inode); | ||
2170 | status = 1; | ||
2171 | } | ||
2172 | |||
2173 | out: | ||
2174 | put_task_struct(task); | ||
2175 | |||
2176 | out_notask: | ||
2177 | if (status <= 0) | ||
2178 | d_drop(dentry); | ||
2179 | |||
2180 | return status; | ||
2181 | } | ||
2182 | |||
2183 | static const struct dentry_operations tid_map_files_dentry_operations = { | ||
2184 | .d_revalidate = map_files_d_revalidate, | ||
2185 | .d_delete = pid_delete_dentry, | ||
2186 | }; | ||
2187 | |||
2188 | static int proc_map_files_get_link(struct dentry *dentry, struct path *path) | ||
2189 | { | ||
2190 | unsigned long vm_start, vm_end; | ||
2191 | struct vm_area_struct *vma; | ||
2192 | struct task_struct *task; | ||
2193 | struct mm_struct *mm; | ||
2194 | int rc; | ||
2195 | |||
2196 | rc = -ENOENT; | ||
2197 | task = get_proc_task(dentry->d_inode); | ||
2198 | if (!task) | ||
2199 | goto out; | ||
2200 | |||
2201 | mm = get_task_mm(task); | ||
2202 | put_task_struct(task); | ||
2203 | if (!mm) | ||
2204 | goto out; | ||
2205 | |||
2206 | rc = dname_to_vma_addr(dentry, &vm_start, &vm_end); | ||
2207 | if (rc) | ||
2208 | goto out_mmput; | ||
2209 | |||
2210 | down_read(&mm->mmap_sem); | ||
2211 | vma = find_exact_vma(mm, vm_start, vm_end); | ||
2212 | if (vma && vma->vm_file) { | ||
2213 | *path = vma->vm_file->f_path; | ||
2214 | path_get(path); | ||
2215 | rc = 0; | ||
2216 | } | ||
2217 | up_read(&mm->mmap_sem); | ||
2218 | |||
2219 | out_mmput: | ||
2220 | mmput(mm); | ||
2221 | out: | ||
2222 | return rc; | ||
2223 | } | ||
2224 | |||
2225 | struct map_files_info { | ||
2226 | struct file *file; | ||
2227 | unsigned long len; | ||
2228 | unsigned char name[4*sizeof(long)+2]; /* max: %lx-%lx\0 */ | ||
2229 | }; | ||
2230 | |||
2231 | static struct dentry * | ||
2232 | proc_map_files_instantiate(struct inode *dir, struct dentry *dentry, | ||
2233 | struct task_struct *task, const void *ptr) | ||
2234 | { | ||
2235 | const struct file *file = ptr; | ||
2236 | struct proc_inode *ei; | ||
2237 | struct inode *inode; | ||
2238 | |||
2239 | if (!file) | ||
2240 | return ERR_PTR(-ENOENT); | ||
2241 | |||
2242 | inode = proc_pid_make_inode(dir->i_sb, task); | ||
2243 | if (!inode) | ||
2244 | return ERR_PTR(-ENOENT); | ||
2245 | |||
2246 | ei = PROC_I(inode); | ||
2247 | ei->op.proc_get_link = proc_map_files_get_link; | ||
2248 | |||
2249 | inode->i_op = &proc_pid_link_inode_operations; | ||
2250 | inode->i_size = 64; | ||
2251 | inode->i_mode = S_IFLNK; | ||
2252 | |||
2253 | if (file->f_mode & FMODE_READ) | ||
2254 | inode->i_mode |= S_IRUSR; | ||
2255 | if (file->f_mode & FMODE_WRITE) | ||
2256 | inode->i_mode |= S_IWUSR; | ||
2257 | |||
2258 | d_set_d_op(dentry, &tid_map_files_dentry_operations); | ||
2259 | d_add(dentry, inode); | ||
2260 | |||
2261 | return NULL; | ||
2262 | } | ||
2263 | |||
2264 | static struct dentry *proc_map_files_lookup(struct inode *dir, | ||
2265 | struct dentry *dentry, struct nameidata *nd) | ||
2266 | { | ||
2267 | unsigned long vm_start, vm_end; | ||
2268 | struct vm_area_struct *vma; | ||
2269 | struct task_struct *task; | ||
2270 | struct dentry *result; | ||
2271 | struct mm_struct *mm; | ||
2272 | |||
2273 | result = ERR_PTR(-EACCES); | ||
2274 | if (!capable(CAP_SYS_ADMIN)) | ||
2275 | goto out; | ||
2276 | |||
2277 | result = ERR_PTR(-ENOENT); | ||
2278 | task = get_proc_task(dir); | ||
2279 | if (!task) | ||
2280 | goto out; | ||
2281 | |||
2282 | result = ERR_PTR(-EACCES); | ||
2283 | if (lock_trace(task)) | ||
2284 | goto out_put_task; | ||
2285 | |||
2286 | result = ERR_PTR(-ENOENT); | ||
2287 | if (dname_to_vma_addr(dentry, &vm_start, &vm_end)) | ||
2288 | goto out_unlock; | ||
2289 | |||
2290 | mm = get_task_mm(task); | ||
2291 | if (!mm) | ||
2292 | goto out_unlock; | ||
2293 | |||
2294 | down_read(&mm->mmap_sem); | ||
2295 | vma = find_exact_vma(mm, vm_start, vm_end); | ||
2296 | if (!vma) | ||
2297 | goto out_no_vma; | ||
2298 | |||
2299 | result = proc_map_files_instantiate(dir, dentry, task, vma->vm_file); | ||
2300 | |||
2301 | out_no_vma: | ||
2302 | up_read(&mm->mmap_sem); | ||
2303 | mmput(mm); | ||
2304 | out_unlock: | ||
2305 | unlock_trace(task); | ||
2306 | out_put_task: | ||
2307 | put_task_struct(task); | ||
2308 | out: | ||
2309 | return result; | ||
2310 | } | ||
2311 | |||
2312 | static const struct inode_operations proc_map_files_inode_operations = { | ||
2313 | .lookup = proc_map_files_lookup, | ||
2314 | .permission = proc_fd_permission, | ||
2315 | .setattr = proc_setattr, | ||
2316 | }; | ||
2317 | |||
2318 | static int | ||
2319 | proc_map_files_readdir(struct file *filp, void *dirent, filldir_t filldir) | ||
2320 | { | ||
2321 | struct dentry *dentry = filp->f_path.dentry; | ||
2322 | struct inode *inode = dentry->d_inode; | ||
2323 | struct vm_area_struct *vma; | ||
2324 | struct task_struct *task; | ||
2325 | struct mm_struct *mm; | ||
2326 | ino_t ino; | ||
2327 | int ret; | ||
2328 | |||
2329 | ret = -EACCES; | ||
2330 | if (!capable(CAP_SYS_ADMIN)) | ||
2331 | goto out; | ||
2332 | |||
2333 | ret = -ENOENT; | ||
2334 | task = get_proc_task(inode); | ||
2335 | if (!task) | ||
2336 | goto out; | ||
2337 | |||
2338 | ret = -EACCES; | ||
2339 | if (lock_trace(task)) | ||
2340 | goto out_put_task; | ||
2341 | |||
2342 | ret = 0; | ||
2343 | switch (filp->f_pos) { | ||
2344 | case 0: | ||
2345 | ino = inode->i_ino; | ||
2346 | if (filldir(dirent, ".", 1, 0, ino, DT_DIR) < 0) | ||
2347 | goto out_unlock; | ||
2348 | filp->f_pos++; | ||
2349 | case 1: | ||
2350 | ino = parent_ino(dentry); | ||
2351 | if (filldir(dirent, "..", 2, 1, ino, DT_DIR) < 0) | ||
2352 | goto out_unlock; | ||
2353 | filp->f_pos++; | ||
2354 | default: | ||
2355 | { | ||
2356 | unsigned long nr_files, pos, i; | ||
2357 | struct flex_array *fa = NULL; | ||
2358 | struct map_files_info info; | ||
2359 | struct map_files_info *p; | ||
2360 | |||
2361 | mm = get_task_mm(task); | ||
2362 | if (!mm) | ||
2363 | goto out_unlock; | ||
2364 | down_read(&mm->mmap_sem); | ||
2365 | |||
2366 | nr_files = 0; | ||
2367 | |||
2368 | /* | ||
2369 | * We need two passes here: | ||
2370 | * | ||
2371 | * 1) Collect vmas of mapped files with mmap_sem taken | ||
2372 | * 2) Release mmap_sem and instantiate entries | ||
2373 | * | ||
2374 | * otherwise we get lockdep complained, since filldir() | ||
2375 | * routine might require mmap_sem taken in might_fault(). | ||
2376 | */ | ||
2377 | |||
2378 | for (vma = mm->mmap, pos = 2; vma; vma = vma->vm_next) { | ||
2379 | if (vma->vm_file && ++pos > filp->f_pos) | ||
2380 | nr_files++; | ||
2381 | } | ||
2382 | |||
2383 | if (nr_files) { | ||
2384 | fa = flex_array_alloc(sizeof(info), nr_files, | ||
2385 | GFP_KERNEL); | ||
2386 | if (!fa || flex_array_prealloc(fa, 0, nr_files, | ||
2387 | GFP_KERNEL)) { | ||
2388 | ret = -ENOMEM; | ||
2389 | if (fa) | ||
2390 | flex_array_free(fa); | ||
2391 | up_read(&mm->mmap_sem); | ||
2392 | mmput(mm); | ||
2393 | goto out_unlock; | ||
2394 | } | ||
2395 | for (i = 0, vma = mm->mmap, pos = 2; vma; | ||
2396 | vma = vma->vm_next) { | ||
2397 | if (!vma->vm_file) | ||
2398 | continue; | ||
2399 | if (++pos <= filp->f_pos) | ||
2400 | continue; | ||
2401 | |||
2402 | get_file(vma->vm_file); | ||
2403 | info.file = vma->vm_file; | ||
2404 | info.len = snprintf(info.name, | ||
2405 | sizeof(info.name), "%lx-%lx", | ||
2406 | vma->vm_start, vma->vm_end); | ||
2407 | if (flex_array_put(fa, i++, &info, GFP_KERNEL)) | ||
2408 | BUG(); | ||
2409 | } | ||
2410 | } | ||
2411 | up_read(&mm->mmap_sem); | ||
2412 | |||
2413 | for (i = 0; i < nr_files; i++) { | ||
2414 | p = flex_array_get(fa, i); | ||
2415 | ret = proc_fill_cache(filp, dirent, filldir, | ||
2416 | p->name, p->len, | ||
2417 | proc_map_files_instantiate, | ||
2418 | task, p->file); | ||
2419 | if (ret) | ||
2420 | break; | ||
2421 | filp->f_pos++; | ||
2422 | fput(p->file); | ||
2423 | } | ||
2424 | for (; i < nr_files; i++) { | ||
2425 | /* | ||
2426 | * In case of error don't forget | ||
2427 | * to put rest of file refs. | ||
2428 | */ | ||
2429 | p = flex_array_get(fa, i); | ||
2430 | fput(p->file); | ||
2431 | } | ||
2432 | if (fa) | ||
2433 | flex_array_free(fa); | ||
2434 | mmput(mm); | ||
2435 | } | ||
2436 | } | ||
2437 | |||
2438 | out_unlock: | ||
2439 | unlock_trace(task); | ||
2440 | out_put_task: | ||
2441 | put_task_struct(task); | ||
2442 | out: | ||
2443 | return ret; | ||
2444 | } | ||
2445 | |||
2446 | static const struct file_operations proc_map_files_operations = { | ||
2447 | .read = generic_read_dir, | ||
2448 | .readdir = proc_map_files_readdir, | ||
2449 | .llseek = default_llseek, | ||
2450 | }; | ||
2451 | |||
2452 | #endif /* CONFIG_CHECKPOINT_RESTORE */ | ||
2453 | |||
2046 | /* | 2454 | /* |
2047 | * /proc/pid/fd needs a special permission handler so that a process can still | 2455 | * /proc/pid/fd needs a special permission handler so that a process can still |
2048 | * access /proc/self/fd after it has executed a setuid(). | 2456 | * access /proc/self/fd after it has executed a setuid(). |
@@ -2658,6 +3066,9 @@ static const struct inode_operations proc_task_inode_operations; | |||
2658 | static const struct pid_entry tgid_base_stuff[] = { | 3066 | static const struct pid_entry tgid_base_stuff[] = { |
2659 | DIR("task", S_IRUGO|S_IXUGO, proc_task_inode_operations, proc_task_operations), | 3067 | DIR("task", S_IRUGO|S_IXUGO, proc_task_inode_operations, proc_task_operations), |
2660 | DIR("fd", S_IRUSR|S_IXUSR, proc_fd_inode_operations, proc_fd_operations), | 3068 | DIR("fd", S_IRUSR|S_IXUSR, proc_fd_inode_operations, proc_fd_operations), |
3069 | #ifdef CONFIG_CHECKPOINT_RESTORE | ||
3070 | DIR("map_files", S_IRUSR|S_IXUSR, proc_map_files_inode_operations, proc_map_files_operations), | ||
3071 | #endif | ||
2661 | DIR("fdinfo", S_IRUSR|S_IXUSR, proc_fdinfo_inode_operations, proc_fdinfo_operations), | 3072 | DIR("fdinfo", S_IRUSR|S_IXUSR, proc_fdinfo_inode_operations, proc_fdinfo_operations), |
2662 | DIR("ns", S_IRUSR|S_IXUGO, proc_ns_dir_inode_operations, proc_ns_dir_operations), | 3073 | DIR("ns", S_IRUSR|S_IXUGO, proc_ns_dir_inode_operations, proc_ns_dir_operations), |
2663 | #ifdef CONFIG_NET | 3074 | #ifdef CONFIG_NET |
@@ -2761,6 +3172,7 @@ static const struct inode_operations proc_tgid_base_inode_operations = { | |||
2761 | .lookup = proc_tgid_base_lookup, | 3172 | .lookup = proc_tgid_base_lookup, |
2762 | .getattr = pid_getattr, | 3173 | .getattr = pid_getattr, |
2763 | .setattr = proc_setattr, | 3174 | .setattr = proc_setattr, |
3175 | .permission = proc_pid_permission, | ||
2764 | }; | 3176 | }; |
2765 | 3177 | ||
2766 | static void proc_flush_task_mnt(struct vfsmount *mnt, pid_t pid, pid_t tgid) | 3178 | static void proc_flush_task_mnt(struct vfsmount *mnt, pid_t pid, pid_t tgid) |
@@ -2964,6 +3376,12 @@ static int proc_pid_fill_cache(struct file *filp, void *dirent, filldir_t filldi | |||
2964 | proc_pid_instantiate, iter.task, NULL); | 3376 | proc_pid_instantiate, iter.task, NULL); |
2965 | } | 3377 | } |
2966 | 3378 | ||
3379 | static int fake_filldir(void *buf, const char *name, int namelen, | ||
3380 | loff_t offset, u64 ino, unsigned d_type) | ||
3381 | { | ||
3382 | return 0; | ||
3383 | } | ||
3384 | |||
2967 | /* for the /proc/ directory itself, after non-process stuff has been done */ | 3385 | /* for the /proc/ directory itself, after non-process stuff has been done */ |
2968 | int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir) | 3386 | int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir) |
2969 | { | 3387 | { |
@@ -2971,6 +3389,7 @@ int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir) | |||
2971 | struct task_struct *reaper; | 3389 | struct task_struct *reaper; |
2972 | struct tgid_iter iter; | 3390 | struct tgid_iter iter; |
2973 | struct pid_namespace *ns; | 3391 | struct pid_namespace *ns; |
3392 | filldir_t __filldir; | ||
2974 | 3393 | ||
2975 | if (filp->f_pos >= PID_MAX_LIMIT + TGID_OFFSET) | 3394 | if (filp->f_pos >= PID_MAX_LIMIT + TGID_OFFSET) |
2976 | goto out_no_task; | 3395 | goto out_no_task; |
@@ -2992,8 +3411,13 @@ int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir) | |||
2992 | for (iter = next_tgid(ns, iter); | 3411 | for (iter = next_tgid(ns, iter); |
2993 | iter.task; | 3412 | iter.task; |
2994 | iter.tgid += 1, iter = next_tgid(ns, iter)) { | 3413 | iter.tgid += 1, iter = next_tgid(ns, iter)) { |
3414 | if (has_pid_permissions(ns, iter.task, 2)) | ||
3415 | __filldir = filldir; | ||
3416 | else | ||
3417 | __filldir = fake_filldir; | ||
3418 | |||
2995 | filp->f_pos = iter.tgid + TGID_OFFSET; | 3419 | filp->f_pos = iter.tgid + TGID_OFFSET; |
2996 | if (proc_pid_fill_cache(filp, dirent, filldir, iter) < 0) { | 3420 | if (proc_pid_fill_cache(filp, dirent, __filldir, iter) < 0) { |
2997 | put_task_struct(iter.task); | 3421 | put_task_struct(iter.task); |
2998 | goto out; | 3422 | goto out; |
2999 | } | 3423 | } |
@@ -3328,6 +3752,7 @@ static const struct inode_operations proc_task_inode_operations = { | |||
3328 | .lookup = proc_task_lookup, | 3752 | .lookup = proc_task_lookup, |
3329 | .getattr = proc_task_getattr, | 3753 | .getattr = proc_task_getattr, |
3330 | .setattr = proc_setattr, | 3754 | .setattr = proc_setattr, |
3755 | .permission = proc_pid_permission, | ||
3331 | }; | 3756 | }; |
3332 | 3757 | ||
3333 | static const struct file_operations proc_task_operations = { | 3758 | static const struct file_operations proc_task_operations = { |
diff --git a/fs/proc/inode.c b/fs/proc/inode.c index 51a176622b8f..84fd3235a590 100644 --- a/fs/proc/inode.c +++ b/fs/proc/inode.c | |||
@@ -7,6 +7,7 @@ | |||
7 | #include <linux/time.h> | 7 | #include <linux/time.h> |
8 | #include <linux/proc_fs.h> | 8 | #include <linux/proc_fs.h> |
9 | #include <linux/kernel.h> | 9 | #include <linux/kernel.h> |
10 | #include <linux/pid_namespace.h> | ||
10 | #include <linux/mm.h> | 11 | #include <linux/mm.h> |
11 | #include <linux/string.h> | 12 | #include <linux/string.h> |
12 | #include <linux/stat.h> | 13 | #include <linux/stat.h> |
@@ -17,7 +18,9 @@ | |||
17 | #include <linux/init.h> | 18 | #include <linux/init.h> |
18 | #include <linux/module.h> | 19 | #include <linux/module.h> |
19 | #include <linux/sysctl.h> | 20 | #include <linux/sysctl.h> |
21 | #include <linux/seq_file.h> | ||
20 | #include <linux/slab.h> | 22 | #include <linux/slab.h> |
23 | #include <linux/mount.h> | ||
21 | 24 | ||
22 | #include <asm/system.h> | 25 | #include <asm/system.h> |
23 | #include <asm/uaccess.h> | 26 | #include <asm/uaccess.h> |
@@ -101,12 +104,27 @@ void __init proc_init_inodecache(void) | |||
101 | init_once); | 104 | init_once); |
102 | } | 105 | } |
103 | 106 | ||
107 | static int proc_show_options(struct seq_file *seq, struct dentry *root) | ||
108 | { | ||
109 | struct super_block *sb = root->d_sb; | ||
110 | struct pid_namespace *pid = sb->s_fs_info; | ||
111 | |||
112 | if (pid->pid_gid) | ||
113 | seq_printf(seq, ",gid=%lu", (unsigned long)pid->pid_gid); | ||
114 | if (pid->hide_pid != 0) | ||
115 | seq_printf(seq, ",hidepid=%u", pid->hide_pid); | ||
116 | |||
117 | return 0; | ||
118 | } | ||
119 | |||
104 | static const struct super_operations proc_sops = { | 120 | static const struct super_operations proc_sops = { |
105 | .alloc_inode = proc_alloc_inode, | 121 | .alloc_inode = proc_alloc_inode, |
106 | .destroy_inode = proc_destroy_inode, | 122 | .destroy_inode = proc_destroy_inode, |
107 | .drop_inode = generic_delete_inode, | 123 | .drop_inode = generic_delete_inode, |
108 | .evict_inode = proc_evict_inode, | 124 | .evict_inode = proc_evict_inode, |
109 | .statfs = simple_statfs, | 125 | .statfs = simple_statfs, |
126 | .remount_fs = proc_remount, | ||
127 | .show_options = proc_show_options, | ||
110 | }; | 128 | }; |
111 | 129 | ||
112 | static void __pde_users_dec(struct proc_dir_entry *pde) | 130 | static void __pde_users_dec(struct proc_dir_entry *pde) |
diff --git a/fs/proc/internal.h b/fs/proc/internal.h index 7838e5cfec14..292577531ad1 100644 --- a/fs/proc/internal.h +++ b/fs/proc/internal.h | |||
@@ -117,6 +117,7 @@ void pde_put(struct proc_dir_entry *pde); | |||
117 | 117 | ||
118 | int proc_fill_super(struct super_block *); | 118 | int proc_fill_super(struct super_block *); |
119 | struct inode *proc_get_inode(struct super_block *, struct proc_dir_entry *); | 119 | struct inode *proc_get_inode(struct super_block *, struct proc_dir_entry *); |
120 | int proc_remount(struct super_block *sb, int *flags, char *data); | ||
120 | 121 | ||
121 | /* | 122 | /* |
122 | * These are generic /proc routines that use the internal | 123 | * These are generic /proc routines that use the internal |
diff --git a/fs/proc/root.c b/fs/proc/root.c index 03102d978180..46a15d8a29ca 100644 --- a/fs/proc/root.c +++ b/fs/proc/root.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/bitops.h> | 18 | #include <linux/bitops.h> |
19 | #include <linux/mount.h> | 19 | #include <linux/mount.h> |
20 | #include <linux/pid_namespace.h> | 20 | #include <linux/pid_namespace.h> |
21 | #include <linux/parser.h> | ||
21 | 22 | ||
22 | #include "internal.h" | 23 | #include "internal.h" |
23 | 24 | ||
@@ -36,6 +37,63 @@ static int proc_set_super(struct super_block *sb, void *data) | |||
36 | return err; | 37 | return err; |
37 | } | 38 | } |
38 | 39 | ||
40 | enum { | ||
41 | Opt_gid, Opt_hidepid, Opt_err, | ||
42 | }; | ||
43 | |||
44 | static const match_table_t tokens = { | ||
45 | {Opt_hidepid, "hidepid=%u"}, | ||
46 | {Opt_gid, "gid=%u"}, | ||
47 | {Opt_err, NULL}, | ||
48 | }; | ||
49 | |||
50 | static int proc_parse_options(char *options, struct pid_namespace *pid) | ||
51 | { | ||
52 | char *p; | ||
53 | substring_t args[MAX_OPT_ARGS]; | ||
54 | int option; | ||
55 | |||
56 | if (!options) | ||
57 | return 1; | ||
58 | |||
59 | while ((p = strsep(&options, ",")) != NULL) { | ||
60 | int token; | ||
61 | if (!*p) | ||
62 | continue; | ||
63 | |||
64 | args[0].to = args[0].from = 0; | ||
65 | token = match_token(p, tokens, args); | ||
66 | switch (token) { | ||
67 | case Opt_gid: | ||
68 | if (match_int(&args[0], &option)) | ||
69 | return 0; | ||
70 | pid->pid_gid = option; | ||
71 | break; | ||
72 | case Opt_hidepid: | ||
73 | if (match_int(&args[0], &option)) | ||
74 | return 0; | ||
75 | if (option < 0 || option > 2) { | ||
76 | pr_err("proc: hidepid value must be between 0 and 2.\n"); | ||
77 | return 0; | ||
78 | } | ||
79 | pid->hide_pid = option; | ||
80 | break; | ||
81 | default: | ||
82 | pr_err("proc: unrecognized mount option \"%s\" " | ||
83 | "or missing value\n", p); | ||
84 | return 0; | ||
85 | } | ||
86 | } | ||
87 | |||
88 | return 1; | ||
89 | } | ||
90 | |||
91 | int proc_remount(struct super_block *sb, int *flags, char *data) | ||
92 | { | ||
93 | struct pid_namespace *pid = sb->s_fs_info; | ||
94 | return !proc_parse_options(data, pid); | ||
95 | } | ||
96 | |||
39 | static struct dentry *proc_mount(struct file_system_type *fs_type, | 97 | static struct dentry *proc_mount(struct file_system_type *fs_type, |
40 | int flags, const char *dev_name, void *data) | 98 | int flags, const char *dev_name, void *data) |
41 | { | 99 | { |
@@ -43,11 +101,15 @@ static struct dentry *proc_mount(struct file_system_type *fs_type, | |||
43 | struct super_block *sb; | 101 | struct super_block *sb; |
44 | struct pid_namespace *ns; | 102 | struct pid_namespace *ns; |
45 | struct proc_inode *ei; | 103 | struct proc_inode *ei; |
104 | char *options; | ||
46 | 105 | ||
47 | if (flags & MS_KERNMOUNT) | 106 | if (flags & MS_KERNMOUNT) { |
48 | ns = (struct pid_namespace *)data; | 107 | ns = (struct pid_namespace *)data; |
49 | else | 108 | options = NULL; |
109 | } else { | ||
50 | ns = current->nsproxy->pid_ns; | 110 | ns = current->nsproxy->pid_ns; |
111 | options = data; | ||
112 | } | ||
51 | 113 | ||
52 | sb = sget(fs_type, proc_test_super, proc_set_super, ns); | 114 | sb = sget(fs_type, proc_test_super, proc_set_super, ns); |
53 | if (IS_ERR(sb)) | 115 | if (IS_ERR(sb)) |
@@ -55,6 +117,10 @@ static struct dentry *proc_mount(struct file_system_type *fs_type, | |||
55 | 117 | ||
56 | if (!sb->s_root) { | 118 | if (!sb->s_root) { |
57 | sb->s_flags = flags; | 119 | sb->s_flags = flags; |
120 | if (!proc_parse_options(options, ns)) { | ||
121 | deactivate_locked_super(sb); | ||
122 | return ERR_PTR(-EINVAL); | ||
123 | } | ||
58 | err = proc_fill_super(sb); | 124 | err = proc_fill_super(sb); |
59 | if (err) { | 125 | if (err) { |
60 | deactivate_locked_super(sb); | 126 | deactivate_locked_super(sb); |
diff --git a/fs/reiserfs/bitmap.c b/fs/reiserfs/bitmap.c index a945cd265228..70de42f09f1d 100644 --- a/fs/reiserfs/bitmap.c +++ b/fs/reiserfs/bitmap.c | |||
@@ -1364,10 +1364,7 @@ int reiserfs_init_bitmap_cache(struct super_block *sb) | |||
1364 | struct reiserfs_bitmap_info *bitmap; | 1364 | struct reiserfs_bitmap_info *bitmap; |
1365 | unsigned int bmap_nr = reiserfs_bmap_count(sb); | 1365 | unsigned int bmap_nr = reiserfs_bmap_count(sb); |
1366 | 1366 | ||
1367 | /* Avoid lock recursion in fault case */ | ||
1368 | reiserfs_write_unlock(sb); | ||
1369 | bitmap = vmalloc(sizeof(*bitmap) * bmap_nr); | 1367 | bitmap = vmalloc(sizeof(*bitmap) * bmap_nr); |
1370 | reiserfs_write_lock(sb); | ||
1371 | if (bitmap == NULL) | 1368 | if (bitmap == NULL) |
1372 | return -ENOMEM; | 1369 | return -ENOMEM; |
1373 | 1370 | ||
diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c index eb711060a6f2..c3cf54fd4de3 100644 --- a/fs/reiserfs/journal.c +++ b/fs/reiserfs/journal.c | |||
@@ -2678,16 +2678,10 @@ int journal_init(struct super_block *sb, const char *j_dev_name, | |||
2678 | char b[BDEVNAME_SIZE]; | 2678 | char b[BDEVNAME_SIZE]; |
2679 | int ret; | 2679 | int ret; |
2680 | 2680 | ||
2681 | /* | ||
2682 | * Unlock here to avoid various RECLAIM-FS-ON <-> IN-RECLAIM-FS | ||
2683 | * dependency inversion warnings. | ||
2684 | */ | ||
2685 | reiserfs_write_unlock(sb); | ||
2686 | journal = SB_JOURNAL(sb) = vzalloc(sizeof(struct reiserfs_journal)); | 2681 | journal = SB_JOURNAL(sb) = vzalloc(sizeof(struct reiserfs_journal)); |
2687 | if (!journal) { | 2682 | if (!journal) { |
2688 | reiserfs_warning(sb, "journal-1256", | 2683 | reiserfs_warning(sb, "journal-1256", |
2689 | "unable to get memory for journal structure"); | 2684 | "unable to get memory for journal structure"); |
2690 | reiserfs_write_lock(sb); | ||
2691 | return 1; | 2685 | return 1; |
2692 | } | 2686 | } |
2693 | INIT_LIST_HEAD(&journal->j_bitmap_nodes); | 2687 | INIT_LIST_HEAD(&journal->j_bitmap_nodes); |
@@ -2695,10 +2689,8 @@ int journal_init(struct super_block *sb, const char *j_dev_name, | |||
2695 | INIT_LIST_HEAD(&journal->j_working_list); | 2689 | INIT_LIST_HEAD(&journal->j_working_list); |
2696 | INIT_LIST_HEAD(&journal->j_journal_list); | 2690 | INIT_LIST_HEAD(&journal->j_journal_list); |
2697 | journal->j_persistent_trans = 0; | 2691 | journal->j_persistent_trans = 0; |
2698 | ret = reiserfs_allocate_list_bitmaps(sb, journal->j_list_bitmap, | 2692 | if (reiserfs_allocate_list_bitmaps(sb, journal->j_list_bitmap, |
2699 | reiserfs_bmap_count(sb)); | 2693 | reiserfs_bmap_count(sb))) |
2700 | reiserfs_write_lock(sb); | ||
2701 | if (ret) | ||
2702 | goto free_and_return; | 2694 | goto free_and_return; |
2703 | 2695 | ||
2704 | allocate_bitmap_nodes(sb); | 2696 | allocate_bitmap_nodes(sb); |
@@ -2727,27 +2719,11 @@ int journal_init(struct super_block *sb, const char *j_dev_name, | |||
2727 | goto free_and_return; | 2719 | goto free_and_return; |
2728 | } | 2720 | } |
2729 | 2721 | ||
2730 | /* | ||
2731 | * We need to unlock here to avoid creating the following | ||
2732 | * dependency: | ||
2733 | * reiserfs_lock -> sysfs_mutex | ||
2734 | * Because the reiserfs mmap path creates the following dependency: | ||
2735 | * mm->mmap -> reiserfs_lock, hence we have | ||
2736 | * mm->mmap -> reiserfs_lock ->sysfs_mutex | ||
2737 | * This would ends up in a circular dependency with sysfs readdir path | ||
2738 | * which does sysfs_mutex -> mm->mmap_sem | ||
2739 | * This is fine because the reiserfs lock is useless in mount path, | ||
2740 | * at least until we call journal_begin. We keep it for paranoid | ||
2741 | * reasons. | ||
2742 | */ | ||
2743 | reiserfs_write_unlock(sb); | ||
2744 | if (journal_init_dev(sb, journal, j_dev_name) != 0) { | 2722 | if (journal_init_dev(sb, journal, j_dev_name) != 0) { |
2745 | reiserfs_write_lock(sb); | ||
2746 | reiserfs_warning(sb, "sh-462", | 2723 | reiserfs_warning(sb, "sh-462", |
2747 | "unable to initialize jornal device"); | 2724 | "unable to initialize jornal device"); |
2748 | goto free_and_return; | 2725 | goto free_and_return; |
2749 | } | 2726 | } |
2750 | reiserfs_write_lock(sb); | ||
2751 | 2727 | ||
2752 | rs = SB_DISK_SUPER_BLOCK(sb); | 2728 | rs = SB_DISK_SUPER_BLOCK(sb); |
2753 | 2729 | ||
@@ -2829,9 +2805,7 @@ int journal_init(struct super_block *sb, const char *j_dev_name, | |||
2829 | journal->j_mount_id = 10; | 2805 | journal->j_mount_id = 10; |
2830 | journal->j_state = 0; | 2806 | journal->j_state = 0; |
2831 | atomic_set(&(journal->j_jlock), 0); | 2807 | atomic_set(&(journal->j_jlock), 0); |
2832 | reiserfs_write_unlock(sb); | ||
2833 | journal->j_cnode_free_list = allocate_cnodes(num_cnodes); | 2808 | journal->j_cnode_free_list = allocate_cnodes(num_cnodes); |
2834 | reiserfs_write_lock(sb); | ||
2835 | journal->j_cnode_free_orig = journal->j_cnode_free_list; | 2809 | journal->j_cnode_free_orig = journal->j_cnode_free_list; |
2836 | journal->j_cnode_free = journal->j_cnode_free_list ? num_cnodes : 0; | 2810 | journal->j_cnode_free = journal->j_cnode_free_list ? num_cnodes : 0; |
2837 | journal->j_cnode_used = 0; | 2811 | journal->j_cnode_used = 0; |
@@ -2848,24 +2822,37 @@ int journal_init(struct super_block *sb, const char *j_dev_name, | |||
2848 | 2822 | ||
2849 | init_journal_hash(sb); | 2823 | init_journal_hash(sb); |
2850 | jl = journal->j_current_jl; | 2824 | jl = journal->j_current_jl; |
2825 | |||
2826 | /* | ||
2827 | * get_list_bitmap() may call flush_commit_list() which | ||
2828 | * requires the lock. Calling flush_commit_list() shouldn't happen | ||
2829 | * this early but I like to be paranoid. | ||
2830 | */ | ||
2831 | reiserfs_write_lock(sb); | ||
2851 | jl->j_list_bitmap = get_list_bitmap(sb, jl); | 2832 | jl->j_list_bitmap = get_list_bitmap(sb, jl); |
2833 | reiserfs_write_unlock(sb); | ||
2852 | if (!jl->j_list_bitmap) { | 2834 | if (!jl->j_list_bitmap) { |
2853 | reiserfs_warning(sb, "journal-2005", | 2835 | reiserfs_warning(sb, "journal-2005", |
2854 | "get_list_bitmap failed for journal list 0"); | 2836 | "get_list_bitmap failed for journal list 0"); |
2855 | goto free_and_return; | 2837 | goto free_and_return; |
2856 | } | 2838 | } |
2857 | if (journal_read(sb) < 0) { | 2839 | |
2840 | /* | ||
2841 | * Journal_read needs to be inspected in order to push down | ||
2842 | * the lock further inside (or even remove it). | ||
2843 | */ | ||
2844 | reiserfs_write_lock(sb); | ||
2845 | ret = journal_read(sb); | ||
2846 | reiserfs_write_unlock(sb); | ||
2847 | if (ret < 0) { | ||
2858 | reiserfs_warning(sb, "reiserfs-2006", | 2848 | reiserfs_warning(sb, "reiserfs-2006", |
2859 | "Replay Failure, unable to mount"); | 2849 | "Replay Failure, unable to mount"); |
2860 | goto free_and_return; | 2850 | goto free_and_return; |
2861 | } | 2851 | } |
2862 | 2852 | ||
2863 | reiserfs_mounted_fs_count++; | 2853 | reiserfs_mounted_fs_count++; |
2864 | if (reiserfs_mounted_fs_count <= 1) { | 2854 | if (reiserfs_mounted_fs_count <= 1) |
2865 | reiserfs_write_unlock(sb); | ||
2866 | commit_wq = alloc_workqueue("reiserfs", WQ_MEM_RECLAIM, 0); | 2855 | commit_wq = alloc_workqueue("reiserfs", WQ_MEM_RECLAIM, 0); |
2867 | reiserfs_write_lock(sb); | ||
2868 | } | ||
2869 | 2856 | ||
2870 | INIT_DELAYED_WORK(&journal->j_work, flush_async_commits); | 2857 | INIT_DELAYED_WORK(&journal->j_work, flush_async_commits); |
2871 | journal->j_work_sb = sb; | 2858 | journal->j_work_sb = sb; |
@@ -2896,14 +2883,13 @@ int journal_transaction_should_end(struct reiserfs_transaction_handle *th, | |||
2896 | journal->j_cnode_free < (journal->j_trans_max * 3)) { | 2883 | journal->j_cnode_free < (journal->j_trans_max * 3)) { |
2897 | return 1; | 2884 | return 1; |
2898 | } | 2885 | } |
2899 | /* protected by the BKL here */ | 2886 | |
2900 | journal->j_len_alloc += new_alloc; | 2887 | journal->j_len_alloc += new_alloc; |
2901 | th->t_blocks_allocated += new_alloc ; | 2888 | th->t_blocks_allocated += new_alloc ; |
2902 | return 0; | 2889 | return 0; |
2903 | } | 2890 | } |
2904 | 2891 | ||
2905 | /* this must be called inside a transaction, and requires the | 2892 | /* this must be called inside a transaction |
2906 | ** kernel_lock to be held | ||
2907 | */ | 2893 | */ |
2908 | void reiserfs_block_writes(struct reiserfs_transaction_handle *th) | 2894 | void reiserfs_block_writes(struct reiserfs_transaction_handle *th) |
2909 | { | 2895 | { |
@@ -2914,8 +2900,7 @@ void reiserfs_block_writes(struct reiserfs_transaction_handle *th) | |||
2914 | return; | 2900 | return; |
2915 | } | 2901 | } |
2916 | 2902 | ||
2917 | /* this must be called without a transaction started, and does not | 2903 | /* this must be called without a transaction started |
2918 | ** require BKL | ||
2919 | */ | 2904 | */ |
2920 | void reiserfs_allow_writes(struct super_block *s) | 2905 | void reiserfs_allow_writes(struct super_block *s) |
2921 | { | 2906 | { |
@@ -2924,8 +2909,7 @@ void reiserfs_allow_writes(struct super_block *s) | |||
2924 | wake_up(&journal->j_join_wait); | 2909 | wake_up(&journal->j_join_wait); |
2925 | } | 2910 | } |
2926 | 2911 | ||
2927 | /* this must be called without a transaction started, and does not | 2912 | /* this must be called without a transaction started |
2928 | ** require BKL | ||
2929 | */ | 2913 | */ |
2930 | void reiserfs_wait_on_write_block(struct super_block *s) | 2914 | void reiserfs_wait_on_write_block(struct super_block *s) |
2931 | { | 2915 | { |
diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c index 1d42e707d5fa..e12d8b97cd4d 100644 --- a/fs/reiserfs/super.c +++ b/fs/reiserfs/super.c | |||
@@ -1519,9 +1519,7 @@ static int read_super_block(struct super_block *s, int offset) | |||
1519 | static int reread_meta_blocks(struct super_block *s) | 1519 | static int reread_meta_blocks(struct super_block *s) |
1520 | { | 1520 | { |
1521 | ll_rw_block(READ, 1, &(SB_BUFFER_WITH_SB(s))); | 1521 | ll_rw_block(READ, 1, &(SB_BUFFER_WITH_SB(s))); |
1522 | reiserfs_write_unlock(s); | ||
1523 | wait_on_buffer(SB_BUFFER_WITH_SB(s)); | 1522 | wait_on_buffer(SB_BUFFER_WITH_SB(s)); |
1524 | reiserfs_write_lock(s); | ||
1525 | if (!buffer_uptodate(SB_BUFFER_WITH_SB(s))) { | 1523 | if (!buffer_uptodate(SB_BUFFER_WITH_SB(s))) { |
1526 | reiserfs_warning(s, "reiserfs-2504", "error reading the super"); | 1524 | reiserfs_warning(s, "reiserfs-2504", "error reading the super"); |
1527 | return 1; | 1525 | return 1; |
@@ -1746,22 +1744,11 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent) | |||
1746 | mutex_init(&REISERFS_SB(s)->lock); | 1744 | mutex_init(&REISERFS_SB(s)->lock); |
1747 | REISERFS_SB(s)->lock_depth = -1; | 1745 | REISERFS_SB(s)->lock_depth = -1; |
1748 | 1746 | ||
1749 | /* | ||
1750 | * This function is called with the bkl, which also was the old | ||
1751 | * locking used here. | ||
1752 | * do_journal_begin() will soon check if we hold the lock (ie: was the | ||
1753 | * bkl). This is likely because do_journal_begin() has several another | ||
1754 | * callers because at this time, it doesn't seem to be necessary to | ||
1755 | * protect against anything. | ||
1756 | * Anyway, let's be conservative and lock for now. | ||
1757 | */ | ||
1758 | reiserfs_write_lock(s); | ||
1759 | |||
1760 | jdev_name = NULL; | 1747 | jdev_name = NULL; |
1761 | if (reiserfs_parse_options | 1748 | if (reiserfs_parse_options |
1762 | (s, (char *)data, &(sbi->s_mount_opt), &blocks, &jdev_name, | 1749 | (s, (char *)data, &(sbi->s_mount_opt), &blocks, &jdev_name, |
1763 | &commit_max_age, qf_names, &qfmt) == 0) { | 1750 | &commit_max_age, qf_names, &qfmt) == 0) { |
1764 | goto error; | 1751 | goto error_unlocked; |
1765 | } | 1752 | } |
1766 | if (jdev_name && jdev_name[0]) { | 1753 | if (jdev_name && jdev_name[0]) { |
1767 | REISERFS_SB(s)->s_jdev = kstrdup(jdev_name, GFP_KERNEL); | 1754 | REISERFS_SB(s)->s_jdev = kstrdup(jdev_name, GFP_KERNEL); |
@@ -1777,7 +1764,7 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent) | |||
1777 | 1764 | ||
1778 | if (blocks) { | 1765 | if (blocks) { |
1779 | SWARN(silent, s, "jmacd-7", "resize option for remount only"); | 1766 | SWARN(silent, s, "jmacd-7", "resize option for remount only"); |
1780 | goto error; | 1767 | goto error_unlocked; |
1781 | } | 1768 | } |
1782 | 1769 | ||
1783 | /* try old format (undistributed bitmap, super block in 8-th 1k block of a device) */ | 1770 | /* try old format (undistributed bitmap, super block in 8-th 1k block of a device) */ |
@@ -1787,7 +1774,7 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent) | |||
1787 | else if (read_super_block(s, REISERFS_DISK_OFFSET_IN_BYTES)) { | 1774 | else if (read_super_block(s, REISERFS_DISK_OFFSET_IN_BYTES)) { |
1788 | SWARN(silent, s, "sh-2021", "can not find reiserfs on %s", | 1775 | SWARN(silent, s, "sh-2021", "can not find reiserfs on %s", |
1789 | reiserfs_bdevname(s)); | 1776 | reiserfs_bdevname(s)); |
1790 | goto error; | 1777 | goto error_unlocked; |
1791 | } | 1778 | } |
1792 | 1779 | ||
1793 | rs = SB_DISK_SUPER_BLOCK(s); | 1780 | rs = SB_DISK_SUPER_BLOCK(s); |
@@ -1803,7 +1790,7 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent) | |||
1803 | "or increase size of your LVM partition"); | 1790 | "or increase size of your LVM partition"); |
1804 | SWARN(silent, s, "", "Or may be you forgot to " | 1791 | SWARN(silent, s, "", "Or may be you forgot to " |
1805 | "reboot after fdisk when it told you to"); | 1792 | "reboot after fdisk when it told you to"); |
1806 | goto error; | 1793 | goto error_unlocked; |
1807 | } | 1794 | } |
1808 | 1795 | ||
1809 | sbi->s_mount_state = SB_REISERFS_STATE(s); | 1796 | sbi->s_mount_state = SB_REISERFS_STATE(s); |
@@ -1811,8 +1798,9 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent) | |||
1811 | 1798 | ||
1812 | if ((errval = reiserfs_init_bitmap_cache(s))) { | 1799 | if ((errval = reiserfs_init_bitmap_cache(s))) { |
1813 | SWARN(silent, s, "jmacd-8", "unable to read bitmap"); | 1800 | SWARN(silent, s, "jmacd-8", "unable to read bitmap"); |
1814 | goto error; | 1801 | goto error_unlocked; |
1815 | } | 1802 | } |
1803 | |||
1816 | errval = -EINVAL; | 1804 | errval = -EINVAL; |
1817 | #ifdef CONFIG_REISERFS_CHECK | 1805 | #ifdef CONFIG_REISERFS_CHECK |
1818 | SWARN(silent, s, "", "CONFIG_REISERFS_CHECK is set ON"); | 1806 | SWARN(silent, s, "", "CONFIG_REISERFS_CHECK is set ON"); |
@@ -1835,24 +1823,26 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent) | |||
1835 | if (reiserfs_barrier_flush(s)) { | 1823 | if (reiserfs_barrier_flush(s)) { |
1836 | printk("reiserfs: using flush barriers\n"); | 1824 | printk("reiserfs: using flush barriers\n"); |
1837 | } | 1825 | } |
1826 | |||
1838 | // set_device_ro(s->s_dev, 1) ; | 1827 | // set_device_ro(s->s_dev, 1) ; |
1839 | if (journal_init(s, jdev_name, old_format, commit_max_age)) { | 1828 | if (journal_init(s, jdev_name, old_format, commit_max_age)) { |
1840 | SWARN(silent, s, "sh-2022", | 1829 | SWARN(silent, s, "sh-2022", |
1841 | "unable to initialize journal space"); | 1830 | "unable to initialize journal space"); |
1842 | goto error; | 1831 | goto error_unlocked; |
1843 | } else { | 1832 | } else { |
1844 | jinit_done = 1; /* once this is set, journal_release must be called | 1833 | jinit_done = 1; /* once this is set, journal_release must be called |
1845 | ** if we error out of the mount | 1834 | ** if we error out of the mount |
1846 | */ | 1835 | */ |
1847 | } | 1836 | } |
1837 | |||
1848 | if (reread_meta_blocks(s)) { | 1838 | if (reread_meta_blocks(s)) { |
1849 | SWARN(silent, s, "jmacd-9", | 1839 | SWARN(silent, s, "jmacd-9", |
1850 | "unable to reread meta blocks after journal init"); | 1840 | "unable to reread meta blocks after journal init"); |
1851 | goto error; | 1841 | goto error_unlocked; |
1852 | } | 1842 | } |
1853 | 1843 | ||
1854 | if (replay_only(s)) | 1844 | if (replay_only(s)) |
1855 | goto error; | 1845 | goto error_unlocked; |
1856 | 1846 | ||
1857 | if (bdev_read_only(s->s_bdev) && !(s->s_flags & MS_RDONLY)) { | 1847 | if (bdev_read_only(s->s_bdev) && !(s->s_flags & MS_RDONLY)) { |
1858 | SWARN(silent, s, "clm-7000", | 1848 | SWARN(silent, s, "clm-7000", |
@@ -1866,9 +1856,19 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent) | |||
1866 | reiserfs_init_locked_inode, (void *)(&args)); | 1856 | reiserfs_init_locked_inode, (void *)(&args)); |
1867 | if (!root_inode) { | 1857 | if (!root_inode) { |
1868 | SWARN(silent, s, "jmacd-10", "get root inode failed"); | 1858 | SWARN(silent, s, "jmacd-10", "get root inode failed"); |
1869 | goto error; | 1859 | goto error_unlocked; |
1870 | } | 1860 | } |
1871 | 1861 | ||
1862 | /* | ||
1863 | * This path assumed to be called with the BKL in the old times. | ||
1864 | * Now we have inherited the big reiserfs lock from it and many | ||
1865 | * reiserfs helpers called in the mount path and elsewhere require | ||
1866 | * this lock to be held even if it's not always necessary. Let's be | ||
1867 | * conservative and hold it early. The window can be reduced after | ||
1868 | * careful review of the code. | ||
1869 | */ | ||
1870 | reiserfs_write_lock(s); | ||
1871 | |||
1872 | if (root_inode->i_state & I_NEW) { | 1872 | if (root_inode->i_state & I_NEW) { |
1873 | reiserfs_read_locked_inode(root_inode, &args); | 1873 | reiserfs_read_locked_inode(root_inode, &args); |
1874 | unlock_new_inode(root_inode); | 1874 | unlock_new_inode(root_inode); |
@@ -1995,12 +1995,16 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent) | |||
1995 | return (0); | 1995 | return (0); |
1996 | 1996 | ||
1997 | error: | 1997 | error: |
1998 | if (jinit_done) { /* kill the commit thread, free journal ram */ | 1998 | reiserfs_write_unlock(s); |
1999 | |||
2000 | error_unlocked: | ||
2001 | /* kill the commit thread, free journal ram */ | ||
2002 | if (jinit_done) { | ||
2003 | reiserfs_write_lock(s); | ||
1999 | journal_release_error(NULL, s); | 2004 | journal_release_error(NULL, s); |
2005 | reiserfs_write_unlock(s); | ||
2000 | } | 2006 | } |
2001 | 2007 | ||
2002 | reiserfs_write_unlock(s); | ||
2003 | |||
2004 | reiserfs_free_bitmap_cache(s); | 2008 | reiserfs_free_bitmap_cache(s); |
2005 | if (SB_BUFFER_WITH_SB(s)) | 2009 | if (SB_BUFFER_WITH_SB(s)) |
2006 | brelse(SB_BUFFER_WITH_SB(s)); | 2010 | brelse(SB_BUFFER_WITH_SB(s)); |
diff --git a/include/linux/compiler-gcc4.h b/include/linux/compiler-gcc4.h index dfadc96e9d63..2f4079175afb 100644 --- a/include/linux/compiler-gcc4.h +++ b/include/linux/compiler-gcc4.h | |||
@@ -29,6 +29,7 @@ | |||
29 | the kernel context */ | 29 | the kernel context */ |
30 | #define __cold __attribute__((__cold__)) | 30 | #define __cold __attribute__((__cold__)) |
31 | 31 | ||
32 | #define __linktime_error(message) __attribute__((__error__(message))) | ||
32 | 33 | ||
33 | #if __GNUC_MINOR__ >= 5 | 34 | #if __GNUC_MINOR__ >= 5 |
34 | /* | 35 | /* |
diff --git a/include/linux/compiler.h b/include/linux/compiler.h index 320d6c94ff84..4a243546d142 100644 --- a/include/linux/compiler.h +++ b/include/linux/compiler.h | |||
@@ -293,7 +293,9 @@ void ftrace_likely_update(struct ftrace_branch_data *f, int val, int expect); | |||
293 | #ifndef __compiletime_error | 293 | #ifndef __compiletime_error |
294 | # define __compiletime_error(message) | 294 | # define __compiletime_error(message) |
295 | #endif | 295 | #endif |
296 | 296 | #ifndef __linktime_error | |
297 | # define __linktime_error(message) | ||
298 | #endif | ||
297 | /* | 299 | /* |
298 | * Prevent the compiler from merging or refetching accesses. The compiler | 300 | * Prevent the compiler from merging or refetching accesses. The compiler |
299 | * is also forbidden from reordering successive instances of ACCESS_ONCE(), | 301 | * is also forbidden from reordering successive instances of ACCESS_ONCE(), |
diff --git a/include/linux/gfp.h b/include/linux/gfp.h index 3a76faf6a3ee..581e74b7df95 100644 --- a/include/linux/gfp.h +++ b/include/linux/gfp.h | |||
@@ -36,6 +36,7 @@ struct vm_area_struct; | |||
36 | #endif | 36 | #endif |
37 | #define ___GFP_NO_KSWAPD 0x400000u | 37 | #define ___GFP_NO_KSWAPD 0x400000u |
38 | #define ___GFP_OTHER_NODE 0x800000u | 38 | #define ___GFP_OTHER_NODE 0x800000u |
39 | #define ___GFP_WRITE 0x1000000u | ||
39 | 40 | ||
40 | /* | 41 | /* |
41 | * GFP bitmasks.. | 42 | * GFP bitmasks.. |
@@ -85,6 +86,7 @@ struct vm_area_struct; | |||
85 | 86 | ||
86 | #define __GFP_NO_KSWAPD ((__force gfp_t)___GFP_NO_KSWAPD) | 87 | #define __GFP_NO_KSWAPD ((__force gfp_t)___GFP_NO_KSWAPD) |
87 | #define __GFP_OTHER_NODE ((__force gfp_t)___GFP_OTHER_NODE) /* On behalf of other node */ | 88 | #define __GFP_OTHER_NODE ((__force gfp_t)___GFP_OTHER_NODE) /* On behalf of other node */ |
89 | #define __GFP_WRITE ((__force gfp_t)___GFP_WRITE) /* Allocator intends to dirty page */ | ||
88 | 90 | ||
89 | /* | 91 | /* |
90 | * This may seem redundant, but it's a way of annotating false positives vs. | 92 | * This may seem redundant, but it's a way of annotating false positives vs. |
@@ -92,7 +94,7 @@ struct vm_area_struct; | |||
92 | */ | 94 | */ |
93 | #define __GFP_NOTRACK_FALSE_POSITIVE (__GFP_NOTRACK) | 95 | #define __GFP_NOTRACK_FALSE_POSITIVE (__GFP_NOTRACK) |
94 | 96 | ||
95 | #define __GFP_BITS_SHIFT 24 /* Room for N __GFP_FOO bits */ | 97 | #define __GFP_BITS_SHIFT 25 /* Room for N __GFP_FOO bits */ |
96 | #define __GFP_BITS_MASK ((__force gfp_t)((1 << __GFP_BITS_SHIFT) - 1)) | 98 | #define __GFP_BITS_MASK ((__force gfp_t)((1 << __GFP_BITS_SHIFT) - 1)) |
97 | 99 | ||
98 | /* This equals 0, but use constants in case they ever change */ | 100 | /* This equals 0, but use constants in case they ever change */ |
@@ -313,7 +315,7 @@ static inline struct page *alloc_pages_node(int nid, gfp_t gfp_mask, | |||
313 | static inline struct page *alloc_pages_exact_node(int nid, gfp_t gfp_mask, | 315 | static inline struct page *alloc_pages_exact_node(int nid, gfp_t gfp_mask, |
314 | unsigned int order) | 316 | unsigned int order) |
315 | { | 317 | { |
316 | VM_BUG_ON(nid < 0 || nid >= MAX_NUMNODES); | 318 | VM_BUG_ON(nid < 0 || nid >= MAX_NUMNODES || !node_online(nid)); |
317 | 319 | ||
318 | return __alloc_pages(gfp_mask, order, node_zonelist(nid, gfp_mask)); | 320 | return __alloc_pages(gfp_mask, order, node_zonelist(nid, gfp_mask)); |
319 | } | 321 | } |
@@ -358,6 +360,7 @@ void *alloc_pages_exact_nid(int nid, size_t size, gfp_t gfp_mask); | |||
358 | extern void __free_pages(struct page *page, unsigned int order); | 360 | extern void __free_pages(struct page *page, unsigned int order); |
359 | extern void free_pages(unsigned long addr, unsigned int order); | 361 | extern void free_pages(unsigned long addr, unsigned int order); |
360 | extern void free_hot_cold_page(struct page *page, int cold); | 362 | extern void free_hot_cold_page(struct page *page, int cold); |
363 | extern void free_hot_cold_page_list(struct list_head *list, int cold); | ||
361 | 364 | ||
362 | #define __free_page(page) __free_pages((page), 0) | 365 | #define __free_page(page) __free_pages((page), 0) |
363 | #define free_page(addr) free_pages((addr), 0) | 366 | #define free_page(addr) free_pages((addr), 0) |
@@ -367,9 +370,25 @@ void drain_zone_pages(struct zone *zone, struct per_cpu_pages *pcp); | |||
367 | void drain_all_pages(void); | 370 | void drain_all_pages(void); |
368 | void drain_local_pages(void *dummy); | 371 | void drain_local_pages(void *dummy); |
369 | 372 | ||
373 | /* | ||
374 | * gfp_allowed_mask is set to GFP_BOOT_MASK during early boot to restrict what | ||
375 | * GFP flags are used before interrupts are enabled. Once interrupts are | ||
376 | * enabled, it is set to __GFP_BITS_MASK while the system is running. During | ||
377 | * hibernation, it is used by PM to avoid I/O during memory allocation while | ||
378 | * devices are suspended. | ||
379 | */ | ||
370 | extern gfp_t gfp_allowed_mask; | 380 | extern gfp_t gfp_allowed_mask; |
371 | 381 | ||
372 | extern void pm_restrict_gfp_mask(void); | 382 | extern void pm_restrict_gfp_mask(void); |
373 | extern void pm_restore_gfp_mask(void); | 383 | extern void pm_restore_gfp_mask(void); |
374 | 384 | ||
385 | #ifdef CONFIG_PM_SLEEP | ||
386 | extern bool pm_suspended_storage(void); | ||
387 | #else | ||
388 | static inline bool pm_suspended_storage(void) | ||
389 | { | ||
390 | return false; | ||
391 | } | ||
392 | #endif /* CONFIG_PM_SLEEP */ | ||
393 | |||
375 | #endif /* __LINUX_GFP_H */ | 394 | #endif /* __LINUX_GFP_H */ |
diff --git a/include/linux/kernel.h b/include/linux/kernel.h index e8b1597b5cf2..f48e8a528544 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h | |||
@@ -665,6 +665,7 @@ static inline void ftrace_dump(enum ftrace_dump_mode oops_dump_mode) { } | |||
665 | #define BUILD_BUG_ON_ZERO(e) (0) | 665 | #define BUILD_BUG_ON_ZERO(e) (0) |
666 | #define BUILD_BUG_ON_NULL(e) ((void*)0) | 666 | #define BUILD_BUG_ON_NULL(e) ((void*)0) |
667 | #define BUILD_BUG_ON(condition) | 667 | #define BUILD_BUG_ON(condition) |
668 | #define BUILD_BUG() (0) | ||
668 | #else /* __CHECKER__ */ | 669 | #else /* __CHECKER__ */ |
669 | 670 | ||
670 | /* Force a compilation error if a constant expression is not a power of 2 */ | 671 | /* Force a compilation error if a constant expression is not a power of 2 */ |
@@ -703,6 +704,21 @@ extern int __build_bug_on_failed; | |||
703 | if (condition) __build_bug_on_failed = 1; \ | 704 | if (condition) __build_bug_on_failed = 1; \ |
704 | } while(0) | 705 | } while(0) |
705 | #endif | 706 | #endif |
707 | |||
708 | /** | ||
709 | * BUILD_BUG - break compile if used. | ||
710 | * | ||
711 | * If you have some code that you expect the compiler to eliminate at | ||
712 | * build time, you should use BUILD_BUG to detect if it is | ||
713 | * unexpectedly used. | ||
714 | */ | ||
715 | #define BUILD_BUG() \ | ||
716 | do { \ | ||
717 | extern void __build_bug_failed(void) \ | ||
718 | __linktime_error("BUILD_BUG failed"); \ | ||
719 | __build_bug_failed(); \ | ||
720 | } while (0) | ||
721 | |||
706 | #endif /* __CHECKER__ */ | 722 | #endif /* __CHECKER__ */ |
707 | 723 | ||
708 | /* Trap pasters of __FUNCTION__ at compile-time */ | 724 | /* Trap pasters of __FUNCTION__ at compile-time */ |
diff --git a/include/linux/leds-tca6507.h b/include/linux/leds-tca6507.h new file mode 100644 index 000000000000..dcabf4fa2aef --- /dev/null +++ b/include/linux/leds-tca6507.h | |||
@@ -0,0 +1,34 @@ | |||
1 | /* | ||
2 | * TCA6507 LED chip driver. | ||
3 | * | ||
4 | * Copyright (C) 2011 Neil Brown <neil@brown.name> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * version 2 as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, but | ||
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | * General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
18 | * 02110-1301 USA | ||
19 | */ | ||
20 | |||
21 | #ifndef __LINUX_TCA6507_H | ||
22 | #define __LINUX_TCA6507_H | ||
23 | #include <linux/leds.h> | ||
24 | |||
25 | struct tca6507_platform_data { | ||
26 | struct led_platform_data leds; | ||
27 | #ifdef CONFIG_GPIOLIB | ||
28 | int gpio_base; | ||
29 | void (*setup)(unsigned gpio_base, unsigned ngpio); | ||
30 | #endif | ||
31 | }; | ||
32 | |||
33 | #define TCA6507_MAKE_GPIO 1 | ||
34 | #endif /* __LINUX_TCA6507_H*/ | ||
diff --git a/include/linux/mempolicy.h b/include/linux/mempolicy.h index 7978eec1b7d9..7c727a90d70d 100644 --- a/include/linux/mempolicy.h +++ b/include/linux/mempolicy.h | |||
@@ -164,11 +164,11 @@ static inline void mpol_get(struct mempolicy *pol) | |||
164 | atomic_inc(&pol->refcnt); | 164 | atomic_inc(&pol->refcnt); |
165 | } | 165 | } |
166 | 166 | ||
167 | extern int __mpol_equal(struct mempolicy *a, struct mempolicy *b); | 167 | extern bool __mpol_equal(struct mempolicy *a, struct mempolicy *b); |
168 | static inline int mpol_equal(struct mempolicy *a, struct mempolicy *b) | 168 | static inline bool mpol_equal(struct mempolicy *a, struct mempolicy *b) |
169 | { | 169 | { |
170 | if (a == b) | 170 | if (a == b) |
171 | return 1; | 171 | return true; |
172 | return __mpol_equal(a, b); | 172 | return __mpol_equal(a, b); |
173 | } | 173 | } |
174 | 174 | ||
@@ -257,9 +257,9 @@ static inline int vma_migratable(struct vm_area_struct *vma) | |||
257 | 257 | ||
258 | struct mempolicy {}; | 258 | struct mempolicy {}; |
259 | 259 | ||
260 | static inline int mpol_equal(struct mempolicy *a, struct mempolicy *b) | 260 | static inline bool mpol_equal(struct mempolicy *a, struct mempolicy *b) |
261 | { | 261 | { |
262 | return 1; | 262 | return true; |
263 | } | 263 | } |
264 | 264 | ||
265 | static inline void mpol_put(struct mempolicy *p) | 265 | static inline void mpol_put(struct mempolicy *p) |
diff --git a/include/linux/mm.h b/include/linux/mm.h index 5d9b4c9813bd..6eba2cc016c9 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h | |||
@@ -1482,6 +1482,18 @@ static inline unsigned long vma_pages(struct vm_area_struct *vma) | |||
1482 | return (vma->vm_end - vma->vm_start) >> PAGE_SHIFT; | 1482 | return (vma->vm_end - vma->vm_start) >> PAGE_SHIFT; |
1483 | } | 1483 | } |
1484 | 1484 | ||
1485 | /* Look up the first VMA which exactly match the interval vm_start ... vm_end */ | ||
1486 | static inline struct vm_area_struct *find_exact_vma(struct mm_struct *mm, | ||
1487 | unsigned long vm_start, unsigned long vm_end) | ||
1488 | { | ||
1489 | struct vm_area_struct *vma = find_vma(mm, vm_start); | ||
1490 | |||
1491 | if (vma && (vma->vm_start != vm_start || vma->vm_end != vm_end)) | ||
1492 | vma = NULL; | ||
1493 | |||
1494 | return vma; | ||
1495 | } | ||
1496 | |||
1485 | #ifdef CONFIG_MMU | 1497 | #ifdef CONFIG_MMU |
1486 | pgprot_t vm_get_page_prot(unsigned long vm_flags); | 1498 | pgprot_t vm_get_page_prot(unsigned long vm_flags); |
1487 | #else | 1499 | #else |
@@ -1618,5 +1630,22 @@ extern void copy_user_huge_page(struct page *dst, struct page *src, | |||
1618 | unsigned int pages_per_huge_page); | 1630 | unsigned int pages_per_huge_page); |
1619 | #endif /* CONFIG_TRANSPARENT_HUGEPAGE || CONFIG_HUGETLBFS */ | 1631 | #endif /* CONFIG_TRANSPARENT_HUGEPAGE || CONFIG_HUGETLBFS */ |
1620 | 1632 | ||
1633 | #ifdef CONFIG_DEBUG_PAGEALLOC | ||
1634 | extern unsigned int _debug_guardpage_minorder; | ||
1635 | |||
1636 | static inline unsigned int debug_guardpage_minorder(void) | ||
1637 | { | ||
1638 | return _debug_guardpage_minorder; | ||
1639 | } | ||
1640 | |||
1641 | static inline bool page_is_guard(struct page *page) | ||
1642 | { | ||
1643 | return test_bit(PAGE_DEBUG_FLAG_GUARD, &page->debug_flags); | ||
1644 | } | ||
1645 | #else | ||
1646 | static inline unsigned int debug_guardpage_minorder(void) { return 0; } | ||
1647 | static inline bool page_is_guard(struct page *page) { return false; } | ||
1648 | #endif /* CONFIG_DEBUG_PAGEALLOC */ | ||
1649 | |||
1621 | #endif /* __KERNEL__ */ | 1650 | #endif /* __KERNEL__ */ |
1622 | #endif /* _LINUX_MM_H */ | 1651 | #endif /* _LINUX_MM_H */ |
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index 3ac040f19369..ca6ca92418a6 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h | |||
@@ -317,6 +317,12 @@ struct zone { | |||
317 | */ | 317 | */ |
318 | unsigned long lowmem_reserve[MAX_NR_ZONES]; | 318 | unsigned long lowmem_reserve[MAX_NR_ZONES]; |
319 | 319 | ||
320 | /* | ||
321 | * This is a per-zone reserve of pages that should not be | ||
322 | * considered dirtyable memory. | ||
323 | */ | ||
324 | unsigned long dirty_balance_reserve; | ||
325 | |||
320 | #ifdef CONFIG_NUMA | 326 | #ifdef CONFIG_NUMA |
321 | int node; | 327 | int node; |
322 | /* | 328 | /* |
diff --git a/include/linux/page-debug-flags.h b/include/linux/page-debug-flags.h index b0638fd91e92..22691f614043 100644 --- a/include/linux/page-debug-flags.h +++ b/include/linux/page-debug-flags.h | |||
@@ -13,6 +13,7 @@ | |||
13 | 13 | ||
14 | enum page_debug_flags { | 14 | enum page_debug_flags { |
15 | PAGE_DEBUG_FLAG_POISON, /* Page is poisoned */ | 15 | PAGE_DEBUG_FLAG_POISON, /* Page is poisoned */ |
16 | PAGE_DEBUG_FLAG_GUARD, | ||
16 | }; | 17 | }; |
17 | 18 | ||
18 | /* | 19 | /* |
@@ -21,7 +22,8 @@ enum page_debug_flags { | |||
21 | */ | 22 | */ |
22 | 23 | ||
23 | #ifdef CONFIG_WANT_PAGE_DEBUG_FLAGS | 24 | #ifdef CONFIG_WANT_PAGE_DEBUG_FLAGS |
24 | #if !defined(CONFIG_PAGE_POISONING) \ | 25 | #if !defined(CONFIG_PAGE_POISONING) && \ |
26 | !defined(CONFIG_PAGE_GUARD) \ | ||
25 | /* && !defined(CONFIG_PAGE_DEBUG_SOMETHING_ELSE) && ... */ | 27 | /* && !defined(CONFIG_PAGE_DEBUG_SOMETHING_ELSE) && ... */ |
26 | #error WANT_PAGE_DEBUG_FLAGS is turned on with no debug features! | 28 | #error WANT_PAGE_DEBUG_FLAGS is turned on with no debug features! |
27 | #endif | 29 | #endif |
diff --git a/include/linux/pagevec.h b/include/linux/pagevec.h index bab82f4c571c..ed17024d2ebe 100644 --- a/include/linux/pagevec.h +++ b/include/linux/pagevec.h | |||
@@ -21,7 +21,6 @@ struct pagevec { | |||
21 | }; | 21 | }; |
22 | 22 | ||
23 | void __pagevec_release(struct pagevec *pvec); | 23 | void __pagevec_release(struct pagevec *pvec); |
24 | void __pagevec_free(struct pagevec *pvec); | ||
25 | void ____pagevec_lru_add(struct pagevec *pvec, enum lru_list lru); | 24 | void ____pagevec_lru_add(struct pagevec *pvec, enum lru_list lru); |
26 | void pagevec_strip(struct pagevec *pvec); | 25 | void pagevec_strip(struct pagevec *pvec); |
27 | unsigned pagevec_lookup(struct pagevec *pvec, struct address_space *mapping, | 26 | unsigned pagevec_lookup(struct pagevec *pvec, struct address_space *mapping, |
@@ -67,12 +66,6 @@ static inline void pagevec_release(struct pagevec *pvec) | |||
67 | __pagevec_release(pvec); | 66 | __pagevec_release(pvec); |
68 | } | 67 | } |
69 | 68 | ||
70 | static inline void pagevec_free(struct pagevec *pvec) | ||
71 | { | ||
72 | if (pagevec_count(pvec)) | ||
73 | __pagevec_free(pvec); | ||
74 | } | ||
75 | |||
76 | static inline void __pagevec_lru_add_anon(struct pagevec *pvec) | 69 | static inline void __pagevec_lru_add_anon(struct pagevec *pvec) |
77 | { | 70 | { |
78 | ____pagevec_lru_add(pvec, LRU_INACTIVE_ANON); | 71 | ____pagevec_lru_add(pvec, LRU_INACTIVE_ANON); |
diff --git a/include/linux/pid_namespace.h b/include/linux/pid_namespace.h index 38d10326246a..e7cf6669ac34 100644 --- a/include/linux/pid_namespace.h +++ b/include/linux/pid_namespace.h | |||
@@ -30,6 +30,8 @@ struct pid_namespace { | |||
30 | #ifdef CONFIG_BSD_PROCESS_ACCT | 30 | #ifdef CONFIG_BSD_PROCESS_ACCT |
31 | struct bsd_acct_struct *bacct; | 31 | struct bsd_acct_struct *bacct; |
32 | #endif | 32 | #endif |
33 | gid_t pid_gid; | ||
34 | int hide_pid; | ||
33 | }; | 35 | }; |
34 | 36 | ||
35 | extern struct pid_namespace init_pid_ns; | 37 | extern struct pid_namespace init_pid_ns; |
diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h index 6d9e575519cc..85c507306239 100644 --- a/include/linux/proc_fs.h +++ b/include/linux/proc_fs.h | |||
@@ -253,7 +253,7 @@ extern const struct proc_ns_operations utsns_operations; | |||
253 | extern const struct proc_ns_operations ipcns_operations; | 253 | extern const struct proc_ns_operations ipcns_operations; |
254 | 254 | ||
255 | union proc_op { | 255 | union proc_op { |
256 | int (*proc_get_link)(struct inode *, struct path *); | 256 | int (*proc_get_link)(struct dentry *, struct path *); |
257 | int (*proc_read)(struct task_struct *task, char *page); | 257 | int (*proc_read)(struct task_struct *task, char *page); |
258 | int (*proc_show)(struct seq_file *m, | 258 | int (*proc_show)(struct seq_file *m, |
259 | struct pid_namespace *ns, struct pid *pid, | 259 | struct pid_namespace *ns, struct pid *pid, |
diff --git a/include/linux/rmap.h b/include/linux/rmap.h index 2148b122779b..1afb9954bbf1 100644 --- a/include/linux/rmap.h +++ b/include/linux/rmap.h | |||
@@ -120,6 +120,7 @@ void anon_vma_init(void); /* create anon_vma_cachep */ | |||
120 | int anon_vma_prepare(struct vm_area_struct *); | 120 | int anon_vma_prepare(struct vm_area_struct *); |
121 | void unlink_anon_vmas(struct vm_area_struct *); | 121 | void unlink_anon_vmas(struct vm_area_struct *); |
122 | int anon_vma_clone(struct vm_area_struct *, struct vm_area_struct *); | 122 | int anon_vma_clone(struct vm_area_struct *, struct vm_area_struct *); |
123 | void anon_vma_moveto_tail(struct vm_area_struct *); | ||
123 | int anon_vma_fork(struct vm_area_struct *, struct vm_area_struct *); | 124 | int anon_vma_fork(struct vm_area_struct *, struct vm_area_struct *); |
124 | void __anon_vma_link(struct vm_area_struct *); | 125 | void __anon_vma_link(struct vm_area_struct *); |
125 | 126 | ||
diff --git a/include/linux/signal.h b/include/linux/signal.h index a822300a253b..7987ce74874b 100644 --- a/include/linux/signal.h +++ b/include/linux/signal.h | |||
@@ -254,6 +254,7 @@ extern void set_current_blocked(const sigset_t *); | |||
254 | extern int show_unhandled_signals; | 254 | extern int show_unhandled_signals; |
255 | 255 | ||
256 | extern int get_signal_to_deliver(siginfo_t *info, struct k_sigaction *return_ka, struct pt_regs *regs, void *cookie); | 256 | extern int get_signal_to_deliver(siginfo_t *info, struct k_sigaction *return_ka, struct pt_regs *regs, void *cookie); |
257 | extern void block_sigmask(struct k_sigaction *ka, int signr); | ||
257 | extern void exit_signals(struct task_struct *tsk); | 258 | extern void exit_signals(struct task_struct *tsk); |
258 | 259 | ||
259 | extern struct kmem_cache *sighand_cachep; | 260 | extern struct kmem_cache *sighand_cachep; |
diff --git a/include/linux/swap.h b/include/linux/swap.h index 1e22e126d2ac..06061a7f8e69 100644 --- a/include/linux/swap.h +++ b/include/linux/swap.h | |||
@@ -207,6 +207,7 @@ struct swap_list_t { | |||
207 | /* linux/mm/page_alloc.c */ | 207 | /* linux/mm/page_alloc.c */ |
208 | extern unsigned long totalram_pages; | 208 | extern unsigned long totalram_pages; |
209 | extern unsigned long totalreserve_pages; | 209 | extern unsigned long totalreserve_pages; |
210 | extern unsigned long dirty_balance_reserve; | ||
210 | extern unsigned int nr_free_buffer_pages(void); | 211 | extern unsigned int nr_free_buffer_pages(void); |
211 | extern unsigned int nr_free_pagecache_pages(void); | 212 | extern unsigned int nr_free_pagecache_pages(void); |
212 | 213 | ||
diff --git a/include/linux/workqueue.h b/include/linux/workqueue.h index 0d556deb497b..eb8b9f15f2e0 100644 --- a/include/linux/workqueue.h +++ b/include/linux/workqueue.h | |||
@@ -297,32 +297,50 @@ extern struct workqueue_struct *system_unbound_wq; | |||
297 | extern struct workqueue_struct *system_freezable_wq; | 297 | extern struct workqueue_struct *system_freezable_wq; |
298 | 298 | ||
299 | extern struct workqueue_struct * | 299 | extern struct workqueue_struct * |
300 | __alloc_workqueue_key(const char *name, unsigned int flags, int max_active, | 300 | __alloc_workqueue_key(const char *fmt, unsigned int flags, int max_active, |
301 | struct lock_class_key *key, const char *lock_name); | 301 | struct lock_class_key *key, const char *lock_name, ...) __printf(1, 6); |
302 | 302 | ||
303 | /** | ||
304 | * alloc_workqueue - allocate a workqueue | ||
305 | * @fmt: printf format for the name of the workqueue | ||
306 | * @flags: WQ_* flags | ||
307 | * @max_active: max in-flight work items, 0 for default | ||
308 | * @args: args for @fmt | ||
309 | * | ||
310 | * Allocate a workqueue with the specified parameters. For detailed | ||
311 | * information on WQ_* flags, please refer to Documentation/workqueue.txt. | ||
312 | * | ||
313 | * The __lock_name macro dance is to guarantee that single lock_class_key | ||
314 | * doesn't end up with different namesm, which isn't allowed by lockdep. | ||
315 | * | ||
316 | * RETURNS: | ||
317 | * Pointer to the allocated workqueue on success, %NULL on failure. | ||
318 | */ | ||
303 | #ifdef CONFIG_LOCKDEP | 319 | #ifdef CONFIG_LOCKDEP |
304 | #define alloc_workqueue(name, flags, max_active) \ | 320 | #define alloc_workqueue(fmt, flags, max_active, args...) \ |
305 | ({ \ | 321 | ({ \ |
306 | static struct lock_class_key __key; \ | 322 | static struct lock_class_key __key; \ |
307 | const char *__lock_name; \ | 323 | const char *__lock_name; \ |
308 | \ | 324 | \ |
309 | if (__builtin_constant_p(name)) \ | 325 | if (__builtin_constant_p(fmt)) \ |
310 | __lock_name = (name); \ | 326 | __lock_name = (fmt); \ |
311 | else \ | 327 | else \ |
312 | __lock_name = #name; \ | 328 | __lock_name = #fmt; \ |
313 | \ | 329 | \ |
314 | __alloc_workqueue_key((name), (flags), (max_active), \ | 330 | __alloc_workqueue_key((fmt), (flags), (max_active), \ |
315 | &__key, __lock_name); \ | 331 | &__key, __lock_name, ##args); \ |
316 | }) | 332 | }) |
317 | #else | 333 | #else |
318 | #define alloc_workqueue(name, flags, max_active) \ | 334 | #define alloc_workqueue(fmt, flags, max_active, args...) \ |
319 | __alloc_workqueue_key((name), (flags), (max_active), NULL, NULL) | 335 | __alloc_workqueue_key((fmt), (flags), (max_active), \ |
336 | NULL, NULL, ##args) | ||
320 | #endif | 337 | #endif |
321 | 338 | ||
322 | /** | 339 | /** |
323 | * alloc_ordered_workqueue - allocate an ordered workqueue | 340 | * alloc_ordered_workqueue - allocate an ordered workqueue |
324 | * @name: name of the workqueue | 341 | * @fmt: printf format for the name of the workqueue |
325 | * @flags: WQ_* flags (only WQ_FREEZABLE and WQ_MEM_RECLAIM are meaningful) | 342 | * @flags: WQ_* flags (only WQ_FREEZABLE and WQ_MEM_RECLAIM are meaningful) |
343 | * @args: args for @fmt | ||
326 | * | 344 | * |
327 | * Allocate an ordered workqueue. An ordered workqueue executes at | 345 | * Allocate an ordered workqueue. An ordered workqueue executes at |
328 | * most one work item at any given time in the queued order. They are | 346 | * most one work item at any given time in the queued order. They are |
@@ -331,11 +349,8 @@ __alloc_workqueue_key(const char *name, unsigned int flags, int max_active, | |||
331 | * RETURNS: | 349 | * RETURNS: |
332 | * Pointer to the allocated workqueue on success, %NULL on failure. | 350 | * Pointer to the allocated workqueue on success, %NULL on failure. |
333 | */ | 351 | */ |
334 | static inline struct workqueue_struct * | 352 | #define alloc_ordered_workqueue(fmt, flags, args...) \ |
335 | alloc_ordered_workqueue(const char *name, unsigned int flags) | 353 | alloc_workqueue(fmt, WQ_UNBOUND | (flags), 1, ##args) |
336 | { | ||
337 | return alloc_workqueue(name, WQ_UNBOUND | flags, 1); | ||
338 | } | ||
339 | 354 | ||
340 | #define create_workqueue(name) \ | 355 | #define create_workqueue(name) \ |
341 | alloc_workqueue((name), WQ_MEM_RECLAIM, 1) | 356 | alloc_workqueue((name), WQ_MEM_RECLAIM, 1) |
diff --git a/include/linux/writeback.h b/include/linux/writeback.h index a378c295851f..6dff47304971 100644 --- a/include/linux/writeback.h +++ b/include/linux/writeback.h | |||
@@ -124,6 +124,7 @@ void laptop_mode_timer_fn(unsigned long data); | |||
124 | static inline void laptop_sync_completion(void) { } | 124 | static inline void laptop_sync_completion(void) { } |
125 | #endif | 125 | #endif |
126 | void throttle_vm_writeout(gfp_t gfp_mask); | 126 | void throttle_vm_writeout(gfp_t gfp_mask); |
127 | bool zone_dirty_ok(struct zone *zone); | ||
127 | 128 | ||
128 | extern unsigned long global_dirty_limit; | 129 | extern unsigned long global_dirty_limit; |
129 | 130 | ||
@@ -138,8 +139,6 @@ extern int vm_highmem_is_dirtyable; | |||
138 | extern int block_dump; | 139 | extern int block_dump; |
139 | extern int laptop_mode; | 140 | extern int laptop_mode; |
140 | 141 | ||
141 | extern unsigned long determine_dirtyable_memory(void); | ||
142 | |||
143 | extern int dirty_background_ratio_handler(struct ctl_table *table, int write, | 142 | extern int dirty_background_ratio_handler(struct ctl_table *table, int write, |
144 | void __user *buffer, size_t *lenp, | 143 | void __user *buffer, size_t *lenp, |
145 | loff_t *ppos); | 144 | loff_t *ppos); |
diff --git a/include/trace/events/kmem.h b/include/trace/events/kmem.h index a9c87ad8331c..5f889f16b0c8 100644 --- a/include/trace/events/kmem.h +++ b/include/trace/events/kmem.h | |||
@@ -147,7 +147,7 @@ DEFINE_EVENT(kmem_free, kmem_cache_free, | |||
147 | TP_ARGS(call_site, ptr) | 147 | TP_ARGS(call_site, ptr) |
148 | ); | 148 | ); |
149 | 149 | ||
150 | TRACE_EVENT(mm_page_free_direct, | 150 | TRACE_EVENT(mm_page_free, |
151 | 151 | ||
152 | TP_PROTO(struct page *page, unsigned int order), | 152 | TP_PROTO(struct page *page, unsigned int order), |
153 | 153 | ||
@@ -169,7 +169,7 @@ TRACE_EVENT(mm_page_free_direct, | |||
169 | __entry->order) | 169 | __entry->order) |
170 | ); | 170 | ); |
171 | 171 | ||
172 | TRACE_EVENT(mm_pagevec_free, | 172 | TRACE_EVENT(mm_page_free_batched, |
173 | 173 | ||
174 | TP_PROTO(struct page *page, int cold), | 174 | TP_PROTO(struct page *page, int cold), |
175 | 175 | ||
diff --git a/include/trace/events/oom.h b/include/trace/events/oom.h new file mode 100644 index 000000000000..dd4ba3b92002 --- /dev/null +++ b/include/trace/events/oom.h | |||
@@ -0,0 +1,33 @@ | |||
1 | #undef TRACE_SYSTEM | ||
2 | #define TRACE_SYSTEM oom | ||
3 | |||
4 | #if !defined(_TRACE_OOM_H) || defined(TRACE_HEADER_MULTI_READ) | ||
5 | #define _TRACE_OOM_H | ||
6 | #include <linux/tracepoint.h> | ||
7 | |||
8 | TRACE_EVENT(oom_score_adj_update, | ||
9 | |||
10 | TP_PROTO(struct task_struct *task), | ||
11 | |||
12 | TP_ARGS(task), | ||
13 | |||
14 | TP_STRUCT__entry( | ||
15 | __field( pid_t, pid) | ||
16 | __array( char, comm, TASK_COMM_LEN ) | ||
17 | __field( int, oom_score_adj) | ||
18 | ), | ||
19 | |||
20 | TP_fast_assign( | ||
21 | __entry->pid = task->pid; | ||
22 | memcpy(__entry->comm, task->comm, TASK_COMM_LEN); | ||
23 | __entry->oom_score_adj = task->signal->oom_score_adj; | ||
24 | ), | ||
25 | |||
26 | TP_printk("pid=%d comm=%s oom_score_adj=%d", | ||
27 | __entry->pid, __entry->comm, __entry->oom_score_adj) | ||
28 | ); | ||
29 | |||
30 | #endif | ||
31 | |||
32 | /* This part must be outside protection */ | ||
33 | #include <trace/define_trace.h> | ||
diff --git a/include/trace/events/task.h b/include/trace/events/task.h new file mode 100644 index 000000000000..b53add02e929 --- /dev/null +++ b/include/trace/events/task.h | |||
@@ -0,0 +1,61 @@ | |||
1 | #undef TRACE_SYSTEM | ||
2 | #define TRACE_SYSTEM task | ||
3 | |||
4 | #if !defined(_TRACE_TASK_H) || defined(TRACE_HEADER_MULTI_READ) | ||
5 | #define _TRACE_TASK_H | ||
6 | #include <linux/tracepoint.h> | ||
7 | |||
8 | TRACE_EVENT(task_newtask, | ||
9 | |||
10 | TP_PROTO(struct task_struct *task, unsigned long clone_flags), | ||
11 | |||
12 | TP_ARGS(task, clone_flags), | ||
13 | |||
14 | TP_STRUCT__entry( | ||
15 | __field( pid_t, pid) | ||
16 | __array( char, comm, TASK_COMM_LEN) | ||
17 | __field( unsigned long, clone_flags) | ||
18 | __field( int, oom_score_adj) | ||
19 | ), | ||
20 | |||
21 | TP_fast_assign( | ||
22 | __entry->pid = task->pid; | ||
23 | memcpy(__entry->comm, task->comm, TASK_COMM_LEN); | ||
24 | __entry->clone_flags = clone_flags; | ||
25 | __entry->oom_score_adj = task->signal->oom_score_adj; | ||
26 | ), | ||
27 | |||
28 | TP_printk("pid=%d comm=%s clone_flags=%lx oom_score_adj=%d", | ||
29 | __entry->pid, __entry->comm, | ||
30 | __entry->clone_flags, __entry->oom_score_adj) | ||
31 | ); | ||
32 | |||
33 | TRACE_EVENT(task_rename, | ||
34 | |||
35 | TP_PROTO(struct task_struct *task, char *comm), | ||
36 | |||
37 | TP_ARGS(task, comm), | ||
38 | |||
39 | TP_STRUCT__entry( | ||
40 | __field( pid_t, pid) | ||
41 | __array( char, oldcomm, TASK_COMM_LEN) | ||
42 | __array( char, newcomm, TASK_COMM_LEN) | ||
43 | __field( int, oom_score_adj) | ||
44 | ), | ||
45 | |||
46 | TP_fast_assign( | ||
47 | __entry->pid = task->pid; | ||
48 | memcpy(entry->oldcomm, task->comm, TASK_COMM_LEN); | ||
49 | memcpy(entry->newcomm, comm, TASK_COMM_LEN); | ||
50 | __entry->oom_score_adj = task->signal->oom_score_adj; | ||
51 | ), | ||
52 | |||
53 | TP_printk("pid=%d oldcomm=%s newcomm=%s oom_score_adj=%d", | ||
54 | __entry->pid, __entry->oldcomm, | ||
55 | __entry->newcomm, __entry->oom_score_adj) | ||
56 | ); | ||
57 | |||
58 | #endif | ||
59 | |||
60 | /* This part must be outside protection */ | ||
61 | #include <trace/define_trace.h> | ||
diff --git a/ipc/mqueue.c b/ipc/mqueue.c index 9a142a290749..9b7c8ab7d75c 100644 --- a/ipc/mqueue.c +++ b/ipc/mqueue.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <linux/nsproxy.h> | 32 | #include <linux/nsproxy.h> |
33 | #include <linux/pid.h> | 33 | #include <linux/pid.h> |
34 | #include <linux/ipc_namespace.h> | 34 | #include <linux/ipc_namespace.h> |
35 | #include <linux/user_namespace.h> | ||
35 | #include <linux/slab.h> | 36 | #include <linux/slab.h> |
36 | 37 | ||
37 | #include <net/sock.h> | 38 | #include <net/sock.h> |
@@ -542,9 +543,13 @@ static void __do_notify(struct mqueue_inode_info *info) | |||
542 | sig_i.si_errno = 0; | 543 | sig_i.si_errno = 0; |
543 | sig_i.si_code = SI_MESGQ; | 544 | sig_i.si_code = SI_MESGQ; |
544 | sig_i.si_value = info->notify.sigev_value; | 545 | sig_i.si_value = info->notify.sigev_value; |
546 | /* map current pid/uid into info->owner's namespaces */ | ||
547 | rcu_read_lock(); | ||
545 | sig_i.si_pid = task_tgid_nr_ns(current, | 548 | sig_i.si_pid = task_tgid_nr_ns(current, |
546 | ns_of_pid(info->notify_owner)); | 549 | ns_of_pid(info->notify_owner)); |
547 | sig_i.si_uid = current_uid(); | 550 | sig_i.si_uid = user_ns_map_uid(info->user->user_ns, |
551 | current_cred(), current_uid()); | ||
552 | rcu_read_unlock(); | ||
548 | 553 | ||
549 | kill_pid_info(info->notify.sigev_signo, | 554 | kill_pid_info(info->notify.sigev_signo, |
550 | &sig_i, info->notify_owner); | 555 | &sig_i, info->notify_owner); |
diff --git a/kernel/fork.c b/kernel/fork.c index b00711ce7c13..5e1391b5ade0 100644 --- a/kernel/fork.c +++ b/kernel/fork.c | |||
@@ -76,6 +76,9 @@ | |||
76 | 76 | ||
77 | #include <trace/events/sched.h> | 77 | #include <trace/events/sched.h> |
78 | 78 | ||
79 | #define CREATE_TRACE_POINTS | ||
80 | #include <trace/events/task.h> | ||
81 | |||
79 | /* | 82 | /* |
80 | * Protected counters by write_lock_irq(&tasklist_lock) | 83 | * Protected counters by write_lock_irq(&tasklist_lock) |
81 | */ | 84 | */ |
@@ -1370,6 +1373,9 @@ static struct task_struct *copy_process(unsigned long clone_flags, | |||
1370 | if (clone_flags & CLONE_THREAD) | 1373 | if (clone_flags & CLONE_THREAD) |
1371 | threadgroup_change_end(current); | 1374 | threadgroup_change_end(current); |
1372 | perf_event_fork(p); | 1375 | perf_event_fork(p); |
1376 | |||
1377 | trace_task_newtask(p, clone_flags); | ||
1378 | |||
1373 | return p; | 1379 | return p; |
1374 | 1380 | ||
1375 | bad_fork_free_pid: | 1381 | bad_fork_free_pid: |
diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c index cbe2c1441392..1cf88900ec4f 100644 --- a/kernel/power/snapshot.c +++ b/kernel/power/snapshot.c | |||
@@ -858,6 +858,9 @@ static struct page *saveable_highmem_page(struct zone *zone, unsigned long pfn) | |||
858 | PageReserved(page)) | 858 | PageReserved(page)) |
859 | return NULL; | 859 | return NULL; |
860 | 860 | ||
861 | if (page_is_guard(page)) | ||
862 | return NULL; | ||
863 | |||
861 | return page; | 864 | return page; |
862 | } | 865 | } |
863 | 866 | ||
@@ -920,6 +923,9 @@ static struct page *saveable_page(struct zone *zone, unsigned long pfn) | |||
920 | && (!kernel_page_present(page) || pfn_is_nosave(pfn))) | 923 | && (!kernel_page_present(page) || pfn_is_nosave(pfn))) |
921 | return NULL; | 924 | return NULL; |
922 | 925 | ||
926 | if (page_is_guard(page)) | ||
927 | return NULL; | ||
928 | |||
923 | return page; | 929 | return page; |
924 | } | 930 | } |
925 | 931 | ||
diff --git a/kernel/signal.c b/kernel/signal.c index bb0efa5705ed..c73c4284160e 100644 --- a/kernel/signal.c +++ b/kernel/signal.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/freezer.h> | 28 | #include <linux/freezer.h> |
29 | #include <linux/pid_namespace.h> | 29 | #include <linux/pid_namespace.h> |
30 | #include <linux/nsproxy.h> | 30 | #include <linux/nsproxy.h> |
31 | #include <linux/user_namespace.h> | ||
31 | #define CREATE_TRACE_POINTS | 32 | #define CREATE_TRACE_POINTS |
32 | #include <trace/events/signal.h> | 33 | #include <trace/events/signal.h> |
33 | 34 | ||
@@ -1019,6 +1020,34 @@ static inline int legacy_queue(struct sigpending *signals, int sig) | |||
1019 | return (sig < SIGRTMIN) && sigismember(&signals->signal, sig); | 1020 | return (sig < SIGRTMIN) && sigismember(&signals->signal, sig); |
1020 | } | 1021 | } |
1021 | 1022 | ||
1023 | /* | ||
1024 | * map the uid in struct cred into user namespace *ns | ||
1025 | */ | ||
1026 | static inline uid_t map_cred_ns(const struct cred *cred, | ||
1027 | struct user_namespace *ns) | ||
1028 | { | ||
1029 | return user_ns_map_uid(ns, cred, cred->uid); | ||
1030 | } | ||
1031 | |||
1032 | #ifdef CONFIG_USER_NS | ||
1033 | static inline void userns_fixup_signal_uid(struct siginfo *info, struct task_struct *t) | ||
1034 | { | ||
1035 | if (current_user_ns() == task_cred_xxx(t, user_ns)) | ||
1036 | return; | ||
1037 | |||
1038 | if (SI_FROMKERNEL(info)) | ||
1039 | return; | ||
1040 | |||
1041 | info->si_uid = user_ns_map_uid(task_cred_xxx(t, user_ns), | ||
1042 | current_cred(), info->si_uid); | ||
1043 | } | ||
1044 | #else | ||
1045 | static inline void userns_fixup_signal_uid(struct siginfo *info, struct task_struct *t) | ||
1046 | { | ||
1047 | return; | ||
1048 | } | ||
1049 | #endif | ||
1050 | |||
1022 | static int __send_signal(int sig, struct siginfo *info, struct task_struct *t, | 1051 | static int __send_signal(int sig, struct siginfo *info, struct task_struct *t, |
1023 | int group, int from_ancestor_ns) | 1052 | int group, int from_ancestor_ns) |
1024 | { | 1053 | { |
@@ -1088,6 +1117,9 @@ static int __send_signal(int sig, struct siginfo *info, struct task_struct *t, | |||
1088 | q->info.si_pid = 0; | 1117 | q->info.si_pid = 0; |
1089 | break; | 1118 | break; |
1090 | } | 1119 | } |
1120 | |||
1121 | userns_fixup_signal_uid(&q->info, t); | ||
1122 | |||
1091 | } else if (!is_si_special(info)) { | 1123 | } else if (!is_si_special(info)) { |
1092 | if (sig >= SIGRTMIN && info->si_code != SI_USER) { | 1124 | if (sig >= SIGRTMIN && info->si_code != SI_USER) { |
1093 | /* | 1125 | /* |
@@ -1626,7 +1658,8 @@ bool do_notify_parent(struct task_struct *tsk, int sig) | |||
1626 | */ | 1658 | */ |
1627 | rcu_read_lock(); | 1659 | rcu_read_lock(); |
1628 | info.si_pid = task_pid_nr_ns(tsk, tsk->parent->nsproxy->pid_ns); | 1660 | info.si_pid = task_pid_nr_ns(tsk, tsk->parent->nsproxy->pid_ns); |
1629 | info.si_uid = __task_cred(tsk)->uid; | 1661 | info.si_uid = map_cred_ns(__task_cred(tsk), |
1662 | task_cred_xxx(tsk->parent, user_ns)); | ||
1630 | rcu_read_unlock(); | 1663 | rcu_read_unlock(); |
1631 | 1664 | ||
1632 | info.si_utime = cputime_to_clock_t(tsk->utime + tsk->signal->utime); | 1665 | info.si_utime = cputime_to_clock_t(tsk->utime + tsk->signal->utime); |
@@ -1709,7 +1742,8 @@ static void do_notify_parent_cldstop(struct task_struct *tsk, | |||
1709 | */ | 1742 | */ |
1710 | rcu_read_lock(); | 1743 | rcu_read_lock(); |
1711 | info.si_pid = task_pid_nr_ns(tsk, parent->nsproxy->pid_ns); | 1744 | info.si_pid = task_pid_nr_ns(tsk, parent->nsproxy->pid_ns); |
1712 | info.si_uid = __task_cred(tsk)->uid; | 1745 | info.si_uid = map_cred_ns(__task_cred(tsk), |
1746 | task_cred_xxx(parent, user_ns)); | ||
1713 | rcu_read_unlock(); | 1747 | rcu_read_unlock(); |
1714 | 1748 | ||
1715 | info.si_utime = cputime_to_clock_t(tsk->utime); | 1749 | info.si_utime = cputime_to_clock_t(tsk->utime); |
@@ -2125,8 +2159,11 @@ static int ptrace_signal(int signr, siginfo_t *info, | |||
2125 | info->si_signo = signr; | 2159 | info->si_signo = signr; |
2126 | info->si_errno = 0; | 2160 | info->si_errno = 0; |
2127 | info->si_code = SI_USER; | 2161 | info->si_code = SI_USER; |
2162 | rcu_read_lock(); | ||
2128 | info->si_pid = task_pid_vnr(current->parent); | 2163 | info->si_pid = task_pid_vnr(current->parent); |
2129 | info->si_uid = task_uid(current->parent); | 2164 | info->si_uid = map_cred_ns(__task_cred(current->parent), |
2165 | current_user_ns()); | ||
2166 | rcu_read_unlock(); | ||
2130 | } | 2167 | } |
2131 | 2168 | ||
2132 | /* If the (new) signal is now blocked, requeue it. */ | 2169 | /* If the (new) signal is now blocked, requeue it. */ |
@@ -2318,6 +2355,27 @@ relock: | |||
2318 | return signr; | 2355 | return signr; |
2319 | } | 2356 | } |
2320 | 2357 | ||
2358 | /** | ||
2359 | * block_sigmask - add @ka's signal mask to current->blocked | ||
2360 | * @ka: action for @signr | ||
2361 | * @signr: signal that has been successfully delivered | ||
2362 | * | ||
2363 | * This function should be called when a signal has succesfully been | ||
2364 | * delivered. It adds the mask of signals for @ka to current->blocked | ||
2365 | * so that they are blocked during the execution of the signal | ||
2366 | * handler. In addition, @signr will be blocked unless %SA_NODEFER is | ||
2367 | * set in @ka->sa.sa_flags. | ||
2368 | */ | ||
2369 | void block_sigmask(struct k_sigaction *ka, int signr) | ||
2370 | { | ||
2371 | sigset_t blocked; | ||
2372 | |||
2373 | sigorsets(&blocked, ¤t->blocked, &ka->sa.sa_mask); | ||
2374 | if (!(ka->sa.sa_flags & SA_NODEFER)) | ||
2375 | sigaddset(&blocked, signr); | ||
2376 | set_current_blocked(&blocked); | ||
2377 | } | ||
2378 | |||
2321 | /* | 2379 | /* |
2322 | * It could be that complete_signal() picked us to notify about the | 2380 | * It could be that complete_signal() picked us to notify about the |
2323 | * group-wide signal. Other threads should be notified now to take | 2381 | * group-wide signal. Other threads should be notified now to take |
diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 42fa9ad0a810..bec7b5b53e03 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c | |||
@@ -242,10 +242,10 @@ struct workqueue_struct { | |||
242 | 242 | ||
243 | int nr_drainers; /* W: drain in progress */ | 243 | int nr_drainers; /* W: drain in progress */ |
244 | int saved_max_active; /* W: saved cwq max_active */ | 244 | int saved_max_active; /* W: saved cwq max_active */ |
245 | const char *name; /* I: workqueue name */ | ||
246 | #ifdef CONFIG_LOCKDEP | 245 | #ifdef CONFIG_LOCKDEP |
247 | struct lockdep_map lockdep_map; | 246 | struct lockdep_map lockdep_map; |
248 | #endif | 247 | #endif |
248 | char name[]; /* I: workqueue name */ | ||
249 | }; | 249 | }; |
250 | 250 | ||
251 | struct workqueue_struct *system_wq __read_mostly; | 251 | struct workqueue_struct *system_wq __read_mostly; |
@@ -2954,14 +2954,29 @@ static int wq_clamp_max_active(int max_active, unsigned int flags, | |||
2954 | return clamp_val(max_active, 1, lim); | 2954 | return clamp_val(max_active, 1, lim); |
2955 | } | 2955 | } |
2956 | 2956 | ||
2957 | struct workqueue_struct *__alloc_workqueue_key(const char *name, | 2957 | struct workqueue_struct *__alloc_workqueue_key(const char *fmt, |
2958 | unsigned int flags, | 2958 | unsigned int flags, |
2959 | int max_active, | 2959 | int max_active, |
2960 | struct lock_class_key *key, | 2960 | struct lock_class_key *key, |
2961 | const char *lock_name) | 2961 | const char *lock_name, ...) |
2962 | { | 2962 | { |
2963 | va_list args, args1; | ||
2963 | struct workqueue_struct *wq; | 2964 | struct workqueue_struct *wq; |
2964 | unsigned int cpu; | 2965 | unsigned int cpu; |
2966 | size_t namelen; | ||
2967 | |||
2968 | /* determine namelen, allocate wq and format name */ | ||
2969 | va_start(args, lock_name); | ||
2970 | va_copy(args1, args); | ||
2971 | namelen = vsnprintf(NULL, 0, fmt, args) + 1; | ||
2972 | |||
2973 | wq = kzalloc(sizeof(*wq) + namelen, GFP_KERNEL); | ||
2974 | if (!wq) | ||
2975 | goto err; | ||
2976 | |||
2977 | vsnprintf(wq->name, namelen, fmt, args1); | ||
2978 | va_end(args); | ||
2979 | va_end(args1); | ||
2965 | 2980 | ||
2966 | /* | 2981 | /* |
2967 | * Workqueues which may be used during memory reclaim should | 2982 | * Workqueues which may be used during memory reclaim should |
@@ -2978,12 +2993,9 @@ struct workqueue_struct *__alloc_workqueue_key(const char *name, | |||
2978 | flags |= WQ_HIGHPRI; | 2993 | flags |= WQ_HIGHPRI; |
2979 | 2994 | ||
2980 | max_active = max_active ?: WQ_DFL_ACTIVE; | 2995 | max_active = max_active ?: WQ_DFL_ACTIVE; |
2981 | max_active = wq_clamp_max_active(max_active, flags, name); | 2996 | max_active = wq_clamp_max_active(max_active, flags, wq->name); |
2982 | |||
2983 | wq = kzalloc(sizeof(*wq), GFP_KERNEL); | ||
2984 | if (!wq) | ||
2985 | goto err; | ||
2986 | 2997 | ||
2998 | /* init wq */ | ||
2987 | wq->flags = flags; | 2999 | wq->flags = flags; |
2988 | wq->saved_max_active = max_active; | 3000 | wq->saved_max_active = max_active; |
2989 | mutex_init(&wq->flush_mutex); | 3001 | mutex_init(&wq->flush_mutex); |
@@ -2991,7 +3003,6 @@ struct workqueue_struct *__alloc_workqueue_key(const char *name, | |||
2991 | INIT_LIST_HEAD(&wq->flusher_queue); | 3003 | INIT_LIST_HEAD(&wq->flusher_queue); |
2992 | INIT_LIST_HEAD(&wq->flusher_overflow); | 3004 | INIT_LIST_HEAD(&wq->flusher_overflow); |
2993 | 3005 | ||
2994 | wq->name = name; | ||
2995 | lockdep_init_map(&wq->lockdep_map, lock_name, key, 0); | 3006 | lockdep_init_map(&wq->lockdep_map, lock_name, key, 0); |
2996 | INIT_LIST_HEAD(&wq->list); | 3007 | INIT_LIST_HEAD(&wq->list); |
2997 | 3008 | ||
@@ -3020,7 +3031,8 @@ struct workqueue_struct *__alloc_workqueue_key(const char *name, | |||
3020 | if (!rescuer) | 3031 | if (!rescuer) |
3021 | goto err; | 3032 | goto err; |
3022 | 3033 | ||
3023 | rescuer->task = kthread_create(rescuer_thread, wq, "%s", name); | 3034 | rescuer->task = kthread_create(rescuer_thread, wq, "%s", |
3035 | wq->name); | ||
3024 | if (IS_ERR(rescuer->task)) | 3036 | if (IS_ERR(rescuer->task)) |
3025 | goto err; | 3037 | goto err; |
3026 | 3038 | ||
diff --git a/lib/btree.c b/lib/btree.c index 2a34392bcecc..e5ec1e9c1aa5 100644 --- a/lib/btree.c +++ b/lib/btree.c | |||
@@ -357,6 +357,7 @@ miss: | |||
357 | } | 357 | } |
358 | return NULL; | 358 | return NULL; |
359 | } | 359 | } |
360 | EXPORT_SYMBOL_GPL(btree_get_prev); | ||
360 | 361 | ||
361 | static int getpos(struct btree_geo *geo, unsigned long *node, | 362 | static int getpos(struct btree_geo *geo, unsigned long *node, |
362 | unsigned long *key) | 363 | unsigned long *key) |
diff --git a/lib/crc32.c b/lib/crc32.c index a6e633a48cea..4b35d2b4437c 100644 --- a/lib/crc32.c +++ b/lib/crc32.c | |||
@@ -51,20 +51,21 @@ static inline u32 | |||
51 | crc32_body(u32 crc, unsigned char const *buf, size_t len, const u32 (*tab)[256]) | 51 | crc32_body(u32 crc, unsigned char const *buf, size_t len, const u32 (*tab)[256]) |
52 | { | 52 | { |
53 | # ifdef __LITTLE_ENDIAN | 53 | # ifdef __LITTLE_ENDIAN |
54 | # define DO_CRC(x) crc = tab[0][(crc ^ (x)) & 255] ^ (crc >> 8) | 54 | # define DO_CRC(x) crc = t0[(crc ^ (x)) & 255] ^ (crc >> 8) |
55 | # define DO_CRC4 crc = tab[3][(crc) & 255] ^ \ | 55 | # define DO_CRC4 crc = t3[(crc) & 255] ^ \ |
56 | tab[2][(crc >> 8) & 255] ^ \ | 56 | t2[(crc >> 8) & 255] ^ \ |
57 | tab[1][(crc >> 16) & 255] ^ \ | 57 | t1[(crc >> 16) & 255] ^ \ |
58 | tab[0][(crc >> 24) & 255] | 58 | t0[(crc >> 24) & 255] |
59 | # else | 59 | # else |
60 | # define DO_CRC(x) crc = tab[0][((crc >> 24) ^ (x)) & 255] ^ (crc << 8) | 60 | # define DO_CRC(x) crc = t0[((crc >> 24) ^ (x)) & 255] ^ (crc << 8) |
61 | # define DO_CRC4 crc = tab[0][(crc) & 255] ^ \ | 61 | # define DO_CRC4 crc = t0[(crc) & 255] ^ \ |
62 | tab[1][(crc >> 8) & 255] ^ \ | 62 | t1[(crc >> 8) & 255] ^ \ |
63 | tab[2][(crc >> 16) & 255] ^ \ | 63 | t2[(crc >> 16) & 255] ^ \ |
64 | tab[3][(crc >> 24) & 255] | 64 | t3[(crc >> 24) & 255] |
65 | # endif | 65 | # endif |
66 | const u32 *b; | 66 | const u32 *b; |
67 | size_t rem_len; | 67 | size_t rem_len; |
68 | const u32 *t0=tab[0], *t1=tab[1], *t2=tab[2], *t3=tab[3]; | ||
68 | 69 | ||
69 | /* Align it */ | 70 | /* Align it */ |
70 | if (unlikely((long)buf & 3 && len)) { | 71 | if (unlikely((long)buf & 3 && len)) { |
diff --git a/mm/Kconfig.debug b/mm/Kconfig.debug index 8b1a477162dc..4b2443254de2 100644 --- a/mm/Kconfig.debug +++ b/mm/Kconfig.debug | |||
@@ -4,6 +4,7 @@ config DEBUG_PAGEALLOC | |||
4 | depends on !HIBERNATION || ARCH_SUPPORTS_DEBUG_PAGEALLOC && !PPC && !SPARC | 4 | depends on !HIBERNATION || ARCH_SUPPORTS_DEBUG_PAGEALLOC && !PPC && !SPARC |
5 | depends on !KMEMCHECK | 5 | depends on !KMEMCHECK |
6 | select PAGE_POISONING if !ARCH_SUPPORTS_DEBUG_PAGEALLOC | 6 | select PAGE_POISONING if !ARCH_SUPPORTS_DEBUG_PAGEALLOC |
7 | select PAGE_GUARD if ARCH_SUPPORTS_DEBUG_PAGEALLOC | ||
7 | ---help--- | 8 | ---help--- |
8 | Unmap pages from the kernel linear mapping after free_pages(). | 9 | Unmap pages from the kernel linear mapping after free_pages(). |
9 | This results in a large slowdown, but helps to find certain types | 10 | This results in a large slowdown, but helps to find certain types |
@@ -22,3 +23,7 @@ config WANT_PAGE_DEBUG_FLAGS | |||
22 | config PAGE_POISONING | 23 | config PAGE_POISONING |
23 | bool | 24 | bool |
24 | select WANT_PAGE_DEBUG_FLAGS | 25 | select WANT_PAGE_DEBUG_FLAGS |
26 | |||
27 | config PAGE_GUARD | ||
28 | bool | ||
29 | select WANT_PAGE_DEBUG_FLAGS | ||
diff --git a/mm/bootmem.c b/mm/bootmem.c index 1a77012ecdb3..668e94df8cf2 100644 --- a/mm/bootmem.c +++ b/mm/bootmem.c | |||
@@ -56,7 +56,7 @@ early_param("bootmem_debug", bootmem_debug_setup); | |||
56 | 56 | ||
57 | static unsigned long __init bootmap_bytes(unsigned long pages) | 57 | static unsigned long __init bootmap_bytes(unsigned long pages) |
58 | { | 58 | { |
59 | unsigned long bytes = (pages + 7) / 8; | 59 | unsigned long bytes = DIV_ROUND_UP(pages, 8); |
60 | 60 | ||
61 | return ALIGN(bytes, sizeof(long)); | 61 | return ALIGN(bytes, sizeof(long)); |
62 | } | 62 | } |
@@ -171,7 +171,6 @@ void __init free_bootmem_late(unsigned long addr, unsigned long size) | |||
171 | 171 | ||
172 | static unsigned long __init free_all_bootmem_core(bootmem_data_t *bdata) | 172 | static unsigned long __init free_all_bootmem_core(bootmem_data_t *bdata) |
173 | { | 173 | { |
174 | int aligned; | ||
175 | struct page *page; | 174 | struct page *page; |
176 | unsigned long start, end, pages, count = 0; | 175 | unsigned long start, end, pages, count = 0; |
177 | 176 | ||
@@ -181,14 +180,8 @@ static unsigned long __init free_all_bootmem_core(bootmem_data_t *bdata) | |||
181 | start = bdata->node_min_pfn; | 180 | start = bdata->node_min_pfn; |
182 | end = bdata->node_low_pfn; | 181 | end = bdata->node_low_pfn; |
183 | 182 | ||
184 | /* | 183 | bdebug("nid=%td start=%lx end=%lx\n", |
185 | * If the start is aligned to the machines wordsize, we might | 184 | bdata - bootmem_node_data, start, end); |
186 | * be able to free pages in bulks of that order. | ||
187 | */ | ||
188 | aligned = !(start & (BITS_PER_LONG - 1)); | ||
189 | |||
190 | bdebug("nid=%td start=%lx end=%lx aligned=%d\n", | ||
191 | bdata - bootmem_node_data, start, end, aligned); | ||
192 | 185 | ||
193 | while (start < end) { | 186 | while (start < end) { |
194 | unsigned long *map, idx, vec; | 187 | unsigned long *map, idx, vec; |
@@ -196,12 +189,17 @@ static unsigned long __init free_all_bootmem_core(bootmem_data_t *bdata) | |||
196 | map = bdata->node_bootmem_map; | 189 | map = bdata->node_bootmem_map; |
197 | idx = start - bdata->node_min_pfn; | 190 | idx = start - bdata->node_min_pfn; |
198 | vec = ~map[idx / BITS_PER_LONG]; | 191 | vec = ~map[idx / BITS_PER_LONG]; |
199 | 192 | /* | |
200 | if (aligned && vec == ~0UL && start + BITS_PER_LONG < end) { | 193 | * If we have a properly aligned and fully unreserved |
194 | * BITS_PER_LONG block of pages in front of us, free | ||
195 | * it in one go. | ||
196 | */ | ||
197 | if (IS_ALIGNED(start, BITS_PER_LONG) && vec == ~0UL) { | ||
201 | int order = ilog2(BITS_PER_LONG); | 198 | int order = ilog2(BITS_PER_LONG); |
202 | 199 | ||
203 | __free_pages_bootmem(pfn_to_page(start), order); | 200 | __free_pages_bootmem(pfn_to_page(start), order); |
204 | count += BITS_PER_LONG; | 201 | count += BITS_PER_LONG; |
202 | start += BITS_PER_LONG; | ||
205 | } else { | 203 | } else { |
206 | unsigned long off = 0; | 204 | unsigned long off = 0; |
207 | 205 | ||
@@ -214,8 +212,8 @@ static unsigned long __init free_all_bootmem_core(bootmem_data_t *bdata) | |||
214 | vec >>= 1; | 212 | vec >>= 1; |
215 | off++; | 213 | off++; |
216 | } | 214 | } |
215 | start = ALIGN(start + 1, BITS_PER_LONG); | ||
217 | } | 216 | } |
218 | start += BITS_PER_LONG; | ||
219 | } | 217 | } |
220 | 218 | ||
221 | page = virt_to_page(bdata->node_bootmem_map); | 219 | page = virt_to_page(bdata->node_bootmem_map); |
diff --git a/mm/compaction.c b/mm/compaction.c index 1253d7ac332b..e6670c34eb49 100644 --- a/mm/compaction.c +++ b/mm/compaction.c | |||
@@ -365,8 +365,10 @@ static isolate_migrate_t isolate_migratepages(struct zone *zone, | |||
365 | nr_isolated++; | 365 | nr_isolated++; |
366 | 366 | ||
367 | /* Avoid isolating too much */ | 367 | /* Avoid isolating too much */ |
368 | if (cc->nr_migratepages == COMPACT_CLUSTER_MAX) | 368 | if (cc->nr_migratepages == COMPACT_CLUSTER_MAX) { |
369 | ++low_pfn; | ||
369 | break; | 370 | break; |
371 | } | ||
370 | } | 372 | } |
371 | 373 | ||
372 | acct_isolated(zone, cc); | 374 | acct_isolated(zone, cc); |
diff --git a/mm/fadvise.c b/mm/fadvise.c index 8d723c9e8b75..469491e0af79 100644 --- a/mm/fadvise.c +++ b/mm/fadvise.c | |||
@@ -117,7 +117,8 @@ SYSCALL_DEFINE(fadvise64_64)(int fd, loff_t offset, loff_t len, int advice) | |||
117 | break; | 117 | break; |
118 | case POSIX_FADV_DONTNEED: | 118 | case POSIX_FADV_DONTNEED: |
119 | if (!bdi_write_congested(mapping->backing_dev_info)) | 119 | if (!bdi_write_congested(mapping->backing_dev_info)) |
120 | filemap_flush(mapping); | 120 | __filemap_fdatawrite_range(mapping, offset, endbyte, |
121 | WB_SYNC_NONE); | ||
121 | 122 | ||
122 | /* First and last FULL page! */ | 123 | /* First and last FULL page! */ |
123 | start_index = (offset+(PAGE_CACHE_SIZE-1)) >> PAGE_CACHE_SHIFT; | 124 | start_index = (offset+(PAGE_CACHE_SIZE-1)) >> PAGE_CACHE_SHIFT; |
diff --git a/mm/filemap.c b/mm/filemap.c index a0701e6eec10..c4ee2e918bea 100644 --- a/mm/filemap.c +++ b/mm/filemap.c | |||
@@ -2351,8 +2351,11 @@ struct page *grab_cache_page_write_begin(struct address_space *mapping, | |||
2351 | pgoff_t index, unsigned flags) | 2351 | pgoff_t index, unsigned flags) |
2352 | { | 2352 | { |
2353 | int status; | 2353 | int status; |
2354 | gfp_t gfp_mask; | ||
2354 | struct page *page; | 2355 | struct page *page; |
2355 | gfp_t gfp_notmask = 0; | 2356 | gfp_t gfp_notmask = 0; |
2357 | |||
2358 | gfp_mask = mapping_gfp_mask(mapping) | __GFP_WRITE; | ||
2356 | if (flags & AOP_FLAG_NOFS) | 2359 | if (flags & AOP_FLAG_NOFS) |
2357 | gfp_notmask = __GFP_FS; | 2360 | gfp_notmask = __GFP_FS; |
2358 | repeat: | 2361 | repeat: |
@@ -2360,7 +2363,7 @@ repeat: | |||
2360 | if (page) | 2363 | if (page) |
2361 | goto found; | 2364 | goto found; |
2362 | 2365 | ||
2363 | page = __page_cache_alloc(mapping_gfp_mask(mapping) & ~gfp_notmask); | 2366 | page = __page_cache_alloc(gfp_mask & ~gfp_notmask); |
2364 | if (!page) | 2367 | if (!page) |
2365 | return NULL; | 2368 | return NULL; |
2366 | status = add_to_page_cache_lru(page, mapping, index, | 2369 | status = add_to_page_cache_lru(page, mapping, index, |
diff --git a/mm/hugetlb.c b/mm/hugetlb.c index 7acd12503f73..ea8c3a4cd2ae 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c | |||
@@ -800,7 +800,7 @@ static struct page *alloc_buddy_huge_page(struct hstate *h, int nid) | |||
800 | 800 | ||
801 | if (page && arch_prepare_hugepage(page)) { | 801 | if (page && arch_prepare_hugepage(page)) { |
802 | __free_pages(page, huge_page_order(h)); | 802 | __free_pages(page, huge_page_order(h)); |
803 | return NULL; | 803 | page = NULL; |
804 | } | 804 | } |
805 | 805 | ||
806 | spin_lock(&hugetlb_lock); | 806 | spin_lock(&hugetlb_lock); |
@@ -2315,8 +2315,7 @@ static int unmap_ref_private(struct mm_struct *mm, struct vm_area_struct *vma, | |||
2315 | * from page cache lookup which is in HPAGE_SIZE units. | 2315 | * from page cache lookup which is in HPAGE_SIZE units. |
2316 | */ | 2316 | */ |
2317 | address = address & huge_page_mask(h); | 2317 | address = address & huge_page_mask(h); |
2318 | pgoff = ((address - vma->vm_start) >> PAGE_SHIFT) | 2318 | pgoff = vma_hugecache_offset(h, vma, address); |
2319 | + (vma->vm_pgoff >> PAGE_SHIFT); | ||
2320 | mapping = (struct address_space *)page_private(page); | 2319 | mapping = (struct address_space *)page_private(page); |
2321 | 2320 | ||
2322 | /* | 2321 | /* |
@@ -2349,6 +2348,9 @@ static int unmap_ref_private(struct mm_struct *mm, struct vm_area_struct *vma, | |||
2349 | 2348 | ||
2350 | /* | 2349 | /* |
2351 | * Hugetlb_cow() should be called with page lock of the original hugepage held. | 2350 | * Hugetlb_cow() should be called with page lock of the original hugepage held. |
2351 | * Called with hugetlb_instantiation_mutex held and pte_page locked so we | ||
2352 | * cannot race with other handlers or page migration. | ||
2353 | * Keep the pte_same checks anyway to make transition from the mutex easier. | ||
2352 | */ | 2354 | */ |
2353 | static int hugetlb_cow(struct mm_struct *mm, struct vm_area_struct *vma, | 2355 | static int hugetlb_cow(struct mm_struct *mm, struct vm_area_struct *vma, |
2354 | unsigned long address, pte_t *ptep, pte_t pte, | 2356 | unsigned long address, pte_t *ptep, pte_t pte, |
@@ -2408,7 +2410,14 @@ retry_avoidcopy: | |||
2408 | BUG_ON(page_count(old_page) != 1); | 2410 | BUG_ON(page_count(old_page) != 1); |
2409 | BUG_ON(huge_pte_none(pte)); | 2411 | BUG_ON(huge_pte_none(pte)); |
2410 | spin_lock(&mm->page_table_lock); | 2412 | spin_lock(&mm->page_table_lock); |
2411 | goto retry_avoidcopy; | 2413 | ptep = huge_pte_offset(mm, address & huge_page_mask(h)); |
2414 | if (likely(pte_same(huge_ptep_get(ptep), pte))) | ||
2415 | goto retry_avoidcopy; | ||
2416 | /* | ||
2417 | * race occurs while re-acquiring page_table_lock, and | ||
2418 | * our job is done. | ||
2419 | */ | ||
2420 | return 0; | ||
2412 | } | 2421 | } |
2413 | WARN_ON_ONCE(1); | 2422 | WARN_ON_ONCE(1); |
2414 | } | 2423 | } |
@@ -2630,6 +2639,8 @@ int hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma, | |||
2630 | static DEFINE_MUTEX(hugetlb_instantiation_mutex); | 2639 | static DEFINE_MUTEX(hugetlb_instantiation_mutex); |
2631 | struct hstate *h = hstate_vma(vma); | 2640 | struct hstate *h = hstate_vma(vma); |
2632 | 2641 | ||
2642 | address &= huge_page_mask(h); | ||
2643 | |||
2633 | ptep = huge_pte_offset(mm, address); | 2644 | ptep = huge_pte_offset(mm, address); |
2634 | if (ptep) { | 2645 | if (ptep) { |
2635 | entry = huge_ptep_get(ptep); | 2646 | entry = huge_ptep_get(ptep); |
diff --git a/mm/mempolicy.c b/mm/mempolicy.c index c3fdbcb17658..e3d58f088466 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c | |||
@@ -1983,28 +1983,28 @@ struct mempolicy *__mpol_cond_copy(struct mempolicy *tompol, | |||
1983 | } | 1983 | } |
1984 | 1984 | ||
1985 | /* Slow path of a mempolicy comparison */ | 1985 | /* Slow path of a mempolicy comparison */ |
1986 | int __mpol_equal(struct mempolicy *a, struct mempolicy *b) | 1986 | bool __mpol_equal(struct mempolicy *a, struct mempolicy *b) |
1987 | { | 1987 | { |
1988 | if (!a || !b) | 1988 | if (!a || !b) |
1989 | return 0; | 1989 | return false; |
1990 | if (a->mode != b->mode) | 1990 | if (a->mode != b->mode) |
1991 | return 0; | 1991 | return false; |
1992 | if (a->flags != b->flags) | 1992 | if (a->flags != b->flags) |
1993 | return 0; | 1993 | return false; |
1994 | if (mpol_store_user_nodemask(a)) | 1994 | if (mpol_store_user_nodemask(a)) |
1995 | if (!nodes_equal(a->w.user_nodemask, b->w.user_nodemask)) | 1995 | if (!nodes_equal(a->w.user_nodemask, b->w.user_nodemask)) |
1996 | return 0; | 1996 | return false; |
1997 | 1997 | ||
1998 | switch (a->mode) { | 1998 | switch (a->mode) { |
1999 | case MPOL_BIND: | 1999 | case MPOL_BIND: |
2000 | /* Fall through */ | 2000 | /* Fall through */ |
2001 | case MPOL_INTERLEAVE: | 2001 | case MPOL_INTERLEAVE: |
2002 | return nodes_equal(a->v.nodes, b->v.nodes); | 2002 | return !!nodes_equal(a->v.nodes, b->v.nodes); |
2003 | case MPOL_PREFERRED: | 2003 | case MPOL_PREFERRED: |
2004 | return a->v.preferred_node == b->v.preferred_node; | 2004 | return a->v.preferred_node == b->v.preferred_node; |
2005 | default: | 2005 | default: |
2006 | BUG(); | 2006 | BUG(); |
2007 | return 0; | 2007 | return false; |
2008 | } | 2008 | } |
2009 | } | 2009 | } |
2010 | 2010 | ||
diff --git a/mm/mempool.c b/mm/mempool.c index e73641b79bb5..d9049811f352 100644 --- a/mm/mempool.c +++ b/mm/mempool.c | |||
@@ -27,7 +27,15 @@ static void *remove_element(mempool_t *pool) | |||
27 | return pool->elements[--pool->curr_nr]; | 27 | return pool->elements[--pool->curr_nr]; |
28 | } | 28 | } |
29 | 29 | ||
30 | static void free_pool(mempool_t *pool) | 30 | /** |
31 | * mempool_destroy - deallocate a memory pool | ||
32 | * @pool: pointer to the memory pool which was allocated via | ||
33 | * mempool_create(). | ||
34 | * | ||
35 | * Free all reserved elements in @pool and @pool itself. This function | ||
36 | * only sleeps if the free_fn() function sleeps. | ||
37 | */ | ||
38 | void mempool_destroy(mempool_t *pool) | ||
31 | { | 39 | { |
32 | while (pool->curr_nr) { | 40 | while (pool->curr_nr) { |
33 | void *element = remove_element(pool); | 41 | void *element = remove_element(pool); |
@@ -36,6 +44,7 @@ static void free_pool(mempool_t *pool) | |||
36 | kfree(pool->elements); | 44 | kfree(pool->elements); |
37 | kfree(pool); | 45 | kfree(pool); |
38 | } | 46 | } |
47 | EXPORT_SYMBOL(mempool_destroy); | ||
39 | 48 | ||
40 | /** | 49 | /** |
41 | * mempool_create - create a memory pool | 50 | * mempool_create - create a memory pool |
@@ -86,7 +95,7 @@ mempool_t *mempool_create_node(int min_nr, mempool_alloc_t *alloc_fn, | |||
86 | 95 | ||
87 | element = pool->alloc(GFP_KERNEL, pool->pool_data); | 96 | element = pool->alloc(GFP_KERNEL, pool->pool_data); |
88 | if (unlikely(!element)) { | 97 | if (unlikely(!element)) { |
89 | free_pool(pool); | 98 | mempool_destroy(pool); |
90 | return NULL; | 99 | return NULL; |
91 | } | 100 | } |
92 | add_element(pool, element); | 101 | add_element(pool, element); |
@@ -172,23 +181,6 @@ out: | |||
172 | EXPORT_SYMBOL(mempool_resize); | 181 | EXPORT_SYMBOL(mempool_resize); |
173 | 182 | ||
174 | /** | 183 | /** |
175 | * mempool_destroy - deallocate a memory pool | ||
176 | * @pool: pointer to the memory pool which was allocated via | ||
177 | * mempool_create(). | ||
178 | * | ||
179 | * this function only sleeps if the free_fn() function sleeps. The caller | ||
180 | * has to guarantee that all elements have been returned to the pool (ie: | ||
181 | * freed) prior to calling mempool_destroy(). | ||
182 | */ | ||
183 | void mempool_destroy(mempool_t *pool) | ||
184 | { | ||
185 | /* Check for outstanding elements */ | ||
186 | BUG_ON(pool->curr_nr != pool->min_nr); | ||
187 | free_pool(pool); | ||
188 | } | ||
189 | EXPORT_SYMBOL(mempool_destroy); | ||
190 | |||
191 | /** | ||
192 | * mempool_alloc - allocate an element from a specific memory pool | 184 | * mempool_alloc - allocate an element from a specific memory pool |
193 | * @pool: pointer to the memory pool which was allocated via | 185 | * @pool: pointer to the memory pool which was allocated via |
194 | * mempool_create(). | 186 | * mempool_create(). |
@@ -224,28 +216,40 @@ repeat_alloc: | |||
224 | if (likely(pool->curr_nr)) { | 216 | if (likely(pool->curr_nr)) { |
225 | element = remove_element(pool); | 217 | element = remove_element(pool); |
226 | spin_unlock_irqrestore(&pool->lock, flags); | 218 | spin_unlock_irqrestore(&pool->lock, flags); |
219 | /* paired with rmb in mempool_free(), read comment there */ | ||
220 | smp_wmb(); | ||
227 | return element; | 221 | return element; |
228 | } | 222 | } |
229 | spin_unlock_irqrestore(&pool->lock, flags); | ||
230 | 223 | ||
231 | /* We must not sleep in the GFP_ATOMIC case */ | 224 | /* |
232 | if (!(gfp_mask & __GFP_WAIT)) | 225 | * We use gfp mask w/o __GFP_WAIT or IO for the first round. If |
226 | * alloc failed with that and @pool was empty, retry immediately. | ||
227 | */ | ||
228 | if (gfp_temp != gfp_mask) { | ||
229 | spin_unlock_irqrestore(&pool->lock, flags); | ||
230 | gfp_temp = gfp_mask; | ||
231 | goto repeat_alloc; | ||
232 | } | ||
233 | |||
234 | /* We must not sleep if !__GFP_WAIT */ | ||
235 | if (!(gfp_mask & __GFP_WAIT)) { | ||
236 | spin_unlock_irqrestore(&pool->lock, flags); | ||
233 | return NULL; | 237 | return NULL; |
238 | } | ||
234 | 239 | ||
235 | /* Now start performing page reclaim */ | 240 | /* Let's wait for someone else to return an element to @pool */ |
236 | gfp_temp = gfp_mask; | ||
237 | init_wait(&wait); | 241 | init_wait(&wait); |
238 | prepare_to_wait(&pool->wait, &wait, TASK_UNINTERRUPTIBLE); | 242 | prepare_to_wait(&pool->wait, &wait, TASK_UNINTERRUPTIBLE); |
239 | smp_mb(); | ||
240 | if (!pool->curr_nr) { | ||
241 | /* | ||
242 | * FIXME: this should be io_schedule(). The timeout is there | ||
243 | * as a workaround for some DM problems in 2.6.18. | ||
244 | */ | ||
245 | io_schedule_timeout(5*HZ); | ||
246 | } | ||
247 | finish_wait(&pool->wait, &wait); | ||
248 | 243 | ||
244 | spin_unlock_irqrestore(&pool->lock, flags); | ||
245 | |||
246 | /* | ||
247 | * FIXME: this should be io_schedule(). The timeout is there as a | ||
248 | * workaround for some DM problems in 2.6.18. | ||
249 | */ | ||
250 | io_schedule_timeout(5*HZ); | ||
251 | |||
252 | finish_wait(&pool->wait, &wait); | ||
249 | goto repeat_alloc; | 253 | goto repeat_alloc; |
250 | } | 254 | } |
251 | EXPORT_SYMBOL(mempool_alloc); | 255 | EXPORT_SYMBOL(mempool_alloc); |
@@ -265,7 +269,39 @@ void mempool_free(void *element, mempool_t *pool) | |||
265 | if (unlikely(element == NULL)) | 269 | if (unlikely(element == NULL)) |
266 | return; | 270 | return; |
267 | 271 | ||
268 | smp_mb(); | 272 | /* |
273 | * Paired with the wmb in mempool_alloc(). The preceding read is | ||
274 | * for @element and the following @pool->curr_nr. This ensures | ||
275 | * that the visible value of @pool->curr_nr is from after the | ||
276 | * allocation of @element. This is necessary for fringe cases | ||
277 | * where @element was passed to this task without going through | ||
278 | * barriers. | ||
279 | * | ||
280 | * For example, assume @p is %NULL at the beginning and one task | ||
281 | * performs "p = mempool_alloc(...);" while another task is doing | ||
282 | * "while (!p) cpu_relax(); mempool_free(p, ...);". This function | ||
283 | * may end up using curr_nr value which is from before allocation | ||
284 | * of @p without the following rmb. | ||
285 | */ | ||
286 | smp_rmb(); | ||
287 | |||
288 | /* | ||
289 | * For correctness, we need a test which is guaranteed to trigger | ||
290 | * if curr_nr + #allocated == min_nr. Testing curr_nr < min_nr | ||
291 | * without locking achieves that and refilling as soon as possible | ||
292 | * is desirable. | ||
293 | * | ||
294 | * Because curr_nr visible here is always a value after the | ||
295 | * allocation of @element, any task which decremented curr_nr below | ||
296 | * min_nr is guaranteed to see curr_nr < min_nr unless curr_nr gets | ||
297 | * incremented to min_nr afterwards. If curr_nr gets incremented | ||
298 | * to min_nr after the allocation of @element, the elements | ||
299 | * allocated after that are subject to the same guarantee. | ||
300 | * | ||
301 | * Waiters happen iff curr_nr is 0 and the above guarantee also | ||
302 | * ensures that there will be frees which return elements to the | ||
303 | * pool waking up the waiters. | ||
304 | */ | ||
269 | if (pool->curr_nr < pool->min_nr) { | 305 | if (pool->curr_nr < pool->min_nr) { |
270 | spin_lock_irqsave(&pool->lock, flags); | 306 | spin_lock_irqsave(&pool->lock, flags); |
271 | if (pool->curr_nr < pool->min_nr) { | 307 | if (pool->curr_nr < pool->min_nr) { |
diff --git a/mm/migrate.c b/mm/migrate.c index 177aca424a06..89ea0854332e 100644 --- a/mm/migrate.c +++ b/mm/migrate.c | |||
@@ -39,8 +39,6 @@ | |||
39 | 39 | ||
40 | #include "internal.h" | 40 | #include "internal.h" |
41 | 41 | ||
42 | #define lru_to_page(_head) (list_entry((_head)->prev, struct page, lru)) | ||
43 | |||
44 | /* | 42 | /* |
45 | * migrate_prep() needs to be called before we start compiling a list of pages | 43 | * migrate_prep() needs to be called before we start compiling a list of pages |
46 | * to be migrated using isolate_lru_page(). If scheduling work on other CPUs is | 44 | * to be migrated using isolate_lru_page(). If scheduling work on other CPUs is |
@@ -181,8 +179,6 @@ static void remove_migration_ptes(struct page *old, struct page *new) | |||
181 | * Something used the pte of a page under migration. We need to | 179 | * Something used the pte of a page under migration. We need to |
182 | * get to the page and wait until migration is finished. | 180 | * get to the page and wait until migration is finished. |
183 | * When we return from this function the fault will be retried. | 181 | * When we return from this function the fault will be retried. |
184 | * | ||
185 | * This function is called from do_swap_page(). | ||
186 | */ | 182 | */ |
187 | void migration_entry_wait(struct mm_struct *mm, pmd_t *pmd, | 183 | void migration_entry_wait(struct mm_struct *mm, pmd_t *pmd, |
188 | unsigned long address) | 184 | unsigned long address) |
@@ -269,12 +265,12 @@ static int migrate_page_move_mapping(struct address_space *mapping, | |||
269 | 265 | ||
270 | radix_tree_replace_slot(pslot, newpage); | 266 | radix_tree_replace_slot(pslot, newpage); |
271 | 267 | ||
272 | page_unfreeze_refs(page, expected_count); | ||
273 | /* | 268 | /* |
274 | * Drop cache reference from old page. | 269 | * Drop cache reference from old page by unfreezing |
270 | * to one less reference. | ||
275 | * We know this isn't the last reference. | 271 | * We know this isn't the last reference. |
276 | */ | 272 | */ |
277 | __put_page(page); | 273 | page_unfreeze_refs(page, expected_count - 1); |
278 | 274 | ||
279 | /* | 275 | /* |
280 | * If moved to a different zone then also account | 276 | * If moved to a different zone then also account |
@@ -334,9 +330,7 @@ int migrate_huge_page_move_mapping(struct address_space *mapping, | |||
334 | 330 | ||
335 | radix_tree_replace_slot(pslot, newpage); | 331 | radix_tree_replace_slot(pslot, newpage); |
336 | 332 | ||
337 | page_unfreeze_refs(page, expected_count); | 333 | page_unfreeze_refs(page, expected_count - 1); |
338 | |||
339 | __put_page(page); | ||
340 | 334 | ||
341 | spin_unlock_irq(&mapping->tree_lock); | 335 | spin_unlock_irq(&mapping->tree_lock); |
342 | return 0; | 336 | return 0; |
@@ -1603,39 +1603,19 @@ struct vm_area_struct *find_vma(struct mm_struct *mm, unsigned long addr) | |||
1603 | 1603 | ||
1604 | EXPORT_SYMBOL(find_vma); | 1604 | EXPORT_SYMBOL(find_vma); |
1605 | 1605 | ||
1606 | /* Same as find_vma, but also return a pointer to the previous VMA in *pprev. */ | 1606 | /* |
1607 | * Same as find_vma, but also return a pointer to the previous VMA in *pprev. | ||
1608 | * Note: pprev is set to NULL when return value is NULL. | ||
1609 | */ | ||
1607 | struct vm_area_struct * | 1610 | struct vm_area_struct * |
1608 | find_vma_prev(struct mm_struct *mm, unsigned long addr, | 1611 | find_vma_prev(struct mm_struct *mm, unsigned long addr, |
1609 | struct vm_area_struct **pprev) | 1612 | struct vm_area_struct **pprev) |
1610 | { | 1613 | { |
1611 | struct vm_area_struct *vma = NULL, *prev = NULL; | 1614 | struct vm_area_struct *vma; |
1612 | struct rb_node *rb_node; | ||
1613 | if (!mm) | ||
1614 | goto out; | ||
1615 | |||
1616 | /* Guard against addr being lower than the first VMA */ | ||
1617 | vma = mm->mmap; | ||
1618 | |||
1619 | /* Go through the RB tree quickly. */ | ||
1620 | rb_node = mm->mm_rb.rb_node; | ||
1621 | |||
1622 | while (rb_node) { | ||
1623 | struct vm_area_struct *vma_tmp; | ||
1624 | vma_tmp = rb_entry(rb_node, struct vm_area_struct, vm_rb); | ||
1625 | |||
1626 | if (addr < vma_tmp->vm_end) { | ||
1627 | rb_node = rb_node->rb_left; | ||
1628 | } else { | ||
1629 | prev = vma_tmp; | ||
1630 | if (!prev->vm_next || (addr < prev->vm_next->vm_end)) | ||
1631 | break; | ||
1632 | rb_node = rb_node->rb_right; | ||
1633 | } | ||
1634 | } | ||
1635 | 1615 | ||
1636 | out: | 1616 | vma = find_vma(mm, addr); |
1637 | *pprev = prev; | 1617 | *pprev = vma ? vma->vm_prev : NULL; |
1638 | return prev ? prev->vm_next : vma; | 1618 | return vma; |
1639 | } | 1619 | } |
1640 | 1620 | ||
1641 | /* | 1621 | /* |
@@ -2322,13 +2302,16 @@ struct vm_area_struct *copy_vma(struct vm_area_struct **vmap, | |||
2322 | struct vm_area_struct *new_vma, *prev; | 2302 | struct vm_area_struct *new_vma, *prev; |
2323 | struct rb_node **rb_link, *rb_parent; | 2303 | struct rb_node **rb_link, *rb_parent; |
2324 | struct mempolicy *pol; | 2304 | struct mempolicy *pol; |
2305 | bool faulted_in_anon_vma = true; | ||
2325 | 2306 | ||
2326 | /* | 2307 | /* |
2327 | * If anonymous vma has not yet been faulted, update new pgoff | 2308 | * If anonymous vma has not yet been faulted, update new pgoff |
2328 | * to match new location, to increase its chance of merging. | 2309 | * to match new location, to increase its chance of merging. |
2329 | */ | 2310 | */ |
2330 | if (!vma->vm_file && !vma->anon_vma) | 2311 | if (unlikely(!vma->vm_file && !vma->anon_vma)) { |
2331 | pgoff = addr >> PAGE_SHIFT; | 2312 | pgoff = addr >> PAGE_SHIFT; |
2313 | faulted_in_anon_vma = false; | ||
2314 | } | ||
2332 | 2315 | ||
2333 | find_vma_prepare(mm, addr, &prev, &rb_link, &rb_parent); | 2316 | find_vma_prepare(mm, addr, &prev, &rb_link, &rb_parent); |
2334 | new_vma = vma_merge(mm, prev, addr, addr + len, vma->vm_flags, | 2317 | new_vma = vma_merge(mm, prev, addr, addr + len, vma->vm_flags, |
@@ -2337,9 +2320,24 @@ struct vm_area_struct *copy_vma(struct vm_area_struct **vmap, | |||
2337 | /* | 2320 | /* |
2338 | * Source vma may have been merged into new_vma | 2321 | * Source vma may have been merged into new_vma |
2339 | */ | 2322 | */ |
2340 | if (vma_start >= new_vma->vm_start && | 2323 | if (unlikely(vma_start >= new_vma->vm_start && |
2341 | vma_start < new_vma->vm_end) | 2324 | vma_start < new_vma->vm_end)) { |
2325 | /* | ||
2326 | * The only way we can get a vma_merge with | ||
2327 | * self during an mremap is if the vma hasn't | ||
2328 | * been faulted in yet and we were allowed to | ||
2329 | * reset the dst vma->vm_pgoff to the | ||
2330 | * destination address of the mremap to allow | ||
2331 | * the merge to happen. mremap must change the | ||
2332 | * vm_pgoff linearity between src and dst vmas | ||
2333 | * (in turn preventing a vma_merge) to be | ||
2334 | * safe. It is only safe to keep the vm_pgoff | ||
2335 | * linear if there are no pages mapped yet. | ||
2336 | */ | ||
2337 | VM_BUG_ON(faulted_in_anon_vma); | ||
2342 | *vmap = new_vma; | 2338 | *vmap = new_vma; |
2339 | } else | ||
2340 | anon_vma_moveto_tail(new_vma); | ||
2343 | } else { | 2341 | } else { |
2344 | new_vma = kmem_cache_alloc(vm_area_cachep, GFP_KERNEL); | 2342 | new_vma = kmem_cache_alloc(vm_area_cachep, GFP_KERNEL); |
2345 | if (new_vma) { | 2343 | if (new_vma) { |
diff --git a/mm/mremap.c b/mm/mremap.c index d6959cb4df58..87bb8393e7d2 100644 --- a/mm/mremap.c +++ b/mm/mremap.c | |||
@@ -221,6 +221,15 @@ static unsigned long move_vma(struct vm_area_struct *vma, | |||
221 | moved_len = move_page_tables(vma, old_addr, new_vma, new_addr, old_len); | 221 | moved_len = move_page_tables(vma, old_addr, new_vma, new_addr, old_len); |
222 | if (moved_len < old_len) { | 222 | if (moved_len < old_len) { |
223 | /* | 223 | /* |
224 | * Before moving the page tables from the new vma to | ||
225 | * the old vma, we need to be sure the old vma is | ||
226 | * queued after new vma in the same_anon_vma list to | ||
227 | * prevent SMP races with rmap_walk (that could lead | ||
228 | * rmap_walk to miss some page table). | ||
229 | */ | ||
230 | anon_vma_moveto_tail(vma); | ||
231 | |||
232 | /* | ||
224 | * On error, move entries back from new area to old, | 233 | * On error, move entries back from new area to old, |
225 | * which will succeed since page tables still there, | 234 | * which will succeed since page tables still there, |
226 | * and then proceed to unmap new area instead of old. | 235 | * and then proceed to unmap new area instead of old. |
diff --git a/mm/oom_kill.c b/mm/oom_kill.c index eeb27e27dce3..7c122faa05c5 100644 --- a/mm/oom_kill.c +++ b/mm/oom_kill.c | |||
@@ -33,6 +33,10 @@ | |||
33 | #include <linux/security.h> | 33 | #include <linux/security.h> |
34 | #include <linux/ptrace.h> | 34 | #include <linux/ptrace.h> |
35 | #include <linux/freezer.h> | 35 | #include <linux/freezer.h> |
36 | #include <linux/ftrace.h> | ||
37 | |||
38 | #define CREATE_TRACE_POINTS | ||
39 | #include <trace/events/oom.h> | ||
36 | 40 | ||
37 | int sysctl_panic_on_oom; | 41 | int sysctl_panic_on_oom; |
38 | int sysctl_oom_kill_allocating_task; | 42 | int sysctl_oom_kill_allocating_task; |
@@ -55,6 +59,7 @@ void compare_swap_oom_score_adj(int old_val, int new_val) | |||
55 | spin_lock_irq(&sighand->siglock); | 59 | spin_lock_irq(&sighand->siglock); |
56 | if (current->signal->oom_score_adj == old_val) | 60 | if (current->signal->oom_score_adj == old_val) |
57 | current->signal->oom_score_adj = new_val; | 61 | current->signal->oom_score_adj = new_val; |
62 | trace_oom_score_adj_update(current); | ||
58 | spin_unlock_irq(&sighand->siglock); | 63 | spin_unlock_irq(&sighand->siglock); |
59 | } | 64 | } |
60 | 65 | ||
@@ -74,6 +79,7 @@ int test_set_oom_score_adj(int new_val) | |||
74 | spin_lock_irq(&sighand->siglock); | 79 | spin_lock_irq(&sighand->siglock); |
75 | old_val = current->signal->oom_score_adj; | 80 | old_val = current->signal->oom_score_adj; |
76 | current->signal->oom_score_adj = new_val; | 81 | current->signal->oom_score_adj = new_val; |
82 | trace_oom_score_adj_update(current); | ||
77 | spin_unlock_irq(&sighand->siglock); | 83 | spin_unlock_irq(&sighand->siglock); |
78 | 84 | ||
79 | return old_val; | 85 | return old_val; |
diff --git a/mm/page-writeback.c b/mm/page-writeback.c index 8616ef3025a4..5cdd4f2b0c9d 100644 --- a/mm/page-writeback.c +++ b/mm/page-writeback.c | |||
@@ -130,6 +130,191 @@ unsigned long global_dirty_limit; | |||
130 | static struct prop_descriptor vm_completions; | 130 | static struct prop_descriptor vm_completions; |
131 | 131 | ||
132 | /* | 132 | /* |
133 | * Work out the current dirty-memory clamping and background writeout | ||
134 | * thresholds. | ||
135 | * | ||
136 | * The main aim here is to lower them aggressively if there is a lot of mapped | ||
137 | * memory around. To avoid stressing page reclaim with lots of unreclaimable | ||
138 | * pages. It is better to clamp down on writers than to start swapping, and | ||
139 | * performing lots of scanning. | ||
140 | * | ||
141 | * We only allow 1/2 of the currently-unmapped memory to be dirtied. | ||
142 | * | ||
143 | * We don't permit the clamping level to fall below 5% - that is getting rather | ||
144 | * excessive. | ||
145 | * | ||
146 | * We make sure that the background writeout level is below the adjusted | ||
147 | * clamping level. | ||
148 | */ | ||
149 | |||
150 | /* | ||
151 | * In a memory zone, there is a certain amount of pages we consider | ||
152 | * available for the page cache, which is essentially the number of | ||
153 | * free and reclaimable pages, minus some zone reserves to protect | ||
154 | * lowmem and the ability to uphold the zone's watermarks without | ||
155 | * requiring writeback. | ||
156 | * | ||
157 | * This number of dirtyable pages is the base value of which the | ||
158 | * user-configurable dirty ratio is the effictive number of pages that | ||
159 | * are allowed to be actually dirtied. Per individual zone, or | ||
160 | * globally by using the sum of dirtyable pages over all zones. | ||
161 | * | ||
162 | * Because the user is allowed to specify the dirty limit globally as | ||
163 | * absolute number of bytes, calculating the per-zone dirty limit can | ||
164 | * require translating the configured limit into a percentage of | ||
165 | * global dirtyable memory first. | ||
166 | */ | ||
167 | |||
168 | static unsigned long highmem_dirtyable_memory(unsigned long total) | ||
169 | { | ||
170 | #ifdef CONFIG_HIGHMEM | ||
171 | int node; | ||
172 | unsigned long x = 0; | ||
173 | |||
174 | for_each_node_state(node, N_HIGH_MEMORY) { | ||
175 | struct zone *z = | ||
176 | &NODE_DATA(node)->node_zones[ZONE_HIGHMEM]; | ||
177 | |||
178 | x += zone_page_state(z, NR_FREE_PAGES) + | ||
179 | zone_reclaimable_pages(z) - z->dirty_balance_reserve; | ||
180 | } | ||
181 | /* | ||
182 | * Make sure that the number of highmem pages is never larger | ||
183 | * than the number of the total dirtyable memory. This can only | ||
184 | * occur in very strange VM situations but we want to make sure | ||
185 | * that this does not occur. | ||
186 | */ | ||
187 | return min(x, total); | ||
188 | #else | ||
189 | return 0; | ||
190 | #endif | ||
191 | } | ||
192 | |||
193 | /** | ||
194 | * global_dirtyable_memory - number of globally dirtyable pages | ||
195 | * | ||
196 | * Returns the global number of pages potentially available for dirty | ||
197 | * page cache. This is the base value for the global dirty limits. | ||
198 | */ | ||
199 | unsigned long global_dirtyable_memory(void) | ||
200 | { | ||
201 | unsigned long x; | ||
202 | |||
203 | x = global_page_state(NR_FREE_PAGES) + global_reclaimable_pages() - | ||
204 | dirty_balance_reserve; | ||
205 | |||
206 | if (!vm_highmem_is_dirtyable) | ||
207 | x -= highmem_dirtyable_memory(x); | ||
208 | |||
209 | return x + 1; /* Ensure that we never return 0 */ | ||
210 | } | ||
211 | |||
212 | /* | ||
213 | * global_dirty_limits - background-writeback and dirty-throttling thresholds | ||
214 | * | ||
215 | * Calculate the dirty thresholds based on sysctl parameters | ||
216 | * - vm.dirty_background_ratio or vm.dirty_background_bytes | ||
217 | * - vm.dirty_ratio or vm.dirty_bytes | ||
218 | * The dirty limits will be lifted by 1/4 for PF_LESS_THROTTLE (ie. nfsd) and | ||
219 | * real-time tasks. | ||
220 | */ | ||
221 | void global_dirty_limits(unsigned long *pbackground, unsigned long *pdirty) | ||
222 | { | ||
223 | unsigned long background; | ||
224 | unsigned long dirty; | ||
225 | unsigned long uninitialized_var(available_memory); | ||
226 | struct task_struct *tsk; | ||
227 | |||
228 | if (!vm_dirty_bytes || !dirty_background_bytes) | ||
229 | available_memory = global_dirtyable_memory(); | ||
230 | |||
231 | if (vm_dirty_bytes) | ||
232 | dirty = DIV_ROUND_UP(vm_dirty_bytes, PAGE_SIZE); | ||
233 | else | ||
234 | dirty = (vm_dirty_ratio * available_memory) / 100; | ||
235 | |||
236 | if (dirty_background_bytes) | ||
237 | background = DIV_ROUND_UP(dirty_background_bytes, PAGE_SIZE); | ||
238 | else | ||
239 | background = (dirty_background_ratio * available_memory) / 100; | ||
240 | |||
241 | if (background >= dirty) | ||
242 | background = dirty / 2; | ||
243 | tsk = current; | ||
244 | if (tsk->flags & PF_LESS_THROTTLE || rt_task(tsk)) { | ||
245 | background += background / 4; | ||
246 | dirty += dirty / 4; | ||
247 | } | ||
248 | *pbackground = background; | ||
249 | *pdirty = dirty; | ||
250 | trace_global_dirty_state(background, dirty); | ||
251 | } | ||
252 | |||
253 | /** | ||
254 | * zone_dirtyable_memory - number of dirtyable pages in a zone | ||
255 | * @zone: the zone | ||
256 | * | ||
257 | * Returns the zone's number of pages potentially available for dirty | ||
258 | * page cache. This is the base value for the per-zone dirty limits. | ||
259 | */ | ||
260 | static unsigned long zone_dirtyable_memory(struct zone *zone) | ||
261 | { | ||
262 | /* | ||
263 | * The effective global number of dirtyable pages may exclude | ||
264 | * highmem as a big-picture measure to keep the ratio between | ||
265 | * dirty memory and lowmem reasonable. | ||
266 | * | ||
267 | * But this function is purely about the individual zone and a | ||
268 | * highmem zone can hold its share of dirty pages, so we don't | ||
269 | * care about vm_highmem_is_dirtyable here. | ||
270 | */ | ||
271 | return zone_page_state(zone, NR_FREE_PAGES) + | ||
272 | zone_reclaimable_pages(zone) - | ||
273 | zone->dirty_balance_reserve; | ||
274 | } | ||
275 | |||
276 | /** | ||
277 | * zone_dirty_limit - maximum number of dirty pages allowed in a zone | ||
278 | * @zone: the zone | ||
279 | * | ||
280 | * Returns the maximum number of dirty pages allowed in a zone, based | ||
281 | * on the zone's dirtyable memory. | ||
282 | */ | ||
283 | static unsigned long zone_dirty_limit(struct zone *zone) | ||
284 | { | ||
285 | unsigned long zone_memory = zone_dirtyable_memory(zone); | ||
286 | struct task_struct *tsk = current; | ||
287 | unsigned long dirty; | ||
288 | |||
289 | if (vm_dirty_bytes) | ||
290 | dirty = DIV_ROUND_UP(vm_dirty_bytes, PAGE_SIZE) * | ||
291 | zone_memory / global_dirtyable_memory(); | ||
292 | else | ||
293 | dirty = vm_dirty_ratio * zone_memory / 100; | ||
294 | |||
295 | if (tsk->flags & PF_LESS_THROTTLE || rt_task(tsk)) | ||
296 | dirty += dirty / 4; | ||
297 | |||
298 | return dirty; | ||
299 | } | ||
300 | |||
301 | /** | ||
302 | * zone_dirty_ok - tells whether a zone is within its dirty limits | ||
303 | * @zone: the zone to check | ||
304 | * | ||
305 | * Returns %true when the dirty pages in @zone are within the zone's | ||
306 | * dirty limit, %false if the limit is exceeded. | ||
307 | */ | ||
308 | bool zone_dirty_ok(struct zone *zone) | ||
309 | { | ||
310 | unsigned long limit = zone_dirty_limit(zone); | ||
311 | |||
312 | return zone_page_state(zone, NR_FILE_DIRTY) + | ||
313 | zone_page_state(zone, NR_UNSTABLE_NFS) + | ||
314 | zone_page_state(zone, NR_WRITEBACK) <= limit; | ||
315 | } | ||
316 | |||
317 | /* | ||
133 | * couple the period to the dirty_ratio: | 318 | * couple the period to the dirty_ratio: |
134 | * | 319 | * |
135 | * period/2 ~ roundup_pow_of_two(dirty limit) | 320 | * period/2 ~ roundup_pow_of_two(dirty limit) |
@@ -141,7 +326,7 @@ static int calc_period_shift(void) | |||
141 | if (vm_dirty_bytes) | 326 | if (vm_dirty_bytes) |
142 | dirty_total = vm_dirty_bytes / PAGE_SIZE; | 327 | dirty_total = vm_dirty_bytes / PAGE_SIZE; |
143 | else | 328 | else |
144 | dirty_total = (vm_dirty_ratio * determine_dirtyable_memory()) / | 329 | dirty_total = (vm_dirty_ratio * global_dirtyable_memory()) / |
145 | 100; | 330 | 100; |
146 | return 2 + ilog2(dirty_total - 1); | 331 | return 2 + ilog2(dirty_total - 1); |
147 | } | 332 | } |
@@ -196,7 +381,6 @@ int dirty_ratio_handler(struct ctl_table *table, int write, | |||
196 | return ret; | 381 | return ret; |
197 | } | 382 | } |
198 | 383 | ||
199 | |||
200 | int dirty_bytes_handler(struct ctl_table *table, int write, | 384 | int dirty_bytes_handler(struct ctl_table *table, int write, |
201 | void __user *buffer, size_t *lenp, | 385 | void __user *buffer, size_t *lenp, |
202 | loff_t *ppos) | 386 | loff_t *ppos) |
@@ -291,67 +475,6 @@ int bdi_set_max_ratio(struct backing_dev_info *bdi, unsigned max_ratio) | |||
291 | } | 475 | } |
292 | EXPORT_SYMBOL(bdi_set_max_ratio); | 476 | EXPORT_SYMBOL(bdi_set_max_ratio); |
293 | 477 | ||
294 | /* | ||
295 | * Work out the current dirty-memory clamping and background writeout | ||
296 | * thresholds. | ||
297 | * | ||
298 | * The main aim here is to lower them aggressively if there is a lot of mapped | ||
299 | * memory around. To avoid stressing page reclaim with lots of unreclaimable | ||
300 | * pages. It is better to clamp down on writers than to start swapping, and | ||
301 | * performing lots of scanning. | ||
302 | * | ||
303 | * We only allow 1/2 of the currently-unmapped memory to be dirtied. | ||
304 | * | ||
305 | * We don't permit the clamping level to fall below 5% - that is getting rather | ||
306 | * excessive. | ||
307 | * | ||
308 | * We make sure that the background writeout level is below the adjusted | ||
309 | * clamping level. | ||
310 | */ | ||
311 | |||
312 | static unsigned long highmem_dirtyable_memory(unsigned long total) | ||
313 | { | ||
314 | #ifdef CONFIG_HIGHMEM | ||
315 | int node; | ||
316 | unsigned long x = 0; | ||
317 | |||
318 | for_each_node_state(node, N_HIGH_MEMORY) { | ||
319 | struct zone *z = | ||
320 | &NODE_DATA(node)->node_zones[ZONE_HIGHMEM]; | ||
321 | |||
322 | x += zone_page_state(z, NR_FREE_PAGES) + | ||
323 | zone_reclaimable_pages(z); | ||
324 | } | ||
325 | /* | ||
326 | * Make sure that the number of highmem pages is never larger | ||
327 | * than the number of the total dirtyable memory. This can only | ||
328 | * occur in very strange VM situations but we want to make sure | ||
329 | * that this does not occur. | ||
330 | */ | ||
331 | return min(x, total); | ||
332 | #else | ||
333 | return 0; | ||
334 | #endif | ||
335 | } | ||
336 | |||
337 | /** | ||
338 | * determine_dirtyable_memory - amount of memory that may be used | ||
339 | * | ||
340 | * Returns the numebr of pages that can currently be freed and used | ||
341 | * by the kernel for direct mappings. | ||
342 | */ | ||
343 | unsigned long determine_dirtyable_memory(void) | ||
344 | { | ||
345 | unsigned long x; | ||
346 | |||
347 | x = global_page_state(NR_FREE_PAGES) + global_reclaimable_pages(); | ||
348 | |||
349 | if (!vm_highmem_is_dirtyable) | ||
350 | x -= highmem_dirtyable_memory(x); | ||
351 | |||
352 | return x + 1; /* Ensure that we never return 0 */ | ||
353 | } | ||
354 | |||
355 | static unsigned long dirty_freerun_ceiling(unsigned long thresh, | 478 | static unsigned long dirty_freerun_ceiling(unsigned long thresh, |
356 | unsigned long bg_thresh) | 479 | unsigned long bg_thresh) |
357 | { | 480 | { |
@@ -363,47 +486,6 @@ static unsigned long hard_dirty_limit(unsigned long thresh) | |||
363 | return max(thresh, global_dirty_limit); | 486 | return max(thresh, global_dirty_limit); |
364 | } | 487 | } |
365 | 488 | ||
366 | /* | ||
367 | * global_dirty_limits - background-writeback and dirty-throttling thresholds | ||
368 | * | ||
369 | * Calculate the dirty thresholds based on sysctl parameters | ||
370 | * - vm.dirty_background_ratio or vm.dirty_background_bytes | ||
371 | * - vm.dirty_ratio or vm.dirty_bytes | ||
372 | * The dirty limits will be lifted by 1/4 for PF_LESS_THROTTLE (ie. nfsd) and | ||
373 | * real-time tasks. | ||
374 | */ | ||
375 | void global_dirty_limits(unsigned long *pbackground, unsigned long *pdirty) | ||
376 | { | ||
377 | unsigned long background; | ||
378 | unsigned long dirty; | ||
379 | unsigned long uninitialized_var(available_memory); | ||
380 | struct task_struct *tsk; | ||
381 | |||
382 | if (!vm_dirty_bytes || !dirty_background_bytes) | ||
383 | available_memory = determine_dirtyable_memory(); | ||
384 | |||
385 | if (vm_dirty_bytes) | ||
386 | dirty = DIV_ROUND_UP(vm_dirty_bytes, PAGE_SIZE); | ||
387 | else | ||
388 | dirty = (vm_dirty_ratio * available_memory) / 100; | ||
389 | |||
390 | if (dirty_background_bytes) | ||
391 | background = DIV_ROUND_UP(dirty_background_bytes, PAGE_SIZE); | ||
392 | else | ||
393 | background = (dirty_background_ratio * available_memory) / 100; | ||
394 | |||
395 | if (background >= dirty) | ||
396 | background = dirty / 2; | ||
397 | tsk = current; | ||
398 | if (tsk->flags & PF_LESS_THROTTLE || rt_task(tsk)) { | ||
399 | background += background / 4; | ||
400 | dirty += dirty / 4; | ||
401 | } | ||
402 | *pbackground = background; | ||
403 | *pdirty = dirty; | ||
404 | trace_global_dirty_state(background, dirty); | ||
405 | } | ||
406 | |||
407 | /** | 489 | /** |
408 | * bdi_dirty_limit - @bdi's share of dirty throttling threshold | 490 | * bdi_dirty_limit - @bdi's share of dirty throttling threshold |
409 | * @bdi: the backing_dev_info to query | 491 | * @bdi: the backing_dev_info to query |
diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 7990ca154d1b..794e6715c226 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c | |||
@@ -57,6 +57,7 @@ | |||
57 | #include <linux/ftrace_event.h> | 57 | #include <linux/ftrace_event.h> |
58 | #include <linux/memcontrol.h> | 58 | #include <linux/memcontrol.h> |
59 | #include <linux/prefetch.h> | 59 | #include <linux/prefetch.h> |
60 | #include <linux/page-debug-flags.h> | ||
60 | 61 | ||
61 | #include <asm/tlbflush.h> | 62 | #include <asm/tlbflush.h> |
62 | #include <asm/div64.h> | 63 | #include <asm/div64.h> |
@@ -96,6 +97,14 @@ EXPORT_SYMBOL(node_states); | |||
96 | 97 | ||
97 | unsigned long totalram_pages __read_mostly; | 98 | unsigned long totalram_pages __read_mostly; |
98 | unsigned long totalreserve_pages __read_mostly; | 99 | unsigned long totalreserve_pages __read_mostly; |
100 | /* | ||
101 | * When calculating the number of globally allowed dirty pages, there | ||
102 | * is a certain number of per-zone reserves that should not be | ||
103 | * considered dirtyable memory. This is the sum of those reserves | ||
104 | * over all existing zones that contribute dirtyable memory. | ||
105 | */ | ||
106 | unsigned long dirty_balance_reserve __read_mostly; | ||
107 | |||
99 | int percpu_pagelist_fraction; | 108 | int percpu_pagelist_fraction; |
100 | gfp_t gfp_allowed_mask __read_mostly = GFP_BOOT_MASK; | 109 | gfp_t gfp_allowed_mask __read_mostly = GFP_BOOT_MASK; |
101 | 110 | ||
@@ -127,6 +136,13 @@ void pm_restrict_gfp_mask(void) | |||
127 | saved_gfp_mask = gfp_allowed_mask; | 136 | saved_gfp_mask = gfp_allowed_mask; |
128 | gfp_allowed_mask &= ~GFP_IOFS; | 137 | gfp_allowed_mask &= ~GFP_IOFS; |
129 | } | 138 | } |
139 | |||
140 | bool pm_suspended_storage(void) | ||
141 | { | ||
142 | if ((gfp_allowed_mask & GFP_IOFS) == GFP_IOFS) | ||
143 | return false; | ||
144 | return true; | ||
145 | } | ||
130 | #endif /* CONFIG_PM_SLEEP */ | 146 | #endif /* CONFIG_PM_SLEEP */ |
131 | 147 | ||
132 | #ifdef CONFIG_HUGETLB_PAGE_SIZE_VARIABLE | 148 | #ifdef CONFIG_HUGETLB_PAGE_SIZE_VARIABLE |
@@ -381,6 +397,37 @@ static inline void prep_zero_page(struct page *page, int order, gfp_t gfp_flags) | |||
381 | clear_highpage(page + i); | 397 | clear_highpage(page + i); |
382 | } | 398 | } |
383 | 399 | ||
400 | #ifdef CONFIG_DEBUG_PAGEALLOC | ||
401 | unsigned int _debug_guardpage_minorder; | ||
402 | |||
403 | static int __init debug_guardpage_minorder_setup(char *buf) | ||
404 | { | ||
405 | unsigned long res; | ||
406 | |||
407 | if (kstrtoul(buf, 10, &res) < 0 || res > MAX_ORDER / 2) { | ||
408 | printk(KERN_ERR "Bad debug_guardpage_minorder value\n"); | ||
409 | return 0; | ||
410 | } | ||
411 | _debug_guardpage_minorder = res; | ||
412 | printk(KERN_INFO "Setting debug_guardpage_minorder to %lu\n", res); | ||
413 | return 0; | ||
414 | } | ||
415 | __setup("debug_guardpage_minorder=", debug_guardpage_minorder_setup); | ||
416 | |||
417 | static inline void set_page_guard_flag(struct page *page) | ||
418 | { | ||
419 | __set_bit(PAGE_DEBUG_FLAG_GUARD, &page->debug_flags); | ||
420 | } | ||
421 | |||
422 | static inline void clear_page_guard_flag(struct page *page) | ||
423 | { | ||
424 | __clear_bit(PAGE_DEBUG_FLAG_GUARD, &page->debug_flags); | ||
425 | } | ||
426 | #else | ||
427 | static inline void set_page_guard_flag(struct page *page) { } | ||
428 | static inline void clear_page_guard_flag(struct page *page) { } | ||
429 | #endif | ||
430 | |||
384 | static inline void set_page_order(struct page *page, int order) | 431 | static inline void set_page_order(struct page *page, int order) |
385 | { | 432 | { |
386 | set_page_private(page, order); | 433 | set_page_private(page, order); |
@@ -438,6 +485,11 @@ static inline int page_is_buddy(struct page *page, struct page *buddy, | |||
438 | if (page_zone_id(page) != page_zone_id(buddy)) | 485 | if (page_zone_id(page) != page_zone_id(buddy)) |
439 | return 0; | 486 | return 0; |
440 | 487 | ||
488 | if (page_is_guard(buddy) && page_order(buddy) == order) { | ||
489 | VM_BUG_ON(page_count(buddy) != 0); | ||
490 | return 1; | ||
491 | } | ||
492 | |||
441 | if (PageBuddy(buddy) && page_order(buddy) == order) { | 493 | if (PageBuddy(buddy) && page_order(buddy) == order) { |
442 | VM_BUG_ON(page_count(buddy) != 0); | 494 | VM_BUG_ON(page_count(buddy) != 0); |
443 | return 1; | 495 | return 1; |
@@ -494,11 +546,19 @@ static inline void __free_one_page(struct page *page, | |||
494 | buddy = page + (buddy_idx - page_idx); | 546 | buddy = page + (buddy_idx - page_idx); |
495 | if (!page_is_buddy(page, buddy, order)) | 547 | if (!page_is_buddy(page, buddy, order)) |
496 | break; | 548 | break; |
497 | 549 | /* | |
498 | /* Our buddy is free, merge with it and move up one order. */ | 550 | * Our buddy is free or it is CONFIG_DEBUG_PAGEALLOC guard page, |
499 | list_del(&buddy->lru); | 551 | * merge with it and move up one order. |
500 | zone->free_area[order].nr_free--; | 552 | */ |
501 | rmv_page_order(buddy); | 553 | if (page_is_guard(buddy)) { |
554 | clear_page_guard_flag(buddy); | ||
555 | set_page_private(page, 0); | ||
556 | __mod_zone_page_state(zone, NR_FREE_PAGES, 1 << order); | ||
557 | } else { | ||
558 | list_del(&buddy->lru); | ||
559 | zone->free_area[order].nr_free--; | ||
560 | rmv_page_order(buddy); | ||
561 | } | ||
502 | combined_idx = buddy_idx & page_idx; | 562 | combined_idx = buddy_idx & page_idx; |
503 | page = page + (combined_idx - page_idx); | 563 | page = page + (combined_idx - page_idx); |
504 | page_idx = combined_idx; | 564 | page_idx = combined_idx; |
@@ -632,7 +692,7 @@ static bool free_pages_prepare(struct page *page, unsigned int order) | |||
632 | int i; | 692 | int i; |
633 | int bad = 0; | 693 | int bad = 0; |
634 | 694 | ||
635 | trace_mm_page_free_direct(page, order); | 695 | trace_mm_page_free(page, order); |
636 | kmemcheck_free_shadow(page, order); | 696 | kmemcheck_free_shadow(page, order); |
637 | 697 | ||
638 | if (PageAnon(page)) | 698 | if (PageAnon(page)) |
@@ -670,32 +730,23 @@ static void __free_pages_ok(struct page *page, unsigned int order) | |||
670 | local_irq_restore(flags); | 730 | local_irq_restore(flags); |
671 | } | 731 | } |
672 | 732 | ||
673 | /* | ||
674 | * permit the bootmem allocator to evade page validation on high-order frees | ||
675 | */ | ||
676 | void __meminit __free_pages_bootmem(struct page *page, unsigned int order) | 733 | void __meminit __free_pages_bootmem(struct page *page, unsigned int order) |
677 | { | 734 | { |
678 | if (order == 0) { | 735 | unsigned int nr_pages = 1 << order; |
679 | __ClearPageReserved(page); | 736 | unsigned int loop; |
680 | set_page_count(page, 0); | ||
681 | set_page_refcounted(page); | ||
682 | __free_page(page); | ||
683 | } else { | ||
684 | int loop; | ||
685 | |||
686 | prefetchw(page); | ||
687 | for (loop = 0; loop < (1 << order); loop++) { | ||
688 | struct page *p = &page[loop]; | ||
689 | 737 | ||
690 | if (loop + 1 < (1 << order)) | 738 | prefetchw(page); |
691 | prefetchw(p + 1); | 739 | for (loop = 0; loop < nr_pages; loop++) { |
692 | __ClearPageReserved(p); | 740 | struct page *p = &page[loop]; |
693 | set_page_count(p, 0); | ||
694 | } | ||
695 | 741 | ||
696 | set_page_refcounted(page); | 742 | if (loop + 1 < nr_pages) |
697 | __free_pages(page, order); | 743 | prefetchw(p + 1); |
744 | __ClearPageReserved(p); | ||
745 | set_page_count(p, 0); | ||
698 | } | 746 | } |
747 | |||
748 | set_page_refcounted(page); | ||
749 | __free_pages(page, order); | ||
699 | } | 750 | } |
700 | 751 | ||
701 | 752 | ||
@@ -724,6 +775,23 @@ static inline void expand(struct zone *zone, struct page *page, | |||
724 | high--; | 775 | high--; |
725 | size >>= 1; | 776 | size >>= 1; |
726 | VM_BUG_ON(bad_range(zone, &page[size])); | 777 | VM_BUG_ON(bad_range(zone, &page[size])); |
778 | |||
779 | #ifdef CONFIG_DEBUG_PAGEALLOC | ||
780 | if (high < debug_guardpage_minorder()) { | ||
781 | /* | ||
782 | * Mark as guard pages (or page), that will allow to | ||
783 | * merge back to allocator when buddy will be freed. | ||
784 | * Corresponding page table entries will not be touched, | ||
785 | * pages will stay not present in virtual address space | ||
786 | */ | ||
787 | INIT_LIST_HEAD(&page[size].lru); | ||
788 | set_page_guard_flag(&page[size]); | ||
789 | set_page_private(&page[size], high); | ||
790 | /* Guard pages are not available for any usage */ | ||
791 | __mod_zone_page_state(zone, NR_FREE_PAGES, -(1 << high)); | ||
792 | continue; | ||
793 | } | ||
794 | #endif | ||
727 | list_add(&page[size].lru, &area->free_list[migratetype]); | 795 | list_add(&page[size].lru, &area->free_list[migratetype]); |
728 | area->nr_free++; | 796 | area->nr_free++; |
729 | set_page_order(&page[size], high); | 797 | set_page_order(&page[size], high); |
@@ -1189,6 +1257,19 @@ out: | |||
1189 | } | 1257 | } |
1190 | 1258 | ||
1191 | /* | 1259 | /* |
1260 | * Free a list of 0-order pages | ||
1261 | */ | ||
1262 | void free_hot_cold_page_list(struct list_head *list, int cold) | ||
1263 | { | ||
1264 | struct page *page, *next; | ||
1265 | |||
1266 | list_for_each_entry_safe(page, next, list, lru) { | ||
1267 | trace_mm_page_free_batched(page, cold); | ||
1268 | free_hot_cold_page(page, cold); | ||
1269 | } | ||
1270 | } | ||
1271 | |||
1272 | /* | ||
1192 | * split_page takes a non-compound higher-order page, and splits it into | 1273 | * split_page takes a non-compound higher-order page, and splits it into |
1193 | * n (1<<order) sub-pages: page[0..n] | 1274 | * n (1<<order) sub-pages: page[0..n] |
1194 | * Each sub-page must be freed individually. | 1275 | * Each sub-page must be freed individually. |
@@ -1435,7 +1516,7 @@ static bool __zone_watermark_ok(struct zone *z, int order, unsigned long mark, | |||
1435 | long min = mark; | 1516 | long min = mark; |
1436 | int o; | 1517 | int o; |
1437 | 1518 | ||
1438 | free_pages -= (1 << order) + 1; | 1519 | free_pages -= (1 << order) - 1; |
1439 | if (alloc_flags & ALLOC_HIGH) | 1520 | if (alloc_flags & ALLOC_HIGH) |
1440 | min -= min / 2; | 1521 | min -= min / 2; |
1441 | if (alloc_flags & ALLOC_HARDER) | 1522 | if (alloc_flags & ALLOC_HARDER) |
@@ -1645,6 +1726,35 @@ zonelist_scan: | |||
1645 | if ((alloc_flags & ALLOC_CPUSET) && | 1726 | if ((alloc_flags & ALLOC_CPUSET) && |
1646 | !cpuset_zone_allowed_softwall(zone, gfp_mask)) | 1727 | !cpuset_zone_allowed_softwall(zone, gfp_mask)) |
1647 | continue; | 1728 | continue; |
1729 | /* | ||
1730 | * When allocating a page cache page for writing, we | ||
1731 | * want to get it from a zone that is within its dirty | ||
1732 | * limit, such that no single zone holds more than its | ||
1733 | * proportional share of globally allowed dirty pages. | ||
1734 | * The dirty limits take into account the zone's | ||
1735 | * lowmem reserves and high watermark so that kswapd | ||
1736 | * should be able to balance it without having to | ||
1737 | * write pages from its LRU list. | ||
1738 | * | ||
1739 | * This may look like it could increase pressure on | ||
1740 | * lower zones by failing allocations in higher zones | ||
1741 | * before they are full. But the pages that do spill | ||
1742 | * over are limited as the lower zones are protected | ||
1743 | * by this very same mechanism. It should not become | ||
1744 | * a practical burden to them. | ||
1745 | * | ||
1746 | * XXX: For now, allow allocations to potentially | ||
1747 | * exceed the per-zone dirty limit in the slowpath | ||
1748 | * (ALLOC_WMARK_LOW unset) before going into reclaim, | ||
1749 | * which is important when on a NUMA setup the allowed | ||
1750 | * zones are together not big enough to reach the | ||
1751 | * global limit. The proper fix for these situations | ||
1752 | * will require awareness of zones in the | ||
1753 | * dirty-throttling and the flusher threads. | ||
1754 | */ | ||
1755 | if ((alloc_flags & ALLOC_WMARK_LOW) && | ||
1756 | (gfp_mask & __GFP_WRITE) && !zone_dirty_ok(zone)) | ||
1757 | goto this_zone_full; | ||
1648 | 1758 | ||
1649 | BUILD_BUG_ON(ALLOC_NO_WATERMARKS < NR_WMARK); | 1759 | BUILD_BUG_ON(ALLOC_NO_WATERMARKS < NR_WMARK); |
1650 | if (!(alloc_flags & ALLOC_NO_WATERMARKS)) { | 1760 | if (!(alloc_flags & ALLOC_NO_WATERMARKS)) { |
@@ -1734,7 +1844,8 @@ void warn_alloc_failed(gfp_t gfp_mask, int order, const char *fmt, ...) | |||
1734 | { | 1844 | { |
1735 | unsigned int filter = SHOW_MEM_FILTER_NODES; | 1845 | unsigned int filter = SHOW_MEM_FILTER_NODES; |
1736 | 1846 | ||
1737 | if ((gfp_mask & __GFP_NOWARN) || !__ratelimit(&nopage_rs)) | 1847 | if ((gfp_mask & __GFP_NOWARN) || !__ratelimit(&nopage_rs) || |
1848 | debug_guardpage_minorder() > 0) | ||
1738 | return; | 1849 | return; |
1739 | 1850 | ||
1740 | /* | 1851 | /* |
@@ -1773,12 +1884,25 @@ void warn_alloc_failed(gfp_t gfp_mask, int order, const char *fmt, ...) | |||
1773 | 1884 | ||
1774 | static inline int | 1885 | static inline int |
1775 | should_alloc_retry(gfp_t gfp_mask, unsigned int order, | 1886 | should_alloc_retry(gfp_t gfp_mask, unsigned int order, |
1887 | unsigned long did_some_progress, | ||
1776 | unsigned long pages_reclaimed) | 1888 | unsigned long pages_reclaimed) |
1777 | { | 1889 | { |
1778 | /* Do not loop if specifically requested */ | 1890 | /* Do not loop if specifically requested */ |
1779 | if (gfp_mask & __GFP_NORETRY) | 1891 | if (gfp_mask & __GFP_NORETRY) |
1780 | return 0; | 1892 | return 0; |
1781 | 1893 | ||
1894 | /* Always retry if specifically requested */ | ||
1895 | if (gfp_mask & __GFP_NOFAIL) | ||
1896 | return 1; | ||
1897 | |||
1898 | /* | ||
1899 | * Suspend converts GFP_KERNEL to __GFP_WAIT which can prevent reclaim | ||
1900 | * making forward progress without invoking OOM. Suspend also disables | ||
1901 | * storage devices so kswapd will not help. Bail if we are suspending. | ||
1902 | */ | ||
1903 | if (!did_some_progress && pm_suspended_storage()) | ||
1904 | return 0; | ||
1905 | |||
1782 | /* | 1906 | /* |
1783 | * In this implementation, order <= PAGE_ALLOC_COSTLY_ORDER | 1907 | * In this implementation, order <= PAGE_ALLOC_COSTLY_ORDER |
1784 | * means __GFP_NOFAIL, but that may not be true in other | 1908 | * means __GFP_NOFAIL, but that may not be true in other |
@@ -1797,13 +1921,6 @@ should_alloc_retry(gfp_t gfp_mask, unsigned int order, | |||
1797 | if (gfp_mask & __GFP_REPEAT && pages_reclaimed < (1 << order)) | 1921 | if (gfp_mask & __GFP_REPEAT && pages_reclaimed < (1 << order)) |
1798 | return 1; | 1922 | return 1; |
1799 | 1923 | ||
1800 | /* | ||
1801 | * Don't let big-order allocations loop unless the caller | ||
1802 | * explicitly requests that. | ||
1803 | */ | ||
1804 | if (gfp_mask & __GFP_NOFAIL) | ||
1805 | return 1; | ||
1806 | |||
1807 | return 0; | 1924 | return 0; |
1808 | } | 1925 | } |
1809 | 1926 | ||
@@ -2196,7 +2313,8 @@ rebalance: | |||
2196 | 2313 | ||
2197 | /* Check if we should retry the allocation */ | 2314 | /* Check if we should retry the allocation */ |
2198 | pages_reclaimed += did_some_progress; | 2315 | pages_reclaimed += did_some_progress; |
2199 | if (should_alloc_retry(gfp_mask, order, pages_reclaimed)) { | 2316 | if (should_alloc_retry(gfp_mask, order, did_some_progress, |
2317 | pages_reclaimed)) { | ||
2200 | /* Wait for some write requests to complete then retry */ | 2318 | /* Wait for some write requests to complete then retry */ |
2201 | wait_iff_congested(preferred_zone, BLK_RW_ASYNC, HZ/50); | 2319 | wait_iff_congested(preferred_zone, BLK_RW_ASYNC, HZ/50); |
2202 | goto rebalance; | 2320 | goto rebalance; |
@@ -2306,16 +2424,6 @@ unsigned long get_zeroed_page(gfp_t gfp_mask) | |||
2306 | } | 2424 | } |
2307 | EXPORT_SYMBOL(get_zeroed_page); | 2425 | EXPORT_SYMBOL(get_zeroed_page); |
2308 | 2426 | ||
2309 | void __pagevec_free(struct pagevec *pvec) | ||
2310 | { | ||
2311 | int i = pagevec_count(pvec); | ||
2312 | |||
2313 | while (--i >= 0) { | ||
2314 | trace_mm_pagevec_free(pvec->pages[i], pvec->cold); | ||
2315 | free_hot_cold_page(pvec->pages[i], pvec->cold); | ||
2316 | } | ||
2317 | } | ||
2318 | |||
2319 | void __free_pages(struct page *page, unsigned int order) | 2427 | void __free_pages(struct page *page, unsigned int order) |
2320 | { | 2428 | { |
2321 | if (put_page_testzero(page)) { | 2429 | if (put_page_testzero(page)) { |
@@ -3385,25 +3493,33 @@ static void setup_zone_migrate_reserve(struct zone *zone) | |||
3385 | if (page_to_nid(page) != zone_to_nid(zone)) | 3493 | if (page_to_nid(page) != zone_to_nid(zone)) |
3386 | continue; | 3494 | continue; |
3387 | 3495 | ||
3388 | /* Blocks with reserved pages will never free, skip them. */ | ||
3389 | block_end_pfn = min(pfn + pageblock_nr_pages, end_pfn); | ||
3390 | if (pageblock_is_reserved(pfn, block_end_pfn)) | ||
3391 | continue; | ||
3392 | |||
3393 | block_migratetype = get_pageblock_migratetype(page); | 3496 | block_migratetype = get_pageblock_migratetype(page); |
3394 | 3497 | ||
3395 | /* If this block is reserved, account for it */ | 3498 | /* Only test what is necessary when the reserves are not met */ |
3396 | if (reserve > 0 && block_migratetype == MIGRATE_RESERVE) { | 3499 | if (reserve > 0) { |
3397 | reserve--; | 3500 | /* |
3398 | continue; | 3501 | * Blocks with reserved pages will never free, skip |
3399 | } | 3502 | * them. |
3503 | */ | ||
3504 | block_end_pfn = min(pfn + pageblock_nr_pages, end_pfn); | ||
3505 | if (pageblock_is_reserved(pfn, block_end_pfn)) | ||
3506 | continue; | ||
3400 | 3507 | ||
3401 | /* Suitable for reserving if this block is movable */ | 3508 | /* If this block is reserved, account for it */ |
3402 | if (reserve > 0 && block_migratetype == MIGRATE_MOVABLE) { | 3509 | if (block_migratetype == MIGRATE_RESERVE) { |
3403 | set_pageblock_migratetype(page, MIGRATE_RESERVE); | 3510 | reserve--; |
3404 | move_freepages_block(zone, page, MIGRATE_RESERVE); | 3511 | continue; |
3405 | reserve--; | 3512 | } |
3406 | continue; | 3513 | |
3514 | /* Suitable for reserving if this block is movable */ | ||
3515 | if (block_migratetype == MIGRATE_MOVABLE) { | ||
3516 | set_pageblock_migratetype(page, | ||
3517 | MIGRATE_RESERVE); | ||
3518 | move_freepages_block(zone, page, | ||
3519 | MIGRATE_RESERVE); | ||
3520 | reserve--; | ||
3521 | continue; | ||
3522 | } | ||
3407 | } | 3523 | } |
3408 | 3524 | ||
3409 | /* | 3525 | /* |
@@ -4734,8 +4850,19 @@ static void calculate_totalreserve_pages(void) | |||
4734 | if (max > zone->present_pages) | 4850 | if (max > zone->present_pages) |
4735 | max = zone->present_pages; | 4851 | max = zone->present_pages; |
4736 | reserve_pages += max; | 4852 | reserve_pages += max; |
4853 | /* | ||
4854 | * Lowmem reserves are not available to | ||
4855 | * GFP_HIGHUSER page cache allocations and | ||
4856 | * kswapd tries to balance zones to their high | ||
4857 | * watermark. As a result, neither should be | ||
4858 | * regarded as dirtyable memory, to prevent a | ||
4859 | * situation where reclaim has to clean pages | ||
4860 | * in order to balance the zones. | ||
4861 | */ | ||
4862 | zone->dirty_balance_reserve = max; | ||
4737 | } | 4863 | } |
4738 | } | 4864 | } |
4865 | dirty_balance_reserve = reserve_pages; | ||
4739 | totalreserve_pages = reserve_pages; | 4866 | totalreserve_pages = reserve_pages; |
4740 | } | 4867 | } |
4741 | 4868 | ||
@@ -272,6 +272,51 @@ int anon_vma_clone(struct vm_area_struct *dst, struct vm_area_struct *src) | |||
272 | } | 272 | } |
273 | 273 | ||
274 | /* | 274 | /* |
275 | * Some rmap walk that needs to find all ptes/hugepmds without false | ||
276 | * negatives (like migrate and split_huge_page) running concurrent | ||
277 | * with operations that copy or move pagetables (like mremap() and | ||
278 | * fork()) to be safe. They depend on the anon_vma "same_anon_vma" | ||
279 | * list to be in a certain order: the dst_vma must be placed after the | ||
280 | * src_vma in the list. This is always guaranteed by fork() but | ||
281 | * mremap() needs to call this function to enforce it in case the | ||
282 | * dst_vma isn't newly allocated and chained with the anon_vma_clone() | ||
283 | * function but just an extension of a pre-existing vma through | ||
284 | * vma_merge. | ||
285 | * | ||
286 | * NOTE: the same_anon_vma list can still be changed by other | ||
287 | * processes while mremap runs because mremap doesn't hold the | ||
288 | * anon_vma mutex to prevent modifications to the list while it | ||
289 | * runs. All we need to enforce is that the relative order of this | ||
290 | * process vmas isn't changing (we don't care about other vmas | ||
291 | * order). Each vma corresponds to an anon_vma_chain structure so | ||
292 | * there's no risk that other processes calling anon_vma_moveto_tail() | ||
293 | * and changing the same_anon_vma list under mremap() will screw with | ||
294 | * the relative order of this process vmas in the list, because we | ||
295 | * they can't alter the order of any vma that belongs to this | ||
296 | * process. And there can't be another anon_vma_moveto_tail() running | ||
297 | * concurrently with mremap() coming from this process because we hold | ||
298 | * the mmap_sem for the whole mremap(). fork() ordering dependency | ||
299 | * also shouldn't be affected because fork() only cares that the | ||
300 | * parent vmas are placed in the list before the child vmas and | ||
301 | * anon_vma_moveto_tail() won't reorder vmas from either the fork() | ||
302 | * parent or child. | ||
303 | */ | ||
304 | void anon_vma_moveto_tail(struct vm_area_struct *dst) | ||
305 | { | ||
306 | struct anon_vma_chain *pavc; | ||
307 | struct anon_vma *root = NULL; | ||
308 | |||
309 | list_for_each_entry_reverse(pavc, &dst->anon_vma_chain, same_vma) { | ||
310 | struct anon_vma *anon_vma = pavc->anon_vma; | ||
311 | VM_BUG_ON(pavc->vma != dst); | ||
312 | root = lock_anon_vma_root(root, anon_vma); | ||
313 | list_del(&pavc->same_anon_vma); | ||
314 | list_add_tail(&pavc->same_anon_vma, &anon_vma->head); | ||
315 | } | ||
316 | unlock_anon_vma_root(root); | ||
317 | } | ||
318 | |||
319 | /* | ||
275 | * Attach vma to its own anon_vma, as well as to the anon_vmas that | 320 | * Attach vma to its own anon_vma, as well as to the anon_vmas that |
276 | * the corresponding VMA in the parent process is attached to. | 321 | * the corresponding VMA in the parent process is attached to. |
277 | * Returns 0 on success, non-zero on failure. | 322 | * Returns 0 on success, non-zero on failure. |
@@ -3654,6 +3654,9 @@ void __init kmem_cache_init(void) | |||
3654 | struct kmem_cache *temp_kmem_cache_node; | 3654 | struct kmem_cache *temp_kmem_cache_node; |
3655 | unsigned long kmalloc_size; | 3655 | unsigned long kmalloc_size; |
3656 | 3656 | ||
3657 | if (debug_guardpage_minorder()) | ||
3658 | slub_max_order = 0; | ||
3659 | |||
3657 | kmem_size = offsetof(struct kmem_cache, node) + | 3660 | kmem_size = offsetof(struct kmem_cache, node) + |
3658 | nr_node_ids * sizeof(struct kmem_cache_node *); | 3661 | nr_node_ids * sizeof(struct kmem_cache_node *); |
3659 | 3662 | ||
@@ -585,11 +585,10 @@ int lru_add_drain_all(void) | |||
585 | void release_pages(struct page **pages, int nr, int cold) | 585 | void release_pages(struct page **pages, int nr, int cold) |
586 | { | 586 | { |
587 | int i; | 587 | int i; |
588 | struct pagevec pages_to_free; | 588 | LIST_HEAD(pages_to_free); |
589 | struct zone *zone = NULL; | 589 | struct zone *zone = NULL; |
590 | unsigned long uninitialized_var(flags); | 590 | unsigned long uninitialized_var(flags); |
591 | 591 | ||
592 | pagevec_init(&pages_to_free, cold); | ||
593 | for (i = 0; i < nr; i++) { | 592 | for (i = 0; i < nr; i++) { |
594 | struct page *page = pages[i]; | 593 | struct page *page = pages[i]; |
595 | 594 | ||
@@ -620,19 +619,12 @@ void release_pages(struct page **pages, int nr, int cold) | |||
620 | del_page_from_lru(zone, page); | 619 | del_page_from_lru(zone, page); |
621 | } | 620 | } |
622 | 621 | ||
623 | if (!pagevec_add(&pages_to_free, page)) { | 622 | list_add(&page->lru, &pages_to_free); |
624 | if (zone) { | ||
625 | spin_unlock_irqrestore(&zone->lru_lock, flags); | ||
626 | zone = NULL; | ||
627 | } | ||
628 | __pagevec_free(&pages_to_free); | ||
629 | pagevec_reinit(&pages_to_free); | ||
630 | } | ||
631 | } | 623 | } |
632 | if (zone) | 624 | if (zone) |
633 | spin_unlock_irqrestore(&zone->lru_lock, flags); | 625 | spin_unlock_irqrestore(&zone->lru_lock, flags); |
634 | 626 | ||
635 | pagevec_free(&pages_to_free); | 627 | free_hot_cold_page_list(&pages_to_free, cold); |
636 | } | 628 | } |
637 | EXPORT_SYMBOL(release_pages); | 629 | EXPORT_SYMBOL(release_pages); |
638 | 630 | ||
diff --git a/mm/swapfile.c b/mm/swapfile.c index b1cd12060723..9520592d4231 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c | |||
@@ -667,10 +667,10 @@ int try_to_free_swap(struct page *page) | |||
667 | * original page might be freed under memory pressure, then | 667 | * original page might be freed under memory pressure, then |
668 | * later read back in from swap, now with the wrong data. | 668 | * later read back in from swap, now with the wrong data. |
669 | * | 669 | * |
670 | * Hibernation clears bits from gfp_allowed_mask to prevent | 670 | * Hibration suspends storage while it is writing the image |
671 | * memory reclaim from writing to disk, so check that here. | 671 | * to disk so check that here. |
672 | */ | 672 | */ |
673 | if (!(gfp_allowed_mask & __GFP_IO)) | 673 | if (pm_suspended_storage()) |
674 | return 0; | 674 | return 0; |
675 | 675 | ||
676 | delete_from_swap_cache(page); | 676 | delete_from_swap_cache(page); |
diff --git a/mm/vmalloc.c b/mm/vmalloc.c index 21fdf46ad5aa..877ca046f43d 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c | |||
@@ -256,7 +256,7 @@ struct vmap_area { | |||
256 | struct rb_node rb_node; /* address sorted rbtree */ | 256 | struct rb_node rb_node; /* address sorted rbtree */ |
257 | struct list_head list; /* address sorted list */ | 257 | struct list_head list; /* address sorted list */ |
258 | struct list_head purge_list; /* "lazy purge" list */ | 258 | struct list_head purge_list; /* "lazy purge" list */ |
259 | void *private; | 259 | struct vm_struct *vm; |
260 | struct rcu_head rcu_head; | 260 | struct rcu_head rcu_head; |
261 | }; | 261 | }; |
262 | 262 | ||
@@ -1285,7 +1285,7 @@ static void setup_vmalloc_vm(struct vm_struct *vm, struct vmap_area *va, | |||
1285 | vm->addr = (void *)va->va_start; | 1285 | vm->addr = (void *)va->va_start; |
1286 | vm->size = va->va_end - va->va_start; | 1286 | vm->size = va->va_end - va->va_start; |
1287 | vm->caller = caller; | 1287 | vm->caller = caller; |
1288 | va->private = vm; | 1288 | va->vm = vm; |
1289 | va->flags |= VM_VM_AREA; | 1289 | va->flags |= VM_VM_AREA; |
1290 | } | 1290 | } |
1291 | 1291 | ||
@@ -1408,7 +1408,7 @@ static struct vm_struct *find_vm_area(const void *addr) | |||
1408 | 1408 | ||
1409 | va = find_vmap_area((unsigned long)addr); | 1409 | va = find_vmap_area((unsigned long)addr); |
1410 | if (va && va->flags & VM_VM_AREA) | 1410 | if (va && va->flags & VM_VM_AREA) |
1411 | return va->private; | 1411 | return va->vm; |
1412 | 1412 | ||
1413 | return NULL; | 1413 | return NULL; |
1414 | } | 1414 | } |
@@ -1427,7 +1427,7 @@ struct vm_struct *remove_vm_area(const void *addr) | |||
1427 | 1427 | ||
1428 | va = find_vmap_area((unsigned long)addr); | 1428 | va = find_vmap_area((unsigned long)addr); |
1429 | if (va && va->flags & VM_VM_AREA) { | 1429 | if (va && va->flags & VM_VM_AREA) { |
1430 | struct vm_struct *vm = va->private; | 1430 | struct vm_struct *vm = va->vm; |
1431 | 1431 | ||
1432 | if (!(vm->flags & VM_UNLIST)) { | 1432 | if (!(vm->flags & VM_UNLIST)) { |
1433 | struct vm_struct *tmp, **p; | 1433 | struct vm_struct *tmp, **p; |
diff --git a/mm/vmscan.c b/mm/vmscan.c index 11adc890ce30..26f4a8a4e0c7 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c | |||
@@ -715,7 +715,13 @@ static enum page_references page_check_references(struct page *page, | |||
715 | */ | 715 | */ |
716 | SetPageReferenced(page); | 716 | SetPageReferenced(page); |
717 | 717 | ||
718 | if (referenced_page) | 718 | if (referenced_page || referenced_ptes > 1) |
719 | return PAGEREF_ACTIVATE; | ||
720 | |||
721 | /* | ||
722 | * Activate file-backed executable pages after first usage. | ||
723 | */ | ||
724 | if (vm_flags & VM_EXEC) | ||
719 | return PAGEREF_ACTIVATE; | 725 | return PAGEREF_ACTIVATE; |
720 | 726 | ||
721 | return PAGEREF_KEEP; | 727 | return PAGEREF_KEEP; |
@@ -728,24 +734,6 @@ static enum page_references page_check_references(struct page *page, | |||
728 | return PAGEREF_RECLAIM; | 734 | return PAGEREF_RECLAIM; |
729 | } | 735 | } |
730 | 736 | ||
731 | static noinline_for_stack void free_page_list(struct list_head *free_pages) | ||
732 | { | ||
733 | struct pagevec freed_pvec; | ||
734 | struct page *page, *tmp; | ||
735 | |||
736 | pagevec_init(&freed_pvec, 1); | ||
737 | |||
738 | list_for_each_entry_safe(page, tmp, free_pages, lru) { | ||
739 | list_del(&page->lru); | ||
740 | if (!pagevec_add(&freed_pvec, page)) { | ||
741 | __pagevec_free(&freed_pvec); | ||
742 | pagevec_reinit(&freed_pvec); | ||
743 | } | ||
744 | } | ||
745 | |||
746 | pagevec_free(&freed_pvec); | ||
747 | } | ||
748 | |||
749 | /* | 737 | /* |
750 | * shrink_page_list() returns the number of reclaimed pages | 738 | * shrink_page_list() returns the number of reclaimed pages |
751 | */ | 739 | */ |
@@ -1009,7 +997,7 @@ keep_lumpy: | |||
1009 | if (nr_dirty && nr_dirty == nr_congested && scanning_global_lru(sc)) | 997 | if (nr_dirty && nr_dirty == nr_congested && scanning_global_lru(sc)) |
1010 | zone_set_flag(zone, ZONE_CONGESTED); | 998 | zone_set_flag(zone, ZONE_CONGESTED); |
1011 | 999 | ||
1012 | free_page_list(&free_pages); | 1000 | free_hot_cold_page_list(&free_pages, 1); |
1013 | 1001 | ||
1014 | list_splice(&ret_pages, page_list); | 1002 | list_splice(&ret_pages, page_list); |
1015 | count_vm_events(PGACTIVATE, pgactivate); | 1003 | count_vm_events(PGACTIVATE, pgactivate); |
@@ -1178,14 +1166,14 @@ static unsigned long isolate_lru_pages(unsigned long nr_to_scan, | |||
1178 | * anon page which don't already have a swap slot is | 1166 | * anon page which don't already have a swap slot is |
1179 | * pointless. | 1167 | * pointless. |
1180 | */ | 1168 | */ |
1181 | if (nr_swap_pages <= 0 && PageAnon(cursor_page) && | 1169 | if (nr_swap_pages <= 0 && PageSwapBacked(cursor_page) && |
1182 | !PageSwapCache(cursor_page)) | 1170 | !PageSwapCache(cursor_page)) |
1183 | break; | 1171 | break; |
1184 | 1172 | ||
1185 | if (__isolate_lru_page(cursor_page, mode, file) == 0) { | 1173 | if (__isolate_lru_page(cursor_page, mode, file) == 0) { |
1186 | list_move(&cursor_page->lru, dst); | 1174 | list_move(&cursor_page->lru, dst); |
1187 | mem_cgroup_del_lru(cursor_page); | 1175 | mem_cgroup_del_lru(cursor_page); |
1188 | nr_taken += hpage_nr_pages(page); | 1176 | nr_taken += hpage_nr_pages(cursor_page); |
1189 | nr_lumpy_taken++; | 1177 | nr_lumpy_taken++; |
1190 | if (PageDirty(cursor_page)) | 1178 | if (PageDirty(cursor_page)) |
1191 | nr_lumpy_dirty++; | 1179 | nr_lumpy_dirty++; |
@@ -2012,8 +2000,9 @@ static inline bool should_continue_reclaim(struct zone *zone, | |||
2012 | * inactive lists are large enough, continue reclaiming | 2000 | * inactive lists are large enough, continue reclaiming |
2013 | */ | 2001 | */ |
2014 | pages_for_compaction = (2UL << sc->order); | 2002 | pages_for_compaction = (2UL << sc->order); |
2015 | inactive_lru_pages = zone_nr_lru_pages(zone, sc, LRU_INACTIVE_ANON) + | 2003 | inactive_lru_pages = zone_nr_lru_pages(zone, sc, LRU_INACTIVE_FILE); |
2016 | zone_nr_lru_pages(zone, sc, LRU_INACTIVE_FILE); | 2004 | if (nr_swap_pages > 0) |
2005 | inactive_lru_pages += zone_nr_lru_pages(zone, sc, LRU_INACTIVE_ANON); | ||
2017 | if (sc->nr_reclaimed < pages_for_compaction && | 2006 | if (sc->nr_reclaimed < pages_for_compaction && |
2018 | inactive_lru_pages > pages_for_compaction) | 2007 | inactive_lru_pages > pages_for_compaction) |
2019 | return true; | 2008 | return true; |
@@ -3448,9 +3437,10 @@ void scan_mapping_unevictable_pages(struct address_space *mapping) | |||
3448 | static void warn_scan_unevictable_pages(void) | 3437 | static void warn_scan_unevictable_pages(void) |
3449 | { | 3438 | { |
3450 | printk_once(KERN_WARNING | 3439 | printk_once(KERN_WARNING |
3451 | "The scan_unevictable_pages sysctl/node-interface has been " | 3440 | "%s: The scan_unevictable_pages sysctl/node-interface has been " |
3452 | "disabled for lack of a legitimate use case. If you have " | 3441 | "disabled for lack of a legitimate use case. If you have " |
3453 | "one, please send an email to linux-mm@kvack.org.\n"); | 3442 | "one, please send an email to linux-mm@kvack.org.\n", |
3443 | current->comm); | ||
3454 | } | 3444 | } |
3455 | 3445 | ||
3456 | /* | 3446 | /* |
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 8fda3b3f7be8..e3bfcbe8a520 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl | |||
@@ -227,7 +227,7 @@ our $Inline = qr{inline|__always_inline|noinline}; | |||
227 | our $Member = qr{->$Ident|\.$Ident|\[[^]]*\]}; | 227 | our $Member = qr{->$Ident|\.$Ident|\[[^]]*\]}; |
228 | our $Lval = qr{$Ident(?:$Member)*}; | 228 | our $Lval = qr{$Ident(?:$Member)*}; |
229 | 229 | ||
230 | our $Constant = qr{(?:[0-9]+|0x[0-9a-fA-F]+)[UL]*}; | 230 | our $Constant = qr{(?i:(?:[0-9]+|0x[0-9a-f]+)[ul]*)}; |
231 | our $Assignment = qr{(?:\*\=|/=|%=|\+=|-=|<<=|>>=|&=|\^=|\|=|=)}; | 231 | our $Assignment = qr{(?:\*\=|/=|%=|\+=|-=|<<=|>>=|&=|\^=|\|=|=)}; |
232 | our $Compare = qr{<=|>=|==|!=|<|>}; | 232 | our $Compare = qr{<=|>=|==|!=|<|>}; |
233 | our $Operators = qr{ | 233 | our $Operators = qr{ |
@@ -315,7 +315,7 @@ sub build_types { | |||
315 | $NonptrType = qr{ | 315 | $NonptrType = qr{ |
316 | (?:$Modifier\s+|const\s+)* | 316 | (?:$Modifier\s+|const\s+)* |
317 | (?: | 317 | (?: |
318 | (?:typeof|__typeof__)\s*\(\s*\**\s*$Ident\s*\)| | 318 | (?:typeof|__typeof__)\s*\([^\)]*\)| |
319 | (?:$typeTypedefs\b)| | 319 | (?:$typeTypedefs\b)| |
320 | (?:${all}\b) | 320 | (?:${all}\b) |
321 | ) | 321 | ) |
@@ -334,6 +334,7 @@ our $match_balanced_parentheses = qr/(\((?:[^\(\)]+|(-1))*\))/; | |||
334 | 334 | ||
335 | our $Typecast = qr{\s*(\(\s*$NonptrType\s*\)){0,1}\s*}; | 335 | our $Typecast = qr{\s*(\(\s*$NonptrType\s*\)){0,1}\s*}; |
336 | our $LvalOrFunc = qr{($Lval)\s*($match_balanced_parentheses{0,1})\s*}; | 336 | our $LvalOrFunc = qr{($Lval)\s*($match_balanced_parentheses{0,1})\s*}; |
337 | our $FuncArg = qr{$Typecast{0,1}($LvalOrFunc|$Constant)}; | ||
337 | 338 | ||
338 | sub deparenthesize { | 339 | sub deparenthesize { |
339 | my ($string) = @_; | 340 | my ($string) = @_; |
@@ -676,6 +677,10 @@ sub ctx_statement_block { | |||
676 | if ($off >= $len) { | 677 | if ($off >= $len) { |
677 | last; | 678 | last; |
678 | } | 679 | } |
680 | if ($level == 0 && substr($blk, $off) =~ /^.\s*#\s*define/) { | ||
681 | $level++; | ||
682 | $type = '#'; | ||
683 | } | ||
679 | } | 684 | } |
680 | $p = $c; | 685 | $p = $c; |
681 | $c = substr($blk, $off, 1); | 686 | $c = substr($blk, $off, 1); |
@@ -738,6 +743,13 @@ sub ctx_statement_block { | |||
738 | last; | 743 | last; |
739 | } | 744 | } |
740 | } | 745 | } |
746 | # Preprocessor commands end at the newline unless escaped. | ||
747 | if ($type eq '#' && $c eq "\n" && $p ne "\\") { | ||
748 | $level--; | ||
749 | $type = ''; | ||
750 | $off++; | ||
751 | last; | ||
752 | } | ||
741 | $off++; | 753 | $off++; |
742 | } | 754 | } |
743 | # We are truly at the end, so shuffle to the next line. | 755 | # We are truly at the end, so shuffle to the next line. |
@@ -1020,7 +1032,7 @@ sub annotate_values { | |||
1020 | } elsif ($cur =~ /^(\(\s*$Type\s*)\)/ && $av_pending eq '_') { | 1032 | } elsif ($cur =~ /^(\(\s*$Type\s*)\)/ && $av_pending eq '_') { |
1021 | print "CAST($1)\n" if ($dbg_values > 1); | 1033 | print "CAST($1)\n" if ($dbg_values > 1); |
1022 | push(@av_paren_type, $type); | 1034 | push(@av_paren_type, $type); |
1023 | $type = 'C'; | 1035 | $type = 'c'; |
1024 | 1036 | ||
1025 | } elsif ($cur =~ /^($Type)\s*(?:$Ident|,|\)|\(|\s*$)/) { | 1037 | } elsif ($cur =~ /^($Type)\s*(?:$Ident|,|\)|\(|\s*$)/) { |
1026 | print "DECLARE($1)\n" if ($dbg_values > 1); | 1038 | print "DECLARE($1)\n" if ($dbg_values > 1); |
@@ -1212,7 +1224,9 @@ sub possible { | |||
1212 | case| | 1224 | case| |
1213 | else| | 1225 | else| |
1214 | asm|__asm__| | 1226 | asm|__asm__| |
1215 | do | 1227 | do| |
1228 | \#| | ||
1229 | \#\#| | ||
1216 | )(?:\s|$)| | 1230 | )(?:\s|$)| |
1217 | ^(?:typedef|struct|enum)\b | 1231 | ^(?:typedef|struct|enum)\b |
1218 | )}x; | 1232 | )}x; |
@@ -1359,6 +1373,7 @@ sub process { | |||
1359 | my %suppress_ifbraces; | 1373 | my %suppress_ifbraces; |
1360 | my %suppress_whiletrailers; | 1374 | my %suppress_whiletrailers; |
1361 | my %suppress_export; | 1375 | my %suppress_export; |
1376 | my $suppress_statement = 0; | ||
1362 | 1377 | ||
1363 | # Pre-scan the patch sanitizing the lines. | 1378 | # Pre-scan the patch sanitizing the lines. |
1364 | # Pre-scan the patch looking for any __setup documentation. | 1379 | # Pre-scan the patch looking for any __setup documentation. |
@@ -1468,6 +1483,7 @@ sub process { | |||
1468 | %suppress_ifbraces = (); | 1483 | %suppress_ifbraces = (); |
1469 | %suppress_whiletrailers = (); | 1484 | %suppress_whiletrailers = (); |
1470 | %suppress_export = (); | 1485 | %suppress_export = (); |
1486 | $suppress_statement = 0; | ||
1471 | next; | 1487 | next; |
1472 | 1488 | ||
1473 | # track the line number as we move through the hunk, note that | 1489 | # track the line number as we move through the hunk, note that |
@@ -1504,9 +1520,11 @@ sub process { | |||
1504 | if ($line =~ /^diff --git.*?(\S+)$/) { | 1520 | if ($line =~ /^diff --git.*?(\S+)$/) { |
1505 | $realfile = $1; | 1521 | $realfile = $1; |
1506 | $realfile =~ s@^([^/]*)/@@; | 1522 | $realfile =~ s@^([^/]*)/@@; |
1523 | $in_commit_log = 0; | ||
1507 | } elsif ($line =~ /^\+\+\+\s+(\S+)/) { | 1524 | } elsif ($line =~ /^\+\+\+\s+(\S+)/) { |
1508 | $realfile = $1; | 1525 | $realfile = $1; |
1509 | $realfile =~ s@^([^/]*)/@@; | 1526 | $realfile =~ s@^([^/]*)/@@; |
1527 | $in_commit_log = 0; | ||
1510 | 1528 | ||
1511 | $p1_prefix = $1; | 1529 | $p1_prefix = $1; |
1512 | if (!$file && $tree && $p1_prefix ne '' && | 1530 | if (!$file && $tree && $p1_prefix ne '' && |
@@ -1546,7 +1564,8 @@ sub process { | |||
1546 | } | 1564 | } |
1547 | 1565 | ||
1548 | # Check signature styles | 1566 | # Check signature styles |
1549 | if ($line =~ /^(\s*)($signature_tags)(\s*)(.*)/) { | 1567 | if (!$in_header_lines && |
1568 | $line =~ /^(\s*)($signature_tags)(\s*)(.*)/) { | ||
1550 | my $space_before = $1; | 1569 | my $space_before = $1; |
1551 | my $sign_off = $2; | 1570 | my $sign_off = $2; |
1552 | my $space_after = $3; | 1571 | my $space_after = $3; |
@@ -1623,7 +1642,7 @@ sub process { | |||
1623 | # Check if it's the start of a commit log | 1642 | # Check if it's the start of a commit log |
1624 | # (not a header line and we haven't seen the patch filename) | 1643 | # (not a header line and we haven't seen the patch filename) |
1625 | if ($in_header_lines && $realfile =~ /^$/ && | 1644 | if ($in_header_lines && $realfile =~ /^$/ && |
1626 | $rawline !~ /^(commit\b|from\b|\w+:).+$/i) { | 1645 | $rawline !~ /^(commit\b|from\b|[\w-]+:).+$/i) { |
1627 | $in_header_lines = 0; | 1646 | $in_header_lines = 0; |
1628 | $in_commit_log = 1; | 1647 | $in_commit_log = 1; |
1629 | } | 1648 | } |
@@ -1655,19 +1674,26 @@ sub process { | |||
1655 | # Only applies when adding the entry originally, after that we do not have | 1674 | # Only applies when adding the entry originally, after that we do not have |
1656 | # sufficient context to determine whether it is indeed long enough. | 1675 | # sufficient context to determine whether it is indeed long enough. |
1657 | if ($realfile =~ /Kconfig/ && | 1676 | if ($realfile =~ /Kconfig/ && |
1658 | $line =~ /\+\s*(?:---)?help(?:---)?$/) { | 1677 | $line =~ /.\s*config\s+/) { |
1659 | my $length = 0; | 1678 | my $length = 0; |
1660 | my $cnt = $realcnt; | 1679 | my $cnt = $realcnt; |
1661 | my $ln = $linenr + 1; | 1680 | my $ln = $linenr + 1; |
1662 | my $f; | 1681 | my $f; |
1682 | my $is_start = 0; | ||
1663 | my $is_end = 0; | 1683 | my $is_end = 0; |
1664 | while ($cnt > 0 && defined $lines[$ln - 1]) { | 1684 | for (; $cnt > 0 && defined $lines[$ln - 1]; $ln++) { |
1665 | $f = $lines[$ln - 1]; | 1685 | $f = $lines[$ln - 1]; |
1666 | $cnt-- if ($lines[$ln - 1] !~ /^-/); | 1686 | $cnt-- if ($lines[$ln - 1] !~ /^-/); |
1667 | $is_end = $lines[$ln - 1] =~ /^\+/; | 1687 | $is_end = $lines[$ln - 1] =~ /^\+/; |
1668 | $ln++; | ||
1669 | 1688 | ||
1670 | next if ($f =~ /^-/); | 1689 | next if ($f =~ /^-/); |
1690 | |||
1691 | if ($lines[$ln - 1] =~ /.\s*(?:bool|tristate)\s*\"/) { | ||
1692 | $is_start = 1; | ||
1693 | } elsif ($lines[$ln - 1] =~ /.\s*(?:---)?help(?:---)?$/) { | ||
1694 | $length = -1; | ||
1695 | } | ||
1696 | |||
1671 | $f =~ s/^.//; | 1697 | $f =~ s/^.//; |
1672 | $f =~ s/#.*//; | 1698 | $f =~ s/#.*//; |
1673 | $f =~ s/^\s+//; | 1699 | $f =~ s/^\s+//; |
@@ -1679,8 +1705,8 @@ sub process { | |||
1679 | $length++; | 1705 | $length++; |
1680 | } | 1706 | } |
1681 | WARN("CONFIG_DESCRIPTION", | 1707 | WARN("CONFIG_DESCRIPTION", |
1682 | "please write a paragraph that describes the config symbol fully\n" . $herecurr) if ($is_end && $length < 4); | 1708 | "please write a paragraph that describes the config symbol fully\n" . $herecurr) if ($is_start && $is_end && $length < 4); |
1683 | #print "is_end<$is_end> length<$length>\n"; | 1709 | #print "is_start<$is_start> is_end<$is_end> length<$length>\n"; |
1684 | } | 1710 | } |
1685 | 1711 | ||
1686 | if (($realfile =~ /Makefile.*/ || $realfile =~ /Kbuild.*/) && | 1712 | if (($realfile =~ /Makefile.*/ || $realfile =~ /Kbuild.*/) && |
@@ -1792,12 +1818,24 @@ sub process { | |||
1792 | # Check for potential 'bare' types | 1818 | # Check for potential 'bare' types |
1793 | my ($stat, $cond, $line_nr_next, $remain_next, $off_next, | 1819 | my ($stat, $cond, $line_nr_next, $remain_next, $off_next, |
1794 | $realline_next); | 1820 | $realline_next); |
1795 | if ($realcnt && $line =~ /.\s*\S/) { | 1821 | #print "LINE<$line>\n"; |
1822 | if ($linenr >= $suppress_statement && | ||
1823 | $realcnt && $line =~ /.\s*\S/) { | ||
1796 | ($stat, $cond, $line_nr_next, $remain_next, $off_next) = | 1824 | ($stat, $cond, $line_nr_next, $remain_next, $off_next) = |
1797 | ctx_statement_block($linenr, $realcnt, 0); | 1825 | ctx_statement_block($linenr, $realcnt, 0); |
1798 | $stat =~ s/\n./\n /g; | 1826 | $stat =~ s/\n./\n /g; |
1799 | $cond =~ s/\n./\n /g; | 1827 | $cond =~ s/\n./\n /g; |
1800 | 1828 | ||
1829 | #print "linenr<$linenr> <$stat>\n"; | ||
1830 | # If this statement has no statement boundaries within | ||
1831 | # it there is no point in retrying a statement scan | ||
1832 | # until we hit end of it. | ||
1833 | my $frag = $stat; $frag =~ s/;+\s*$//; | ||
1834 | if ($frag !~ /(?:{|;)/) { | ||
1835 | #print "skip<$line_nr_next>\n"; | ||
1836 | $suppress_statement = $line_nr_next; | ||
1837 | } | ||
1838 | |||
1801 | # Find the real next line. | 1839 | # Find the real next line. |
1802 | $realline_next = $line_nr_next; | 1840 | $realline_next = $line_nr_next; |
1803 | if (defined $realline_next && | 1841 | if (defined $realline_next && |
@@ -1923,6 +1961,9 @@ sub process { | |||
1923 | 1961 | ||
1924 | # Check relative indent for conditionals and blocks. | 1962 | # Check relative indent for conditionals and blocks. |
1925 | if ($line =~ /\b(?:(?:if|while|for)\s*\(|do\b)/ && $line !~ /^.\s*#/ && $line !~ /\}\s*while\s*/) { | 1963 | if ($line =~ /\b(?:(?:if|while|for)\s*\(|do\b)/ && $line !~ /^.\s*#/ && $line !~ /\}\s*while\s*/) { |
1964 | ($stat, $cond, $line_nr_next, $remain_next, $off_next) = | ||
1965 | ctx_statement_block($linenr, $realcnt, 0) | ||
1966 | if (!defined $stat); | ||
1926 | my ($s, $c) = ($stat, $cond); | 1967 | my ($s, $c) = ($stat, $cond); |
1927 | 1968 | ||
1928 | substr($s, 0, length($c), ''); | 1969 | substr($s, 0, length($c), ''); |
@@ -2090,7 +2131,7 @@ sub process { | |||
2090 | # XXX(foo); | 2131 | # XXX(foo); |
2091 | # EXPORT_SYMBOL(something_foo); | 2132 | # EXPORT_SYMBOL(something_foo); |
2092 | my $name = $1; | 2133 | my $name = $1; |
2093 | if ($stat =~ /^.([A-Z_]+)\s*\(\s*($Ident)/ && | 2134 | if ($stat =~ /^(?:.\s*}\s*\n)?.([A-Z_]+)\s*\(\s*($Ident)/ && |
2094 | $name =~ /^${Ident}_$2/) { | 2135 | $name =~ /^${Ident}_$2/) { |
2095 | #print "FOO C name<$name>\n"; | 2136 | #print "FOO C name<$name>\n"; |
2096 | $suppress_export{$realline_next} = 1; | 2137 | $suppress_export{$realline_next} = 1; |
@@ -2168,8 +2209,9 @@ sub process { | |||
2168 | 2209 | ||
2169 | # * goes on variable not on type | 2210 | # * goes on variable not on type |
2170 | # (char*[ const]) | 2211 | # (char*[ const]) |
2171 | if ($line =~ m{\($NonptrType(\s*(?:$Modifier\b\s*|\*\s*)+)\)}) { | 2212 | while ($line =~ m{(\($NonptrType(\s*(?:$Modifier\b\s*|\*\s*)+)\))}g) { |
2172 | my ($from, $to) = ($1, $1); | 2213 | #print "AA<$1>\n"; |
2214 | my ($from, $to) = ($2, $2); | ||
2173 | 2215 | ||
2174 | # Should start with a space. | 2216 | # Should start with a space. |
2175 | $to =~ s/^(\S)/ $1/; | 2217 | $to =~ s/^(\S)/ $1/; |
@@ -2184,8 +2226,10 @@ sub process { | |||
2184 | ERROR("POINTER_LOCATION", | 2226 | ERROR("POINTER_LOCATION", |
2185 | "\"(foo$from)\" should be \"(foo$to)\"\n" . $herecurr); | 2227 | "\"(foo$from)\" should be \"(foo$to)\"\n" . $herecurr); |
2186 | } | 2228 | } |
2187 | } elsif ($line =~ m{\b$NonptrType(\s*(?:$Modifier\b\s*|\*\s*)+)($Ident)}) { | 2229 | } |
2188 | my ($from, $to, $ident) = ($1, $1, $2); | 2230 | while ($line =~ m{(\b$NonptrType(\s*(?:$Modifier\b\s*|\*\s*)+)($Ident))}g) { |
2231 | #print "BB<$1>\n"; | ||
2232 | my ($from, $to, $ident) = ($2, $2, $3); | ||
2189 | 2233 | ||
2190 | # Should start with a space. | 2234 | # Should start with a space. |
2191 | $to =~ s/^(\S)/ $1/; | 2235 | $to =~ s/^(\S)/ $1/; |
@@ -2568,7 +2612,7 @@ sub process { | |||
2568 | # Flatten any parentheses | 2612 | # Flatten any parentheses |
2569 | $value =~ s/\(/ \(/g; | 2613 | $value =~ s/\(/ \(/g; |
2570 | $value =~ s/\)/\) /g; | 2614 | $value =~ s/\)/\) /g; |
2571 | while ($value =~ s/\[[^\{\}]*\]/1/ || | 2615 | while ($value =~ s/\[[^\[\]]*\]/1/ || |
2572 | $value !~ /(?:$Ident|-?$Constant)\s* | 2616 | $value !~ /(?:$Ident|-?$Constant)\s* |
2573 | $Compare\s* | 2617 | $Compare\s* |
2574 | (?:$Ident|-?$Constant)/x && | 2618 | (?:$Ident|-?$Constant)/x && |
@@ -2593,28 +2637,6 @@ sub process { | |||
2593 | } | 2637 | } |
2594 | } | 2638 | } |
2595 | 2639 | ||
2596 | # typecasts on min/max could be min_t/max_t | ||
2597 | if ($line =~ /^\+(?:.*?)\b(min|max)\s*\($Typecast{0,1}($LvalOrFunc)\s*,\s*$Typecast{0,1}($LvalOrFunc)\s*\)/) { | ||
2598 | if (defined $2 || defined $8) { | ||
2599 | my $call = $1; | ||
2600 | my $cast1 = deparenthesize($2); | ||
2601 | my $arg1 = $3; | ||
2602 | my $cast2 = deparenthesize($8); | ||
2603 | my $arg2 = $9; | ||
2604 | my $cast; | ||
2605 | |||
2606 | if ($cast1 ne "" && $cast2 ne "") { | ||
2607 | $cast = "$cast1 or $cast2"; | ||
2608 | } elsif ($cast1 ne "") { | ||
2609 | $cast = $cast1; | ||
2610 | } else { | ||
2611 | $cast = $cast2; | ||
2612 | } | ||
2613 | WARN("MINMAX", | ||
2614 | "$call() should probably be ${call}_t($cast, $arg1, $arg2)\n" . $herecurr); | ||
2615 | } | ||
2616 | } | ||
2617 | |||
2618 | # Need a space before open parenthesis after if, while etc | 2640 | # Need a space before open parenthesis after if, while etc |
2619 | if ($line=~/\b(if|while|for|switch)\(/) { | 2641 | if ($line=~/\b(if|while|for|switch)\(/) { |
2620 | ERROR("SPACING", "space required before the open parenthesis '('\n" . $herecurr); | 2642 | ERROR("SPACING", "space required before the open parenthesis '('\n" . $herecurr); |
@@ -2623,6 +2645,9 @@ sub process { | |||
2623 | # Check for illegal assignment in if conditional -- and check for trailing | 2645 | # Check for illegal assignment in if conditional -- and check for trailing |
2624 | # statements after the conditional. | 2646 | # statements after the conditional. |
2625 | if ($line =~ /do\s*(?!{)/) { | 2647 | if ($line =~ /do\s*(?!{)/) { |
2648 | ($stat, $cond, $line_nr_next, $remain_next, $off_next) = | ||
2649 | ctx_statement_block($linenr, $realcnt, 0) | ||
2650 | if (!defined $stat); | ||
2626 | my ($stat_next) = ctx_statement_block($line_nr_next, | 2651 | my ($stat_next) = ctx_statement_block($line_nr_next, |
2627 | $remain_next, $off_next); | 2652 | $remain_next, $off_next); |
2628 | $stat_next =~ s/\n./\n /g; | 2653 | $stat_next =~ s/\n./\n /g; |
@@ -2778,47 +2803,13 @@ sub process { | |||
2778 | my $cnt = $realcnt; | 2803 | my $cnt = $realcnt; |
2779 | my ($off, $dstat, $dcond, $rest); | 2804 | my ($off, $dstat, $dcond, $rest); |
2780 | my $ctx = ''; | 2805 | my $ctx = ''; |
2781 | |||
2782 | my $args = defined($1); | ||
2783 | |||
2784 | # Find the end of the macro and limit our statement | ||
2785 | # search to that. | ||
2786 | while ($cnt > 0 && defined $lines[$ln - 1] && | ||
2787 | $lines[$ln - 1] =~ /^(?:-|..*\\$)/) | ||
2788 | { | ||
2789 | $ctx .= $rawlines[$ln - 1] . "\n"; | ||
2790 | $cnt-- if ($lines[$ln - 1] !~ /^-/); | ||
2791 | $ln++; | ||
2792 | } | ||
2793 | $ctx .= $rawlines[$ln - 1]; | ||
2794 | |||
2795 | ($dstat, $dcond, $ln, $cnt, $off) = | 2806 | ($dstat, $dcond, $ln, $cnt, $off) = |
2796 | ctx_statement_block($linenr, $ln - $linenr + 1, 0); | 2807 | ctx_statement_block($linenr, $realcnt, 0); |
2808 | $ctx = $dstat; | ||
2797 | #print "dstat<$dstat> dcond<$dcond> cnt<$cnt> off<$off>\n"; | 2809 | #print "dstat<$dstat> dcond<$dcond> cnt<$cnt> off<$off>\n"; |
2798 | #print "LINE<$lines[$ln-1]> len<" . length($lines[$ln-1]) . "\n"; | 2810 | #print "LINE<$lines[$ln-1]> len<" . length($lines[$ln-1]) . "\n"; |
2799 | 2811 | ||
2800 | # Extract the remainder of the define (if any) and | 2812 | $dstat =~ s/^.\s*\#\s*define\s+$Ident(?:\([^\)]*\))?\s*//; |
2801 | # rip off surrounding spaces, and trailing \'s. | ||
2802 | $rest = ''; | ||
2803 | while ($off != 0 || ($cnt > 0 && $rest =~ /\\\s*$/)) { | ||
2804 | #print "ADDING cnt<$cnt> $off <" . substr($lines[$ln - 1], $off) . "> rest<$rest>\n"; | ||
2805 | if ($off != 0 || $lines[$ln - 1] !~ /^-/) { | ||
2806 | $rest .= substr($lines[$ln - 1], $off) . "\n"; | ||
2807 | $cnt--; | ||
2808 | } | ||
2809 | $ln++; | ||
2810 | $off = 0; | ||
2811 | } | ||
2812 | $rest =~ s/\\\n.//g; | ||
2813 | $rest =~ s/^\s*//s; | ||
2814 | $rest =~ s/\s*$//s; | ||
2815 | |||
2816 | # Clean up the original statement. | ||
2817 | if ($args) { | ||
2818 | substr($dstat, 0, length($dcond), ''); | ||
2819 | } else { | ||
2820 | $dstat =~ s/^.\s*\#\s*define\s+$Ident\s*//; | ||
2821 | } | ||
2822 | $dstat =~ s/$;//g; | 2813 | $dstat =~ s/$;//g; |
2823 | $dstat =~ s/\\\n.//g; | 2814 | $dstat =~ s/\\\n.//g; |
2824 | $dstat =~ s/^\s*//s; | 2815 | $dstat =~ s/^\s*//s; |
@@ -2827,7 +2818,7 @@ sub process { | |||
2827 | # Flatten any parentheses and braces | 2818 | # Flatten any parentheses and braces |
2828 | while ($dstat =~ s/\([^\(\)]*\)/1/ || | 2819 | while ($dstat =~ s/\([^\(\)]*\)/1/ || |
2829 | $dstat =~ s/\{[^\{\}]*\}/1/ || | 2820 | $dstat =~ s/\{[^\{\}]*\}/1/ || |
2830 | $dstat =~ s/\[[^\{\}]*\]/1/) | 2821 | $dstat =~ s/\[[^\[\]]*\]/1/) |
2831 | { | 2822 | { |
2832 | } | 2823 | } |
2833 | 2824 | ||
@@ -2844,23 +2835,32 @@ sub process { | |||
2844 | ^\"|\"$ | 2835 | ^\"|\"$ |
2845 | }x; | 2836 | }x; |
2846 | #print "REST<$rest> dstat<$dstat> ctx<$ctx>\n"; | 2837 | #print "REST<$rest> dstat<$dstat> ctx<$ctx>\n"; |
2847 | if ($rest ne '' && $rest ne ',') { | 2838 | if ($dstat ne '' && |
2848 | if ($rest !~ /while\s*\(/ && | 2839 | $dstat !~ /^(?:$Ident|-?$Constant),$/ && # 10, // foo(), |
2849 | $dstat !~ /$exceptions/) | 2840 | $dstat !~ /^(?:$Ident|-?$Constant);$/ && # foo(); |
2850 | { | 2841 | $dstat !~ /^(?:$Ident|-?$Constant)$/ && # 10 // foo() |
2851 | ERROR("MULTISTATEMENT_MACRO_USE_DO_WHILE", | 2842 | $dstat !~ /$exceptions/ && |
2852 | "Macros with multiple statements should be enclosed in a do - while loop\n" . "$here\n$ctx\n"); | 2843 | $dstat !~ /^\.$Ident\s*=/ && # .foo = |
2844 | $dstat !~ /^do\s*$Constant\s*while\s*$Constant;?$/ && # do {...} while (...); // do {...} while (...) | ||
2845 | $dstat !~ /^for\s*$Constant$/ && # for (...) | ||
2846 | $dstat !~ /^for\s*$Constant\s+(?:$Ident|-?$Constant)$/ && # for (...) bar() | ||
2847 | $dstat !~ /^do\s*{/ && # do {... | ||
2848 | $dstat !~ /^\({/) # ({... | ||
2849 | { | ||
2850 | $ctx =~ s/\n*$//; | ||
2851 | my $herectx = $here . "\n"; | ||
2852 | my $cnt = statement_rawlines($ctx); | ||
2853 | |||
2854 | for (my $n = 0; $n < $cnt; $n++) { | ||
2855 | $herectx .= raw_line($linenr, $n) . "\n"; | ||
2853 | } | 2856 | } |
2854 | 2857 | ||
2855 | } elsif ($ctx !~ /;/) { | 2858 | if ($dstat =~ /;/) { |
2856 | if ($dstat ne '' && | 2859 | ERROR("MULTISTATEMENT_MACRO_USE_DO_WHILE", |
2857 | $dstat !~ /^(?:$Ident|-?$Constant)$/ && | 2860 | "Macros with multiple statements should be enclosed in a do - while loop\n" . "$herectx"); |
2858 | $dstat !~ /$exceptions/ && | 2861 | } else { |
2859 | $dstat !~ /^\.$Ident\s*=/ && | ||
2860 | $dstat =~ /$Operators/) | ||
2861 | { | ||
2862 | ERROR("COMPLEX_MACRO", | 2862 | ERROR("COMPLEX_MACRO", |
2863 | "Macros with complex values should be enclosed in parenthesis\n" . "$here\n$ctx\n"); | 2863 | "Macros with complex values should be enclosed in parenthesis\n" . "$herectx"); |
2864 | } | 2864 | } |
2865 | } | 2865 | } |
2866 | } | 2866 | } |
@@ -3111,6 +3111,12 @@ sub process { | |||
3111 | "__aligned(size) is preferred over __attribute__((aligned(size)))\n" . $herecurr); | 3111 | "__aligned(size) is preferred over __attribute__((aligned(size)))\n" . $herecurr); |
3112 | } | 3112 | } |
3113 | 3113 | ||
3114 | # Check for __attribute__ format(printf, prefer __printf | ||
3115 | if ($line =~ /\b__attribute__\s*\(\s*\(\s*format\s*\(\s*printf/) { | ||
3116 | WARN("PREFER_PRINTF", | ||
3117 | "__printf(string-index, first-to-check) is preferred over __attribute__((format(printf, string-index, first-to-check)))\n" . $herecurr); | ||
3118 | } | ||
3119 | |||
3114 | # check for sizeof(&) | 3120 | # check for sizeof(&) |
3115 | if ($line =~ /\bsizeof\s*\(\s*\&/) { | 3121 | if ($line =~ /\bsizeof\s*\(\s*\&/) { |
3116 | WARN("SIZEOF_ADDRESS", | 3122 | WARN("SIZEOF_ADDRESS", |
@@ -3123,6 +3129,46 @@ sub process { | |||
3123 | "Avoid line continuations in quoted strings\n" . $herecurr); | 3129 | "Avoid line continuations in quoted strings\n" . $herecurr); |
3124 | } | 3130 | } |
3125 | 3131 | ||
3132 | # Check for misused memsets | ||
3133 | if (defined $stat && | ||
3134 | $stat =~ /^\+(?:.*?)\bmemset\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*$FuncArg\s*\)/s) { | ||
3135 | |||
3136 | my $ms_addr = $2; | ||
3137 | my $ms_val = $8; | ||
3138 | my $ms_size = $14; | ||
3139 | |||
3140 | if ($ms_size =~ /^(0x|)0$/i) { | ||
3141 | ERROR("MEMSET", | ||
3142 | "memset to 0's uses 0 as the 2nd argument, not the 3rd\n" . "$here\n$stat\n"); | ||
3143 | } elsif ($ms_size =~ /^(0x|)1$/i) { | ||
3144 | WARN("MEMSET", | ||
3145 | "single byte memset is suspicious. Swapped 2nd/3rd argument?\n" . "$here\n$stat\n"); | ||
3146 | } | ||
3147 | } | ||
3148 | |||
3149 | # typecasts on min/max could be min_t/max_t | ||
3150 | if (defined $stat && | ||
3151 | $stat =~ /^\+(?:.*?)\b(min|max)\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\)/) { | ||
3152 | if (defined $2 || defined $8) { | ||
3153 | my $call = $1; | ||
3154 | my $cast1 = deparenthesize($2); | ||
3155 | my $arg1 = $3; | ||
3156 | my $cast2 = deparenthesize($8); | ||
3157 | my $arg2 = $9; | ||
3158 | my $cast; | ||
3159 | |||
3160 | if ($cast1 ne "" && $cast2 ne "") { | ||
3161 | $cast = "$cast1 or $cast2"; | ||
3162 | } elsif ($cast1 ne "") { | ||
3163 | $cast = $cast1; | ||
3164 | } else { | ||
3165 | $cast = $cast2; | ||
3166 | } | ||
3167 | WARN("MINMAX", | ||
3168 | "$call() should probably be ${call}_t($cast, $arg1, $arg2)\n" . "$here\n$stat\n"); | ||
3169 | } | ||
3170 | } | ||
3171 | |||
3126 | # check for new externs in .c files. | 3172 | # check for new externs in .c files. |
3127 | if ($realfile =~ /\.c$/ && defined $stat && | 3173 | if ($realfile =~ /\.c$/ && defined $stat && |
3128 | $stat =~ /^.\s*(?:extern\s+)?$Type\s+($Ident)(\s*)\(/s) | 3174 | $stat =~ /^.\s*(?:extern\s+)?$Type\s+($Ident)(\s*)\(/s) |
@@ -3294,12 +3340,6 @@ sub process { | |||
3294 | WARN("EXPORTED_WORLD_WRITABLE", | 3340 | WARN("EXPORTED_WORLD_WRITABLE", |
3295 | "Exporting world writable files is usually an error. Consider more restrictive permissions.\n" . $herecurr); | 3341 | "Exporting world writable files is usually an error. Consider more restrictive permissions.\n" . $herecurr); |
3296 | } | 3342 | } |
3297 | |||
3298 | # Check for memset with swapped arguments | ||
3299 | if ($line =~ /memset.*\,(\ |)(0x|)0(\ |0|)\);/) { | ||
3300 | ERROR("MEMSET", | ||
3301 | "memset size is 3rd argument, not the second.\n" . $herecurr); | ||
3302 | } | ||
3303 | } | 3343 | } |
3304 | 3344 | ||
3305 | # If we have no input at all, then there is nothing to report on | 3345 | # If we have no input at all, then there is nothing to report on |
diff --git a/scripts/get_maintainer.pl b/scripts/get_maintainer.pl index 4594f3341051..f32a04c4c5bc 100755 --- a/scripts/get_maintainer.pl +++ b/scripts/get_maintainer.pl | |||
@@ -95,7 +95,7 @@ my %VCS_cmds_git = ( | |||
95 | "execute_cmd" => \&git_execute_cmd, | 95 | "execute_cmd" => \&git_execute_cmd, |
96 | "available" => '(which("git") ne "") && (-d ".git")', | 96 | "available" => '(which("git") ne "") && (-d ".git")', |
97 | "find_signers_cmd" => | 97 | "find_signers_cmd" => |
98 | "git log --no-color --since=\$email_git_since " . | 98 | "git log --no-color --follow --since=\$email_git_since " . |
99 | '--format="GitCommit: %H%n' . | 99 | '--format="GitCommit: %H%n' . |
100 | 'GitAuthor: %an <%ae>%n' . | 100 | 'GitAuthor: %an <%ae>%n' . |
101 | 'GitDate: %aD%n' . | 101 | 'GitDate: %aD%n' . |
diff --git a/tools/perf/Documentation/examples.txt b/tools/perf/Documentation/examples.txt index 8eb6c489fb15..77f952762426 100644 --- a/tools/perf/Documentation/examples.txt +++ b/tools/perf/Documentation/examples.txt | |||
@@ -17,8 +17,8 @@ titan:~> perf list | |||
17 | kmem:kmem_cache_alloc_node [Tracepoint event] | 17 | kmem:kmem_cache_alloc_node [Tracepoint event] |
18 | kmem:kfree [Tracepoint event] | 18 | kmem:kfree [Tracepoint event] |
19 | kmem:kmem_cache_free [Tracepoint event] | 19 | kmem:kmem_cache_free [Tracepoint event] |
20 | kmem:mm_page_free_direct [Tracepoint event] | 20 | kmem:mm_page_free [Tracepoint event] |
21 | kmem:mm_pagevec_free [Tracepoint event] | 21 | kmem:mm_page_free_batched [Tracepoint event] |
22 | kmem:mm_page_alloc [Tracepoint event] | 22 | kmem:mm_page_alloc [Tracepoint event] |
23 | kmem:mm_page_alloc_zone_locked [Tracepoint event] | 23 | kmem:mm_page_alloc_zone_locked [Tracepoint event] |
24 | kmem:mm_page_pcpu_drain [Tracepoint event] | 24 | kmem:mm_page_pcpu_drain [Tracepoint event] |
@@ -29,15 +29,15 @@ measured. For example the page alloc/free properties of a 'hackbench | |||
29 | run' are: | 29 | run' are: |
30 | 30 | ||
31 | titan:~> perf stat -e kmem:mm_page_pcpu_drain -e kmem:mm_page_alloc | 31 | titan:~> perf stat -e kmem:mm_page_pcpu_drain -e kmem:mm_page_alloc |
32 | -e kmem:mm_pagevec_free -e kmem:mm_page_free_direct ./hackbench 10 | 32 | -e kmem:mm_page_free_batched -e kmem:mm_page_free ./hackbench 10 |
33 | Time: 0.575 | 33 | Time: 0.575 |
34 | 34 | ||
35 | Performance counter stats for './hackbench 10': | 35 | Performance counter stats for './hackbench 10': |
36 | 36 | ||
37 | 13857 kmem:mm_page_pcpu_drain | 37 | 13857 kmem:mm_page_pcpu_drain |
38 | 27576 kmem:mm_page_alloc | 38 | 27576 kmem:mm_page_alloc |
39 | 6025 kmem:mm_pagevec_free | 39 | 6025 kmem:mm_page_free_batched |
40 | 20934 kmem:mm_page_free_direct | 40 | 20934 kmem:mm_page_free |
41 | 41 | ||
42 | 0.613972165 seconds time elapsed | 42 | 0.613972165 seconds time elapsed |
43 | 43 | ||
@@ -45,8 +45,8 @@ You can observe the statistical properties as well, by using the | |||
45 | 'repeat the workload N times' feature of perf stat: | 45 | 'repeat the workload N times' feature of perf stat: |
46 | 46 | ||
47 | titan:~> perf stat --repeat 5 -e kmem:mm_page_pcpu_drain -e | 47 | titan:~> perf stat --repeat 5 -e kmem:mm_page_pcpu_drain -e |
48 | kmem:mm_page_alloc -e kmem:mm_pagevec_free -e | 48 | kmem:mm_page_alloc -e kmem:mm_page_free_batched -e |
49 | kmem:mm_page_free_direct ./hackbench 10 | 49 | kmem:mm_page_free ./hackbench 10 |
50 | Time: 0.627 | 50 | Time: 0.627 |
51 | Time: 0.644 | 51 | Time: 0.644 |
52 | Time: 0.564 | 52 | Time: 0.564 |
@@ -57,8 +57,8 @@ You can observe the statistical properties as well, by using the | |||
57 | 57 | ||
58 | 12920 kmem:mm_page_pcpu_drain ( +- 3.359% ) | 58 | 12920 kmem:mm_page_pcpu_drain ( +- 3.359% ) |
59 | 25035 kmem:mm_page_alloc ( +- 3.783% ) | 59 | 25035 kmem:mm_page_alloc ( +- 3.783% ) |
60 | 6104 kmem:mm_pagevec_free ( +- 0.934% ) | 60 | 6104 kmem:mm_page_free_batched ( +- 0.934% ) |
61 | 18376 kmem:mm_page_free_direct ( +- 4.941% ) | 61 | 18376 kmem:mm_page_free ( +- 4.941% ) |
62 | 62 | ||
63 | 0.643954516 seconds time elapsed ( +- 2.363% ) | 63 | 0.643954516 seconds time elapsed ( +- 2.363% ) |
64 | 64 | ||
@@ -158,15 +158,15 @@ Or you can observe the whole system's page allocations for 10 | |||
158 | seconds: | 158 | seconds: |
159 | 159 | ||
160 | titan:~/git> perf stat -a -e kmem:mm_page_pcpu_drain -e | 160 | titan:~/git> perf stat -a -e kmem:mm_page_pcpu_drain -e |
161 | kmem:mm_page_alloc -e kmem:mm_pagevec_free -e | 161 | kmem:mm_page_alloc -e kmem:mm_page_free_batched -e |
162 | kmem:mm_page_free_direct sleep 10 | 162 | kmem:mm_page_free sleep 10 |
163 | 163 | ||
164 | Performance counter stats for 'sleep 10': | 164 | Performance counter stats for 'sleep 10': |
165 | 165 | ||
166 | 171585 kmem:mm_page_pcpu_drain | 166 | 171585 kmem:mm_page_pcpu_drain |
167 | 322114 kmem:mm_page_alloc | 167 | 322114 kmem:mm_page_alloc |
168 | 73623 kmem:mm_pagevec_free | 168 | 73623 kmem:mm_page_free_batched |
169 | 254115 kmem:mm_page_free_direct | 169 | 254115 kmem:mm_page_free |
170 | 170 | ||
171 | 10.000591410 seconds time elapsed | 171 | 10.000591410 seconds time elapsed |
172 | 172 | ||
@@ -174,15 +174,15 @@ Or observe how fluctuating the page allocations are, via statistical | |||
174 | analysis done over ten 1-second intervals: | 174 | analysis done over ten 1-second intervals: |
175 | 175 | ||
176 | titan:~/git> perf stat --repeat 10 -a -e kmem:mm_page_pcpu_drain -e | 176 | titan:~/git> perf stat --repeat 10 -a -e kmem:mm_page_pcpu_drain -e |
177 | kmem:mm_page_alloc -e kmem:mm_pagevec_free -e | 177 | kmem:mm_page_alloc -e kmem:mm_page_free_batched -e |
178 | kmem:mm_page_free_direct sleep 1 | 178 | kmem:mm_page_free sleep 1 |
179 | 179 | ||
180 | Performance counter stats for 'sleep 1' (10 runs): | 180 | Performance counter stats for 'sleep 1' (10 runs): |
181 | 181 | ||
182 | 17254 kmem:mm_page_pcpu_drain ( +- 3.709% ) | 182 | 17254 kmem:mm_page_pcpu_drain ( +- 3.709% ) |
183 | 34394 kmem:mm_page_alloc ( +- 4.617% ) | 183 | 34394 kmem:mm_page_alloc ( +- 4.617% ) |
184 | 7509 kmem:mm_pagevec_free ( +- 4.820% ) | 184 | 7509 kmem:mm_page_free_batched ( +- 4.820% ) |
185 | 25653 kmem:mm_page_free_direct ( +- 3.672% ) | 185 | 25653 kmem:mm_page_free ( +- 3.672% ) |
186 | 186 | ||
187 | 1.058135029 seconds time elapsed ( +- 3.089% ) | 187 | 1.058135029 seconds time elapsed ( +- 3.089% ) |
188 | 188 | ||