diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-10-26 20:15:20 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-10-26 20:15:20 -0400 |
commit | 31453a9764f7e2a72a6e2c502ace586e2663a68c (patch) | |
tree | 5d4db63de5b4b85d1ffdab4e95a75175a784a10a | |
parent | f9ba5375a8aae4aeea6be15df77e24707a429812 (diff) | |
parent | 93ed0e2d07b25aff4db1d61bfbcd1e82074c0ad5 (diff) |
Merge branch 'akpm-incoming-1'
* akpm-incoming-1: (176 commits)
scripts/checkpatch.pl: add check for declaration of pci_device_id
scripts/checkpatch.pl: add warnings for static char that could be static const char
checkpatch: version 0.31
checkpatch: statement/block context analyser should look at sanitised lines
checkpatch: handle EXPORT_SYMBOL for DEVICE_ATTR and similar
checkpatch: clean up structure definition macro handline
checkpatch: update copyright dates
checkpatch: Add additional attribute #defines
checkpatch: check for incorrect permissions
checkpatch: ensure kconfig help checks only apply when we are adding help
checkpatch: simplify and consolidate "missing space after" checks
checkpatch: add check for space after struct, union, and enum
checkpatch: returning errno typically should be negative
checkpatch: handle casts better fixing false categorisation of : as binary
checkpatch: ensure we do not collapse bracketed sections into constants
checkpatch: suggest cleanpatch and cleanfile when appropriate
checkpatch: types may sit on a line on their own
checkpatch: fix regressions in "fix handling of leading spaces"
div64_u64(): improve precision on 32bit platforms
lib/parser: cleanup match_number()
...
209 files changed, 7228 insertions, 1699 deletions
diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt index a6aca8740883..a563b74c7aef 100644 --- a/Documentation/filesystems/proc.txt +++ b/Documentation/filesystems/proc.txt | |||
@@ -374,13 +374,13 @@ Swap: 0 kB | |||
374 | KernelPageSize: 4 kB | 374 | KernelPageSize: 4 kB |
375 | MMUPageSize: 4 kB | 375 | MMUPageSize: 4 kB |
376 | 376 | ||
377 | The first of these lines shows the same information as is displayed for the | 377 | The first of these lines shows the same information as is displayed for the |
378 | mapping in /proc/PID/maps. The remaining lines show the size of the mapping, | 378 | mapping in /proc/PID/maps. The remaining lines show the size of the mapping |
379 | the amount of the mapping that is currently resident in RAM, the "proportional | 379 | (size), the amount of the mapping that is currently resident in RAM (RSS), the |
380 | set size” (divide each shared page by the number of processes sharing it), the | 380 | process' proportional share of this mapping (PSS), the number of clean and |
381 | number of clean and dirty shared pages in the mapping, and the number of clean | 381 | dirty shared pages in the mapping, and the number of clean and dirty private |
382 | and dirty private pages in the mapping. The "Referenced" indicates the amount | 382 | pages in the mapping. The "Referenced" indicates the amount of memory |
383 | of memory currently marked as referenced or accessed. | 383 | currently marked as referenced or accessed. |
384 | 384 | ||
385 | This file is only present if the CONFIG_MMU kernel configuration option is | 385 | This file is only present if the CONFIG_MMU kernel configuration option is |
386 | enabled. | 386 | enabled. |
diff --git a/Documentation/misc-devices/apds990x.txt b/Documentation/misc-devices/apds990x.txt new file mode 100644 index 000000000000..d5408cade32f --- /dev/null +++ b/Documentation/misc-devices/apds990x.txt | |||
@@ -0,0 +1,111 @@ | |||
1 | Kernel driver apds990x | ||
2 | ====================== | ||
3 | |||
4 | Supported chips: | ||
5 | Avago APDS990X | ||
6 | |||
7 | Data sheet: | ||
8 | Not freely available | ||
9 | |||
10 | Author: | ||
11 | Samu Onkalo <samu.p.onkalo@nokia.com> | ||
12 | |||
13 | Description | ||
14 | ----------- | ||
15 | |||
16 | APDS990x is a combined ambient light and proximity sensor. ALS and proximity | ||
17 | functionality are highly connected. ALS measurement path must be running | ||
18 | while the proximity functionality is enabled. | ||
19 | |||
20 | ALS produces raw measurement values for two channels: Clear channel | ||
21 | (infrared + visible light) and IR only. However, threshold comparisons happen | ||
22 | using clear channel only. Lux value and the threshold level on the HW | ||
23 | might vary quite much depending the spectrum of the light source. | ||
24 | |||
25 | Driver makes necessary conversions to both directions so that user handles | ||
26 | only lux values. Lux value is calculated using information from the both | ||
27 | channels. HW threshold level is calculated from the given lux value to match | ||
28 | with current type of the lightning. Sometimes inaccuracy of the estimations | ||
29 | lead to false interrupt, but that doesn't harm. | ||
30 | |||
31 | ALS contains 4 different gain steps. Driver automatically | ||
32 | selects suitable gain step. After each measurement, reliability of the results | ||
33 | is estimated and new measurement is trigged if necessary. | ||
34 | |||
35 | Platform data can provide tuned values to the conversion formulas if | ||
36 | values are known. Otherwise plain sensor default values are used. | ||
37 | |||
38 | Proximity side is little bit simpler. There is no need for complex conversions. | ||
39 | It produces directly usable values. | ||
40 | |||
41 | Driver controls chip operational state using pm_runtime framework. | ||
42 | Voltage regulators are controlled based on chip operational state. | ||
43 | |||
44 | SYSFS | ||
45 | ----- | ||
46 | |||
47 | |||
48 | chip_id | ||
49 | RO - shows detected chip type and version | ||
50 | |||
51 | power_state | ||
52 | RW - enable / disable chip. Uses counting logic | ||
53 | 1 enables the chip | ||
54 | 0 disables the chip | ||
55 | lux0_input | ||
56 | RO - measured lux value | ||
57 | sysfs_notify called when threshold interrupt occurs | ||
58 | |||
59 | lux0_sensor_range | ||
60 | RO - lux0_input max value. Actually never reaches since sensor tends | ||
61 | to saturate much before that. Real max value varies depending | ||
62 | on the light spectrum etc. | ||
63 | |||
64 | lux0_rate | ||
65 | RW - measurement rate in Hz | ||
66 | |||
67 | lux0_rate_avail | ||
68 | RO - supported measurement rates | ||
69 | |||
70 | lux0_calibscale | ||
71 | RW - calibration value. Set to neutral value by default. | ||
72 | Output results are multiplied with calibscale / calibscale_default | ||
73 | value. | ||
74 | |||
75 | lux0_calibscale_default | ||
76 | RO - neutral calibration value | ||
77 | |||
78 | lux0_thresh_above_value | ||
79 | RW - HI level threshold value. All results above the value | ||
80 | trigs an interrupt. 65535 (i.e. sensor_range) disables the above | ||
81 | interrupt. | ||
82 | |||
83 | lux0_thresh_below_value | ||
84 | RW - LO level threshold value. All results below the value | ||
85 | trigs an interrupt. 0 disables the below interrupt. | ||
86 | |||
87 | prox0_raw | ||
88 | RO - measured proximity value | ||
89 | sysfs_notify called when threshold interrupt occurs | ||
90 | |||
91 | prox0_sensor_range | ||
92 | RO - prox0_raw max value (1023) | ||
93 | |||
94 | prox0_raw_en | ||
95 | RW - enable / disable proximity - uses counting logic | ||
96 | 1 enables the proximity | ||
97 | 0 disables the proximity | ||
98 | |||
99 | prox0_reporting_mode | ||
100 | RW - trigger / periodic. In "trigger" mode the driver tells two possible | ||
101 | values: 0 or prox0_sensor_range value. 0 means no proximity, | ||
102 | 1023 means proximity. This causes minimal number of interrupts. | ||
103 | In "periodic" mode the driver reports all values above | ||
104 | prox0_thresh_above. This causes more interrupts, but it can give | ||
105 | _rough_ estimate about the distance. | ||
106 | |||
107 | prox0_reporting_mode_avail | ||
108 | RO - accepted values to prox0_reporting_mode (trigger, periodic) | ||
109 | |||
110 | prox0_thresh_above_value | ||
111 | RW - threshold level which trigs proximity events. | ||
diff --git a/Documentation/misc-devices/bh1770glc.txt b/Documentation/misc-devices/bh1770glc.txt new file mode 100644 index 000000000000..7d64c014dc70 --- /dev/null +++ b/Documentation/misc-devices/bh1770glc.txt | |||
@@ -0,0 +1,116 @@ | |||
1 | Kernel driver bh1770glc | ||
2 | ======================= | ||
3 | |||
4 | Supported chips: | ||
5 | ROHM BH1770GLC | ||
6 | OSRAM SFH7770 | ||
7 | |||
8 | Data sheet: | ||
9 | Not freely available | ||
10 | |||
11 | Author: | ||
12 | Samu Onkalo <samu.p.onkalo@nokia.com> | ||
13 | |||
14 | Description | ||
15 | ----------- | ||
16 | BH1770GLC and SFH7770 are combined ambient light and proximity sensors. | ||
17 | ALS and proximity parts operates on their own, but they shares common I2C | ||
18 | interface and interrupt logic. In principle they can run on their own, | ||
19 | but ALS side results are used to estimate reliability of the proximity sensor. | ||
20 | |||
21 | ALS produces 16 bit lux values. The chip contains interrupt logic to produce | ||
22 | low and high threshold interrupts. | ||
23 | |||
24 | Proximity part contains IR-led driver up to 3 IR leds. The chip measures | ||
25 | amount of reflected IR light and produces proximity result. Resolution is | ||
26 | 8 bit. Driver supports only one channel. Driver uses ALS results to estimate | ||
27 | reliability of the proximity results. Thus ALS is always running while | ||
28 | proximity detection is needed. | ||
29 | |||
30 | Driver uses threshold interrupts to avoid need for polling the values. | ||
31 | Proximity low interrupt doesn't exists in the chip. This is simulated | ||
32 | by using a delayed work. As long as there is proximity threshold above | ||
33 | interrupts the delayed work is pushed forward. So, when proximity level goes | ||
34 | below the threshold value, there is no interrupt and the delayed work will | ||
35 | finally run. This is handled as no proximity indication. | ||
36 | |||
37 | Chip state is controlled via runtime pm framework when enabled in config. | ||
38 | |||
39 | Calibscale factor is used to hide differences between the chips. By default | ||
40 | value set to neutral state meaning factor of 1.00. To get proper values, | ||
41 | calibrated source of light is needed as a reference. Calibscale factor is set | ||
42 | so that measurement produces about the expected lux value. | ||
43 | |||
44 | SYSFS | ||
45 | ----- | ||
46 | |||
47 | chip_id | ||
48 | RO - shows detected chip type and version | ||
49 | |||
50 | power_state | ||
51 | RW - enable / disable chip. Uses counting logic | ||
52 | 1 enables the chip | ||
53 | 0 disables the chip | ||
54 | |||
55 | lux0_input | ||
56 | RO - measured lux value | ||
57 | sysfs_notify called when threshold interrupt occurs | ||
58 | |||
59 | lux0_sensor_range | ||
60 | RO - lux0_input max value | ||
61 | |||
62 | lux0_rate | ||
63 | RW - measurement rate in Hz | ||
64 | |||
65 | lux0_rate_avail | ||
66 | RO - supported measurement rates | ||
67 | |||
68 | lux0_thresh_above_value | ||
69 | RW - HI level threshold value. All results above the value | ||
70 | trigs an interrupt. 65535 (i.e. sensor_range) disables the above | ||
71 | interrupt. | ||
72 | |||
73 | lux0_thresh_below_value | ||
74 | RW - LO level threshold value. All results below the value | ||
75 | trigs an interrupt. 0 disables the below interrupt. | ||
76 | |||
77 | lux0_calibscale | ||
78 | RW - calibration value. Set to neutral value by default. | ||
79 | Output results are multiplied with calibscale / calibscale_default | ||
80 | value. | ||
81 | |||
82 | lux0_calibscale_default | ||
83 | RO - neutral calibration value | ||
84 | |||
85 | prox0_raw | ||
86 | RO - measured proximity value | ||
87 | sysfs_notify called when threshold interrupt occurs | ||
88 | |||
89 | prox0_sensor_range | ||
90 | RO - prox0_raw max value | ||
91 | |||
92 | prox0_raw_en | ||
93 | RW - enable / disable proximity - uses counting logic | ||
94 | 1 enables the proximity | ||
95 | 0 disables the proximity | ||
96 | |||
97 | prox0_thresh_above_count | ||
98 | RW - number of proximity interrupts needed before triggering the event | ||
99 | |||
100 | prox0_rate_above | ||
101 | RW - Measurement rate (in Hz) when the level is above threshold | ||
102 | i.e. when proximity on has been reported. | ||
103 | |||
104 | prox0_rate_below | ||
105 | RW - Measurement rate (in Hz) when the level is below threshold | ||
106 | i.e. when proximity off has been reported. | ||
107 | |||
108 | prox0_rate_avail | ||
109 | RO - Supported proximity measurement rates in Hz | ||
110 | |||
111 | prox0_thresh_above0_value | ||
112 | RW - threshold level which trigs proximity events. | ||
113 | Filtered by persistence filter (prox0_thresh_above_count) | ||
114 | |||
115 | prox0_thresh_above1_value | ||
116 | RW - threshold level which trigs event immediately | ||
diff --git a/Documentation/timers/hpet_example.c b/Documentation/timers/hpet_example.c index 4bfafb7bc4c5..9a3e7012c190 100644 --- a/Documentation/timers/hpet_example.c +++ b/Documentation/timers/hpet_example.c | |||
@@ -97,6 +97,33 @@ hpet_open_close(int argc, const char **argv) | |||
97 | void | 97 | void |
98 | hpet_info(int argc, const char **argv) | 98 | hpet_info(int argc, const char **argv) |
99 | { | 99 | { |
100 | struct hpet_info info; | ||
101 | int fd; | ||
102 | |||
103 | if (argc != 1) { | ||
104 | fprintf(stderr, "hpet_info: device-name\n"); | ||
105 | return; | ||
106 | } | ||
107 | |||
108 | fd = open(argv[0], O_RDONLY); | ||
109 | if (fd < 0) { | ||
110 | fprintf(stderr, "hpet_info: open of %s failed\n", argv[0]); | ||
111 | return; | ||
112 | } | ||
113 | |||
114 | if (ioctl(fd, HPET_INFO, &info) < 0) { | ||
115 | fprintf(stderr, "hpet_info: failed to get info\n"); | ||
116 | goto out; | ||
117 | } | ||
118 | |||
119 | fprintf(stderr, "hpet_info: hi_irqfreq 0x%lx hi_flags 0x%lx ", | ||
120 | info.hi_ireqfreq, info.hi_flags); | ||
121 | fprintf(stderr, "hi_hpet %d hi_timer %d\n", | ||
122 | info.hi_hpet, info.hi_timer); | ||
123 | |||
124 | out: | ||
125 | close(fd); | ||
126 | return; | ||
100 | } | 127 | } |
101 | 128 | ||
102 | void | 129 | void |
diff --git a/Documentation/trace/postprocess/trace-vmscan-postprocess.pl b/Documentation/trace/postprocess/trace-vmscan-postprocess.pl index 1b55146d1c8d..b3e73ddb1567 100644 --- a/Documentation/trace/postprocess/trace-vmscan-postprocess.pl +++ b/Documentation/trace/postprocess/trace-vmscan-postprocess.pl | |||
@@ -46,7 +46,7 @@ use constant HIGH_KSWAPD_LATENCY => 20; | |||
46 | use constant HIGH_KSWAPD_REWAKEUP => 21; | 46 | use constant HIGH_KSWAPD_REWAKEUP => 21; |
47 | use constant HIGH_NR_SCANNED => 22; | 47 | use constant HIGH_NR_SCANNED => 22; |
48 | use constant HIGH_NR_TAKEN => 23; | 48 | use constant HIGH_NR_TAKEN => 23; |
49 | use constant HIGH_NR_RECLAIM => 24; | 49 | use constant HIGH_NR_RECLAIMED => 24; |
50 | use constant HIGH_NR_CONTIG_DIRTY => 25; | 50 | use constant HIGH_NR_CONTIG_DIRTY => 25; |
51 | 51 | ||
52 | my %perprocesspid; | 52 | my %perprocesspid; |
@@ -58,11 +58,13 @@ my $opt_read_procstat; | |||
58 | my $total_wakeup_kswapd; | 58 | my $total_wakeup_kswapd; |
59 | my ($total_direct_reclaim, $total_direct_nr_scanned); | 59 | my ($total_direct_reclaim, $total_direct_nr_scanned); |
60 | my ($total_direct_latency, $total_kswapd_latency); | 60 | my ($total_direct_latency, $total_kswapd_latency); |
61 | my ($total_direct_nr_reclaimed); | ||
61 | my ($total_direct_writepage_file_sync, $total_direct_writepage_file_async); | 62 | my ($total_direct_writepage_file_sync, $total_direct_writepage_file_async); |
62 | my ($total_direct_writepage_anon_sync, $total_direct_writepage_anon_async); | 63 | my ($total_direct_writepage_anon_sync, $total_direct_writepage_anon_async); |
63 | my ($total_kswapd_nr_scanned, $total_kswapd_wake); | 64 | my ($total_kswapd_nr_scanned, $total_kswapd_wake); |
64 | my ($total_kswapd_writepage_file_sync, $total_kswapd_writepage_file_async); | 65 | my ($total_kswapd_writepage_file_sync, $total_kswapd_writepage_file_async); |
65 | my ($total_kswapd_writepage_anon_sync, $total_kswapd_writepage_anon_async); | 66 | my ($total_kswapd_writepage_anon_sync, $total_kswapd_writepage_anon_async); |
67 | my ($total_kswapd_nr_reclaimed); | ||
66 | 68 | ||
67 | # Catch sigint and exit on request | 69 | # Catch sigint and exit on request |
68 | my $sigint_report = 0; | 70 | my $sigint_report = 0; |
@@ -104,7 +106,7 @@ my $regex_kswapd_wake_default = 'nid=([0-9]*) order=([0-9]*)'; | |||
104 | my $regex_kswapd_sleep_default = 'nid=([0-9]*)'; | 106 | my $regex_kswapd_sleep_default = 'nid=([0-9]*)'; |
105 | my $regex_wakeup_kswapd_default = 'nid=([0-9]*) zid=([0-9]*) order=([0-9]*)'; | 107 | my $regex_wakeup_kswapd_default = 'nid=([0-9]*) zid=([0-9]*) order=([0-9]*)'; |
106 | my $regex_lru_isolate_default = 'isolate_mode=([0-9]*) order=([0-9]*) nr_requested=([0-9]*) nr_scanned=([0-9]*) nr_taken=([0-9]*) contig_taken=([0-9]*) contig_dirty=([0-9]*) contig_failed=([0-9]*)'; | 108 | my $regex_lru_isolate_default = 'isolate_mode=([0-9]*) order=([0-9]*) nr_requested=([0-9]*) nr_scanned=([0-9]*) nr_taken=([0-9]*) contig_taken=([0-9]*) contig_dirty=([0-9]*) contig_failed=([0-9]*)'; |
107 | my $regex_lru_shrink_inactive_default = 'lru=([A-Z_]*) nr_scanned=([0-9]*) nr_reclaimed=([0-9]*) priority=([0-9]*)'; | 109 | my $regex_lru_shrink_inactive_default = 'nid=([0-9]*) zid=([0-9]*) nr_scanned=([0-9]*) nr_reclaimed=([0-9]*) priority=([0-9]*) flags=([A-Z_|]*)'; |
108 | my $regex_lru_shrink_active_default = 'lru=([A-Z_]*) nr_scanned=([0-9]*) nr_rotated=([0-9]*) priority=([0-9]*)'; | 110 | my $regex_lru_shrink_active_default = 'lru=([A-Z_]*) nr_scanned=([0-9]*) nr_rotated=([0-9]*) priority=([0-9]*)'; |
109 | my $regex_writepage_default = 'page=([0-9a-f]*) pfn=([0-9]*) flags=([A-Z_|]*)'; | 111 | my $regex_writepage_default = 'page=([0-9a-f]*) pfn=([0-9]*) flags=([A-Z_|]*)'; |
110 | 112 | ||
@@ -203,8 +205,8 @@ $regex_lru_shrink_inactive = generate_traceevent_regex( | |||
203 | "vmscan/mm_vmscan_lru_shrink_inactive", | 205 | "vmscan/mm_vmscan_lru_shrink_inactive", |
204 | $regex_lru_shrink_inactive_default, | 206 | $regex_lru_shrink_inactive_default, |
205 | "nid", "zid", | 207 | "nid", "zid", |
206 | "lru", | 208 | "nr_scanned", "nr_reclaimed", "priority", |
207 | "nr_scanned", "nr_reclaimed", "priority"); | 209 | "flags"); |
208 | $regex_lru_shrink_active = generate_traceevent_regex( | 210 | $regex_lru_shrink_active = generate_traceevent_regex( |
209 | "vmscan/mm_vmscan_lru_shrink_active", | 211 | "vmscan/mm_vmscan_lru_shrink_active", |
210 | $regex_lru_shrink_active_default, | 212 | $regex_lru_shrink_active_default, |
@@ -375,6 +377,16 @@ EVENT_PROCESS: | |||
375 | my $nr_contig_dirty = $7; | 377 | my $nr_contig_dirty = $7; |
376 | $perprocesspid{$process_pid}->{HIGH_NR_SCANNED} += $nr_scanned; | 378 | $perprocesspid{$process_pid}->{HIGH_NR_SCANNED} += $nr_scanned; |
377 | $perprocesspid{$process_pid}->{HIGH_NR_CONTIG_DIRTY} += $nr_contig_dirty; | 379 | $perprocesspid{$process_pid}->{HIGH_NR_CONTIG_DIRTY} += $nr_contig_dirty; |
380 | } elsif ($tracepoint eq "mm_vmscan_lru_shrink_inactive") { | ||
381 | $details = $5; | ||
382 | if ($details !~ /$regex_lru_shrink_inactive/o) { | ||
383 | print "WARNING: Failed to parse mm_vmscan_lru_shrink_inactive as expected\n"; | ||
384 | print " $details\n"; | ||
385 | print " $regex_lru_shrink_inactive/o\n"; | ||
386 | next; | ||
387 | } | ||
388 | my $nr_reclaimed = $4; | ||
389 | $perprocesspid{$process_pid}->{HIGH_NR_RECLAIMED} += $nr_reclaimed; | ||
378 | } elsif ($tracepoint eq "mm_vmscan_writepage") { | 390 | } elsif ($tracepoint eq "mm_vmscan_writepage") { |
379 | $details = $5; | 391 | $details = $5; |
380 | if ($details !~ /$regex_writepage/o) { | 392 | if ($details !~ /$regex_writepage/o) { |
@@ -464,8 +476,8 @@ sub dump_stats { | |||
464 | 476 | ||
465 | # Print out process activity | 477 | # Print out process activity |
466 | printf("\n"); | 478 | printf("\n"); |
467 | printf("%-" . $max_strlen . "s %8s %10s %8s %8s %8s %8s %8s\n", "Process", "Direct", "Wokeup", "Pages", "Pages", "Pages", "Time"); | 479 | printf("%-" . $max_strlen . "s %8s %10s %8s %8s %8s %8s %8s %8s\n", "Process", "Direct", "Wokeup", "Pages", "Pages", "Pages", "Pages", "Time"); |
468 | printf("%-" . $max_strlen . "s %8s %10s %8s %8s %8s %8s %8s\n", "details", "Rclms", "Kswapd", "Scanned", "Sync-IO", "ASync-IO", "Stalled"); | 480 | printf("%-" . $max_strlen . "s %8s %10s %8s %8s %8s %8s %8s %8s\n", "details", "Rclms", "Kswapd", "Scanned", "Rclmed", "Sync-IO", "ASync-IO", "Stalled"); |
469 | foreach $process_pid (keys %stats) { | 481 | foreach $process_pid (keys %stats) { |
470 | 482 | ||
471 | if (!$stats{$process_pid}->{MM_VMSCAN_DIRECT_RECLAIM_BEGIN}) { | 483 | if (!$stats{$process_pid}->{MM_VMSCAN_DIRECT_RECLAIM_BEGIN}) { |
@@ -475,6 +487,7 @@ sub dump_stats { | |||
475 | $total_direct_reclaim += $stats{$process_pid}->{MM_VMSCAN_DIRECT_RECLAIM_BEGIN}; | 487 | $total_direct_reclaim += $stats{$process_pid}->{MM_VMSCAN_DIRECT_RECLAIM_BEGIN}; |
476 | $total_wakeup_kswapd += $stats{$process_pid}->{MM_VMSCAN_WAKEUP_KSWAPD}; | 488 | $total_wakeup_kswapd += $stats{$process_pid}->{MM_VMSCAN_WAKEUP_KSWAPD}; |
477 | $total_direct_nr_scanned += $stats{$process_pid}->{HIGH_NR_SCANNED}; | 489 | $total_direct_nr_scanned += $stats{$process_pid}->{HIGH_NR_SCANNED}; |
490 | $total_direct_nr_reclaimed += $stats{$process_pid}->{HIGH_NR_RECLAIMED}; | ||
478 | $total_direct_writepage_file_sync += $stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_FILE_SYNC}; | 491 | $total_direct_writepage_file_sync += $stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_FILE_SYNC}; |
479 | $total_direct_writepage_anon_sync += $stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_ANON_SYNC}; | 492 | $total_direct_writepage_anon_sync += $stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_ANON_SYNC}; |
480 | $total_direct_writepage_file_async += $stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_FILE_ASYNC}; | 493 | $total_direct_writepage_file_async += $stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_FILE_ASYNC}; |
@@ -489,11 +502,12 @@ sub dump_stats { | |||
489 | $index++; | 502 | $index++; |
490 | } | 503 | } |
491 | 504 | ||
492 | printf("%-" . $max_strlen . "s %8d %10d %8u %8u %8u %8.3f", | 505 | printf("%-" . $max_strlen . "s %8d %10d %8u %8u %8u %8u %8.3f", |
493 | $process_pid, | 506 | $process_pid, |
494 | $stats{$process_pid}->{MM_VMSCAN_DIRECT_RECLAIM_BEGIN}, | 507 | $stats{$process_pid}->{MM_VMSCAN_DIRECT_RECLAIM_BEGIN}, |
495 | $stats{$process_pid}->{MM_VMSCAN_WAKEUP_KSWAPD}, | 508 | $stats{$process_pid}->{MM_VMSCAN_WAKEUP_KSWAPD}, |
496 | $stats{$process_pid}->{HIGH_NR_SCANNED}, | 509 | $stats{$process_pid}->{HIGH_NR_SCANNED}, |
510 | $stats{$process_pid}->{HIGH_NR_RECLAIMED}, | ||
497 | $stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_FILE_SYNC} + $stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_ANON_SYNC}, | 511 | $stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_FILE_SYNC} + $stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_ANON_SYNC}, |
498 | $stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_FILE_ASYNC} + $stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_ANON_ASYNC}, | 512 | $stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_FILE_ASYNC} + $stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_ANON_ASYNC}, |
499 | $this_reclaim_delay / 1000); | 513 | $this_reclaim_delay / 1000); |
@@ -529,8 +543,8 @@ sub dump_stats { | |||
529 | 543 | ||
530 | # Print out kswapd activity | 544 | # Print out kswapd activity |
531 | printf("\n"); | 545 | printf("\n"); |
532 | printf("%-" . $max_strlen . "s %8s %10s %8s %8s %8s %8s\n", "Kswapd", "Kswapd", "Order", "Pages", "Pages", "Pages"); | 546 | printf("%-" . $max_strlen . "s %8s %10s %8s %8s %8s %8s\n", "Kswapd", "Kswapd", "Order", "Pages", "Pages", "Pages", "Pages"); |
533 | printf("%-" . $max_strlen . "s %8s %10s %8s %8s %8s %8s\n", "Instance", "Wakeups", "Re-wakeup", "Scanned", "Sync-IO", "ASync-IO"); | 547 | printf("%-" . $max_strlen . "s %8s %10s %8s %8s %8s %8s\n", "Instance", "Wakeups", "Re-wakeup", "Scanned", "Rclmed", "Sync-IO", "ASync-IO"); |
534 | foreach $process_pid (keys %stats) { | 548 | foreach $process_pid (keys %stats) { |
535 | 549 | ||
536 | if (!$stats{$process_pid}->{MM_VMSCAN_KSWAPD_WAKE}) { | 550 | if (!$stats{$process_pid}->{MM_VMSCAN_KSWAPD_WAKE}) { |
@@ -539,16 +553,18 @@ sub dump_stats { | |||
539 | 553 | ||
540 | $total_kswapd_wake += $stats{$process_pid}->{MM_VMSCAN_KSWAPD_WAKE}; | 554 | $total_kswapd_wake += $stats{$process_pid}->{MM_VMSCAN_KSWAPD_WAKE}; |
541 | $total_kswapd_nr_scanned += $stats{$process_pid}->{HIGH_NR_SCANNED}; | 555 | $total_kswapd_nr_scanned += $stats{$process_pid}->{HIGH_NR_SCANNED}; |
556 | $total_kswapd_nr_reclaimed += $stats{$process_pid}->{HIGH_NR_RECLAIMED}; | ||
542 | $total_kswapd_writepage_file_sync += $stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_FILE_SYNC}; | 557 | $total_kswapd_writepage_file_sync += $stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_FILE_SYNC}; |
543 | $total_kswapd_writepage_anon_sync += $stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_ANON_SYNC}; | 558 | $total_kswapd_writepage_anon_sync += $stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_ANON_SYNC}; |
544 | $total_kswapd_writepage_file_async += $stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_FILE_ASYNC}; | 559 | $total_kswapd_writepage_file_async += $stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_FILE_ASYNC}; |
545 | $total_kswapd_writepage_anon_async += $stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_ANON_ASYNC}; | 560 | $total_kswapd_writepage_anon_async += $stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_ANON_ASYNC}; |
546 | 561 | ||
547 | printf("%-" . $max_strlen . "s %8d %10d %8u %8i %8u", | 562 | printf("%-" . $max_strlen . "s %8d %10d %8u %8u %8i %8u", |
548 | $process_pid, | 563 | $process_pid, |
549 | $stats{$process_pid}->{MM_VMSCAN_KSWAPD_WAKE}, | 564 | $stats{$process_pid}->{MM_VMSCAN_KSWAPD_WAKE}, |
550 | $stats{$process_pid}->{HIGH_KSWAPD_REWAKEUP}, | 565 | $stats{$process_pid}->{HIGH_KSWAPD_REWAKEUP}, |
551 | $stats{$process_pid}->{HIGH_NR_SCANNED}, | 566 | $stats{$process_pid}->{HIGH_NR_SCANNED}, |
567 | $stats{$process_pid}->{HIGH_NR_RECLAIMED}, | ||
552 | $stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_FILE_SYNC} + $stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_ANON_SYNC}, | 568 | $stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_FILE_SYNC} + $stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_ANON_SYNC}, |
553 | $stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_FILE_ASYNC} + $stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_ANON_ASYNC}); | 569 | $stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_FILE_ASYNC} + $stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_ANON_ASYNC}); |
554 | 570 | ||
@@ -579,6 +595,7 @@ sub dump_stats { | |||
579 | print "\nSummary\n"; | 595 | print "\nSummary\n"; |
580 | print "Direct reclaims: $total_direct_reclaim\n"; | 596 | print "Direct reclaims: $total_direct_reclaim\n"; |
581 | print "Direct reclaim pages scanned: $total_direct_nr_scanned\n"; | 597 | print "Direct reclaim pages scanned: $total_direct_nr_scanned\n"; |
598 | print "Direct reclaim pages reclaimed: $total_direct_nr_reclaimed\n"; | ||
582 | print "Direct reclaim write file sync I/O: $total_direct_writepage_file_sync\n"; | 599 | print "Direct reclaim write file sync I/O: $total_direct_writepage_file_sync\n"; |
583 | print "Direct reclaim write anon sync I/O: $total_direct_writepage_anon_sync\n"; | 600 | print "Direct reclaim write anon sync I/O: $total_direct_writepage_anon_sync\n"; |
584 | print "Direct reclaim write file async I/O: $total_direct_writepage_file_async\n"; | 601 | print "Direct reclaim write file async I/O: $total_direct_writepage_file_async\n"; |
@@ -588,6 +605,7 @@ sub dump_stats { | |||
588 | print "\n"; | 605 | print "\n"; |
589 | print "Kswapd wakeups: $total_kswapd_wake\n"; | 606 | print "Kswapd wakeups: $total_kswapd_wake\n"; |
590 | print "Kswapd pages scanned: $total_kswapd_nr_scanned\n"; | 607 | print "Kswapd pages scanned: $total_kswapd_nr_scanned\n"; |
608 | print "Kswapd pages reclaimed: $total_kswapd_nr_reclaimed\n"; | ||
591 | print "Kswapd reclaim write file sync I/O: $total_kswapd_writepage_file_sync\n"; | 609 | print "Kswapd reclaim write file sync I/O: $total_kswapd_writepage_file_sync\n"; |
592 | print "Kswapd reclaim write anon sync I/O: $total_kswapd_writepage_anon_sync\n"; | 610 | print "Kswapd reclaim write anon sync I/O: $total_kswapd_writepage_anon_sync\n"; |
593 | print "Kswapd reclaim write file async I/O: $total_kswapd_writepage_file_async\n"; | 611 | print "Kswapd reclaim write file async I/O: $total_kswapd_writepage_file_async\n"; |
@@ -612,6 +630,7 @@ sub aggregate_perprocesspid() { | |||
612 | $perprocess{$process}->{MM_VMSCAN_WAKEUP_KSWAPD} += $perprocesspid{$process_pid}->{MM_VMSCAN_WAKEUP_KSWAPD}; | 630 | $perprocess{$process}->{MM_VMSCAN_WAKEUP_KSWAPD} += $perprocesspid{$process_pid}->{MM_VMSCAN_WAKEUP_KSWAPD}; |
613 | $perprocess{$process}->{HIGH_KSWAPD_REWAKEUP} += $perprocesspid{$process_pid}->{HIGH_KSWAPD_REWAKEUP}; | 631 | $perprocess{$process}->{HIGH_KSWAPD_REWAKEUP} += $perprocesspid{$process_pid}->{HIGH_KSWAPD_REWAKEUP}; |
614 | $perprocess{$process}->{HIGH_NR_SCANNED} += $perprocesspid{$process_pid}->{HIGH_NR_SCANNED}; | 632 | $perprocess{$process}->{HIGH_NR_SCANNED} += $perprocesspid{$process_pid}->{HIGH_NR_SCANNED}; |
633 | $perprocess{$process}->{HIGH_NR_RECLAIMED} += $perprocesspid{$process_pid}->{HIGH_NR_RECLAIMED}; | ||
615 | $perprocess{$process}->{MM_VMSCAN_WRITEPAGE_FILE_SYNC} += $perprocesspid{$process_pid}->{MM_VMSCAN_WRITEPAGE_FILE_SYNC}; | 634 | $perprocess{$process}->{MM_VMSCAN_WRITEPAGE_FILE_SYNC} += $perprocesspid{$process_pid}->{MM_VMSCAN_WRITEPAGE_FILE_SYNC}; |
616 | $perprocess{$process}->{MM_VMSCAN_WRITEPAGE_ANON_SYNC} += $perprocesspid{$process_pid}->{MM_VMSCAN_WRITEPAGE_ANON_SYNC}; | 635 | $perprocess{$process}->{MM_VMSCAN_WRITEPAGE_ANON_SYNC} += $perprocesspid{$process_pid}->{MM_VMSCAN_WRITEPAGE_ANON_SYNC}; |
617 | $perprocess{$process}->{MM_VMSCAN_WRITEPAGE_FILE_ASYNC} += $perprocesspid{$process_pid}->{MM_VMSCAN_WRITEPAGE_FILE_ASYNC}; | 636 | $perprocess{$process}->{MM_VMSCAN_WRITEPAGE_FILE_ASYNC} += $perprocesspid{$process_pid}->{MM_VMSCAN_WRITEPAGE_FILE_ASYNC}; |
diff --git a/Documentation/vm/highmem.txt b/Documentation/vm/highmem.txt new file mode 100644 index 000000000000..4324d24ffacd --- /dev/null +++ b/Documentation/vm/highmem.txt | |||
@@ -0,0 +1,162 @@ | |||
1 | |||
2 | ==================== | ||
3 | HIGH MEMORY HANDLING | ||
4 | ==================== | ||
5 | |||
6 | By: Peter Zijlstra <a.p.zijlstra@chello.nl> | ||
7 | |||
8 | Contents: | ||
9 | |||
10 | (*) What is high memory? | ||
11 | |||
12 | (*) Temporary virtual mappings. | ||
13 | |||
14 | (*) Using kmap_atomic. | ||
15 | |||
16 | (*) Cost of temporary mappings. | ||
17 | |||
18 | (*) i386 PAE. | ||
19 | |||
20 | |||
21 | ==================== | ||
22 | WHAT IS HIGH MEMORY? | ||
23 | ==================== | ||
24 | |||
25 | High memory (highmem) is used when the size of physical memory approaches or | ||
26 | exceeds the maximum size of virtual memory. At that point it becomes | ||
27 | impossible for the kernel to keep all of the available physical memory mapped | ||
28 | at all times. This means the kernel needs to start using temporary mappings of | ||
29 | the pieces of physical memory that it wants to access. | ||
30 | |||
31 | The part of (physical) memory not covered by a permanent mapping is what we | ||
32 | refer to as 'highmem'. There are various architecture dependent constraints on | ||
33 | where exactly that border lies. | ||
34 | |||
35 | In the i386 arch, for example, we choose to map the kernel into every process's | ||
36 | VM space so that we don't have to pay the full TLB invalidation costs for | ||
37 | kernel entry/exit. This means the available virtual memory space (4GiB on | ||
38 | i386) has to be divided between user and kernel space. | ||
39 | |||
40 | The traditional split for architectures using this approach is 3:1, 3GiB for | ||
41 | userspace and the top 1GiB for kernel space: | ||
42 | |||
43 | +--------+ 0xffffffff | ||
44 | | Kernel | | ||
45 | +--------+ 0xc0000000 | ||
46 | | | | ||
47 | | User | | ||
48 | | | | ||
49 | +--------+ 0x00000000 | ||
50 | |||
51 | This means that the kernel can at most map 1GiB of physical memory at any one | ||
52 | time, but because we need virtual address space for other things - including | ||
53 | temporary maps to access the rest of the physical memory - the actual direct | ||
54 | map will typically be less (usually around ~896MiB). | ||
55 | |||
56 | Other architectures that have mm context tagged TLBs can have separate kernel | ||
57 | and user maps. Some hardware (like some ARMs), however, have limited virtual | ||
58 | space when they use mm context tags. | ||
59 | |||
60 | |||
61 | ========================== | ||
62 | TEMPORARY VIRTUAL MAPPINGS | ||
63 | ========================== | ||
64 | |||
65 | The kernel contains several ways of creating temporary mappings: | ||
66 | |||
67 | (*) vmap(). This can be used to make a long duration mapping of multiple | ||
68 | physical pages into a contiguous virtual space. It needs global | ||
69 | synchronization to unmap. | ||
70 | |||
71 | (*) kmap(). This permits a short duration mapping of a single page. It needs | ||
72 | global synchronization, but is amortized somewhat. It is also prone to | ||
73 | deadlocks when using in a nested fashion, and so it is not recommended for | ||
74 | new code. | ||
75 | |||
76 | (*) kmap_atomic(). This permits a very short duration mapping of a single | ||
77 | page. Since the mapping is restricted to the CPU that issued it, it | ||
78 | performs well, but the issuing task is therefore required to stay on that | ||
79 | CPU until it has finished, lest some other task displace its mappings. | ||
80 | |||
81 | kmap_atomic() may also be used by interrupt contexts, since it is does not | ||
82 | sleep and the caller may not sleep until after kunmap_atomic() is called. | ||
83 | |||
84 | It may be assumed that k[un]map_atomic() won't fail. | ||
85 | |||
86 | |||
87 | ================= | ||
88 | USING KMAP_ATOMIC | ||
89 | ================= | ||
90 | |||
91 | When and where to use kmap_atomic() is straightforward. It is used when code | ||
92 | wants to access the contents of a page that might be allocated from high memory | ||
93 | (see __GFP_HIGHMEM), for example a page in the pagecache. The API has two | ||
94 | functions, and they can be used in a manner similar to the following: | ||
95 | |||
96 | /* Find the page of interest. */ | ||
97 | struct page *page = find_get_page(mapping, offset); | ||
98 | |||
99 | /* Gain access to the contents of that page. */ | ||
100 | void *vaddr = kmap_atomic(page); | ||
101 | |||
102 | /* Do something to the contents of that page. */ | ||
103 | memset(vaddr, 0, PAGE_SIZE); | ||
104 | |||
105 | /* Unmap that page. */ | ||
106 | kunmap_atomic(vaddr); | ||
107 | |||
108 | Note that the kunmap_atomic() call takes the result of the kmap_atomic() call | ||
109 | not the argument. | ||
110 | |||
111 | If you need to map two pages because you want to copy from one page to | ||
112 | another you need to keep the kmap_atomic calls strictly nested, like: | ||
113 | |||
114 | vaddr1 = kmap_atomic(page1); | ||
115 | vaddr2 = kmap_atomic(page2); | ||
116 | |||
117 | memcpy(vaddr1, vaddr2, PAGE_SIZE); | ||
118 | |||
119 | kunmap_atomic(vaddr2); | ||
120 | kunmap_atomic(vaddr1); | ||
121 | |||
122 | |||
123 | ========================== | ||
124 | COST OF TEMPORARY MAPPINGS | ||
125 | ========================== | ||
126 | |||
127 | The cost of creating temporary mappings can be quite high. The arch has to | ||
128 | manipulate the kernel's page tables, the data TLB and/or the MMU's registers. | ||
129 | |||
130 | If CONFIG_HIGHMEM is not set, then the kernel will try and create a mapping | ||
131 | simply with a bit of arithmetic that will convert the page struct address into | ||
132 | a pointer to the page contents rather than juggling mappings about. In such a | ||
133 | case, the unmap operation may be a null operation. | ||
134 | |||
135 | If CONFIG_MMU is not set, then there can be no temporary mappings and no | ||
136 | highmem. In such a case, the arithmetic approach will also be used. | ||
137 | |||
138 | |||
139 | ======== | ||
140 | i386 PAE | ||
141 | ======== | ||
142 | |||
143 | The i386 arch, under some circumstances, will permit you to stick up to 64GiB | ||
144 | of RAM into your 32-bit machine. This has a number of consequences: | ||
145 | |||
146 | (*) Linux needs a page-frame structure for each page in the system and the | ||
147 | pageframes need to live in the permanent mapping, which means: | ||
148 | |||
149 | (*) you can have 896M/sizeof(struct page) page-frames at most; with struct | ||
150 | page being 32-bytes that would end up being something in the order of 112G | ||
151 | worth of pages; the kernel, however, needs to store more than just | ||
152 | page-frames in that memory... | ||
153 | |||
154 | (*) PAE makes your page tables larger - which slows the system down as more | ||
155 | data has to be accessed to traverse in TLB fills and the like. One | ||
156 | advantage is that PAE has more PTE bits and can provide advanced features | ||
157 | like NX and PAT. | ||
158 | |||
159 | The general recommendation is that you don't use more than 8GiB on a 32-bit | ||
160 | machine - although more might work for you and your workload, you're pretty | ||
161 | much on your own - don't expect kernel developers to really care much if things | ||
162 | come apart. | ||
diff --git a/MAINTAINERS b/MAINTAINERS index 146b8a068a4e..014b648f99ed 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -657,7 +657,7 @@ ARM/FARADAY FA526 PORT | |||
657 | M: Hans Ulli Kroll <ulli.kroll@googlemail.com> | 657 | M: Hans Ulli Kroll <ulli.kroll@googlemail.com> |
658 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) | 658 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) |
659 | S: Maintained | 659 | S: Maintained |
660 | T: git://git.berlios.de/gemini-board | 660 | T: git git://git.berlios.de/gemini-board |
661 | F: arch/arm/mm/*-fa* | 661 | F: arch/arm/mm/*-fa* |
662 | 662 | ||
663 | ARM/FOOTBRIDGE ARCHITECTURE | 663 | ARM/FOOTBRIDGE ARCHITECTURE |
@@ -672,7 +672,7 @@ ARM/FREESCALE IMX / MXC ARM ARCHITECTURE | |||
672 | M: Sascha Hauer <kernel@pengutronix.de> | 672 | M: Sascha Hauer <kernel@pengutronix.de> |
673 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) | 673 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) |
674 | S: Maintained | 674 | S: Maintained |
675 | T: git://git.pengutronix.de/git/imx/linux-2.6.git | 675 | T: git git://git.pengutronix.de/git/imx/linux-2.6.git |
676 | F: arch/arm/mach-mx*/ | 676 | F: arch/arm/mach-mx*/ |
677 | F: arch/arm/plat-mxc/ | 677 | F: arch/arm/plat-mxc/ |
678 | 678 | ||
@@ -710,8 +710,7 @@ ARM/INCOME PXA270 SUPPORT | |||
710 | M: Marek Vasut <marek.vasut@gmail.com> | 710 | M: Marek Vasut <marek.vasut@gmail.com> |
711 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) | 711 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) |
712 | S: Maintained | 712 | S: Maintained |
713 | F: arch/arm/mach-pxa/income.c | 713 | F: arch/arm/mach-pxa/colibri-pxa270-income.c |
714 | F: arch/arm/mach-pxa/include/mach-pxa/income.h | ||
715 | 714 | ||
716 | ARM/INTEL IOP32X ARM ARCHITECTURE | 715 | ARM/INTEL IOP32X ARM ARCHITECTURE |
717 | M: Lennert Buytenhek <kernel@wantstofly.org> | 716 | M: Lennert Buytenhek <kernel@wantstofly.org> |
@@ -758,13 +757,7 @@ L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) | |||
758 | S: Maintained | 757 | S: Maintained |
759 | F: arch/arm/mach-ixp4xx/ | 758 | F: arch/arm/mach-ixp4xx/ |
760 | 759 | ||
761 | ARM/INTEL RESEARCH IMOTE 2 MACHINE SUPPORT | 760 | ARM/INTEL RESEARCH IMOTE/STARGATE 2 MACHINE SUPPORT |
762 | M: Jonathan Cameron <jic23@cam.ac.uk> | ||
763 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) | ||
764 | S: Maintained | ||
765 | F: arch/arm/mach-pxa/imote2.c | ||
766 | |||
767 | ARM/INTEL RESEARCH STARGATE 2 MACHINE SUPPORT | ||
768 | M: Jonathan Cameron <jic23@cam.ac.uk> | 761 | M: Jonathan Cameron <jic23@cam.ac.uk> |
769 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) | 762 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) |
770 | S: Maintained | 763 | S: Maintained |
@@ -929,40 +922,20 @@ W: http://www.fluff.org/ben/linux/ | |||
929 | S: Maintained | 922 | S: Maintained |
930 | F: arch/arm/mach-s3c2410/ | 923 | F: arch/arm/mach-s3c2410/ |
931 | 924 | ||
932 | ARM/S3C2440 ARM ARCHITECTURE | 925 | ARM/S3C244x ARM ARCHITECTURE |
933 | M: Ben Dooks <ben-linux@fluff.org> | 926 | M: Ben Dooks <ben-linux@fluff.org> |
934 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) | 927 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) |
935 | W: http://www.fluff.org/ben/linux/ | 928 | W: http://www.fluff.org/ben/linux/ |
936 | S: Maintained | 929 | S: Maintained |
937 | F: arch/arm/mach-s3c2440/ | 930 | F: arch/arm/mach-s3c2440/ |
938 | |||
939 | ARM/S3C2442 ARM ARCHITECTURE | ||
940 | M: Ben Dooks <ben-linux@fluff.org> | ||
941 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) | ||
942 | W: http://www.fluff.org/ben/linux/ | ||
943 | S: Maintained | ||
944 | F: arch/arm/mach-s3c2442/ | ||
945 | |||
946 | ARM/S3C2443 ARM ARCHITECTURE | ||
947 | M: Ben Dooks <ben-linux@fluff.org> | ||
948 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) | ||
949 | W: http://www.fluff.org/ben/linux/ | ||
950 | S: Maintained | ||
951 | F: arch/arm/mach-s3c2443/ | 931 | F: arch/arm/mach-s3c2443/ |
952 | 932 | ||
953 | ARM/S3C6400 ARM ARCHITECTURE | 933 | ARM/S3C64xx ARM ARCHITECTURE |
954 | M: Ben Dooks <ben-linux@fluff.org> | 934 | M: Ben Dooks <ben-linux@fluff.org> |
955 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) | 935 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) |
956 | W: http://www.fluff.org/ben/linux/ | 936 | W: http://www.fluff.org/ben/linux/ |
957 | S: Maintained | 937 | S: Maintained |
958 | F: arch/arm/mach-s3c6400/ | 938 | F: arch/arm/mach-s3c64xx/ |
959 | |||
960 | ARM/S3C6410 ARM ARCHITECTURE | ||
961 | M: Ben Dooks <ben-linux@fluff.org> | ||
962 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) | ||
963 | W: http://www.fluff.org/ben/linux/ | ||
964 | S: Maintained | ||
965 | F: arch/arm/mach-s3c6410/ | ||
966 | 939 | ||
967 | ARM/S5P ARM ARCHITECTURES | 940 | ARM/S5P ARM ARCHITECTURES |
968 | M: Kukjin Kim <kgene.kim@samsung.com> | 941 | M: Kukjin Kim <kgene.kim@samsung.com> |
@@ -3867,7 +3840,7 @@ F: drivers/net/wireless/mwl8k.c | |||
3867 | MARVELL SOC MMC/SD/SDIO CONTROLLER DRIVER | 3840 | MARVELL SOC MMC/SD/SDIO CONTROLLER DRIVER |
3868 | M: Nicolas Pitre <nico@fluxnic.net> | 3841 | M: Nicolas Pitre <nico@fluxnic.net> |
3869 | S: Odd Fixes | 3842 | S: Odd Fixes |
3870 | F: drivers/mmc/host/mvsdio.* | 3843 | F: drivers/mmc/host/mvsdio.* |
3871 | 3844 | ||
3872 | MARVELL YUKON / SYSKONNECT DRIVER | 3845 | MARVELL YUKON / SYSKONNECT DRIVER |
3873 | M: Mirko Lindner <mlindner@syskonnect.de> | 3846 | M: Mirko Lindner <mlindner@syskonnect.de> |
@@ -4958,7 +4931,7 @@ RCUTORTURE MODULE | |||
4958 | M: Josh Triplett <josh@freedesktop.org> | 4931 | M: Josh Triplett <josh@freedesktop.org> |
4959 | M: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com> | 4932 | M: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com> |
4960 | S: Supported | 4933 | S: Supported |
4961 | T: git://git.kernel.org/pub/scm/linux/kernel/git/paulmck/linux-2.6-rcu.git | 4934 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/paulmck/linux-2.6-rcu.git |
4962 | F: Documentation/RCU/torture.txt | 4935 | F: Documentation/RCU/torture.txt |
4963 | F: kernel/rcutorture.c | 4936 | F: kernel/rcutorture.c |
4964 | 4937 | ||
@@ -4983,7 +4956,7 @@ M: Dipankar Sarma <dipankar@in.ibm.com> | |||
4983 | M: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com> | 4956 | M: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com> |
4984 | W: http://www.rdrop.com/users/paulmck/rclock/ | 4957 | W: http://www.rdrop.com/users/paulmck/rclock/ |
4985 | S: Supported | 4958 | S: Supported |
4986 | T: git://git.kernel.org/pub/scm/linux/kernel/git/paulmck/linux-2.6-rcu.git | 4959 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/paulmck/linux-2.6-rcu.git |
4987 | F: Documentation/RCU/ | 4960 | F: Documentation/RCU/ |
4988 | F: include/linux/rcu* | 4961 | F: include/linux/rcu* |
4989 | F: include/linux/srcu* | 4962 | F: include/linux/srcu* |
@@ -6141,13 +6114,6 @@ L: linux-usb@vger.kernel.org | |||
6141 | S: Maintained | 6114 | S: Maintained |
6142 | F: drivers/usb/serial/option.c | 6115 | F: drivers/usb/serial/option.c |
6143 | 6116 | ||
6144 | USB OV511 DRIVER | ||
6145 | M: Mark McClelland <mmcclell@bigfoot.com> | ||
6146 | L: linux-usb@vger.kernel.org | ||
6147 | W: http://alpha.dyndns.org/ov511/ | ||
6148 | S: Maintained | ||
6149 | F: drivers/media/video/ov511.* | ||
6150 | |||
6151 | USB PEGASUS DRIVER | 6117 | USB PEGASUS DRIVER |
6152 | M: Petko Manolov <petkan@users.sourceforge.net> | 6118 | M: Petko Manolov <petkan@users.sourceforge.net> |
6153 | L: linux-usb@vger.kernel.org | 6119 | L: linux-usb@vger.kernel.org |
@@ -6308,16 +6274,6 @@ S: Supported | |||
6308 | F: drivers/usb/host/xhci* | 6274 | F: drivers/usb/host/xhci* |
6309 | F: drivers/usb/host/pci-quirks* | 6275 | F: drivers/usb/host/pci-quirks* |
6310 | 6276 | ||
6311 | USB ZC0301 DRIVER | ||
6312 | M: Luca Risolia <luca.risolia@studio.unibo.it> | ||
6313 | L: linux-usb@vger.kernel.org | ||
6314 | L: linux-media@vger.kernel.org | ||
6315 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git | ||
6316 | W: http://www.linux-projects.org | ||
6317 | S: Maintained | ||
6318 | F: Documentation/video4linux/zc0301.txt | ||
6319 | F: drivers/media/video/zc0301/ | ||
6320 | |||
6321 | USB ZD1201 DRIVER | 6277 | USB ZD1201 DRIVER |
6322 | L: linux-wireless@vger.kernel.org | 6278 | L: linux-wireless@vger.kernel.org |
6323 | W: http://linux-lc100020.sourceforge.net | 6279 | W: http://linux-lc100020.sourceforge.net |
diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig index d04ccd73af45..28f93a6c0fde 100644 --- a/arch/alpha/Kconfig +++ b/arch/alpha/Kconfig | |||
@@ -55,6 +55,9 @@ config ZONE_DMA | |||
55 | bool | 55 | bool |
56 | default y | 56 | default y |
57 | 57 | ||
58 | config ARCH_DMA_ADDR_T_64BIT | ||
59 | def_bool y | ||
60 | |||
58 | config NEED_DMA_MAP_STATE | 61 | config NEED_DMA_MAP_STATE |
59 | def_bool y | 62 | def_bool y |
60 | 63 | ||
diff --git a/arch/alpha/include/asm/core_mcpcia.h b/arch/alpha/include/asm/core_mcpcia.h index 21ac53383b37..9f67a056b461 100644 --- a/arch/alpha/include/asm/core_mcpcia.h +++ b/arch/alpha/include/asm/core_mcpcia.h | |||
@@ -247,7 +247,7 @@ struct el_MCPCIA_uncorrected_frame_mcheck { | |||
247 | #define vip volatile int __force * | 247 | #define vip volatile int __force * |
248 | #define vuip volatile unsigned int __force * | 248 | #define vuip volatile unsigned int __force * |
249 | 249 | ||
250 | #ifdef MCPCIA_ONE_HAE_WINDOW | 250 | #ifndef MCPCIA_ONE_HAE_WINDOW |
251 | #define MCPCIA_FROB_MMIO \ | 251 | #define MCPCIA_FROB_MMIO \ |
252 | if (__mcpcia_is_mmio(hose)) { \ | 252 | if (__mcpcia_is_mmio(hose)) { \ |
253 | set_hae(hose & 0xffffffff); \ | 253 | set_hae(hose & 0xffffffff); \ |
diff --git a/arch/alpha/include/asm/core_t2.h b/arch/alpha/include/asm/core_t2.h index 471c07292e0b..91b46801b290 100644 --- a/arch/alpha/include/asm/core_t2.h +++ b/arch/alpha/include/asm/core_t2.h | |||
@@ -1,6 +1,9 @@ | |||
1 | #ifndef __ALPHA_T2__H__ | 1 | #ifndef __ALPHA_T2__H__ |
2 | #define __ALPHA_T2__H__ | 2 | #define __ALPHA_T2__H__ |
3 | 3 | ||
4 | /* Fit everything into one 128MB HAE window. */ | ||
5 | #define T2_ONE_HAE_WINDOW 1 | ||
6 | |||
4 | #include <linux/types.h> | 7 | #include <linux/types.h> |
5 | #include <linux/spinlock.h> | 8 | #include <linux/spinlock.h> |
6 | #include <asm/compiler.h> | 9 | #include <asm/compiler.h> |
@@ -19,7 +22,7 @@ | |||
19 | * | 22 | * |
20 | */ | 23 | */ |
21 | 24 | ||
22 | #define T2_MEM_R1_MASK 0x07ffffff /* Mem sparse region 1 mask is 26 bits */ | 25 | #define T2_MEM_R1_MASK 0x07ffffff /* Mem sparse region 1 mask is 27 bits */ |
23 | 26 | ||
24 | /* GAMMA-SABLE is a SABLE with EV5-based CPUs */ | 27 | /* GAMMA-SABLE is a SABLE with EV5-based CPUs */ |
25 | /* All LYNX machines, EV4 or EV5, use the GAMMA bias also */ | 28 | /* All LYNX machines, EV4 or EV5, use the GAMMA bias also */ |
@@ -85,7 +88,9 @@ | |||
85 | #define T2_DIR (IDENT_ADDR + GAMMA_BIAS + 0x38e0004a0UL) | 88 | #define T2_DIR (IDENT_ADDR + GAMMA_BIAS + 0x38e0004a0UL) |
86 | #define T2_ICE (IDENT_ADDR + GAMMA_BIAS + 0x38e0004c0UL) | 89 | #define T2_ICE (IDENT_ADDR + GAMMA_BIAS + 0x38e0004c0UL) |
87 | 90 | ||
91 | #ifndef T2_ONE_HAE_WINDOW | ||
88 | #define T2_HAE_ADDRESS T2_HAE_1 | 92 | #define T2_HAE_ADDRESS T2_HAE_1 |
93 | #endif | ||
89 | 94 | ||
90 | /* T2 CSRs are in the non-cachable primary IO space from 3.8000.0000 to | 95 | /* T2 CSRs are in the non-cachable primary IO space from 3.8000.0000 to |
91 | 3.8fff.ffff | 96 | 3.8fff.ffff |
@@ -429,13 +434,15 @@ extern inline void t2_outl(u32 b, unsigned long addr) | |||
429 | * | 434 | * |
430 | */ | 435 | */ |
431 | 436 | ||
437 | #ifdef T2_ONE_HAE_WINDOW | ||
438 | #define t2_set_hae | ||
439 | #else | ||
432 | #define t2_set_hae { \ | 440 | #define t2_set_hae { \ |
433 | msb = addr >> 27; \ | 441 | unsigned long msb = addr >> 27; \ |
434 | addr &= T2_MEM_R1_MASK; \ | 442 | addr &= T2_MEM_R1_MASK; \ |
435 | set_hae(msb); \ | 443 | set_hae(msb); \ |
436 | } | 444 | } |
437 | 445 | #endif | |
438 | extern raw_spinlock_t t2_hae_lock; | ||
439 | 446 | ||
440 | /* | 447 | /* |
441 | * NOTE: take T2_DENSE_MEM off in each readX/writeX routine, since | 448 | * NOTE: take T2_DENSE_MEM off in each readX/writeX routine, since |
@@ -446,28 +453,22 @@ extern raw_spinlock_t t2_hae_lock; | |||
446 | __EXTERN_INLINE u8 t2_readb(const volatile void __iomem *xaddr) | 453 | __EXTERN_INLINE u8 t2_readb(const volatile void __iomem *xaddr) |
447 | { | 454 | { |
448 | unsigned long addr = (unsigned long) xaddr - T2_DENSE_MEM; | 455 | unsigned long addr = (unsigned long) xaddr - T2_DENSE_MEM; |
449 | unsigned long result, msb; | 456 | unsigned long result; |
450 | unsigned long flags; | ||
451 | raw_spin_lock_irqsave(&t2_hae_lock, flags); | ||
452 | 457 | ||
453 | t2_set_hae; | 458 | t2_set_hae; |
454 | 459 | ||
455 | result = *(vip) ((addr << 5) + T2_SPARSE_MEM + 0x00); | 460 | result = *(vip) ((addr << 5) + T2_SPARSE_MEM + 0x00); |
456 | raw_spin_unlock_irqrestore(&t2_hae_lock, flags); | ||
457 | return __kernel_extbl(result, addr & 3); | 461 | return __kernel_extbl(result, addr & 3); |
458 | } | 462 | } |
459 | 463 | ||
460 | __EXTERN_INLINE u16 t2_readw(const volatile void __iomem *xaddr) | 464 | __EXTERN_INLINE u16 t2_readw(const volatile void __iomem *xaddr) |
461 | { | 465 | { |
462 | unsigned long addr = (unsigned long) xaddr - T2_DENSE_MEM; | 466 | unsigned long addr = (unsigned long) xaddr - T2_DENSE_MEM; |
463 | unsigned long result, msb; | 467 | unsigned long result; |
464 | unsigned long flags; | ||
465 | raw_spin_lock_irqsave(&t2_hae_lock, flags); | ||
466 | 468 | ||
467 | t2_set_hae; | 469 | t2_set_hae; |
468 | 470 | ||
469 | result = *(vuip) ((addr << 5) + T2_SPARSE_MEM + 0x08); | 471 | result = *(vuip) ((addr << 5) + T2_SPARSE_MEM + 0x08); |
470 | raw_spin_unlock_irqrestore(&t2_hae_lock, flags); | ||
471 | return __kernel_extwl(result, addr & 3); | 472 | return __kernel_extwl(result, addr & 3); |
472 | } | 473 | } |
473 | 474 | ||
@@ -478,59 +479,47 @@ __EXTERN_INLINE u16 t2_readw(const volatile void __iomem *xaddr) | |||
478 | __EXTERN_INLINE u32 t2_readl(const volatile void __iomem *xaddr) | 479 | __EXTERN_INLINE u32 t2_readl(const volatile void __iomem *xaddr) |
479 | { | 480 | { |
480 | unsigned long addr = (unsigned long) xaddr - T2_DENSE_MEM; | 481 | unsigned long addr = (unsigned long) xaddr - T2_DENSE_MEM; |
481 | unsigned long result, msb; | 482 | unsigned long result; |
482 | unsigned long flags; | ||
483 | raw_spin_lock_irqsave(&t2_hae_lock, flags); | ||
484 | 483 | ||
485 | t2_set_hae; | 484 | t2_set_hae; |
486 | 485 | ||
487 | result = *(vuip) ((addr << 5) + T2_SPARSE_MEM + 0x18); | 486 | result = *(vuip) ((addr << 5) + T2_SPARSE_MEM + 0x18); |
488 | raw_spin_unlock_irqrestore(&t2_hae_lock, flags); | ||
489 | return result & 0xffffffffUL; | 487 | return result & 0xffffffffUL; |
490 | } | 488 | } |
491 | 489 | ||
492 | __EXTERN_INLINE u64 t2_readq(const volatile void __iomem *xaddr) | 490 | __EXTERN_INLINE u64 t2_readq(const volatile void __iomem *xaddr) |
493 | { | 491 | { |
494 | unsigned long addr = (unsigned long) xaddr - T2_DENSE_MEM; | 492 | unsigned long addr = (unsigned long) xaddr - T2_DENSE_MEM; |
495 | unsigned long r0, r1, work, msb; | 493 | unsigned long r0, r1, work; |
496 | unsigned long flags; | ||
497 | raw_spin_lock_irqsave(&t2_hae_lock, flags); | ||
498 | 494 | ||
499 | t2_set_hae; | 495 | t2_set_hae; |
500 | 496 | ||
501 | work = (addr << 5) + T2_SPARSE_MEM + 0x18; | 497 | work = (addr << 5) + T2_SPARSE_MEM + 0x18; |
502 | r0 = *(vuip)(work); | 498 | r0 = *(vuip)(work); |
503 | r1 = *(vuip)(work + (4 << 5)); | 499 | r1 = *(vuip)(work + (4 << 5)); |
504 | raw_spin_unlock_irqrestore(&t2_hae_lock, flags); | ||
505 | return r1 << 32 | r0; | 500 | return r1 << 32 | r0; |
506 | } | 501 | } |
507 | 502 | ||
508 | __EXTERN_INLINE void t2_writeb(u8 b, volatile void __iomem *xaddr) | 503 | __EXTERN_INLINE void t2_writeb(u8 b, volatile void __iomem *xaddr) |
509 | { | 504 | { |
510 | unsigned long addr = (unsigned long) xaddr - T2_DENSE_MEM; | 505 | unsigned long addr = (unsigned long) xaddr - T2_DENSE_MEM; |
511 | unsigned long msb, w; | 506 | unsigned long w; |
512 | unsigned long flags; | ||
513 | raw_spin_lock_irqsave(&t2_hae_lock, flags); | ||
514 | 507 | ||
515 | t2_set_hae; | 508 | t2_set_hae; |
516 | 509 | ||
517 | w = __kernel_insbl(b, addr & 3); | 510 | w = __kernel_insbl(b, addr & 3); |
518 | *(vuip) ((addr << 5) + T2_SPARSE_MEM + 0x00) = w; | 511 | *(vuip) ((addr << 5) + T2_SPARSE_MEM + 0x00) = w; |
519 | raw_spin_unlock_irqrestore(&t2_hae_lock, flags); | ||
520 | } | 512 | } |
521 | 513 | ||
522 | __EXTERN_INLINE void t2_writew(u16 b, volatile void __iomem *xaddr) | 514 | __EXTERN_INLINE void t2_writew(u16 b, volatile void __iomem *xaddr) |
523 | { | 515 | { |
524 | unsigned long addr = (unsigned long) xaddr - T2_DENSE_MEM; | 516 | unsigned long addr = (unsigned long) xaddr - T2_DENSE_MEM; |
525 | unsigned long msb, w; | 517 | unsigned long w; |
526 | unsigned long flags; | ||
527 | raw_spin_lock_irqsave(&t2_hae_lock, flags); | ||
528 | 518 | ||
529 | t2_set_hae; | 519 | t2_set_hae; |
530 | 520 | ||
531 | w = __kernel_inswl(b, addr & 3); | 521 | w = __kernel_inswl(b, addr & 3); |
532 | *(vuip) ((addr << 5) + T2_SPARSE_MEM + 0x08) = w; | 522 | *(vuip) ((addr << 5) + T2_SPARSE_MEM + 0x08) = w; |
533 | raw_spin_unlock_irqrestore(&t2_hae_lock, flags); | ||
534 | } | 523 | } |
535 | 524 | ||
536 | /* | 525 | /* |
@@ -540,29 +529,22 @@ __EXTERN_INLINE void t2_writew(u16 b, volatile void __iomem *xaddr) | |||
540 | __EXTERN_INLINE void t2_writel(u32 b, volatile void __iomem *xaddr) | 529 | __EXTERN_INLINE void t2_writel(u32 b, volatile void __iomem *xaddr) |
541 | { | 530 | { |
542 | unsigned long addr = (unsigned long) xaddr - T2_DENSE_MEM; | 531 | unsigned long addr = (unsigned long) xaddr - T2_DENSE_MEM; |
543 | unsigned long msb; | ||
544 | unsigned long flags; | ||
545 | raw_spin_lock_irqsave(&t2_hae_lock, flags); | ||
546 | 532 | ||
547 | t2_set_hae; | 533 | t2_set_hae; |
548 | 534 | ||
549 | *(vuip) ((addr << 5) + T2_SPARSE_MEM + 0x18) = b; | 535 | *(vuip) ((addr << 5) + T2_SPARSE_MEM + 0x18) = b; |
550 | raw_spin_unlock_irqrestore(&t2_hae_lock, flags); | ||
551 | } | 536 | } |
552 | 537 | ||
553 | __EXTERN_INLINE void t2_writeq(u64 b, volatile void __iomem *xaddr) | 538 | __EXTERN_INLINE void t2_writeq(u64 b, volatile void __iomem *xaddr) |
554 | { | 539 | { |
555 | unsigned long addr = (unsigned long) xaddr - T2_DENSE_MEM; | 540 | unsigned long addr = (unsigned long) xaddr - T2_DENSE_MEM; |
556 | unsigned long msb, work; | 541 | unsigned long work; |
557 | unsigned long flags; | ||
558 | raw_spin_lock_irqsave(&t2_hae_lock, flags); | ||
559 | 542 | ||
560 | t2_set_hae; | 543 | t2_set_hae; |
561 | 544 | ||
562 | work = (addr << 5) + T2_SPARSE_MEM + 0x18; | 545 | work = (addr << 5) + T2_SPARSE_MEM + 0x18; |
563 | *(vuip)work = b; | 546 | *(vuip)work = b; |
564 | *(vuip)(work + (4 << 5)) = b >> 32; | 547 | *(vuip)(work + (4 << 5)) = b >> 32; |
565 | raw_spin_unlock_irqrestore(&t2_hae_lock, flags); | ||
566 | } | 548 | } |
567 | 549 | ||
568 | __EXTERN_INLINE void __iomem *t2_ioportmap(unsigned long addr) | 550 | __EXTERN_INLINE void __iomem *t2_ioportmap(unsigned long addr) |
diff --git a/arch/alpha/include/asm/pgtable.h b/arch/alpha/include/asm/pgtable.h index 71a243294142..de98a732683d 100644 --- a/arch/alpha/include/asm/pgtable.h +++ b/arch/alpha/include/asm/pgtable.h | |||
@@ -318,9 +318,7 @@ extern inline pte_t * pte_offset_kernel(pmd_t * dir, unsigned long address) | |||
318 | } | 318 | } |
319 | 319 | ||
320 | #define pte_offset_map(dir,addr) pte_offset_kernel((dir),(addr)) | 320 | #define pte_offset_map(dir,addr) pte_offset_kernel((dir),(addr)) |
321 | #define pte_offset_map_nested(dir,addr) pte_offset_kernel((dir),(addr)) | ||
322 | #define pte_unmap(pte) do { } while (0) | 321 | #define pte_unmap(pte) do { } while (0) |
323 | #define pte_unmap_nested(pte) do { } while (0) | ||
324 | 322 | ||
325 | extern pgd_t swapper_pg_dir[1024]; | 323 | extern pgd_t swapper_pg_dir[1024]; |
326 | 324 | ||
diff --git a/arch/alpha/kernel/core_t2.c b/arch/alpha/kernel/core_t2.c index e6d90568b65d..2f770e994289 100644 --- a/arch/alpha/kernel/core_t2.c +++ b/arch/alpha/kernel/core_t2.c | |||
@@ -74,8 +74,6 @@ | |||
74 | # define DBG(args) | 74 | # define DBG(args) |
75 | #endif | 75 | #endif |
76 | 76 | ||
77 | DEFINE_RAW_SPINLOCK(t2_hae_lock); | ||
78 | |||
79 | static volatile unsigned int t2_mcheck_any_expected; | 77 | static volatile unsigned int t2_mcheck_any_expected; |
80 | static volatile unsigned int t2_mcheck_last_taken; | 78 | static volatile unsigned int t2_mcheck_last_taken; |
81 | 79 | ||
@@ -406,6 +404,7 @@ void __init | |||
406 | t2_init_arch(void) | 404 | t2_init_arch(void) |
407 | { | 405 | { |
408 | struct pci_controller *hose; | 406 | struct pci_controller *hose; |
407 | struct resource *hae_mem; | ||
409 | unsigned long temp; | 408 | unsigned long temp; |
410 | unsigned int i; | 409 | unsigned int i; |
411 | 410 | ||
@@ -433,7 +432,13 @@ t2_init_arch(void) | |||
433 | */ | 432 | */ |
434 | pci_isa_hose = hose = alloc_pci_controller(); | 433 | pci_isa_hose = hose = alloc_pci_controller(); |
435 | hose->io_space = &ioport_resource; | 434 | hose->io_space = &ioport_resource; |
436 | hose->mem_space = &iomem_resource; | 435 | hae_mem = alloc_resource(); |
436 | hae_mem->start = 0; | ||
437 | hae_mem->end = T2_MEM_R1_MASK; | ||
438 | hae_mem->name = pci_hae0_name; | ||
439 | if (request_resource(&iomem_resource, hae_mem) < 0) | ||
440 | printk(KERN_ERR "Failed to request HAE_MEM\n"); | ||
441 | hose->mem_space = hae_mem; | ||
437 | hose->index = 0; | 442 | hose->index = 0; |
438 | 443 | ||
439 | hose->sparse_mem_base = T2_SPARSE_MEM - IDENT_ADDR; | 444 | hose->sparse_mem_base = T2_SPARSE_MEM - IDENT_ADDR; |
diff --git a/arch/alpha/kernel/machvec_impl.h b/arch/alpha/kernel/machvec_impl.h index 512685f78097..7fa62488bd16 100644 --- a/arch/alpha/kernel/machvec_impl.h +++ b/arch/alpha/kernel/machvec_impl.h | |||
@@ -25,6 +25,9 @@ | |||
25 | #ifdef MCPCIA_ONE_HAE_WINDOW | 25 | #ifdef MCPCIA_ONE_HAE_WINDOW |
26 | #define MCPCIA_HAE_ADDRESS (&alpha_mv.hae_cache) | 26 | #define MCPCIA_HAE_ADDRESS (&alpha_mv.hae_cache) |
27 | #endif | 27 | #endif |
28 | #ifdef T2_ONE_HAE_WINDOW | ||
29 | #define T2_HAE_ADDRESS (&alpha_mv.hae_cache) | ||
30 | #endif | ||
28 | 31 | ||
29 | /* Only a few systems don't define IACK_SC, handling all interrupts through | 32 | /* Only a few systems don't define IACK_SC, handling all interrupts through |
30 | the SRM console. But splitting out that one case from IO() below | 33 | the SRM console. But splitting out that one case from IO() below |
diff --git a/arch/arm/include/asm/highmem.h b/arch/arm/include/asm/highmem.h index 5aff58126602..1fc684e70ab6 100644 --- a/arch/arm/include/asm/highmem.h +++ b/arch/arm/include/asm/highmem.h | |||
@@ -35,9 +35,9 @@ extern void kunmap_high_l1_vipt(struct page *page, pte_t saved_pte); | |||
35 | #ifdef CONFIG_HIGHMEM | 35 | #ifdef CONFIG_HIGHMEM |
36 | extern void *kmap(struct page *page); | 36 | extern void *kmap(struct page *page); |
37 | extern void kunmap(struct page *page); | 37 | extern void kunmap(struct page *page); |
38 | extern void *kmap_atomic(struct page *page, enum km_type type); | 38 | extern void *__kmap_atomic(struct page *page); |
39 | extern void kunmap_atomic_notypecheck(void *kvaddr, enum km_type type); | 39 | extern void __kunmap_atomic(void *kvaddr); |
40 | extern void *kmap_atomic_pfn(unsigned long pfn, enum km_type type); | 40 | extern void *kmap_atomic_pfn(unsigned long pfn); |
41 | extern struct page *kmap_atomic_to_page(const void *ptr); | 41 | extern struct page *kmap_atomic_to_page(const void *ptr); |
42 | #endif | 42 | #endif |
43 | 43 | ||
diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h index a9672e8406a3..b155414192da 100644 --- a/arch/arm/include/asm/pgtable.h +++ b/arch/arm/include/asm/pgtable.h | |||
@@ -263,17 +263,15 @@ extern struct page *empty_zero_page; | |||
263 | #define pte_page(pte) (pfn_to_page(pte_pfn(pte))) | 263 | #define pte_page(pte) (pfn_to_page(pte_pfn(pte))) |
264 | #define pte_offset_kernel(dir,addr) (pmd_page_vaddr(*(dir)) + __pte_index(addr)) | 264 | #define pte_offset_kernel(dir,addr) (pmd_page_vaddr(*(dir)) + __pte_index(addr)) |
265 | 265 | ||
266 | #define pte_offset_map(dir,addr) (__pte_map(dir, KM_PTE0) + __pte_index(addr)) | 266 | #define pte_offset_map(dir,addr) (__pte_map(dir) + __pte_index(addr)) |
267 | #define pte_offset_map_nested(dir,addr) (__pte_map(dir, KM_PTE1) + __pte_index(addr)) | 267 | #define pte_unmap(pte) __pte_unmap(pte) |
268 | #define pte_unmap(pte) __pte_unmap(pte, KM_PTE0) | ||
269 | #define pte_unmap_nested(pte) __pte_unmap(pte, KM_PTE1) | ||
270 | 268 | ||
271 | #ifndef CONFIG_HIGHPTE | 269 | #ifndef CONFIG_HIGHPTE |
272 | #define __pte_map(dir,km) pmd_page_vaddr(*(dir)) | 270 | #define __pte_map(dir) pmd_page_vaddr(*(dir)) |
273 | #define __pte_unmap(pte,km) do { } while (0) | 271 | #define __pte_unmap(pte) do { } while (0) |
274 | #else | 272 | #else |
275 | #define __pte_map(dir,km) ((pte_t *)kmap_atomic(pmd_page(*(dir)), km) + PTRS_PER_PTE) | 273 | #define __pte_map(dir) ((pte_t *)kmap_atomic(pmd_page(*(dir))) + PTRS_PER_PTE) |
276 | #define __pte_unmap(pte,km) kunmap_atomic((pte - PTRS_PER_PTE), km) | 274 | #define __pte_unmap(pte) kunmap_atomic((pte - PTRS_PER_PTE)) |
277 | #endif | 275 | #endif |
278 | 276 | ||
279 | #define set_pte_ext(ptep,pte,ext) cpu_set_pte_ext(ptep,pte,ext) | 277 | #define set_pte_ext(ptep,pte,ext) cpu_set_pte_ext(ptep,pte,ext) |
diff --git a/arch/arm/mach-ep93xx/clock.c b/arch/arm/mach-ep93xx/clock.c index 4566bd1c8660..ef06c66a6f16 100644 --- a/arch/arm/mach-ep93xx/clock.c +++ b/arch/arm/mach-ep93xx/clock.c | |||
@@ -358,8 +358,7 @@ static int calc_clk_div(struct clk *clk, unsigned long rate, | |||
358 | int i, found = 0, __div = 0, __pdiv = 0; | 358 | int i, found = 0, __div = 0, __pdiv = 0; |
359 | 359 | ||
360 | /* Don't exceed the maximum rate */ | 360 | /* Don't exceed the maximum rate */ |
361 | max_rate = max(max(clk_pll1.rate / 4, clk_pll2.rate / 4), | 361 | max_rate = max3(clk_pll1.rate / 4, clk_pll2.rate / 4, clk_xtali.rate / 4); |
362 | clk_xtali.rate / 4); | ||
363 | rate = min(rate, max_rate); | 362 | rate = min(rate, max_rate); |
364 | 363 | ||
365 | /* | 364 | /* |
diff --git a/arch/arm/mm/fault-armv.c b/arch/arm/mm/fault-armv.c index 8440d952ba6d..c493d7244d3d 100644 --- a/arch/arm/mm/fault-armv.c +++ b/arch/arm/mm/fault-armv.c | |||
@@ -89,13 +89,13 @@ static int adjust_pte(struct vm_area_struct *vma, unsigned long address, | |||
89 | * open-code the spin-locking. | 89 | * open-code the spin-locking. |
90 | */ | 90 | */ |
91 | ptl = pte_lockptr(vma->vm_mm, pmd); | 91 | ptl = pte_lockptr(vma->vm_mm, pmd); |
92 | pte = pte_offset_map_nested(pmd, address); | 92 | pte = pte_offset_map(pmd, address); |
93 | spin_lock(ptl); | 93 | spin_lock(ptl); |
94 | 94 | ||
95 | ret = do_adjust_pte(vma, address, pfn, pte); | 95 | ret = do_adjust_pte(vma, address, pfn, pte); |
96 | 96 | ||
97 | spin_unlock(ptl); | 97 | spin_unlock(ptl); |
98 | pte_unmap_nested(pte); | 98 | pte_unmap(pte); |
99 | 99 | ||
100 | return ret; | 100 | return ret; |
101 | } | 101 | } |
diff --git a/arch/arm/mm/highmem.c b/arch/arm/mm/highmem.c index 1fbdb55bfd1b..c00f119babbf 100644 --- a/arch/arm/mm/highmem.c +++ b/arch/arm/mm/highmem.c | |||
@@ -36,18 +36,17 @@ void kunmap(struct page *page) | |||
36 | } | 36 | } |
37 | EXPORT_SYMBOL(kunmap); | 37 | EXPORT_SYMBOL(kunmap); |
38 | 38 | ||
39 | void *kmap_atomic(struct page *page, enum km_type type) | 39 | void *__kmap_atomic(struct page *page) |
40 | { | 40 | { |
41 | unsigned int idx; | 41 | unsigned int idx; |
42 | unsigned long vaddr; | 42 | unsigned long vaddr; |
43 | void *kmap; | 43 | void *kmap; |
44 | int type; | ||
44 | 45 | ||
45 | pagefault_disable(); | 46 | pagefault_disable(); |
46 | if (!PageHighMem(page)) | 47 | if (!PageHighMem(page)) |
47 | return page_address(page); | 48 | return page_address(page); |
48 | 49 | ||
49 | debug_kmap_atomic(type); | ||
50 | |||
51 | #ifdef CONFIG_DEBUG_HIGHMEM | 50 | #ifdef CONFIG_DEBUG_HIGHMEM |
52 | /* | 51 | /* |
53 | * There is no cache coherency issue when non VIVT, so force the | 52 | * There is no cache coherency issue when non VIVT, so force the |
@@ -61,6 +60,8 @@ void *kmap_atomic(struct page *page, enum km_type type) | |||
61 | if (kmap) | 60 | if (kmap) |
62 | return kmap; | 61 | return kmap; |
63 | 62 | ||
63 | type = kmap_atomic_idx_push(); | ||
64 | |||
64 | idx = type + KM_TYPE_NR * smp_processor_id(); | 65 | idx = type + KM_TYPE_NR * smp_processor_id(); |
65 | vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); | 66 | vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); |
66 | #ifdef CONFIG_DEBUG_HIGHMEM | 67 | #ifdef CONFIG_DEBUG_HIGHMEM |
@@ -80,14 +81,17 @@ void *kmap_atomic(struct page *page, enum km_type type) | |||
80 | 81 | ||
81 | return (void *)vaddr; | 82 | return (void *)vaddr; |
82 | } | 83 | } |
83 | EXPORT_SYMBOL(kmap_atomic); | 84 | EXPORT_SYMBOL(__kmap_atomic); |
84 | 85 | ||
85 | void kunmap_atomic_notypecheck(void *kvaddr, enum km_type type) | 86 | void __kunmap_atomic(void *kvaddr) |
86 | { | 87 | { |
87 | unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK; | 88 | unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK; |
88 | unsigned int idx = type + KM_TYPE_NR * smp_processor_id(); | 89 | int idx, type; |
89 | 90 | ||
90 | if (kvaddr >= (void *)FIXADDR_START) { | 91 | if (kvaddr >= (void *)FIXADDR_START) { |
92 | type = kmap_atomic_idx_pop(); | ||
93 | idx = type + KM_TYPE_NR * smp_processor_id(); | ||
94 | |||
91 | if (cache_is_vivt()) | 95 | if (cache_is_vivt()) |
92 | __cpuc_flush_dcache_area((void *)vaddr, PAGE_SIZE); | 96 | __cpuc_flush_dcache_area((void *)vaddr, PAGE_SIZE); |
93 | #ifdef CONFIG_DEBUG_HIGHMEM | 97 | #ifdef CONFIG_DEBUG_HIGHMEM |
@@ -103,15 +107,16 @@ void kunmap_atomic_notypecheck(void *kvaddr, enum km_type type) | |||
103 | } | 107 | } |
104 | pagefault_enable(); | 108 | pagefault_enable(); |
105 | } | 109 | } |
106 | EXPORT_SYMBOL(kunmap_atomic_notypecheck); | 110 | EXPORT_SYMBOL(__kunmap_atomic); |
107 | 111 | ||
108 | void *kmap_atomic_pfn(unsigned long pfn, enum km_type type) | 112 | void *kmap_atomic_pfn(unsigned long pfn) |
109 | { | 113 | { |
110 | unsigned int idx; | ||
111 | unsigned long vaddr; | 114 | unsigned long vaddr; |
115 | int idx, type; | ||
112 | 116 | ||
113 | pagefault_disable(); | 117 | pagefault_disable(); |
114 | 118 | ||
119 | type = kmap_atomic_idx_push(); | ||
115 | idx = type + KM_TYPE_NR * smp_processor_id(); | 120 | idx = type + KM_TYPE_NR * smp_processor_id(); |
116 | vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); | 121 | vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); |
117 | #ifdef CONFIG_DEBUG_HIGHMEM | 122 | #ifdef CONFIG_DEBUG_HIGHMEM |
diff --git a/arch/arm/mm/pgd.c b/arch/arm/mm/pgd.c index be5f58e153bf..69bbfc6645a6 100644 --- a/arch/arm/mm/pgd.c +++ b/arch/arm/mm/pgd.c | |||
@@ -57,9 +57,9 @@ pgd_t *get_pgd_slow(struct mm_struct *mm) | |||
57 | goto no_pte; | 57 | goto no_pte; |
58 | 58 | ||
59 | init_pmd = pmd_offset(init_pgd, 0); | 59 | init_pmd = pmd_offset(init_pgd, 0); |
60 | init_pte = pte_offset_map_nested(init_pmd, 0); | 60 | init_pte = pte_offset_map(init_pmd, 0); |
61 | set_pte_ext(new_pte, *init_pte, 0); | 61 | set_pte_ext(new_pte, *init_pte, 0); |
62 | pte_unmap_nested(init_pte); | 62 | pte_unmap(init_pte); |
63 | pte_unmap(new_pte); | 63 | pte_unmap(new_pte); |
64 | } | 64 | } |
65 | 65 | ||
diff --git a/arch/avr32/include/asm/pgtable.h b/arch/avr32/include/asm/pgtable.h index a9ae30c41e74..6fbfea61f7bb 100644 --- a/arch/avr32/include/asm/pgtable.h +++ b/arch/avr32/include/asm/pgtable.h | |||
@@ -319,9 +319,7 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) | |||
319 | #define pte_offset_kernel(dir, address) \ | 319 | #define pte_offset_kernel(dir, address) \ |
320 | ((pte_t *) pmd_page_vaddr(*(dir)) + pte_index(address)) | 320 | ((pte_t *) pmd_page_vaddr(*(dir)) + pte_index(address)) |
321 | #define pte_offset_map(dir, address) pte_offset_kernel(dir, address) | 321 | #define pte_offset_map(dir, address) pte_offset_kernel(dir, address) |
322 | #define pte_offset_map_nested(dir, address) pte_offset_kernel(dir, address) | ||
323 | #define pte_unmap(pte) do { } while (0) | 322 | #define pte_unmap(pte) do { } while (0) |
324 | #define pte_unmap_nested(pte) do { } while (0) | ||
325 | 323 | ||
326 | struct vm_area_struct; | 324 | struct vm_area_struct; |
327 | extern void update_mmu_cache(struct vm_area_struct * vma, | 325 | extern void update_mmu_cache(struct vm_area_struct * vma, |
diff --git a/arch/blackfin/include/asm/entry.h b/arch/blackfin/include/asm/entry.h index a6886f6e4819..4104d5783e2c 100644 --- a/arch/blackfin/include/asm/entry.h +++ b/arch/blackfin/include/asm/entry.h | |||
@@ -15,14 +15,6 @@ | |||
15 | #define LFLUSH_I_AND_D 0x00000808 | 15 | #define LFLUSH_I_AND_D 0x00000808 |
16 | #define LSIGTRAP 5 | 16 | #define LSIGTRAP 5 |
17 | 17 | ||
18 | /* process bits for task_struct.flags */ | ||
19 | #define PF_TRACESYS_OFF 3 | ||
20 | #define PF_TRACESYS_BIT 5 | ||
21 | #define PF_PTRACED_OFF 3 | ||
22 | #define PF_PTRACED_BIT 4 | ||
23 | #define PF_DTRACE_OFF 1 | ||
24 | #define PF_DTRACE_BIT 5 | ||
25 | |||
26 | /* | 18 | /* |
27 | * NOTE! The single-stepping code assumes that all interrupt handlers | 19 | * NOTE! The single-stepping code assumes that all interrupt handlers |
28 | * start by saving SYSCFG on the stack with their first instruction. | 20 | * start by saving SYSCFG on the stack with their first instruction. |
diff --git a/arch/cris/include/asm/pgtable.h b/arch/cris/include/asm/pgtable.h index f63d6fccbc6c..9eaae217b21b 100644 --- a/arch/cris/include/asm/pgtable.h +++ b/arch/cris/include/asm/pgtable.h | |||
@@ -248,10 +248,8 @@ static inline pgd_t * pgd_offset(const struct mm_struct *mm, unsigned long addre | |||
248 | ((pte_t *) pmd_page_vaddr(*(dir)) + __pte_offset(address)) | 248 | ((pte_t *) pmd_page_vaddr(*(dir)) + __pte_offset(address)) |
249 | #define pte_offset_map(dir, address) \ | 249 | #define pte_offset_map(dir, address) \ |
250 | ((pte_t *)page_address(pmd_page(*(dir))) + __pte_offset(address)) | 250 | ((pte_t *)page_address(pmd_page(*(dir))) + __pte_offset(address)) |
251 | #define pte_offset_map_nested(dir, address) pte_offset_map(dir, address) | ||
252 | 251 | ||
253 | #define pte_unmap(pte) do { } while (0) | 252 | #define pte_unmap(pte) do { } while (0) |
254 | #define pte_unmap_nested(pte) do { } while (0) | ||
255 | #define pte_pfn(x) ((unsigned long)(__va((x).pte)) >> PAGE_SHIFT) | 253 | #define pte_pfn(x) ((unsigned long)(__va((x).pte)) >> PAGE_SHIFT) |
256 | #define pfn_pte(pfn, prot) __pte(((pfn) << PAGE_SHIFT) | pgprot_val(prot)) | 254 | #define pfn_pte(pfn, prot) __pte(((pfn) << PAGE_SHIFT) | pgprot_val(prot)) |
257 | 255 | ||
diff --git a/arch/frv/include/asm/highmem.h b/arch/frv/include/asm/highmem.h index cb4c317eaecc..a8d6565d415d 100644 --- a/arch/frv/include/asm/highmem.h +++ b/arch/frv/include/asm/highmem.h | |||
@@ -112,12 +112,11 @@ extern struct page *kmap_atomic_to_page(void *ptr); | |||
112 | (void *) damlr; \ | 112 | (void *) damlr; \ |
113 | }) | 113 | }) |
114 | 114 | ||
115 | static inline void *kmap_atomic(struct page *page, enum km_type type) | 115 | static inline void *kmap_atomic_primary(struct page *page, enum km_type type) |
116 | { | 116 | { |
117 | unsigned long paddr; | 117 | unsigned long paddr; |
118 | 118 | ||
119 | pagefault_disable(); | 119 | pagefault_disable(); |
120 | debug_kmap_atomic(type); | ||
121 | paddr = page_to_phys(page); | 120 | paddr = page_to_phys(page); |
122 | 121 | ||
123 | switch (type) { | 122 | switch (type) { |
@@ -125,14 +124,6 @@ static inline void *kmap_atomic(struct page *page, enum km_type type) | |||
125 | case 1: return __kmap_atomic_primary(1, paddr, 3); | 124 | case 1: return __kmap_atomic_primary(1, paddr, 3); |
126 | case 2: return __kmap_atomic_primary(2, paddr, 4); | 125 | case 2: return __kmap_atomic_primary(2, paddr, 4); |
127 | case 3: return __kmap_atomic_primary(3, paddr, 5); | 126 | case 3: return __kmap_atomic_primary(3, paddr, 5); |
128 | case 4: return __kmap_atomic_primary(4, paddr, 6); | ||
129 | case 5: return __kmap_atomic_primary(5, paddr, 7); | ||
130 | case 6: return __kmap_atomic_primary(6, paddr, 8); | ||
131 | case 7: return __kmap_atomic_primary(7, paddr, 9); | ||
132 | case 8: return __kmap_atomic_primary(8, paddr, 10); | ||
133 | |||
134 | case 9 ... 9 + NR_TLB_LINES - 1: | ||
135 | return __kmap_atomic_secondary(type - 9, paddr); | ||
136 | 127 | ||
137 | default: | 128 | default: |
138 | BUG(); | 129 | BUG(); |
@@ -152,22 +143,13 @@ do { \ | |||
152 | asm volatile("tlbpr %0,gr0,#4,#1" : : "r"(vaddr) : "memory"); \ | 143 | asm volatile("tlbpr %0,gr0,#4,#1" : : "r"(vaddr) : "memory"); \ |
153 | } while(0) | 144 | } while(0) |
154 | 145 | ||
155 | static inline void kunmap_atomic_notypecheck(void *kvaddr, enum km_type type) | 146 | static inline void kunmap_atomic_primary(void *kvaddr, enum km_type type) |
156 | { | 147 | { |
157 | switch (type) { | 148 | switch (type) { |
158 | case 0: __kunmap_atomic_primary(0, 2); break; | 149 | case 0: __kunmap_atomic_primary(0, 2); break; |
159 | case 1: __kunmap_atomic_primary(1, 3); break; | 150 | case 1: __kunmap_atomic_primary(1, 3); break; |
160 | case 2: __kunmap_atomic_primary(2, 4); break; | 151 | case 2: __kunmap_atomic_primary(2, 4); break; |
161 | case 3: __kunmap_atomic_primary(3, 5); break; | 152 | case 3: __kunmap_atomic_primary(3, 5); break; |
162 | case 4: __kunmap_atomic_primary(4, 6); break; | ||
163 | case 5: __kunmap_atomic_primary(5, 7); break; | ||
164 | case 6: __kunmap_atomic_primary(6, 8); break; | ||
165 | case 7: __kunmap_atomic_primary(7, 9); break; | ||
166 | case 8: __kunmap_atomic_primary(8, 10); break; | ||
167 | |||
168 | case 9 ... 9 + NR_TLB_LINES - 1: | ||
169 | __kunmap_atomic_secondary(type - 9, kvaddr); | ||
170 | break; | ||
171 | 153 | ||
172 | default: | 154 | default: |
173 | BUG(); | 155 | BUG(); |
@@ -175,6 +157,9 @@ static inline void kunmap_atomic_notypecheck(void *kvaddr, enum km_type type) | |||
175 | pagefault_enable(); | 157 | pagefault_enable(); |
176 | } | 158 | } |
177 | 159 | ||
160 | void *__kmap_atomic(struct page *page); | ||
161 | void __kunmap_atomic(void *kvaddr); | ||
162 | |||
178 | #endif /* !__ASSEMBLY__ */ | 163 | #endif /* !__ASSEMBLY__ */ |
179 | 164 | ||
180 | #endif /* __KERNEL__ */ | 165 | #endif /* __KERNEL__ */ |
diff --git a/arch/frv/include/asm/pgtable.h b/arch/frv/include/asm/pgtable.h index c18b0d32e636..6bc241e4b4f8 100644 --- a/arch/frv/include/asm/pgtable.h +++ b/arch/frv/include/asm/pgtable.h | |||
@@ -451,17 +451,12 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) | |||
451 | 451 | ||
452 | #if defined(CONFIG_HIGHPTE) | 452 | #if defined(CONFIG_HIGHPTE) |
453 | #define pte_offset_map(dir, address) \ | 453 | #define pte_offset_map(dir, address) \ |
454 | ((pte_t *)kmap_atomic(pmd_page(*(dir)),KM_PTE0) + pte_index(address)) | 454 | ((pte_t *)kmap_atomic(pmd_page(*(dir))) + pte_index(address)) |
455 | #define pte_offset_map_nested(dir, address) \ | 455 | #define pte_unmap(pte) kunmap_atomic(pte) |
456 | ((pte_t *)kmap_atomic(pmd_page(*(dir)),KM_PTE1) + pte_index(address)) | ||
457 | #define pte_unmap(pte) kunmap_atomic(pte, KM_PTE0) | ||
458 | #define pte_unmap_nested(pte) kunmap_atomic((pte), KM_PTE1) | ||
459 | #else | 456 | #else |
460 | #define pte_offset_map(dir, address) \ | 457 | #define pte_offset_map(dir, address) \ |
461 | ((pte_t *)page_address(pmd_page(*(dir))) + pte_index(address)) | 458 | ((pte_t *)page_address(pmd_page(*(dir))) + pte_index(address)) |
462 | #define pte_offset_map_nested(dir, address) pte_offset_map((dir), (address)) | ||
463 | #define pte_unmap(pte) do { } while (0) | 459 | #define pte_unmap(pte) do { } while (0) |
464 | #define pte_unmap_nested(pte) do { } while (0) | ||
465 | #endif | 460 | #endif |
466 | 461 | ||
467 | /* | 462 | /* |
diff --git a/arch/frv/mb93090-mb00/pci-dma.c b/arch/frv/mb93090-mb00/pci-dma.c index 85d110b71cf7..41098a3803a2 100644 --- a/arch/frv/mb93090-mb00/pci-dma.c +++ b/arch/frv/mb93090-mb00/pci-dma.c | |||
@@ -61,14 +61,14 @@ int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, | |||
61 | dampr2 = __get_DAMPR(2); | 61 | dampr2 = __get_DAMPR(2); |
62 | 62 | ||
63 | for (i = 0; i < nents; i++) { | 63 | for (i = 0; i < nents; i++) { |
64 | vaddr = kmap_atomic(sg_page(&sg[i]), __KM_CACHE); | 64 | vaddr = kmap_atomic_primary(sg_page(&sg[i]), __KM_CACHE); |
65 | 65 | ||
66 | frv_dcache_writeback((unsigned long) vaddr, | 66 | frv_dcache_writeback((unsigned long) vaddr, |
67 | (unsigned long) vaddr + PAGE_SIZE); | 67 | (unsigned long) vaddr + PAGE_SIZE); |
68 | 68 | ||
69 | } | 69 | } |
70 | 70 | ||
71 | kunmap_atomic(vaddr, __KM_CACHE); | 71 | kunmap_atomic_primary(vaddr, __KM_CACHE); |
72 | if (dampr2) { | 72 | if (dampr2) { |
73 | __set_DAMPR(2, dampr2); | 73 | __set_DAMPR(2, dampr2); |
74 | __set_IAMPR(2, dampr2); | 74 | __set_IAMPR(2, dampr2); |
diff --git a/arch/frv/mm/cache-page.c b/arch/frv/mm/cache-page.c index 0261cbe153b5..b24ade27a0f0 100644 --- a/arch/frv/mm/cache-page.c +++ b/arch/frv/mm/cache-page.c | |||
@@ -26,11 +26,11 @@ void flush_dcache_page(struct page *page) | |||
26 | 26 | ||
27 | dampr2 = __get_DAMPR(2); | 27 | dampr2 = __get_DAMPR(2); |
28 | 28 | ||
29 | vaddr = kmap_atomic(page, __KM_CACHE); | 29 | vaddr = kmap_atomic_primary(page, __KM_CACHE); |
30 | 30 | ||
31 | frv_dcache_writeback((unsigned long) vaddr, (unsigned long) vaddr + PAGE_SIZE); | 31 | frv_dcache_writeback((unsigned long) vaddr, (unsigned long) vaddr + PAGE_SIZE); |
32 | 32 | ||
33 | kunmap_atomic(vaddr, __KM_CACHE); | 33 | kunmap_atomic_primary(vaddr, __KM_CACHE); |
34 | 34 | ||
35 | if (dampr2) { | 35 | if (dampr2) { |
36 | __set_DAMPR(2, dampr2); | 36 | __set_DAMPR(2, dampr2); |
@@ -54,12 +54,12 @@ void flush_icache_user_range(struct vm_area_struct *vma, struct page *page, | |||
54 | 54 | ||
55 | dampr2 = __get_DAMPR(2); | 55 | dampr2 = __get_DAMPR(2); |
56 | 56 | ||
57 | vaddr = kmap_atomic(page, __KM_CACHE); | 57 | vaddr = kmap_atomic_primary(page, __KM_CACHE); |
58 | 58 | ||
59 | start = (start & ~PAGE_MASK) | (unsigned long) vaddr; | 59 | start = (start & ~PAGE_MASK) | (unsigned long) vaddr; |
60 | frv_cache_wback_inv(start, start + len); | 60 | frv_cache_wback_inv(start, start + len); |
61 | 61 | ||
62 | kunmap_atomic(vaddr, __KM_CACHE); | 62 | kunmap_atomic_primary(vaddr, __KM_CACHE); |
63 | 63 | ||
64 | if (dampr2) { | 64 | if (dampr2) { |
65 | __set_DAMPR(2, dampr2); | 65 | __set_DAMPR(2, dampr2); |
diff --git a/arch/frv/mm/highmem.c b/arch/frv/mm/highmem.c index eadd07658075..61088dcc1594 100644 --- a/arch/frv/mm/highmem.c +++ b/arch/frv/mm/highmem.c | |||
@@ -36,3 +36,53 @@ struct page *kmap_atomic_to_page(void *ptr) | |||
36 | { | 36 | { |
37 | return virt_to_page(ptr); | 37 | return virt_to_page(ptr); |
38 | } | 38 | } |
39 | |||
40 | void *__kmap_atomic(struct page *page) | ||
41 | { | ||
42 | unsigned long paddr; | ||
43 | int type; | ||
44 | |||
45 | pagefault_disable(); | ||
46 | type = kmap_atomic_idx_push(); | ||
47 | paddr = page_to_phys(page); | ||
48 | |||
49 | switch (type) { | ||
50 | /* | ||
51 | * The first 4 primary maps are reserved for architecture code | ||
52 | */ | ||
53 | case 0: return __kmap_atomic_primary(4, paddr, 6); | ||
54 | case 1: return __kmap_atomic_primary(5, paddr, 7); | ||
55 | case 2: return __kmap_atomic_primary(6, paddr, 8); | ||
56 | case 3: return __kmap_atomic_primary(7, paddr, 9); | ||
57 | case 4: return __kmap_atomic_primary(8, paddr, 10); | ||
58 | |||
59 | case 5 ... 5 + NR_TLB_LINES - 1: | ||
60 | return __kmap_atomic_secondary(type - 5, paddr); | ||
61 | |||
62 | default: | ||
63 | BUG(); | ||
64 | return NULL; | ||
65 | } | ||
66 | } | ||
67 | EXPORT_SYMBOL(__kmap_atomic); | ||
68 | |||
69 | void __kunmap_atomic(void *kvaddr) | ||
70 | { | ||
71 | int type = kmap_atomic_idx_pop(); | ||
72 | switch (type) { | ||
73 | case 0: __kunmap_atomic_primary(4, 6); break; | ||
74 | case 1: __kunmap_atomic_primary(5, 7); break; | ||
75 | case 2: __kunmap_atomic_primary(6, 8); break; | ||
76 | case 3: __kunmap_atomic_primary(7, 9); break; | ||
77 | case 4: __kunmap_atomic_primary(8, 10); break; | ||
78 | |||
79 | case 5 ... 5 + NR_TLB_LINES - 1: | ||
80 | __kunmap_atomic_secondary(type - 5, kvaddr); | ||
81 | break; | ||
82 | |||
83 | default: | ||
84 | BUG(); | ||
85 | } | ||
86 | pagefault_enable(); | ||
87 | } | ||
88 | EXPORT_SYMBOL(__kunmap_atomic); | ||
diff --git a/arch/ia64/include/asm/pgtable.h b/arch/ia64/include/asm/pgtable.h index c3286f42e501..1a97af31ef17 100644 --- a/arch/ia64/include/asm/pgtable.h +++ b/arch/ia64/include/asm/pgtable.h | |||
@@ -406,9 +406,7 @@ pgd_offset (const struct mm_struct *mm, unsigned long address) | |||
406 | #define pte_index(addr) (((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)) | 406 | #define pte_index(addr) (((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)) |
407 | #define pte_offset_kernel(dir,addr) ((pte_t *) pmd_page_vaddr(*(dir)) + pte_index(addr)) | 407 | #define pte_offset_kernel(dir,addr) ((pte_t *) pmd_page_vaddr(*(dir)) + pte_index(addr)) |
408 | #define pte_offset_map(dir,addr) pte_offset_kernel(dir, addr) | 408 | #define pte_offset_map(dir,addr) pte_offset_kernel(dir, addr) |
409 | #define pte_offset_map_nested(dir,addr) pte_offset_map(dir, addr) | ||
410 | #define pte_unmap(pte) do { } while (0) | 409 | #define pte_unmap(pte) do { } while (0) |
411 | #define pte_unmap_nested(pte) do { } while (0) | ||
412 | 410 | ||
413 | /* atomic versions of the some PTE manipulations: */ | 411 | /* atomic versions of the some PTE manipulations: */ |
414 | 412 | ||
diff --git a/arch/m32r/include/asm/pgtable.h b/arch/m32r/include/asm/pgtable.h index e6359c566b50..8a28cfea2729 100644 --- a/arch/m32r/include/asm/pgtable.h +++ b/arch/m32r/include/asm/pgtable.h | |||
@@ -332,9 +332,7 @@ static inline void pmd_set(pmd_t * pmdp, pte_t * ptep) | |||
332 | ((pte_t *)pmd_page_vaddr(*(dir)) + pte_index(address)) | 332 | ((pte_t *)pmd_page_vaddr(*(dir)) + pte_index(address)) |
333 | #define pte_offset_map(dir, address) \ | 333 | #define pte_offset_map(dir, address) \ |
334 | ((pte_t *)page_address(pmd_page(*(dir))) + pte_index(address)) | 334 | ((pte_t *)page_address(pmd_page(*(dir))) + pte_index(address)) |
335 | #define pte_offset_map_nested(dir, address) pte_offset_map(dir, address) | ||
336 | #define pte_unmap(pte) do { } while (0) | 335 | #define pte_unmap(pte) do { } while (0) |
337 | #define pte_unmap_nested(pte) do { } while (0) | ||
338 | 336 | ||
339 | /* Encode and de-code a swap entry */ | 337 | /* Encode and de-code a swap entry */ |
340 | #define __swp_type(x) (((x).val >> 2) & 0x1f) | 338 | #define __swp_type(x) (((x).val >> 2) & 0x1f) |
diff --git a/arch/m68k/include/asm/entry_mm.h b/arch/m68k/include/asm/entry_mm.h index e41fea399bfe..73b8c8fbed9c 100644 --- a/arch/m68k/include/asm/entry_mm.h +++ b/arch/m68k/include/asm/entry_mm.h | |||
@@ -50,14 +50,6 @@ | |||
50 | 50 | ||
51 | LFLUSH_I_AND_D = 0x00000808 | 51 | LFLUSH_I_AND_D = 0x00000808 |
52 | 52 | ||
53 | /* process bits for task_struct.ptrace */ | ||
54 | PT_TRACESYS_OFF = 3 | ||
55 | PT_TRACESYS_BIT = 1 | ||
56 | PT_PTRACED_OFF = 3 | ||
57 | PT_PTRACED_BIT = 0 | ||
58 | PT_DTRACE_OFF = 3 | ||
59 | PT_DTRACE_BIT = 2 | ||
60 | |||
61 | #define SAVE_ALL_INT save_all_int | 53 | #define SAVE_ALL_INT save_all_int |
62 | #define SAVE_ALL_SYS save_all_sys | 54 | #define SAVE_ALL_SYS save_all_sys |
63 | #define RESTORE_ALL restore_all | 55 | #define RESTORE_ALL restore_all |
diff --git a/arch/m68k/include/asm/entry_no.h b/arch/m68k/include/asm/entry_no.h index 80e41492aa2a..26be277394f9 100644 --- a/arch/m68k/include/asm/entry_no.h +++ b/arch/m68k/include/asm/entry_no.h | |||
@@ -32,16 +32,6 @@ | |||
32 | 32 | ||
33 | #ifdef __ASSEMBLY__ | 33 | #ifdef __ASSEMBLY__ |
34 | 34 | ||
35 | /* process bits for task_struct.flags */ | ||
36 | PF_TRACESYS_OFF = 3 | ||
37 | PF_TRACESYS_BIT = 5 | ||
38 | PF_PTRACED_OFF = 3 | ||
39 | PF_PTRACED_BIT = 4 | ||
40 | PF_DTRACE_OFF = 1 | ||
41 | PF_DTRACE_BIT = 5 | ||
42 | |||
43 | LENOSYS = 38 | ||
44 | |||
45 | #define SWITCH_STACK_SIZE (6*4+4) /* Includes return address */ | 35 | #define SWITCH_STACK_SIZE (6*4+4) /* Includes return address */ |
46 | 36 | ||
47 | /* | 37 | /* |
diff --git a/arch/m68k/include/asm/motorola_pgtable.h b/arch/m68k/include/asm/motorola_pgtable.h index 8e9a8a754dde..45bd3f589bf0 100644 --- a/arch/m68k/include/asm/motorola_pgtable.h +++ b/arch/m68k/include/asm/motorola_pgtable.h | |||
@@ -221,9 +221,7 @@ static inline pte_t *pte_offset_kernel(pmd_t *pmdp, unsigned long address) | |||
221 | } | 221 | } |
222 | 222 | ||
223 | #define pte_offset_map(pmdp,address) ((pte_t *)__pmd_page(*pmdp) + (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))) | 223 | #define pte_offset_map(pmdp,address) ((pte_t *)__pmd_page(*pmdp) + (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))) |
224 | #define pte_offset_map_nested(pmdp, address) pte_offset_map(pmdp, address) | ||
225 | #define pte_unmap(pte) ((void)0) | 224 | #define pte_unmap(pte) ((void)0) |
226 | #define pte_unmap_nested(pte) ((void)0) | ||
227 | 225 | ||
228 | /* | 226 | /* |
229 | * Allocate and free page tables. The xxx_kernel() versions are | 227 | * Allocate and free page tables. The xxx_kernel() versions are |
diff --git a/arch/m68k/include/asm/sun3_pgtable.h b/arch/m68k/include/asm/sun3_pgtable.h index f847ec732d62..cf5fad9b5250 100644 --- a/arch/m68k/include/asm/sun3_pgtable.h +++ b/arch/m68k/include/asm/sun3_pgtable.h | |||
@@ -219,9 +219,7 @@ static inline pte_t pgoff_to_pte(unsigned off) | |||
219 | #define pte_offset_kernel(pmd, address) ((pte_t *) __pmd_page(*pmd) + pte_index(address)) | 219 | #define pte_offset_kernel(pmd, address) ((pte_t *) __pmd_page(*pmd) + pte_index(address)) |
220 | /* FIXME: should we bother with kmap() here? */ | 220 | /* FIXME: should we bother with kmap() here? */ |
221 | #define pte_offset_map(pmd, address) ((pte_t *)kmap(pmd_page(*pmd)) + pte_index(address)) | 221 | #define pte_offset_map(pmd, address) ((pte_t *)kmap(pmd_page(*pmd)) + pte_index(address)) |
222 | #define pte_offset_map_nested(pmd, address) pte_offset_map(pmd, address) | ||
223 | #define pte_unmap(pte) kunmap(pte) | 222 | #define pte_unmap(pte) kunmap(pte) |
224 | #define pte_unmap_nested(pte) kunmap(pte) | ||
225 | 223 | ||
226 | /* Macros to (de)construct the fake PTEs representing swap pages. */ | 224 | /* Macros to (de)construct the fake PTEs representing swap pages. */ |
227 | #define __swp_type(x) ((x).val & 0x7F) | 225 | #define __swp_type(x) ((x).val & 0x7F) |
diff --git a/arch/microblaze/include/asm/pgtable.h b/arch/microblaze/include/asm/pgtable.h index d4f421672d3b..cae268c22ba2 100644 --- a/arch/microblaze/include/asm/pgtable.h +++ b/arch/microblaze/include/asm/pgtable.h | |||
@@ -504,12 +504,9 @@ static inline pmd_t *pmd_offset(pgd_t *dir, unsigned long address) | |||
504 | #define pte_offset_kernel(dir, addr) \ | 504 | #define pte_offset_kernel(dir, addr) \ |
505 | ((pte_t *) pmd_page_kernel(*(dir)) + pte_index(addr)) | 505 | ((pte_t *) pmd_page_kernel(*(dir)) + pte_index(addr)) |
506 | #define pte_offset_map(dir, addr) \ | 506 | #define pte_offset_map(dir, addr) \ |
507 | ((pte_t *) kmap_atomic(pmd_page(*(dir)), KM_PTE0) + pte_index(addr)) | 507 | ((pte_t *) kmap_atomic(pmd_page(*(dir))) + pte_index(addr)) |
508 | #define pte_offset_map_nested(dir, addr) \ | ||
509 | ((pte_t *) kmap_atomic(pmd_page(*(dir)), KM_PTE1) + pte_index(addr)) | ||
510 | 508 | ||
511 | #define pte_unmap(pte) kunmap_atomic(pte, KM_PTE0) | 509 | #define pte_unmap(pte) kunmap_atomic(pte) |
512 | #define pte_unmap_nested(pte) kunmap_atomic(pte, KM_PTE1) | ||
513 | 510 | ||
514 | /* Encode and decode a nonlinear file mapping entry */ | 511 | /* Encode and decode a nonlinear file mapping entry */ |
515 | #define PTE_FILE_MAX_BITS 29 | 512 | #define PTE_FILE_MAX_BITS 29 |
diff --git a/arch/mips/include/asm/highmem.h b/arch/mips/include/asm/highmem.h index 75753ca73bfd..77e644082a3b 100644 --- a/arch/mips/include/asm/highmem.h +++ b/arch/mips/include/asm/highmem.h | |||
@@ -45,18 +45,12 @@ extern pte_t *pkmap_page_table; | |||
45 | extern void * kmap_high(struct page *page); | 45 | extern void * kmap_high(struct page *page); |
46 | extern void kunmap_high(struct page *page); | 46 | extern void kunmap_high(struct page *page); |
47 | 47 | ||
48 | extern void *__kmap(struct page *page); | 48 | extern void *kmap(struct page *page); |
49 | extern void __kunmap(struct page *page); | 49 | extern void kunmap(struct page *page); |
50 | extern void *__kmap_atomic(struct page *page, enum km_type type); | 50 | extern void *__kmap_atomic(struct page *page); |
51 | extern void __kunmap_atomic_notypecheck(void *kvaddr, enum km_type type); | 51 | extern void __kunmap_atomic(void *kvaddr); |
52 | extern void *kmap_atomic_pfn(unsigned long pfn, enum km_type type); | 52 | extern void *kmap_atomic_pfn(unsigned long pfn); |
53 | extern struct page *__kmap_atomic_to_page(void *ptr); | 53 | extern struct page *kmap_atomic_to_page(void *ptr); |
54 | |||
55 | #define kmap __kmap | ||
56 | #define kunmap __kunmap | ||
57 | #define kmap_atomic __kmap_atomic | ||
58 | #define kunmap_atomic_notypecheck __kunmap_atomic_notypecheck | ||
59 | #define kmap_atomic_to_page __kmap_atomic_to_page | ||
60 | 54 | ||
61 | #define flush_cache_kmaps() flush_cache_all() | 55 | #define flush_cache_kmaps() flush_cache_all() |
62 | 56 | ||
diff --git a/arch/mips/include/asm/pgtable-32.h b/arch/mips/include/asm/pgtable-32.h index ae90412556d0..8a153d2fa62a 100644 --- a/arch/mips/include/asm/pgtable-32.h +++ b/arch/mips/include/asm/pgtable-32.h | |||
@@ -154,10 +154,7 @@ pfn_pte(unsigned long pfn, pgprot_t prot) | |||
154 | 154 | ||
155 | #define pte_offset_map(dir, address) \ | 155 | #define pte_offset_map(dir, address) \ |
156 | ((pte_t *)page_address(pmd_page(*(dir))) + __pte_offset(address)) | 156 | ((pte_t *)page_address(pmd_page(*(dir))) + __pte_offset(address)) |
157 | #define pte_offset_map_nested(dir, address) \ | ||
158 | ((pte_t *)page_address(pmd_page(*(dir))) + __pte_offset(address)) | ||
159 | #define pte_unmap(pte) ((void)(pte)) | 157 | #define pte_unmap(pte) ((void)(pte)) |
160 | #define pte_unmap_nested(pte) ((void)(pte)) | ||
161 | 158 | ||
162 | #if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX) | 159 | #if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX) |
163 | 160 | ||
diff --git a/arch/mips/include/asm/pgtable-64.h b/arch/mips/include/asm/pgtable-64.h index 1be4b0fa30da..f00896087dda 100644 --- a/arch/mips/include/asm/pgtable-64.h +++ b/arch/mips/include/asm/pgtable-64.h | |||
@@ -257,10 +257,7 @@ static inline pmd_t *pmd_offset(pud_t * pud, unsigned long address) | |||
257 | ((pte_t *) pmd_page_vaddr(*(dir)) + __pte_offset(address)) | 257 | ((pte_t *) pmd_page_vaddr(*(dir)) + __pte_offset(address)) |
258 | #define pte_offset_map(dir, address) \ | 258 | #define pte_offset_map(dir, address) \ |
259 | ((pte_t *)page_address(pmd_page(*(dir))) + __pte_offset(address)) | 259 | ((pte_t *)page_address(pmd_page(*(dir))) + __pte_offset(address)) |
260 | #define pte_offset_map_nested(dir, address) \ | ||
261 | ((pte_t *)page_address(pmd_page(*(dir))) + __pte_offset(address)) | ||
262 | #define pte_unmap(pte) ((void)(pte)) | 260 | #define pte_unmap(pte) ((void)(pte)) |
263 | #define pte_unmap_nested(pte) ((void)(pte)) | ||
264 | 261 | ||
265 | /* | 262 | /* |
266 | * Initialize a new pgd / pmd table with invalid pointers. | 263 | * Initialize a new pgd / pmd table with invalid pointers. |
diff --git a/arch/mips/mm/highmem.c b/arch/mips/mm/highmem.c index 6a2b1bf9ef11..1e69b1fb4b85 100644 --- a/arch/mips/mm/highmem.c +++ b/arch/mips/mm/highmem.c | |||
@@ -9,7 +9,7 @@ static pte_t *kmap_pte; | |||
9 | 9 | ||
10 | unsigned long highstart_pfn, highend_pfn; | 10 | unsigned long highstart_pfn, highend_pfn; |
11 | 11 | ||
12 | void *__kmap(struct page *page) | 12 | void *kmap(struct page *page) |
13 | { | 13 | { |
14 | void *addr; | 14 | void *addr; |
15 | 15 | ||
@@ -21,16 +21,16 @@ void *__kmap(struct page *page) | |||
21 | 21 | ||
22 | return addr; | 22 | return addr; |
23 | } | 23 | } |
24 | EXPORT_SYMBOL(__kmap); | 24 | EXPORT_SYMBOL(kmap); |
25 | 25 | ||
26 | void __kunmap(struct page *page) | 26 | void kunmap(struct page *page) |
27 | { | 27 | { |
28 | BUG_ON(in_interrupt()); | 28 | BUG_ON(in_interrupt()); |
29 | if (!PageHighMem(page)) | 29 | if (!PageHighMem(page)) |
30 | return; | 30 | return; |
31 | kunmap_high(page); | 31 | kunmap_high(page); |
32 | } | 32 | } |
33 | EXPORT_SYMBOL(__kunmap); | 33 | EXPORT_SYMBOL(kunmap); |
34 | 34 | ||
35 | /* | 35 | /* |
36 | * kmap_atomic/kunmap_atomic is significantly faster than kmap/kunmap because | 36 | * kmap_atomic/kunmap_atomic is significantly faster than kmap/kunmap because |
@@ -41,17 +41,17 @@ EXPORT_SYMBOL(__kunmap); | |||
41 | * kmaps are appropriate for short, tight code paths only. | 41 | * kmaps are appropriate for short, tight code paths only. |
42 | */ | 42 | */ |
43 | 43 | ||
44 | void *__kmap_atomic(struct page *page, enum km_type type) | 44 | void *__kmap_atomic(struct page *page) |
45 | { | 45 | { |
46 | enum fixed_addresses idx; | ||
47 | unsigned long vaddr; | 46 | unsigned long vaddr; |
47 | int idx, type; | ||
48 | 48 | ||
49 | /* even !CONFIG_PREEMPT needs this, for in_atomic in do_page_fault */ | 49 | /* even !CONFIG_PREEMPT needs this, for in_atomic in do_page_fault */ |
50 | pagefault_disable(); | 50 | pagefault_disable(); |
51 | if (!PageHighMem(page)) | 51 | if (!PageHighMem(page)) |
52 | return page_address(page); | 52 | return page_address(page); |
53 | 53 | ||
54 | debug_kmap_atomic(type); | 54 | type = kmap_atomic_idx_push(); |
55 | idx = type + KM_TYPE_NR*smp_processor_id(); | 55 | idx = type + KM_TYPE_NR*smp_processor_id(); |
56 | vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); | 56 | vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); |
57 | #ifdef CONFIG_DEBUG_HIGHMEM | 57 | #ifdef CONFIG_DEBUG_HIGHMEM |
@@ -64,43 +64,47 @@ void *__kmap_atomic(struct page *page, enum km_type type) | |||
64 | } | 64 | } |
65 | EXPORT_SYMBOL(__kmap_atomic); | 65 | EXPORT_SYMBOL(__kmap_atomic); |
66 | 66 | ||
67 | void __kunmap_atomic_notypecheck(void *kvaddr, enum km_type type) | 67 | void __kunmap_atomic(void *kvaddr) |
68 | { | 68 | { |
69 | #ifdef CONFIG_DEBUG_HIGHMEM | ||
70 | unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK; | 69 | unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK; |
71 | enum fixed_addresses idx = type + KM_TYPE_NR*smp_processor_id(); | 70 | int type; |
72 | 71 | ||
73 | if (vaddr < FIXADDR_START) { // FIXME | 72 | if (vaddr < FIXADDR_START) { // FIXME |
74 | pagefault_enable(); | 73 | pagefault_enable(); |
75 | return; | 74 | return; |
76 | } | 75 | } |
77 | 76 | ||
78 | BUG_ON(vaddr != __fix_to_virt(FIX_KMAP_BEGIN + idx)); | 77 | type = kmap_atomic_idx_pop(); |
78 | #ifdef CONFIG_DEBUG_HIGHMEM | ||
79 | { | ||
80 | int idx = type + KM_TYPE_NR * smp_processor_id(); | ||
79 | 81 | ||
80 | /* | 82 | BUG_ON(vaddr != __fix_to_virt(FIX_KMAP_BEGIN + idx)); |
81 | * force other mappings to Oops if they'll try to access | ||
82 | * this pte without first remap it | ||
83 | */ | ||
84 | pte_clear(&init_mm, vaddr, kmap_pte-idx); | ||
85 | local_flush_tlb_one(vaddr); | ||
86 | #endif | ||
87 | 83 | ||
84 | /* | ||
85 | * force other mappings to Oops if they'll try to access | ||
86 | * this pte without first remap it | ||
87 | */ | ||
88 | pte_clear(&init_mm, vaddr, kmap_pte-idx); | ||
89 | local_flush_tlb_one(vaddr); | ||
90 | } | ||
91 | #endif | ||
88 | pagefault_enable(); | 92 | pagefault_enable(); |
89 | } | 93 | } |
90 | EXPORT_SYMBOL(__kunmap_atomic_notypecheck); | 94 | EXPORT_SYMBOL(__kunmap_atomic); |
91 | 95 | ||
92 | /* | 96 | /* |
93 | * This is the same as kmap_atomic() but can map memory that doesn't | 97 | * This is the same as kmap_atomic() but can map memory that doesn't |
94 | * have a struct page associated with it. | 98 | * have a struct page associated with it. |
95 | */ | 99 | */ |
96 | void *kmap_atomic_pfn(unsigned long pfn, enum km_type type) | 100 | void *kmap_atomic_pfn(unsigned long pfn) |
97 | { | 101 | { |
98 | enum fixed_addresses idx; | ||
99 | unsigned long vaddr; | 102 | unsigned long vaddr; |
103 | int idx, type; | ||
100 | 104 | ||
101 | pagefault_disable(); | 105 | pagefault_disable(); |
102 | 106 | ||
103 | debug_kmap_atomic(type); | 107 | type = kmap_atomic_idx_push(); |
104 | idx = type + KM_TYPE_NR*smp_processor_id(); | 108 | idx = type + KM_TYPE_NR*smp_processor_id(); |
105 | vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); | 109 | vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); |
106 | set_pte(kmap_pte-idx, pfn_pte(pfn, PAGE_KERNEL)); | 110 | set_pte(kmap_pte-idx, pfn_pte(pfn, PAGE_KERNEL)); |
@@ -109,7 +113,7 @@ void *kmap_atomic_pfn(unsigned long pfn, enum km_type type) | |||
109 | return (void*) vaddr; | 113 | return (void*) vaddr; |
110 | } | 114 | } |
111 | 115 | ||
112 | struct page *__kmap_atomic_to_page(void *ptr) | 116 | struct page *kmap_atomic_to_page(void *ptr) |
113 | { | 117 | { |
114 | unsigned long idx, vaddr = (unsigned long)ptr; | 118 | unsigned long idx, vaddr = (unsigned long)ptr; |
115 | pte_t *pte; | 119 | pte_t *pte; |
diff --git a/arch/mn10300/include/asm/highmem.h b/arch/mn10300/include/asm/highmem.h index b0b187a29b88..f577ba2268ca 100644 --- a/arch/mn10300/include/asm/highmem.h +++ b/arch/mn10300/include/asm/highmem.h | |||
@@ -70,15 +70,16 @@ static inline void kunmap(struct page *page) | |||
70 | * be used in IRQ contexts, so in some (very limited) cases we need | 70 | * be used in IRQ contexts, so in some (very limited) cases we need |
71 | * it. | 71 | * it. |
72 | */ | 72 | */ |
73 | static inline unsigned long kmap_atomic(struct page *page, enum km_type type) | 73 | static inline unsigned long __kmap_atomic(struct page *page) |
74 | { | 74 | { |
75 | enum fixed_addresses idx; | ||
76 | unsigned long vaddr; | 75 | unsigned long vaddr; |
76 | int idx, type; | ||
77 | 77 | ||
78 | pagefault_disable(); | ||
78 | if (page < highmem_start_page) | 79 | if (page < highmem_start_page) |
79 | return page_address(page); | 80 | return page_address(page); |
80 | 81 | ||
81 | debug_kmap_atomic(type); | 82 | type = kmap_atomic_idx_push(); |
82 | idx = type + KM_TYPE_NR * smp_processor_id(); | 83 | idx = type + KM_TYPE_NR * smp_processor_id(); |
83 | vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); | 84 | vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); |
84 | #if HIGHMEM_DEBUG | 85 | #if HIGHMEM_DEBUG |
@@ -91,26 +92,35 @@ static inline unsigned long kmap_atomic(struct page *page, enum km_type type) | |||
91 | return vaddr; | 92 | return vaddr; |
92 | } | 93 | } |
93 | 94 | ||
94 | static inline void kunmap_atomic_notypecheck(unsigned long vaddr, enum km_type type) | 95 | static inline void __kunmap_atomic(unsigned long vaddr) |
95 | { | 96 | { |
96 | #if HIGHMEM_DEBUG | 97 | int type; |
97 | enum fixed_addresses idx = type + KM_TYPE_NR * smp_processor_id(); | ||
98 | 98 | ||
99 | if (vaddr < FIXADDR_START) /* FIXME */ | 99 | if (vaddr < FIXADDR_START) { /* FIXME */ |
100 | pagefault_enable(); | ||
100 | return; | 101 | return; |
102 | } | ||
101 | 103 | ||
102 | if (vaddr != __fix_to_virt(FIX_KMAP_BEGIN + idx)) | 104 | type = kmap_atomic_idx_pop(); |
103 | BUG(); | ||
104 | 105 | ||
105 | /* | 106 | #if HIGHMEM_DEBUG |
106 | * force other mappings to Oops if they'll try to access | 107 | { |
107 | * this pte without first remap it | 108 | unsigned int idx; |
108 | */ | 109 | idx = type + KM_TYPE_NR * smp_processor_id(); |
109 | pte_clear(kmap_pte - idx); | 110 | |
110 | __flush_tlb_one(vaddr); | 111 | if (vaddr != __fix_to_virt(FIX_KMAP_BEGIN + idx)) |
112 | BUG(); | ||
113 | |||
114 | /* | ||
115 | * force other mappings to Oops if they'll try to access | ||
116 | * this pte without first remap it | ||
117 | */ | ||
118 | pte_clear(kmap_pte - idx); | ||
119 | __flush_tlb_one(vaddr); | ||
120 | } | ||
111 | #endif | 121 | #endif |
122 | pagefault_enable(); | ||
112 | } | 123 | } |
113 | |||
114 | #endif /* __KERNEL__ */ | 124 | #endif /* __KERNEL__ */ |
115 | 125 | ||
116 | #endif /* _ASM_HIGHMEM_H */ | 126 | #endif /* _ASM_HIGHMEM_H */ |
diff --git a/arch/mn10300/include/asm/pgtable.h b/arch/mn10300/include/asm/pgtable.h index 16d88577f3e0..b049a8bd1577 100644 --- a/arch/mn10300/include/asm/pgtable.h +++ b/arch/mn10300/include/asm/pgtable.h | |||
@@ -457,9 +457,7 @@ static inline int set_kernel_exec(unsigned long vaddr, int enable) | |||
457 | 457 | ||
458 | #define pte_offset_map(dir, address) \ | 458 | #define pte_offset_map(dir, address) \ |
459 | ((pte_t *) page_address(pmd_page(*(dir))) + pte_index(address)) | 459 | ((pte_t *) page_address(pmd_page(*(dir))) + pte_index(address)) |
460 | #define pte_offset_map_nested(dir, address) pte_offset_map(dir, address) | ||
461 | #define pte_unmap(pte) do {} while (0) | 460 | #define pte_unmap(pte) do {} while (0) |
462 | #define pte_unmap_nested(pte) do {} while (0) | ||
463 | 461 | ||
464 | /* | 462 | /* |
465 | * The MN10300 has external MMU info in the form of a TLB: this is adapted from | 463 | * The MN10300 has external MMU info in the form of a TLB: this is adapted from |
diff --git a/arch/parisc/include/asm/pgtable.h b/arch/parisc/include/asm/pgtable.h index 01c15035e783..865f37a8a881 100644 --- a/arch/parisc/include/asm/pgtable.h +++ b/arch/parisc/include/asm/pgtable.h | |||
@@ -397,9 +397,7 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) | |||
397 | #define pte_offset_kernel(pmd, address) \ | 397 | #define pte_offset_kernel(pmd, address) \ |
398 | ((pte_t *) pmd_page_vaddr(*(pmd)) + pte_index(address)) | 398 | ((pte_t *) pmd_page_vaddr(*(pmd)) + pte_index(address)) |
399 | #define pte_offset_map(pmd, address) pte_offset_kernel(pmd, address) | 399 | #define pte_offset_map(pmd, address) pte_offset_kernel(pmd, address) |
400 | #define pte_offset_map_nested(pmd, address) pte_offset_kernel(pmd, address) | ||
401 | #define pte_unmap(pte) do { } while (0) | 400 | #define pte_unmap(pte) do { } while (0) |
402 | #define pte_unmap_nested(pte) do { } while (0) | ||
403 | 401 | ||
404 | #define pte_unmap(pte) do { } while (0) | 402 | #define pte_unmap(pte) do { } while (0) |
405 | #define pte_unmap_nested(pte) do { } while (0) | 403 | #define pte_unmap_nested(pte) do { } while (0) |
diff --git a/arch/powerpc/include/asm/highmem.h b/arch/powerpc/include/asm/highmem.h index d10d64a4be38..dbc264010d0b 100644 --- a/arch/powerpc/include/asm/highmem.h +++ b/arch/powerpc/include/asm/highmem.h | |||
@@ -60,9 +60,8 @@ extern pte_t *pkmap_page_table; | |||
60 | 60 | ||
61 | extern void *kmap_high(struct page *page); | 61 | extern void *kmap_high(struct page *page); |
62 | extern void kunmap_high(struct page *page); | 62 | extern void kunmap_high(struct page *page); |
63 | extern void *kmap_atomic_prot(struct page *page, enum km_type type, | 63 | extern void *kmap_atomic_prot(struct page *page, pgprot_t prot); |
64 | pgprot_t prot); | 64 | extern void __kunmap_atomic(void *kvaddr); |
65 | extern void kunmap_atomic_notypecheck(void *kvaddr, enum km_type type); | ||
66 | 65 | ||
67 | static inline void *kmap(struct page *page) | 66 | static inline void *kmap(struct page *page) |
68 | { | 67 | { |
@@ -80,9 +79,9 @@ static inline void kunmap(struct page *page) | |||
80 | kunmap_high(page); | 79 | kunmap_high(page); |
81 | } | 80 | } |
82 | 81 | ||
83 | static inline void *kmap_atomic(struct page *page, enum km_type type) | 82 | static inline void *__kmap_atomic(struct page *page) |
84 | { | 83 | { |
85 | return kmap_atomic_prot(page, type, kmap_prot); | 84 | return kmap_atomic_prot(page, kmap_prot); |
86 | } | 85 | } |
87 | 86 | ||
88 | static inline struct page *kmap_atomic_to_page(void *ptr) | 87 | static inline struct page *kmap_atomic_to_page(void *ptr) |
diff --git a/arch/powerpc/include/asm/pgtable-ppc32.h b/arch/powerpc/include/asm/pgtable-ppc32.h index a7db96f2b5c3..47edde8c3556 100644 --- a/arch/powerpc/include/asm/pgtable-ppc32.h +++ b/arch/powerpc/include/asm/pgtable-ppc32.h | |||
@@ -308,12 +308,8 @@ static inline void __ptep_set_access_flags(pte_t *ptep, pte_t entry) | |||
308 | #define pte_offset_kernel(dir, addr) \ | 308 | #define pte_offset_kernel(dir, addr) \ |
309 | ((pte_t *) pmd_page_vaddr(*(dir)) + pte_index(addr)) | 309 | ((pte_t *) pmd_page_vaddr(*(dir)) + pte_index(addr)) |
310 | #define pte_offset_map(dir, addr) \ | 310 | #define pte_offset_map(dir, addr) \ |
311 | ((pte_t *) kmap_atomic(pmd_page(*(dir)), KM_PTE0) + pte_index(addr)) | 311 | ((pte_t *) kmap_atomic(pmd_page(*(dir))) + pte_index(addr)) |
312 | #define pte_offset_map_nested(dir, addr) \ | 312 | #define pte_unmap(pte) kunmap_atomic(pte) |
313 | ((pte_t *) kmap_atomic(pmd_page(*(dir)), KM_PTE1) + pte_index(addr)) | ||
314 | |||
315 | #define pte_unmap(pte) kunmap_atomic(pte, KM_PTE0) | ||
316 | #define pte_unmap_nested(pte) kunmap_atomic(pte, KM_PTE1) | ||
317 | 313 | ||
318 | /* | 314 | /* |
319 | * Encode and decode a swap entry. | 315 | * Encode and decode a swap entry. |
diff --git a/arch/powerpc/include/asm/pgtable-ppc64.h b/arch/powerpc/include/asm/pgtable-ppc64.h index 49865045d56f..2b09cd522d33 100644 --- a/arch/powerpc/include/asm/pgtable-ppc64.h +++ b/arch/powerpc/include/asm/pgtable-ppc64.h | |||
@@ -193,9 +193,7 @@ | |||
193 | (((pte_t *) pmd_page_vaddr(*(dir))) + (((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))) | 193 | (((pte_t *) pmd_page_vaddr(*(dir))) + (((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))) |
194 | 194 | ||
195 | #define pte_offset_map(dir,addr) pte_offset_kernel((dir), (addr)) | 195 | #define pte_offset_map(dir,addr) pte_offset_kernel((dir), (addr)) |
196 | #define pte_offset_map_nested(dir,addr) pte_offset_kernel((dir), (addr)) | ||
197 | #define pte_unmap(pte) do { } while(0) | 196 | #define pte_unmap(pte) do { } while(0) |
198 | #define pte_unmap_nested(pte) do { } while(0) | ||
199 | 197 | ||
200 | /* to find an entry in a kernel page-table-directory */ | 198 | /* to find an entry in a kernel page-table-directory */ |
201 | /* This now only contains the vmalloc pages */ | 199 | /* This now only contains the vmalloc pages */ |
diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c index d692989a4318..441d2a722f06 100644 --- a/arch/powerpc/kernel/vio.c +++ b/arch/powerpc/kernel/vio.c | |||
@@ -238,9 +238,7 @@ static inline void vio_cmo_dealloc(struct vio_dev *viodev, size_t size) | |||
238 | * memory in this pool does not change. | 238 | * memory in this pool does not change. |
239 | */ | 239 | */ |
240 | if (spare_needed && reserve_freed) { | 240 | if (spare_needed && reserve_freed) { |
241 | tmp = min(spare_needed, min(reserve_freed, | 241 | tmp = min3(spare_needed, reserve_freed, (viodev->cmo.entitled - VIO_CMO_MIN_ENT)); |
242 | (viodev->cmo.entitled - | ||
243 | VIO_CMO_MIN_ENT))); | ||
244 | 242 | ||
245 | vio_cmo.spare += tmp; | 243 | vio_cmo.spare += tmp; |
246 | viodev->cmo.entitled -= tmp; | 244 | viodev->cmo.entitled -= tmp; |
diff --git a/arch/powerpc/mm/highmem.c b/arch/powerpc/mm/highmem.c index 857d4173f9c6..b0848b462bbc 100644 --- a/arch/powerpc/mm/highmem.c +++ b/arch/powerpc/mm/highmem.c | |||
@@ -29,17 +29,17 @@ | |||
29 | * be used in IRQ contexts, so in some (very limited) cases we need | 29 | * be used in IRQ contexts, so in some (very limited) cases we need |
30 | * it. | 30 | * it. |
31 | */ | 31 | */ |
32 | void *kmap_atomic_prot(struct page *page, enum km_type type, pgprot_t prot) | 32 | void *kmap_atomic_prot(struct page *page, pgprot_t prot) |
33 | { | 33 | { |
34 | unsigned int idx; | ||
35 | unsigned long vaddr; | 34 | unsigned long vaddr; |
35 | int idx, type; | ||
36 | 36 | ||
37 | /* even !CONFIG_PREEMPT needs this, for in_atomic in do_page_fault */ | 37 | /* even !CONFIG_PREEMPT needs this, for in_atomic in do_page_fault */ |
38 | pagefault_disable(); | 38 | pagefault_disable(); |
39 | if (!PageHighMem(page)) | 39 | if (!PageHighMem(page)) |
40 | return page_address(page); | 40 | return page_address(page); |
41 | 41 | ||
42 | debug_kmap_atomic(type); | 42 | type = kmap_atomic_idx_push(); |
43 | idx = type + KM_TYPE_NR*smp_processor_id(); | 43 | idx = type + KM_TYPE_NR*smp_processor_id(); |
44 | vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); | 44 | vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); |
45 | #ifdef CONFIG_DEBUG_HIGHMEM | 45 | #ifdef CONFIG_DEBUG_HIGHMEM |
@@ -52,26 +52,33 @@ void *kmap_atomic_prot(struct page *page, enum km_type type, pgprot_t prot) | |||
52 | } | 52 | } |
53 | EXPORT_SYMBOL(kmap_atomic_prot); | 53 | EXPORT_SYMBOL(kmap_atomic_prot); |
54 | 54 | ||
55 | void kunmap_atomic_notypecheck(void *kvaddr, enum km_type type) | 55 | void __kunmap_atomic(void *kvaddr) |
56 | { | 56 | { |
57 | #ifdef CONFIG_DEBUG_HIGHMEM | ||
58 | unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK; | 57 | unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK; |
59 | enum fixed_addresses idx = type + KM_TYPE_NR*smp_processor_id(); | 58 | int type; |
60 | 59 | ||
61 | if (vaddr < __fix_to_virt(FIX_KMAP_END)) { | 60 | if (vaddr < __fix_to_virt(FIX_KMAP_END)) { |
62 | pagefault_enable(); | 61 | pagefault_enable(); |
63 | return; | 62 | return; |
64 | } | 63 | } |
65 | 64 | ||
66 | BUG_ON(vaddr != __fix_to_virt(FIX_KMAP_BEGIN + idx)); | 65 | type = kmap_atomic_idx_pop(); |
67 | 66 | ||
68 | /* | 67 | #ifdef CONFIG_DEBUG_HIGHMEM |
69 | * force other mappings to Oops if they'll try to access | 68 | { |
70 | * this pte without first remap it | 69 | unsigned int idx; |
71 | */ | 70 | |
72 | pte_clear(&init_mm, vaddr, kmap_pte-idx); | 71 | idx = type + KM_TYPE_NR * smp_processor_id(); |
73 | local_flush_tlb_page(NULL, vaddr); | 72 | BUG_ON(vaddr != __fix_to_virt(FIX_KMAP_BEGIN + idx)); |
73 | |||
74 | /* | ||
75 | * force other mappings to Oops if they'll try to access | ||
76 | * this pte without first remap it | ||
77 | */ | ||
78 | pte_clear(&init_mm, vaddr, kmap_pte-idx); | ||
79 | local_flush_tlb_page(NULL, vaddr); | ||
80 | } | ||
74 | #endif | 81 | #endif |
75 | pagefault_enable(); | 82 | pagefault_enable(); |
76 | } | 83 | } |
77 | EXPORT_SYMBOL(kunmap_atomic_notypecheck); | 84 | EXPORT_SYMBOL(__kunmap_atomic); |
diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgtable.h index 986dc9476c21..02ace3491c51 100644 --- a/arch/s390/include/asm/pgtable.h +++ b/arch/s390/include/asm/pgtable.h | |||
@@ -1094,9 +1094,7 @@ static inline pmd_t *pmd_offset(pud_t *pud, unsigned long address) | |||
1094 | #define pte_offset(pmd, addr) ((pte_t *) pmd_deref(*(pmd)) + pte_index(addr)) | 1094 | #define pte_offset(pmd, addr) ((pte_t *) pmd_deref(*(pmd)) + pte_index(addr)) |
1095 | #define pte_offset_kernel(pmd, address) pte_offset(pmd,address) | 1095 | #define pte_offset_kernel(pmd, address) pte_offset(pmd,address) |
1096 | #define pte_offset_map(pmd, address) pte_offset_kernel(pmd, address) | 1096 | #define pte_offset_map(pmd, address) pte_offset_kernel(pmd, address) |
1097 | #define pte_offset_map_nested(pmd, address) pte_offset_kernel(pmd, address) | ||
1098 | #define pte_unmap(pte) do { } while (0) | 1097 | #define pte_unmap(pte) do { } while (0) |
1099 | #define pte_unmap_nested(pte) do { } while (0) | ||
1100 | 1098 | ||
1101 | /* | 1099 | /* |
1102 | * 31 bit swap entry format: | 1100 | * 31 bit swap entry format: |
diff --git a/arch/score/include/asm/pgtable.h b/arch/score/include/asm/pgtable.h index ccf38f06c57d..2fd469807683 100644 --- a/arch/score/include/asm/pgtable.h +++ b/arch/score/include/asm/pgtable.h | |||
@@ -88,10 +88,7 @@ static inline void pmd_clear(pmd_t *pmdp) | |||
88 | 88 | ||
89 | #define pte_offset_map(dir, address) \ | 89 | #define pte_offset_map(dir, address) \ |
90 | ((pte_t *)page_address(pmd_page(*(dir))) + __pte_offset(address)) | 90 | ((pte_t *)page_address(pmd_page(*(dir))) + __pte_offset(address)) |
91 | #define pte_offset_map_nested(dir, address) \ | ||
92 | ((pte_t *)page_address(pmd_page(*(dir))) + __pte_offset(address)) | ||
93 | #define pte_unmap(pte) ((void)(pte)) | 91 | #define pte_unmap(pte) ((void)(pte)) |
94 | #define pte_unmap_nested(pte) ((void)(pte)) | ||
95 | 92 | ||
96 | /* | 93 | /* |
97 | * Bits 9(_PAGE_PRESENT) and 10(_PAGE_FILE)are taken, | 94 | * Bits 9(_PAGE_PRESENT) and 10(_PAGE_FILE)are taken, |
diff --git a/arch/sh/include/asm/pgtable_32.h b/arch/sh/include/asm/pgtable_32.h index e172d696e52b..69fdfbf14ea5 100644 --- a/arch/sh/include/asm/pgtable_32.h +++ b/arch/sh/include/asm/pgtable_32.h | |||
@@ -429,10 +429,7 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) | |||
429 | #define pte_offset_kernel(dir, address) \ | 429 | #define pte_offset_kernel(dir, address) \ |
430 | ((pte_t *) pmd_page_vaddr(*(dir)) + pte_index(address)) | 430 | ((pte_t *) pmd_page_vaddr(*(dir)) + pte_index(address)) |
431 | #define pte_offset_map(dir, address) pte_offset_kernel(dir, address) | 431 | #define pte_offset_map(dir, address) pte_offset_kernel(dir, address) |
432 | #define pte_offset_map_nested(dir, address) pte_offset_kernel(dir, address) | ||
433 | |||
434 | #define pte_unmap(pte) do { } while (0) | 432 | #define pte_unmap(pte) do { } while (0) |
435 | #define pte_unmap_nested(pte) do { } while (0) | ||
436 | 433 | ||
437 | #ifdef CONFIG_X2TLB | 434 | #ifdef CONFIG_X2TLB |
438 | #define pte_ERROR(e) \ | 435 | #define pte_ERROR(e) \ |
diff --git a/arch/sh/include/asm/pgtable_64.h b/arch/sh/include/asm/pgtable_64.h index 0ee46776dad6..10a48111226d 100644 --- a/arch/sh/include/asm/pgtable_64.h +++ b/arch/sh/include/asm/pgtable_64.h | |||
@@ -84,9 +84,7 @@ static __inline__ void set_pte(pte_t *pteptr, pte_t pteval) | |||
84 | ((pte_t *) ((pmd_val(*(dir))) & PAGE_MASK) + pte_index((addr))) | 84 | ((pte_t *) ((pmd_val(*(dir))) & PAGE_MASK) + pte_index((addr))) |
85 | 85 | ||
86 | #define pte_offset_map(dir,addr) pte_offset_kernel(dir, addr) | 86 | #define pte_offset_map(dir,addr) pte_offset_kernel(dir, addr) |
87 | #define pte_offset_map_nested(dir,addr) pte_offset_kernel(dir, addr) | ||
88 | #define pte_unmap(pte) do { } while (0) | 87 | #define pte_unmap(pte) do { } while (0) |
89 | #define pte_unmap_nested(pte) do { } while (0) | ||
90 | 88 | ||
91 | #ifndef __ASSEMBLY__ | 89 | #ifndef __ASSEMBLY__ |
92 | #define IOBASE_VADDR 0xff000000 | 90 | #define IOBASE_VADDR 0xff000000 |
diff --git a/arch/sparc/include/asm/highmem.h b/arch/sparc/include/asm/highmem.h index ec23b0a87b98..3d7afbb7f4bb 100644 --- a/arch/sparc/include/asm/highmem.h +++ b/arch/sparc/include/asm/highmem.h | |||
@@ -70,8 +70,8 @@ static inline void kunmap(struct page *page) | |||
70 | kunmap_high(page); | 70 | kunmap_high(page); |
71 | } | 71 | } |
72 | 72 | ||
73 | extern void *kmap_atomic(struct page *page, enum km_type type); | 73 | extern void *__kmap_atomic(struct page *page); |
74 | extern void kunmap_atomic_notypecheck(void *kvaddr, enum km_type type); | 74 | extern void __kunmap_atomic(void *kvaddr); |
75 | extern struct page *kmap_atomic_to_page(void *vaddr); | 75 | extern struct page *kmap_atomic_to_page(void *vaddr); |
76 | 76 | ||
77 | #define flush_cache_kmaps() flush_cache_all() | 77 | #define flush_cache_kmaps() flush_cache_all() |
diff --git a/arch/sparc/include/asm/pgtable_32.h b/arch/sparc/include/asm/pgtable_32.h index 0ece77f47753..303bd4dc8292 100644 --- a/arch/sparc/include/asm/pgtable_32.h +++ b/arch/sparc/include/asm/pgtable_32.h | |||
@@ -304,10 +304,7 @@ BTFIXUPDEF_CALL(pte_t *, pte_offset_kernel, pmd_t *, unsigned long) | |||
304 | * and sun4c is guaranteed to have no highmem anyway. | 304 | * and sun4c is guaranteed to have no highmem anyway. |
305 | */ | 305 | */ |
306 | #define pte_offset_map(d, a) pte_offset_kernel(d,a) | 306 | #define pte_offset_map(d, a) pte_offset_kernel(d,a) |
307 | #define pte_offset_map_nested(d, a) pte_offset_kernel(d,a) | ||
308 | |||
309 | #define pte_unmap(pte) do{}while(0) | 307 | #define pte_unmap(pte) do{}while(0) |
310 | #define pte_unmap_nested(pte) do{}while(0) | ||
311 | 308 | ||
312 | /* Certain architectures need to do special things when pte's | 309 | /* Certain architectures need to do special things when pte's |
313 | * within a page table are directly modified. Thus, the following | 310 | * within a page table are directly modified. Thus, the following |
diff --git a/arch/sparc/include/asm/pgtable_64.h b/arch/sparc/include/asm/pgtable_64.h index f5b5fa76c02d..f8dddb7045bb 100644 --- a/arch/sparc/include/asm/pgtable_64.h +++ b/arch/sparc/include/asm/pgtable_64.h | |||
@@ -652,9 +652,7 @@ static inline int pte_special(pte_t pte) | |||
652 | ((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))) | 652 | ((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))) |
653 | #define pte_offset_kernel pte_index | 653 | #define pte_offset_kernel pte_index |
654 | #define pte_offset_map pte_index | 654 | #define pte_offset_map pte_index |
655 | #define pte_offset_map_nested pte_index | ||
656 | #define pte_unmap(pte) do { } while (0) | 655 | #define pte_unmap(pte) do { } while (0) |
657 | #define pte_unmap_nested(pte) do { } while (0) | ||
658 | 656 | ||
659 | /* Actual page table PTE updates. */ | 657 | /* Actual page table PTE updates. */ |
660 | extern void tlb_batch_add(struct mm_struct *mm, unsigned long vaddr, pte_t *ptep, pte_t orig); | 658 | extern void tlb_batch_add(struct mm_struct *mm, unsigned long vaddr, pte_t *ptep, pte_t orig); |
diff --git a/arch/sparc/mm/highmem.c b/arch/sparc/mm/highmem.c index e139e9cbf5f7..5e50c09b7dce 100644 --- a/arch/sparc/mm/highmem.c +++ b/arch/sparc/mm/highmem.c | |||
@@ -29,17 +29,17 @@ | |||
29 | #include <asm/tlbflush.h> | 29 | #include <asm/tlbflush.h> |
30 | #include <asm/fixmap.h> | 30 | #include <asm/fixmap.h> |
31 | 31 | ||
32 | void *kmap_atomic(struct page *page, enum km_type type) | 32 | void *__kmap_atomic(struct page *page) |
33 | { | 33 | { |
34 | unsigned long idx; | ||
35 | unsigned long vaddr; | 34 | unsigned long vaddr; |
35 | long idx, type; | ||
36 | 36 | ||
37 | /* even !CONFIG_PREEMPT needs this, for in_atomic in do_page_fault */ | 37 | /* even !CONFIG_PREEMPT needs this, for in_atomic in do_page_fault */ |
38 | pagefault_disable(); | 38 | pagefault_disable(); |
39 | if (!PageHighMem(page)) | 39 | if (!PageHighMem(page)) |
40 | return page_address(page); | 40 | return page_address(page); |
41 | 41 | ||
42 | debug_kmap_atomic(type); | 42 | type = kmap_atomic_idx_push(); |
43 | idx = type + KM_TYPE_NR*smp_processor_id(); | 43 | idx = type + KM_TYPE_NR*smp_processor_id(); |
44 | vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); | 44 | vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); |
45 | 45 | ||
@@ -63,44 +63,50 @@ void *kmap_atomic(struct page *page, enum km_type type) | |||
63 | 63 | ||
64 | return (void*) vaddr; | 64 | return (void*) vaddr; |
65 | } | 65 | } |
66 | EXPORT_SYMBOL(kmap_atomic); | 66 | EXPORT_SYMBOL(__kmap_atomic); |
67 | 67 | ||
68 | void kunmap_atomic_notypecheck(void *kvaddr, enum km_type type) | 68 | void __kunmap_atomic(void *kvaddr) |
69 | { | 69 | { |
70 | #ifdef CONFIG_DEBUG_HIGHMEM | ||
71 | unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK; | 70 | unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK; |
72 | unsigned long idx = type + KM_TYPE_NR*smp_processor_id(); | 71 | int type; |
73 | 72 | ||
74 | if (vaddr < FIXADDR_START) { // FIXME | 73 | if (vaddr < FIXADDR_START) { // FIXME |
75 | pagefault_enable(); | 74 | pagefault_enable(); |
76 | return; | 75 | return; |
77 | } | 76 | } |
78 | 77 | ||
79 | BUG_ON(vaddr != __fix_to_virt(FIX_KMAP_BEGIN+idx)); | 78 | type = kmap_atomic_idx_pop(); |
80 | 79 | ||
81 | /* XXX Fix - Anton */ | 80 | #ifdef CONFIG_DEBUG_HIGHMEM |
81 | { | ||
82 | unsigned long idx; | ||
83 | |||
84 | idx = type + KM_TYPE_NR * smp_processor_id(); | ||
85 | BUG_ON(vaddr != __fix_to_virt(FIX_KMAP_BEGIN+idx)); | ||
86 | |||
87 | /* XXX Fix - Anton */ | ||
82 | #if 0 | 88 | #if 0 |
83 | __flush_cache_one(vaddr); | 89 | __flush_cache_one(vaddr); |
84 | #else | 90 | #else |
85 | flush_cache_all(); | 91 | flush_cache_all(); |
86 | #endif | 92 | #endif |
87 | 93 | ||
88 | /* | 94 | /* |
89 | * force other mappings to Oops if they'll try to access | 95 | * force other mappings to Oops if they'll try to access |
90 | * this pte without first remap it | 96 | * this pte without first remap it |
91 | */ | 97 | */ |
92 | pte_clear(&init_mm, vaddr, kmap_pte-idx); | 98 | pte_clear(&init_mm, vaddr, kmap_pte-idx); |
93 | /* XXX Fix - Anton */ | 99 | /* XXX Fix - Anton */ |
94 | #if 0 | 100 | #if 0 |
95 | __flush_tlb_one(vaddr); | 101 | __flush_tlb_one(vaddr); |
96 | #else | 102 | #else |
97 | flush_tlb_all(); | 103 | flush_tlb_all(); |
98 | #endif | 104 | #endif |
105 | } | ||
99 | #endif | 106 | #endif |
100 | |||
101 | pagefault_enable(); | 107 | pagefault_enable(); |
102 | } | 108 | } |
103 | EXPORT_SYMBOL(kunmap_atomic_notypecheck); | 109 | EXPORT_SYMBOL(__kunmap_atomic); |
104 | 110 | ||
105 | /* We may be fed a pagetable here by ptep_to_xxx and others. */ | 111 | /* We may be fed a pagetable here by ptep_to_xxx and others. */ |
106 | struct page *kmap_atomic_to_page(void *ptr) | 112 | struct page *kmap_atomic_to_page(void *ptr) |
diff --git a/arch/tile/include/asm/highmem.h b/arch/tile/include/asm/highmem.h index d155db6fa9bd..e0f7ee186721 100644 --- a/arch/tile/include/asm/highmem.h +++ b/arch/tile/include/asm/highmem.h | |||
@@ -60,12 +60,12 @@ void *kmap_fix_kpte(struct page *page, int finished); | |||
60 | /* This macro is used only in map_new_virtual() to map "page". */ | 60 | /* This macro is used only in map_new_virtual() to map "page". */ |
61 | #define kmap_prot page_to_kpgprot(page) | 61 | #define kmap_prot page_to_kpgprot(page) |
62 | 62 | ||
63 | void kunmap_atomic_notypecheck(void *kvaddr, enum km_type type); | 63 | void *__kmap_atomic(struct page *page); |
64 | void *kmap_atomic_pfn(unsigned long pfn, enum km_type type); | 64 | void __kunmap_atomic(void *kvaddr); |
65 | void *kmap_atomic_prot_pfn(unsigned long pfn, enum km_type type, pgprot_t prot); | 65 | void *kmap_atomic_pfn(unsigned long pfn); |
66 | void *kmap_atomic_prot_pfn(unsigned long pfn, pgprot_t prot); | ||
66 | struct page *kmap_atomic_to_page(void *ptr); | 67 | struct page *kmap_atomic_to_page(void *ptr); |
67 | void *kmap_atomic_prot(struct page *page, enum km_type type, pgprot_t prot); | 68 | void *kmap_atomic_prot(struct page *page, pgprot_t prot); |
68 | void *kmap_atomic(struct page *page, enum km_type type); | ||
69 | void kmap_atomic_fix_kpte(struct page *page, int finished); | 69 | void kmap_atomic_fix_kpte(struct page *page, int finished); |
70 | 70 | ||
71 | #define flush_cache_kmaps() do { } while (0) | 71 | #define flush_cache_kmaps() do { } while (0) |
diff --git a/arch/tile/include/asm/pgtable.h b/arch/tile/include/asm/pgtable.h index b3367379d537..dc4ccdd855bc 100644 --- a/arch/tile/include/asm/pgtable.h +++ b/arch/tile/include/asm/pgtable.h | |||
@@ -347,15 +347,10 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) | |||
347 | extern pte_t *_pte_offset_map(pmd_t *, unsigned long address, enum km_type); | 347 | extern pte_t *_pte_offset_map(pmd_t *, unsigned long address, enum km_type); |
348 | #define pte_offset_map(dir, address) \ | 348 | #define pte_offset_map(dir, address) \ |
349 | _pte_offset_map(dir, address, KM_PTE0) | 349 | _pte_offset_map(dir, address, KM_PTE0) |
350 | #define pte_offset_map_nested(dir, address) \ | ||
351 | _pte_offset_map(dir, address, KM_PTE1) | ||
352 | #define pte_unmap(pte) kunmap_atomic(pte, KM_PTE0) | 350 | #define pte_unmap(pte) kunmap_atomic(pte, KM_PTE0) |
353 | #define pte_unmap_nested(pte) kunmap_atomic(pte, KM_PTE1) | ||
354 | #else | 351 | #else |
355 | #define pte_offset_map(dir, address) pte_offset_kernel(dir, address) | 352 | #define pte_offset_map(dir, address) pte_offset_kernel(dir, address) |
356 | #define pte_offset_map_nested(dir, address) pte_offset_map(dir, address) | ||
357 | #define pte_unmap(pte) do { } while (0) | 353 | #define pte_unmap(pte) do { } while (0) |
358 | #define pte_unmap_nested(pte) do { } while (0) | ||
359 | #endif | 354 | #endif |
360 | 355 | ||
361 | /* Clear a non-executable kernel PTE and flush it from the TLB. */ | 356 | /* Clear a non-executable kernel PTE and flush it from the TLB. */ |
diff --git a/arch/tile/mm/highmem.c b/arch/tile/mm/highmem.c index 12ab137e7d4f..8ef6595e162c 100644 --- a/arch/tile/mm/highmem.c +++ b/arch/tile/mm/highmem.c | |||
@@ -56,50 +56,6 @@ void kunmap(struct page *page) | |||
56 | } | 56 | } |
57 | EXPORT_SYMBOL(kunmap); | 57 | EXPORT_SYMBOL(kunmap); |
58 | 58 | ||
59 | static void debug_kmap_atomic_prot(enum km_type type) | ||
60 | { | ||
61 | #ifdef CONFIG_DEBUG_HIGHMEM | ||
62 | static unsigned warn_count = 10; | ||
63 | |||
64 | if (unlikely(warn_count == 0)) | ||
65 | return; | ||
66 | |||
67 | if (unlikely(in_interrupt())) { | ||
68 | if (in_irq()) { | ||
69 | if (type != KM_IRQ0 && type != KM_IRQ1 && | ||
70 | type != KM_BIO_SRC_IRQ && | ||
71 | /* type != KM_BIO_DST_IRQ && */ | ||
72 | type != KM_BOUNCE_READ) { | ||
73 | WARN_ON(1); | ||
74 | warn_count--; | ||
75 | } | ||
76 | } else if (!irqs_disabled()) { /* softirq */ | ||
77 | if (type != KM_IRQ0 && type != KM_IRQ1 && | ||
78 | type != KM_SOFTIRQ0 && type != KM_SOFTIRQ1 && | ||
79 | type != KM_SKB_SUNRPC_DATA && | ||
80 | type != KM_SKB_DATA_SOFTIRQ && | ||
81 | type != KM_BOUNCE_READ) { | ||
82 | WARN_ON(1); | ||
83 | warn_count--; | ||
84 | } | ||
85 | } | ||
86 | } | ||
87 | |||
88 | if (type == KM_IRQ0 || type == KM_IRQ1 || type == KM_BOUNCE_READ || | ||
89 | type == KM_BIO_SRC_IRQ /* || type == KM_BIO_DST_IRQ */) { | ||
90 | if (!irqs_disabled()) { | ||
91 | WARN_ON(1); | ||
92 | warn_count--; | ||
93 | } | ||
94 | } else if (type == KM_SOFTIRQ0 || type == KM_SOFTIRQ1) { | ||
95 | if (irq_count() == 0 && !irqs_disabled()) { | ||
96 | WARN_ON(1); | ||
97 | warn_count--; | ||
98 | } | ||
99 | } | ||
100 | #endif | ||
101 | } | ||
102 | |||
103 | /* | 59 | /* |
104 | * Describe a single atomic mapping of a page on a given cpu at a | 60 | * Describe a single atomic mapping of a page on a given cpu at a |
105 | * given address, and allow it to be linked into a list. | 61 | * given address, and allow it to be linked into a list. |
@@ -240,10 +196,10 @@ void kmap_atomic_fix_kpte(struct page *page, int finished) | |||
240 | * When holding an atomic kmap is is not legal to sleep, so atomic | 196 | * When holding an atomic kmap is is not legal to sleep, so atomic |
241 | * kmaps are appropriate for short, tight code paths only. | 197 | * kmaps are appropriate for short, tight code paths only. |
242 | */ | 198 | */ |
243 | void *kmap_atomic_prot(struct page *page, enum km_type type, pgprot_t prot) | 199 | void *kmap_atomic_prot(struct page *page, pgprot_t prot) |
244 | { | 200 | { |
245 | enum fixed_addresses idx; | ||
246 | unsigned long vaddr; | 201 | unsigned long vaddr; |
202 | int idx, type; | ||
247 | pte_t *pte; | 203 | pte_t *pte; |
248 | 204 | ||
249 | /* even !CONFIG_PREEMPT needs this, for in_atomic in do_page_fault */ | 205 | /* even !CONFIG_PREEMPT needs this, for in_atomic in do_page_fault */ |
@@ -255,8 +211,7 @@ void *kmap_atomic_prot(struct page *page, enum km_type type, pgprot_t prot) | |||
255 | if (!PageHighMem(page)) | 211 | if (!PageHighMem(page)) |
256 | return page_address(page); | 212 | return page_address(page); |
257 | 213 | ||
258 | debug_kmap_atomic_prot(type); | 214 | type = kmap_atomic_idx_push(); |
259 | |||
260 | idx = type + KM_TYPE_NR*smp_processor_id(); | 215 | idx = type + KM_TYPE_NR*smp_processor_id(); |
261 | vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); | 216 | vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); |
262 | pte = kmap_get_pte(vaddr); | 217 | pte = kmap_get_pte(vaddr); |
@@ -269,25 +224,31 @@ void *kmap_atomic_prot(struct page *page, enum km_type type, pgprot_t prot) | |||
269 | } | 224 | } |
270 | EXPORT_SYMBOL(kmap_atomic_prot); | 225 | EXPORT_SYMBOL(kmap_atomic_prot); |
271 | 226 | ||
272 | void *kmap_atomic(struct page *page, enum km_type type) | 227 | void *__kmap_atomic(struct page *page) |
273 | { | 228 | { |
274 | /* PAGE_NONE is a magic value that tells us to check immutability. */ | 229 | /* PAGE_NONE is a magic value that tells us to check immutability. */ |
275 | return kmap_atomic_prot(page, type, PAGE_NONE); | 230 | return kmap_atomic_prot(page, type, PAGE_NONE); |
276 | } | 231 | } |
277 | EXPORT_SYMBOL(kmap_atomic); | 232 | EXPORT_SYMBOL(__kmap_atomic); |
278 | 233 | ||
279 | void kunmap_atomic_notypecheck(void *kvaddr, enum km_type type) | 234 | void __kunmap_atomic(void *kvaddr) |
280 | { | 235 | { |
281 | unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK; | 236 | unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK; |
282 | enum fixed_addresses idx = type + KM_TYPE_NR*smp_processor_id(); | ||
283 | 237 | ||
284 | /* | 238 | if (vaddr >= __fix_to_virt(FIX_KMAP_END) && |
285 | * Force other mappings to Oops if they try to access this pte without | 239 | vaddr <= __fix_to_virt(FIX_KMAP_BEGIN)) { |
286 | * first remapping it. Keeping stale mappings around is a bad idea. | ||
287 | */ | ||
288 | if (vaddr == __fix_to_virt(FIX_KMAP_BEGIN+idx)) { | ||
289 | pte_t *pte = kmap_get_pte(vaddr); | 240 | pte_t *pte = kmap_get_pte(vaddr); |
290 | pte_t pteval = *pte; | 241 | pte_t pteval = *pte; |
242 | int idx, type; | ||
243 | |||
244 | type = kmap_atomic_idx_pop(); | ||
245 | idx = type + KM_TYPE_NR*smp_processor_id(); | ||
246 | |||
247 | /* | ||
248 | * Force other mappings to Oops if they try to access this pte | ||
249 | * without first remapping it. Keeping stale mappings around | ||
250 | * is a bad idea. | ||
251 | */ | ||
291 | BUG_ON(!pte_present(pteval) && !pte_migrating(pteval)); | 252 | BUG_ON(!pte_present(pteval) && !pte_migrating(pteval)); |
292 | kmap_atomic_unregister(pte_page(pteval), vaddr); | 253 | kmap_atomic_unregister(pte_page(pteval), vaddr); |
293 | kpte_clear_flush(pte, vaddr); | 254 | kpte_clear_flush(pte, vaddr); |
@@ -300,19 +261,19 @@ void kunmap_atomic_notypecheck(void *kvaddr, enum km_type type) | |||
300 | arch_flush_lazy_mmu_mode(); | 261 | arch_flush_lazy_mmu_mode(); |
301 | pagefault_enable(); | 262 | pagefault_enable(); |
302 | } | 263 | } |
303 | EXPORT_SYMBOL(kunmap_atomic_notypecheck); | 264 | EXPORT_SYMBOL(__kunmap_atomic); |
304 | 265 | ||
305 | /* | 266 | /* |
306 | * This API is supposed to allow us to map memory without a "struct page". | 267 | * This API is supposed to allow us to map memory without a "struct page". |
307 | * Currently we don't support this, though this may change in the future. | 268 | * Currently we don't support this, though this may change in the future. |
308 | */ | 269 | */ |
309 | void *kmap_atomic_pfn(unsigned long pfn, enum km_type type) | 270 | void *kmap_atomic_pfn(unsigned long pfn) |
310 | { | 271 | { |
311 | return kmap_atomic(pfn_to_page(pfn), type); | 272 | return kmap_atomic(pfn_to_page(pfn)); |
312 | } | 273 | } |
313 | void *kmap_atomic_prot_pfn(unsigned long pfn, enum km_type type, pgprot_t prot) | 274 | void *kmap_atomic_prot_pfn(unsigned long pfn, pgprot_t prot) |
314 | { | 275 | { |
315 | return kmap_atomic_prot(pfn_to_page(pfn), type, prot); | 276 | return kmap_atomic_prot(pfn_to_page(pfn), prot); |
316 | } | 277 | } |
317 | 278 | ||
318 | struct page *kmap_atomic_to_page(void *ptr) | 279 | struct page *kmap_atomic_to_page(void *ptr) |
diff --git a/arch/um/Kconfig.um b/arch/um/Kconfig.um index ec2b8da1aba4..50d6aa20c353 100644 --- a/arch/um/Kconfig.um +++ b/arch/um/Kconfig.um | |||
@@ -120,6 +120,9 @@ config SMP | |||
120 | 120 | ||
121 | If you don't know what to do, say N. | 121 | If you don't know what to do, say N. |
122 | 122 | ||
123 | config GENERIC_HARDIRQS_NO__DO_IRQ | ||
124 | def_bool y | ||
125 | |||
123 | config NR_CPUS | 126 | config NR_CPUS |
124 | int "Maximum number of CPUs (2-32)" | 127 | int "Maximum number of CPUs (2-32)" |
125 | range 2 32 | 128 | range 2 32 |
@@ -147,3 +150,6 @@ config KERNEL_STACK_ORDER | |||
147 | This option determines the size of UML kernel stacks. They will | 150 | This option determines the size of UML kernel stacks. They will |
148 | be 1 << order pages. The default is OK unless you're running Valgrind | 151 | be 1 << order pages. The default is OK unless you're running Valgrind |
149 | on UML, in which case, set this to 3. | 152 | on UML, in which case, set this to 3. |
153 | |||
154 | config NO_DMA | ||
155 | def_bool y | ||
diff --git a/arch/um/defconfig b/arch/um/defconfig index 6bd456f96f90..564f3de65b4a 100644 --- a/arch/um/defconfig +++ b/arch/um/defconfig | |||
@@ -566,7 +566,6 @@ CONFIG_CRC32=m | |||
566 | # CONFIG_CRC7 is not set | 566 | # CONFIG_CRC7 is not set |
567 | # CONFIG_LIBCRC32C is not set | 567 | # CONFIG_LIBCRC32C is not set |
568 | CONFIG_PLIST=y | 568 | CONFIG_PLIST=y |
569 | CONFIG_HAS_DMA=y | ||
570 | 569 | ||
571 | # | 570 | # |
572 | # SCSI device support | 571 | # SCSI device support |
diff --git a/arch/um/include/asm/dma-mapping.h b/arch/um/include/asm/dma-mapping.h deleted file mode 100644 index 1f469e80fdd3..000000000000 --- a/arch/um/include/asm/dma-mapping.h +++ /dev/null | |||
@@ -1,112 +0,0 @@ | |||
1 | #ifndef _ASM_DMA_MAPPING_H | ||
2 | #define _ASM_DMA_MAPPING_H | ||
3 | |||
4 | #include <asm/scatterlist.h> | ||
5 | |||
6 | static inline int | ||
7 | dma_supported(struct device *dev, u64 mask) | ||
8 | { | ||
9 | BUG(); | ||
10 | return(0); | ||
11 | } | ||
12 | |||
13 | static inline int | ||
14 | dma_set_mask(struct device *dev, u64 dma_mask) | ||
15 | { | ||
16 | BUG(); | ||
17 | return(0); | ||
18 | } | ||
19 | |||
20 | static inline void * | ||
21 | dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, | ||
22 | gfp_t flag) | ||
23 | { | ||
24 | BUG(); | ||
25 | return((void *) 0); | ||
26 | } | ||
27 | |||
28 | static inline void | ||
29 | dma_free_coherent(struct device *dev, size_t size, void *cpu_addr, | ||
30 | dma_addr_t dma_handle) | ||
31 | { | ||
32 | BUG(); | ||
33 | } | ||
34 | |||
35 | static inline dma_addr_t | ||
36 | dma_map_single(struct device *dev, void *cpu_addr, size_t size, | ||
37 | enum dma_data_direction direction) | ||
38 | { | ||
39 | BUG(); | ||
40 | return(0); | ||
41 | } | ||
42 | |||
43 | static inline void | ||
44 | dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, | ||
45 | enum dma_data_direction direction) | ||
46 | { | ||
47 | BUG(); | ||
48 | } | ||
49 | |||
50 | static inline dma_addr_t | ||
51 | dma_map_page(struct device *dev, struct page *page, | ||
52 | unsigned long offset, size_t size, | ||
53 | enum dma_data_direction direction) | ||
54 | { | ||
55 | BUG(); | ||
56 | return(0); | ||
57 | } | ||
58 | |||
59 | static inline void | ||
60 | dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size, | ||
61 | enum dma_data_direction direction) | ||
62 | { | ||
63 | BUG(); | ||
64 | } | ||
65 | |||
66 | static inline int | ||
67 | dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, | ||
68 | enum dma_data_direction direction) | ||
69 | { | ||
70 | BUG(); | ||
71 | return(0); | ||
72 | } | ||
73 | |||
74 | static inline void | ||
75 | dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries, | ||
76 | enum dma_data_direction direction) | ||
77 | { | ||
78 | BUG(); | ||
79 | } | ||
80 | |||
81 | static inline void | ||
82 | dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size, | ||
83 | enum dma_data_direction direction) | ||
84 | { | ||
85 | BUG(); | ||
86 | } | ||
87 | |||
88 | static inline void | ||
89 | dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems, | ||
90 | enum dma_data_direction direction) | ||
91 | { | ||
92 | BUG(); | ||
93 | } | ||
94 | |||
95 | #define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f) | ||
96 | #define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h) | ||
97 | |||
98 | static inline void | ||
99 | dma_cache_sync(struct device *dev, void *vaddr, size_t size, | ||
100 | enum dma_data_direction direction) | ||
101 | { | ||
102 | BUG(); | ||
103 | } | ||
104 | |||
105 | static inline int | ||
106 | dma_mapping_error(struct device *dev, dma_addr_t dma_handle) | ||
107 | { | ||
108 | BUG(); | ||
109 | return 0; | ||
110 | } | ||
111 | |||
112 | #endif | ||
diff --git a/arch/um/include/asm/pgtable.h b/arch/um/include/asm/pgtable.h index a9f7251b4a8d..41474fb5eee7 100644 --- a/arch/um/include/asm/pgtable.h +++ b/arch/um/include/asm/pgtable.h | |||
@@ -338,9 +338,7 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) | |||
338 | ((pte_t *) pmd_page_vaddr(*(dir)) + pte_index(address)) | 338 | ((pte_t *) pmd_page_vaddr(*(dir)) + pte_index(address)) |
339 | #define pte_offset_map(dir, address) \ | 339 | #define pte_offset_map(dir, address) \ |
340 | ((pte_t *)page_address(pmd_page(*(dir))) + pte_index(address)) | 340 | ((pte_t *)page_address(pmd_page(*(dir))) + pte_index(address)) |
341 | #define pte_offset_map_nested(dir, address) pte_offset_map(dir, address) | ||
342 | #define pte_unmap(pte) do { } while (0) | 341 | #define pte_unmap(pte) do { } while (0) |
343 | #define pte_unmap_nested(pte) do { } while (0) | ||
344 | 342 | ||
345 | struct mm_struct; | 343 | struct mm_struct; |
346 | extern pte_t *virt_to_pte(struct mm_struct *mm, unsigned long addr); | 344 | extern pte_t *virt_to_pte(struct mm_struct *mm, unsigned long addr); |
diff --git a/arch/um/include/asm/system.h b/arch/um/include/asm/system.h index 93af1cf0907d..68a90ecd1450 100644 --- a/arch/um/include/asm/system.h +++ b/arch/um/include/asm/system.h | |||
@@ -8,23 +8,38 @@ extern int set_signals(int enable); | |||
8 | extern void block_signals(void); | 8 | extern void block_signals(void); |
9 | extern void unblock_signals(void); | 9 | extern void unblock_signals(void); |
10 | 10 | ||
11 | #define local_save_flags(flags) do { typecheck(unsigned long, flags); \ | 11 | static inline unsigned long arch_local_save_flags(void) |
12 | (flags) = get_signals(); } while(0) | 12 | { |
13 | #define local_irq_restore(flags) do { typecheck(unsigned long, flags); \ | 13 | return get_signals(); |
14 | set_signals(flags); } while(0) | 14 | } |
15 | 15 | ||
16 | #define local_irq_save(flags) do { local_save_flags(flags); \ | 16 | static inline void arch_local_irq_restore(unsigned long flags) |
17 | local_irq_disable(); } while(0) | 17 | { |
18 | 18 | set_signals(flags); | |
19 | #define local_irq_enable() unblock_signals() | 19 | } |
20 | #define local_irq_disable() block_signals() | 20 | |
21 | 21 | static inline void arch_local_irq_enable(void) | |
22 | #define irqs_disabled() \ | 22 | { |
23 | ({ \ | 23 | unblock_signals(); |
24 | unsigned long flags; \ | 24 | } |
25 | local_save_flags(flags); \ | 25 | |
26 | (flags == 0); \ | 26 | static inline void arch_local_irq_disable(void) |
27 | }) | 27 | { |
28 | block_signals(); | ||
29 | } | ||
30 | |||
31 | static inline unsigned long arch_local_irq_save(void) | ||
32 | { | ||
33 | unsigned long flags; | ||
34 | flags = arch_local_save_flags(); | ||
35 | arch_local_irq_disable(); | ||
36 | return flags; | ||
37 | } | ||
38 | |||
39 | static inline bool arch_irqs_disabled(void) | ||
40 | { | ||
41 | return arch_local_save_flags() == 0; | ||
42 | } | ||
28 | 43 | ||
29 | extern void *_switch_to(void *prev, void *next, void *last); | 44 | extern void *_switch_to(void *prev, void *next, void *last); |
30 | #define switch_to(prev, next, last) prev = _switch_to(prev, next, last) | 45 | #define switch_to(prev, next, last) prev = _switch_to(prev, next, last) |
diff --git a/arch/um/kernel/dyn.lds.S b/arch/um/kernel/dyn.lds.S index 69268014dd8e..a3cab6d3ae02 100644 --- a/arch/um/kernel/dyn.lds.S +++ b/arch/um/kernel/dyn.lds.S | |||
@@ -50,8 +50,18 @@ SECTIONS | |||
50 | .rela.got : { *(.rela.got) } | 50 | .rela.got : { *(.rela.got) } |
51 | .rel.bss : { *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) } | 51 | .rel.bss : { *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) } |
52 | .rela.bss : { *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) } | 52 | .rela.bss : { *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) } |
53 | .rel.plt : { *(.rel.plt) } | 53 | .rel.plt : { |
54 | .rela.plt : { *(.rela.plt) } | 54 | *(.rel.plt) |
55 | PROVIDE_HIDDEN(__rel_iplt_start = .); | ||
56 | *(.rel.iplt) | ||
57 | PROVIDE_HIDDEN(__rel_iplt_end = .); | ||
58 | } | ||
59 | .rela.plt : { | ||
60 | *(.rela.plt) | ||
61 | PROVIDE_HIDDEN(__rela_iplt_start = .); | ||
62 | *(.rela.iplt) | ||
63 | PROVIDE_HIDDEN(__rela_iplt_end = .); | ||
64 | } | ||
55 | .init : { | 65 | .init : { |
56 | KEEP (*(.init)) | 66 | KEEP (*(.init)) |
57 | } =0x90909090 | 67 | } =0x90909090 |
diff --git a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c index a746e3037a5b..3f0ac9e0c966 100644 --- a/arch/um/kernel/irq.c +++ b/arch/um/kernel/irq.c | |||
@@ -334,7 +334,7 @@ unsigned int do_IRQ(int irq, struct uml_pt_regs *regs) | |||
334 | { | 334 | { |
335 | struct pt_regs *old_regs = set_irq_regs((struct pt_regs *)regs); | 335 | struct pt_regs *old_regs = set_irq_regs((struct pt_regs *)regs); |
336 | irq_enter(); | 336 | irq_enter(); |
337 | __do_IRQ(irq); | 337 | generic_handle_irq(irq); |
338 | irq_exit(); | 338 | irq_exit(); |
339 | set_irq_regs(old_regs); | 339 | set_irq_regs(old_regs); |
340 | return 1; | 340 | return 1; |
@@ -391,17 +391,10 @@ void __init init_IRQ(void) | |||
391 | { | 391 | { |
392 | int i; | 392 | int i; |
393 | 393 | ||
394 | irq_desc[TIMER_IRQ].status = IRQ_DISABLED; | 394 | set_irq_chip_and_handler(TIMER_IRQ, &SIGVTALRM_irq_type, handle_edge_irq); |
395 | irq_desc[TIMER_IRQ].action = NULL; | 395 | |
396 | irq_desc[TIMER_IRQ].depth = 1; | ||
397 | irq_desc[TIMER_IRQ].chip = &SIGVTALRM_irq_type; | ||
398 | enable_irq(TIMER_IRQ); | ||
399 | for (i = 1; i < NR_IRQS; i++) { | 396 | for (i = 1; i < NR_IRQS; i++) { |
400 | irq_desc[i].status = IRQ_DISABLED; | 397 | set_irq_chip_and_handler(i, &normal_irq_type, handle_edge_irq); |
401 | irq_desc[i].action = NULL; | ||
402 | irq_desc[i].depth = 1; | ||
403 | irq_desc[i].chip = &normal_irq_type; | ||
404 | enable_irq(i); | ||
405 | } | 398 | } |
406 | } | 399 | } |
407 | 400 | ||
diff --git a/arch/um/kernel/uml.lds.S b/arch/um/kernel/uml.lds.S index ec6378550671..fbd99402d4d2 100644 --- a/arch/um/kernel/uml.lds.S +++ b/arch/um/kernel/uml.lds.S | |||
@@ -22,7 +22,7 @@ SECTIONS | |||
22 | _text = .; | 22 | _text = .; |
23 | _stext = .; | 23 | _stext = .; |
24 | __init_begin = .; | 24 | __init_begin = .; |
25 | INIT_TEXT_SECTION(PAGE_SIZE) | 25 | INIT_TEXT_SECTION(0) |
26 | . = ALIGN(PAGE_SIZE); | 26 | . = ALIGN(PAGE_SIZE); |
27 | 27 | ||
28 | .text : | 28 | .text : |
@@ -43,6 +43,23 @@ SECTIONS | |||
43 | __syscall_stub_end = .; | 43 | __syscall_stub_end = .; |
44 | } | 44 | } |
45 | 45 | ||
46 | /* | ||
47 | * These are needed even in a static link, even if they wind up being empty. | ||
48 | * Newer glibc needs these __rel{,a}_iplt_{start,end} symbols. | ||
49 | */ | ||
50 | .rel.plt : { | ||
51 | *(.rel.plt) | ||
52 | PROVIDE_HIDDEN(__rel_iplt_start = .); | ||
53 | *(.rel.iplt) | ||
54 | PROVIDE_HIDDEN(__rel_iplt_end = .); | ||
55 | } | ||
56 | .rela.plt : { | ||
57 | *(.rela.plt) | ||
58 | PROVIDE_HIDDEN(__rela_iplt_start = .); | ||
59 | *(.rela.iplt) | ||
60 | PROVIDE_HIDDEN(__rela_iplt_end = .); | ||
61 | } | ||
62 | |||
46 | #include "asm/common.lds.S" | 63 | #include "asm/common.lds.S" |
47 | 64 | ||
48 | init.data : { INIT_DATA } | 65 | init.data : { INIT_DATA } |
diff --git a/arch/um/os-Linux/time.c b/arch/um/os-Linux/time.c index dec5678fc17f..6e3359d6a839 100644 --- a/arch/um/os-Linux/time.c +++ b/arch/um/os-Linux/time.c | |||
@@ -60,7 +60,7 @@ static inline long long timeval_to_ns(const struct timeval *tv) | |||
60 | long long disable_timer(void) | 60 | long long disable_timer(void) |
61 | { | 61 | { |
62 | struct itimerval time = ((struct itimerval) { { 0, 0 }, { 0, 0 } }); | 62 | struct itimerval time = ((struct itimerval) { { 0, 0 }, { 0, 0 } }); |
63 | int remain, max = UM_NSEC_PER_SEC / UM_HZ; | 63 | long long remain, max = UM_NSEC_PER_SEC / UM_HZ; |
64 | 64 | ||
65 | if (setitimer(ITIMER_VIRTUAL, &time, &time) < 0) | 65 | if (setitimer(ITIMER_VIRTUAL, &time, &time) < 0) |
66 | printk(UM_KERN_ERR "disable_timer - setitimer failed, " | 66 | printk(UM_KERN_ERR "disable_timer - setitimer failed, " |
diff --git a/arch/x86/include/asm/highmem.h b/arch/x86/include/asm/highmem.h index 8caac76ac324..3bd04022fd0c 100644 --- a/arch/x86/include/asm/highmem.h +++ b/arch/x86/include/asm/highmem.h | |||
@@ -59,11 +59,12 @@ extern void kunmap_high(struct page *page); | |||
59 | 59 | ||
60 | void *kmap(struct page *page); | 60 | void *kmap(struct page *page); |
61 | void kunmap(struct page *page); | 61 | void kunmap(struct page *page); |
62 | void *kmap_atomic_prot(struct page *page, enum km_type type, pgprot_t prot); | 62 | |
63 | void *kmap_atomic(struct page *page, enum km_type type); | 63 | void *kmap_atomic_prot(struct page *page, pgprot_t prot); |
64 | void kunmap_atomic_notypecheck(void *kvaddr, enum km_type type); | 64 | void *__kmap_atomic(struct page *page); |
65 | void *kmap_atomic_pfn(unsigned long pfn, enum km_type type); | 65 | void __kunmap_atomic(void *kvaddr); |
66 | void *kmap_atomic_prot_pfn(unsigned long pfn, enum km_type type, pgprot_t prot); | 66 | void *kmap_atomic_pfn(unsigned long pfn); |
67 | void *kmap_atomic_prot_pfn(unsigned long pfn, pgprot_t prot); | ||
67 | struct page *kmap_atomic_to_page(void *ptr); | 68 | struct page *kmap_atomic_to_page(void *ptr); |
68 | 69 | ||
69 | #define flush_cache_kmaps() do { } while (0) | 70 | #define flush_cache_kmaps() do { } while (0) |
diff --git a/arch/x86/include/asm/iomap.h b/arch/x86/include/asm/iomap.h index c4191b3b7056..363e33eb6ec1 100644 --- a/arch/x86/include/asm/iomap.h +++ b/arch/x86/include/asm/iomap.h | |||
@@ -27,10 +27,10 @@ | |||
27 | #include <asm/tlbflush.h> | 27 | #include <asm/tlbflush.h> |
28 | 28 | ||
29 | void __iomem * | 29 | void __iomem * |
30 | iomap_atomic_prot_pfn(unsigned long pfn, enum km_type type, pgprot_t prot); | 30 | iomap_atomic_prot_pfn(unsigned long pfn, pgprot_t prot); |
31 | 31 | ||
32 | void | 32 | void |
33 | iounmap_atomic(void __iomem *kvaddr, enum km_type type); | 33 | iounmap_atomic(void __iomem *kvaddr); |
34 | 34 | ||
35 | int | 35 | int |
36 | iomap_create_wc(resource_size_t base, unsigned long size, pgprot_t *prot); | 36 | iomap_create_wc(resource_size_t base, unsigned long size, pgprot_t *prot); |
diff --git a/arch/x86/include/asm/pgtable_32.h b/arch/x86/include/asm/pgtable_32.h index 8abde9ec90bf..0c92113c4cb6 100644 --- a/arch/x86/include/asm/pgtable_32.h +++ b/arch/x86/include/asm/pgtable_32.h | |||
@@ -49,24 +49,14 @@ extern void set_pmd_pfn(unsigned long, unsigned long, pgprot_t); | |||
49 | #endif | 49 | #endif |
50 | 50 | ||
51 | #if defined(CONFIG_HIGHPTE) | 51 | #if defined(CONFIG_HIGHPTE) |
52 | #define __KM_PTE \ | ||
53 | (in_nmi() ? KM_NMI_PTE : \ | ||
54 | in_irq() ? KM_IRQ_PTE : \ | ||
55 | KM_PTE0) | ||
56 | #define pte_offset_map(dir, address) \ | 52 | #define pte_offset_map(dir, address) \ |
57 | ((pte_t *)kmap_atomic(pmd_page(*(dir)), __KM_PTE) + \ | 53 | ((pte_t *)kmap_atomic(pmd_page(*(dir))) + \ |
58 | pte_index((address))) | 54 | pte_index((address))) |
59 | #define pte_offset_map_nested(dir, address) \ | 55 | #define pte_unmap(pte) kunmap_atomic((pte)) |
60 | ((pte_t *)kmap_atomic(pmd_page(*(dir)), KM_PTE1) + \ | ||
61 | pte_index((address))) | ||
62 | #define pte_unmap(pte) kunmap_atomic((pte), __KM_PTE) | ||
63 | #define pte_unmap_nested(pte) kunmap_atomic((pte), KM_PTE1) | ||
64 | #else | 56 | #else |
65 | #define pte_offset_map(dir, address) \ | 57 | #define pte_offset_map(dir, address) \ |
66 | ((pte_t *)page_address(pmd_page(*(dir))) + pte_index((address))) | 58 | ((pte_t *)page_address(pmd_page(*(dir))) + pte_index((address))) |
67 | #define pte_offset_map_nested(dir, address) pte_offset_map((dir), (address)) | ||
68 | #define pte_unmap(pte) do { } while (0) | 59 | #define pte_unmap(pte) do { } while (0) |
69 | #define pte_unmap_nested(pte) do { } while (0) | ||
70 | #endif | 60 | #endif |
71 | 61 | ||
72 | /* Clear a kernel PTE and flush it from the TLB */ | 62 | /* Clear a kernel PTE and flush it from the TLB */ |
diff --git a/arch/x86/include/asm/pgtable_64.h b/arch/x86/include/asm/pgtable_64.h index f96ac9bedf75..f86da20347f2 100644 --- a/arch/x86/include/asm/pgtable_64.h +++ b/arch/x86/include/asm/pgtable_64.h | |||
@@ -127,9 +127,7 @@ static inline int pgd_large(pgd_t pgd) { return 0; } | |||
127 | 127 | ||
128 | /* x86-64 always has all page tables mapped. */ | 128 | /* x86-64 always has all page tables mapped. */ |
129 | #define pte_offset_map(dir, address) pte_offset_kernel((dir), (address)) | 129 | #define pte_offset_map(dir, address) pte_offset_kernel((dir), (address)) |
130 | #define pte_offset_map_nested(dir, address) pte_offset_kernel((dir), (address)) | ||
131 | #define pte_unmap(pte) ((void)(pte))/* NOP */ | 130 | #define pte_unmap(pte) ((void)(pte))/* NOP */ |
132 | #define pte_unmap_nested(pte) ((void)(pte)) /* NOP */ | ||
133 | 131 | ||
134 | #define update_mmu_cache(vma, address, ptep) do { } while (0) | 132 | #define update_mmu_cache(vma, address, ptep) do { } while (0) |
135 | 133 | ||
diff --git a/arch/x86/kernel/cpu/intel_cacheinfo.c b/arch/x86/kernel/cpu/intel_cacheinfo.c index 12cd823c8d03..17ad03366211 100644 --- a/arch/x86/kernel/cpu/intel_cacheinfo.c +++ b/arch/x86/kernel/cpu/intel_cacheinfo.c | |||
@@ -327,6 +327,7 @@ static void __cpuinit amd_calc_l3_indices(struct amd_l3_cache *l3) | |||
327 | l3->subcaches[3] = sc3 = !(val & BIT(12)) + !(val & BIT(13)); | 327 | l3->subcaches[3] = sc3 = !(val & BIT(12)) + !(val & BIT(13)); |
328 | 328 | ||
329 | l3->indices = (max(max(max(sc0, sc1), sc2), sc3) << 10) - 1; | 329 | l3->indices = (max(max(max(sc0, sc1), sc2), sc3) << 10) - 1; |
330 | l3->indices = (max(max3(sc0, sc1, sc2), sc3) << 10) - 1; | ||
330 | } | 331 | } |
331 | 332 | ||
332 | static struct amd_l3_cache * __cpuinit amd_init_l3_cache(int node) | 333 | static struct amd_l3_cache * __cpuinit amd_init_l3_cache(int node) |
diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index fe73c1844a9a..c1e8c7a51164 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c | |||
@@ -49,7 +49,6 @@ static unsigned long | |||
49 | copy_from_user_nmi(void *to, const void __user *from, unsigned long n) | 49 | copy_from_user_nmi(void *to, const void __user *from, unsigned long n) |
50 | { | 50 | { |
51 | unsigned long offset, addr = (unsigned long)from; | 51 | unsigned long offset, addr = (unsigned long)from; |
52 | int type = in_nmi() ? KM_NMI : KM_IRQ0; | ||
53 | unsigned long size, len = 0; | 52 | unsigned long size, len = 0; |
54 | struct page *page; | 53 | struct page *page; |
55 | void *map; | 54 | void *map; |
@@ -63,9 +62,9 @@ copy_from_user_nmi(void *to, const void __user *from, unsigned long n) | |||
63 | offset = addr & (PAGE_SIZE - 1); | 62 | offset = addr & (PAGE_SIZE - 1); |
64 | size = min(PAGE_SIZE - offset, n - len); | 63 | size = min(PAGE_SIZE - offset, n - len); |
65 | 64 | ||
66 | map = kmap_atomic(page, type); | 65 | map = kmap_atomic(page); |
67 | memcpy(to, map+offset, size); | 66 | memcpy(to, map+offset, size); |
68 | kunmap_atomic(map, type); | 67 | kunmap_atomic(map); |
69 | put_page(page); | 68 | put_page(page); |
70 | 69 | ||
71 | len += size; | 70 | len += size; |
diff --git a/arch/x86/kernel/crash_dump_32.c b/arch/x86/kernel/crash_dump_32.c index 67414550c3cc..d5cd13945d5a 100644 --- a/arch/x86/kernel/crash_dump_32.c +++ b/arch/x86/kernel/crash_dump_32.c | |||
@@ -61,7 +61,7 @@ ssize_t copy_oldmem_page(unsigned long pfn, char *buf, | |||
61 | if (!is_crashed_pfn_valid(pfn)) | 61 | if (!is_crashed_pfn_valid(pfn)) |
62 | return -EFAULT; | 62 | return -EFAULT; |
63 | 63 | ||
64 | vaddr = kmap_atomic_pfn(pfn, KM_PTE0); | 64 | vaddr = kmap_atomic_pfn(pfn); |
65 | 65 | ||
66 | if (!userbuf) { | 66 | if (!userbuf) { |
67 | memcpy(buf, (vaddr + offset), csize); | 67 | memcpy(buf, (vaddr + offset), csize); |
diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c index aff0b3c27509..ae03cab4352e 100644 --- a/arch/x86/kernel/hpet.c +++ b/arch/x86/kernel/hpet.c | |||
@@ -713,7 +713,7 @@ static int hpet_cpuhp_notify(struct notifier_block *n, | |||
713 | 713 | ||
714 | switch (action & 0xf) { | 714 | switch (action & 0xf) { |
715 | case CPU_ONLINE: | 715 | case CPU_ONLINE: |
716 | INIT_DELAYED_WORK_ON_STACK(&work.work, hpet_work); | 716 | INIT_DELAYED_WORK_ONSTACK(&work.work, hpet_work); |
717 | init_completion(&work.complete); | 717 | init_completion(&work.complete); |
718 | /* FIXME: add schedule_work_on() */ | 718 | /* FIXME: add schedule_work_on() */ |
719 | schedule_delayed_work_on(cpu, &work.work, 0); | 719 | schedule_delayed_work_on(cpu, &work.work, 0); |
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 6af118511b4a..6c7faecd9e4a 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c | |||
@@ -747,7 +747,7 @@ static int __cpuinit do_boot_cpu(int apicid, int cpu) | |||
747 | .done = COMPLETION_INITIALIZER_ONSTACK(c_idle.done), | 747 | .done = COMPLETION_INITIALIZER_ONSTACK(c_idle.done), |
748 | }; | 748 | }; |
749 | 749 | ||
750 | INIT_WORK_ON_STACK(&c_idle.work, do_fork_idle); | 750 | INIT_WORK_ONSTACK(&c_idle.work, do_fork_idle); |
751 | 751 | ||
752 | alternatives_smp_switch(1); | 752 | alternatives_smp_switch(1); |
753 | 753 | ||
diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c index 852b319edbdc..7d90ceb882a4 100644 --- a/arch/x86/mm/fault.c +++ b/arch/x86/mm/fault.c | |||
@@ -919,9 +919,9 @@ spurious_fault(unsigned long error_code, unsigned long address) | |||
919 | int show_unhandled_signals = 1; | 919 | int show_unhandled_signals = 1; |
920 | 920 | ||
921 | static inline int | 921 | static inline int |
922 | access_error(unsigned long error_code, int write, struct vm_area_struct *vma) | 922 | access_error(unsigned long error_code, struct vm_area_struct *vma) |
923 | { | 923 | { |
924 | if (write) { | 924 | if (error_code & PF_WRITE) { |
925 | /* write, present and write, not present: */ | 925 | /* write, present and write, not present: */ |
926 | if (unlikely(!(vma->vm_flags & VM_WRITE))) | 926 | if (unlikely(!(vma->vm_flags & VM_WRITE))) |
927 | return 1; | 927 | return 1; |
@@ -956,8 +956,10 @@ do_page_fault(struct pt_regs *regs, unsigned long error_code) | |||
956 | struct task_struct *tsk; | 956 | struct task_struct *tsk; |
957 | unsigned long address; | 957 | unsigned long address; |
958 | struct mm_struct *mm; | 958 | struct mm_struct *mm; |
959 | int write; | ||
960 | int fault; | 959 | int fault; |
960 | int write = error_code & PF_WRITE; | ||
961 | unsigned int flags = FAULT_FLAG_ALLOW_RETRY | | ||
962 | (write ? FAULT_FLAG_WRITE : 0); | ||
961 | 963 | ||
962 | tsk = current; | 964 | tsk = current; |
963 | mm = tsk->mm; | 965 | mm = tsk->mm; |
@@ -1068,6 +1070,7 @@ do_page_fault(struct pt_regs *regs, unsigned long error_code) | |||
1068 | bad_area_nosemaphore(regs, error_code, address); | 1070 | bad_area_nosemaphore(regs, error_code, address); |
1069 | return; | 1071 | return; |
1070 | } | 1072 | } |
1073 | retry: | ||
1071 | down_read(&mm->mmap_sem); | 1074 | down_read(&mm->mmap_sem); |
1072 | } else { | 1075 | } else { |
1073 | /* | 1076 | /* |
@@ -1111,9 +1114,7 @@ do_page_fault(struct pt_regs *regs, unsigned long error_code) | |||
1111 | * we can handle it.. | 1114 | * we can handle it.. |
1112 | */ | 1115 | */ |
1113 | good_area: | 1116 | good_area: |
1114 | write = error_code & PF_WRITE; | 1117 | if (unlikely(access_error(error_code, vma))) { |
1115 | |||
1116 | if (unlikely(access_error(error_code, write, vma))) { | ||
1117 | bad_area_access_error(regs, error_code, address); | 1118 | bad_area_access_error(regs, error_code, address); |
1118 | return; | 1119 | return; |
1119 | } | 1120 | } |
@@ -1123,21 +1124,34 @@ good_area: | |||
1123 | * make sure we exit gracefully rather than endlessly redo | 1124 | * make sure we exit gracefully rather than endlessly redo |
1124 | * the fault: | 1125 | * the fault: |
1125 | */ | 1126 | */ |
1126 | fault = handle_mm_fault(mm, vma, address, write ? FAULT_FLAG_WRITE : 0); | 1127 | fault = handle_mm_fault(mm, vma, address, flags); |
1127 | 1128 | ||
1128 | if (unlikely(fault & VM_FAULT_ERROR)) { | 1129 | if (unlikely(fault & VM_FAULT_ERROR)) { |
1129 | mm_fault_error(regs, error_code, address, fault); | 1130 | mm_fault_error(regs, error_code, address, fault); |
1130 | return; | 1131 | return; |
1131 | } | 1132 | } |
1132 | 1133 | ||
1133 | if (fault & VM_FAULT_MAJOR) { | 1134 | /* |
1134 | tsk->maj_flt++; | 1135 | * Major/minor page fault accounting is only done on the |
1135 | perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, 0, | 1136 | * initial attempt. If we go through a retry, it is extremely |
1136 | regs, address); | 1137 | * likely that the page will be found in page cache at that point. |
1137 | } else { | 1138 | */ |
1138 | tsk->min_flt++; | 1139 | if (flags & FAULT_FLAG_ALLOW_RETRY) { |
1139 | perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, 0, | 1140 | if (fault & VM_FAULT_MAJOR) { |
1140 | regs, address); | 1141 | tsk->maj_flt++; |
1142 | perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, 0, | ||
1143 | regs, address); | ||
1144 | } else { | ||
1145 | tsk->min_flt++; | ||
1146 | perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, 0, | ||
1147 | regs, address); | ||
1148 | } | ||
1149 | if (fault & VM_FAULT_RETRY) { | ||
1150 | /* Clear FAULT_FLAG_ALLOW_RETRY to avoid any risk | ||
1151 | * of starvation. */ | ||
1152 | flags &= ~FAULT_FLAG_ALLOW_RETRY; | ||
1153 | goto retry; | ||
1154 | } | ||
1141 | } | 1155 | } |
1142 | 1156 | ||
1143 | check_v8086_mode(regs, address, tsk); | 1157 | check_v8086_mode(regs, address, tsk); |
diff --git a/arch/x86/mm/highmem_32.c b/arch/x86/mm/highmem_32.c index 5e8fa12ef861..d723e369003c 100644 --- a/arch/x86/mm/highmem_32.c +++ b/arch/x86/mm/highmem_32.c | |||
@@ -9,6 +9,7 @@ void *kmap(struct page *page) | |||
9 | return page_address(page); | 9 | return page_address(page); |
10 | return kmap_high(page); | 10 | return kmap_high(page); |
11 | } | 11 | } |
12 | EXPORT_SYMBOL(kmap); | ||
12 | 13 | ||
13 | void kunmap(struct page *page) | 14 | void kunmap(struct page *page) |
14 | { | 15 | { |
@@ -18,6 +19,7 @@ void kunmap(struct page *page) | |||
18 | return; | 19 | return; |
19 | kunmap_high(page); | 20 | kunmap_high(page); |
20 | } | 21 | } |
22 | EXPORT_SYMBOL(kunmap); | ||
21 | 23 | ||
22 | /* | 24 | /* |
23 | * kmap_atomic/kunmap_atomic is significantly faster than kmap/kunmap because | 25 | * kmap_atomic/kunmap_atomic is significantly faster than kmap/kunmap because |
@@ -27,10 +29,10 @@ void kunmap(struct page *page) | |||
27 | * However when holding an atomic kmap it is not legal to sleep, so atomic | 29 | * However when holding an atomic kmap it is not legal to sleep, so atomic |
28 | * kmaps are appropriate for short, tight code paths only. | 30 | * kmaps are appropriate for short, tight code paths only. |
29 | */ | 31 | */ |
30 | void *kmap_atomic_prot(struct page *page, enum km_type type, pgprot_t prot) | 32 | void *kmap_atomic_prot(struct page *page, pgprot_t prot) |
31 | { | 33 | { |
32 | enum fixed_addresses idx; | ||
33 | unsigned long vaddr; | 34 | unsigned long vaddr; |
35 | int idx, type; | ||
34 | 36 | ||
35 | /* even !CONFIG_PREEMPT needs this, for in_atomic in do_page_fault */ | 37 | /* even !CONFIG_PREEMPT needs this, for in_atomic in do_page_fault */ |
36 | pagefault_disable(); | 38 | pagefault_disable(); |
@@ -38,8 +40,7 @@ void *kmap_atomic_prot(struct page *page, enum km_type type, pgprot_t prot) | |||
38 | if (!PageHighMem(page)) | 40 | if (!PageHighMem(page)) |
39 | return page_address(page); | 41 | return page_address(page); |
40 | 42 | ||
41 | debug_kmap_atomic(type); | 43 | type = kmap_atomic_idx_push(); |
42 | |||
43 | idx = type + KM_TYPE_NR*smp_processor_id(); | 44 | idx = type + KM_TYPE_NR*smp_processor_id(); |
44 | vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); | 45 | vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); |
45 | BUG_ON(!pte_none(*(kmap_pte-idx))); | 46 | BUG_ON(!pte_none(*(kmap_pte-idx))); |
@@ -47,44 +48,56 @@ void *kmap_atomic_prot(struct page *page, enum km_type type, pgprot_t prot) | |||
47 | 48 | ||
48 | return (void *)vaddr; | 49 | return (void *)vaddr; |
49 | } | 50 | } |
51 | EXPORT_SYMBOL(kmap_atomic_prot); | ||
52 | |||
53 | void *__kmap_atomic(struct page *page) | ||
54 | { | ||
55 | return kmap_atomic_prot(page, kmap_prot); | ||
56 | } | ||
57 | EXPORT_SYMBOL(__kmap_atomic); | ||
50 | 58 | ||
51 | void *kmap_atomic(struct page *page, enum km_type type) | 59 | /* |
60 | * This is the same as kmap_atomic() but can map memory that doesn't | ||
61 | * have a struct page associated with it. | ||
62 | */ | ||
63 | void *kmap_atomic_pfn(unsigned long pfn) | ||
52 | { | 64 | { |
53 | return kmap_atomic_prot(page, type, kmap_prot); | 65 | return kmap_atomic_prot_pfn(pfn, kmap_prot); |
54 | } | 66 | } |
67 | EXPORT_SYMBOL_GPL(kmap_atomic_pfn); | ||
55 | 68 | ||
56 | void kunmap_atomic_notypecheck(void *kvaddr, enum km_type type) | 69 | void __kunmap_atomic(void *kvaddr) |
57 | { | 70 | { |
58 | unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK; | 71 | unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK; |
59 | enum fixed_addresses idx = type + KM_TYPE_NR*smp_processor_id(); | 72 | |
60 | 73 | if (vaddr >= __fix_to_virt(FIX_KMAP_END) && | |
61 | /* | 74 | vaddr <= __fix_to_virt(FIX_KMAP_BEGIN)) { |
62 | * Force other mappings to Oops if they'll try to access this pte | 75 | int idx, type; |
63 | * without first remap it. Keeping stale mappings around is a bad idea | 76 | |
64 | * also, in case the page changes cacheability attributes or becomes | 77 | type = kmap_atomic_idx_pop(); |
65 | * a protected page in a hypervisor. | 78 | idx = type + KM_TYPE_NR * smp_processor_id(); |
66 | */ | 79 | |
67 | if (vaddr == __fix_to_virt(FIX_KMAP_BEGIN+idx)) | 80 | #ifdef CONFIG_DEBUG_HIGHMEM |
81 | WARN_ON_ONCE(vaddr != __fix_to_virt(FIX_KMAP_BEGIN + idx)); | ||
82 | #endif | ||
83 | /* | ||
84 | * Force other mappings to Oops if they'll try to access this | ||
85 | * pte without first remap it. Keeping stale mappings around | ||
86 | * is a bad idea also, in case the page changes cacheability | ||
87 | * attributes or becomes a protected page in a hypervisor. | ||
88 | */ | ||
68 | kpte_clear_flush(kmap_pte-idx, vaddr); | 89 | kpte_clear_flush(kmap_pte-idx, vaddr); |
69 | else { | 90 | } |
70 | #ifdef CONFIG_DEBUG_HIGHMEM | 91 | #ifdef CONFIG_DEBUG_HIGHMEM |
92 | else { | ||
71 | BUG_ON(vaddr < PAGE_OFFSET); | 93 | BUG_ON(vaddr < PAGE_OFFSET); |
72 | BUG_ON(vaddr >= (unsigned long)high_memory); | 94 | BUG_ON(vaddr >= (unsigned long)high_memory); |
73 | #endif | ||
74 | } | 95 | } |
96 | #endif | ||
75 | 97 | ||
76 | pagefault_enable(); | 98 | pagefault_enable(); |
77 | } | 99 | } |
78 | 100 | EXPORT_SYMBOL(__kunmap_atomic); | |
79 | /* | ||
80 | * This is the same as kmap_atomic() but can map memory that doesn't | ||
81 | * have a struct page associated with it. | ||
82 | */ | ||
83 | void *kmap_atomic_pfn(unsigned long pfn, enum km_type type) | ||
84 | { | ||
85 | return kmap_atomic_prot_pfn(pfn, type, kmap_prot); | ||
86 | } | ||
87 | EXPORT_SYMBOL_GPL(kmap_atomic_pfn); /* temporarily in use by i915 GEM until vmap */ | ||
88 | 101 | ||
89 | struct page *kmap_atomic_to_page(void *ptr) | 102 | struct page *kmap_atomic_to_page(void *ptr) |
90 | { | 103 | { |
@@ -98,12 +111,6 @@ struct page *kmap_atomic_to_page(void *ptr) | |||
98 | pte = kmap_pte - (idx - FIX_KMAP_BEGIN); | 111 | pte = kmap_pte - (idx - FIX_KMAP_BEGIN); |
99 | return pte_page(*pte); | 112 | return pte_page(*pte); |
100 | } | 113 | } |
101 | |||
102 | EXPORT_SYMBOL(kmap); | ||
103 | EXPORT_SYMBOL(kunmap); | ||
104 | EXPORT_SYMBOL(kmap_atomic); | ||
105 | EXPORT_SYMBOL(kunmap_atomic_notypecheck); | ||
106 | EXPORT_SYMBOL(kmap_atomic_prot); | ||
107 | EXPORT_SYMBOL(kmap_atomic_to_page); | 114 | EXPORT_SYMBOL(kmap_atomic_to_page); |
108 | 115 | ||
109 | void __init set_highmem_pages_init(void) | 116 | void __init set_highmem_pages_init(void) |
diff --git a/arch/x86/mm/iomap_32.c b/arch/x86/mm/iomap_32.c index 72fc70cf6184..75a3d7f24a2c 100644 --- a/arch/x86/mm/iomap_32.c +++ b/arch/x86/mm/iomap_32.c | |||
@@ -48,21 +48,20 @@ int iomap_create_wc(resource_size_t base, unsigned long size, pgprot_t *prot) | |||
48 | } | 48 | } |
49 | EXPORT_SYMBOL_GPL(iomap_create_wc); | 49 | EXPORT_SYMBOL_GPL(iomap_create_wc); |
50 | 50 | ||
51 | void | 51 | void iomap_free(resource_size_t base, unsigned long size) |
52 | iomap_free(resource_size_t base, unsigned long size) | ||
53 | { | 52 | { |
54 | io_free_memtype(base, base + size); | 53 | io_free_memtype(base, base + size); |
55 | } | 54 | } |
56 | EXPORT_SYMBOL_GPL(iomap_free); | 55 | EXPORT_SYMBOL_GPL(iomap_free); |
57 | 56 | ||
58 | void *kmap_atomic_prot_pfn(unsigned long pfn, enum km_type type, pgprot_t prot) | 57 | void *kmap_atomic_prot_pfn(unsigned long pfn, pgprot_t prot) |
59 | { | 58 | { |
60 | enum fixed_addresses idx; | ||
61 | unsigned long vaddr; | 59 | unsigned long vaddr; |
60 | int idx, type; | ||
62 | 61 | ||
63 | pagefault_disable(); | 62 | pagefault_disable(); |
64 | 63 | ||
65 | debug_kmap_atomic(type); | 64 | type = kmap_atomic_idx_push(); |
66 | idx = type + KM_TYPE_NR * smp_processor_id(); | 65 | idx = type + KM_TYPE_NR * smp_processor_id(); |
67 | vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); | 66 | vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); |
68 | set_pte(kmap_pte - idx, pfn_pte(pfn, prot)); | 67 | set_pte(kmap_pte - idx, pfn_pte(pfn, prot)); |
@@ -72,10 +71,10 @@ void *kmap_atomic_prot_pfn(unsigned long pfn, enum km_type type, pgprot_t prot) | |||
72 | } | 71 | } |
73 | 72 | ||
74 | /* | 73 | /* |
75 | * Map 'pfn' using fixed map 'type' and protections 'prot' | 74 | * Map 'pfn' using protections 'prot' |
76 | */ | 75 | */ |
77 | void __iomem * | 76 | void __iomem * |
78 | iomap_atomic_prot_pfn(unsigned long pfn, enum km_type type, pgprot_t prot) | 77 | iomap_atomic_prot_pfn(unsigned long pfn, pgprot_t prot) |
79 | { | 78 | { |
80 | /* | 79 | /* |
81 | * For non-PAT systems, promote PAGE_KERNEL_WC to PAGE_KERNEL_UC_MINUS. | 80 | * For non-PAT systems, promote PAGE_KERNEL_WC to PAGE_KERNEL_UC_MINUS. |
@@ -86,24 +85,33 @@ iomap_atomic_prot_pfn(unsigned long pfn, enum km_type type, pgprot_t prot) | |||
86 | if (!pat_enabled && pgprot_val(prot) == pgprot_val(PAGE_KERNEL_WC)) | 85 | if (!pat_enabled && pgprot_val(prot) == pgprot_val(PAGE_KERNEL_WC)) |
87 | prot = PAGE_KERNEL_UC_MINUS; | 86 | prot = PAGE_KERNEL_UC_MINUS; |
88 | 87 | ||
89 | return (void __force __iomem *) kmap_atomic_prot_pfn(pfn, type, prot); | 88 | return (void __force __iomem *) kmap_atomic_prot_pfn(pfn, prot); |
90 | } | 89 | } |
91 | EXPORT_SYMBOL_GPL(iomap_atomic_prot_pfn); | 90 | EXPORT_SYMBOL_GPL(iomap_atomic_prot_pfn); |
92 | 91 | ||
93 | void | 92 | void |
94 | iounmap_atomic(void __iomem *kvaddr, enum km_type type) | 93 | iounmap_atomic(void __iomem *kvaddr) |
95 | { | 94 | { |
96 | unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK; | 95 | unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK; |
97 | enum fixed_addresses idx = type + KM_TYPE_NR*smp_processor_id(); | ||
98 | 96 | ||
99 | /* | 97 | if (vaddr >= __fix_to_virt(FIX_KMAP_END) && |
100 | * Force other mappings to Oops if they'll try to access this pte | 98 | vaddr <= __fix_to_virt(FIX_KMAP_BEGIN)) { |
101 | * without first remap it. Keeping stale mappings around is a bad idea | 99 | int idx, type; |
102 | * also, in case the page changes cacheability attributes or becomes | 100 | |
103 | * a protected page in a hypervisor. | 101 | type = kmap_atomic_idx_pop(); |
104 | */ | 102 | idx = type + KM_TYPE_NR * smp_processor_id(); |
105 | if (vaddr == __fix_to_virt(FIX_KMAP_BEGIN+idx)) | 103 | |
104 | #ifdef CONFIG_DEBUG_HIGHMEM | ||
105 | WARN_ON_ONCE(vaddr != __fix_to_virt(FIX_KMAP_BEGIN + idx)); | ||
106 | #endif | ||
107 | /* | ||
108 | * Force other mappings to Oops if they'll try to access this | ||
109 | * pte without first remap it. Keeping stale mappings around | ||
110 | * is a bad idea also, in case the page changes cacheability | ||
111 | * attributes or becomes a protected page in a hypervisor. | ||
112 | */ | ||
106 | kpte_clear_flush(kmap_pte-idx, vaddr); | 113 | kpte_clear_flush(kmap_pte-idx, vaddr); |
114 | } | ||
107 | 115 | ||
108 | pagefault_enable(); | 116 | pagefault_enable(); |
109 | } | 117 | } |
diff --git a/arch/xtensa/include/asm/pgtable.h b/arch/xtensa/include/asm/pgtable.h index 76bf35554117..b03c043ce75b 100644 --- a/arch/xtensa/include/asm/pgtable.h +++ b/arch/xtensa/include/asm/pgtable.h | |||
@@ -324,10 +324,7 @@ ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep) | |||
324 | #define pte_offset_kernel(dir,addr) \ | 324 | #define pte_offset_kernel(dir,addr) \ |
325 | ((pte_t*) pmd_page_vaddr(*(dir)) + pte_index(addr)) | 325 | ((pte_t*) pmd_page_vaddr(*(dir)) + pte_index(addr)) |
326 | #define pte_offset_map(dir,addr) pte_offset_kernel((dir),(addr)) | 326 | #define pte_offset_map(dir,addr) pte_offset_kernel((dir),(addr)) |
327 | #define pte_offset_map_nested(dir,addr) pte_offset_kernel((dir),(addr)) | ||
328 | |||
329 | #define pte_unmap(pte) do { } while (0) | 327 | #define pte_unmap(pte) do { } while (0) |
330 | #define pte_unmap_nested(pte) do { } while (0) | ||
331 | 328 | ||
332 | 329 | ||
333 | /* | 330 | /* |
diff --git a/crypto/async_tx/async_memcpy.c b/crypto/async_tx/async_memcpy.c index 0ec1fb69d4ea..518c22bd9562 100644 --- a/crypto/async_tx/async_memcpy.c +++ b/crypto/async_tx/async_memcpy.c | |||
@@ -83,8 +83,8 @@ async_memcpy(struct page *dest, struct page *src, unsigned int dest_offset, | |||
83 | 83 | ||
84 | memcpy(dest_buf, src_buf, len); | 84 | memcpy(dest_buf, src_buf, len); |
85 | 85 | ||
86 | kunmap_atomic(dest_buf, KM_USER0); | ||
87 | kunmap_atomic(src_buf, KM_USER1); | 86 | kunmap_atomic(src_buf, KM_USER1); |
87 | kunmap_atomic(dest_buf, KM_USER0); | ||
88 | 88 | ||
89 | async_tx_sync_epilog(submit); | 89 | async_tx_sync_epilog(submit); |
90 | } | 90 | } |
diff --git a/crypto/blkcipher.c b/crypto/blkcipher.c index 90d26c91f4e9..7a7219266e3c 100644 --- a/crypto/blkcipher.c +++ b/crypto/blkcipher.c | |||
@@ -89,9 +89,9 @@ static inline unsigned int blkcipher_done_fast(struct blkcipher_walk *walk, | |||
89 | memcpy(walk->dst.virt.addr, walk->page, n); | 89 | memcpy(walk->dst.virt.addr, walk->page, n); |
90 | blkcipher_unmap_dst(walk); | 90 | blkcipher_unmap_dst(walk); |
91 | } else if (!(walk->flags & BLKCIPHER_WALK_PHYS)) { | 91 | } else if (!(walk->flags & BLKCIPHER_WALK_PHYS)) { |
92 | blkcipher_unmap_src(walk); | ||
93 | if (walk->flags & BLKCIPHER_WALK_DIFF) | 92 | if (walk->flags & BLKCIPHER_WALK_DIFF) |
94 | blkcipher_unmap_dst(walk); | 93 | blkcipher_unmap_dst(walk); |
94 | blkcipher_unmap_src(walk); | ||
95 | } | 95 | } |
96 | 96 | ||
97 | scatterwalk_advance(&walk->in, n); | 97 | scatterwalk_advance(&walk->in, n); |
diff --git a/drivers/base/node.c b/drivers/base/node.c index ee53558b452f..ce012a9c6201 100644 --- a/drivers/base/node.c +++ b/drivers/base/node.c | |||
@@ -160,6 +160,18 @@ static ssize_t node_read_numastat(struct sys_device * dev, | |||
160 | } | 160 | } |
161 | static SYSDEV_ATTR(numastat, S_IRUGO, node_read_numastat, NULL); | 161 | static SYSDEV_ATTR(numastat, S_IRUGO, node_read_numastat, NULL); |
162 | 162 | ||
163 | static ssize_t node_read_vmstat(struct sys_device *dev, | ||
164 | struct sysdev_attribute *attr, char *buf) | ||
165 | { | ||
166 | int nid = dev->id; | ||
167 | return sprintf(buf, | ||
168 | "nr_written %lu\n" | ||
169 | "nr_dirtied %lu\n", | ||
170 | node_page_state(nid, NR_WRITTEN), | ||
171 | node_page_state(nid, NR_DIRTIED)); | ||
172 | } | ||
173 | static SYSDEV_ATTR(vmstat, S_IRUGO, node_read_vmstat, NULL); | ||
174 | |||
163 | static ssize_t node_read_distance(struct sys_device * dev, | 175 | static ssize_t node_read_distance(struct sys_device * dev, |
164 | struct sysdev_attribute *attr, char * buf) | 176 | struct sysdev_attribute *attr, char * buf) |
165 | { | 177 | { |
@@ -243,6 +255,7 @@ int register_node(struct node *node, int num, struct node *parent) | |||
243 | sysdev_create_file(&node->sysdev, &attr_meminfo); | 255 | sysdev_create_file(&node->sysdev, &attr_meminfo); |
244 | sysdev_create_file(&node->sysdev, &attr_numastat); | 256 | sysdev_create_file(&node->sysdev, &attr_numastat); |
245 | sysdev_create_file(&node->sysdev, &attr_distance); | 257 | sysdev_create_file(&node->sysdev, &attr_distance); |
258 | sysdev_create_file(&node->sysdev, &attr_vmstat); | ||
246 | 259 | ||
247 | scan_unevictable_register_node(node); | 260 | scan_unevictable_register_node(node); |
248 | 261 | ||
@@ -267,6 +280,7 @@ void unregister_node(struct node *node) | |||
267 | sysdev_remove_file(&node->sysdev, &attr_meminfo); | 280 | sysdev_remove_file(&node->sysdev, &attr_meminfo); |
268 | sysdev_remove_file(&node->sysdev, &attr_numastat); | 281 | sysdev_remove_file(&node->sysdev, &attr_numastat); |
269 | sysdev_remove_file(&node->sysdev, &attr_distance); | 282 | sysdev_remove_file(&node->sysdev, &attr_distance); |
283 | sysdev_remove_file(&node->sysdev, &attr_vmstat); | ||
270 | 284 | ||
271 | scan_unevictable_unregister_node(node); | 285 | scan_unevictable_unregister_node(node); |
272 | hugetlb_unregister_node(node); /* no-op, if memoryless node */ | 286 | hugetlb_unregister_node(node); /* no-op, if memoryless node */ |
diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 6c48b3545f84..450c958b514f 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c | |||
@@ -101,8 +101,8 @@ static int transfer_none(struct loop_device *lo, int cmd, | |||
101 | else | 101 | else |
102 | memcpy(raw_buf, loop_buf, size); | 102 | memcpy(raw_buf, loop_buf, size); |
103 | 103 | ||
104 | kunmap_atomic(raw_buf, KM_USER0); | ||
105 | kunmap_atomic(loop_buf, KM_USER1); | 104 | kunmap_atomic(loop_buf, KM_USER1); |
105 | kunmap_atomic(raw_buf, KM_USER0); | ||
106 | cond_resched(); | 106 | cond_resched(); |
107 | return 0; | 107 | return 0; |
108 | } | 108 | } |
@@ -130,8 +130,8 @@ static int transfer_xor(struct loop_device *lo, int cmd, | |||
130 | for (i = 0; i < size; i++) | 130 | for (i = 0; i < size; i++) |
131 | *out++ = *in++ ^ key[(i & 511) % keysize]; | 131 | *out++ = *in++ ^ key[(i & 511) % keysize]; |
132 | 132 | ||
133 | kunmap_atomic(raw_buf, KM_USER0); | ||
134 | kunmap_atomic(loop_buf, KM_USER1); | 133 | kunmap_atomic(loop_buf, KM_USER1); |
134 | kunmap_atomic(raw_buf, KM_USER0); | ||
135 | cond_resched(); | 135 | cond_resched(); |
136 | return 0; | 136 | return 0; |
137 | } | 137 | } |
diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c index a4eee324eb1e..55b8667f739f 100644 --- a/drivers/char/hpet.c +++ b/drivers/char/hpet.c | |||
@@ -32,12 +32,12 @@ | |||
32 | #include <linux/bitops.h> | 32 | #include <linux/bitops.h> |
33 | #include <linux/compat.h> | 33 | #include <linux/compat.h> |
34 | #include <linux/clocksource.h> | 34 | #include <linux/clocksource.h> |
35 | #include <linux/uaccess.h> | ||
35 | #include <linux/slab.h> | 36 | #include <linux/slab.h> |
37 | #include <linux/io.h> | ||
36 | 38 | ||
37 | #include <asm/current.h> | 39 | #include <asm/current.h> |
38 | #include <asm/uaccess.h> | ||
39 | #include <asm/system.h> | 40 | #include <asm/system.h> |
40 | #include <asm/io.h> | ||
41 | #include <asm/irq.h> | 41 | #include <asm/irq.h> |
42 | #include <asm/div64.h> | 42 | #include <asm/div64.h> |
43 | 43 | ||
@@ -81,13 +81,13 @@ static cycle_t read_hpet(struct clocksource *cs) | |||
81 | } | 81 | } |
82 | 82 | ||
83 | static struct clocksource clocksource_hpet = { | 83 | static struct clocksource clocksource_hpet = { |
84 | .name = "hpet", | 84 | .name = "hpet", |
85 | .rating = 250, | 85 | .rating = 250, |
86 | .read = read_hpet, | 86 | .read = read_hpet, |
87 | .mask = CLOCKSOURCE_MASK(64), | 87 | .mask = CLOCKSOURCE_MASK(64), |
88 | .mult = 0, /* to be calculated */ | 88 | .mult = 0, /* to be calculated */ |
89 | .shift = 10, | 89 | .shift = 10, |
90 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | 90 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, |
91 | }; | 91 | }; |
92 | static struct clocksource *hpet_clocksource; | 92 | static struct clocksource *hpet_clocksource; |
93 | #endif | 93 | #endif |
@@ -465,6 +465,21 @@ static int hpet_ioctl_ieon(struct hpet_dev *devp) | |||
465 | if (irq) { | 465 | if (irq) { |
466 | unsigned long irq_flags; | 466 | unsigned long irq_flags; |
467 | 467 | ||
468 | if (devp->hd_flags & HPET_SHARED_IRQ) { | ||
469 | /* | ||
470 | * To prevent the interrupt handler from seeing an | ||
471 | * unwanted interrupt status bit, program the timer | ||
472 | * so that it will not fire in the near future ... | ||
473 | */ | ||
474 | writel(readl(&timer->hpet_config) & ~Tn_TYPE_CNF_MASK, | ||
475 | &timer->hpet_config); | ||
476 | write_counter(read_counter(&hpet->hpet_mc), | ||
477 | &timer->hpet_compare); | ||
478 | /* ... and clear any left-over status. */ | ||
479 | isr = 1 << (devp - devp->hd_hpets->hp_dev); | ||
480 | writel(isr, &hpet->hpet_isr); | ||
481 | } | ||
482 | |||
468 | sprintf(devp->hd_name, "hpet%d", (int)(devp - hpetp->hp_dev)); | 483 | sprintf(devp->hd_name, "hpet%d", (int)(devp - hpetp->hp_dev)); |
469 | irq_flags = devp->hd_flags & HPET_SHARED_IRQ | 484 | irq_flags = devp->hd_flags & HPET_SHARED_IRQ |
470 | ? IRQF_SHARED : IRQF_DISABLED; | 485 | ? IRQF_SHARED : IRQF_DISABLED; |
@@ -581,11 +596,10 @@ hpet_ioctl_common(struct hpet_dev *devp, int cmd, unsigned long arg, | |||
581 | break; | 596 | break; |
582 | case HPET_INFO: | 597 | case HPET_INFO: |
583 | { | 598 | { |
599 | memset(info, 0, sizeof(*info)); | ||
584 | if (devp->hd_ireqfreq) | 600 | if (devp->hd_ireqfreq) |
585 | info->hi_ireqfreq = | 601 | info->hi_ireqfreq = |
586 | hpet_time_div(hpetp, devp->hd_ireqfreq); | 602 | hpet_time_div(hpetp, devp->hd_ireqfreq); |
587 | else | ||
588 | info->hi_ireqfreq = 0; | ||
589 | info->hi_flags = | 603 | info->hi_flags = |
590 | readq(&timer->hpet_config) & Tn_PER_INT_CAP_MASK; | 604 | readq(&timer->hpet_config) & Tn_PER_INT_CAP_MASK; |
591 | info->hi_hpet = hpetp->hp_which; | 605 | info->hi_hpet = hpetp->hp_which; |
@@ -811,7 +825,7 @@ int hpet_alloc(struct hpet_data *hdp) | |||
811 | struct hpets *hpetp; | 825 | struct hpets *hpetp; |
812 | size_t siz; | 826 | size_t siz; |
813 | struct hpet __iomem *hpet; | 827 | struct hpet __iomem *hpet; |
814 | static struct hpets *last = NULL; | 828 | static struct hpets *last; |
815 | unsigned long period; | 829 | unsigned long period; |
816 | unsigned long long temp; | 830 | unsigned long long temp; |
817 | u32 remainder; | 831 | u32 remainder; |
@@ -1000,6 +1014,8 @@ static int hpet_acpi_add(struct acpi_device *device) | |||
1000 | return -ENODEV; | 1014 | return -ENODEV; |
1001 | 1015 | ||
1002 | if (!data.hd_address || !data.hd_nirqs) { | 1016 | if (!data.hd_address || !data.hd_nirqs) { |
1017 | if (data.hd_address) | ||
1018 | iounmap(data.hd_address); | ||
1003 | printk("%s: no address or irqs in _CRS\n", __func__); | 1019 | printk("%s: no address or irqs in _CRS\n", __func__); |
1004 | return -ENODEV; | 1020 | return -ENODEV; |
1005 | } | 1021 | } |
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index e537610d2f09..b293d57d30a7 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c | |||
@@ -1665,6 +1665,17 @@ static int check_hotmod_int_op(const char *curr, const char *option, | |||
1665 | return 0; | 1665 | return 0; |
1666 | } | 1666 | } |
1667 | 1667 | ||
1668 | static struct smi_info *smi_info_alloc(void) | ||
1669 | { | ||
1670 | struct smi_info *info = kzalloc(sizeof(*info), GFP_KERNEL); | ||
1671 | |||
1672 | if (info) { | ||
1673 | spin_lock_init(&info->si_lock); | ||
1674 | spin_lock_init(&info->msg_lock); | ||
1675 | } | ||
1676 | return info; | ||
1677 | } | ||
1678 | |||
1668 | static int hotmod_handler(const char *val, struct kernel_param *kp) | 1679 | static int hotmod_handler(const char *val, struct kernel_param *kp) |
1669 | { | 1680 | { |
1670 | char *str = kstrdup(val, GFP_KERNEL); | 1681 | char *str = kstrdup(val, GFP_KERNEL); |
@@ -1779,7 +1790,7 @@ static int hotmod_handler(const char *val, struct kernel_param *kp) | |||
1779 | } | 1790 | } |
1780 | 1791 | ||
1781 | if (op == HM_ADD) { | 1792 | if (op == HM_ADD) { |
1782 | info = kzalloc(sizeof(*info), GFP_KERNEL); | 1793 | info = smi_info_alloc(); |
1783 | if (!info) { | 1794 | if (!info) { |
1784 | rv = -ENOMEM; | 1795 | rv = -ENOMEM; |
1785 | goto out; | 1796 | goto out; |
@@ -1844,7 +1855,7 @@ static __devinit void hardcode_find_bmc(void) | |||
1844 | if (!ports[i] && !addrs[i]) | 1855 | if (!ports[i] && !addrs[i]) |
1845 | continue; | 1856 | continue; |
1846 | 1857 | ||
1847 | info = kzalloc(sizeof(*info), GFP_KERNEL); | 1858 | info = smi_info_alloc(); |
1848 | if (!info) | 1859 | if (!info) |
1849 | return; | 1860 | return; |
1850 | 1861 | ||
@@ -2027,7 +2038,7 @@ static __devinit int try_init_spmi(struct SPMITable *spmi) | |||
2027 | return -ENODEV; | 2038 | return -ENODEV; |
2028 | } | 2039 | } |
2029 | 2040 | ||
2030 | info = kzalloc(sizeof(*info), GFP_KERNEL); | 2041 | info = smi_info_alloc(); |
2031 | if (!info) { | 2042 | if (!info) { |
2032 | printk(KERN_ERR PFX "Could not allocate SI data (3)\n"); | 2043 | printk(KERN_ERR PFX "Could not allocate SI data (3)\n"); |
2033 | return -ENOMEM; | 2044 | return -ENOMEM; |
@@ -2137,7 +2148,7 @@ static int __devinit ipmi_pnp_probe(struct pnp_dev *dev, | |||
2137 | if (!acpi_dev) | 2148 | if (!acpi_dev) |
2138 | return -ENODEV; | 2149 | return -ENODEV; |
2139 | 2150 | ||
2140 | info = kzalloc(sizeof(*info), GFP_KERNEL); | 2151 | info = smi_info_alloc(); |
2141 | if (!info) | 2152 | if (!info) |
2142 | return -ENOMEM; | 2153 | return -ENOMEM; |
2143 | 2154 | ||
@@ -2318,7 +2329,7 @@ static __devinit void try_init_dmi(struct dmi_ipmi_data *ipmi_data) | |||
2318 | { | 2329 | { |
2319 | struct smi_info *info; | 2330 | struct smi_info *info; |
2320 | 2331 | ||
2321 | info = kzalloc(sizeof(*info), GFP_KERNEL); | 2332 | info = smi_info_alloc(); |
2322 | if (!info) { | 2333 | if (!info) { |
2323 | printk(KERN_ERR PFX "Could not allocate SI data\n"); | 2334 | printk(KERN_ERR PFX "Could not allocate SI data\n"); |
2324 | return; | 2335 | return; |
@@ -2425,7 +2436,7 @@ static int __devinit ipmi_pci_probe(struct pci_dev *pdev, | |||
2425 | int class_type = pdev->class & PCI_ERMC_CLASSCODE_TYPE_MASK; | 2436 | int class_type = pdev->class & PCI_ERMC_CLASSCODE_TYPE_MASK; |
2426 | struct smi_info *info; | 2437 | struct smi_info *info; |
2427 | 2438 | ||
2428 | info = kzalloc(sizeof(*info), GFP_KERNEL); | 2439 | info = smi_info_alloc(); |
2429 | if (!info) | 2440 | if (!info) |
2430 | return -ENOMEM; | 2441 | return -ENOMEM; |
2431 | 2442 | ||
@@ -2566,7 +2577,7 @@ static int __devinit ipmi_of_probe(struct platform_device *dev, | |||
2566 | return -EINVAL; | 2577 | return -EINVAL; |
2567 | } | 2578 | } |
2568 | 2579 | ||
2569 | info = kzalloc(sizeof(*info), GFP_KERNEL); | 2580 | info = smi_info_alloc(); |
2570 | 2581 | ||
2571 | if (!info) { | 2582 | if (!info) { |
2572 | dev_err(&dev->dev, | 2583 | dev_err(&dev->dev, |
@@ -3013,7 +3024,7 @@ static __devinit void default_find_bmc(void) | |||
3013 | if (check_legacy_ioport(ipmi_defaults[i].port)) | 3024 | if (check_legacy_ioport(ipmi_defaults[i].port)) |
3014 | continue; | 3025 | continue; |
3015 | #endif | 3026 | #endif |
3016 | info = kzalloc(sizeof(*info), GFP_KERNEL); | 3027 | info = smi_info_alloc(); |
3017 | if (!info) | 3028 | if (!info) |
3018 | return; | 3029 | return; |
3019 | 3030 | ||
@@ -3138,9 +3149,6 @@ static int try_smi_init(struct smi_info *new_smi) | |||
3138 | goto out_err; | 3149 | goto out_err; |
3139 | } | 3150 | } |
3140 | 3151 | ||
3141 | spin_lock_init(&(new_smi->si_lock)); | ||
3142 | spin_lock_init(&(new_smi->msg_lock)); | ||
3143 | |||
3144 | /* Do low-level detection first. */ | 3152 | /* Do low-level detection first. */ |
3145 | if (new_smi->handlers->detect(new_smi->si_sm)) { | 3153 | if (new_smi->handlers->detect(new_smi->si_sm)) { |
3146 | if (new_smi->addr_source) | 3154 | if (new_smi->addr_source) |
diff --git a/drivers/crypto/hifn_795x.c b/drivers/crypto/hifn_795x.c index 0eac3da566ba..a84250a5dd51 100644 --- a/drivers/crypto/hifn_795x.c +++ b/drivers/crypto/hifn_795x.c | |||
@@ -1467,7 +1467,7 @@ static int ablkcipher_add(unsigned int *drestp, struct scatterlist *dst, | |||
1467 | return -EINVAL; | 1467 | return -EINVAL; |
1468 | 1468 | ||
1469 | while (size) { | 1469 | while (size) { |
1470 | copy = min(drest, min(size, dst->length)); | 1470 | copy = min3(drest, size, dst->length); |
1471 | 1471 | ||
1472 | size -= copy; | 1472 | size -= copy; |
1473 | drest -= copy; | 1473 | drest -= copy; |
@@ -1729,7 +1729,7 @@ static int ablkcipher_get(void *saddr, unsigned int *srestp, unsigned int offset | |||
1729 | return -EINVAL; | 1729 | return -EINVAL; |
1730 | 1730 | ||
1731 | while (size) { | 1731 | while (size) { |
1732 | copy = min(srest, min(dst->length, size)); | 1732 | copy = min3(srest, dst->length, size); |
1733 | 1733 | ||
1734 | daddr = kmap_atomic(sg_page(dst), KM_IRQ0); | 1734 | daddr = kmap_atomic(sg_page(dst), KM_IRQ0); |
1735 | memcpy(daddr + dst->offset + offset, saddr, copy); | 1735 | memcpy(daddr + dst->offset + offset, saddr, copy); |
diff --git a/drivers/gpio/pca953x.c b/drivers/gpio/pca953x.c index a2b12aa1f2b9..501866662e05 100644 --- a/drivers/gpio/pca953x.c +++ b/drivers/gpio/pca953x.c | |||
@@ -345,7 +345,7 @@ static irqreturn_t pca953x_irq_handler(int irq, void *devid) | |||
345 | 345 | ||
346 | do { | 346 | do { |
347 | level = __ffs(pending); | 347 | level = __ffs(pending); |
348 | handle_nested_irq(level + chip->irq_base); | 348 | generic_handle_irq(level + chip->irq_base); |
349 | 349 | ||
350 | pending &= ~(1 << level); | 350 | pending &= ~(1 << level); |
351 | } while (pending); | 351 | } while (pending); |
@@ -360,7 +360,8 @@ static int pca953x_irq_setup(struct pca953x_chip *chip, | |||
360 | struct pca953x_platform_data *pdata = client->dev.platform_data; | 360 | struct pca953x_platform_data *pdata = client->dev.platform_data; |
361 | int ret; | 361 | int ret; |
362 | 362 | ||
363 | if (pdata->irq_base && (id->driver_data & PCA953X_INT)) { | 363 | if (pdata->irq_base != -1 |
364 | && (id->driver_data & PCA953X_INT)) { | ||
364 | int lvl; | 365 | int lvl; |
365 | 366 | ||
366 | ret = pca953x_read_reg(chip, PCA953X_INPUT, | 367 | ret = pca953x_read_reg(chip, PCA953X_INPUT, |
@@ -383,7 +384,6 @@ static int pca953x_irq_setup(struct pca953x_chip *chip, | |||
383 | set_irq_chip_data(irq, chip); | 384 | set_irq_chip_data(irq, chip); |
384 | set_irq_chip_and_handler(irq, &pca953x_irq_chip, | 385 | set_irq_chip_and_handler(irq, &pca953x_irq_chip, |
385 | handle_edge_irq); | 386 | handle_edge_irq); |
386 | set_irq_nested_thread(irq, 1); | ||
387 | #ifdef CONFIG_ARM | 387 | #ifdef CONFIG_ARM |
388 | set_irq_flags(irq, IRQF_VALID); | 388 | set_irq_flags(irq, IRQF_VALID); |
389 | #else | 389 | #else |
@@ -394,6 +394,7 @@ static int pca953x_irq_setup(struct pca953x_chip *chip, | |||
394 | ret = request_threaded_irq(client->irq, | 394 | ret = request_threaded_irq(client->irq, |
395 | NULL, | 395 | NULL, |
396 | pca953x_irq_handler, | 396 | pca953x_irq_handler, |
397 | IRQF_TRIGGER_RISING | | ||
397 | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, | 398 | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, |
398 | dev_name(&client->dev), chip); | 399 | dev_name(&client->dev), chip); |
399 | if (ret) { | 400 | if (ret) { |
@@ -408,13 +409,13 @@ static int pca953x_irq_setup(struct pca953x_chip *chip, | |||
408 | return 0; | 409 | return 0; |
409 | 410 | ||
410 | out_failed: | 411 | out_failed: |
411 | chip->irq_base = 0; | 412 | chip->irq_base = -1; |
412 | return ret; | 413 | return ret; |
413 | } | 414 | } |
414 | 415 | ||
415 | static void pca953x_irq_teardown(struct pca953x_chip *chip) | 416 | static void pca953x_irq_teardown(struct pca953x_chip *chip) |
416 | { | 417 | { |
417 | if (chip->irq_base) | 418 | if (chip->irq_base != -1) |
418 | free_irq(chip->client->irq, chip); | 419 | free_irq(chip->client->irq, chip); |
419 | } | 420 | } |
420 | #else /* CONFIG_GPIO_PCA953X_IRQ */ | 421 | #else /* CONFIG_GPIO_PCA953X_IRQ */ |
@@ -424,7 +425,7 @@ static int pca953x_irq_setup(struct pca953x_chip *chip, | |||
424 | struct i2c_client *client = chip->client; | 425 | struct i2c_client *client = chip->client; |
425 | struct pca953x_platform_data *pdata = client->dev.platform_data; | 426 | struct pca953x_platform_data *pdata = client->dev.platform_data; |
426 | 427 | ||
427 | if (pdata->irq_base && (id->driver_data & PCA953X_INT)) | 428 | if (pdata->irq_base != -1 && (id->driver_data & PCA953X_INT)) |
428 | dev_warn(&client->dev, "interrupt support not compiled in\n"); | 429 | dev_warn(&client->dev, "interrupt support not compiled in\n"); |
429 | 430 | ||
430 | return 0; | 431 | return 0; |
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 90b1d6753b9d..eb6c473c6d1b 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c | |||
@@ -155,11 +155,11 @@ fast_shmem_read(struct page **pages, | |||
155 | char __iomem *vaddr; | 155 | char __iomem *vaddr; |
156 | int unwritten; | 156 | int unwritten; |
157 | 157 | ||
158 | vaddr = kmap_atomic(pages[page_base >> PAGE_SHIFT], KM_USER0); | 158 | vaddr = kmap_atomic(pages[page_base >> PAGE_SHIFT]); |
159 | if (vaddr == NULL) | 159 | if (vaddr == NULL) |
160 | return -ENOMEM; | 160 | return -ENOMEM; |
161 | unwritten = __copy_to_user_inatomic(data, vaddr + page_offset, length); | 161 | unwritten = __copy_to_user_inatomic(data, vaddr + page_offset, length); |
162 | kunmap_atomic(vaddr, KM_USER0); | 162 | kunmap_atomic(vaddr); |
163 | 163 | ||
164 | if (unwritten) | 164 | if (unwritten) |
165 | return -EFAULT; | 165 | return -EFAULT; |
@@ -509,10 +509,10 @@ fast_user_write(struct io_mapping *mapping, | |||
509 | char *vaddr_atomic; | 509 | char *vaddr_atomic; |
510 | unsigned long unwritten; | 510 | unsigned long unwritten; |
511 | 511 | ||
512 | vaddr_atomic = io_mapping_map_atomic_wc(mapping, page_base, KM_USER0); | 512 | vaddr_atomic = io_mapping_map_atomic_wc(mapping, page_base); |
513 | unwritten = __copy_from_user_inatomic_nocache(vaddr_atomic + page_offset, | 513 | unwritten = __copy_from_user_inatomic_nocache(vaddr_atomic + page_offset, |
514 | user_data, length); | 514 | user_data, length); |
515 | io_mapping_unmap_atomic(vaddr_atomic, KM_USER0); | 515 | io_mapping_unmap_atomic(vaddr_atomic); |
516 | if (unwritten) | 516 | if (unwritten) |
517 | return -EFAULT; | 517 | return -EFAULT; |
518 | return 0; | 518 | return 0; |
@@ -551,11 +551,11 @@ fast_shmem_write(struct page **pages, | |||
551 | char __iomem *vaddr; | 551 | char __iomem *vaddr; |
552 | unsigned long unwritten; | 552 | unsigned long unwritten; |
553 | 553 | ||
554 | vaddr = kmap_atomic(pages[page_base >> PAGE_SHIFT], KM_USER0); | 554 | vaddr = kmap_atomic(pages[page_base >> PAGE_SHIFT]); |
555 | if (vaddr == NULL) | 555 | if (vaddr == NULL) |
556 | return -ENOMEM; | 556 | return -ENOMEM; |
557 | unwritten = __copy_from_user_inatomic(vaddr + page_offset, data, length); | 557 | unwritten = __copy_from_user_inatomic(vaddr + page_offset, data, length); |
558 | kunmap_atomic(vaddr, KM_USER0); | 558 | kunmap_atomic(vaddr); |
559 | 559 | ||
560 | if (unwritten) | 560 | if (unwritten) |
561 | return -EFAULT; | 561 | return -EFAULT; |
@@ -3346,8 +3346,7 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj, | |||
3346 | reloc_offset = obj_priv->gtt_offset + reloc->offset; | 3346 | reloc_offset = obj_priv->gtt_offset + reloc->offset; |
3347 | reloc_page = io_mapping_map_atomic_wc(dev_priv->mm.gtt_mapping, | 3347 | reloc_page = io_mapping_map_atomic_wc(dev_priv->mm.gtt_mapping, |
3348 | (reloc_offset & | 3348 | (reloc_offset & |
3349 | ~(PAGE_SIZE - 1)), | 3349 | ~(PAGE_SIZE - 1))); |
3350 | KM_USER0); | ||
3351 | reloc_entry = (uint32_t __iomem *)(reloc_page + | 3350 | reloc_entry = (uint32_t __iomem *)(reloc_page + |
3352 | (reloc_offset & (PAGE_SIZE - 1))); | 3351 | (reloc_offset & (PAGE_SIZE - 1))); |
3353 | reloc_val = target_obj_priv->gtt_offset + reloc->delta; | 3352 | reloc_val = target_obj_priv->gtt_offset + reloc->delta; |
@@ -3358,7 +3357,7 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj, | |||
3358 | readl(reloc_entry), reloc_val); | 3357 | readl(reloc_entry), reloc_val); |
3359 | #endif | 3358 | #endif |
3360 | writel(reloc_val, reloc_entry); | 3359 | writel(reloc_val, reloc_entry); |
3361 | io_mapping_unmap_atomic(reloc_page, KM_USER0); | 3360 | io_mapping_unmap_atomic(reloc_page); |
3362 | 3361 | ||
3363 | /* The updated presumed offset for this entry will be | 3362 | /* The updated presumed offset for this entry will be |
3364 | * copied back out to the user. | 3363 | * copied back out to the user. |
@@ -4772,11 +4771,11 @@ void i915_gem_detach_phys_object(struct drm_device *dev, | |||
4772 | page_count = obj->size / PAGE_SIZE; | 4771 | page_count = obj->size / PAGE_SIZE; |
4773 | 4772 | ||
4774 | for (i = 0; i < page_count; i++) { | 4773 | for (i = 0; i < page_count; i++) { |
4775 | char *dst = kmap_atomic(obj_priv->pages[i], KM_USER0); | 4774 | char *dst = kmap_atomic(obj_priv->pages[i]); |
4776 | char *src = obj_priv->phys_obj->handle->vaddr + (i * PAGE_SIZE); | 4775 | char *src = obj_priv->phys_obj->handle->vaddr + (i * PAGE_SIZE); |
4777 | 4776 | ||
4778 | memcpy(dst, src, PAGE_SIZE); | 4777 | memcpy(dst, src, PAGE_SIZE); |
4779 | kunmap_atomic(dst, KM_USER0); | 4778 | kunmap_atomic(dst); |
4780 | } | 4779 | } |
4781 | drm_clflush_pages(obj_priv->pages, page_count); | 4780 | drm_clflush_pages(obj_priv->pages, page_count); |
4782 | drm_agp_chipset_flush(dev); | 4781 | drm_agp_chipset_flush(dev); |
@@ -4833,11 +4832,11 @@ i915_gem_attach_phys_object(struct drm_device *dev, | |||
4833 | page_count = obj->size / PAGE_SIZE; | 4832 | page_count = obj->size / PAGE_SIZE; |
4834 | 4833 | ||
4835 | for (i = 0; i < page_count; i++) { | 4834 | for (i = 0; i < page_count; i++) { |
4836 | char *src = kmap_atomic(obj_priv->pages[i], KM_USER0); | 4835 | char *src = kmap_atomic(obj_priv->pages[i]); |
4837 | char *dst = obj_priv->phys_obj->handle->vaddr + (i * PAGE_SIZE); | 4836 | char *dst = obj_priv->phys_obj->handle->vaddr + (i * PAGE_SIZE); |
4838 | 4837 | ||
4839 | memcpy(dst, src, PAGE_SIZE); | 4838 | memcpy(dst, src, PAGE_SIZE); |
4840 | kunmap_atomic(src, KM_USER0); | 4839 | kunmap_atomic(src); |
4841 | } | 4840 | } |
4842 | 4841 | ||
4843 | i915_gem_object_put_pages(obj); | 4842 | i915_gem_object_put_pages(obj); |
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 744225ebb4b2..b80010f0c4c9 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c | |||
@@ -456,10 +456,9 @@ i915_error_object_create(struct drm_device *dev, | |||
456 | 456 | ||
457 | local_irq_save(flags); | 457 | local_irq_save(flags); |
458 | s = io_mapping_map_atomic_wc(dev_priv->mm.gtt_mapping, | 458 | s = io_mapping_map_atomic_wc(dev_priv->mm.gtt_mapping, |
459 | reloc_offset, | 459 | reloc_offset); |
460 | KM_IRQ0); | ||
461 | memcpy_fromio(d, s, PAGE_SIZE); | 460 | memcpy_fromio(d, s, PAGE_SIZE); |
462 | io_mapping_unmap_atomic(s, KM_IRQ0); | 461 | io_mapping_unmap_atomic(s); |
463 | local_irq_restore(flags); | 462 | local_irq_restore(flags); |
464 | 463 | ||
465 | dst->pages[page] = d; | 464 | dst->pages[page] = d; |
diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c index 1d306a458be6..3264bbd47e65 100644 --- a/drivers/gpu/drm/i915/intel_overlay.c +++ b/drivers/gpu/drm/i915/intel_overlay.c | |||
@@ -187,8 +187,7 @@ static struct overlay_registers *intel_overlay_map_regs_atomic(struct intel_over | |||
187 | 187 | ||
188 | if (OVERLAY_NONPHYSICAL(overlay->dev)) { | 188 | if (OVERLAY_NONPHYSICAL(overlay->dev)) { |
189 | regs = io_mapping_map_atomic_wc(dev_priv->mm.gtt_mapping, | 189 | regs = io_mapping_map_atomic_wc(dev_priv->mm.gtt_mapping, |
190 | overlay->reg_bo->gtt_offset, | 190 | overlay->reg_bo->gtt_offset); |
191 | KM_USER0); | ||
192 | 191 | ||
193 | if (!regs) { | 192 | if (!regs) { |
194 | DRM_ERROR("failed to map overlay regs in GTT\n"); | 193 | DRM_ERROR("failed to map overlay regs in GTT\n"); |
@@ -203,7 +202,7 @@ static struct overlay_registers *intel_overlay_map_regs_atomic(struct intel_over | |||
203 | static void intel_overlay_unmap_regs_atomic(struct intel_overlay *overlay) | 202 | static void intel_overlay_unmap_regs_atomic(struct intel_overlay *overlay) |
204 | { | 203 | { |
205 | if (OVERLAY_NONPHYSICAL(overlay->dev)) | 204 | if (OVERLAY_NONPHYSICAL(overlay->dev)) |
206 | io_mapping_unmap_atomic(overlay->virt_addr, KM_USER0); | 205 | io_mapping_unmap_atomic(overlay->virt_addr); |
207 | 206 | ||
208 | overlay->virt_addr = NULL; | 207 | overlay->virt_addr = NULL; |
209 | 208 | ||
diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c index 974b0f8ae048..8fa339600fe3 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bios.c +++ b/drivers/gpu/drm/nouveau/nouveau_bios.c | |||
@@ -2167,11 +2167,11 @@ peek_fb(struct drm_device *dev, struct io_mapping *fb, | |||
2167 | 2167 | ||
2168 | if (off < pci_resource_len(dev->pdev, 1)) { | 2168 | if (off < pci_resource_len(dev->pdev, 1)) { |
2169 | uint8_t __iomem *p = | 2169 | uint8_t __iomem *p = |
2170 | io_mapping_map_atomic_wc(fb, off & PAGE_MASK, KM_USER0); | 2170 | io_mapping_map_atomic_wc(fb, off & PAGE_MASK); |
2171 | 2171 | ||
2172 | val = ioread32(p + (off & ~PAGE_MASK)); | 2172 | val = ioread32(p + (off & ~PAGE_MASK)); |
2173 | 2173 | ||
2174 | io_mapping_unmap_atomic(p, KM_USER0); | 2174 | io_mapping_unmap_atomic(p); |
2175 | } | 2175 | } |
2176 | 2176 | ||
2177 | return val; | 2177 | return val; |
@@ -2183,12 +2183,12 @@ poke_fb(struct drm_device *dev, struct io_mapping *fb, | |||
2183 | { | 2183 | { |
2184 | if (off < pci_resource_len(dev->pdev, 1)) { | 2184 | if (off < pci_resource_len(dev->pdev, 1)) { |
2185 | uint8_t __iomem *p = | 2185 | uint8_t __iomem *p = |
2186 | io_mapping_map_atomic_wc(fb, off & PAGE_MASK, KM_USER0); | 2186 | io_mapping_map_atomic_wc(fb, off & PAGE_MASK); |
2187 | 2187 | ||
2188 | iowrite32(val, p + (off & ~PAGE_MASK)); | 2188 | iowrite32(val, p + (off & ~PAGE_MASK)); |
2189 | wmb(); | 2189 | wmb(); |
2190 | 2190 | ||
2191 | io_mapping_unmap_atomic(p, KM_USER0); | 2191 | io_mapping_unmap_atomic(p); |
2192 | } | 2192 | } |
2193 | } | 2193 | } |
2194 | 2194 | ||
diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c index 3451a82adba7..e8a73e65da69 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_util.c +++ b/drivers/gpu/drm/ttm/ttm_bo_util.c | |||
@@ -170,7 +170,7 @@ static int ttm_copy_io_ttm_page(struct ttm_tt *ttm, void *src, | |||
170 | src = (void *)((unsigned long)src + (page << PAGE_SHIFT)); | 170 | src = (void *)((unsigned long)src + (page << PAGE_SHIFT)); |
171 | 171 | ||
172 | #ifdef CONFIG_X86 | 172 | #ifdef CONFIG_X86 |
173 | dst = kmap_atomic_prot(d, KM_USER0, prot); | 173 | dst = kmap_atomic_prot(d, prot); |
174 | #else | 174 | #else |
175 | if (pgprot_val(prot) != pgprot_val(PAGE_KERNEL)) | 175 | if (pgprot_val(prot) != pgprot_val(PAGE_KERNEL)) |
176 | dst = vmap(&d, 1, 0, prot); | 176 | dst = vmap(&d, 1, 0, prot); |
@@ -183,7 +183,7 @@ static int ttm_copy_io_ttm_page(struct ttm_tt *ttm, void *src, | |||
183 | memcpy_fromio(dst, src, PAGE_SIZE); | 183 | memcpy_fromio(dst, src, PAGE_SIZE); |
184 | 184 | ||
185 | #ifdef CONFIG_X86 | 185 | #ifdef CONFIG_X86 |
186 | kunmap_atomic(dst, KM_USER0); | 186 | kunmap_atomic(dst); |
187 | #else | 187 | #else |
188 | if (pgprot_val(prot) != pgprot_val(PAGE_KERNEL)) | 188 | if (pgprot_val(prot) != pgprot_val(PAGE_KERNEL)) |
189 | vunmap(dst); | 189 | vunmap(dst); |
@@ -206,7 +206,7 @@ static int ttm_copy_ttm_io_page(struct ttm_tt *ttm, void *dst, | |||
206 | 206 | ||
207 | dst = (void *)((unsigned long)dst + (page << PAGE_SHIFT)); | 207 | dst = (void *)((unsigned long)dst + (page << PAGE_SHIFT)); |
208 | #ifdef CONFIG_X86 | 208 | #ifdef CONFIG_X86 |
209 | src = kmap_atomic_prot(s, KM_USER0, prot); | 209 | src = kmap_atomic_prot(s, prot); |
210 | #else | 210 | #else |
211 | if (pgprot_val(prot) != pgprot_val(PAGE_KERNEL)) | 211 | if (pgprot_val(prot) != pgprot_val(PAGE_KERNEL)) |
212 | src = vmap(&s, 1, 0, prot); | 212 | src = vmap(&s, 1, 0, prot); |
@@ -219,7 +219,7 @@ static int ttm_copy_ttm_io_page(struct ttm_tt *ttm, void *dst, | |||
219 | memcpy_toio(dst, src, PAGE_SIZE); | 219 | memcpy_toio(dst, src, PAGE_SIZE); |
220 | 220 | ||
221 | #ifdef CONFIG_X86 | 221 | #ifdef CONFIG_X86 |
222 | kunmap_atomic(src, KM_USER0); | 222 | kunmap_atomic(src); |
223 | #else | 223 | #else |
224 | if (pgprot_val(prot) != pgprot_val(PAGE_KERNEL)) | 224 | if (pgprot_val(prot) != pgprot_val(PAGE_KERNEL)) |
225 | vunmap(src); | 225 | vunmap(src); |
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index b4b22576f12a..19c5d3b191f4 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c | |||
@@ -1409,8 +1409,7 @@ static int __init ipoib_init_module(void) | |||
1409 | 1409 | ||
1410 | ipoib_sendq_size = roundup_pow_of_two(ipoib_sendq_size); | 1410 | ipoib_sendq_size = roundup_pow_of_two(ipoib_sendq_size); |
1411 | ipoib_sendq_size = min(ipoib_sendq_size, IPOIB_MAX_QUEUE_SIZE); | 1411 | ipoib_sendq_size = min(ipoib_sendq_size, IPOIB_MAX_QUEUE_SIZE); |
1412 | ipoib_sendq_size = max(ipoib_sendq_size, max(2 * MAX_SEND_CQE, | 1412 | ipoib_sendq_size = max3(ipoib_sendq_size, 2 * MAX_SEND_CQE, IPOIB_MIN_QUEUE_SIZE); |
1413 | IPOIB_MIN_QUEUE_SIZE)); | ||
1414 | #ifdef CONFIG_INFINIBAND_IPOIB_CM | 1413 | #ifdef CONFIG_INFINIBAND_IPOIB_CM |
1415 | ipoib_max_conn_qp = min(ipoib_max_conn_qp, IPOIB_CM_MAX_CONN_QP); | 1414 | ipoib_max_conn_qp = min(ipoib_max_conn_qp, IPOIB_CM_MAX_CONN_QP); |
1416 | #endif | 1415 | #endif |
diff --git a/drivers/macintosh/windfarm_pm121.c b/drivers/macintosh/windfarm_pm121.c index 947d4afa25ca..30e6195e19d4 100644 --- a/drivers/macintosh/windfarm_pm121.c +++ b/drivers/macintosh/windfarm_pm121.c | |||
@@ -482,7 +482,7 @@ static s32 pm121_correct(s32 new_setpoint, | |||
482 | new_min += correction->offset; | 482 | new_min += correction->offset; |
483 | new_min = (new_min >> 16) + min; | 483 | new_min = (new_min >> 16) + min; |
484 | 484 | ||
485 | return max(new_setpoint, max(new_min, 0)); | 485 | return max3(new_setpoint, new_min, 0); |
486 | } | 486 | } |
487 | 487 | ||
488 | static s32 pm121_connect(unsigned int control_id, s32 setpoint) | 488 | static s32 pm121_connect(unsigned int control_id, s32 setpoint) |
diff --git a/drivers/md/dm-snap-persistent.c b/drivers/md/dm-snap-persistent.c index 0b61792a2780..2129cdb115dc 100644 --- a/drivers/md/dm-snap-persistent.c +++ b/drivers/md/dm-snap-persistent.c | |||
@@ -254,7 +254,7 @@ static int chunk_io(struct pstore *ps, void *area, chunk_t chunk, int rw, | |||
254 | * Issue the synchronous I/O from a different thread | 254 | * Issue the synchronous I/O from a different thread |
255 | * to avoid generic_make_request recursion. | 255 | * to avoid generic_make_request recursion. |
256 | */ | 256 | */ |
257 | INIT_WORK_ON_STACK(&req.work, do_metadata); | 257 | INIT_WORK_ONSTACK(&req.work, do_metadata); |
258 | queue_work(ps->metadata_wq, &req.work); | 258 | queue_work(ps->metadata_wq, &req.work); |
259 | flush_workqueue(ps->metadata_wq); | 259 | flush_workqueue(ps->metadata_wq); |
260 | 260 | ||
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 1f69743b12ec..5a74db75f66f 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig | |||
@@ -4,7 +4,6 @@ | |||
4 | 4 | ||
5 | menuconfig MISC_DEVICES | 5 | menuconfig MISC_DEVICES |
6 | bool "Misc devices" | 6 | bool "Misc devices" |
7 | default y | ||
8 | ---help--- | 7 | ---help--- |
9 | Say Y here to get to see options for device drivers from various | 8 | Say Y here to get to see options for device drivers from various |
10 | different categories. This option alone does not add any kernel code. | 9 | different categories. This option alone does not add any kernel code. |
@@ -24,7 +23,8 @@ config AD525X_DPOT | |||
24 | AD5260, AD5262, AD5263, AD5290, AD5291, AD5292, AD5293, | 23 | AD5260, AD5262, AD5263, AD5290, AD5291, AD5292, AD5293, |
25 | AD7376, AD8400, AD8402, AD8403, ADN2850, AD5241, AD5242, | 24 | AD7376, AD8400, AD8402, AD8403, ADN2850, AD5241, AD5242, |
26 | AD5243, AD5245, AD5246, AD5247, AD5248, AD5280, AD5282, | 25 | AD5243, AD5245, AD5246, AD5247, AD5248, AD5280, AD5282, |
27 | ADN2860, AD5273, AD5171, AD5170, AD5172, AD5173 | 26 | ADN2860, AD5273, AD5171, AD5170, AD5172, AD5173, AD5270, |
27 | AD5271, AD5272, AD5274 | ||
28 | digital potentiometer chips. | 28 | digital potentiometer chips. |
29 | 29 | ||
30 | See Documentation/misc-devices/ad525x_dpot.txt for the | 30 | See Documentation/misc-devices/ad525x_dpot.txt for the |
@@ -284,6 +284,16 @@ config SGI_GRU_DEBUG | |||
284 | This option enables addition debugging code for the SGI GRU driver. If | 284 | This option enables addition debugging code for the SGI GRU driver. If |
285 | you are unsure, say N. | 285 | you are unsure, say N. |
286 | 286 | ||
287 | config APDS9802ALS | ||
288 | tristate "Medfield Avago APDS9802 ALS Sensor module" | ||
289 | depends on I2C | ||
290 | help | ||
291 | If you say yes here you get support for the ALS APDS9802 ambient | ||
292 | light sensor. | ||
293 | |||
294 | This driver can also be built as a module. If so, the module | ||
295 | will be called apds9802als. | ||
296 | |||
287 | config ISL29003 | 297 | config ISL29003 |
288 | tristate "Intersil ISL29003 ambient light sensor" | 298 | tristate "Intersil ISL29003 ambient light sensor" |
289 | depends on I2C && SYSFS | 299 | depends on I2C && SYSFS |
@@ -294,6 +304,16 @@ config ISL29003 | |||
294 | This driver can also be built as a module. If so, the module | 304 | This driver can also be built as a module. If so, the module |
295 | will be called isl29003. | 305 | will be called isl29003. |
296 | 306 | ||
307 | config ISL29020 | ||
308 | tristate "Intersil ISL29020 ambient light sensor" | ||
309 | depends on I2C | ||
310 | help | ||
311 | If you say yes here you get support for the Intersil ISL29020 | ||
312 | ambient light sensor. | ||
313 | |||
314 | This driver can also be built as a module. If so, the module | ||
315 | will be called isl29020. | ||
316 | |||
297 | config SENSORS_TSL2550 | 317 | config SENSORS_TSL2550 |
298 | tristate "Taos TSL2550 ambient light sensor" | 318 | tristate "Taos TSL2550 ambient light sensor" |
299 | depends on I2C && SYSFS | 319 | depends on I2C && SYSFS |
@@ -314,6 +334,27 @@ config SENSORS_BH1780 | |||
314 | This driver can also be built as a module. If so, the module | 334 | This driver can also be built as a module. If so, the module |
315 | will be called bh1780gli. | 335 | will be called bh1780gli. |
316 | 336 | ||
337 | config SENSORS_BH1770 | ||
338 | tristate "BH1770GLC / SFH7770 combined ALS - Proximity sensor" | ||
339 | depends on I2C | ||
340 | ---help--- | ||
341 | Say Y here if you want to build a driver for BH1770GLC (ROHM) or | ||
342 | SFH7770 (Osram) combined ambient light and proximity sensor chip. | ||
343 | |||
344 | To compile this driver as a module, choose M here: the | ||
345 | module will be called bh1770glc. If unsure, say N here. | ||
346 | |||
347 | config SENSORS_APDS990X | ||
348 | tristate "APDS990X combined als and proximity sensors" | ||
349 | depends on I2C | ||
350 | default n | ||
351 | ---help--- | ||
352 | Say Y here if you want to build a driver for Avago APDS990x | ||
353 | combined ambient light and proximity sensor chip. | ||
354 | |||
355 | To compile this driver as a module, choose M here: the | ||
356 | module will be called apds990x. If unsure, say N here. | ||
357 | |||
317 | config HMC6352 | 358 | config HMC6352 |
318 | tristate "Honeywell HMC6352 compass" | 359 | tristate "Honeywell HMC6352 compass" |
319 | depends on I2C | 360 | depends on I2C |
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 9f2986b4da2f..4be5c6fc5ef4 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile | |||
@@ -16,6 +16,8 @@ obj-$(CONFIG_TIFM_CORE) += tifm_core.o | |||
16 | obj-$(CONFIG_TIFM_7XX1) += tifm_7xx1.o | 16 | obj-$(CONFIG_TIFM_7XX1) += tifm_7xx1.o |
17 | obj-$(CONFIG_PHANTOM) += phantom.o | 17 | obj-$(CONFIG_PHANTOM) += phantom.o |
18 | obj-$(CONFIG_SENSORS_BH1780) += bh1780gli.o | 18 | obj-$(CONFIG_SENSORS_BH1780) += bh1780gli.o |
19 | obj-$(CONFIG_SENSORS_BH1770) += bh1770glc.o | ||
20 | obj-$(CONFIG_SENSORS_APDS990X) += apds990x.o | ||
19 | obj-$(CONFIG_SGI_IOC4) += ioc4.o | 21 | obj-$(CONFIG_SGI_IOC4) += ioc4.o |
20 | obj-$(CONFIG_ENCLOSURE_SERVICES) += enclosure.o | 22 | obj-$(CONFIG_ENCLOSURE_SERVICES) += enclosure.o |
21 | obj-$(CONFIG_KGDB_TESTS) += kgdbts.o | 23 | obj-$(CONFIG_KGDB_TESTS) += kgdbts.o |
@@ -23,7 +25,9 @@ obj-$(CONFIG_SGI_XP) += sgi-xp/ | |||
23 | obj-$(CONFIG_SGI_GRU) += sgi-gru/ | 25 | obj-$(CONFIG_SGI_GRU) += sgi-gru/ |
24 | obj-$(CONFIG_CS5535_MFGPT) += cs5535-mfgpt.o | 26 | obj-$(CONFIG_CS5535_MFGPT) += cs5535-mfgpt.o |
25 | obj-$(CONFIG_HP_ILO) += hpilo.o | 27 | obj-$(CONFIG_HP_ILO) += hpilo.o |
28 | obj-$(CONFIG_APDS9802ALS) += apds9802als.o | ||
26 | obj-$(CONFIG_ISL29003) += isl29003.o | 29 | obj-$(CONFIG_ISL29003) += isl29003.o |
30 | obj-$(CONFIG_ISL29020) += isl29020.o | ||
27 | obj-$(CONFIG_SENSORS_TSL2550) += tsl2550.o | 31 | obj-$(CONFIG_SENSORS_TSL2550) += tsl2550.o |
28 | obj-$(CONFIG_EP93XX_PWM) += ep93xx_pwm.o | 32 | obj-$(CONFIG_EP93XX_PWM) += ep93xx_pwm.o |
29 | obj-$(CONFIG_DS1682) += ds1682.o | 33 | obj-$(CONFIG_DS1682) += ds1682.o |
diff --git a/drivers/misc/ad525x_dpot-i2c.c b/drivers/misc/ad525x_dpot-i2c.c index 374352af7979..4ff73c215746 100644 --- a/drivers/misc/ad525x_dpot-i2c.c +++ b/drivers/misc/ad525x_dpot-i2c.c | |||
@@ -102,6 +102,8 @@ static const struct i2c_device_id ad_dpot_id[] = { | |||
102 | {"ad5170", AD5170_ID}, | 102 | {"ad5170", AD5170_ID}, |
103 | {"ad5172", AD5172_ID}, | 103 | {"ad5172", AD5172_ID}, |
104 | {"ad5173", AD5173_ID}, | 104 | {"ad5173", AD5173_ID}, |
105 | {"ad5272", AD5272_ID}, | ||
106 | {"ad5274", AD5274_ID}, | ||
105 | {} | 107 | {} |
106 | }; | 108 | }; |
107 | MODULE_DEVICE_TABLE(i2c, ad_dpot_id); | 109 | MODULE_DEVICE_TABLE(i2c, ad_dpot_id); |
diff --git a/drivers/misc/ad525x_dpot-spi.c b/drivers/misc/ad525x_dpot-spi.c index b8c6df9c8437..7f9a55afe05d 100644 --- a/drivers/misc/ad525x_dpot-spi.c +++ b/drivers/misc/ad525x_dpot-spi.c | |||
@@ -38,6 +38,8 @@ static const struct ad_dpot_id ad_dpot_spi_devlist[] = { | |||
38 | {.name = "ad8402", .devid = AD8402_ID}, | 38 | {.name = "ad8402", .devid = AD8402_ID}, |
39 | {.name = "ad8403", .devid = AD8403_ID}, | 39 | {.name = "ad8403", .devid = AD8403_ID}, |
40 | {.name = "adn2850", .devid = ADN2850_ID}, | 40 | {.name = "adn2850", .devid = ADN2850_ID}, |
41 | {.name = "ad5270", .devid = AD5270_ID}, | ||
42 | {.name = "ad5271", .devid = AD5271_ID}, | ||
41 | {} | 43 | {} |
42 | }; | 44 | }; |
43 | 45 | ||
@@ -53,13 +55,13 @@ static int write8(void *client, u8 val) | |||
53 | static int write16(void *client, u8 reg, u8 val) | 55 | static int write16(void *client, u8 reg, u8 val) |
54 | { | 56 | { |
55 | u8 data[2] = {reg, val}; | 57 | u8 data[2] = {reg, val}; |
56 | return spi_write(client, data, 1); | 58 | return spi_write(client, data, 2); |
57 | } | 59 | } |
58 | 60 | ||
59 | static int write24(void *client, u8 reg, u16 val) | 61 | static int write24(void *client, u8 reg, u16 val) |
60 | { | 62 | { |
61 | u8 data[3] = {reg, val >> 8, val}; | 63 | u8 data[3] = {reg, val >> 8, val}; |
62 | return spi_write(client, data, 1); | 64 | return spi_write(client, data, 3); |
63 | } | 65 | } |
64 | 66 | ||
65 | static int read8(void *client) | 67 | static int read8(void *client) |
diff --git a/drivers/misc/ad525x_dpot.c b/drivers/misc/ad525x_dpot.c index 5e6fa8449e8b..7cb911028d09 100644 --- a/drivers/misc/ad525x_dpot.c +++ b/drivers/misc/ad525x_dpot.c | |||
@@ -29,9 +29,9 @@ | |||
29 | * AD5262 2 256 20, 50, 200 | 29 | * AD5262 2 256 20, 50, 200 |
30 | * AD5263 4 256 20, 50, 200 | 30 | * AD5263 4 256 20, 50, 200 |
31 | * AD5290 1 256 10, 50, 100 | 31 | * AD5290 1 256 10, 50, 100 |
32 | * AD5291 1 256 20 | 32 | * AD5291 1 256 20, 50, 100 (20-TP) |
33 | * AD5292 1 1024 20 | 33 | * AD5292 1 1024 20, 50, 100 (20-TP) |
34 | * AD5293 1 1024 20 | 34 | * AD5293 1 1024 20, 50, 100 |
35 | * AD7376 1 128 10, 50, 100, 1M | 35 | * AD7376 1 128 10, 50, 100, 1M |
36 | * AD8400 1 256 1, 10, 50, 100 | 36 | * AD8400 1 256 1, 10, 50, 100 |
37 | * AD8402 2 256 1, 10, 50, 100 | 37 | * AD8402 2 256 1, 10, 50, 100 |
@@ -52,6 +52,10 @@ | |||
52 | * AD5170 1 256 2.5, 10, 50, 100 (OTP) | 52 | * AD5170 1 256 2.5, 10, 50, 100 (OTP) |
53 | * AD5172 2 256 2.5, 10, 50, 100 (OTP) | 53 | * AD5172 2 256 2.5, 10, 50, 100 (OTP) |
54 | * AD5173 2 256 2.5, 10, 50, 100 (OTP) | 54 | * AD5173 2 256 2.5, 10, 50, 100 (OTP) |
55 | * AD5270 1 1024 20, 50, 100 (50-TP) | ||
56 | * AD5271 1 256 20, 50, 100 (50-TP) | ||
57 | * AD5272 1 1024 20, 50, 100 (50-TP) | ||
58 | * AD5274 1 256 20, 50, 100 (50-TP) | ||
55 | * | 59 | * |
56 | * See Documentation/misc-devices/ad525x_dpot.txt for more info. | 60 | * See Documentation/misc-devices/ad525x_dpot.txt for more info. |
57 | * | 61 | * |
@@ -126,18 +130,38 @@ static inline int dpot_write_r8d16(struct dpot_data *dpot, u8 reg, u16 val) | |||
126 | static s32 dpot_read_spi(struct dpot_data *dpot, u8 reg) | 130 | static s32 dpot_read_spi(struct dpot_data *dpot, u8 reg) |
127 | { | 131 | { |
128 | unsigned ctrl = 0; | 132 | unsigned ctrl = 0; |
133 | int value; | ||
129 | 134 | ||
130 | if (!(reg & (DPOT_ADDR_EEPROM | DPOT_ADDR_CMD))) { | 135 | if (!(reg & (DPOT_ADDR_EEPROM | DPOT_ADDR_CMD))) { |
131 | 136 | ||
132 | if (dpot->feat & F_RDACS_WONLY) | 137 | if (dpot->feat & F_RDACS_WONLY) |
133 | return dpot->rdac_cache[reg & DPOT_RDAC_MASK]; | 138 | return dpot->rdac_cache[reg & DPOT_RDAC_MASK]; |
134 | |||
135 | if (dpot->uid == DPOT_UID(AD5291_ID) || | 139 | if (dpot->uid == DPOT_UID(AD5291_ID) || |
136 | dpot->uid == DPOT_UID(AD5292_ID) || | 140 | dpot->uid == DPOT_UID(AD5292_ID) || |
137 | dpot->uid == DPOT_UID(AD5293_ID)) | 141 | dpot->uid == DPOT_UID(AD5293_ID)) { |
138 | return dpot_read_r8d8(dpot, | 142 | |
143 | value = dpot_read_r8d8(dpot, | ||
139 | DPOT_AD5291_READ_RDAC << 2); | 144 | DPOT_AD5291_READ_RDAC << 2); |
140 | 145 | ||
146 | if (dpot->uid == DPOT_UID(AD5291_ID)) | ||
147 | value = value >> 2; | ||
148 | |||
149 | return value; | ||
150 | } else if (dpot->uid == DPOT_UID(AD5270_ID) || | ||
151 | dpot->uid == DPOT_UID(AD5271_ID)) { | ||
152 | |||
153 | value = dpot_read_r8d8(dpot, | ||
154 | DPOT_AD5270_1_2_4_READ_RDAC << 2); | ||
155 | |||
156 | if (value < 0) | ||
157 | return value; | ||
158 | |||
159 | if (dpot->uid == DPOT_UID(AD5271_ID)) | ||
160 | value = value >> 2; | ||
161 | |||
162 | return value; | ||
163 | } | ||
164 | |||
141 | ctrl = DPOT_SPI_READ_RDAC; | 165 | ctrl = DPOT_SPI_READ_RDAC; |
142 | } else if (reg & DPOT_ADDR_EEPROM) { | 166 | } else if (reg & DPOT_ADDR_EEPROM) { |
143 | ctrl = DPOT_SPI_READ_EEPROM; | 167 | ctrl = DPOT_SPI_READ_EEPROM; |
@@ -153,6 +177,7 @@ static s32 dpot_read_spi(struct dpot_data *dpot, u8 reg) | |||
153 | 177 | ||
154 | static s32 dpot_read_i2c(struct dpot_data *dpot, u8 reg) | 178 | static s32 dpot_read_i2c(struct dpot_data *dpot, u8 reg) |
155 | { | 179 | { |
180 | int value; | ||
156 | unsigned ctrl = 0; | 181 | unsigned ctrl = 0; |
157 | switch (dpot->uid) { | 182 | switch (dpot->uid) { |
158 | case DPOT_UID(AD5246_ID): | 183 | case DPOT_UID(AD5246_ID): |
@@ -166,7 +191,7 @@ static s32 dpot_read_i2c(struct dpot_data *dpot, u8 reg) | |||
166 | case DPOT_UID(AD5280_ID): | 191 | case DPOT_UID(AD5280_ID): |
167 | case DPOT_UID(AD5282_ID): | 192 | case DPOT_UID(AD5282_ID): |
168 | ctrl = ((reg & DPOT_RDAC_MASK) == DPOT_RDAC0) ? | 193 | ctrl = ((reg & DPOT_RDAC_MASK) == DPOT_RDAC0) ? |
169 | 0 : DPOT_AD5291_RDAC_AB; | 194 | 0 : DPOT_AD5282_RDAC_AB; |
170 | return dpot_read_r8d8(dpot, ctrl); | 195 | return dpot_read_r8d8(dpot, ctrl); |
171 | case DPOT_UID(AD5170_ID): | 196 | case DPOT_UID(AD5170_ID): |
172 | case DPOT_UID(AD5171_ID): | 197 | case DPOT_UID(AD5171_ID): |
@@ -175,8 +200,27 @@ static s32 dpot_read_i2c(struct dpot_data *dpot, u8 reg) | |||
175 | case DPOT_UID(AD5172_ID): | 200 | case DPOT_UID(AD5172_ID): |
176 | case DPOT_UID(AD5173_ID): | 201 | case DPOT_UID(AD5173_ID): |
177 | ctrl = ((reg & DPOT_RDAC_MASK) == DPOT_RDAC0) ? | 202 | ctrl = ((reg & DPOT_RDAC_MASK) == DPOT_RDAC0) ? |
178 | 0 : DPOT_AD5272_3_A0; | 203 | 0 : DPOT_AD5172_3_A0; |
179 | return dpot_read_r8d8(dpot, ctrl); | 204 | return dpot_read_r8d8(dpot, ctrl); |
205 | case DPOT_UID(AD5272_ID): | ||
206 | case DPOT_UID(AD5274_ID): | ||
207 | dpot_write_r8d8(dpot, | ||
208 | (DPOT_AD5270_1_2_4_READ_RDAC << 2), 0); | ||
209 | |||
210 | value = dpot_read_r8d16(dpot, | ||
211 | DPOT_AD5270_1_2_4_RDAC << 2); | ||
212 | |||
213 | if (value < 0) | ||
214 | return value; | ||
215 | /* | ||
216 | * AD5272/AD5274 returns high byte first, however | ||
217 | * underling smbus expects low byte first. | ||
218 | */ | ||
219 | value = swab16(value); | ||
220 | |||
221 | if (dpot->uid == DPOT_UID(AD5271_ID)) | ||
222 | value = value >> 2; | ||
223 | return value; | ||
180 | default: | 224 | default: |
181 | if ((reg & DPOT_REG_TOL) || (dpot->max_pos > 256)) | 225 | if ((reg & DPOT_REG_TOL) || (dpot->max_pos > 256)) |
182 | return dpot_read_r8d16(dpot, (reg & 0xF8) | | 226 | return dpot_read_r8d16(dpot, (reg & 0xF8) | |
@@ -198,7 +242,7 @@ static s32 dpot_write_spi(struct dpot_data *dpot, u8 reg, u16 value) | |||
198 | { | 242 | { |
199 | unsigned val = 0; | 243 | unsigned val = 0; |
200 | 244 | ||
201 | if (!(reg & (DPOT_ADDR_EEPROM | DPOT_ADDR_CMD))) { | 245 | if (!(reg & (DPOT_ADDR_EEPROM | DPOT_ADDR_CMD | DPOT_ADDR_OTP))) { |
202 | if (dpot->feat & F_RDACS_WONLY) | 246 | if (dpot->feat & F_RDACS_WONLY) |
203 | dpot->rdac_cache[reg & DPOT_RDAC_MASK] = value; | 247 | dpot->rdac_cache[reg & DPOT_RDAC_MASK] = value; |
204 | 248 | ||
@@ -219,11 +263,30 @@ static s32 dpot_write_spi(struct dpot_data *dpot, u8 reg, u16 value) | |||
219 | } else { | 263 | } else { |
220 | if (dpot->uid == DPOT_UID(AD5291_ID) || | 264 | if (dpot->uid == DPOT_UID(AD5291_ID) || |
221 | dpot->uid == DPOT_UID(AD5292_ID) || | 265 | dpot->uid == DPOT_UID(AD5292_ID) || |
222 | dpot->uid == DPOT_UID(AD5293_ID)) | 266 | dpot->uid == DPOT_UID(AD5293_ID)) { |
267 | |||
268 | dpot_write_r8d8(dpot, DPOT_AD5291_CTRLREG << 2, | ||
269 | DPOT_AD5291_UNLOCK_CMD); | ||
270 | |||
271 | if (dpot->uid == DPOT_UID(AD5291_ID)) | ||
272 | value = value << 2; | ||
273 | |||
223 | return dpot_write_r8d8(dpot, | 274 | return dpot_write_r8d8(dpot, |
224 | (DPOT_AD5291_RDAC << 2) | | 275 | (DPOT_AD5291_RDAC << 2) | |
225 | (value >> 8), value & 0xFF); | 276 | (value >> 8), value & 0xFF); |
277 | } else if (dpot->uid == DPOT_UID(AD5270_ID) || | ||
278 | dpot->uid == DPOT_UID(AD5271_ID)) { | ||
279 | dpot_write_r8d8(dpot, | ||
280 | DPOT_AD5270_1_2_4_CTRLREG << 2, | ||
281 | DPOT_AD5270_1_2_4_UNLOCK_CMD); | ||
282 | |||
283 | if (dpot->uid == DPOT_UID(AD5271_ID)) | ||
284 | value = value << 2; | ||
226 | 285 | ||
286 | return dpot_write_r8d8(dpot, | ||
287 | (DPOT_AD5270_1_2_4_RDAC << 2) | | ||
288 | (value >> 8), value & 0xFF); | ||
289 | } | ||
227 | val = DPOT_SPI_RDAC | (reg & DPOT_RDAC_MASK); | 290 | val = DPOT_SPI_RDAC | (reg & DPOT_RDAC_MASK); |
228 | } | 291 | } |
229 | } else if (reg & DPOT_ADDR_EEPROM) { | 292 | } else if (reg & DPOT_ADDR_EEPROM) { |
@@ -243,6 +306,16 @@ static s32 dpot_write_spi(struct dpot_data *dpot, u8 reg, u16 value) | |||
243 | val = DPOT_SPI_INC_ALL; | 306 | val = DPOT_SPI_INC_ALL; |
244 | break; | 307 | break; |
245 | } | 308 | } |
309 | } else if (reg & DPOT_ADDR_OTP) { | ||
310 | if (dpot->uid == DPOT_UID(AD5291_ID) || | ||
311 | dpot->uid == DPOT_UID(AD5292_ID)) { | ||
312 | return dpot_write_r8d8(dpot, | ||
313 | DPOT_AD5291_STORE_XTPM << 2, 0); | ||
314 | } else if (dpot->uid == DPOT_UID(AD5270_ID) || | ||
315 | dpot->uid == DPOT_UID(AD5271_ID)) { | ||
316 | return dpot_write_r8d8(dpot, | ||
317 | DPOT_AD5270_1_2_4_STORE_XTPM << 2, 0); | ||
318 | } | ||
246 | } else | 319 | } else |
247 | BUG(); | 320 | BUG(); |
248 | 321 | ||
@@ -273,7 +346,7 @@ static s32 dpot_write_i2c(struct dpot_data *dpot, u8 reg, u16 value) | |||
273 | case DPOT_UID(AD5280_ID): | 346 | case DPOT_UID(AD5280_ID): |
274 | case DPOT_UID(AD5282_ID): | 347 | case DPOT_UID(AD5282_ID): |
275 | ctrl = ((reg & DPOT_RDAC_MASK) == DPOT_RDAC0) ? | 348 | ctrl = ((reg & DPOT_RDAC_MASK) == DPOT_RDAC0) ? |
276 | 0 : DPOT_AD5291_RDAC_AB; | 349 | 0 : DPOT_AD5282_RDAC_AB; |
277 | return dpot_write_r8d8(dpot, ctrl, value); | 350 | return dpot_write_r8d8(dpot, ctrl, value); |
278 | break; | 351 | break; |
279 | case DPOT_UID(AD5171_ID): | 352 | case DPOT_UID(AD5171_ID): |
@@ -289,12 +362,12 @@ static s32 dpot_write_i2c(struct dpot_data *dpot, u8 reg, u16 value) | |||
289 | case DPOT_UID(AD5172_ID): | 362 | case DPOT_UID(AD5172_ID): |
290 | case DPOT_UID(AD5173_ID): | 363 | case DPOT_UID(AD5173_ID): |
291 | ctrl = ((reg & DPOT_RDAC_MASK) == DPOT_RDAC0) ? | 364 | ctrl = ((reg & DPOT_RDAC_MASK) == DPOT_RDAC0) ? |
292 | 0 : DPOT_AD5272_3_A0; | 365 | 0 : DPOT_AD5172_3_A0; |
293 | if (reg & DPOT_ADDR_OTP) { | 366 | if (reg & DPOT_ADDR_OTP) { |
294 | tmp = dpot_read_r8d16(dpot, ctrl); | 367 | tmp = dpot_read_r8d16(dpot, ctrl); |
295 | if (tmp >> 14) /* Ready to Program? */ | 368 | if (tmp >> 14) /* Ready to Program? */ |
296 | return -EFAULT; | 369 | return -EFAULT; |
297 | ctrl |= DPOT_AD5270_2_3_FUSE; | 370 | ctrl |= DPOT_AD5170_2_3_FUSE; |
298 | } | 371 | } |
299 | return dpot_write_r8d8(dpot, ctrl, value); | 372 | return dpot_write_r8d8(dpot, ctrl, value); |
300 | break; | 373 | break; |
@@ -303,10 +376,25 @@ static s32 dpot_write_i2c(struct dpot_data *dpot, u8 reg, u16 value) | |||
303 | tmp = dpot_read_r8d16(dpot, tmp); | 376 | tmp = dpot_read_r8d16(dpot, tmp); |
304 | if (tmp >> 14) /* Ready to Program? */ | 377 | if (tmp >> 14) /* Ready to Program? */ |
305 | return -EFAULT; | 378 | return -EFAULT; |
306 | ctrl = DPOT_AD5270_2_3_FUSE; | 379 | ctrl = DPOT_AD5170_2_3_FUSE; |
307 | } | 380 | } |
308 | return dpot_write_r8d8(dpot, ctrl, value); | 381 | return dpot_write_r8d8(dpot, ctrl, value); |
309 | break; | 382 | break; |
383 | case DPOT_UID(AD5272_ID): | ||
384 | case DPOT_UID(AD5274_ID): | ||
385 | dpot_write_r8d8(dpot, DPOT_AD5270_1_2_4_CTRLREG << 2, | ||
386 | DPOT_AD5270_1_2_4_UNLOCK_CMD); | ||
387 | |||
388 | if (reg & DPOT_ADDR_OTP) | ||
389 | return dpot_write_r8d8(dpot, | ||
390 | DPOT_AD5270_1_2_4_STORE_XTPM << 2, 0); | ||
391 | |||
392 | if (dpot->uid == DPOT_UID(AD5274_ID)) | ||
393 | value = value << 2; | ||
394 | |||
395 | return dpot_write_r8d8(dpot, (DPOT_AD5270_1_2_4_RDAC << 2) | | ||
396 | (value >> 8), value & 0xFF); | ||
397 | break; | ||
310 | default: | 398 | default: |
311 | if (reg & DPOT_ADDR_CMD) | 399 | if (reg & DPOT_ADDR_CMD) |
312 | return dpot_write_d8(dpot, reg); | 400 | return dpot_write_d8(dpot, reg); |
@@ -320,7 +408,6 @@ static s32 dpot_write_i2c(struct dpot_data *dpot, u8 reg, u16 value) | |||
320 | } | 408 | } |
321 | } | 409 | } |
322 | 410 | ||
323 | |||
324 | static s32 dpot_write(struct dpot_data *dpot, u8 reg, u16 value) | 411 | static s32 dpot_write(struct dpot_data *dpot, u8 reg, u16 value) |
325 | { | 412 | { |
326 | if (dpot->feat & F_SPI) | 413 | if (dpot->feat & F_SPI) |
diff --git a/drivers/misc/ad525x_dpot.h b/drivers/misc/ad525x_dpot.h index 78b89fd2e2fd..a662f5987b68 100644 --- a/drivers/misc/ad525x_dpot.h +++ b/drivers/misc/ad525x_dpot.h | |||
@@ -47,9 +47,9 @@ enum dpot_devid { | |||
47 | AD5258_ID = DPOT_CONF(F_RDACS_RW_TOL, BRDAC0, 6, 0), /* I2C */ | 47 | AD5258_ID = DPOT_CONF(F_RDACS_RW_TOL, BRDAC0, 6, 0), /* I2C */ |
48 | AD5259_ID = DPOT_CONF(F_RDACS_RW_TOL, BRDAC0, 8, 1), | 48 | AD5259_ID = DPOT_CONF(F_RDACS_RW_TOL, BRDAC0, 8, 1), |
49 | AD5251_ID = DPOT_CONF(F_RDACS_RW_TOL | F_CMD_INC, | 49 | AD5251_ID = DPOT_CONF(F_RDACS_RW_TOL | F_CMD_INC, |
50 | BRDAC0 | BRDAC3, 6, 2), | 50 | BRDAC1 | BRDAC3, 6, 2), |
51 | AD5252_ID = DPOT_CONF(F_RDACS_RW_TOL | F_CMD_INC, | 51 | AD5252_ID = DPOT_CONF(F_RDACS_RW_TOL | F_CMD_INC, |
52 | BRDAC0 | BRDAC3, 8, 3), | 52 | BRDAC1 | BRDAC3, 8, 3), |
53 | AD5253_ID = DPOT_CONF(F_RDACS_RW_TOL | F_CMD_INC, | 53 | AD5253_ID = DPOT_CONF(F_RDACS_RW_TOL | F_CMD_INC, |
54 | BRDAC0 | BRDAC1 | BRDAC2 | BRDAC3, 6, 4), | 54 | BRDAC0 | BRDAC1 | BRDAC2 | BRDAC3, 6, 4), |
55 | AD5254_ID = DPOT_CONF(F_RDACS_RW_TOL | F_CMD_INC, | 55 | AD5254_ID = DPOT_CONF(F_RDACS_RW_TOL | F_CMD_INC, |
@@ -93,8 +93,10 @@ enum dpot_devid { | |||
93 | BRDAC0 | BRDAC1 | BRDAC2 | BRDAC3, 8, 23), | 93 | BRDAC0 | BRDAC1 | BRDAC2 | BRDAC3, 8, 23), |
94 | AD5290_ID = DPOT_CONF(F_RDACS_WONLY | F_AD_APPDATA | F_SPI_8BIT, | 94 | AD5290_ID = DPOT_CONF(F_RDACS_WONLY | F_AD_APPDATA | F_SPI_8BIT, |
95 | BRDAC0, 8, 24), | 95 | BRDAC0, 8, 24), |
96 | AD5291_ID = DPOT_CONF(F_RDACS_RW | F_SPI_16BIT, BRDAC0, 8, 25), | 96 | AD5291_ID = DPOT_CONF(F_RDACS_RW | F_SPI_16BIT | F_CMD_OTP, |
97 | AD5292_ID = DPOT_CONF(F_RDACS_RW | F_SPI_16BIT, BRDAC0, 10, 26), | 97 | BRDAC0, 8, 25), |
98 | AD5292_ID = DPOT_CONF(F_RDACS_RW | F_SPI_16BIT | F_CMD_OTP, | ||
99 | BRDAC0, 10, 26), | ||
98 | AD5293_ID = DPOT_CONF(F_RDACS_RW | F_SPI_16BIT, BRDAC0, 10, 27), | 100 | AD5293_ID = DPOT_CONF(F_RDACS_RW | F_SPI_16BIT, BRDAC0, 10, 27), |
99 | AD7376_ID = DPOT_CONF(F_RDACS_WONLY | F_AD_APPDATA | F_SPI_8BIT, | 101 | AD7376_ID = DPOT_CONF(F_RDACS_WONLY | F_AD_APPDATA | F_SPI_8BIT, |
100 | BRDAC0, 7, 28), | 102 | BRDAC0, 7, 28), |
@@ -122,6 +124,12 @@ enum dpot_devid { | |||
122 | AD5170_ID = DPOT_CONF(F_RDACS_RW | F_CMD_OTP, BRDAC0, 8, 45), | 124 | AD5170_ID = DPOT_CONF(F_RDACS_RW | F_CMD_OTP, BRDAC0, 8, 45), |
123 | AD5172_ID = DPOT_CONF(F_RDACS_RW | F_CMD_OTP, BRDAC0 | BRDAC1, 8, 46), | 125 | AD5172_ID = DPOT_CONF(F_RDACS_RW | F_CMD_OTP, BRDAC0 | BRDAC1, 8, 46), |
124 | AD5173_ID = DPOT_CONF(F_RDACS_RW | F_CMD_OTP, BRDAC0 | BRDAC1, 8, 47), | 126 | AD5173_ID = DPOT_CONF(F_RDACS_RW | F_CMD_OTP, BRDAC0 | BRDAC1, 8, 47), |
127 | AD5270_ID = DPOT_CONF(F_RDACS_RW | F_CMD_OTP | F_SPI_16BIT, | ||
128 | BRDAC0, 10, 48), | ||
129 | AD5271_ID = DPOT_CONF(F_RDACS_RW | F_CMD_OTP | F_SPI_16BIT, | ||
130 | BRDAC0, 8, 49), | ||
131 | AD5272_ID = DPOT_CONF(F_RDACS_RW | F_CMD_OTP, BRDAC0, 10, 50), | ||
132 | AD5274_ID = DPOT_CONF(F_RDACS_RW | F_CMD_OTP, BRDAC0, 8, 51), | ||
125 | }; | 133 | }; |
126 | 134 | ||
127 | #define DPOT_RDAC0 0 | 135 | #define DPOT_RDAC0 0 |
@@ -165,15 +173,24 @@ enum dpot_devid { | |||
165 | /* AD5291/2/3 use special commands */ | 173 | /* AD5291/2/3 use special commands */ |
166 | #define DPOT_AD5291_RDAC 0x01 | 174 | #define DPOT_AD5291_RDAC 0x01 |
167 | #define DPOT_AD5291_READ_RDAC 0x02 | 175 | #define DPOT_AD5291_READ_RDAC 0x02 |
176 | #define DPOT_AD5291_STORE_XTPM 0x03 | ||
177 | #define DPOT_AD5291_CTRLREG 0x06 | ||
178 | #define DPOT_AD5291_UNLOCK_CMD 0x03 | ||
168 | 179 | ||
169 | /* AD524x use special commands */ | 180 | /* AD5270/1/2/4 use special commands */ |
170 | #define DPOT_AD5291_RDAC_AB 0x80 | 181 | #define DPOT_AD5270_1_2_4_RDAC 0x01 |
182 | #define DPOT_AD5270_1_2_4_READ_RDAC 0x02 | ||
183 | #define DPOT_AD5270_1_2_4_STORE_XTPM 0x03 | ||
184 | #define DPOT_AD5270_1_2_4_CTRLREG 0x07 | ||
185 | #define DPOT_AD5270_1_2_4_UNLOCK_CMD 0x03 | ||
186 | |||
187 | #define DPOT_AD5282_RDAC_AB 0x80 | ||
171 | 188 | ||
172 | #define DPOT_AD5273_FUSE 0x80 | 189 | #define DPOT_AD5273_FUSE 0x80 |
173 | #define DPOT_AD5270_2_3_FUSE 0x20 | 190 | #define DPOT_AD5170_2_3_FUSE 0x20 |
174 | #define DPOT_AD5270_2_3_OW 0x08 | 191 | #define DPOT_AD5170_2_3_OW 0x08 |
175 | #define DPOT_AD5272_3_A0 0x08 | 192 | #define DPOT_AD5172_3_A0 0x08 |
176 | #define DPOT_AD5270_2FUSE 0x80 | 193 | #define DPOT_AD5170_2FUSE 0x80 |
177 | 194 | ||
178 | struct dpot_data; | 195 | struct dpot_data; |
179 | 196 | ||
diff --git a/drivers/misc/apds9802als.c b/drivers/misc/apds9802als.c new file mode 100644 index 000000000000..f9b91ba8900c --- /dev/null +++ b/drivers/misc/apds9802als.c | |||
@@ -0,0 +1,347 @@ | |||
1 | /* | ||
2 | * apds9802als.c - apds9802 ALS Driver | ||
3 | * | ||
4 | * Copyright (C) 2009 Intel Corp | ||
5 | * | ||
6 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; version 2 of the License. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but | ||
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License along | ||
18 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
19 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. | ||
20 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
21 | * | ||
22 | */ | ||
23 | |||
24 | #include <linux/module.h> | ||
25 | #include <linux/init.h> | ||
26 | #include <linux/slab.h> | ||
27 | #include <linux/i2c.h> | ||
28 | #include <linux/err.h> | ||
29 | #include <linux/delay.h> | ||
30 | #include <linux/mutex.h> | ||
31 | #include <linux/sysfs.h> | ||
32 | #include <linux/pm_runtime.h> | ||
33 | |||
34 | #define ALS_MIN_RANGE_VAL 1 | ||
35 | #define ALS_MAX_RANGE_VAL 2 | ||
36 | #define POWER_STA_ENABLE 1 | ||
37 | #define POWER_STA_DISABLE 0 | ||
38 | |||
39 | #define DRIVER_NAME "apds9802als" | ||
40 | |||
41 | struct als_data { | ||
42 | struct mutex mutex; | ||
43 | }; | ||
44 | |||
45 | static ssize_t als_sensing_range_show(struct device *dev, | ||
46 | struct device_attribute *attr, char *buf) | ||
47 | { | ||
48 | struct i2c_client *client = to_i2c_client(dev); | ||
49 | int val; | ||
50 | |||
51 | val = i2c_smbus_read_byte_data(client, 0x81); | ||
52 | if (val < 0) | ||
53 | return val; | ||
54 | if (val & 1) | ||
55 | return sprintf(buf, "4095\n"); | ||
56 | else | ||
57 | return sprintf(buf, "65535\n"); | ||
58 | } | ||
59 | |||
60 | static int als_wait_for_data_ready(struct device *dev) | ||
61 | { | ||
62 | struct i2c_client *client = to_i2c_client(dev); | ||
63 | int ret; | ||
64 | int retry = 10; | ||
65 | |||
66 | do { | ||
67 | msleep(30); | ||
68 | ret = i2c_smbus_read_byte_data(client, 0x86); | ||
69 | } while (!(ret & 0x80) && retry--); | ||
70 | |||
71 | if (!retry) { | ||
72 | dev_warn(dev, "timeout waiting for data ready\n"); | ||
73 | return -ETIMEDOUT; | ||
74 | } | ||
75 | |||
76 | return 0; | ||
77 | } | ||
78 | |||
79 | static ssize_t als_lux0_input_data_show(struct device *dev, | ||
80 | struct device_attribute *attr, char *buf) | ||
81 | { | ||
82 | struct i2c_client *client = to_i2c_client(dev); | ||
83 | struct als_data *data = i2c_get_clientdata(client); | ||
84 | int ret_val; | ||
85 | int temp; | ||
86 | |||
87 | /* Protect against parallel reads */ | ||
88 | pm_runtime_get_sync(dev); | ||
89 | mutex_lock(&data->mutex); | ||
90 | |||
91 | /* clear EOC interrupt status */ | ||
92 | i2c_smbus_write_byte(client, 0x40); | ||
93 | /* start measurement */ | ||
94 | temp = i2c_smbus_read_byte_data(client, 0x81); | ||
95 | i2c_smbus_write_byte_data(client, 0x81, temp | 0x08); | ||
96 | |||
97 | ret_val = als_wait_for_data_ready(dev); | ||
98 | if (ret_val < 0) | ||
99 | goto failed; | ||
100 | |||
101 | temp = i2c_smbus_read_byte_data(client, 0x8C); /* LSB data */ | ||
102 | if (temp < 0) { | ||
103 | ret_val = temp; | ||
104 | goto failed; | ||
105 | } | ||
106 | ret_val = i2c_smbus_read_byte_data(client, 0x8D); /* MSB data */ | ||
107 | if (ret_val < 0) | ||
108 | goto failed; | ||
109 | |||
110 | mutex_unlock(&data->mutex); | ||
111 | pm_runtime_put_sync(dev); | ||
112 | |||
113 | temp = (ret_val << 8) | temp; | ||
114 | return sprintf(buf, "%d\n", temp); | ||
115 | failed: | ||
116 | mutex_unlock(&data->mutex); | ||
117 | pm_runtime_put_sync(dev); | ||
118 | return ret_val; | ||
119 | } | ||
120 | |||
121 | static ssize_t als_sensing_range_store(struct device *dev, | ||
122 | struct device_attribute *attr, const char *buf, size_t count) | ||
123 | { | ||
124 | struct i2c_client *client = to_i2c_client(dev); | ||
125 | struct als_data *data = i2c_get_clientdata(client); | ||
126 | unsigned int ret_val; | ||
127 | unsigned long val; | ||
128 | |||
129 | if (strict_strtoul(buf, 10, &val)) | ||
130 | return -EINVAL; | ||
131 | |||
132 | if (val < 4096) | ||
133 | val = 1; | ||
134 | else if (val < 65536) | ||
135 | val = 2; | ||
136 | else | ||
137 | return -ERANGE; | ||
138 | |||
139 | pm_runtime_get_sync(dev); | ||
140 | |||
141 | /* Make sure nobody else reads/modifies/writes 0x81 while we | ||
142 | are active */ | ||
143 | mutex_lock(&data->mutex); | ||
144 | |||
145 | ret_val = i2c_smbus_read_byte_data(client, 0x81); | ||
146 | if (ret_val < 0) | ||
147 | goto fail; | ||
148 | |||
149 | /* Reset the bits before setting them */ | ||
150 | ret_val = ret_val & 0xFA; | ||
151 | |||
152 | if (val == 1) /* Setting detection range up to 4k LUX */ | ||
153 | ret_val = (ret_val | 0x01); | ||
154 | else /* Setting detection range up to 64k LUX*/ | ||
155 | ret_val = (ret_val | 0x00); | ||
156 | |||
157 | ret_val = i2c_smbus_write_byte_data(client, 0x81, ret_val); | ||
158 | |||
159 | if (ret_val >= 0) { | ||
160 | /* All OK */ | ||
161 | mutex_unlock(&data->mutex); | ||
162 | pm_runtime_put_sync(dev); | ||
163 | return count; | ||
164 | } | ||
165 | fail: | ||
166 | mutex_unlock(&data->mutex); | ||
167 | pm_runtime_put_sync(dev); | ||
168 | return ret_val; | ||
169 | } | ||
170 | |||
171 | static int als_set_power_state(struct i2c_client *client, bool on_off) | ||
172 | { | ||
173 | int ret_val; | ||
174 | struct als_data *data = i2c_get_clientdata(client); | ||
175 | |||
176 | mutex_lock(&data->mutex); | ||
177 | ret_val = i2c_smbus_read_byte_data(client, 0x80); | ||
178 | if (ret_val < 0) | ||
179 | goto fail; | ||
180 | if (on_off) | ||
181 | ret_val = ret_val | 0x01; | ||
182 | else | ||
183 | ret_val = ret_val & 0xFE; | ||
184 | ret_val = i2c_smbus_write_byte_data(client, 0x80, ret_val); | ||
185 | fail: | ||
186 | mutex_unlock(&data->mutex); | ||
187 | return ret_val; | ||
188 | } | ||
189 | |||
190 | static DEVICE_ATTR(lux0_sensor_range, S_IRUGO | S_IWUSR, | ||
191 | als_sensing_range_show, als_sensing_range_store); | ||
192 | static DEVICE_ATTR(lux0_input, S_IRUGO, als_lux0_input_data_show, NULL); | ||
193 | |||
194 | static struct attribute *mid_att_als[] = { | ||
195 | &dev_attr_lux0_sensor_range.attr, | ||
196 | &dev_attr_lux0_input.attr, | ||
197 | NULL | ||
198 | }; | ||
199 | |||
200 | static struct attribute_group m_als_gr = { | ||
201 | .name = "apds9802als", | ||
202 | .attrs = mid_att_als | ||
203 | }; | ||
204 | |||
205 | static int als_set_default_config(struct i2c_client *client) | ||
206 | { | ||
207 | int ret_val; | ||
208 | /* Write the command and then switch on */ | ||
209 | ret_val = i2c_smbus_write_byte_data(client, 0x80, 0x01); | ||
210 | if (ret_val < 0) { | ||
211 | dev_err(&client->dev, "failed default switch on write\n"); | ||
212 | return ret_val; | ||
213 | } | ||
214 | /* detection range: 1~64K Lux, maunal measurement */ | ||
215 | ret_val = i2c_smbus_write_byte_data(client, 0x81, 0x08); | ||
216 | if (ret_val < 0) | ||
217 | dev_err(&client->dev, "failed default LUX on write\n"); | ||
218 | |||
219 | /* We always get 0 for the 1st measurement after system power on, | ||
220 | * so make sure it is finished before user asks for data. | ||
221 | */ | ||
222 | als_wait_for_data_ready(&client->dev); | ||
223 | |||
224 | return ret_val; | ||
225 | } | ||
226 | |||
227 | static int apds9802als_probe(struct i2c_client *client, | ||
228 | const struct i2c_device_id *id) | ||
229 | { | ||
230 | int res; | ||
231 | struct als_data *data; | ||
232 | |||
233 | data = kzalloc(sizeof(struct als_data), GFP_KERNEL); | ||
234 | if (data == NULL) { | ||
235 | dev_err(&client->dev, "Memory allocation failed\n"); | ||
236 | return -ENOMEM; | ||
237 | } | ||
238 | i2c_set_clientdata(client, data); | ||
239 | res = sysfs_create_group(&client->dev.kobj, &m_als_gr); | ||
240 | if (res) { | ||
241 | dev_err(&client->dev, "device create file failed\n"); | ||
242 | goto als_error1; | ||
243 | } | ||
244 | dev_info(&client->dev, "ALS chip found\n"); | ||
245 | als_set_default_config(client); | ||
246 | mutex_init(&data->mutex); | ||
247 | |||
248 | pm_runtime_enable(&client->dev); | ||
249 | pm_runtime_get(&client->dev); | ||
250 | pm_runtime_put(&client->dev); | ||
251 | |||
252 | return res; | ||
253 | als_error1: | ||
254 | i2c_set_clientdata(client, NULL); | ||
255 | kfree(data); | ||
256 | return res; | ||
257 | } | ||
258 | |||
259 | static int apds9802als_remove(struct i2c_client *client) | ||
260 | { | ||
261 | struct als_data *data = i2c_get_clientdata(client); | ||
262 | |||
263 | als_set_power_state(client, false); | ||
264 | sysfs_remove_group(&client->dev.kobj, &m_als_gr); | ||
265 | kfree(data); | ||
266 | return 0; | ||
267 | } | ||
268 | |||
269 | #ifdef CONFIG_PM | ||
270 | static int apds9802als_suspend(struct i2c_client *client, pm_message_t mesg) | ||
271 | { | ||
272 | als_set_power_state(client, false); | ||
273 | return 0; | ||
274 | } | ||
275 | |||
276 | static int apds9802als_resume(struct i2c_client *client) | ||
277 | { | ||
278 | als_set_default_config(client); | ||
279 | |||
280 | pm_runtime_get(&client->dev); | ||
281 | pm_runtime_put(&client->dev); | ||
282 | return 0; | ||
283 | } | ||
284 | |||
285 | static int apds9802als_runtime_suspend(struct device *dev) | ||
286 | { | ||
287 | struct i2c_client *client = to_i2c_client(dev); | ||
288 | |||
289 | als_set_power_state(client, false); | ||
290 | return 0; | ||
291 | } | ||
292 | |||
293 | static int apds9802als_runtime_resume(struct device *dev) | ||
294 | { | ||
295 | struct i2c_client *client = to_i2c_client(dev); | ||
296 | |||
297 | als_set_power_state(client, true); | ||
298 | return 0; | ||
299 | } | ||
300 | |||
301 | static const struct dev_pm_ops apds9802als_pm_ops = { | ||
302 | .runtime_suspend = apds9802als_runtime_suspend, | ||
303 | .runtime_resume = apds9802als_runtime_resume, | ||
304 | }; | ||
305 | |||
306 | #define APDS9802ALS_PM_OPS (&apds9802als_pm_ops) | ||
307 | |||
308 | #else /* CONFIG_PM */ | ||
309 | #define apds9802als_suspend NULL | ||
310 | #define apds9802als_resume NULL | ||
311 | #define APDS9802ALS_PM_OPS NULL | ||
312 | #endif /* CONFIG_PM */ | ||
313 | |||
314 | static struct i2c_device_id apds9802als_id[] = { | ||
315 | { DRIVER_NAME, 0 }, | ||
316 | { } | ||
317 | }; | ||
318 | |||
319 | MODULE_DEVICE_TABLE(i2c, apds9802als_id); | ||
320 | |||
321 | static struct i2c_driver apds9802als_driver = { | ||
322 | .driver = { | ||
323 | .name = DRIVER_NAME, | ||
324 | .pm = APDS9802ALS_PM_OPS, | ||
325 | }, | ||
326 | .probe = apds9802als_probe, | ||
327 | .remove = apds9802als_remove, | ||
328 | .suspend = apds9802als_suspend, | ||
329 | .resume = apds9802als_resume, | ||
330 | .id_table = apds9802als_id, | ||
331 | }; | ||
332 | |||
333 | static int __init sensor_apds9802als_init(void) | ||
334 | { | ||
335 | return i2c_add_driver(&apds9802als_driver); | ||
336 | } | ||
337 | |||
338 | static void __exit sensor_apds9802als_exit(void) | ||
339 | { | ||
340 | i2c_del_driver(&apds9802als_driver); | ||
341 | } | ||
342 | module_init(sensor_apds9802als_init); | ||
343 | module_exit(sensor_apds9802als_exit); | ||
344 | |||
345 | MODULE_AUTHOR("Anantha Narayanan <Anantha.Narayanan@intel.com"); | ||
346 | MODULE_DESCRIPTION("Avago apds9802als ALS Driver"); | ||
347 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/misc/apds990x.c b/drivers/misc/apds990x.c new file mode 100644 index 000000000000..200311fea369 --- /dev/null +++ b/drivers/misc/apds990x.c | |||
@@ -0,0 +1,1295 @@ | |||
1 | /* | ||
2 | * This file is part of the APDS990x sensor driver. | ||
3 | * Chip is combined proximity and ambient light sensor. | ||
4 | * | ||
5 | * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). | ||
6 | * | ||
7 | * Contact: Samu Onkalo <samu.p.onkalo@nokia.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or | ||
10 | * modify it under the terms of the GNU General Public License | ||
11 | * version 2 as published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
21 | * 02110-1301 USA | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | #include <linux/kernel.h> | ||
26 | #include <linux/module.h> | ||
27 | #include <linux/i2c.h> | ||
28 | #include <linux/interrupt.h> | ||
29 | #include <linux/mutex.h> | ||
30 | #include <linux/regulator/consumer.h> | ||
31 | #include <linux/pm_runtime.h> | ||
32 | #include <linux/delay.h> | ||
33 | #include <linux/wait.h> | ||
34 | #include <linux/slab.h> | ||
35 | #include <linux/i2c/apds990x.h> | ||
36 | |||
37 | /* Register map */ | ||
38 | #define APDS990X_ENABLE 0x00 /* Enable of states and interrupts */ | ||
39 | #define APDS990X_ATIME 0x01 /* ALS ADC time */ | ||
40 | #define APDS990X_PTIME 0x02 /* Proximity ADC time */ | ||
41 | #define APDS990X_WTIME 0x03 /* Wait time */ | ||
42 | #define APDS990X_AILTL 0x04 /* ALS interrupt low threshold low byte */ | ||
43 | #define APDS990X_AILTH 0x05 /* ALS interrupt low threshold hi byte */ | ||
44 | #define APDS990X_AIHTL 0x06 /* ALS interrupt hi threshold low byte */ | ||
45 | #define APDS990X_AIHTH 0x07 /* ALS interrupt hi threshold hi byte */ | ||
46 | #define APDS990X_PILTL 0x08 /* Proximity interrupt low threshold low byte */ | ||
47 | #define APDS990X_PILTH 0x09 /* Proximity interrupt low threshold hi byte */ | ||
48 | #define APDS990X_PIHTL 0x0a /* Proximity interrupt hi threshold low byte */ | ||
49 | #define APDS990X_PIHTH 0x0b /* Proximity interrupt hi threshold hi byte */ | ||
50 | #define APDS990X_PERS 0x0c /* Interrupt persistence filters */ | ||
51 | #define APDS990X_CONFIG 0x0d /* Configuration */ | ||
52 | #define APDS990X_PPCOUNT 0x0e /* Proximity pulse count */ | ||
53 | #define APDS990X_CONTROL 0x0f /* Gain control register */ | ||
54 | #define APDS990X_REV 0x11 /* Revision Number */ | ||
55 | #define APDS990X_ID 0x12 /* Device ID */ | ||
56 | #define APDS990X_STATUS 0x13 /* Device status */ | ||
57 | #define APDS990X_CDATAL 0x14 /* Clear ADC low data register */ | ||
58 | #define APDS990X_CDATAH 0x15 /* Clear ADC high data register */ | ||
59 | #define APDS990X_IRDATAL 0x16 /* IR ADC low data register */ | ||
60 | #define APDS990X_IRDATAH 0x17 /* IR ADC high data register */ | ||
61 | #define APDS990X_PDATAL 0x18 /* Proximity ADC low data register */ | ||
62 | #define APDS990X_PDATAH 0x19 /* Proximity ADC high data register */ | ||
63 | |||
64 | /* Control */ | ||
65 | #define APDS990X_MAX_AGAIN 3 | ||
66 | |||
67 | /* Enable register */ | ||
68 | #define APDS990X_EN_PIEN (0x1 << 5) | ||
69 | #define APDS990X_EN_AIEN (0x1 << 4) | ||
70 | #define APDS990X_EN_WEN (0x1 << 3) | ||
71 | #define APDS990X_EN_PEN (0x1 << 2) | ||
72 | #define APDS990X_EN_AEN (0x1 << 1) | ||
73 | #define APDS990X_EN_PON (0x1 << 0) | ||
74 | #define APDS990X_EN_DISABLE_ALL 0 | ||
75 | |||
76 | /* Status register */ | ||
77 | #define APDS990X_ST_PINT (0x1 << 5) | ||
78 | #define APDS990X_ST_AINT (0x1 << 4) | ||
79 | |||
80 | /* I2C access types */ | ||
81 | #define APDS990x_CMD_TYPE_MASK (0x03 << 5) | ||
82 | #define APDS990x_CMD_TYPE_RB (0x00 << 5) /* Repeated byte */ | ||
83 | #define APDS990x_CMD_TYPE_INC (0x01 << 5) /* Auto increment */ | ||
84 | #define APDS990x_CMD_TYPE_SPE (0x03 << 5) /* Special function */ | ||
85 | |||
86 | #define APDS990x_ADDR_SHIFT 0 | ||
87 | #define APDS990x_CMD 0x80 | ||
88 | |||
89 | /* Interrupt ack commands */ | ||
90 | #define APDS990X_INT_ACK_ALS 0x6 | ||
91 | #define APDS990X_INT_ACK_PS 0x5 | ||
92 | #define APDS990X_INT_ACK_BOTH 0x7 | ||
93 | |||
94 | /* ptime */ | ||
95 | #define APDS990X_PTIME_DEFAULT 0xff /* Recommended conversion time 2.7ms*/ | ||
96 | |||
97 | /* wtime */ | ||
98 | #define APDS990X_WTIME_DEFAULT 0xee /* ~50ms wait time */ | ||
99 | |||
100 | #define APDS990X_TIME_TO_ADC 1024 /* One timetick as ADC count value */ | ||
101 | |||
102 | /* Persistence */ | ||
103 | #define APDS990X_APERS_SHIFT 0 | ||
104 | #define APDS990X_PPERS_SHIFT 4 | ||
105 | |||
106 | /* Supported ID:s */ | ||
107 | #define APDS990X_ID_0 0x0 | ||
108 | #define APDS990X_ID_4 0x4 | ||
109 | #define APDS990X_ID_29 0x29 | ||
110 | |||
111 | /* pgain and pdiode settings */ | ||
112 | #define APDS_PGAIN_1X 0x0 | ||
113 | #define APDS_PDIODE_IR 0x2 | ||
114 | |||
115 | #define APDS990X_LUX_OUTPUT_SCALE 10 | ||
116 | |||
117 | /* Reverse chip factors for threshold calculation */ | ||
118 | struct reverse_factors { | ||
119 | u32 afactor; | ||
120 | int cf1; | ||
121 | int irf1; | ||
122 | int cf2; | ||
123 | int irf2; | ||
124 | }; | ||
125 | |||
126 | struct apds990x_chip { | ||
127 | struct apds990x_platform_data *pdata; | ||
128 | struct i2c_client *client; | ||
129 | struct mutex mutex; /* avoid parallel access */ | ||
130 | struct regulator_bulk_data regs[2]; | ||
131 | wait_queue_head_t wait; | ||
132 | |||
133 | int prox_en; | ||
134 | bool prox_continuous_mode; | ||
135 | bool lux_wait_fresh_res; | ||
136 | |||
137 | /* Chip parameters */ | ||
138 | struct apds990x_chip_factors cf; | ||
139 | struct reverse_factors rcf; | ||
140 | u16 atime; /* als integration time */ | ||
141 | u16 arate; /* als reporting rate */ | ||
142 | u16 a_max_result; /* Max possible ADC value with current atime */ | ||
143 | u8 again_meas; /* Gain used in last measurement */ | ||
144 | u8 again_next; /* Next calculated gain */ | ||
145 | u8 pgain; | ||
146 | u8 pdiode; | ||
147 | u8 pdrive; | ||
148 | u8 lux_persistence; | ||
149 | u8 prox_persistence; | ||
150 | |||
151 | u32 lux_raw; | ||
152 | u32 lux; | ||
153 | u16 lux_clear; | ||
154 | u16 lux_ir; | ||
155 | u16 lux_calib; | ||
156 | u32 lux_thres_hi; | ||
157 | u32 lux_thres_lo; | ||
158 | |||
159 | u32 prox_thres; | ||
160 | u16 prox_data; | ||
161 | u16 prox_calib; | ||
162 | |||
163 | char chipname[10]; | ||
164 | u8 revision; | ||
165 | }; | ||
166 | |||
167 | #define APDS_CALIB_SCALER 8192 | ||
168 | #define APDS_LUX_NEUTRAL_CALIB_VALUE (1 * APDS_CALIB_SCALER) | ||
169 | #define APDS_PROX_NEUTRAL_CALIB_VALUE (1 * APDS_CALIB_SCALER) | ||
170 | |||
171 | #define APDS_PROX_DEF_THRES 600 | ||
172 | #define APDS_PROX_HYSTERESIS 50 | ||
173 | #define APDS_LUX_DEF_THRES_HI 101 | ||
174 | #define APDS_LUX_DEF_THRES_LO 100 | ||
175 | #define APDS_DEFAULT_PROX_PERS 1 | ||
176 | |||
177 | #define APDS_TIMEOUT 2000 | ||
178 | #define APDS_STARTUP_DELAY 25000 /* us */ | ||
179 | #define APDS_RANGE 65535 | ||
180 | #define APDS_PROX_RANGE 1023 | ||
181 | #define APDS_LUX_GAIN_LO_LIMIT 100 | ||
182 | #define APDS_LUX_GAIN_LO_LIMIT_STRICT 25 | ||
183 | |||
184 | #define TIMESTEP 87 /* 2.7ms is about 87 / 32 */ | ||
185 | #define TIME_STEP_SCALER 32 | ||
186 | |||
187 | #define APDS_LUX_AVERAGING_TIME 50 /* tolerates 50/60Hz ripple */ | ||
188 | #define APDS_LUX_DEFAULT_RATE 200 | ||
189 | |||
190 | static const u8 again[] = {1, 8, 16, 120}; /* ALS gain steps */ | ||
191 | static const u8 ir_currents[] = {100, 50, 25, 12}; /* IRled currents in mA */ | ||
192 | |||
193 | /* Following two tables must match i.e 10Hz rate means 1 as persistence value */ | ||
194 | static const u16 arates_hz[] = {10, 5, 2, 1}; | ||
195 | static const u8 apersis[] = {1, 2, 4, 5}; | ||
196 | |||
197 | /* Regulators */ | ||
198 | static const char reg_vcc[] = "Vdd"; | ||
199 | static const char reg_vled[] = "Vled"; | ||
200 | |||
201 | static int apds990x_read_byte(struct apds990x_chip *chip, u8 reg, u8 *data) | ||
202 | { | ||
203 | struct i2c_client *client = chip->client; | ||
204 | s32 ret; | ||
205 | |||
206 | reg &= ~APDS990x_CMD_TYPE_MASK; | ||
207 | reg |= APDS990x_CMD | APDS990x_CMD_TYPE_RB; | ||
208 | |||
209 | ret = i2c_smbus_read_byte_data(client, reg); | ||
210 | *data = ret; | ||
211 | return (int)ret; | ||
212 | } | ||
213 | |||
214 | static int apds990x_read_word(struct apds990x_chip *chip, u8 reg, u16 *data) | ||
215 | { | ||
216 | struct i2c_client *client = chip->client; | ||
217 | s32 ret; | ||
218 | |||
219 | reg &= ~APDS990x_CMD_TYPE_MASK; | ||
220 | reg |= APDS990x_CMD | APDS990x_CMD_TYPE_INC; | ||
221 | |||
222 | ret = i2c_smbus_read_word_data(client, reg); | ||
223 | *data = ret; | ||
224 | return (int)ret; | ||
225 | } | ||
226 | |||
227 | static int apds990x_write_byte(struct apds990x_chip *chip, u8 reg, u8 data) | ||
228 | { | ||
229 | struct i2c_client *client = chip->client; | ||
230 | s32 ret; | ||
231 | |||
232 | reg &= ~APDS990x_CMD_TYPE_MASK; | ||
233 | reg |= APDS990x_CMD | APDS990x_CMD_TYPE_RB; | ||
234 | |||
235 | ret = i2c_smbus_write_byte_data(client, reg, data); | ||
236 | return (int)ret; | ||
237 | } | ||
238 | |||
239 | static int apds990x_write_word(struct apds990x_chip *chip, u8 reg, u16 data) | ||
240 | { | ||
241 | struct i2c_client *client = chip->client; | ||
242 | s32 ret; | ||
243 | |||
244 | reg &= ~APDS990x_CMD_TYPE_MASK; | ||
245 | reg |= APDS990x_CMD | APDS990x_CMD_TYPE_INC; | ||
246 | |||
247 | ret = i2c_smbus_write_word_data(client, reg, data); | ||
248 | return (int)ret; | ||
249 | } | ||
250 | |||
251 | static int apds990x_mode_on(struct apds990x_chip *chip) | ||
252 | { | ||
253 | /* ALS is mandatory, proximity optional */ | ||
254 | u8 reg = APDS990X_EN_AIEN | APDS990X_EN_PON | APDS990X_EN_AEN | | ||
255 | APDS990X_EN_WEN; | ||
256 | |||
257 | if (chip->prox_en) | ||
258 | reg |= APDS990X_EN_PIEN | APDS990X_EN_PEN; | ||
259 | |||
260 | return apds990x_write_byte(chip, APDS990X_ENABLE, reg); | ||
261 | } | ||
262 | |||
263 | static u16 apds990x_lux_to_threshold(struct apds990x_chip *chip, u32 lux) | ||
264 | { | ||
265 | u32 thres; | ||
266 | u32 cpl; | ||
267 | u32 ir; | ||
268 | |||
269 | if (lux == 0) | ||
270 | return 0; | ||
271 | else if (lux == APDS_RANGE) | ||
272 | return APDS_RANGE; | ||
273 | |||
274 | /* | ||
275 | * Reported LUX value is a combination of the IR and CLEAR channel | ||
276 | * values. However, interrupt threshold is only for clear channel. | ||
277 | * This function approximates needed HW threshold value for a given | ||
278 | * LUX value in the current lightning type. | ||
279 | * IR level compared to visible light varies heavily depending on the | ||
280 | * source of the light | ||
281 | * | ||
282 | * Calculate threshold value for the next measurement period. | ||
283 | * Math: threshold = lux * cpl where | ||
284 | * cpl = atime * again / (glass_attenuation * device_factor) | ||
285 | * (count-per-lux) | ||
286 | * | ||
287 | * First remove calibration. Division by four is to avoid overflow | ||
288 | */ | ||
289 | lux = lux * (APDS_CALIB_SCALER / 4) / (chip->lux_calib / 4); | ||
290 | |||
291 | /* Multiplication by 64 is to increase accuracy */ | ||
292 | cpl = ((u32)chip->atime * (u32)again[chip->again_next] * | ||
293 | APDS_PARAM_SCALE * 64) / (chip->cf.ga * chip->cf.df); | ||
294 | |||
295 | thres = lux * cpl / 64; | ||
296 | /* | ||
297 | * Convert IR light from the latest result to match with | ||
298 | * new gain step. This helps to adapt with the current | ||
299 | * source of light. | ||
300 | */ | ||
301 | ir = (u32)chip->lux_ir * (u32)again[chip->again_next] / | ||
302 | (u32)again[chip->again_meas]; | ||
303 | |||
304 | /* | ||
305 | * Compensate count with IR light impact | ||
306 | * IAC1 > IAC2 (see apds990x_get_lux for formulas) | ||
307 | */ | ||
308 | if (chip->lux_clear * APDS_PARAM_SCALE >= | ||
309 | chip->rcf.afactor * chip->lux_ir) | ||
310 | thres = (chip->rcf.cf1 * thres + chip->rcf.irf1 * ir) / | ||
311 | APDS_PARAM_SCALE; | ||
312 | else | ||
313 | thres = (chip->rcf.cf2 * thres + chip->rcf.irf2 * ir) / | ||
314 | APDS_PARAM_SCALE; | ||
315 | |||
316 | if (thres >= chip->a_max_result) | ||
317 | thres = chip->a_max_result - 1; | ||
318 | return thres; | ||
319 | } | ||
320 | |||
321 | static inline int apds990x_set_atime(struct apds990x_chip *chip, u32 time_ms) | ||
322 | { | ||
323 | u8 reg_value; | ||
324 | |||
325 | chip->atime = time_ms; | ||
326 | /* Formula is specified in the data sheet */ | ||
327 | reg_value = 256 - ((time_ms * TIME_STEP_SCALER) / TIMESTEP); | ||
328 | /* Calculate max ADC value for given integration time */ | ||
329 | chip->a_max_result = (u16)(256 - reg_value) * APDS990X_TIME_TO_ADC; | ||
330 | return apds990x_write_byte(chip, APDS990X_ATIME, reg_value); | ||
331 | } | ||
332 | |||
333 | /* Called always with mutex locked */ | ||
334 | static int apds990x_refresh_pthres(struct apds990x_chip *chip, int data) | ||
335 | { | ||
336 | int ret, lo, hi; | ||
337 | |||
338 | /* If the chip is not in use, don't try to access it */ | ||
339 | if (pm_runtime_suspended(&chip->client->dev)) | ||
340 | return 0; | ||
341 | |||
342 | if (data < chip->prox_thres) { | ||
343 | lo = 0; | ||
344 | hi = chip->prox_thres; | ||
345 | } else { | ||
346 | lo = chip->prox_thres - APDS_PROX_HYSTERESIS; | ||
347 | if (chip->prox_continuous_mode) | ||
348 | hi = chip->prox_thres; | ||
349 | else | ||
350 | hi = APDS_RANGE; | ||
351 | } | ||
352 | |||
353 | ret = apds990x_write_word(chip, APDS990X_PILTL, lo); | ||
354 | ret |= apds990x_write_word(chip, APDS990X_PIHTL, hi); | ||
355 | return ret; | ||
356 | } | ||
357 | |||
358 | /* Called always with mutex locked */ | ||
359 | static int apds990x_refresh_athres(struct apds990x_chip *chip) | ||
360 | { | ||
361 | int ret; | ||
362 | /* If the chip is not in use, don't try to access it */ | ||
363 | if (pm_runtime_suspended(&chip->client->dev)) | ||
364 | return 0; | ||
365 | |||
366 | ret = apds990x_write_word(chip, APDS990X_AILTL, | ||
367 | apds990x_lux_to_threshold(chip, chip->lux_thres_lo)); | ||
368 | ret |= apds990x_write_word(chip, APDS990X_AIHTL, | ||
369 | apds990x_lux_to_threshold(chip, chip->lux_thres_hi)); | ||
370 | |||
371 | return ret; | ||
372 | } | ||
373 | |||
374 | /* Called always with mutex locked */ | ||
375 | static void apds990x_force_a_refresh(struct apds990x_chip *chip) | ||
376 | { | ||
377 | /* This will force ALS interrupt after the next measurement. */ | ||
378 | apds990x_write_word(chip, APDS990X_AILTL, APDS_LUX_DEF_THRES_LO); | ||
379 | apds990x_write_word(chip, APDS990X_AIHTL, APDS_LUX_DEF_THRES_HI); | ||
380 | } | ||
381 | |||
382 | /* Called always with mutex locked */ | ||
383 | static void apds990x_force_p_refresh(struct apds990x_chip *chip) | ||
384 | { | ||
385 | /* This will force proximity interrupt after the next measurement. */ | ||
386 | apds990x_write_word(chip, APDS990X_PILTL, APDS_PROX_DEF_THRES - 1); | ||
387 | apds990x_write_word(chip, APDS990X_PIHTL, APDS_PROX_DEF_THRES); | ||
388 | } | ||
389 | |||
390 | /* Called always with mutex locked */ | ||
391 | static int apds990x_calc_again(struct apds990x_chip *chip) | ||
392 | { | ||
393 | int curr_again = chip->again_meas; | ||
394 | int next_again = chip->again_meas; | ||
395 | int ret = 0; | ||
396 | |||
397 | /* Calculate suitable als gain */ | ||
398 | if (chip->lux_clear == chip->a_max_result) | ||
399 | next_again -= 2; /* ALS saturated. Decrease gain by 2 steps */ | ||
400 | else if (chip->lux_clear > chip->a_max_result / 2) | ||
401 | next_again--; | ||
402 | else if (chip->lux_clear < APDS_LUX_GAIN_LO_LIMIT_STRICT) | ||
403 | next_again += 2; /* Too dark. Increase gain by 2 steps */ | ||
404 | else if (chip->lux_clear < APDS_LUX_GAIN_LO_LIMIT) | ||
405 | next_again++; | ||
406 | |||
407 | /* Limit gain to available range */ | ||
408 | if (next_again < 0) | ||
409 | next_again = 0; | ||
410 | else if (next_again > APDS990X_MAX_AGAIN) | ||
411 | next_again = APDS990X_MAX_AGAIN; | ||
412 | |||
413 | /* Let's check can we trust the measured result */ | ||
414 | if (chip->lux_clear == chip->a_max_result) | ||
415 | /* Result can be totally garbage due to saturation */ | ||
416 | ret = -ERANGE; | ||
417 | else if (next_again != curr_again && | ||
418 | chip->lux_clear < APDS_LUX_GAIN_LO_LIMIT_STRICT) | ||
419 | /* | ||
420 | * Gain is changed and measurement result is very small. | ||
421 | * Result can be totally garbage due to underflow | ||
422 | */ | ||
423 | ret = -ERANGE; | ||
424 | |||
425 | chip->again_next = next_again; | ||
426 | apds990x_write_byte(chip, APDS990X_CONTROL, | ||
427 | (chip->pdrive << 6) | | ||
428 | (chip->pdiode << 4) | | ||
429 | (chip->pgain << 2) | | ||
430 | (chip->again_next << 0)); | ||
431 | |||
432 | /* | ||
433 | * Error means bad result -> re-measurement is needed. The forced | ||
434 | * refresh uses fastest possible persistence setting to get result | ||
435 | * as soon as possible. | ||
436 | */ | ||
437 | if (ret < 0) | ||
438 | apds990x_force_a_refresh(chip); | ||
439 | else | ||
440 | apds990x_refresh_athres(chip); | ||
441 | |||
442 | return ret; | ||
443 | } | ||
444 | |||
445 | /* Called always with mutex locked */ | ||
446 | static int apds990x_get_lux(struct apds990x_chip *chip, int clear, int ir) | ||
447 | { | ||
448 | int iac, iac1, iac2; /* IR adjusted counts */ | ||
449 | u32 lpc; /* Lux per count */ | ||
450 | |||
451 | /* Formulas: | ||
452 | * iac1 = CF1 * CLEAR_CH - IRF1 * IR_CH | ||
453 | * iac2 = CF2 * CLEAR_CH - IRF2 * IR_CH | ||
454 | */ | ||
455 | iac1 = (chip->cf.cf1 * clear - chip->cf.irf1 * ir) / APDS_PARAM_SCALE; | ||
456 | iac2 = (chip->cf.cf2 * clear - chip->cf.irf2 * ir) / APDS_PARAM_SCALE; | ||
457 | |||
458 | iac = max(iac1, iac2); | ||
459 | iac = max(iac, 0); | ||
460 | |||
461 | lpc = APDS990X_LUX_OUTPUT_SCALE * (chip->cf.df * chip->cf.ga) / | ||
462 | (u32)(again[chip->again_meas] * (u32)chip->atime); | ||
463 | |||
464 | return (iac * lpc) / APDS_PARAM_SCALE; | ||
465 | } | ||
466 | |||
467 | static int apds990x_ack_int(struct apds990x_chip *chip, u8 mode) | ||
468 | { | ||
469 | struct i2c_client *client = chip->client; | ||
470 | s32 ret; | ||
471 | u8 reg = APDS990x_CMD | APDS990x_CMD_TYPE_SPE; | ||
472 | |||
473 | switch (mode & (APDS990X_ST_AINT | APDS990X_ST_PINT)) { | ||
474 | case APDS990X_ST_AINT: | ||
475 | reg |= APDS990X_INT_ACK_ALS; | ||
476 | break; | ||
477 | case APDS990X_ST_PINT: | ||
478 | reg |= APDS990X_INT_ACK_PS; | ||
479 | break; | ||
480 | default: | ||
481 | reg |= APDS990X_INT_ACK_BOTH; | ||
482 | break; | ||
483 | } | ||
484 | |||
485 | ret = i2c_smbus_read_byte_data(client, reg); | ||
486 | return (int)ret; | ||
487 | } | ||
488 | |||
489 | static irqreturn_t apds990x_irq(int irq, void *data) | ||
490 | { | ||
491 | struct apds990x_chip *chip = data; | ||
492 | u8 status; | ||
493 | |||
494 | apds990x_read_byte(chip, APDS990X_STATUS, &status); | ||
495 | apds990x_ack_int(chip, status); | ||
496 | |||
497 | mutex_lock(&chip->mutex); | ||
498 | if (!pm_runtime_suspended(&chip->client->dev)) { | ||
499 | if (status & APDS990X_ST_AINT) { | ||
500 | apds990x_read_word(chip, APDS990X_CDATAL, | ||
501 | &chip->lux_clear); | ||
502 | apds990x_read_word(chip, APDS990X_IRDATAL, | ||
503 | &chip->lux_ir); | ||
504 | /* Store used gain for calculations */ | ||
505 | chip->again_meas = chip->again_next; | ||
506 | |||
507 | chip->lux_raw = apds990x_get_lux(chip, | ||
508 | chip->lux_clear, | ||
509 | chip->lux_ir); | ||
510 | |||
511 | if (apds990x_calc_again(chip) == 0) { | ||
512 | /* Result is valid */ | ||
513 | chip->lux = chip->lux_raw; | ||
514 | chip->lux_wait_fresh_res = false; | ||
515 | wake_up(&chip->wait); | ||
516 | sysfs_notify(&chip->client->dev.kobj, | ||
517 | NULL, "lux0_input"); | ||
518 | } | ||
519 | } | ||
520 | |||
521 | if ((status & APDS990X_ST_PINT) && chip->prox_en) { | ||
522 | u16 clr_ch; | ||
523 | |||
524 | apds990x_read_word(chip, APDS990X_CDATAL, &clr_ch); | ||
525 | /* | ||
526 | * If ALS channel is saturated at min gain, | ||
527 | * proximity gives false posivite values. | ||
528 | * Just ignore them. | ||
529 | */ | ||
530 | if (chip->again_meas == 0 && | ||
531 | clr_ch == chip->a_max_result) | ||
532 | chip->prox_data = 0; | ||
533 | else | ||
534 | apds990x_read_word(chip, | ||
535 | APDS990X_PDATAL, | ||
536 | &chip->prox_data); | ||
537 | |||
538 | apds990x_refresh_pthres(chip, chip->prox_data); | ||
539 | if (chip->prox_data < chip->prox_thres) | ||
540 | chip->prox_data = 0; | ||
541 | else if (!chip->prox_continuous_mode) | ||
542 | chip->prox_data = APDS_PROX_RANGE; | ||
543 | sysfs_notify(&chip->client->dev.kobj, | ||
544 | NULL, "prox0_raw"); | ||
545 | } | ||
546 | } | ||
547 | mutex_unlock(&chip->mutex); | ||
548 | return IRQ_HANDLED; | ||
549 | } | ||
550 | |||
551 | static int apds990x_configure(struct apds990x_chip *chip) | ||
552 | { | ||
553 | /* It is recommended to use disabled mode during these operations */ | ||
554 | apds990x_write_byte(chip, APDS990X_ENABLE, APDS990X_EN_DISABLE_ALL); | ||
555 | |||
556 | /* conversion and wait times for different state machince states */ | ||
557 | apds990x_write_byte(chip, APDS990X_PTIME, APDS990X_PTIME_DEFAULT); | ||
558 | apds990x_write_byte(chip, APDS990X_WTIME, APDS990X_WTIME_DEFAULT); | ||
559 | apds990x_set_atime(chip, APDS_LUX_AVERAGING_TIME); | ||
560 | |||
561 | apds990x_write_byte(chip, APDS990X_CONFIG, 0); | ||
562 | |||
563 | /* Persistence levels */ | ||
564 | apds990x_write_byte(chip, APDS990X_PERS, | ||
565 | (chip->lux_persistence << APDS990X_APERS_SHIFT) | | ||
566 | (chip->prox_persistence << APDS990X_PPERS_SHIFT)); | ||
567 | |||
568 | apds990x_write_byte(chip, APDS990X_PPCOUNT, chip->pdata->ppcount); | ||
569 | |||
570 | /* Start with relatively small gain */ | ||
571 | chip->again_meas = 1; | ||
572 | chip->again_next = 1; | ||
573 | apds990x_write_byte(chip, APDS990X_CONTROL, | ||
574 | (chip->pdrive << 6) | | ||
575 | (chip->pdiode << 4) | | ||
576 | (chip->pgain << 2) | | ||
577 | (chip->again_next << 0)); | ||
578 | return 0; | ||
579 | } | ||
580 | |||
581 | static int apds990x_detect(struct apds990x_chip *chip) | ||
582 | { | ||
583 | struct i2c_client *client = chip->client; | ||
584 | int ret; | ||
585 | u8 id; | ||
586 | |||
587 | ret = apds990x_read_byte(chip, APDS990X_ID, &id); | ||
588 | if (ret < 0) { | ||
589 | dev_err(&client->dev, "ID read failed\n"); | ||
590 | return ret; | ||
591 | } | ||
592 | |||
593 | ret = apds990x_read_byte(chip, APDS990X_REV, &chip->revision); | ||
594 | if (ret < 0) { | ||
595 | dev_err(&client->dev, "REV read failed\n"); | ||
596 | return ret; | ||
597 | } | ||
598 | |||
599 | switch (id) { | ||
600 | case APDS990X_ID_0: | ||
601 | case APDS990X_ID_4: | ||
602 | case APDS990X_ID_29: | ||
603 | snprintf(chip->chipname, sizeof(chip->chipname), "APDS-990x"); | ||
604 | break; | ||
605 | default: | ||
606 | ret = -ENODEV; | ||
607 | break; | ||
608 | } | ||
609 | return ret; | ||
610 | } | ||
611 | |||
612 | static int apds990x_chip_on(struct apds990x_chip *chip) | ||
613 | { | ||
614 | int err = regulator_bulk_enable(ARRAY_SIZE(chip->regs), | ||
615 | chip->regs); | ||
616 | if (err < 0) | ||
617 | return err; | ||
618 | |||
619 | usleep_range(APDS_STARTUP_DELAY, 2 * APDS_STARTUP_DELAY); | ||
620 | |||
621 | /* Refresh all configs in case of regulators were off */ | ||
622 | chip->prox_data = 0; | ||
623 | apds990x_configure(chip); | ||
624 | apds990x_mode_on(chip); | ||
625 | return 0; | ||
626 | } | ||
627 | |||
628 | static int apds990x_chip_off(struct apds990x_chip *chip) | ||
629 | { | ||
630 | apds990x_write_byte(chip, APDS990X_ENABLE, APDS990X_EN_DISABLE_ALL); | ||
631 | regulator_bulk_disable(ARRAY_SIZE(chip->regs), chip->regs); | ||
632 | return 0; | ||
633 | } | ||
634 | |||
635 | static ssize_t apds990x_lux_show(struct device *dev, | ||
636 | struct device_attribute *attr, char *buf) | ||
637 | { | ||
638 | struct apds990x_chip *chip = dev_get_drvdata(dev); | ||
639 | ssize_t ret; | ||
640 | u32 result; | ||
641 | long timeout; | ||
642 | |||
643 | if (pm_runtime_suspended(dev)) | ||
644 | return -EIO; | ||
645 | |||
646 | timeout = wait_event_interruptible_timeout(chip->wait, | ||
647 | !chip->lux_wait_fresh_res, | ||
648 | msecs_to_jiffies(APDS_TIMEOUT)); | ||
649 | if (!timeout) | ||
650 | return -EIO; | ||
651 | |||
652 | mutex_lock(&chip->mutex); | ||
653 | result = (chip->lux * chip->lux_calib) / APDS_CALIB_SCALER; | ||
654 | if (result > (APDS_RANGE * APDS990X_LUX_OUTPUT_SCALE)) | ||
655 | result = APDS_RANGE * APDS990X_LUX_OUTPUT_SCALE; | ||
656 | |||
657 | ret = sprintf(buf, "%d.%d\n", | ||
658 | result / APDS990X_LUX_OUTPUT_SCALE, | ||
659 | result % APDS990X_LUX_OUTPUT_SCALE); | ||
660 | mutex_unlock(&chip->mutex); | ||
661 | return ret; | ||
662 | } | ||
663 | |||
664 | static DEVICE_ATTR(lux0_input, S_IRUGO, apds990x_lux_show, NULL); | ||
665 | |||
666 | static ssize_t apds990x_lux_range_show(struct device *dev, | ||
667 | struct device_attribute *attr, char *buf) | ||
668 | { | ||
669 | return sprintf(buf, "%u\n", APDS_RANGE); | ||
670 | } | ||
671 | |||
672 | static DEVICE_ATTR(lux0_sensor_range, S_IRUGO, apds990x_lux_range_show, NULL); | ||
673 | |||
674 | static ssize_t apds990x_lux_calib_format_show(struct device *dev, | ||
675 | struct device_attribute *attr, char *buf) | ||
676 | { | ||
677 | return sprintf(buf, "%u\n", APDS_CALIB_SCALER); | ||
678 | } | ||
679 | |||
680 | static DEVICE_ATTR(lux0_calibscale_default, S_IRUGO, | ||
681 | apds990x_lux_calib_format_show, NULL); | ||
682 | |||
683 | static ssize_t apds990x_lux_calib_show(struct device *dev, | ||
684 | struct device_attribute *attr, char *buf) | ||
685 | { | ||
686 | struct apds990x_chip *chip = dev_get_drvdata(dev); | ||
687 | |||
688 | return sprintf(buf, "%u\n", chip->lux_calib); | ||
689 | } | ||
690 | |||
691 | static ssize_t apds990x_lux_calib_store(struct device *dev, | ||
692 | struct device_attribute *attr, | ||
693 | const char *buf, size_t len) | ||
694 | { | ||
695 | struct apds990x_chip *chip = dev_get_drvdata(dev); | ||
696 | unsigned long value; | ||
697 | |||
698 | if (strict_strtoul(buf, 0, &value)) | ||
699 | return -EINVAL; | ||
700 | |||
701 | if (chip->lux_calib > APDS_RANGE) | ||
702 | return -EINVAL; | ||
703 | |||
704 | chip->lux_calib = value; | ||
705 | |||
706 | return len; | ||
707 | } | ||
708 | |||
709 | static DEVICE_ATTR(lux0_calibscale, S_IRUGO | S_IWUSR, apds990x_lux_calib_show, | ||
710 | apds990x_lux_calib_store); | ||
711 | |||
712 | static ssize_t apds990x_rate_avail(struct device *dev, | ||
713 | struct device_attribute *attr, char *buf) | ||
714 | { | ||
715 | int i; | ||
716 | int pos = 0; | ||
717 | for (i = 0; i < ARRAY_SIZE(arates_hz); i++) | ||
718 | pos += sprintf(buf + pos, "%d ", arates_hz[i]); | ||
719 | sprintf(buf + pos - 1, "\n"); | ||
720 | return pos; | ||
721 | } | ||
722 | |||
723 | static ssize_t apds990x_rate_show(struct device *dev, | ||
724 | struct device_attribute *attr, char *buf) | ||
725 | { | ||
726 | struct apds990x_chip *chip = dev_get_drvdata(dev); | ||
727 | return sprintf(buf, "%d\n", chip->arate); | ||
728 | } | ||
729 | |||
730 | static int apds990x_set_arate(struct apds990x_chip *chip, int rate) | ||
731 | { | ||
732 | int i; | ||
733 | |||
734 | for (i = 0; i < ARRAY_SIZE(arates_hz); i++) | ||
735 | if (rate >= arates_hz[i]) | ||
736 | break; | ||
737 | |||
738 | if (i == ARRAY_SIZE(arates_hz)) | ||
739 | return -EINVAL; | ||
740 | |||
741 | /* Pick up corresponding persistence value */ | ||
742 | chip->lux_persistence = apersis[i]; | ||
743 | chip->arate = arates_hz[i]; | ||
744 | |||
745 | /* If the chip is not in use, don't try to access it */ | ||
746 | if (pm_runtime_suspended(&chip->client->dev)) | ||
747 | return 0; | ||
748 | |||
749 | /* Persistence levels */ | ||
750 | return apds990x_write_byte(chip, APDS990X_PERS, | ||
751 | (chip->lux_persistence << APDS990X_APERS_SHIFT) | | ||
752 | (chip->prox_persistence << APDS990X_PPERS_SHIFT)); | ||
753 | } | ||
754 | |||
755 | static ssize_t apds990x_rate_store(struct device *dev, | ||
756 | struct device_attribute *attr, | ||
757 | const char *buf, size_t len) | ||
758 | { | ||
759 | struct apds990x_chip *chip = dev_get_drvdata(dev); | ||
760 | unsigned long value; | ||
761 | int ret; | ||
762 | |||
763 | if (strict_strtoul(buf, 0, &value)) | ||
764 | return -EINVAL; | ||
765 | |||
766 | mutex_lock(&chip->mutex); | ||
767 | ret = apds990x_set_arate(chip, value); | ||
768 | mutex_unlock(&chip->mutex); | ||
769 | |||
770 | if (ret < 0) | ||
771 | return ret; | ||
772 | return len; | ||
773 | } | ||
774 | |||
775 | static DEVICE_ATTR(lux0_rate_avail, S_IRUGO, apds990x_rate_avail, NULL); | ||
776 | |||
777 | static DEVICE_ATTR(lux0_rate, S_IRUGO | S_IWUSR, apds990x_rate_show, | ||
778 | apds990x_rate_store); | ||
779 | |||
780 | static ssize_t apds990x_prox_show(struct device *dev, | ||
781 | struct device_attribute *attr, char *buf) | ||
782 | { | ||
783 | ssize_t ret; | ||
784 | struct apds990x_chip *chip = dev_get_drvdata(dev); | ||
785 | if (pm_runtime_suspended(dev) || !chip->prox_en) | ||
786 | return -EIO; | ||
787 | |||
788 | mutex_lock(&chip->mutex); | ||
789 | ret = sprintf(buf, "%d\n", chip->prox_data); | ||
790 | mutex_unlock(&chip->mutex); | ||
791 | return ret; | ||
792 | } | ||
793 | |||
794 | static DEVICE_ATTR(prox0_raw, S_IRUGO, apds990x_prox_show, NULL); | ||
795 | |||
796 | static ssize_t apds990x_prox_range_show(struct device *dev, | ||
797 | struct device_attribute *attr, char *buf) | ||
798 | { | ||
799 | return sprintf(buf, "%u\n", APDS_PROX_RANGE); | ||
800 | } | ||
801 | |||
802 | static DEVICE_ATTR(prox0_sensor_range, S_IRUGO, apds990x_prox_range_show, NULL); | ||
803 | |||
804 | static ssize_t apds990x_prox_enable_show(struct device *dev, | ||
805 | struct device_attribute *attr, char *buf) | ||
806 | { | ||
807 | struct apds990x_chip *chip = dev_get_drvdata(dev); | ||
808 | return sprintf(buf, "%d\n", chip->prox_en); | ||
809 | } | ||
810 | |||
811 | static ssize_t apds990x_prox_enable_store(struct device *dev, | ||
812 | struct device_attribute *attr, | ||
813 | const char *buf, size_t len) | ||
814 | { | ||
815 | struct apds990x_chip *chip = dev_get_drvdata(dev); | ||
816 | unsigned long value; | ||
817 | |||
818 | if (strict_strtoul(buf, 0, &value)) | ||
819 | return -EINVAL; | ||
820 | |||
821 | mutex_lock(&chip->mutex); | ||
822 | |||
823 | if (!chip->prox_en) | ||
824 | chip->prox_data = 0; | ||
825 | |||
826 | if (value) | ||
827 | chip->prox_en++; | ||
828 | else if (chip->prox_en > 0) | ||
829 | chip->prox_en--; | ||
830 | |||
831 | if (!pm_runtime_suspended(dev)) | ||
832 | apds990x_mode_on(chip); | ||
833 | mutex_unlock(&chip->mutex); | ||
834 | return len; | ||
835 | } | ||
836 | |||
837 | static DEVICE_ATTR(prox0_raw_en, S_IRUGO | S_IWUSR, apds990x_prox_enable_show, | ||
838 | apds990x_prox_enable_store); | ||
839 | |||
840 | static const char reporting_modes[][9] = {"trigger", "periodic"}; | ||
841 | |||
842 | static ssize_t apds990x_prox_reporting_mode_show(struct device *dev, | ||
843 | struct device_attribute *attr, char *buf) | ||
844 | { | ||
845 | struct apds990x_chip *chip = dev_get_drvdata(dev); | ||
846 | return sprintf(buf, "%s\n", | ||
847 | reporting_modes[!!chip->prox_continuous_mode]); | ||
848 | } | ||
849 | |||
850 | static ssize_t apds990x_prox_reporting_mode_store(struct device *dev, | ||
851 | struct device_attribute *attr, | ||
852 | const char *buf, size_t len) | ||
853 | { | ||
854 | struct apds990x_chip *chip = dev_get_drvdata(dev); | ||
855 | |||
856 | if (sysfs_streq(buf, reporting_modes[0])) | ||
857 | chip->prox_continuous_mode = 0; | ||
858 | else if (sysfs_streq(buf, reporting_modes[1])) | ||
859 | chip->prox_continuous_mode = 1; | ||
860 | else | ||
861 | return -EINVAL; | ||
862 | return len; | ||
863 | } | ||
864 | |||
865 | static DEVICE_ATTR(prox0_reporting_mode, S_IRUGO | S_IWUSR, | ||
866 | apds990x_prox_reporting_mode_show, | ||
867 | apds990x_prox_reporting_mode_store); | ||
868 | |||
869 | static ssize_t apds990x_prox_reporting_avail_show(struct device *dev, | ||
870 | struct device_attribute *attr, char *buf) | ||
871 | { | ||
872 | return sprintf(buf, "%s %s\n", reporting_modes[0], reporting_modes[1]); | ||
873 | } | ||
874 | |||
875 | static DEVICE_ATTR(prox0_reporting_mode_avail, S_IRUGO | S_IWUSR, | ||
876 | apds990x_prox_reporting_avail_show, NULL); | ||
877 | |||
878 | |||
879 | static ssize_t apds990x_lux_thresh_above_show(struct device *dev, | ||
880 | struct device_attribute *attr, char *buf) | ||
881 | { | ||
882 | struct apds990x_chip *chip = dev_get_drvdata(dev); | ||
883 | return sprintf(buf, "%d\n", chip->lux_thres_hi); | ||
884 | } | ||
885 | |||
886 | static ssize_t apds990x_lux_thresh_below_show(struct device *dev, | ||
887 | struct device_attribute *attr, char *buf) | ||
888 | { | ||
889 | struct apds990x_chip *chip = dev_get_drvdata(dev); | ||
890 | return sprintf(buf, "%d\n", chip->lux_thres_lo); | ||
891 | } | ||
892 | |||
893 | static ssize_t apds990x_set_lux_thresh(struct apds990x_chip *chip, u32 *target, | ||
894 | const char *buf) | ||
895 | { | ||
896 | int ret = 0; | ||
897 | unsigned long thresh; | ||
898 | |||
899 | if (strict_strtoul(buf, 0, &thresh)) | ||
900 | return -EINVAL; | ||
901 | |||
902 | if (thresh > APDS_RANGE) | ||
903 | return -EINVAL; | ||
904 | |||
905 | mutex_lock(&chip->mutex); | ||
906 | *target = thresh; | ||
907 | /* | ||
908 | * Don't update values in HW if we are still waiting for | ||
909 | * first interrupt to come after device handle open call. | ||
910 | */ | ||
911 | if (!chip->lux_wait_fresh_res) | ||
912 | apds990x_refresh_athres(chip); | ||
913 | mutex_unlock(&chip->mutex); | ||
914 | return ret; | ||
915 | |||
916 | } | ||
917 | |||
918 | static ssize_t apds990x_lux_thresh_above_store(struct device *dev, | ||
919 | struct device_attribute *attr, | ||
920 | const char *buf, size_t len) | ||
921 | { | ||
922 | struct apds990x_chip *chip = dev_get_drvdata(dev); | ||
923 | int ret = apds990x_set_lux_thresh(chip, &chip->lux_thres_hi, buf); | ||
924 | if (ret < 0) | ||
925 | return ret; | ||
926 | return len; | ||
927 | } | ||
928 | |||
929 | static ssize_t apds990x_lux_thresh_below_store(struct device *dev, | ||
930 | struct device_attribute *attr, | ||
931 | const char *buf, size_t len) | ||
932 | { | ||
933 | struct apds990x_chip *chip = dev_get_drvdata(dev); | ||
934 | int ret = apds990x_set_lux_thresh(chip, &chip->lux_thres_lo, buf); | ||
935 | if (ret < 0) | ||
936 | return ret; | ||
937 | return len; | ||
938 | } | ||
939 | |||
940 | static DEVICE_ATTR(lux0_thresh_above_value, S_IRUGO | S_IWUSR, | ||
941 | apds990x_lux_thresh_above_show, | ||
942 | apds990x_lux_thresh_above_store); | ||
943 | |||
944 | static DEVICE_ATTR(lux0_thresh_below_value, S_IRUGO | S_IWUSR, | ||
945 | apds990x_lux_thresh_below_show, | ||
946 | apds990x_lux_thresh_below_store); | ||
947 | |||
948 | static ssize_t apds990x_prox_threshold_show(struct device *dev, | ||
949 | struct device_attribute *attr, char *buf) | ||
950 | { | ||
951 | struct apds990x_chip *chip = dev_get_drvdata(dev); | ||
952 | return sprintf(buf, "%d\n", chip->prox_thres); | ||
953 | } | ||
954 | |||
955 | static ssize_t apds990x_prox_threshold_store(struct device *dev, | ||
956 | struct device_attribute *attr, | ||
957 | const char *buf, size_t len) | ||
958 | { | ||
959 | struct apds990x_chip *chip = dev_get_drvdata(dev); | ||
960 | unsigned long value; | ||
961 | |||
962 | if (strict_strtoul(buf, 0, &value)) | ||
963 | return -EINVAL; | ||
964 | |||
965 | if ((value > APDS_RANGE) || (value == 0) || | ||
966 | (value < APDS_PROX_HYSTERESIS)) | ||
967 | return -EINVAL; | ||
968 | |||
969 | mutex_lock(&chip->mutex); | ||
970 | chip->prox_thres = value; | ||
971 | |||
972 | apds990x_force_p_refresh(chip); | ||
973 | mutex_unlock(&chip->mutex); | ||
974 | return len; | ||
975 | } | ||
976 | |||
977 | static DEVICE_ATTR(prox0_thresh_above_value, S_IRUGO | S_IWUSR, | ||
978 | apds990x_prox_threshold_show, | ||
979 | apds990x_prox_threshold_store); | ||
980 | |||
981 | static ssize_t apds990x_power_state_show(struct device *dev, | ||
982 | struct device_attribute *attr, char *buf) | ||
983 | { | ||
984 | return sprintf(buf, "%d\n", !pm_runtime_suspended(dev)); | ||
985 | return 0; | ||
986 | } | ||
987 | |||
988 | static ssize_t apds990x_power_state_store(struct device *dev, | ||
989 | struct device_attribute *attr, | ||
990 | const char *buf, size_t len) | ||
991 | { | ||
992 | struct apds990x_chip *chip = dev_get_drvdata(dev); | ||
993 | unsigned long value; | ||
994 | |||
995 | if (strict_strtoul(buf, 0, &value)) | ||
996 | return -EINVAL; | ||
997 | if (value) { | ||
998 | pm_runtime_get_sync(dev); | ||
999 | mutex_lock(&chip->mutex); | ||
1000 | chip->lux_wait_fresh_res = true; | ||
1001 | apds990x_force_a_refresh(chip); | ||
1002 | apds990x_force_p_refresh(chip); | ||
1003 | mutex_unlock(&chip->mutex); | ||
1004 | } else { | ||
1005 | if (!pm_runtime_suspended(dev)) | ||
1006 | pm_runtime_put(dev); | ||
1007 | } | ||
1008 | return len; | ||
1009 | } | ||
1010 | |||
1011 | static DEVICE_ATTR(power_state, S_IRUGO | S_IWUSR, | ||
1012 | apds990x_power_state_show, | ||
1013 | apds990x_power_state_store); | ||
1014 | |||
1015 | static ssize_t apds990x_chip_id_show(struct device *dev, | ||
1016 | struct device_attribute *attr, char *buf) | ||
1017 | { | ||
1018 | struct apds990x_chip *chip = dev_get_drvdata(dev); | ||
1019 | return sprintf(buf, "%s %d\n", chip->chipname, chip->revision); | ||
1020 | } | ||
1021 | |||
1022 | static DEVICE_ATTR(chip_id, S_IRUGO, apds990x_chip_id_show, NULL); | ||
1023 | |||
1024 | static struct attribute *sysfs_attrs_ctrl[] = { | ||
1025 | &dev_attr_lux0_calibscale.attr, | ||
1026 | &dev_attr_lux0_calibscale_default.attr, | ||
1027 | &dev_attr_lux0_input.attr, | ||
1028 | &dev_attr_lux0_sensor_range.attr, | ||
1029 | &dev_attr_lux0_rate.attr, | ||
1030 | &dev_attr_lux0_rate_avail.attr, | ||
1031 | &dev_attr_lux0_thresh_above_value.attr, | ||
1032 | &dev_attr_lux0_thresh_below_value.attr, | ||
1033 | &dev_attr_prox0_raw_en.attr, | ||
1034 | &dev_attr_prox0_raw.attr, | ||
1035 | &dev_attr_prox0_sensor_range.attr, | ||
1036 | &dev_attr_prox0_thresh_above_value.attr, | ||
1037 | &dev_attr_prox0_reporting_mode.attr, | ||
1038 | &dev_attr_prox0_reporting_mode_avail.attr, | ||
1039 | &dev_attr_chip_id.attr, | ||
1040 | &dev_attr_power_state.attr, | ||
1041 | NULL | ||
1042 | }; | ||
1043 | |||
1044 | static struct attribute_group apds990x_attribute_group[] = { | ||
1045 | {.attrs = sysfs_attrs_ctrl }, | ||
1046 | }; | ||
1047 | |||
1048 | static int __devinit apds990x_probe(struct i2c_client *client, | ||
1049 | const struct i2c_device_id *id) | ||
1050 | { | ||
1051 | struct apds990x_chip *chip; | ||
1052 | int err; | ||
1053 | |||
1054 | chip = kzalloc(sizeof *chip, GFP_KERNEL); | ||
1055 | if (!chip) | ||
1056 | return -ENOMEM; | ||
1057 | |||
1058 | i2c_set_clientdata(client, chip); | ||
1059 | chip->client = client; | ||
1060 | |||
1061 | init_waitqueue_head(&chip->wait); | ||
1062 | mutex_init(&chip->mutex); | ||
1063 | chip->pdata = client->dev.platform_data; | ||
1064 | |||
1065 | if (chip->pdata == NULL) { | ||
1066 | dev_err(&client->dev, "platform data is mandatory\n"); | ||
1067 | err = -EINVAL; | ||
1068 | goto fail1; | ||
1069 | } | ||
1070 | |||
1071 | if (chip->pdata->cf.ga == 0) { | ||
1072 | /* set uncovered sensor default parameters */ | ||
1073 | chip->cf.ga = 1966; /* 0.48 * APDS_PARAM_SCALE */ | ||
1074 | chip->cf.cf1 = 4096; /* 1.00 * APDS_PARAM_SCALE */ | ||
1075 | chip->cf.irf1 = 9134; /* 2.23 * APDS_PARAM_SCALE */ | ||
1076 | chip->cf.cf2 = 2867; /* 0.70 * APDS_PARAM_SCALE */ | ||
1077 | chip->cf.irf2 = 5816; /* 1.42 * APDS_PARAM_SCALE */ | ||
1078 | chip->cf.df = 52; | ||
1079 | } else { | ||
1080 | chip->cf = chip->pdata->cf; | ||
1081 | } | ||
1082 | |||
1083 | /* precalculate inverse chip factors for threshold control */ | ||
1084 | chip->rcf.afactor = | ||
1085 | (chip->cf.irf1 - chip->cf.irf2) * APDS_PARAM_SCALE / | ||
1086 | (chip->cf.cf1 - chip->cf.cf2); | ||
1087 | chip->rcf.cf1 = APDS_PARAM_SCALE * APDS_PARAM_SCALE / | ||
1088 | chip->cf.cf1; | ||
1089 | chip->rcf.irf1 = chip->cf.irf1 * APDS_PARAM_SCALE / | ||
1090 | chip->cf.cf1; | ||
1091 | chip->rcf.cf2 = APDS_PARAM_SCALE * APDS_PARAM_SCALE / | ||
1092 | chip->cf.cf2; | ||
1093 | chip->rcf.irf2 = chip->cf.irf2 * APDS_PARAM_SCALE / | ||
1094 | chip->cf.cf2; | ||
1095 | |||
1096 | /* Set something to start with */ | ||
1097 | chip->lux_thres_hi = APDS_LUX_DEF_THRES_HI; | ||
1098 | chip->lux_thres_lo = APDS_LUX_DEF_THRES_LO; | ||
1099 | chip->lux_calib = APDS_LUX_NEUTRAL_CALIB_VALUE; | ||
1100 | |||
1101 | chip->prox_thres = APDS_PROX_DEF_THRES; | ||
1102 | chip->pdrive = chip->pdata->pdrive; | ||
1103 | chip->pdiode = APDS_PDIODE_IR; | ||
1104 | chip->pgain = APDS_PGAIN_1X; | ||
1105 | chip->prox_calib = APDS_PROX_NEUTRAL_CALIB_VALUE; | ||
1106 | chip->prox_persistence = APDS_DEFAULT_PROX_PERS; | ||
1107 | chip->prox_continuous_mode = false; | ||
1108 | |||
1109 | chip->regs[0].supply = reg_vcc; | ||
1110 | chip->regs[1].supply = reg_vled; | ||
1111 | |||
1112 | err = regulator_bulk_get(&client->dev, | ||
1113 | ARRAY_SIZE(chip->regs), chip->regs); | ||
1114 | if (err < 0) { | ||
1115 | dev_err(&client->dev, "Cannot get regulators\n"); | ||
1116 | goto fail1; | ||
1117 | } | ||
1118 | |||
1119 | err = regulator_bulk_enable(ARRAY_SIZE(chip->regs), chip->regs); | ||
1120 | if (err < 0) { | ||
1121 | dev_err(&client->dev, "Cannot enable regulators\n"); | ||
1122 | goto fail2; | ||
1123 | } | ||
1124 | |||
1125 | usleep_range(APDS_STARTUP_DELAY, 2 * APDS_STARTUP_DELAY); | ||
1126 | |||
1127 | err = apds990x_detect(chip); | ||
1128 | if (err < 0) { | ||
1129 | dev_err(&client->dev, "APDS990X not found\n"); | ||
1130 | goto fail3; | ||
1131 | } | ||
1132 | |||
1133 | pm_runtime_set_active(&client->dev); | ||
1134 | |||
1135 | apds990x_configure(chip); | ||
1136 | apds990x_set_arate(chip, APDS_LUX_DEFAULT_RATE); | ||
1137 | apds990x_mode_on(chip); | ||
1138 | |||
1139 | pm_runtime_enable(&client->dev); | ||
1140 | |||
1141 | if (chip->pdata->setup_resources) { | ||
1142 | err = chip->pdata->setup_resources(); | ||
1143 | if (err) { | ||
1144 | err = -EINVAL; | ||
1145 | goto fail3; | ||
1146 | } | ||
1147 | } | ||
1148 | |||
1149 | err = sysfs_create_group(&chip->client->dev.kobj, | ||
1150 | apds990x_attribute_group); | ||
1151 | if (err < 0) { | ||
1152 | dev_err(&chip->client->dev, "Sysfs registration failed\n"); | ||
1153 | goto fail4; | ||
1154 | } | ||
1155 | |||
1156 | err = request_threaded_irq(client->irq, NULL, | ||
1157 | apds990x_irq, | ||
1158 | IRQF_TRIGGER_FALLING | IRQF_TRIGGER_LOW | | ||
1159 | IRQF_ONESHOT, | ||
1160 | "apds990x", chip); | ||
1161 | if (err) { | ||
1162 | dev_err(&client->dev, "could not get IRQ %d\n", | ||
1163 | client->irq); | ||
1164 | goto fail5; | ||
1165 | } | ||
1166 | return err; | ||
1167 | fail5: | ||
1168 | sysfs_remove_group(&chip->client->dev.kobj, | ||
1169 | &apds990x_attribute_group[0]); | ||
1170 | fail4: | ||
1171 | if (chip->pdata && chip->pdata->release_resources) | ||
1172 | chip->pdata->release_resources(); | ||
1173 | fail3: | ||
1174 | regulator_bulk_disable(ARRAY_SIZE(chip->regs), chip->regs); | ||
1175 | fail2: | ||
1176 | regulator_bulk_free(ARRAY_SIZE(chip->regs), chip->regs); | ||
1177 | fail1: | ||
1178 | kfree(chip); | ||
1179 | return err; | ||
1180 | } | ||
1181 | |||
1182 | static int __devexit apds990x_remove(struct i2c_client *client) | ||
1183 | { | ||
1184 | struct apds990x_chip *chip = i2c_get_clientdata(client); | ||
1185 | |||
1186 | free_irq(client->irq, chip); | ||
1187 | sysfs_remove_group(&chip->client->dev.kobj, | ||
1188 | apds990x_attribute_group); | ||
1189 | |||
1190 | if (chip->pdata && chip->pdata->release_resources) | ||
1191 | chip->pdata->release_resources(); | ||
1192 | |||
1193 | if (!pm_runtime_suspended(&client->dev)) | ||
1194 | apds990x_chip_off(chip); | ||
1195 | |||
1196 | pm_runtime_disable(&client->dev); | ||
1197 | pm_runtime_set_suspended(&client->dev); | ||
1198 | |||
1199 | regulator_bulk_free(ARRAY_SIZE(chip->regs), chip->regs); | ||
1200 | |||
1201 | kfree(chip); | ||
1202 | return 0; | ||
1203 | } | ||
1204 | |||
1205 | #ifdef CONFIG_PM | ||
1206 | static int apds990x_suspend(struct device *dev) | ||
1207 | { | ||
1208 | struct i2c_client *client = container_of(dev, struct i2c_client, dev); | ||
1209 | struct apds990x_chip *chip = i2c_get_clientdata(client); | ||
1210 | |||
1211 | apds990x_chip_off(chip); | ||
1212 | return 0; | ||
1213 | } | ||
1214 | |||
1215 | static int apds990x_resume(struct device *dev) | ||
1216 | { | ||
1217 | struct i2c_client *client = container_of(dev, struct i2c_client, dev); | ||
1218 | struct apds990x_chip *chip = i2c_get_clientdata(client); | ||
1219 | |||
1220 | /* | ||
1221 | * If we were enabled at suspend time, it is expected | ||
1222 | * everything works nice and smoothly. Chip_on is enough | ||
1223 | */ | ||
1224 | apds990x_chip_on(chip); | ||
1225 | |||
1226 | return 0; | ||
1227 | } | ||
1228 | #else | ||
1229 | #define apds990x_suspend NULL | ||
1230 | #define apds990x_resume NULL | ||
1231 | #define apds990x_shutdown NULL | ||
1232 | #endif | ||
1233 | |||
1234 | #ifdef CONFIG_PM_RUNTIME | ||
1235 | static int apds990x_runtime_suspend(struct device *dev) | ||
1236 | { | ||
1237 | struct i2c_client *client = container_of(dev, struct i2c_client, dev); | ||
1238 | struct apds990x_chip *chip = i2c_get_clientdata(client); | ||
1239 | |||
1240 | apds990x_chip_off(chip); | ||
1241 | return 0; | ||
1242 | } | ||
1243 | |||
1244 | static int apds990x_runtime_resume(struct device *dev) | ||
1245 | { | ||
1246 | struct i2c_client *client = container_of(dev, struct i2c_client, dev); | ||
1247 | struct apds990x_chip *chip = i2c_get_clientdata(client); | ||
1248 | |||
1249 | apds990x_chip_on(chip); | ||
1250 | return 0; | ||
1251 | } | ||
1252 | |||
1253 | #endif | ||
1254 | |||
1255 | static const struct i2c_device_id apds990x_id[] = { | ||
1256 | {"apds990x", 0 }, | ||
1257 | {} | ||
1258 | }; | ||
1259 | |||
1260 | MODULE_DEVICE_TABLE(i2c, apds990x_id); | ||
1261 | |||
1262 | static const struct dev_pm_ops apds990x_pm_ops = { | ||
1263 | SET_SYSTEM_SLEEP_PM_OPS(apds990x_suspend, apds990x_resume) | ||
1264 | SET_RUNTIME_PM_OPS(apds990x_runtime_suspend, | ||
1265 | apds990x_runtime_resume, | ||
1266 | NULL) | ||
1267 | }; | ||
1268 | |||
1269 | static struct i2c_driver apds990x_driver = { | ||
1270 | .driver = { | ||
1271 | .name = "apds990x", | ||
1272 | .owner = THIS_MODULE, | ||
1273 | .pm = &apds990x_pm_ops, | ||
1274 | }, | ||
1275 | .probe = apds990x_probe, | ||
1276 | .remove = __devexit_p(apds990x_remove), | ||
1277 | .id_table = apds990x_id, | ||
1278 | }; | ||
1279 | |||
1280 | static int __init apds990x_init(void) | ||
1281 | { | ||
1282 | return i2c_add_driver(&apds990x_driver); | ||
1283 | } | ||
1284 | |||
1285 | static void __exit apds990x_exit(void) | ||
1286 | { | ||
1287 | i2c_del_driver(&apds990x_driver); | ||
1288 | } | ||
1289 | |||
1290 | MODULE_DESCRIPTION("APDS990X combined ALS and proximity sensor"); | ||
1291 | MODULE_AUTHOR("Samu Onkalo, Nokia Corporation"); | ||
1292 | MODULE_LICENSE("GPL v2"); | ||
1293 | |||
1294 | module_init(apds990x_init); | ||
1295 | module_exit(apds990x_exit); | ||
diff --git a/drivers/misc/bh1770glc.c b/drivers/misc/bh1770glc.c new file mode 100644 index 000000000000..cee632e645e1 --- /dev/null +++ b/drivers/misc/bh1770glc.c | |||
@@ -0,0 +1,1413 @@ | |||
1 | /* | ||
2 | * This file is part of the ROHM BH1770GLC / OSRAM SFH7770 sensor driver. | ||
3 | * Chip is combined proximity and ambient light sensor. | ||
4 | * | ||
5 | * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). | ||
6 | * | ||
7 | * Contact: Samu Onkalo <samu.p.onkalo@nokia.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or | ||
10 | * modify it under the terms of the GNU General Public License | ||
11 | * version 2 as published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
21 | * 02110-1301 USA | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | #include <linux/kernel.h> | ||
26 | #include <linux/module.h> | ||
27 | #include <linux/i2c.h> | ||
28 | #include <linux/interrupt.h> | ||
29 | #include <linux/mutex.h> | ||
30 | #include <linux/i2c/bh1770glc.h> | ||
31 | #include <linux/regulator/consumer.h> | ||
32 | #include <linux/pm_runtime.h> | ||
33 | #include <linux/workqueue.h> | ||
34 | #include <linux/delay.h> | ||
35 | #include <linux/wait.h> | ||
36 | #include <linux/slab.h> | ||
37 | |||
38 | #define BH1770_ALS_CONTROL 0x80 /* ALS operation mode control */ | ||
39 | #define BH1770_PS_CONTROL 0x81 /* PS operation mode control */ | ||
40 | #define BH1770_I_LED 0x82 /* active LED and LED1, LED2 current */ | ||
41 | #define BH1770_I_LED3 0x83 /* LED3 current setting */ | ||
42 | #define BH1770_ALS_PS_MEAS 0x84 /* Forced mode trigger */ | ||
43 | #define BH1770_PS_MEAS_RATE 0x85 /* PS meas. rate at stand alone mode */ | ||
44 | #define BH1770_ALS_MEAS_RATE 0x86 /* ALS meas. rate at stand alone mode */ | ||
45 | #define BH1770_PART_ID 0x8a /* Part number and revision ID */ | ||
46 | #define BH1770_MANUFACT_ID 0x8b /* Manufacturerer ID */ | ||
47 | #define BH1770_ALS_DATA_0 0x8c /* ALS DATA low byte */ | ||
48 | #define BH1770_ALS_DATA_1 0x8d /* ALS DATA high byte */ | ||
49 | #define BH1770_ALS_PS_STATUS 0x8e /* Measurement data and int status */ | ||
50 | #define BH1770_PS_DATA_LED1 0x8f /* PS data from LED1 */ | ||
51 | #define BH1770_PS_DATA_LED2 0x90 /* PS data from LED2 */ | ||
52 | #define BH1770_PS_DATA_LED3 0x91 /* PS data from LED3 */ | ||
53 | #define BH1770_INTERRUPT 0x92 /* Interrupt setting */ | ||
54 | #define BH1770_PS_TH_LED1 0x93 /* PS interrupt threshold for LED1 */ | ||
55 | #define BH1770_PS_TH_LED2 0x94 /* PS interrupt threshold for LED2 */ | ||
56 | #define BH1770_PS_TH_LED3 0x95 /* PS interrupt threshold for LED3 */ | ||
57 | #define BH1770_ALS_TH_UP_0 0x96 /* ALS upper threshold low byte */ | ||
58 | #define BH1770_ALS_TH_UP_1 0x97 /* ALS upper threshold high byte */ | ||
59 | #define BH1770_ALS_TH_LOW_0 0x98 /* ALS lower threshold low byte */ | ||
60 | #define BH1770_ALS_TH_LOW_1 0x99 /* ALS lower threshold high byte */ | ||
61 | |||
62 | /* MANUFACT_ID */ | ||
63 | #define BH1770_MANUFACT_ROHM 0x01 | ||
64 | #define BH1770_MANUFACT_OSRAM 0x03 | ||
65 | |||
66 | /* PART_ID */ | ||
67 | #define BH1770_PART 0x90 | ||
68 | #define BH1770_PART_MASK 0xf0 | ||
69 | #define BH1770_REV_MASK 0x0f | ||
70 | #define BH1770_REV_SHIFT 0 | ||
71 | #define BH1770_REV_0 0x00 | ||
72 | #define BH1770_REV_1 0x01 | ||
73 | |||
74 | /* Operating modes for both */ | ||
75 | #define BH1770_STANDBY 0x00 | ||
76 | #define BH1770_FORCED 0x02 | ||
77 | #define BH1770_STANDALONE 0x03 | ||
78 | #define BH1770_SWRESET (0x01 << 2) | ||
79 | |||
80 | #define BH1770_PS_TRIG_MEAS (1 << 0) | ||
81 | #define BH1770_ALS_TRIG_MEAS (1 << 1) | ||
82 | |||
83 | /* Interrupt control */ | ||
84 | #define BH1770_INT_OUTPUT_MODE (1 << 3) /* 0 = latched */ | ||
85 | #define BH1770_INT_POLARITY (1 << 2) /* 1 = active high */ | ||
86 | #define BH1770_INT_ALS_ENA (1 << 1) | ||
87 | #define BH1770_INT_PS_ENA (1 << 0) | ||
88 | |||
89 | /* Interrupt status */ | ||
90 | #define BH1770_INT_LED1_DATA (1 << 0) | ||
91 | #define BH1770_INT_LED1_INT (1 << 1) | ||
92 | #define BH1770_INT_LED2_DATA (1 << 2) | ||
93 | #define BH1770_INT_LED2_INT (1 << 3) | ||
94 | #define BH1770_INT_LED3_DATA (1 << 4) | ||
95 | #define BH1770_INT_LED3_INT (1 << 5) | ||
96 | #define BH1770_INT_LEDS_INT ((1 << 1) | (1 << 3) | (1 << 5)) | ||
97 | #define BH1770_INT_ALS_DATA (1 << 6) | ||
98 | #define BH1770_INT_ALS_INT (1 << 7) | ||
99 | |||
100 | /* Led channels */ | ||
101 | #define BH1770_LED1 0x00 | ||
102 | |||
103 | #define BH1770_DISABLE 0 | ||
104 | #define BH1770_ENABLE 1 | ||
105 | #define BH1770_PROX_CHANNELS 1 | ||
106 | |||
107 | #define BH1770_LUX_DEFAULT_RATE 1 /* Index to lux rate table */ | ||
108 | #define BH1770_PROX_DEFAULT_RATE 1 /* Direct HW value =~ 50Hz */ | ||
109 | #define BH1770_PROX_DEF_RATE_THRESH 6 /* Direct HW value =~ 5 Hz */ | ||
110 | #define BH1770_STARTUP_DELAY 50 | ||
111 | #define BH1770_RESET_TIME 10 | ||
112 | #define BH1770_TIMEOUT 2100 /* Timeout in 2.1 seconds */ | ||
113 | |||
114 | #define BH1770_LUX_RANGE 65535 | ||
115 | #define BH1770_PROX_RANGE 255 | ||
116 | #define BH1770_COEF_SCALER 1024 | ||
117 | #define BH1770_CALIB_SCALER 8192 | ||
118 | #define BH1770_LUX_NEUTRAL_CALIB_VALUE (1 * BH1770_CALIB_SCALER) | ||
119 | #define BH1770_LUX_DEF_THRES 1000 | ||
120 | #define BH1770_PROX_DEF_THRES 70 | ||
121 | #define BH1770_PROX_DEF_ABS_THRES 100 | ||
122 | #define BH1770_DEFAULT_PERSISTENCE 10 | ||
123 | #define BH1770_PROX_MAX_PERSISTENCE 50 | ||
124 | #define BH1770_LUX_GA_SCALE 16384 | ||
125 | #define BH1770_LUX_CF_SCALE 2048 /* CF ChipFactor */ | ||
126 | #define BH1770_NEUTRAL_CF BH1770_LUX_CF_SCALE | ||
127 | #define BH1770_LUX_CORR_SCALE 4096 | ||
128 | |||
129 | #define PROX_ABOVE_THRESHOLD 1 | ||
130 | #define PROX_BELOW_THRESHOLD 0 | ||
131 | |||
132 | #define PROX_IGNORE_LUX_LIMIT 500 | ||
133 | |||
134 | struct bh1770_chip { | ||
135 | struct bh1770_platform_data *pdata; | ||
136 | char chipname[10]; | ||
137 | u8 revision; | ||
138 | struct i2c_client *client; | ||
139 | struct regulator_bulk_data regs[2]; | ||
140 | struct mutex mutex; /* avoid parallel access */ | ||
141 | wait_queue_head_t wait; | ||
142 | |||
143 | bool int_mode_prox; | ||
144 | bool int_mode_lux; | ||
145 | struct delayed_work prox_work; | ||
146 | u32 lux_cf; /* Chip specific factor */ | ||
147 | u32 lux_ga; | ||
148 | u32 lux_calib; | ||
149 | int lux_rate_index; | ||
150 | u32 lux_corr; | ||
151 | u16 lux_data_raw; | ||
152 | u16 lux_threshold_hi; | ||
153 | u16 lux_threshold_lo; | ||
154 | u16 lux_thres_hi_onchip; | ||
155 | u16 lux_thres_lo_onchip; | ||
156 | bool lux_wait_result; | ||
157 | |||
158 | int prox_enable_count; | ||
159 | u16 prox_coef; | ||
160 | u16 prox_const; | ||
161 | int prox_rate; | ||
162 | int prox_rate_threshold; | ||
163 | u8 prox_persistence; | ||
164 | u8 prox_persistence_counter; | ||
165 | u8 prox_data; | ||
166 | u8 prox_threshold; | ||
167 | u8 prox_threshold_hw; | ||
168 | bool prox_force_update; | ||
169 | u8 prox_abs_thres; | ||
170 | u8 prox_led; | ||
171 | }; | ||
172 | |||
173 | static const char reg_vcc[] = "Vcc"; | ||
174 | static const char reg_vleds[] = "Vleds"; | ||
175 | |||
176 | /* | ||
177 | * Supported stand alone rates in ms from chip data sheet | ||
178 | * {10, 20, 30, 40, 70, 100, 200, 500, 1000, 2000}; | ||
179 | */ | ||
180 | static const s16 prox_rates_hz[] = {100, 50, 33, 25, 14, 10, 5, 2}; | ||
181 | static const s16 prox_rates_ms[] = {10, 20, 30, 40, 70, 100, 200, 500}; | ||
182 | |||
183 | /* Supported IR-led currents in mA */ | ||
184 | static const u8 prox_curr_ma[] = {5, 10, 20, 50, 100, 150, 200}; | ||
185 | |||
186 | /* | ||
187 | * Supported stand alone rates in ms from chip data sheet | ||
188 | * {100, 200, 500, 1000, 2000}; | ||
189 | */ | ||
190 | static const s16 lux_rates_hz[] = {10, 5, 2, 1, 0}; | ||
191 | |||
192 | /* | ||
193 | * interrupt control functions are called while keeping chip->mutex | ||
194 | * excluding module probe / remove | ||
195 | */ | ||
196 | static inline int bh1770_lux_interrupt_control(struct bh1770_chip *chip, | ||
197 | int lux) | ||
198 | { | ||
199 | chip->int_mode_lux = lux; | ||
200 | /* Set interrupt modes, interrupt active low, latched */ | ||
201 | return i2c_smbus_write_byte_data(chip->client, | ||
202 | BH1770_INTERRUPT, | ||
203 | (lux << 1) | chip->int_mode_prox); | ||
204 | } | ||
205 | |||
206 | static inline int bh1770_prox_interrupt_control(struct bh1770_chip *chip, | ||
207 | int ps) | ||
208 | { | ||
209 | chip->int_mode_prox = ps; | ||
210 | return i2c_smbus_write_byte_data(chip->client, | ||
211 | BH1770_INTERRUPT, | ||
212 | (chip->int_mode_lux << 1) | (ps << 0)); | ||
213 | } | ||
214 | |||
215 | /* chip->mutex is always kept here */ | ||
216 | static int bh1770_lux_rate(struct bh1770_chip *chip, int rate_index) | ||
217 | { | ||
218 | /* sysfs may call this when the chip is powered off */ | ||
219 | if (pm_runtime_suspended(&chip->client->dev)) | ||
220 | return 0; | ||
221 | |||
222 | /* Proper proximity response needs fastest lux rate (100ms) */ | ||
223 | if (chip->prox_enable_count) | ||
224 | rate_index = 0; | ||
225 | |||
226 | return i2c_smbus_write_byte_data(chip->client, | ||
227 | BH1770_ALS_MEAS_RATE, | ||
228 | rate_index); | ||
229 | } | ||
230 | |||
231 | static int bh1770_prox_rate(struct bh1770_chip *chip, int mode) | ||
232 | { | ||
233 | int rate; | ||
234 | |||
235 | rate = (mode == PROX_ABOVE_THRESHOLD) ? | ||
236 | chip->prox_rate_threshold : chip->prox_rate; | ||
237 | |||
238 | return i2c_smbus_write_byte_data(chip->client, | ||
239 | BH1770_PS_MEAS_RATE, | ||
240 | rate); | ||
241 | } | ||
242 | |||
243 | /* InfraredLED is controlled by the chip during proximity scanning */ | ||
244 | static inline int bh1770_led_cfg(struct bh1770_chip *chip) | ||
245 | { | ||
246 | /* LED cfg, current for leds 1 and 2 */ | ||
247 | return i2c_smbus_write_byte_data(chip->client, | ||
248 | BH1770_I_LED, | ||
249 | (BH1770_LED1 << 6) | | ||
250 | (BH1770_LED_5mA << 3) | | ||
251 | chip->prox_led); | ||
252 | } | ||
253 | |||
254 | /* | ||
255 | * Following two functions converts raw ps values from HW to normalized | ||
256 | * values. Purpose is to compensate differences between different sensor | ||
257 | * versions and variants so that result means about the same between | ||
258 | * versions. | ||
259 | */ | ||
260 | static inline u8 bh1770_psraw_to_adjusted(struct bh1770_chip *chip, u8 psraw) | ||
261 | { | ||
262 | u16 adjusted; | ||
263 | adjusted = (u16)(((u32)(psraw + chip->prox_const) * chip->prox_coef) / | ||
264 | BH1770_COEF_SCALER); | ||
265 | if (adjusted > BH1770_PROX_RANGE) | ||
266 | adjusted = BH1770_PROX_RANGE; | ||
267 | return adjusted; | ||
268 | } | ||
269 | |||
270 | static inline u8 bh1770_psadjusted_to_raw(struct bh1770_chip *chip, u8 ps) | ||
271 | { | ||
272 | u16 raw; | ||
273 | |||
274 | raw = (((u32)ps * BH1770_COEF_SCALER) / chip->prox_coef); | ||
275 | if (raw > chip->prox_const) | ||
276 | raw = raw - chip->prox_const; | ||
277 | else | ||
278 | raw = 0; | ||
279 | return raw; | ||
280 | } | ||
281 | |||
282 | /* | ||
283 | * Following two functions converts raw lux values from HW to normalized | ||
284 | * values. Purpose is to compensate differences between different sensor | ||
285 | * versions and variants so that result means about the same between | ||
286 | * versions. Chip->mutex is kept when this is called. | ||
287 | */ | ||
288 | static int bh1770_prox_set_threshold(struct bh1770_chip *chip) | ||
289 | { | ||
290 | u8 tmp = 0; | ||
291 | |||
292 | /* sysfs may call this when the chip is powered off */ | ||
293 | if (pm_runtime_suspended(&chip->client->dev)) | ||
294 | return 0; | ||
295 | |||
296 | tmp = bh1770_psadjusted_to_raw(chip, chip->prox_threshold); | ||
297 | chip->prox_threshold_hw = tmp; | ||
298 | |||
299 | return i2c_smbus_write_byte_data(chip->client, BH1770_PS_TH_LED1, | ||
300 | tmp); | ||
301 | } | ||
302 | |||
303 | static inline u16 bh1770_lux_raw_to_adjusted(struct bh1770_chip *chip, u16 raw) | ||
304 | { | ||
305 | u32 lux; | ||
306 | lux = ((u32)raw * chip->lux_corr) / BH1770_LUX_CORR_SCALE; | ||
307 | return min(lux, (u32)BH1770_LUX_RANGE); | ||
308 | } | ||
309 | |||
310 | static inline u16 bh1770_lux_adjusted_to_raw(struct bh1770_chip *chip, | ||
311 | u16 adjusted) | ||
312 | { | ||
313 | return (u32)adjusted * BH1770_LUX_CORR_SCALE / chip->lux_corr; | ||
314 | } | ||
315 | |||
316 | /* chip->mutex is kept when this is called */ | ||
317 | static int bh1770_lux_update_thresholds(struct bh1770_chip *chip, | ||
318 | u16 threshold_hi, u16 threshold_lo) | ||
319 | { | ||
320 | u8 data[4]; | ||
321 | int ret; | ||
322 | |||
323 | /* sysfs may call this when the chip is powered off */ | ||
324 | if (pm_runtime_suspended(&chip->client->dev)) | ||
325 | return 0; | ||
326 | |||
327 | /* | ||
328 | * Compensate threshold values with the correction factors if not | ||
329 | * set to minimum or maximum. | ||
330 | * Min & max values disables interrupts. | ||
331 | */ | ||
332 | if (threshold_hi != BH1770_LUX_RANGE && threshold_hi != 0) | ||
333 | threshold_hi = bh1770_lux_adjusted_to_raw(chip, threshold_hi); | ||
334 | |||
335 | if (threshold_lo != BH1770_LUX_RANGE && threshold_lo != 0) | ||
336 | threshold_lo = bh1770_lux_adjusted_to_raw(chip, threshold_lo); | ||
337 | |||
338 | if (chip->lux_thres_hi_onchip == threshold_hi && | ||
339 | chip->lux_thres_lo_onchip == threshold_lo) | ||
340 | return 0; | ||
341 | |||
342 | chip->lux_thres_hi_onchip = threshold_hi; | ||
343 | chip->lux_thres_lo_onchip = threshold_lo; | ||
344 | |||
345 | data[0] = threshold_hi; | ||
346 | data[1] = threshold_hi >> 8; | ||
347 | data[2] = threshold_lo; | ||
348 | data[3] = threshold_lo >> 8; | ||
349 | |||
350 | ret = i2c_smbus_write_i2c_block_data(chip->client, | ||
351 | BH1770_ALS_TH_UP_0, | ||
352 | ARRAY_SIZE(data), | ||
353 | data); | ||
354 | return ret; | ||
355 | } | ||
356 | |||
357 | static int bh1770_lux_get_result(struct bh1770_chip *chip) | ||
358 | { | ||
359 | u16 data; | ||
360 | int ret; | ||
361 | |||
362 | ret = i2c_smbus_read_byte_data(chip->client, BH1770_ALS_DATA_0); | ||
363 | if (ret < 0) | ||
364 | return ret; | ||
365 | |||
366 | data = ret & 0xff; | ||
367 | ret = i2c_smbus_read_byte_data(chip->client, BH1770_ALS_DATA_1); | ||
368 | if (ret < 0) | ||
369 | return ret; | ||
370 | |||
371 | chip->lux_data_raw = data | ((ret & 0xff) << 8); | ||
372 | |||
373 | return 0; | ||
374 | } | ||
375 | |||
376 | /* Calculate correction value which contains chip and device specific parts */ | ||
377 | static u32 bh1770_get_corr_value(struct bh1770_chip *chip) | ||
378 | { | ||
379 | u32 tmp; | ||
380 | /* Impact of glass attenuation correction */ | ||
381 | tmp = (BH1770_LUX_CORR_SCALE * chip->lux_ga) / BH1770_LUX_GA_SCALE; | ||
382 | /* Impact of chip factor correction */ | ||
383 | tmp = (tmp * chip->lux_cf) / BH1770_LUX_CF_SCALE; | ||
384 | /* Impact of Device specific calibration correction */ | ||
385 | tmp = (tmp * chip->lux_calib) / BH1770_CALIB_SCALER; | ||
386 | return tmp; | ||
387 | } | ||
388 | |||
389 | static int bh1770_lux_read_result(struct bh1770_chip *chip) | ||
390 | { | ||
391 | bh1770_lux_get_result(chip); | ||
392 | return bh1770_lux_raw_to_adjusted(chip, chip->lux_data_raw); | ||
393 | } | ||
394 | |||
395 | /* | ||
396 | * Chip on / off functions are called while keeping mutex except probe | ||
397 | * or remove phase | ||
398 | */ | ||
399 | static int bh1770_chip_on(struct bh1770_chip *chip) | ||
400 | { | ||
401 | int ret = regulator_bulk_enable(ARRAY_SIZE(chip->regs), | ||
402 | chip->regs); | ||
403 | if (ret < 0) | ||
404 | return ret; | ||
405 | |||
406 | usleep_range(BH1770_STARTUP_DELAY, BH1770_STARTUP_DELAY * 2); | ||
407 | |||
408 | /* Reset the chip */ | ||
409 | i2c_smbus_write_byte_data(chip->client, BH1770_ALS_CONTROL, | ||
410 | BH1770_SWRESET); | ||
411 | usleep_range(BH1770_RESET_TIME, BH1770_RESET_TIME * 2); | ||
412 | |||
413 | /* | ||
414 | * ALS is started always since proximity needs als results | ||
415 | * for realibility estimation. | ||
416 | * Let's assume dark until the first ALS measurement is ready. | ||
417 | */ | ||
418 | chip->lux_data_raw = 0; | ||
419 | chip->prox_data = 0; | ||
420 | ret = i2c_smbus_write_byte_data(chip->client, | ||
421 | BH1770_ALS_CONTROL, BH1770_STANDALONE); | ||
422 | |||
423 | /* Assume reset defaults */ | ||
424 | chip->lux_thres_hi_onchip = BH1770_LUX_RANGE; | ||
425 | chip->lux_thres_lo_onchip = 0; | ||
426 | |||
427 | return ret; | ||
428 | } | ||
429 | |||
430 | static void bh1770_chip_off(struct bh1770_chip *chip) | ||
431 | { | ||
432 | i2c_smbus_write_byte_data(chip->client, | ||
433 | BH1770_INTERRUPT, BH1770_DISABLE); | ||
434 | i2c_smbus_write_byte_data(chip->client, | ||
435 | BH1770_ALS_CONTROL, BH1770_STANDBY); | ||
436 | i2c_smbus_write_byte_data(chip->client, | ||
437 | BH1770_PS_CONTROL, BH1770_STANDBY); | ||
438 | regulator_bulk_disable(ARRAY_SIZE(chip->regs), chip->regs); | ||
439 | } | ||
440 | |||
441 | /* chip->mutex is kept when this is called */ | ||
442 | static int bh1770_prox_mode_control(struct bh1770_chip *chip) | ||
443 | { | ||
444 | if (chip->prox_enable_count) { | ||
445 | chip->prox_force_update = true; /* Force immediate update */ | ||
446 | |||
447 | bh1770_lux_rate(chip, chip->lux_rate_index); | ||
448 | bh1770_prox_set_threshold(chip); | ||
449 | bh1770_led_cfg(chip); | ||
450 | bh1770_prox_rate(chip, PROX_BELOW_THRESHOLD); | ||
451 | bh1770_prox_interrupt_control(chip, BH1770_ENABLE); | ||
452 | i2c_smbus_write_byte_data(chip->client, | ||
453 | BH1770_PS_CONTROL, BH1770_STANDALONE); | ||
454 | } else { | ||
455 | chip->prox_data = 0; | ||
456 | bh1770_lux_rate(chip, chip->lux_rate_index); | ||
457 | bh1770_prox_interrupt_control(chip, BH1770_DISABLE); | ||
458 | i2c_smbus_write_byte_data(chip->client, | ||
459 | BH1770_PS_CONTROL, BH1770_STANDBY); | ||
460 | } | ||
461 | return 0; | ||
462 | } | ||
463 | |||
464 | /* chip->mutex is kept when this is called */ | ||
465 | static int bh1770_prox_read_result(struct bh1770_chip *chip) | ||
466 | { | ||
467 | int ret; | ||
468 | bool above; | ||
469 | u8 mode; | ||
470 | |||
471 | ret = i2c_smbus_read_byte_data(chip->client, BH1770_PS_DATA_LED1); | ||
472 | if (ret < 0) | ||
473 | goto out; | ||
474 | |||
475 | if (ret > chip->prox_threshold_hw) | ||
476 | above = true; | ||
477 | else | ||
478 | above = false; | ||
479 | |||
480 | /* | ||
481 | * when ALS levels goes above limit, proximity result may be | ||
482 | * false proximity. Thus ignore the result. With real proximity | ||
483 | * there is a shadow causing low als levels. | ||
484 | */ | ||
485 | if (chip->lux_data_raw > PROX_IGNORE_LUX_LIMIT) | ||
486 | ret = 0; | ||
487 | |||
488 | chip->prox_data = bh1770_psraw_to_adjusted(chip, ret); | ||
489 | |||
490 | /* Strong proximity level or force mode requires immediate response */ | ||
491 | if (chip->prox_data >= chip->prox_abs_thres || | ||
492 | chip->prox_force_update) | ||
493 | chip->prox_persistence_counter = chip->prox_persistence; | ||
494 | |||
495 | chip->prox_force_update = false; | ||
496 | |||
497 | /* Persistence filttering to reduce false proximity events */ | ||
498 | if (likely(above)) { | ||
499 | if (chip->prox_persistence_counter < chip->prox_persistence) { | ||
500 | chip->prox_persistence_counter++; | ||
501 | ret = -ENODATA; | ||
502 | } else { | ||
503 | mode = PROX_ABOVE_THRESHOLD; | ||
504 | ret = 0; | ||
505 | } | ||
506 | } else { | ||
507 | chip->prox_persistence_counter = 0; | ||
508 | mode = PROX_BELOW_THRESHOLD; | ||
509 | chip->prox_data = 0; | ||
510 | ret = 0; | ||
511 | } | ||
512 | |||
513 | /* Set proximity detection rate based on above or below value */ | ||
514 | if (ret == 0) { | ||
515 | bh1770_prox_rate(chip, mode); | ||
516 | sysfs_notify(&chip->client->dev.kobj, NULL, "prox0_raw"); | ||
517 | } | ||
518 | out: | ||
519 | return ret; | ||
520 | } | ||
521 | |||
522 | static int bh1770_detect(struct bh1770_chip *chip) | ||
523 | { | ||
524 | struct i2c_client *client = chip->client; | ||
525 | s32 ret; | ||
526 | u8 manu, part; | ||
527 | |||
528 | ret = i2c_smbus_read_byte_data(client, BH1770_MANUFACT_ID); | ||
529 | if (ret < 0) | ||
530 | goto error; | ||
531 | manu = (u8)ret; | ||
532 | |||
533 | ret = i2c_smbus_read_byte_data(client, BH1770_PART_ID); | ||
534 | if (ret < 0) | ||
535 | goto error; | ||
536 | part = (u8)ret; | ||
537 | |||
538 | chip->revision = (part & BH1770_REV_MASK) >> BH1770_REV_SHIFT; | ||
539 | chip->prox_coef = BH1770_COEF_SCALER; | ||
540 | chip->prox_const = 0; | ||
541 | chip->lux_cf = BH1770_NEUTRAL_CF; | ||
542 | |||
543 | if ((manu == BH1770_MANUFACT_ROHM) && | ||
544 | ((part & BH1770_PART_MASK) == BH1770_PART)) { | ||
545 | snprintf(chip->chipname, sizeof(chip->chipname), "BH1770GLC"); | ||
546 | return 0; | ||
547 | } | ||
548 | |||
549 | if ((manu == BH1770_MANUFACT_OSRAM) && | ||
550 | ((part & BH1770_PART_MASK) == BH1770_PART)) { | ||
551 | snprintf(chip->chipname, sizeof(chip->chipname), "SFH7770"); | ||
552 | /* Values selected by comparing different versions */ | ||
553 | chip->prox_coef = 819; /* 0.8 * BH1770_COEF_SCALER */ | ||
554 | chip->prox_const = 40; | ||
555 | return 0; | ||
556 | } | ||
557 | |||
558 | ret = -ENODEV; | ||
559 | error: | ||
560 | dev_dbg(&client->dev, "BH1770 or SFH7770 not found\n"); | ||
561 | |||
562 | return ret; | ||
563 | } | ||
564 | |||
565 | /* | ||
566 | * This work is re-scheduled at every proximity interrupt. | ||
567 | * If this work is running, it means that there hasn't been any | ||
568 | * proximity interrupt in time. Situation is handled as no-proximity. | ||
569 | * It would be nice to have low-threshold interrupt or interrupt | ||
570 | * when measurement and hi-threshold are both 0. But neither of those exists. | ||
571 | * This is a workaroud for missing HW feature. | ||
572 | */ | ||
573 | |||
574 | static void bh1770_prox_work(struct work_struct *work) | ||
575 | { | ||
576 | struct bh1770_chip *chip = | ||
577 | container_of(work, struct bh1770_chip, prox_work.work); | ||
578 | |||
579 | mutex_lock(&chip->mutex); | ||
580 | bh1770_prox_read_result(chip); | ||
581 | mutex_unlock(&chip->mutex); | ||
582 | } | ||
583 | |||
584 | /* This is threaded irq handler */ | ||
585 | static irqreturn_t bh1770_irq(int irq, void *data) | ||
586 | { | ||
587 | struct bh1770_chip *chip = data; | ||
588 | int status; | ||
589 | int rate = 0; | ||
590 | |||
591 | mutex_lock(&chip->mutex); | ||
592 | status = i2c_smbus_read_byte_data(chip->client, BH1770_ALS_PS_STATUS); | ||
593 | |||
594 | /* Acknowledge interrupt by reading this register */ | ||
595 | i2c_smbus_read_byte_data(chip->client, BH1770_INTERRUPT); | ||
596 | |||
597 | /* | ||
598 | * Check if there is fresh data available for als. | ||
599 | * If this is the very first data, update thresholds after that. | ||
600 | */ | ||
601 | if (status & BH1770_INT_ALS_DATA) { | ||
602 | bh1770_lux_get_result(chip); | ||
603 | if (unlikely(chip->lux_wait_result)) { | ||
604 | chip->lux_wait_result = false; | ||
605 | wake_up(&chip->wait); | ||
606 | bh1770_lux_update_thresholds(chip, | ||
607 | chip->lux_threshold_hi, | ||
608 | chip->lux_threshold_lo); | ||
609 | } | ||
610 | } | ||
611 | |||
612 | /* Disable interrupt logic to guarantee acknowledgement */ | ||
613 | i2c_smbus_write_byte_data(chip->client, BH1770_INTERRUPT, | ||
614 | (0 << 1) | (0 << 0)); | ||
615 | |||
616 | if ((status & BH1770_INT_ALS_INT)) | ||
617 | sysfs_notify(&chip->client->dev.kobj, NULL, "lux0_input"); | ||
618 | |||
619 | if (chip->int_mode_prox && (status & BH1770_INT_LEDS_INT)) { | ||
620 | rate = prox_rates_ms[chip->prox_rate_threshold]; | ||
621 | bh1770_prox_read_result(chip); | ||
622 | } | ||
623 | |||
624 | /* Re-enable interrupt logic */ | ||
625 | i2c_smbus_write_byte_data(chip->client, BH1770_INTERRUPT, | ||
626 | (chip->int_mode_lux << 1) | | ||
627 | (chip->int_mode_prox << 0)); | ||
628 | mutex_unlock(&chip->mutex); | ||
629 | |||
630 | /* | ||
631 | * Can't cancel work while keeping mutex since the work uses the | ||
632 | * same mutex. | ||
633 | */ | ||
634 | if (rate) { | ||
635 | /* | ||
636 | * Simulate missing no-proximity interrupt 50ms after the | ||
637 | * next expected interrupt time. | ||
638 | */ | ||
639 | cancel_delayed_work_sync(&chip->prox_work); | ||
640 | schedule_delayed_work(&chip->prox_work, | ||
641 | msecs_to_jiffies(rate + 50)); | ||
642 | } | ||
643 | return IRQ_HANDLED; | ||
644 | } | ||
645 | |||
646 | static ssize_t bh1770_power_state_store(struct device *dev, | ||
647 | struct device_attribute *attr, | ||
648 | const char *buf, size_t count) | ||
649 | { | ||
650 | struct bh1770_chip *chip = dev_get_drvdata(dev); | ||
651 | unsigned long value; | ||
652 | size_t ret; | ||
653 | |||
654 | if (strict_strtoul(buf, 0, &value)) | ||
655 | return -EINVAL; | ||
656 | |||
657 | mutex_lock(&chip->mutex); | ||
658 | if (value) { | ||
659 | pm_runtime_get_sync(dev); | ||
660 | |||
661 | ret = bh1770_lux_rate(chip, chip->lux_rate_index); | ||
662 | ret |= bh1770_lux_interrupt_control(chip, BH1770_ENABLE); | ||
663 | |||
664 | if (ret < 0) { | ||
665 | pm_runtime_put(dev); | ||
666 | goto leave; | ||
667 | } | ||
668 | |||
669 | /* This causes interrupt after the next measurement cycle */ | ||
670 | bh1770_lux_update_thresholds(chip, BH1770_LUX_DEF_THRES, | ||
671 | BH1770_LUX_DEF_THRES); | ||
672 | /* Inform that we are waiting for a result from ALS */ | ||
673 | chip->lux_wait_result = true; | ||
674 | bh1770_prox_mode_control(chip); | ||
675 | } else if (!pm_runtime_suspended(dev)) { | ||
676 | pm_runtime_put(dev); | ||
677 | } | ||
678 | ret = count; | ||
679 | leave: | ||
680 | mutex_unlock(&chip->mutex); | ||
681 | return ret; | ||
682 | } | ||
683 | |||
684 | static ssize_t bh1770_power_state_show(struct device *dev, | ||
685 | struct device_attribute *attr, char *buf) | ||
686 | { | ||
687 | return sprintf(buf, "%d\n", !pm_runtime_suspended(dev)); | ||
688 | } | ||
689 | |||
690 | static ssize_t bh1770_lux_result_show(struct device *dev, | ||
691 | struct device_attribute *attr, char *buf) | ||
692 | { | ||
693 | struct bh1770_chip *chip = dev_get_drvdata(dev); | ||
694 | ssize_t ret; | ||
695 | long timeout; | ||
696 | |||
697 | if (pm_runtime_suspended(dev)) | ||
698 | return -EIO; /* Chip is not enabled at all */ | ||
699 | |||
700 | timeout = wait_event_interruptible_timeout(chip->wait, | ||
701 | !chip->lux_wait_result, | ||
702 | msecs_to_jiffies(BH1770_TIMEOUT)); | ||
703 | if (!timeout) | ||
704 | return -EIO; | ||
705 | |||
706 | mutex_lock(&chip->mutex); | ||
707 | ret = sprintf(buf, "%d\n", bh1770_lux_read_result(chip)); | ||
708 | mutex_unlock(&chip->mutex); | ||
709 | |||
710 | return ret; | ||
711 | } | ||
712 | |||
713 | static ssize_t bh1770_lux_range_show(struct device *dev, | ||
714 | struct device_attribute *attr, char *buf) | ||
715 | { | ||
716 | return sprintf(buf, "%d\n", BH1770_LUX_RANGE); | ||
717 | } | ||
718 | |||
719 | static ssize_t bh1770_prox_enable_store(struct device *dev, | ||
720 | struct device_attribute *attr, | ||
721 | const char *buf, size_t count) | ||
722 | { | ||
723 | struct bh1770_chip *chip = dev_get_drvdata(dev); | ||
724 | unsigned long value; | ||
725 | |||
726 | if (strict_strtoul(buf, 0, &value)) | ||
727 | return -EINVAL; | ||
728 | |||
729 | mutex_lock(&chip->mutex); | ||
730 | /* Assume no proximity. Sensor will tell real state soon */ | ||
731 | if (!chip->prox_enable_count) | ||
732 | chip->prox_data = 0; | ||
733 | |||
734 | if (value) | ||
735 | chip->prox_enable_count++; | ||
736 | else if (chip->prox_enable_count > 0) | ||
737 | chip->prox_enable_count--; | ||
738 | else | ||
739 | goto leave; | ||
740 | |||
741 | /* Run control only when chip is powered on */ | ||
742 | if (!pm_runtime_suspended(dev)) | ||
743 | bh1770_prox_mode_control(chip); | ||
744 | leave: | ||
745 | mutex_unlock(&chip->mutex); | ||
746 | return count; | ||
747 | } | ||
748 | |||
749 | static ssize_t bh1770_prox_enable_show(struct device *dev, | ||
750 | struct device_attribute *attr, char *buf) | ||
751 | { | ||
752 | struct bh1770_chip *chip = dev_get_drvdata(dev); | ||
753 | ssize_t len; | ||
754 | |||
755 | mutex_lock(&chip->mutex); | ||
756 | len = sprintf(buf, "%d\n", chip->prox_enable_count); | ||
757 | mutex_unlock(&chip->mutex); | ||
758 | return len; | ||
759 | } | ||
760 | |||
761 | static ssize_t bh1770_prox_result_show(struct device *dev, | ||
762 | struct device_attribute *attr, char *buf) | ||
763 | { | ||
764 | struct bh1770_chip *chip = dev_get_drvdata(dev); | ||
765 | ssize_t ret; | ||
766 | |||
767 | mutex_lock(&chip->mutex); | ||
768 | if (chip->prox_enable_count && !pm_runtime_suspended(dev)) | ||
769 | ret = sprintf(buf, "%d\n", chip->prox_data); | ||
770 | else | ||
771 | ret = -EIO; | ||
772 | mutex_unlock(&chip->mutex); | ||
773 | return ret; | ||
774 | } | ||
775 | |||
776 | static ssize_t bh1770_prox_range_show(struct device *dev, | ||
777 | struct device_attribute *attr, char *buf) | ||
778 | { | ||
779 | return sprintf(buf, "%d\n", BH1770_PROX_RANGE); | ||
780 | } | ||
781 | |||
782 | static ssize_t bh1770_get_prox_rate_avail(struct device *dev, | ||
783 | struct device_attribute *attr, char *buf) | ||
784 | { | ||
785 | int i; | ||
786 | int pos = 0; | ||
787 | for (i = 0; i < ARRAY_SIZE(prox_rates_hz); i++) | ||
788 | pos += sprintf(buf + pos, "%d ", prox_rates_hz[i]); | ||
789 | sprintf(buf + pos - 1, "\n"); | ||
790 | return pos; | ||
791 | } | ||
792 | |||
793 | static ssize_t bh1770_get_prox_rate_above(struct device *dev, | ||
794 | struct device_attribute *attr, char *buf) | ||
795 | { | ||
796 | struct bh1770_chip *chip = dev_get_drvdata(dev); | ||
797 | return sprintf(buf, "%d\n", prox_rates_hz[chip->prox_rate_threshold]); | ||
798 | } | ||
799 | |||
800 | static ssize_t bh1770_get_prox_rate_below(struct device *dev, | ||
801 | struct device_attribute *attr, char *buf) | ||
802 | { | ||
803 | struct bh1770_chip *chip = dev_get_drvdata(dev); | ||
804 | return sprintf(buf, "%d\n", prox_rates_hz[chip->prox_rate]); | ||
805 | } | ||
806 | |||
807 | static int bh1770_prox_rate_validate(int rate) | ||
808 | { | ||
809 | int i; | ||
810 | |||
811 | for (i = 0; i < ARRAY_SIZE(prox_rates_hz) - 1; i++) | ||
812 | if (rate >= prox_rates_hz[i]) | ||
813 | break; | ||
814 | return i; | ||
815 | } | ||
816 | |||
817 | static ssize_t bh1770_set_prox_rate_above(struct device *dev, | ||
818 | struct device_attribute *attr, | ||
819 | const char *buf, size_t count) | ||
820 | { | ||
821 | struct bh1770_chip *chip = dev_get_drvdata(dev); | ||
822 | unsigned long value; | ||
823 | |||
824 | if (strict_strtoul(buf, 0, &value)) | ||
825 | return -EINVAL; | ||
826 | |||
827 | mutex_lock(&chip->mutex); | ||
828 | chip->prox_rate_threshold = bh1770_prox_rate_validate(value); | ||
829 | mutex_unlock(&chip->mutex); | ||
830 | return count; | ||
831 | } | ||
832 | |||
833 | static ssize_t bh1770_set_prox_rate_below(struct device *dev, | ||
834 | struct device_attribute *attr, | ||
835 | const char *buf, size_t count) | ||
836 | { | ||
837 | struct bh1770_chip *chip = dev_get_drvdata(dev); | ||
838 | unsigned long value; | ||
839 | |||
840 | if (strict_strtoul(buf, 0, &value)) | ||
841 | return -EINVAL; | ||
842 | |||
843 | mutex_lock(&chip->mutex); | ||
844 | chip->prox_rate = bh1770_prox_rate_validate(value); | ||
845 | mutex_unlock(&chip->mutex); | ||
846 | return count; | ||
847 | } | ||
848 | |||
849 | static ssize_t bh1770_get_prox_thres(struct device *dev, | ||
850 | struct device_attribute *attr, char *buf) | ||
851 | { | ||
852 | struct bh1770_chip *chip = dev_get_drvdata(dev); | ||
853 | return sprintf(buf, "%d\n", chip->prox_threshold); | ||
854 | } | ||
855 | |||
856 | static ssize_t bh1770_set_prox_thres(struct device *dev, | ||
857 | struct device_attribute *attr, | ||
858 | const char *buf, size_t count) | ||
859 | { | ||
860 | struct bh1770_chip *chip = dev_get_drvdata(dev); | ||
861 | unsigned long value; | ||
862 | int ret; | ||
863 | |||
864 | if (strict_strtoul(buf, 0, &value)) | ||
865 | return -EINVAL; | ||
866 | if (value > BH1770_PROX_RANGE) | ||
867 | return -EINVAL; | ||
868 | |||
869 | mutex_lock(&chip->mutex); | ||
870 | chip->prox_threshold = value; | ||
871 | ret = bh1770_prox_set_threshold(chip); | ||
872 | mutex_unlock(&chip->mutex); | ||
873 | if (ret < 0) | ||
874 | return ret; | ||
875 | return count; | ||
876 | } | ||
877 | |||
878 | static ssize_t bh1770_prox_persistence_show(struct device *dev, | ||
879 | struct device_attribute *attr, char *buf) | ||
880 | { | ||
881 | struct bh1770_chip *chip = dev_get_drvdata(dev); | ||
882 | |||
883 | return sprintf(buf, "%u\n", chip->prox_persistence); | ||
884 | } | ||
885 | |||
886 | static ssize_t bh1770_prox_persistence_store(struct device *dev, | ||
887 | struct device_attribute *attr, | ||
888 | const char *buf, size_t len) | ||
889 | { | ||
890 | struct bh1770_chip *chip = dev_get_drvdata(dev); | ||
891 | unsigned long value; | ||
892 | |||
893 | if (strict_strtoul(buf, 0, &value)) | ||
894 | return -EINVAL; | ||
895 | |||
896 | if (value > BH1770_PROX_MAX_PERSISTENCE) | ||
897 | return -EINVAL; | ||
898 | |||
899 | chip->prox_persistence = value; | ||
900 | |||
901 | return len; | ||
902 | } | ||
903 | |||
904 | static ssize_t bh1770_prox_abs_thres_show(struct device *dev, | ||
905 | struct device_attribute *attr, char *buf) | ||
906 | { | ||
907 | struct bh1770_chip *chip = dev_get_drvdata(dev); | ||
908 | return sprintf(buf, "%u\n", chip->prox_abs_thres); | ||
909 | } | ||
910 | |||
911 | static ssize_t bh1770_prox_abs_thres_store(struct device *dev, | ||
912 | struct device_attribute *attr, | ||
913 | const char *buf, size_t len) | ||
914 | { | ||
915 | struct bh1770_chip *chip = dev_get_drvdata(dev); | ||
916 | unsigned long value; | ||
917 | |||
918 | if (strict_strtoul(buf, 0, &value)) | ||
919 | return -EINVAL; | ||
920 | |||
921 | if (value > BH1770_PROX_RANGE) | ||
922 | return -EINVAL; | ||
923 | |||
924 | chip->prox_abs_thres = value; | ||
925 | |||
926 | return len; | ||
927 | } | ||
928 | |||
929 | static ssize_t bh1770_chip_id_show(struct device *dev, | ||
930 | struct device_attribute *attr, char *buf) | ||
931 | { | ||
932 | struct bh1770_chip *chip = dev_get_drvdata(dev); | ||
933 | return sprintf(buf, "%s rev %d\n", chip->chipname, chip->revision); | ||
934 | } | ||
935 | |||
936 | static ssize_t bh1770_lux_calib_default_show(struct device *dev, | ||
937 | struct device_attribute *attr, char *buf) | ||
938 | { | ||
939 | return sprintf(buf, "%u\n", BH1770_CALIB_SCALER); | ||
940 | } | ||
941 | |||
942 | static ssize_t bh1770_lux_calib_show(struct device *dev, | ||
943 | struct device_attribute *attr, char *buf) | ||
944 | { | ||
945 | struct bh1770_chip *chip = dev_get_drvdata(dev); | ||
946 | ssize_t len; | ||
947 | |||
948 | mutex_lock(&chip->mutex); | ||
949 | len = sprintf(buf, "%u\n", chip->lux_calib); | ||
950 | mutex_unlock(&chip->mutex); | ||
951 | return len; | ||
952 | } | ||
953 | |||
954 | static ssize_t bh1770_lux_calib_store(struct device *dev, | ||
955 | struct device_attribute *attr, | ||
956 | const char *buf, size_t len) | ||
957 | { | ||
958 | struct bh1770_chip *chip = dev_get_drvdata(dev); | ||
959 | unsigned long value; | ||
960 | u32 old_calib; | ||
961 | u32 new_corr; | ||
962 | |||
963 | if (strict_strtoul(buf, 0, &value)) | ||
964 | return -EINVAL; | ||
965 | |||
966 | mutex_lock(&chip->mutex); | ||
967 | old_calib = chip->lux_calib; | ||
968 | chip->lux_calib = value; | ||
969 | new_corr = bh1770_get_corr_value(chip); | ||
970 | if (new_corr == 0) { | ||
971 | chip->lux_calib = old_calib; | ||
972 | mutex_unlock(&chip->mutex); | ||
973 | return -EINVAL; | ||
974 | } | ||
975 | chip->lux_corr = new_corr; | ||
976 | /* Refresh thresholds on HW after changing correction value */ | ||
977 | bh1770_lux_update_thresholds(chip, chip->lux_threshold_hi, | ||
978 | chip->lux_threshold_lo); | ||
979 | |||
980 | mutex_unlock(&chip->mutex); | ||
981 | |||
982 | return len; | ||
983 | } | ||
984 | |||
985 | static ssize_t bh1770_get_lux_rate_avail(struct device *dev, | ||
986 | struct device_attribute *attr, char *buf) | ||
987 | { | ||
988 | int i; | ||
989 | int pos = 0; | ||
990 | for (i = 0; i < ARRAY_SIZE(lux_rates_hz); i++) | ||
991 | pos += sprintf(buf + pos, "%d ", lux_rates_hz[i]); | ||
992 | sprintf(buf + pos - 1, "\n"); | ||
993 | return pos; | ||
994 | } | ||
995 | |||
996 | static ssize_t bh1770_get_lux_rate(struct device *dev, | ||
997 | struct device_attribute *attr, char *buf) | ||
998 | { | ||
999 | struct bh1770_chip *chip = dev_get_drvdata(dev); | ||
1000 | return sprintf(buf, "%d\n", lux_rates_hz[chip->lux_rate_index]); | ||
1001 | } | ||
1002 | |||
1003 | static ssize_t bh1770_set_lux_rate(struct device *dev, | ||
1004 | struct device_attribute *attr, | ||
1005 | const char *buf, size_t count) | ||
1006 | { | ||
1007 | struct bh1770_chip *chip = dev_get_drvdata(dev); | ||
1008 | unsigned long rate_hz; | ||
1009 | int ret, i; | ||
1010 | |||
1011 | if (strict_strtoul(buf, 0, &rate_hz)) | ||
1012 | return -EINVAL; | ||
1013 | |||
1014 | for (i = 0; i < ARRAY_SIZE(lux_rates_hz) - 1; i++) | ||
1015 | if (rate_hz >= lux_rates_hz[i]) | ||
1016 | break; | ||
1017 | |||
1018 | mutex_lock(&chip->mutex); | ||
1019 | chip->lux_rate_index = i; | ||
1020 | ret = bh1770_lux_rate(chip, i); | ||
1021 | mutex_unlock(&chip->mutex); | ||
1022 | |||
1023 | if (ret < 0) | ||
1024 | return ret; | ||
1025 | |||
1026 | return count; | ||
1027 | } | ||
1028 | |||
1029 | static ssize_t bh1770_get_lux_thresh_above(struct device *dev, | ||
1030 | struct device_attribute *attr, char *buf) | ||
1031 | { | ||
1032 | struct bh1770_chip *chip = dev_get_drvdata(dev); | ||
1033 | return sprintf(buf, "%d\n", chip->lux_threshold_hi); | ||
1034 | } | ||
1035 | |||
1036 | static ssize_t bh1770_get_lux_thresh_below(struct device *dev, | ||
1037 | struct device_attribute *attr, char *buf) | ||
1038 | { | ||
1039 | struct bh1770_chip *chip = dev_get_drvdata(dev); | ||
1040 | return sprintf(buf, "%d\n", chip->lux_threshold_lo); | ||
1041 | } | ||
1042 | |||
1043 | static ssize_t bh1770_set_lux_thresh(struct bh1770_chip *chip, u16 *target, | ||
1044 | const char *buf) | ||
1045 | { | ||
1046 | int ret = 0; | ||
1047 | unsigned long thresh; | ||
1048 | |||
1049 | if (strict_strtoul(buf, 0, &thresh)) | ||
1050 | return -EINVAL; | ||
1051 | |||
1052 | if (thresh > BH1770_LUX_RANGE) | ||
1053 | return -EINVAL; | ||
1054 | |||
1055 | mutex_lock(&chip->mutex); | ||
1056 | *target = thresh; | ||
1057 | /* | ||
1058 | * Don't update values in HW if we are still waiting for | ||
1059 | * first interrupt to come after device handle open call. | ||
1060 | */ | ||
1061 | if (!chip->lux_wait_result) | ||
1062 | ret = bh1770_lux_update_thresholds(chip, | ||
1063 | chip->lux_threshold_hi, | ||
1064 | chip->lux_threshold_lo); | ||
1065 | mutex_unlock(&chip->mutex); | ||
1066 | return ret; | ||
1067 | |||
1068 | } | ||
1069 | |||
1070 | static ssize_t bh1770_set_lux_thresh_above(struct device *dev, | ||
1071 | struct device_attribute *attr, | ||
1072 | const char *buf, size_t len) | ||
1073 | { | ||
1074 | struct bh1770_chip *chip = dev_get_drvdata(dev); | ||
1075 | int ret = bh1770_set_lux_thresh(chip, &chip->lux_threshold_hi, buf); | ||
1076 | if (ret < 0) | ||
1077 | return ret; | ||
1078 | return len; | ||
1079 | } | ||
1080 | |||
1081 | static ssize_t bh1770_set_lux_thresh_below(struct device *dev, | ||
1082 | struct device_attribute *attr, | ||
1083 | const char *buf, size_t len) | ||
1084 | { | ||
1085 | struct bh1770_chip *chip = dev_get_drvdata(dev); | ||
1086 | int ret = bh1770_set_lux_thresh(chip, &chip->lux_threshold_lo, buf); | ||
1087 | if (ret < 0) | ||
1088 | return ret; | ||
1089 | return len; | ||
1090 | } | ||
1091 | |||
1092 | static DEVICE_ATTR(prox0_raw_en, S_IRUGO | S_IWUSR, bh1770_prox_enable_show, | ||
1093 | bh1770_prox_enable_store); | ||
1094 | static DEVICE_ATTR(prox0_thresh_above1_value, S_IRUGO | S_IWUSR, | ||
1095 | bh1770_prox_abs_thres_show, | ||
1096 | bh1770_prox_abs_thres_store); | ||
1097 | static DEVICE_ATTR(prox0_thresh_above0_value, S_IRUGO | S_IWUSR, | ||
1098 | bh1770_get_prox_thres, | ||
1099 | bh1770_set_prox_thres); | ||
1100 | static DEVICE_ATTR(prox0_raw, S_IRUGO, bh1770_prox_result_show, NULL); | ||
1101 | static DEVICE_ATTR(prox0_sensor_range, S_IRUGO, bh1770_prox_range_show, NULL); | ||
1102 | static DEVICE_ATTR(prox0_thresh_above_count, S_IRUGO | S_IWUSR, | ||
1103 | bh1770_prox_persistence_show, | ||
1104 | bh1770_prox_persistence_store); | ||
1105 | static DEVICE_ATTR(prox0_rate_above, S_IRUGO | S_IWUSR, | ||
1106 | bh1770_get_prox_rate_above, | ||
1107 | bh1770_set_prox_rate_above); | ||
1108 | static DEVICE_ATTR(prox0_rate_below, S_IRUGO | S_IWUSR, | ||
1109 | bh1770_get_prox_rate_below, | ||
1110 | bh1770_set_prox_rate_below); | ||
1111 | static DEVICE_ATTR(prox0_rate_avail, S_IRUGO, bh1770_get_prox_rate_avail, NULL); | ||
1112 | |||
1113 | static DEVICE_ATTR(lux0_calibscale, S_IRUGO | S_IWUSR, bh1770_lux_calib_show, | ||
1114 | bh1770_lux_calib_store); | ||
1115 | static DEVICE_ATTR(lux0_calibscale_default, S_IRUGO, | ||
1116 | bh1770_lux_calib_default_show, | ||
1117 | NULL); | ||
1118 | static DEVICE_ATTR(lux0_input, S_IRUGO, bh1770_lux_result_show, NULL); | ||
1119 | static DEVICE_ATTR(lux0_sensor_range, S_IRUGO, bh1770_lux_range_show, NULL); | ||
1120 | static DEVICE_ATTR(lux0_rate, S_IRUGO | S_IWUSR, bh1770_get_lux_rate, | ||
1121 | bh1770_set_lux_rate); | ||
1122 | static DEVICE_ATTR(lux0_rate_avail, S_IRUGO, bh1770_get_lux_rate_avail, NULL); | ||
1123 | static DEVICE_ATTR(lux0_thresh_above_value, S_IRUGO | S_IWUSR, | ||
1124 | bh1770_get_lux_thresh_above, | ||
1125 | bh1770_set_lux_thresh_above); | ||
1126 | static DEVICE_ATTR(lux0_thresh_below_value, S_IRUGO | S_IWUSR, | ||
1127 | bh1770_get_lux_thresh_below, | ||
1128 | bh1770_set_lux_thresh_below); | ||
1129 | static DEVICE_ATTR(chip_id, S_IRUGO, bh1770_chip_id_show, NULL); | ||
1130 | static DEVICE_ATTR(power_state, S_IRUGO | S_IWUSR, bh1770_power_state_show, | ||
1131 | bh1770_power_state_store); | ||
1132 | |||
1133 | |||
1134 | static struct attribute *sysfs_attrs[] = { | ||
1135 | &dev_attr_lux0_calibscale.attr, | ||
1136 | &dev_attr_lux0_calibscale_default.attr, | ||
1137 | &dev_attr_lux0_input.attr, | ||
1138 | &dev_attr_lux0_sensor_range.attr, | ||
1139 | &dev_attr_lux0_rate.attr, | ||
1140 | &dev_attr_lux0_rate_avail.attr, | ||
1141 | &dev_attr_lux0_thresh_above_value.attr, | ||
1142 | &dev_attr_lux0_thresh_below_value.attr, | ||
1143 | &dev_attr_prox0_raw.attr, | ||
1144 | &dev_attr_prox0_sensor_range.attr, | ||
1145 | &dev_attr_prox0_raw_en.attr, | ||
1146 | &dev_attr_prox0_thresh_above_count.attr, | ||
1147 | &dev_attr_prox0_rate_above.attr, | ||
1148 | &dev_attr_prox0_rate_below.attr, | ||
1149 | &dev_attr_prox0_rate_avail.attr, | ||
1150 | &dev_attr_prox0_thresh_above0_value.attr, | ||
1151 | &dev_attr_prox0_thresh_above1_value.attr, | ||
1152 | &dev_attr_chip_id.attr, | ||
1153 | &dev_attr_power_state.attr, | ||
1154 | NULL | ||
1155 | }; | ||
1156 | |||
1157 | static struct attribute_group bh1770_attribute_group = { | ||
1158 | .attrs = sysfs_attrs | ||
1159 | }; | ||
1160 | |||
1161 | static int __devinit bh1770_probe(struct i2c_client *client, | ||
1162 | const struct i2c_device_id *id) | ||
1163 | { | ||
1164 | struct bh1770_chip *chip; | ||
1165 | int err; | ||
1166 | |||
1167 | chip = kzalloc(sizeof *chip, GFP_KERNEL); | ||
1168 | if (!chip) | ||
1169 | return -ENOMEM; | ||
1170 | |||
1171 | i2c_set_clientdata(client, chip); | ||
1172 | chip->client = client; | ||
1173 | |||
1174 | mutex_init(&chip->mutex); | ||
1175 | init_waitqueue_head(&chip->wait); | ||
1176 | INIT_DELAYED_WORK(&chip->prox_work, bh1770_prox_work); | ||
1177 | |||
1178 | if (client->dev.platform_data == NULL) { | ||
1179 | dev_err(&client->dev, "platform data is mandatory\n"); | ||
1180 | err = -EINVAL; | ||
1181 | goto fail1; | ||
1182 | } | ||
1183 | |||
1184 | chip->pdata = client->dev.platform_data; | ||
1185 | chip->lux_calib = BH1770_LUX_NEUTRAL_CALIB_VALUE; | ||
1186 | chip->lux_rate_index = BH1770_LUX_DEFAULT_RATE; | ||
1187 | chip->lux_threshold_lo = BH1770_LUX_DEF_THRES; | ||
1188 | chip->lux_threshold_hi = BH1770_LUX_DEF_THRES; | ||
1189 | |||
1190 | if (chip->pdata->glass_attenuation == 0) | ||
1191 | chip->lux_ga = BH1770_NEUTRAL_GA; | ||
1192 | else | ||
1193 | chip->lux_ga = chip->pdata->glass_attenuation; | ||
1194 | |||
1195 | chip->prox_threshold = BH1770_PROX_DEF_THRES; | ||
1196 | chip->prox_led = chip->pdata->led_def_curr; | ||
1197 | chip->prox_abs_thres = BH1770_PROX_DEF_ABS_THRES; | ||
1198 | chip->prox_persistence = BH1770_DEFAULT_PERSISTENCE; | ||
1199 | chip->prox_rate_threshold = BH1770_PROX_DEF_RATE_THRESH; | ||
1200 | chip->prox_rate = BH1770_PROX_DEFAULT_RATE; | ||
1201 | chip->prox_data = 0; | ||
1202 | |||
1203 | chip->regs[0].supply = reg_vcc; | ||
1204 | chip->regs[1].supply = reg_vleds; | ||
1205 | |||
1206 | err = regulator_bulk_get(&client->dev, | ||
1207 | ARRAY_SIZE(chip->regs), chip->regs); | ||
1208 | if (err < 0) { | ||
1209 | dev_err(&client->dev, "Cannot get regulators\n"); | ||
1210 | goto fail1; | ||
1211 | } | ||
1212 | |||
1213 | err = regulator_bulk_enable(ARRAY_SIZE(chip->regs), | ||
1214 | chip->regs); | ||
1215 | if (err < 0) { | ||
1216 | dev_err(&client->dev, "Cannot enable regulators\n"); | ||
1217 | goto fail2; | ||
1218 | } | ||
1219 | |||
1220 | usleep_range(BH1770_STARTUP_DELAY, BH1770_STARTUP_DELAY * 2); | ||
1221 | err = bh1770_detect(chip); | ||
1222 | if (err < 0) | ||
1223 | goto fail3; | ||
1224 | |||
1225 | /* Start chip */ | ||
1226 | bh1770_chip_on(chip); | ||
1227 | pm_runtime_set_active(&client->dev); | ||
1228 | pm_runtime_enable(&client->dev); | ||
1229 | |||
1230 | chip->lux_corr = bh1770_get_corr_value(chip); | ||
1231 | if (chip->lux_corr == 0) { | ||
1232 | dev_err(&client->dev, "Improper correction values\n"); | ||
1233 | err = -EINVAL; | ||
1234 | goto fail3; | ||
1235 | } | ||
1236 | |||
1237 | if (chip->pdata->setup_resources) { | ||
1238 | err = chip->pdata->setup_resources(); | ||
1239 | if (err) { | ||
1240 | err = -EINVAL; | ||
1241 | goto fail3; | ||
1242 | } | ||
1243 | } | ||
1244 | |||
1245 | err = sysfs_create_group(&chip->client->dev.kobj, | ||
1246 | &bh1770_attribute_group); | ||
1247 | if (err < 0) { | ||
1248 | dev_err(&chip->client->dev, "Sysfs registration failed\n"); | ||
1249 | goto fail4; | ||
1250 | } | ||
1251 | |||
1252 | /* | ||
1253 | * Chip needs level triggered interrupt to work. However, | ||
1254 | * level triggering doesn't work always correctly with power | ||
1255 | * management. Select both | ||
1256 | */ | ||
1257 | err = request_threaded_irq(client->irq, NULL, | ||
1258 | bh1770_irq, | ||
1259 | IRQF_TRIGGER_FALLING | IRQF_ONESHOT | | ||
1260 | IRQF_TRIGGER_LOW, | ||
1261 | "bh1770", chip); | ||
1262 | if (err) { | ||
1263 | dev_err(&client->dev, "could not get IRQ %d\n", | ||
1264 | client->irq); | ||
1265 | goto fail5; | ||
1266 | } | ||
1267 | regulator_bulk_disable(ARRAY_SIZE(chip->regs), chip->regs); | ||
1268 | return err; | ||
1269 | fail5: | ||
1270 | sysfs_remove_group(&chip->client->dev.kobj, | ||
1271 | &bh1770_attribute_group); | ||
1272 | fail4: | ||
1273 | if (chip->pdata->release_resources) | ||
1274 | chip->pdata->release_resources(); | ||
1275 | fail3: | ||
1276 | regulator_bulk_disable(ARRAY_SIZE(chip->regs), chip->regs); | ||
1277 | fail2: | ||
1278 | regulator_bulk_free(ARRAY_SIZE(chip->regs), chip->regs); | ||
1279 | fail1: | ||
1280 | kfree(chip); | ||
1281 | return err; | ||
1282 | } | ||
1283 | |||
1284 | static int __devexit bh1770_remove(struct i2c_client *client) | ||
1285 | { | ||
1286 | struct bh1770_chip *chip = i2c_get_clientdata(client); | ||
1287 | |||
1288 | free_irq(client->irq, chip); | ||
1289 | |||
1290 | sysfs_remove_group(&chip->client->dev.kobj, | ||
1291 | &bh1770_attribute_group); | ||
1292 | |||
1293 | if (chip->pdata->release_resources) | ||
1294 | chip->pdata->release_resources(); | ||
1295 | |||
1296 | cancel_delayed_work_sync(&chip->prox_work); | ||
1297 | |||
1298 | if (!pm_runtime_suspended(&client->dev)) | ||
1299 | bh1770_chip_off(chip); | ||
1300 | |||
1301 | pm_runtime_disable(&client->dev); | ||
1302 | pm_runtime_set_suspended(&client->dev); | ||
1303 | |||
1304 | regulator_bulk_free(ARRAY_SIZE(chip->regs), chip->regs); | ||
1305 | kfree(chip); | ||
1306 | return 0; | ||
1307 | } | ||
1308 | |||
1309 | #ifdef CONFIG_PM | ||
1310 | static int bh1770_suspend(struct device *dev) | ||
1311 | { | ||
1312 | struct i2c_client *client = container_of(dev, struct i2c_client, dev); | ||
1313 | struct bh1770_chip *chip = i2c_get_clientdata(client); | ||
1314 | |||
1315 | bh1770_chip_off(chip); | ||
1316 | |||
1317 | return 0; | ||
1318 | } | ||
1319 | |||
1320 | static int bh1770_resume(struct device *dev) | ||
1321 | { | ||
1322 | struct i2c_client *client = container_of(dev, struct i2c_client, dev); | ||
1323 | struct bh1770_chip *chip = i2c_get_clientdata(client); | ||
1324 | int ret = 0; | ||
1325 | |||
1326 | bh1770_chip_on(chip); | ||
1327 | |||
1328 | if (!pm_runtime_suspended(dev)) { | ||
1329 | /* | ||
1330 | * If we were enabled at suspend time, it is expected | ||
1331 | * everything works nice and smoothly | ||
1332 | */ | ||
1333 | ret = bh1770_lux_rate(chip, chip->lux_rate_index); | ||
1334 | ret |= bh1770_lux_interrupt_control(chip, BH1770_ENABLE); | ||
1335 | |||
1336 | /* This causes interrupt after the next measurement cycle */ | ||
1337 | bh1770_lux_update_thresholds(chip, BH1770_LUX_DEF_THRES, | ||
1338 | BH1770_LUX_DEF_THRES); | ||
1339 | /* Inform that we are waiting for a result from ALS */ | ||
1340 | chip->lux_wait_result = true; | ||
1341 | bh1770_prox_mode_control(chip); | ||
1342 | } | ||
1343 | return ret; | ||
1344 | } | ||
1345 | |||
1346 | #else | ||
1347 | #define bh1770_suspend NULL | ||
1348 | #define bh1770_shutdown NULL | ||
1349 | #define bh1770_resume NULL | ||
1350 | #endif | ||
1351 | |||
1352 | #ifdef CONFIG_PM_RUNTIME | ||
1353 | static int bh1770_runtime_suspend(struct device *dev) | ||
1354 | { | ||
1355 | struct i2c_client *client = container_of(dev, struct i2c_client, dev); | ||
1356 | struct bh1770_chip *chip = i2c_get_clientdata(client); | ||
1357 | |||
1358 | bh1770_chip_off(chip); | ||
1359 | |||
1360 | return 0; | ||
1361 | } | ||
1362 | |||
1363 | static int bh1770_runtime_resume(struct device *dev) | ||
1364 | { | ||
1365 | struct i2c_client *client = container_of(dev, struct i2c_client, dev); | ||
1366 | struct bh1770_chip *chip = i2c_get_clientdata(client); | ||
1367 | |||
1368 | bh1770_chip_on(chip); | ||
1369 | |||
1370 | return 0; | ||
1371 | } | ||
1372 | #endif | ||
1373 | |||
1374 | static const struct i2c_device_id bh1770_id[] = { | ||
1375 | {"bh1770glc", 0 }, | ||
1376 | {"sfh7770", 0 }, | ||
1377 | {} | ||
1378 | }; | ||
1379 | |||
1380 | MODULE_DEVICE_TABLE(i2c, bh1770_id); | ||
1381 | |||
1382 | static const struct dev_pm_ops bh1770_pm_ops = { | ||
1383 | SET_SYSTEM_SLEEP_PM_OPS(bh1770_suspend, bh1770_resume) | ||
1384 | SET_RUNTIME_PM_OPS(bh1770_runtime_suspend, bh1770_runtime_resume, NULL) | ||
1385 | }; | ||
1386 | |||
1387 | static struct i2c_driver bh1770_driver = { | ||
1388 | .driver = { | ||
1389 | .name = "bh1770glc", | ||
1390 | .owner = THIS_MODULE, | ||
1391 | .pm = &bh1770_pm_ops, | ||
1392 | }, | ||
1393 | .probe = bh1770_probe, | ||
1394 | .remove = __devexit_p(bh1770_remove), | ||
1395 | .id_table = bh1770_id, | ||
1396 | }; | ||
1397 | |||
1398 | static int __init bh1770_init(void) | ||
1399 | { | ||
1400 | return i2c_add_driver(&bh1770_driver); | ||
1401 | } | ||
1402 | |||
1403 | static void __exit bh1770_exit(void) | ||
1404 | { | ||
1405 | i2c_del_driver(&bh1770_driver); | ||
1406 | } | ||
1407 | |||
1408 | MODULE_DESCRIPTION("BH1770GLC / SFH7770 combined ALS and proximity sensor"); | ||
1409 | MODULE_AUTHOR("Samu Onkalo, Nokia Corporation"); | ||
1410 | MODULE_LICENSE("GPL v2"); | ||
1411 | |||
1412 | module_init(bh1770_init); | ||
1413 | module_exit(bh1770_exit); | ||
diff --git a/drivers/misc/isl29020.c b/drivers/misc/isl29020.c new file mode 100644 index 000000000000..34fe835921c4 --- /dev/null +++ b/drivers/misc/isl29020.c | |||
@@ -0,0 +1,248 @@ | |||
1 | /* | ||
2 | * isl29020.c - Intersil ALS Driver | ||
3 | * | ||
4 | * Copyright (C) 2008 Intel Corp | ||
5 | * | ||
6 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; version 2 of the License. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but | ||
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License along | ||
18 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
19 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. | ||
20 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
21 | * | ||
22 | * Data sheet at: http://www.intersil.com/data/fn/fn6505.pdf | ||
23 | */ | ||
24 | |||
25 | #include <linux/module.h> | ||
26 | #include <linux/init.h> | ||
27 | #include <linux/slab.h> | ||
28 | #include <linux/i2c.h> | ||
29 | #include <linux/err.h> | ||
30 | #include <linux/delay.h> | ||
31 | #include <linux/sysfs.h> | ||
32 | #include <linux/pm_runtime.h> | ||
33 | |||
34 | static DEFINE_MUTEX(mutex); | ||
35 | |||
36 | static ssize_t als_sensing_range_show(struct device *dev, | ||
37 | struct device_attribute *attr, char *buf) | ||
38 | { | ||
39 | struct i2c_client *client = to_i2c_client(dev); | ||
40 | int val; | ||
41 | |||
42 | val = i2c_smbus_read_byte_data(client, 0x00); | ||
43 | |||
44 | if (val < 0) | ||
45 | return val; | ||
46 | return sprintf(buf, "%d000\n", 1 << (2 * (val & 3))); | ||
47 | |||
48 | } | ||
49 | |||
50 | static ssize_t als_lux_input_data_show(struct device *dev, | ||
51 | struct device_attribute *attr, char *buf) | ||
52 | { | ||
53 | struct i2c_client *client = to_i2c_client(dev); | ||
54 | int ret_val, val; | ||
55 | unsigned long int lux; | ||
56 | int temp; | ||
57 | |||
58 | pm_runtime_get_sync(dev); | ||
59 | msleep(100); | ||
60 | |||
61 | mutex_lock(&mutex); | ||
62 | temp = i2c_smbus_read_byte_data(client, 0x02); /* MSB data */ | ||
63 | if (temp < 0) { | ||
64 | pm_runtime_put_sync(dev); | ||
65 | mutex_unlock(&mutex); | ||
66 | return temp; | ||
67 | } | ||
68 | |||
69 | ret_val = i2c_smbus_read_byte_data(client, 0x01); /* LSB data */ | ||
70 | mutex_unlock(&mutex); | ||
71 | |||
72 | if (ret_val < 0) { | ||
73 | pm_runtime_put_sync(dev); | ||
74 | return ret_val; | ||
75 | } | ||
76 | |||
77 | ret_val |= temp << 8; | ||
78 | val = i2c_smbus_read_byte_data(client, 0x00); | ||
79 | pm_runtime_put_sync(dev); | ||
80 | if (val < 0) | ||
81 | return val; | ||
82 | lux = ((((1 << (2 * (val & 3))))*1000) * ret_val) / 65536; | ||
83 | return sprintf(buf, "%ld\n", lux); | ||
84 | } | ||
85 | |||
86 | static ssize_t als_sensing_range_store(struct device *dev, | ||
87 | struct device_attribute *attr, const char *buf, size_t count) | ||
88 | { | ||
89 | struct i2c_client *client = to_i2c_client(dev); | ||
90 | unsigned int ret_val; | ||
91 | unsigned long val; | ||
92 | |||
93 | if (strict_strtoul(buf, 10, &val)) | ||
94 | return -EINVAL; | ||
95 | if (val < 1 || val > 64000) | ||
96 | return -EINVAL; | ||
97 | |||
98 | /* Pick the smallest sensor range that will meet our requirements */ | ||
99 | if (val <= 1000) | ||
100 | val = 1; | ||
101 | else if (val <= 4000) | ||
102 | val = 2; | ||
103 | else if (val <= 16000) | ||
104 | val = 3; | ||
105 | else | ||
106 | val = 4; | ||
107 | |||
108 | ret_val = i2c_smbus_read_byte_data(client, 0x00); | ||
109 | |||
110 | ret_val &= 0xFC; /*reset the bit before setting them */ | ||
111 | ret_val |= val - 1; | ||
112 | ret_val = i2c_smbus_write_byte_data(client, 0x00, ret_val); | ||
113 | |||
114 | if (ret_val < 0) | ||
115 | return ret_val; | ||
116 | return count; | ||
117 | } | ||
118 | |||
119 | static void als_set_power_state(struct i2c_client *client, int enable) | ||
120 | { | ||
121 | int ret_val; | ||
122 | |||
123 | ret_val = i2c_smbus_read_byte_data(client, 0x00); | ||
124 | if (ret_val < 0) | ||
125 | return; | ||
126 | |||
127 | if (enable) | ||
128 | ret_val |= 0x80; | ||
129 | else | ||
130 | ret_val &= 0x7F; | ||
131 | |||
132 | i2c_smbus_write_byte_data(client, 0x00, ret_val); | ||
133 | } | ||
134 | |||
135 | static DEVICE_ATTR(lux0_sensor_range, S_IRUGO | S_IWUSR, | ||
136 | als_sensing_range_show, als_sensing_range_store); | ||
137 | static DEVICE_ATTR(lux0_input, S_IRUGO, als_lux_input_data_show, NULL); | ||
138 | |||
139 | static struct attribute *mid_att_als[] = { | ||
140 | &dev_attr_lux0_sensor_range.attr, | ||
141 | &dev_attr_lux0_input.attr, | ||
142 | NULL | ||
143 | }; | ||
144 | |||
145 | static struct attribute_group m_als_gr = { | ||
146 | .name = "isl29020", | ||
147 | .attrs = mid_att_als | ||
148 | }; | ||
149 | |||
150 | static int als_set_default_config(struct i2c_client *client) | ||
151 | { | ||
152 | int retval; | ||
153 | |||
154 | retval = i2c_smbus_write_byte_data(client, 0x00, 0xc0); | ||
155 | if (retval < 0) { | ||
156 | dev_err(&client->dev, "default write failed."); | ||
157 | return retval; | ||
158 | } | ||
159 | return 0;; | ||
160 | } | ||
161 | |||
162 | static int isl29020_probe(struct i2c_client *client, | ||
163 | const struct i2c_device_id *id) | ||
164 | { | ||
165 | int res; | ||
166 | |||
167 | res = als_set_default_config(client); | ||
168 | if (res < 0) | ||
169 | return res; | ||
170 | |||
171 | res = sysfs_create_group(&client->dev.kobj, &m_als_gr); | ||
172 | if (res) { | ||
173 | dev_err(&client->dev, "isl29020: device create file failed\n"); | ||
174 | return res; | ||
175 | } | ||
176 | dev_info(&client->dev, "%s isl29020: ALS chip found\n", client->name); | ||
177 | als_set_power_state(client, 0); | ||
178 | pm_runtime_enable(&client->dev); | ||
179 | return res; | ||
180 | } | ||
181 | |||
182 | static int isl29020_remove(struct i2c_client *client) | ||
183 | { | ||
184 | struct als_data *data = i2c_get_clientdata(client); | ||
185 | sysfs_remove_group(&client->dev.kobj, &m_als_gr); | ||
186 | kfree(data); | ||
187 | return 0; | ||
188 | } | ||
189 | |||
190 | static struct i2c_device_id isl29020_id[] = { | ||
191 | { "isl29020", 0 }, | ||
192 | { } | ||
193 | }; | ||
194 | |||
195 | MODULE_DEVICE_TABLE(i2c, isl29020_id); | ||
196 | |||
197 | #ifdef CONFIG_PM | ||
198 | |||
199 | static int isl29020_runtime_suspend(struct device *dev) | ||
200 | { | ||
201 | struct i2c_client *client = to_i2c_client(dev); | ||
202 | als_set_power_state(client, 0); | ||
203 | return 0; | ||
204 | } | ||
205 | |||
206 | static int isl29020_runtime_resume(struct device *dev) | ||
207 | { | ||
208 | struct i2c_client *client = to_i2c_client(dev); | ||
209 | als_set_power_state(client, 1); | ||
210 | return 0; | ||
211 | } | ||
212 | |||
213 | static const struct dev_pm_ops isl29020_pm_ops = { | ||
214 | .runtime_suspend = isl29020_runtime_suspend, | ||
215 | .runtime_resume = isl29020_runtime_resume, | ||
216 | }; | ||
217 | |||
218 | #define ISL29020_PM_OPS (&isl29020_pm_ops) | ||
219 | #else /* CONFIG_PM */ | ||
220 | #define ISL29020_PM_OPS NULL | ||
221 | #endif /* CONFIG_PM */ | ||
222 | |||
223 | static struct i2c_driver isl29020_driver = { | ||
224 | .driver = { | ||
225 | .name = "isl29020", | ||
226 | .pm = ISL29020_PM_OPS, | ||
227 | }, | ||
228 | .probe = isl29020_probe, | ||
229 | .remove = isl29020_remove, | ||
230 | .id_table = isl29020_id, | ||
231 | }; | ||
232 | |||
233 | static int __init sensor_isl29020_init(void) | ||
234 | { | ||
235 | return i2c_add_driver(&isl29020_driver); | ||
236 | } | ||
237 | |||
238 | static void __exit sensor_isl29020_exit(void) | ||
239 | { | ||
240 | i2c_del_driver(&isl29020_driver); | ||
241 | } | ||
242 | |||
243 | module_init(sensor_isl29020_init); | ||
244 | module_exit(sensor_isl29020_exit); | ||
245 | |||
246 | MODULE_AUTHOR("Kalhan Trisal <kalhan.trisal@intel.com"); | ||
247 | MODULE_DESCRIPTION("Intersil isl29020 ALS Driver"); | ||
248 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/misc/lkdtm.c b/drivers/misc/lkdtm.c index 343b5d8ea697..81d7fa4ec0db 100644 --- a/drivers/misc/lkdtm.c +++ b/drivers/misc/lkdtm.c | |||
@@ -52,32 +52,32 @@ | |||
52 | #define REC_NUM_DEFAULT 10 | 52 | #define REC_NUM_DEFAULT 10 |
53 | 53 | ||
54 | enum cname { | 54 | enum cname { |
55 | INVALID, | 55 | CN_INVALID, |
56 | INT_HARDWARE_ENTRY, | 56 | CN_INT_HARDWARE_ENTRY, |
57 | INT_HW_IRQ_EN, | 57 | CN_INT_HW_IRQ_EN, |
58 | INT_TASKLET_ENTRY, | 58 | CN_INT_TASKLET_ENTRY, |
59 | FS_DEVRW, | 59 | CN_FS_DEVRW, |
60 | MEM_SWAPOUT, | 60 | CN_MEM_SWAPOUT, |
61 | TIMERADD, | 61 | CN_TIMERADD, |
62 | SCSI_DISPATCH_CMD, | 62 | CN_SCSI_DISPATCH_CMD, |
63 | IDE_CORE_CP, | 63 | CN_IDE_CORE_CP, |
64 | DIRECT, | 64 | CN_DIRECT, |
65 | }; | 65 | }; |
66 | 66 | ||
67 | enum ctype { | 67 | enum ctype { |
68 | NONE, | 68 | CT_NONE, |
69 | PANIC, | 69 | CT_PANIC, |
70 | BUG, | 70 | CT_BUG, |
71 | EXCEPTION, | 71 | CT_EXCEPTION, |
72 | LOOP, | 72 | CT_LOOP, |
73 | OVERFLOW, | 73 | CT_OVERFLOW, |
74 | CORRUPT_STACK, | 74 | CT_CORRUPT_STACK, |
75 | UNALIGNED_LOAD_STORE_WRITE, | 75 | CT_UNALIGNED_LOAD_STORE_WRITE, |
76 | OVERWRITE_ALLOCATION, | 76 | CT_OVERWRITE_ALLOCATION, |
77 | WRITE_AFTER_FREE, | 77 | CT_WRITE_AFTER_FREE, |
78 | SOFTLOCKUP, | 78 | CT_SOFTLOCKUP, |
79 | HARDLOCKUP, | 79 | CT_HARDLOCKUP, |
80 | HUNG_TASK, | 80 | CT_HUNG_TASK, |
81 | }; | 81 | }; |
82 | 82 | ||
83 | static char* cp_name[] = { | 83 | static char* cp_name[] = { |
@@ -117,8 +117,8 @@ static char* cpoint_type; | |||
117 | static int cpoint_count = DEFAULT_COUNT; | 117 | static int cpoint_count = DEFAULT_COUNT; |
118 | static int recur_count = REC_NUM_DEFAULT; | 118 | static int recur_count = REC_NUM_DEFAULT; |
119 | 119 | ||
120 | static enum cname cpoint = INVALID; | 120 | static enum cname cpoint = CN_INVALID; |
121 | static enum ctype cptype = NONE; | 121 | static enum ctype cptype = CT_NONE; |
122 | static int count = DEFAULT_COUNT; | 122 | static int count = DEFAULT_COUNT; |
123 | 123 | ||
124 | module_param(recur_count, int, 0644); | 124 | module_param(recur_count, int, 0644); |
@@ -207,12 +207,12 @@ static enum ctype parse_cp_type(const char *what, size_t count) | |||
207 | return i + 1; | 207 | return i + 1; |
208 | } | 208 | } |
209 | 209 | ||
210 | return NONE; | 210 | return CT_NONE; |
211 | } | 211 | } |
212 | 212 | ||
213 | static const char *cp_type_to_str(enum ctype type) | 213 | static const char *cp_type_to_str(enum ctype type) |
214 | { | 214 | { |
215 | if (type == NONE || type < 0 || type > ARRAY_SIZE(cp_type)) | 215 | if (type == CT_NONE || type < 0 || type > ARRAY_SIZE(cp_type)) |
216 | return "None"; | 216 | return "None"; |
217 | 217 | ||
218 | return cp_type[type - 1]; | 218 | return cp_type[type - 1]; |
@@ -220,7 +220,7 @@ static const char *cp_type_to_str(enum ctype type) | |||
220 | 220 | ||
221 | static const char *cp_name_to_str(enum cname name) | 221 | static const char *cp_name_to_str(enum cname name) |
222 | { | 222 | { |
223 | if (name == INVALID || name < 0 || name > ARRAY_SIZE(cp_name)) | 223 | if (name == CN_INVALID || name < 0 || name > ARRAY_SIZE(cp_name)) |
224 | return "INVALID"; | 224 | return "INVALID"; |
225 | 225 | ||
226 | return cp_name[name - 1]; | 226 | return cp_name[name - 1]; |
@@ -245,7 +245,7 @@ static int lkdtm_parse_commandline(void) | |||
245 | return -EINVAL; | 245 | return -EINVAL; |
246 | 246 | ||
247 | cptype = parse_cp_type(cpoint_type, strlen(cpoint_type)); | 247 | cptype = parse_cp_type(cpoint_type, strlen(cpoint_type)); |
248 | if (cptype == NONE) | 248 | if (cptype == CT_NONE) |
249 | return -EINVAL; | 249 | return -EINVAL; |
250 | 250 | ||
251 | for (i = 0; i < ARRAY_SIZE(cp_name); i++) { | 251 | for (i = 0; i < ARRAY_SIZE(cp_name); i++) { |
@@ -274,30 +274,30 @@ static int recursive_loop(int a) | |||
274 | static void lkdtm_do_action(enum ctype which) | 274 | static void lkdtm_do_action(enum ctype which) |
275 | { | 275 | { |
276 | switch (which) { | 276 | switch (which) { |
277 | case PANIC: | 277 | case CT_PANIC: |
278 | panic("dumptest"); | 278 | panic("dumptest"); |
279 | break; | 279 | break; |
280 | case BUG: | 280 | case CT_BUG: |
281 | BUG(); | 281 | BUG(); |
282 | break; | 282 | break; |
283 | case EXCEPTION: | 283 | case CT_EXCEPTION: |
284 | *((int *) 0) = 0; | 284 | *((int *) 0) = 0; |
285 | break; | 285 | break; |
286 | case LOOP: | 286 | case CT_LOOP: |
287 | for (;;) | 287 | for (;;) |
288 | ; | 288 | ; |
289 | break; | 289 | break; |
290 | case OVERFLOW: | 290 | case CT_OVERFLOW: |
291 | (void) recursive_loop(0); | 291 | (void) recursive_loop(0); |
292 | break; | 292 | break; |
293 | case CORRUPT_STACK: { | 293 | case CT_CORRUPT_STACK: { |
294 | volatile u32 data[8]; | 294 | volatile u32 data[8]; |
295 | volatile u32 *p = data; | 295 | volatile u32 *p = data; |
296 | 296 | ||
297 | p[12] = 0x12345678; | 297 | p[12] = 0x12345678; |
298 | break; | 298 | break; |
299 | } | 299 | } |
300 | case UNALIGNED_LOAD_STORE_WRITE: { | 300 | case CT_UNALIGNED_LOAD_STORE_WRITE: { |
301 | static u8 data[5] __attribute__((aligned(4))) = {1, 2, | 301 | static u8 data[5] __attribute__((aligned(4))) = {1, 2, |
302 | 3, 4, 5}; | 302 | 3, 4, 5}; |
303 | u32 *p; | 303 | u32 *p; |
@@ -309,7 +309,7 @@ static void lkdtm_do_action(enum ctype which) | |||
309 | *p = val; | 309 | *p = val; |
310 | break; | 310 | break; |
311 | } | 311 | } |
312 | case OVERWRITE_ALLOCATION: { | 312 | case CT_OVERWRITE_ALLOCATION: { |
313 | size_t len = 1020; | 313 | size_t len = 1020; |
314 | u32 *data = kmalloc(len, GFP_KERNEL); | 314 | u32 *data = kmalloc(len, GFP_KERNEL); |
315 | 315 | ||
@@ -317,7 +317,7 @@ static void lkdtm_do_action(enum ctype which) | |||
317 | kfree(data); | 317 | kfree(data); |
318 | break; | 318 | break; |
319 | } | 319 | } |
320 | case WRITE_AFTER_FREE: { | 320 | case CT_WRITE_AFTER_FREE: { |
321 | size_t len = 1024; | 321 | size_t len = 1024; |
322 | u32 *data = kmalloc(len, GFP_KERNEL); | 322 | u32 *data = kmalloc(len, GFP_KERNEL); |
323 | 323 | ||
@@ -326,21 +326,21 @@ static void lkdtm_do_action(enum ctype which) | |||
326 | memset(data, 0x78, len); | 326 | memset(data, 0x78, len); |
327 | break; | 327 | break; |
328 | } | 328 | } |
329 | case SOFTLOCKUP: | 329 | case CT_SOFTLOCKUP: |
330 | preempt_disable(); | 330 | preempt_disable(); |
331 | for (;;) | 331 | for (;;) |
332 | cpu_relax(); | 332 | cpu_relax(); |
333 | break; | 333 | break; |
334 | case HARDLOCKUP: | 334 | case CT_HARDLOCKUP: |
335 | local_irq_disable(); | 335 | local_irq_disable(); |
336 | for (;;) | 336 | for (;;) |
337 | cpu_relax(); | 337 | cpu_relax(); |
338 | break; | 338 | break; |
339 | case HUNG_TASK: | 339 | case CT_HUNG_TASK: |
340 | set_current_state(TASK_UNINTERRUPTIBLE); | 340 | set_current_state(TASK_UNINTERRUPTIBLE); |
341 | schedule(); | 341 | schedule(); |
342 | break; | 342 | break; |
343 | case NONE: | 343 | case CT_NONE: |
344 | default: | 344 | default: |
345 | break; | 345 | break; |
346 | } | 346 | } |
@@ -363,43 +363,43 @@ static int lkdtm_register_cpoint(enum cname which) | |||
363 | { | 363 | { |
364 | int ret; | 364 | int ret; |
365 | 365 | ||
366 | cpoint = INVALID; | 366 | cpoint = CN_INVALID; |
367 | if (lkdtm.entry != NULL) | 367 | if (lkdtm.entry != NULL) |
368 | unregister_jprobe(&lkdtm); | 368 | unregister_jprobe(&lkdtm); |
369 | 369 | ||
370 | switch (which) { | 370 | switch (which) { |
371 | case DIRECT: | 371 | case CN_DIRECT: |
372 | lkdtm_do_action(cptype); | 372 | lkdtm_do_action(cptype); |
373 | return 0; | 373 | return 0; |
374 | case INT_HARDWARE_ENTRY: | 374 | case CN_INT_HARDWARE_ENTRY: |
375 | lkdtm.kp.symbol_name = "do_IRQ"; | 375 | lkdtm.kp.symbol_name = "do_IRQ"; |
376 | lkdtm.entry = (kprobe_opcode_t*) jp_do_irq; | 376 | lkdtm.entry = (kprobe_opcode_t*) jp_do_irq; |
377 | break; | 377 | break; |
378 | case INT_HW_IRQ_EN: | 378 | case CN_INT_HW_IRQ_EN: |
379 | lkdtm.kp.symbol_name = "handle_IRQ_event"; | 379 | lkdtm.kp.symbol_name = "handle_IRQ_event"; |
380 | lkdtm.entry = (kprobe_opcode_t*) jp_handle_irq_event; | 380 | lkdtm.entry = (kprobe_opcode_t*) jp_handle_irq_event; |
381 | break; | 381 | break; |
382 | case INT_TASKLET_ENTRY: | 382 | case CN_INT_TASKLET_ENTRY: |
383 | lkdtm.kp.symbol_name = "tasklet_action"; | 383 | lkdtm.kp.symbol_name = "tasklet_action"; |
384 | lkdtm.entry = (kprobe_opcode_t*) jp_tasklet_action; | 384 | lkdtm.entry = (kprobe_opcode_t*) jp_tasklet_action; |
385 | break; | 385 | break; |
386 | case FS_DEVRW: | 386 | case CN_FS_DEVRW: |
387 | lkdtm.kp.symbol_name = "ll_rw_block"; | 387 | lkdtm.kp.symbol_name = "ll_rw_block"; |
388 | lkdtm.entry = (kprobe_opcode_t*) jp_ll_rw_block; | 388 | lkdtm.entry = (kprobe_opcode_t*) jp_ll_rw_block; |
389 | break; | 389 | break; |
390 | case MEM_SWAPOUT: | 390 | case CN_MEM_SWAPOUT: |
391 | lkdtm.kp.symbol_name = "shrink_inactive_list"; | 391 | lkdtm.kp.symbol_name = "shrink_inactive_list"; |
392 | lkdtm.entry = (kprobe_opcode_t*) jp_shrink_inactive_list; | 392 | lkdtm.entry = (kprobe_opcode_t*) jp_shrink_inactive_list; |
393 | break; | 393 | break; |
394 | case TIMERADD: | 394 | case CN_TIMERADD: |
395 | lkdtm.kp.symbol_name = "hrtimer_start"; | 395 | lkdtm.kp.symbol_name = "hrtimer_start"; |
396 | lkdtm.entry = (kprobe_opcode_t*) jp_hrtimer_start; | 396 | lkdtm.entry = (kprobe_opcode_t*) jp_hrtimer_start; |
397 | break; | 397 | break; |
398 | case SCSI_DISPATCH_CMD: | 398 | case CN_SCSI_DISPATCH_CMD: |
399 | lkdtm.kp.symbol_name = "scsi_dispatch_cmd"; | 399 | lkdtm.kp.symbol_name = "scsi_dispatch_cmd"; |
400 | lkdtm.entry = (kprobe_opcode_t*) jp_scsi_dispatch_cmd; | 400 | lkdtm.entry = (kprobe_opcode_t*) jp_scsi_dispatch_cmd; |
401 | break; | 401 | break; |
402 | case IDE_CORE_CP: | 402 | case CN_IDE_CORE_CP: |
403 | #ifdef CONFIG_IDE | 403 | #ifdef CONFIG_IDE |
404 | lkdtm.kp.symbol_name = "generic_ide_ioctl"; | 404 | lkdtm.kp.symbol_name = "generic_ide_ioctl"; |
405 | lkdtm.entry = (kprobe_opcode_t*) jp_generic_ide_ioctl; | 405 | lkdtm.entry = (kprobe_opcode_t*) jp_generic_ide_ioctl; |
@@ -416,7 +416,7 @@ static int lkdtm_register_cpoint(enum cname which) | |||
416 | cpoint = which; | 416 | cpoint = which; |
417 | if ((ret = register_jprobe(&lkdtm)) < 0) { | 417 | if ((ret = register_jprobe(&lkdtm)) < 0) { |
418 | printk(KERN_INFO "lkdtm: Couldn't register jprobe\n"); | 418 | printk(KERN_INFO "lkdtm: Couldn't register jprobe\n"); |
419 | cpoint = INVALID; | 419 | cpoint = CN_INVALID; |
420 | } | 420 | } |
421 | 421 | ||
422 | return ret; | 422 | return ret; |
@@ -445,7 +445,7 @@ static ssize_t do_register_entry(enum cname which, struct file *f, | |||
445 | cptype = parse_cp_type(buf, count); | 445 | cptype = parse_cp_type(buf, count); |
446 | free_page((unsigned long) buf); | 446 | free_page((unsigned long) buf); |
447 | 447 | ||
448 | if (cptype == NONE) | 448 | if (cptype == CT_NONE) |
449 | return -EINVAL; | 449 | return -EINVAL; |
450 | 450 | ||
451 | err = lkdtm_register_cpoint(which); | 451 | err = lkdtm_register_cpoint(which); |
@@ -487,49 +487,49 @@ static int lkdtm_debugfs_open(struct inode *inode, struct file *file) | |||
487 | static ssize_t int_hardware_entry(struct file *f, const char __user *buf, | 487 | static ssize_t int_hardware_entry(struct file *f, const char __user *buf, |
488 | size_t count, loff_t *off) | 488 | size_t count, loff_t *off) |
489 | { | 489 | { |
490 | return do_register_entry(INT_HARDWARE_ENTRY, f, buf, count, off); | 490 | return do_register_entry(CN_INT_HARDWARE_ENTRY, f, buf, count, off); |
491 | } | 491 | } |
492 | 492 | ||
493 | static ssize_t int_hw_irq_en(struct file *f, const char __user *buf, | 493 | static ssize_t int_hw_irq_en(struct file *f, const char __user *buf, |
494 | size_t count, loff_t *off) | 494 | size_t count, loff_t *off) |
495 | { | 495 | { |
496 | return do_register_entry(INT_HW_IRQ_EN, f, buf, count, off); | 496 | return do_register_entry(CN_INT_HW_IRQ_EN, f, buf, count, off); |
497 | } | 497 | } |
498 | 498 | ||
499 | static ssize_t int_tasklet_entry(struct file *f, const char __user *buf, | 499 | static ssize_t int_tasklet_entry(struct file *f, const char __user *buf, |
500 | size_t count, loff_t *off) | 500 | size_t count, loff_t *off) |
501 | { | 501 | { |
502 | return do_register_entry(INT_TASKLET_ENTRY, f, buf, count, off); | 502 | return do_register_entry(CN_INT_TASKLET_ENTRY, f, buf, count, off); |
503 | } | 503 | } |
504 | 504 | ||
505 | static ssize_t fs_devrw_entry(struct file *f, const char __user *buf, | 505 | static ssize_t fs_devrw_entry(struct file *f, const char __user *buf, |
506 | size_t count, loff_t *off) | 506 | size_t count, loff_t *off) |
507 | { | 507 | { |
508 | return do_register_entry(FS_DEVRW, f, buf, count, off); | 508 | return do_register_entry(CN_FS_DEVRW, f, buf, count, off); |
509 | } | 509 | } |
510 | 510 | ||
511 | static ssize_t mem_swapout_entry(struct file *f, const char __user *buf, | 511 | static ssize_t mem_swapout_entry(struct file *f, const char __user *buf, |
512 | size_t count, loff_t *off) | 512 | size_t count, loff_t *off) |
513 | { | 513 | { |
514 | return do_register_entry(MEM_SWAPOUT, f, buf, count, off); | 514 | return do_register_entry(CN_MEM_SWAPOUT, f, buf, count, off); |
515 | } | 515 | } |
516 | 516 | ||
517 | static ssize_t timeradd_entry(struct file *f, const char __user *buf, | 517 | static ssize_t timeradd_entry(struct file *f, const char __user *buf, |
518 | size_t count, loff_t *off) | 518 | size_t count, loff_t *off) |
519 | { | 519 | { |
520 | return do_register_entry(TIMERADD, f, buf, count, off); | 520 | return do_register_entry(CN_TIMERADD, f, buf, count, off); |
521 | } | 521 | } |
522 | 522 | ||
523 | static ssize_t scsi_dispatch_cmd_entry(struct file *f, | 523 | static ssize_t scsi_dispatch_cmd_entry(struct file *f, |
524 | const char __user *buf, size_t count, loff_t *off) | 524 | const char __user *buf, size_t count, loff_t *off) |
525 | { | 525 | { |
526 | return do_register_entry(SCSI_DISPATCH_CMD, f, buf, count, off); | 526 | return do_register_entry(CN_SCSI_DISPATCH_CMD, f, buf, count, off); |
527 | } | 527 | } |
528 | 528 | ||
529 | static ssize_t ide_core_cp_entry(struct file *f, const char __user *buf, | 529 | static ssize_t ide_core_cp_entry(struct file *f, const char __user *buf, |
530 | size_t count, loff_t *off) | 530 | size_t count, loff_t *off) |
531 | { | 531 | { |
532 | return do_register_entry(IDE_CORE_CP, f, buf, count, off); | 532 | return do_register_entry(CN_IDE_CORE_CP, f, buf, count, off); |
533 | } | 533 | } |
534 | 534 | ||
535 | /* Special entry to just crash directly. Available without KPROBEs */ | 535 | /* Special entry to just crash directly. Available without KPROBEs */ |
@@ -557,7 +557,7 @@ static ssize_t direct_entry(struct file *f, const char __user *user_buf, | |||
557 | 557 | ||
558 | type = parse_cp_type(buf, count); | 558 | type = parse_cp_type(buf, count); |
559 | free_page((unsigned long) buf); | 559 | free_page((unsigned long) buf); |
560 | if (type == NONE) | 560 | if (type == CT_NONE) |
561 | return -EINVAL; | 561 | return -EINVAL; |
562 | 562 | ||
563 | printk(KERN_INFO "lkdtm: Performing direct entry %s\n", | 563 | printk(KERN_INFO "lkdtm: Performing direct entry %s\n", |
@@ -649,7 +649,7 @@ static int __init lkdtm_module_init(void) | |||
649 | goto out_err; | 649 | goto out_err; |
650 | } | 650 | } |
651 | 651 | ||
652 | if (cpoint != INVALID && cptype != NONE) { | 652 | if (cpoint != CN_INVALID && cptype != CT_NONE) { |
653 | ret = lkdtm_register_cpoint(cpoint); | 653 | ret = lkdtm_register_cpoint(cpoint); |
654 | if (ret < 0) { | 654 | if (ret < 0) { |
655 | printk(KERN_INFO "lkdtm: Invalid crash point %d\n", | 655 | printk(KERN_INFO "lkdtm: Invalid crash point %d\n", |
diff --git a/drivers/misc/phantom.c b/drivers/misc/phantom.c index 4197a3cb26ba..b05db55c8c8e 100644 --- a/drivers/misc/phantom.c +++ b/drivers/misc/phantom.c | |||
@@ -343,8 +343,10 @@ static int __devinit phantom_probe(struct pci_dev *pdev, | |||
343 | int retval; | 343 | int retval; |
344 | 344 | ||
345 | retval = pci_enable_device(pdev); | 345 | retval = pci_enable_device(pdev); |
346 | if (retval) | 346 | if (retval) { |
347 | dev_err(&pdev->dev, "pci_enable_device failed!\n"); | ||
347 | goto err; | 348 | goto err; |
349 | } | ||
348 | 350 | ||
349 | minor = phantom_get_free(); | 351 | minor = phantom_get_free(); |
350 | if (minor == PHANTOM_MAX_MINORS) { | 352 | if (minor == PHANTOM_MAX_MINORS) { |
@@ -356,8 +358,10 @@ static int __devinit phantom_probe(struct pci_dev *pdev, | |||
356 | phantom_devices[minor] = 1; | 358 | phantom_devices[minor] = 1; |
357 | 359 | ||
358 | retval = pci_request_regions(pdev, "phantom"); | 360 | retval = pci_request_regions(pdev, "phantom"); |
359 | if (retval) | 361 | if (retval) { |
362 | dev_err(&pdev->dev, "pci_request_regions failed!\n"); | ||
360 | goto err_null; | 363 | goto err_null; |
364 | } | ||
361 | 365 | ||
362 | retval = -ENOMEM; | 366 | retval = -ENOMEM; |
363 | pht = kzalloc(sizeof(*pht), GFP_KERNEL); | 367 | pht = kzalloc(sizeof(*pht), GFP_KERNEL); |
diff --git a/drivers/misc/sgi-xp/xpc_uv.c b/drivers/misc/sgi-xp/xpc_uv.c index 1f59ee2226ca..17bbacb1b4b1 100644 --- a/drivers/misc/sgi-xp/xpc_uv.c +++ b/drivers/misc/sgi-xp/xpc_uv.c | |||
@@ -417,6 +417,7 @@ xpc_process_activate_IRQ_rcvd_uv(void) | |||
417 | static void | 417 | static void |
418 | xpc_handle_activate_mq_msg_uv(struct xpc_partition *part, | 418 | xpc_handle_activate_mq_msg_uv(struct xpc_partition *part, |
419 | struct xpc_activate_mq_msghdr_uv *msg_hdr, | 419 | struct xpc_activate_mq_msghdr_uv *msg_hdr, |
420 | int part_setup, | ||
420 | int *wakeup_hb_checker) | 421 | int *wakeup_hb_checker) |
421 | { | 422 | { |
422 | unsigned long irq_flags; | 423 | unsigned long irq_flags; |
@@ -481,6 +482,9 @@ xpc_handle_activate_mq_msg_uv(struct xpc_partition *part, | |||
481 | case XPC_ACTIVATE_MQ_MSG_CHCTL_CLOSEREQUEST_UV: { | 482 | case XPC_ACTIVATE_MQ_MSG_CHCTL_CLOSEREQUEST_UV: { |
482 | struct xpc_activate_mq_msg_chctl_closerequest_uv *msg; | 483 | struct xpc_activate_mq_msg_chctl_closerequest_uv *msg; |
483 | 484 | ||
485 | if (!part_setup) | ||
486 | break; | ||
487 | |||
484 | msg = container_of(msg_hdr, struct | 488 | msg = container_of(msg_hdr, struct |
485 | xpc_activate_mq_msg_chctl_closerequest_uv, | 489 | xpc_activate_mq_msg_chctl_closerequest_uv, |
486 | hdr); | 490 | hdr); |
@@ -497,6 +501,9 @@ xpc_handle_activate_mq_msg_uv(struct xpc_partition *part, | |||
497 | case XPC_ACTIVATE_MQ_MSG_CHCTL_CLOSEREPLY_UV: { | 501 | case XPC_ACTIVATE_MQ_MSG_CHCTL_CLOSEREPLY_UV: { |
498 | struct xpc_activate_mq_msg_chctl_closereply_uv *msg; | 502 | struct xpc_activate_mq_msg_chctl_closereply_uv *msg; |
499 | 503 | ||
504 | if (!part_setup) | ||
505 | break; | ||
506 | |||
500 | msg = container_of(msg_hdr, struct | 507 | msg = container_of(msg_hdr, struct |
501 | xpc_activate_mq_msg_chctl_closereply_uv, | 508 | xpc_activate_mq_msg_chctl_closereply_uv, |
502 | hdr); | 509 | hdr); |
@@ -511,6 +518,9 @@ xpc_handle_activate_mq_msg_uv(struct xpc_partition *part, | |||
511 | case XPC_ACTIVATE_MQ_MSG_CHCTL_OPENREQUEST_UV: { | 518 | case XPC_ACTIVATE_MQ_MSG_CHCTL_OPENREQUEST_UV: { |
512 | struct xpc_activate_mq_msg_chctl_openrequest_uv *msg; | 519 | struct xpc_activate_mq_msg_chctl_openrequest_uv *msg; |
513 | 520 | ||
521 | if (!part_setup) | ||
522 | break; | ||
523 | |||
514 | msg = container_of(msg_hdr, struct | 524 | msg = container_of(msg_hdr, struct |
515 | xpc_activate_mq_msg_chctl_openrequest_uv, | 525 | xpc_activate_mq_msg_chctl_openrequest_uv, |
516 | hdr); | 526 | hdr); |
@@ -528,6 +538,9 @@ xpc_handle_activate_mq_msg_uv(struct xpc_partition *part, | |||
528 | case XPC_ACTIVATE_MQ_MSG_CHCTL_OPENREPLY_UV: { | 538 | case XPC_ACTIVATE_MQ_MSG_CHCTL_OPENREPLY_UV: { |
529 | struct xpc_activate_mq_msg_chctl_openreply_uv *msg; | 539 | struct xpc_activate_mq_msg_chctl_openreply_uv *msg; |
530 | 540 | ||
541 | if (!part_setup) | ||
542 | break; | ||
543 | |||
531 | msg = container_of(msg_hdr, struct | 544 | msg = container_of(msg_hdr, struct |
532 | xpc_activate_mq_msg_chctl_openreply_uv, hdr); | 545 | xpc_activate_mq_msg_chctl_openreply_uv, hdr); |
533 | args = &part->remote_openclose_args[msg->ch_number]; | 546 | args = &part->remote_openclose_args[msg->ch_number]; |
@@ -545,6 +558,9 @@ xpc_handle_activate_mq_msg_uv(struct xpc_partition *part, | |||
545 | case XPC_ACTIVATE_MQ_MSG_CHCTL_OPENCOMPLETE_UV: { | 558 | case XPC_ACTIVATE_MQ_MSG_CHCTL_OPENCOMPLETE_UV: { |
546 | struct xpc_activate_mq_msg_chctl_opencomplete_uv *msg; | 559 | struct xpc_activate_mq_msg_chctl_opencomplete_uv *msg; |
547 | 560 | ||
561 | if (!part_setup) | ||
562 | break; | ||
563 | |||
548 | msg = container_of(msg_hdr, struct | 564 | msg = container_of(msg_hdr, struct |
549 | xpc_activate_mq_msg_chctl_opencomplete_uv, hdr); | 565 | xpc_activate_mq_msg_chctl_opencomplete_uv, hdr); |
550 | spin_lock_irqsave(&part->chctl_lock, irq_flags); | 566 | spin_lock_irqsave(&part->chctl_lock, irq_flags); |
@@ -621,6 +637,7 @@ xpc_handle_activate_IRQ_uv(int irq, void *dev_id) | |||
621 | 637 | ||
622 | part_referenced = xpc_part_ref(part); | 638 | part_referenced = xpc_part_ref(part); |
623 | xpc_handle_activate_mq_msg_uv(part, msg_hdr, | 639 | xpc_handle_activate_mq_msg_uv(part, msg_hdr, |
640 | part_referenced, | ||
624 | &wakeup_hb_checker); | 641 | &wakeup_hb_checker); |
625 | if (part_referenced) | 642 | if (part_referenced) |
626 | xpc_part_deref(part); | 643 | xpc_part_deref(part); |
diff --git a/drivers/video/au1200fb.c b/drivers/video/au1200fb.c index e77e8e4280fb..4ea187d93768 100644 --- a/drivers/video/au1200fb.c +++ b/drivers/video/au1200fb.c | |||
@@ -1079,7 +1079,7 @@ static int au1200fb_fb_check_var(struct fb_var_screeninfo *var, | |||
1079 | * clock can only be obtain by dividing this value by an even integer. | 1079 | * clock can only be obtain by dividing this value by an even integer. |
1080 | * Fallback to a slower pixel clock if necessary. */ | 1080 | * Fallback to a slower pixel clock if necessary. */ |
1081 | pixclock = max((u32)(PICOS2KHZ(var->pixclock) * 1000), fbi->monspecs.dclkmin); | 1081 | pixclock = max((u32)(PICOS2KHZ(var->pixclock) * 1000), fbi->monspecs.dclkmin); |
1082 | pixclock = min(pixclock, min(fbi->monspecs.dclkmax, (u32)AU1200_LCD_MAX_CLK/2)); | 1082 | pixclock = min3(pixclock, fbi->monspecs.dclkmax, (u32)AU1200_LCD_MAX_CLK/2); |
1083 | 1083 | ||
1084 | if (AU1200_LCD_MAX_CLK % pixclock) { | 1084 | if (AU1200_LCD_MAX_CLK % pixclock) { |
1085 | int diff = AU1200_LCD_MAX_CLK % pixclock; | 1085 | int diff = AU1200_LCD_MAX_CLK % pixclock; |
diff --git a/firmware/ihex2fw.c b/firmware/ihex2fw.c index 5a03ba8c8364..ba0cf0b601bb 100644 --- a/firmware/ihex2fw.c +++ b/firmware/ihex2fw.c | |||
@@ -55,6 +55,7 @@ static int output_records(int outfd); | |||
55 | 55 | ||
56 | static int sort_records = 0; | 56 | static int sort_records = 0; |
57 | static int wide_records = 0; | 57 | static int wide_records = 0; |
58 | static int include_jump = 0; | ||
58 | 59 | ||
59 | static int usage(void) | 60 | static int usage(void) |
60 | { | 61 | { |
@@ -63,6 +64,7 @@ static int usage(void) | |||
63 | fprintf(stderr, "usage: ihex2fw [<options>] <src.HEX> <dst.fw>\n"); | 64 | fprintf(stderr, "usage: ihex2fw [<options>] <src.HEX> <dst.fw>\n"); |
64 | fprintf(stderr, " -w: wide records (16-bit length)\n"); | 65 | fprintf(stderr, " -w: wide records (16-bit length)\n"); |
65 | fprintf(stderr, " -s: sort records by address\n"); | 66 | fprintf(stderr, " -s: sort records by address\n"); |
67 | fprintf(stderr, " -j: include records for CS:IP/EIP address\n"); | ||
66 | return 1; | 68 | return 1; |
67 | } | 69 | } |
68 | 70 | ||
@@ -73,7 +75,7 @@ int main(int argc, char **argv) | |||
73 | uint8_t *data; | 75 | uint8_t *data; |
74 | int opt; | 76 | int opt; |
75 | 77 | ||
76 | while ((opt = getopt(argc, argv, "ws")) != -1) { | 78 | while ((opt = getopt(argc, argv, "wsj")) != -1) { |
77 | switch (opt) { | 79 | switch (opt) { |
78 | case 'w': | 80 | case 'w': |
79 | wide_records = 1; | 81 | wide_records = 1; |
@@ -81,7 +83,9 @@ int main(int argc, char **argv) | |||
81 | case 's': | 83 | case 's': |
82 | sort_records = 1; | 84 | sort_records = 1; |
83 | break; | 85 | break; |
84 | default: | 86 | case 'j': |
87 | include_jump = 1; | ||
88 | break; | ||
85 | return usage(); | 89 | return usage(); |
86 | } | 90 | } |
87 | } | 91 | } |
@@ -128,6 +132,7 @@ static int process_ihex(uint8_t *data, ssize_t size) | |||
128 | { | 132 | { |
129 | struct ihex_binrec *record; | 133 | struct ihex_binrec *record; |
130 | uint32_t offset = 0; | 134 | uint32_t offset = 0; |
135 | uint32_t data32; | ||
131 | uint8_t type, crc = 0, crcbyte = 0; | 136 | uint8_t type, crc = 0, crcbyte = 0; |
132 | int i, j; | 137 | int i, j; |
133 | int line = 1; | 138 | int line = 1; |
@@ -223,8 +228,14 @@ next_record: | |||
223 | return -EINVAL; | 228 | return -EINVAL; |
224 | } | 229 | } |
225 | 230 | ||
231 | memcpy(&data32, &record->data[0], sizeof(data32)); | ||
232 | data32 = htonl(data32); | ||
233 | memcpy(&record->data[0], &data32, sizeof(data32)); | ||
234 | |||
226 | /* These records contain the CS/IP or EIP where execution | 235 | /* These records contain the CS/IP or EIP where execution |
227 | * starts. Don't really know what to do with them. */ | 236 | * starts. If requested output this as a record. */ |
237 | if (include_jump) | ||
238 | file_record(record); | ||
228 | goto next_record; | 239 | goto next_record; |
229 | 240 | ||
230 | default: | 241 | default: |
diff --git a/fs/Kconfig b/fs/Kconfig index 65781de44fc0..b5e582bd769d 100644 --- a/fs/Kconfig +++ b/fs/Kconfig | |||
@@ -47,6 +47,9 @@ source "fs/nilfs2/Kconfig" | |||
47 | 47 | ||
48 | endif # BLOCK | 48 | endif # BLOCK |
49 | 49 | ||
50 | config EXPORTFS | ||
51 | tristate | ||
52 | |||
50 | config FILE_LOCKING | 53 | config FILE_LOCKING |
51 | bool "Enable POSIX file locking API" if EMBEDDED | 54 | bool "Enable POSIX file locking API" if EMBEDDED |
52 | default y | 55 | default y |
@@ -222,9 +225,6 @@ config LOCKD_V4 | |||
222 | depends on FILE_LOCKING | 225 | depends on FILE_LOCKING |
223 | default y | 226 | default y |
224 | 227 | ||
225 | config EXPORTFS | ||
226 | tristate | ||
227 | |||
228 | config NFS_ACL_SUPPORT | 228 | config NFS_ACL_SUPPORT |
229 | tristate | 229 | tristate |
230 | select FS_POSIX_ACL | 230 | select FS_POSIX_ACL |
diff --git a/fs/afs/write.c b/fs/afs/write.c index 722743b152d8..15690bb1d3b5 100644 --- a/fs/afs/write.c +++ b/fs/afs/write.c | |||
@@ -438,7 +438,6 @@ no_more: | |||
438 | */ | 438 | */ |
439 | int afs_writepage(struct page *page, struct writeback_control *wbc) | 439 | int afs_writepage(struct page *page, struct writeback_control *wbc) |
440 | { | 440 | { |
441 | struct backing_dev_info *bdi = page->mapping->backing_dev_info; | ||
442 | struct afs_writeback *wb; | 441 | struct afs_writeback *wb; |
443 | int ret; | 442 | int ret; |
444 | 443 | ||
@@ -455,8 +454,6 @@ int afs_writepage(struct page *page, struct writeback_control *wbc) | |||
455 | } | 454 | } |
456 | 455 | ||
457 | wbc->nr_to_write -= ret; | 456 | wbc->nr_to_write -= ret; |
458 | if (wbc->nonblocking && bdi_write_congested(bdi)) | ||
459 | wbc->encountered_congestion = 1; | ||
460 | 457 | ||
461 | _leave(" = 0"); | 458 | _leave(" = 0"); |
462 | return 0; | 459 | return 0; |
@@ -469,7 +466,6 @@ static int afs_writepages_region(struct address_space *mapping, | |||
469 | struct writeback_control *wbc, | 466 | struct writeback_control *wbc, |
470 | pgoff_t index, pgoff_t end, pgoff_t *_next) | 467 | pgoff_t index, pgoff_t end, pgoff_t *_next) |
471 | { | 468 | { |
472 | struct backing_dev_info *bdi = mapping->backing_dev_info; | ||
473 | struct afs_writeback *wb; | 469 | struct afs_writeback *wb; |
474 | struct page *page; | 470 | struct page *page; |
475 | int ret, n; | 471 | int ret, n; |
@@ -529,11 +525,6 @@ static int afs_writepages_region(struct address_space *mapping, | |||
529 | 525 | ||
530 | wbc->nr_to_write -= ret; | 526 | wbc->nr_to_write -= ret; |
531 | 527 | ||
532 | if (wbc->nonblocking && bdi_write_congested(bdi)) { | ||
533 | wbc->encountered_congestion = 1; | ||
534 | break; | ||
535 | } | ||
536 | |||
537 | cond_resched(); | 528 | cond_resched(); |
538 | } while (index < end && wbc->nr_to_write > 0); | 529 | } while (index < end && wbc->nr_to_write > 0); |
539 | 530 | ||
@@ -548,24 +539,16 @@ static int afs_writepages_region(struct address_space *mapping, | |||
548 | int afs_writepages(struct address_space *mapping, | 539 | int afs_writepages(struct address_space *mapping, |
549 | struct writeback_control *wbc) | 540 | struct writeback_control *wbc) |
550 | { | 541 | { |
551 | struct backing_dev_info *bdi = mapping->backing_dev_info; | ||
552 | pgoff_t start, end, next; | 542 | pgoff_t start, end, next; |
553 | int ret; | 543 | int ret; |
554 | 544 | ||
555 | _enter(""); | 545 | _enter(""); |
556 | 546 | ||
557 | if (wbc->nonblocking && bdi_write_congested(bdi)) { | ||
558 | wbc->encountered_congestion = 1; | ||
559 | _leave(" = 0 [congest]"); | ||
560 | return 0; | ||
561 | } | ||
562 | |||
563 | if (wbc->range_cyclic) { | 547 | if (wbc->range_cyclic) { |
564 | start = mapping->writeback_index; | 548 | start = mapping->writeback_index; |
565 | end = -1; | 549 | end = -1; |
566 | ret = afs_writepages_region(mapping, wbc, start, end, &next); | 550 | ret = afs_writepages_region(mapping, wbc, start, end, &next); |
567 | if (start > 0 && wbc->nr_to_write > 0 && ret == 0 && | 551 | if (start > 0 && wbc->nr_to_write > 0 && ret == 0) |
568 | !(wbc->nonblocking && wbc->encountered_congestion)) | ||
569 | ret = afs_writepages_region(mapping, wbc, 0, start, | 552 | ret = afs_writepages_region(mapping, wbc, 0, start, |
570 | &next); | 553 | &next); |
571 | mapping->writeback_index = next; | 554 | mapping->writeback_index = next; |
diff --git a/fs/buffer.c b/fs/buffer.c index 7f0b9b083f77..8d595ab2aed1 100644 --- a/fs/buffer.c +++ b/fs/buffer.c | |||
@@ -905,7 +905,6 @@ try_again: | |||
905 | 905 | ||
906 | bh->b_state = 0; | 906 | bh->b_state = 0; |
907 | atomic_set(&bh->b_count, 0); | 907 | atomic_set(&bh->b_count, 0); |
908 | bh->b_private = NULL; | ||
909 | bh->b_size = size; | 908 | bh->b_size = size; |
910 | 909 | ||
911 | /* Link the buffer to its page */ | 910 | /* Link the buffer to its page */ |
@@ -1706,7 +1705,7 @@ static int __block_write_full_page(struct inode *inode, struct page *page, | |||
1706 | * and kswapd activity, but those code paths have their own | 1705 | * and kswapd activity, but those code paths have their own |
1707 | * higher-level throttling. | 1706 | * higher-level throttling. |
1708 | */ | 1707 | */ |
1709 | if (wbc->sync_mode != WB_SYNC_NONE || !wbc->nonblocking) { | 1708 | if (wbc->sync_mode != WB_SYNC_NONE) { |
1710 | lock_buffer(bh); | 1709 | lock_buffer(bh); |
1711 | } else if (!trylock_buffer(bh)) { | 1710 | } else if (!trylock_buffer(bh)) { |
1712 | redirty_page_for_writepage(wbc, page); | 1711 | redirty_page_for_writepage(wbc, page); |
diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c index 51bcc5ce3230..e9c874abc9e1 100644 --- a/fs/ceph/addr.c +++ b/fs/ceph/addr.c | |||
@@ -591,7 +591,6 @@ static int ceph_writepages_start(struct address_space *mapping, | |||
591 | struct writeback_control *wbc) | 591 | struct writeback_control *wbc) |
592 | { | 592 | { |
593 | struct inode *inode = mapping->host; | 593 | struct inode *inode = mapping->host; |
594 | struct backing_dev_info *bdi = mapping->backing_dev_info; | ||
595 | struct ceph_inode_info *ci = ceph_inode(inode); | 594 | struct ceph_inode_info *ci = ceph_inode(inode); |
596 | struct ceph_fs_client *fsc; | 595 | struct ceph_fs_client *fsc; |
597 | pgoff_t index, start, end; | 596 | pgoff_t index, start, end; |
@@ -633,13 +632,6 @@ static int ceph_writepages_start(struct address_space *mapping, | |||
633 | 632 | ||
634 | pagevec_init(&pvec, 0); | 633 | pagevec_init(&pvec, 0); |
635 | 634 | ||
636 | /* ?? */ | ||
637 | if (wbc->nonblocking && bdi_write_congested(bdi)) { | ||
638 | dout(" writepages congested\n"); | ||
639 | wbc->encountered_congestion = 1; | ||
640 | goto out_final; | ||
641 | } | ||
642 | |||
643 | /* where to start/end? */ | 635 | /* where to start/end? */ |
644 | if (wbc->range_cyclic) { | 636 | if (wbc->range_cyclic) { |
645 | start = mapping->writeback_index; /* Start from prev offset */ | 637 | start = mapping->writeback_index; /* Start from prev offset */ |
@@ -885,7 +877,6 @@ out: | |||
885 | rc = 0; /* vfs expects us to return 0 */ | 877 | rc = 0; /* vfs expects us to return 0 */ |
886 | ceph_put_snap_context(snapc); | 878 | ceph_put_snap_context(snapc); |
887 | dout("writepages done, rc = %d\n", rc); | 879 | dout("writepages done, rc = %d\n", rc); |
888 | out_final: | ||
889 | return rc; | 880 | return rc; |
890 | } | 881 | } |
891 | 882 | ||
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 8c81e7b14d53..45af003865d2 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
@@ -1303,7 +1303,6 @@ static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to) | |||
1303 | static int cifs_writepages(struct address_space *mapping, | 1303 | static int cifs_writepages(struct address_space *mapping, |
1304 | struct writeback_control *wbc) | 1304 | struct writeback_control *wbc) |
1305 | { | 1305 | { |
1306 | struct backing_dev_info *bdi = mapping->backing_dev_info; | ||
1307 | unsigned int bytes_to_write; | 1306 | unsigned int bytes_to_write; |
1308 | unsigned int bytes_written; | 1307 | unsigned int bytes_written; |
1309 | struct cifs_sb_info *cifs_sb; | 1308 | struct cifs_sb_info *cifs_sb; |
@@ -1326,15 +1325,6 @@ static int cifs_writepages(struct address_space *mapping, | |||
1326 | int scanned = 0; | 1325 | int scanned = 0; |
1327 | int xid, long_op; | 1326 | int xid, long_op; |
1328 | 1327 | ||
1329 | /* | ||
1330 | * BB: Is this meaningful for a non-block-device file system? | ||
1331 | * If it is, we should test it again after we do I/O | ||
1332 | */ | ||
1333 | if (wbc->nonblocking && bdi_write_congested(bdi)) { | ||
1334 | wbc->encountered_congestion = 1; | ||
1335 | return 0; | ||
1336 | } | ||
1337 | |||
1338 | cifs_sb = CIFS_SB(mapping->host->i_sb); | 1328 | cifs_sb = CIFS_SB(mapping->host->i_sb); |
1339 | 1329 | ||
1340 | /* | 1330 | /* |
diff --git a/fs/direct-io.c b/fs/direct-io.c index 48d74c7391d1..85882f6ba5f7 100644 --- a/fs/direct-io.c +++ b/fs/direct-io.c | |||
@@ -218,7 +218,7 @@ static struct page *dio_get_page(struct dio *dio) | |||
218 | * filesystems can use it to hold additional state between get_block calls and | 218 | * filesystems can use it to hold additional state between get_block calls and |
219 | * dio_complete. | 219 | * dio_complete. |
220 | */ | 220 | */ |
221 | static int dio_complete(struct dio *dio, loff_t offset, int ret, bool is_async) | 221 | static ssize_t dio_complete(struct dio *dio, loff_t offset, ssize_t ret, bool is_async) |
222 | { | 222 | { |
223 | ssize_t transferred = 0; | 223 | ssize_t transferred = 0; |
224 | 224 | ||
@@ -54,6 +54,7 @@ | |||
54 | #include <linux/fsnotify.h> | 54 | #include <linux/fsnotify.h> |
55 | #include <linux/fs_struct.h> | 55 | #include <linux/fs_struct.h> |
56 | #include <linux/pipe_fs_i.h> | 56 | #include <linux/pipe_fs_i.h> |
57 | #include <linux/oom.h> | ||
57 | 58 | ||
58 | #include <asm/uaccess.h> | 59 | #include <asm/uaccess.h> |
59 | #include <asm/mmu_context.h> | 60 | #include <asm/mmu_context.h> |
@@ -759,6 +760,10 @@ static int exec_mmap(struct mm_struct *mm) | |||
759 | tsk->mm = mm; | 760 | tsk->mm = mm; |
760 | tsk->active_mm = mm; | 761 | tsk->active_mm = mm; |
761 | activate_mm(active_mm, mm); | 762 | activate_mm(active_mm, mm); |
763 | if (old_mm && tsk->signal->oom_score_adj == OOM_SCORE_ADJ_MIN) { | ||
764 | atomic_dec(&old_mm->oom_disable_count); | ||
765 | atomic_inc(&tsk->mm->oom_disable_count); | ||
766 | } | ||
762 | task_unlock(tsk); | 767 | task_unlock(tsk); |
763 | arch_pick_mmap_layout(mm); | 768 | arch_pick_mmap_layout(mm); |
764 | if (old_mm) { | 769 | if (old_mm) { |
diff --git a/fs/file_table.c b/fs/file_table.c index a04bdd81c11c..c3dee381f1b4 100644 --- a/fs/file_table.c +++ b/fs/file_table.c | |||
@@ -60,7 +60,7 @@ static inline void file_free(struct file *f) | |||
60 | /* | 60 | /* |
61 | * Return the total number of open files in the system | 61 | * Return the total number of open files in the system |
62 | */ | 62 | */ |
63 | static int get_nr_files(void) | 63 | static long get_nr_files(void) |
64 | { | 64 | { |
65 | return percpu_counter_read_positive(&nr_files); | 65 | return percpu_counter_read_positive(&nr_files); |
66 | } | 66 | } |
@@ -68,7 +68,7 @@ static int get_nr_files(void) | |||
68 | /* | 68 | /* |
69 | * Return the maximum number of open files in the system | 69 | * Return the maximum number of open files in the system |
70 | */ | 70 | */ |
71 | int get_max_files(void) | 71 | unsigned long get_max_files(void) |
72 | { | 72 | { |
73 | return files_stat.max_files; | 73 | return files_stat.max_files; |
74 | } | 74 | } |
@@ -82,7 +82,7 @@ int proc_nr_files(ctl_table *table, int write, | |||
82 | void __user *buffer, size_t *lenp, loff_t *ppos) | 82 | void __user *buffer, size_t *lenp, loff_t *ppos) |
83 | { | 83 | { |
84 | files_stat.nr_files = get_nr_files(); | 84 | files_stat.nr_files = get_nr_files(); |
85 | return proc_dointvec(table, write, buffer, lenp, ppos); | 85 | return proc_doulongvec_minmax(table, write, buffer, lenp, ppos); |
86 | } | 86 | } |
87 | #else | 87 | #else |
88 | int proc_nr_files(ctl_table *table, int write, | 88 | int proc_nr_files(ctl_table *table, int write, |
@@ -105,7 +105,7 @@ int proc_nr_files(ctl_table *table, int write, | |||
105 | struct file *get_empty_filp(void) | 105 | struct file *get_empty_filp(void) |
106 | { | 106 | { |
107 | const struct cred *cred = current_cred(); | 107 | const struct cred *cred = current_cred(); |
108 | static int old_max; | 108 | static long old_max; |
109 | struct file * f; | 109 | struct file * f; |
110 | 110 | ||
111 | /* | 111 | /* |
@@ -140,8 +140,7 @@ struct file *get_empty_filp(void) | |||
140 | over: | 140 | over: |
141 | /* Ran out of filps - report that */ | 141 | /* Ran out of filps - report that */ |
142 | if (get_nr_files() > old_max) { | 142 | if (get_nr_files() > old_max) { |
143 | printk(KERN_INFO "VFS: file-max limit %d reached\n", | 143 | pr_info("VFS: file-max limit %lu reached\n", get_max_files()); |
144 | get_max_files()); | ||
145 | old_max = get_nr_files(); | 144 | old_max = get_nr_files(); |
146 | } | 145 | } |
147 | goto fail; | 146 | goto fail; |
@@ -487,7 +486,7 @@ retry: | |||
487 | 486 | ||
488 | void __init files_init(unsigned long mempages) | 487 | void __init files_init(unsigned long mempages) |
489 | { | 488 | { |
490 | int n; | 489 | unsigned long n; |
491 | 490 | ||
492 | filp_cachep = kmem_cache_create("filp", sizeof(struct file), 0, | 491 | filp_cachep = kmem_cache_create("filp", sizeof(struct file), 0, |
493 | SLAB_HWCACHE_ALIGN | SLAB_PANIC, NULL); | 492 | SLAB_HWCACHE_ALIGN | SLAB_PANIC, NULL); |
@@ -498,9 +497,7 @@ void __init files_init(unsigned long mempages) | |||
498 | */ | 497 | */ |
499 | 498 | ||
500 | n = (mempages * (PAGE_SIZE / 1024)) / 10; | 499 | n = (mempages * (PAGE_SIZE / 1024)) / 10; |
501 | files_stat.max_files = n; | 500 | files_stat.max_files = max_t(unsigned long, n, NR_FILE); |
502 | if (files_stat.max_files < NR_FILE) | ||
503 | files_stat.max_files = NR_FILE; | ||
504 | files_defer_init(); | 501 | files_defer_init(); |
505 | lg_lock_init(files_lglock); | 502 | lg_lock_init(files_lglock); |
506 | percpu_counter_init(&nr_files, 0); | 503 | percpu_counter_init(&nr_files, 0); |
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index ab38fef1c9a1..9e46aec10d1a 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c | |||
@@ -582,7 +582,7 @@ static inline bool over_bground_thresh(void) | |||
582 | global_dirty_limits(&background_thresh, &dirty_thresh); | 582 | global_dirty_limits(&background_thresh, &dirty_thresh); |
583 | 583 | ||
584 | return (global_page_state(NR_FILE_DIRTY) + | 584 | return (global_page_state(NR_FILE_DIRTY) + |
585 | global_page_state(NR_UNSTABLE_NFS) >= background_thresh); | 585 | global_page_state(NR_UNSTABLE_NFS) > background_thresh); |
586 | } | 586 | } |
587 | 587 | ||
588 | /* | 588 | /* |
@@ -721,6 +721,10 @@ static long wb_check_old_data_flush(struct bdi_writeback *wb) | |||
721 | return 0; | 721 | return 0; |
722 | 722 | ||
723 | wb->last_old_flush = jiffies; | 723 | wb->last_old_flush = jiffies; |
724 | /* | ||
725 | * Add in the number of potentially dirty inodes, because each inode | ||
726 | * write can dirty pagecache in the underlying blockdev. | ||
727 | */ | ||
724 | nr_pages = global_page_state(NR_FILE_DIRTY) + | 728 | nr_pages = global_page_state(NR_FILE_DIRTY) + |
725 | global_page_state(NR_UNSTABLE_NFS) + | 729 | global_page_state(NR_UNSTABLE_NFS) + |
726 | (inodes_stat.nr_inodes - inodes_stat.nr_unused); | 730 | (inodes_stat.nr_inodes - inodes_stat.nr_unused); |
@@ -790,7 +794,7 @@ int bdi_writeback_thread(void *data) | |||
790 | struct backing_dev_info *bdi = wb->bdi; | 794 | struct backing_dev_info *bdi = wb->bdi; |
791 | long pages_written; | 795 | long pages_written; |
792 | 796 | ||
793 | current->flags |= PF_FLUSHER | PF_SWAPWRITE; | 797 | current->flags |= PF_SWAPWRITE; |
794 | set_freezable(); | 798 | set_freezable(); |
795 | wb->last_active = jiffies; | 799 | wb->last_active = jiffies; |
796 | 800 | ||
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index cde755cca564..b98664275f02 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c | |||
@@ -809,11 +809,9 @@ static int fuse_copy_page(struct fuse_copy_state *cs, struct page **pagep, | |||
809 | int err; | 809 | int err; |
810 | struct page *page = *pagep; | 810 | struct page *page = *pagep; |
811 | 811 | ||
812 | if (page && zeroing && count < PAGE_SIZE) { | 812 | if (page && zeroing && count < PAGE_SIZE) |
813 | void *mapaddr = kmap_atomic(page, KM_USER1); | 813 | clear_highpage(page); |
814 | memset(mapaddr, 0, PAGE_SIZE); | 814 | |
815 | kunmap_atomic(mapaddr, KM_USER1); | ||
816 | } | ||
817 | while (count) { | 815 | while (count) { |
818 | if (cs->write && cs->pipebufs && page) { | 816 | if (cs->write && cs->pipebufs && page) { |
819 | return fuse_ref_page(cs, page, offset, count); | 817 | return fuse_ref_page(cs, page, offset, count); |
@@ -830,10 +828,10 @@ static int fuse_copy_page(struct fuse_copy_state *cs, struct page **pagep, | |||
830 | } | 828 | } |
831 | } | 829 | } |
832 | if (page) { | 830 | if (page) { |
833 | void *mapaddr = kmap_atomic(page, KM_USER1); | 831 | void *mapaddr = kmap_atomic(page, KM_USER0); |
834 | void *buf = mapaddr + offset; | 832 | void *buf = mapaddr + offset; |
835 | offset += fuse_copy_do(cs, &buf, &count); | 833 | offset += fuse_copy_do(cs, &buf, &count); |
836 | kunmap_atomic(mapaddr, KM_USER1); | 834 | kunmap_atomic(mapaddr, KM_USER0); |
837 | } else | 835 | } else |
838 | offset += fuse_copy_do(cs, NULL, &count); | 836 | offset += fuse_copy_do(cs, NULL, &count); |
839 | } | 837 | } |
diff --git a/fs/gfs2/meta_io.c b/fs/gfs2/meta_io.c index f3b071f921aa..939739c7b3f9 100644 --- a/fs/gfs2/meta_io.c +++ b/fs/gfs2/meta_io.c | |||
@@ -55,7 +55,7 @@ static int gfs2_aspace_writepage(struct page *page, struct writeback_control *wb | |||
55 | * activity, but those code paths have their own higher-level | 55 | * activity, but those code paths have their own higher-level |
56 | * throttling. | 56 | * throttling. |
57 | */ | 57 | */ |
58 | if (wbc->sync_mode != WB_SYNC_NONE || !wbc->nonblocking) { | 58 | if (wbc->sync_mode != WB_SYNC_NONE) { |
59 | lock_buffer(bh); | 59 | lock_buffer(bh); |
60 | } else if (!trylock_buffer(bh)) { | 60 | } else if (!trylock_buffer(bh)) { |
61 | redirty_page_for_writepage(wbc, page); | 61 | redirty_page_for_writepage(wbc, page); |
diff --git a/fs/hostfs/hostfs.h b/fs/hostfs/hostfs.h index 7c232c1487ee..bf15a43016b9 100644 --- a/fs/hostfs/hostfs.h +++ b/fs/hostfs/hostfs.h | |||
@@ -91,7 +91,6 @@ extern int rename_file(char *from, char *to); | |||
91 | extern int do_statfs(char *root, long *bsize_out, long long *blocks_out, | 91 | extern int do_statfs(char *root, long *bsize_out, long long *blocks_out, |
92 | long long *bfree_out, long long *bavail_out, | 92 | long long *bfree_out, long long *bavail_out, |
93 | long long *files_out, long long *ffree_out, | 93 | long long *files_out, long long *ffree_out, |
94 | void *fsid_out, int fsid_size, long *namelen_out, | 94 | void *fsid_out, int fsid_size, long *namelen_out); |
95 | long *spare_out); | ||
96 | 95 | ||
97 | #endif | 96 | #endif |
diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c index f7dc9b5f9ef8..cd7c93917cc7 100644 --- a/fs/hostfs/hostfs_kern.c +++ b/fs/hostfs/hostfs_kern.c | |||
@@ -217,7 +217,7 @@ int hostfs_statfs(struct dentry *dentry, struct kstatfs *sf) | |||
217 | err = do_statfs(dentry->d_sb->s_fs_info, | 217 | err = do_statfs(dentry->d_sb->s_fs_info, |
218 | &sf->f_bsize, &f_blocks, &f_bfree, &f_bavail, &f_files, | 218 | &sf->f_bsize, &f_blocks, &f_bfree, &f_bavail, &f_files, |
219 | &f_ffree, &sf->f_fsid, sizeof(sf->f_fsid), | 219 | &f_ffree, &sf->f_fsid, sizeof(sf->f_fsid), |
220 | &sf->f_namelen, sf->f_spare); | 220 | &sf->f_namelen); |
221 | if (err) | 221 | if (err) |
222 | return err; | 222 | return err; |
223 | sf->f_blocks = f_blocks; | 223 | sf->f_blocks = f_blocks; |
diff --git a/fs/hostfs/hostfs_user.c b/fs/hostfs/hostfs_user.c index 6777aa06ce2c..d51a98384bc0 100644 --- a/fs/hostfs/hostfs_user.c +++ b/fs/hostfs/hostfs_user.c | |||
@@ -94,8 +94,7 @@ void *open_dir(char *path, int *err_out) | |||
94 | 94 | ||
95 | dir = opendir(path); | 95 | dir = opendir(path); |
96 | *err_out = errno; | 96 | *err_out = errno; |
97 | if (dir == NULL) | 97 | |
98 | return NULL; | ||
99 | return dir; | 98 | return dir; |
100 | } | 99 | } |
101 | 100 | ||
@@ -205,7 +204,7 @@ int set_attr(const char *file, struct hostfs_iattr *attrs, int fd) | |||
205 | if (attrs->ia_valid & HOSTFS_ATTR_MODE) { | 204 | if (attrs->ia_valid & HOSTFS_ATTR_MODE) { |
206 | if (fd >= 0) { | 205 | if (fd >= 0) { |
207 | if (fchmod(fd, attrs->ia_mode) != 0) | 206 | if (fchmod(fd, attrs->ia_mode) != 0) |
208 | return (-errno); | 207 | return -errno; |
209 | } else if (chmod(file, attrs->ia_mode) != 0) { | 208 | } else if (chmod(file, attrs->ia_mode) != 0) { |
210 | return -errno; | 209 | return -errno; |
211 | } | 210 | } |
@@ -364,8 +363,7 @@ int rename_file(char *from, char *to) | |||
364 | int do_statfs(char *root, long *bsize_out, long long *blocks_out, | 363 | int do_statfs(char *root, long *bsize_out, long long *blocks_out, |
365 | long long *bfree_out, long long *bavail_out, | 364 | long long *bfree_out, long long *bavail_out, |
366 | long long *files_out, long long *ffree_out, | 365 | long long *files_out, long long *ffree_out, |
367 | void *fsid_out, int fsid_size, long *namelen_out, | 366 | void *fsid_out, int fsid_size, long *namelen_out) |
368 | long *spare_out) | ||
369 | { | 367 | { |
370 | struct statfs64 buf; | 368 | struct statfs64 buf; |
371 | int err; | 369 | int err; |
@@ -384,10 +382,6 @@ int do_statfs(char *root, long *bsize_out, long long *blocks_out, | |||
384 | sizeof(buf.f_fsid) > fsid_size ? fsid_size : | 382 | sizeof(buf.f_fsid) > fsid_size ? fsid_size : |
385 | sizeof(buf.f_fsid)); | 383 | sizeof(buf.f_fsid)); |
386 | *namelen_out = buf.f_namelen; | 384 | *namelen_out = buf.f_namelen; |
387 | spare_out[0] = buf.f_spare[0]; | 385 | |
388 | spare_out[1] = buf.f_spare[1]; | ||
389 | spare_out[2] = buf.f_spare[2]; | ||
390 | spare_out[3] = buf.f_spare[3]; | ||
391 | spare_out[4] = buf.f_spare[4]; | ||
392 | return 0; | 386 | return 0; |
393 | } | 387 | } |
diff --git a/fs/locks.c b/fs/locks.c index 8b2b6ad56a09..4de3a2666810 100644 --- a/fs/locks.c +++ b/fs/locks.c | |||
@@ -2109,7 +2109,7 @@ EXPORT_SYMBOL_GPL(vfs_cancel_lock); | |||
2109 | #include <linux/seq_file.h> | 2109 | #include <linux/seq_file.h> |
2110 | 2110 | ||
2111 | static void lock_get_status(struct seq_file *f, struct file_lock *fl, | 2111 | static void lock_get_status(struct seq_file *f, struct file_lock *fl, |
2112 | int id, char *pfx) | 2112 | loff_t id, char *pfx) |
2113 | { | 2113 | { |
2114 | struct inode *inode = NULL; | 2114 | struct inode *inode = NULL; |
2115 | unsigned int fl_pid; | 2115 | unsigned int fl_pid; |
@@ -2122,7 +2122,7 @@ static void lock_get_status(struct seq_file *f, struct file_lock *fl, | |||
2122 | if (fl->fl_file != NULL) | 2122 | if (fl->fl_file != NULL) |
2123 | inode = fl->fl_file->f_path.dentry->d_inode; | 2123 | inode = fl->fl_file->f_path.dentry->d_inode; |
2124 | 2124 | ||
2125 | seq_printf(f, "%d:%s ", id, pfx); | 2125 | seq_printf(f, "%lld:%s ", id, pfx); |
2126 | if (IS_POSIX(fl)) { | 2126 | if (IS_POSIX(fl)) { |
2127 | seq_printf(f, "%6s %s ", | 2127 | seq_printf(f, "%6s %s ", |
2128 | (fl->fl_flags & FL_ACCESS) ? "ACCESS" : "POSIX ", | 2128 | (fl->fl_flags & FL_ACCESS) ? "ACCESS" : "POSIX ", |
@@ -2185,24 +2185,27 @@ static int locks_show(struct seq_file *f, void *v) | |||
2185 | 2185 | ||
2186 | fl = list_entry(v, struct file_lock, fl_link); | 2186 | fl = list_entry(v, struct file_lock, fl_link); |
2187 | 2187 | ||
2188 | lock_get_status(f, fl, (long)f->private, ""); | 2188 | lock_get_status(f, fl, *((loff_t *)f->private), ""); |
2189 | 2189 | ||
2190 | list_for_each_entry(bfl, &fl->fl_block, fl_block) | 2190 | list_for_each_entry(bfl, &fl->fl_block, fl_block) |
2191 | lock_get_status(f, bfl, (long)f->private, " ->"); | 2191 | lock_get_status(f, bfl, *((loff_t *)f->private), " ->"); |
2192 | 2192 | ||
2193 | f->private++; | ||
2194 | return 0; | 2193 | return 0; |
2195 | } | 2194 | } |
2196 | 2195 | ||
2197 | static void *locks_start(struct seq_file *f, loff_t *pos) | 2196 | static void *locks_start(struct seq_file *f, loff_t *pos) |
2198 | { | 2197 | { |
2198 | loff_t *p = f->private; | ||
2199 | |||
2199 | lock_flocks(); | 2200 | lock_flocks(); |
2200 | f->private = (void *)1; | 2201 | *p = (*pos + 1); |
2201 | return seq_list_start(&file_lock_list, *pos); | 2202 | return seq_list_start(&file_lock_list, *pos); |
2202 | } | 2203 | } |
2203 | 2204 | ||
2204 | static void *locks_next(struct seq_file *f, void *v, loff_t *pos) | 2205 | static void *locks_next(struct seq_file *f, void *v, loff_t *pos) |
2205 | { | 2206 | { |
2207 | loff_t *p = f->private; | ||
2208 | ++*p; | ||
2206 | return seq_list_next(v, &file_lock_list, pos); | 2209 | return seq_list_next(v, &file_lock_list, pos); |
2207 | } | 2210 | } |
2208 | 2211 | ||
@@ -2220,14 +2223,14 @@ static const struct seq_operations locks_seq_operations = { | |||
2220 | 2223 | ||
2221 | static int locks_open(struct inode *inode, struct file *filp) | 2224 | static int locks_open(struct inode *inode, struct file *filp) |
2222 | { | 2225 | { |
2223 | return seq_open(filp, &locks_seq_operations); | 2226 | return seq_open_private(filp, &locks_seq_operations, sizeof(loff_t)); |
2224 | } | 2227 | } |
2225 | 2228 | ||
2226 | static const struct file_operations proc_locks_operations = { | 2229 | static const struct file_operations proc_locks_operations = { |
2227 | .open = locks_open, | 2230 | .open = locks_open, |
2228 | .read = seq_read, | 2231 | .read = seq_read, |
2229 | .llseek = seq_lseek, | 2232 | .llseek = seq_lseek, |
2230 | .release = seq_release, | 2233 | .release = seq_release_private, |
2231 | }; | 2234 | }; |
2232 | 2235 | ||
2233 | static int __init proc_locks_init(void) | 2236 | static int __init proc_locks_init(void) |
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 605e292501f4..4c14c17a5276 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
@@ -290,9 +290,7 @@ static int nfs_do_writepage(struct page *page, struct writeback_control *wbc, st | |||
290 | nfs_add_stats(inode, NFSIOS_WRITEPAGES, 1); | 290 | nfs_add_stats(inode, NFSIOS_WRITEPAGES, 1); |
291 | 291 | ||
292 | nfs_pageio_cond_complete(pgio, page->index); | 292 | nfs_pageio_cond_complete(pgio, page->index); |
293 | ret = nfs_page_async_flush(pgio, page, | 293 | ret = nfs_page_async_flush(pgio, page, wbc->sync_mode == WB_SYNC_NONE); |
294 | wbc->sync_mode == WB_SYNC_NONE || | ||
295 | wbc->nonblocking != 0); | ||
296 | if (ret == -EAGAIN) { | 294 | if (ret == -EAGAIN) { |
297 | redirty_page_for_writepage(wbc, page); | 295 | redirty_page_for_writepage(wbc, page); |
298 | ret = 0; | 296 | ret = 0; |
diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c index d926af626177..687d090cea34 100644 --- a/fs/nilfs2/segment.c +++ b/fs/nilfs2/segment.c | |||
@@ -1609,7 +1609,7 @@ nilfs_copy_replace_page_buffers(struct page *page, struct list_head *out) | |||
1609 | kunmap_atomic(kaddr, KM_USER0); | 1609 | kunmap_atomic(kaddr, KM_USER0); |
1610 | 1610 | ||
1611 | if (!TestSetPageWriteback(clone_page)) | 1611 | if (!TestSetPageWriteback(clone_page)) |
1612 | inc_zone_page_state(clone_page, NR_WRITEBACK); | 1612 | account_page_writeback(clone_page); |
1613 | unlock_page(clone_page); | 1613 | unlock_page(clone_page); |
1614 | 1614 | ||
1615 | return 0; | 1615 | return 0; |
diff --git a/fs/proc/Kconfig b/fs/proc/Kconfig index 50f8f0600f06..6a0068841d96 100644 --- a/fs/proc/Kconfig +++ b/fs/proc/Kconfig | |||
@@ -33,8 +33,8 @@ config PROC_KCORE | |||
33 | depends on PROC_FS && MMU | 33 | depends on PROC_FS && MMU |
34 | 34 | ||
35 | config PROC_VMCORE | 35 | config PROC_VMCORE |
36 | bool "/proc/vmcore support (EXPERIMENTAL)" | 36 | bool "/proc/vmcore support" |
37 | depends on PROC_FS && CRASH_DUMP | 37 | depends on PROC_FS && CRASH_DUMP |
38 | default y | 38 | default y |
39 | help | 39 | help |
40 | Exports the dump image of crashed kernel in ELF format. | 40 | Exports the dump image of crashed kernel in ELF format. |
diff --git a/fs/proc/base.c b/fs/proc/base.c index dc5d5f51f3fe..53dc8ad40ae6 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
@@ -1023,28 +1023,47 @@ static ssize_t oom_adjust_write(struct file *file, const char __user *buf, | |||
1023 | memset(buffer, 0, sizeof(buffer)); | 1023 | memset(buffer, 0, sizeof(buffer)); |
1024 | if (count > sizeof(buffer) - 1) | 1024 | if (count > sizeof(buffer) - 1) |
1025 | count = sizeof(buffer) - 1; | 1025 | count = sizeof(buffer) - 1; |
1026 | if (copy_from_user(buffer, buf, count)) | 1026 | if (copy_from_user(buffer, buf, count)) { |
1027 | return -EFAULT; | 1027 | err = -EFAULT; |
1028 | goto out; | ||
1029 | } | ||
1028 | 1030 | ||
1029 | err = strict_strtol(strstrip(buffer), 0, &oom_adjust); | 1031 | err = strict_strtol(strstrip(buffer), 0, &oom_adjust); |
1030 | if (err) | 1032 | if (err) |
1031 | return -EINVAL; | 1033 | goto out; |
1032 | if ((oom_adjust < OOM_ADJUST_MIN || oom_adjust > OOM_ADJUST_MAX) && | 1034 | if ((oom_adjust < OOM_ADJUST_MIN || oom_adjust > OOM_ADJUST_MAX) && |
1033 | oom_adjust != OOM_DISABLE) | 1035 | oom_adjust != OOM_DISABLE) { |
1034 | return -EINVAL; | 1036 | err = -EINVAL; |
1037 | goto out; | ||
1038 | } | ||
1035 | 1039 | ||
1036 | task = get_proc_task(file->f_path.dentry->d_inode); | 1040 | task = get_proc_task(file->f_path.dentry->d_inode); |
1037 | if (!task) | 1041 | if (!task) { |
1038 | return -ESRCH; | 1042 | err = -ESRCH; |
1043 | goto out; | ||
1044 | } | ||
1045 | |||
1046 | task_lock(task); | ||
1047 | if (!task->mm) { | ||
1048 | err = -EINVAL; | ||
1049 | goto err_task_lock; | ||
1050 | } | ||
1051 | |||
1039 | if (!lock_task_sighand(task, &flags)) { | 1052 | if (!lock_task_sighand(task, &flags)) { |
1040 | put_task_struct(task); | 1053 | err = -ESRCH; |
1041 | return -ESRCH; | 1054 | goto err_task_lock; |
1042 | } | 1055 | } |
1043 | 1056 | ||
1044 | if (oom_adjust < task->signal->oom_adj && !capable(CAP_SYS_RESOURCE)) { | 1057 | if (oom_adjust < task->signal->oom_adj && !capable(CAP_SYS_RESOURCE)) { |
1045 | unlock_task_sighand(task, &flags); | 1058 | err = -EACCES; |
1046 | put_task_struct(task); | 1059 | goto err_sighand; |
1047 | return -EACCES; | 1060 | } |
1061 | |||
1062 | if (oom_adjust != task->signal->oom_adj) { | ||
1063 | if (oom_adjust == OOM_DISABLE) | ||
1064 | atomic_inc(&task->mm->oom_disable_count); | ||
1065 | if (task->signal->oom_adj == OOM_DISABLE) | ||
1066 | atomic_dec(&task->mm->oom_disable_count); | ||
1048 | } | 1067 | } |
1049 | 1068 | ||
1050 | /* | 1069 | /* |
@@ -1065,10 +1084,13 @@ static ssize_t oom_adjust_write(struct file *file, const char __user *buf, | |||
1065 | else | 1084 | else |
1066 | task->signal->oom_score_adj = (oom_adjust * OOM_SCORE_ADJ_MAX) / | 1085 | task->signal->oom_score_adj = (oom_adjust * OOM_SCORE_ADJ_MAX) / |
1067 | -OOM_DISABLE; | 1086 | -OOM_DISABLE; |
1087 | err_sighand: | ||
1068 | unlock_task_sighand(task, &flags); | 1088 | unlock_task_sighand(task, &flags); |
1089 | err_task_lock: | ||
1090 | task_unlock(task); | ||
1069 | put_task_struct(task); | 1091 | put_task_struct(task); |
1070 | 1092 | out: | |
1071 | return count; | 1093 | return err < 0 ? err : count; |
1072 | } | 1094 | } |
1073 | 1095 | ||
1074 | static const struct file_operations proc_oom_adjust_operations = { | 1096 | static const struct file_operations proc_oom_adjust_operations = { |
@@ -1109,30 +1131,49 @@ static ssize_t oom_score_adj_write(struct file *file, const char __user *buf, | |||
1109 | memset(buffer, 0, sizeof(buffer)); | 1131 | memset(buffer, 0, sizeof(buffer)); |
1110 | if (count > sizeof(buffer) - 1) | 1132 | if (count > sizeof(buffer) - 1) |
1111 | count = sizeof(buffer) - 1; | 1133 | count = sizeof(buffer) - 1; |
1112 | if (copy_from_user(buffer, buf, count)) | 1134 | if (copy_from_user(buffer, buf, count)) { |
1113 | return -EFAULT; | 1135 | err = -EFAULT; |
1136 | goto out; | ||
1137 | } | ||
1114 | 1138 | ||
1115 | err = strict_strtol(strstrip(buffer), 0, &oom_score_adj); | 1139 | err = strict_strtol(strstrip(buffer), 0, &oom_score_adj); |
1116 | if (err) | 1140 | if (err) |
1117 | return -EINVAL; | 1141 | goto out; |
1118 | if (oom_score_adj < OOM_SCORE_ADJ_MIN || | 1142 | if (oom_score_adj < OOM_SCORE_ADJ_MIN || |
1119 | oom_score_adj > OOM_SCORE_ADJ_MAX) | 1143 | oom_score_adj > OOM_SCORE_ADJ_MAX) { |
1120 | return -EINVAL; | 1144 | err = -EINVAL; |
1145 | goto out; | ||
1146 | } | ||
1121 | 1147 | ||
1122 | task = get_proc_task(file->f_path.dentry->d_inode); | 1148 | task = get_proc_task(file->f_path.dentry->d_inode); |
1123 | if (!task) | 1149 | if (!task) { |
1124 | return -ESRCH; | 1150 | err = -ESRCH; |
1151 | goto out; | ||
1152 | } | ||
1153 | |||
1154 | task_lock(task); | ||
1155 | if (!task->mm) { | ||
1156 | err = -EINVAL; | ||
1157 | goto err_task_lock; | ||
1158 | } | ||
1159 | |||
1125 | if (!lock_task_sighand(task, &flags)) { | 1160 | if (!lock_task_sighand(task, &flags)) { |
1126 | put_task_struct(task); | 1161 | err = -ESRCH; |
1127 | return -ESRCH; | 1162 | goto err_task_lock; |
1128 | } | 1163 | } |
1164 | |||
1129 | if (oom_score_adj < task->signal->oom_score_adj && | 1165 | if (oom_score_adj < task->signal->oom_score_adj && |
1130 | !capable(CAP_SYS_RESOURCE)) { | 1166 | !capable(CAP_SYS_RESOURCE)) { |
1131 | unlock_task_sighand(task, &flags); | 1167 | err = -EACCES; |
1132 | put_task_struct(task); | 1168 | goto err_sighand; |
1133 | return -EACCES; | ||
1134 | } | 1169 | } |
1135 | 1170 | ||
1171 | if (oom_score_adj != task->signal->oom_score_adj) { | ||
1172 | if (oom_score_adj == OOM_SCORE_ADJ_MIN) | ||
1173 | atomic_inc(&task->mm->oom_disable_count); | ||
1174 | if (task->signal->oom_score_adj == OOM_SCORE_ADJ_MIN) | ||
1175 | atomic_dec(&task->mm->oom_disable_count); | ||
1176 | } | ||
1136 | task->signal->oom_score_adj = oom_score_adj; | 1177 | task->signal->oom_score_adj = oom_score_adj; |
1137 | /* | 1178 | /* |
1138 | * Scale /proc/pid/oom_adj appropriately ensuring that OOM_DISABLE is | 1179 | * Scale /proc/pid/oom_adj appropriately ensuring that OOM_DISABLE is |
@@ -1143,9 +1184,13 @@ static ssize_t oom_score_adj_write(struct file *file, const char __user *buf, | |||
1143 | else | 1184 | else |
1144 | task->signal->oom_adj = (oom_score_adj * OOM_ADJUST_MAX) / | 1185 | task->signal->oom_adj = (oom_score_adj * OOM_ADJUST_MAX) / |
1145 | OOM_SCORE_ADJ_MAX; | 1186 | OOM_SCORE_ADJ_MAX; |
1187 | err_sighand: | ||
1146 | unlock_task_sighand(task, &flags); | 1188 | unlock_task_sighand(task, &flags); |
1189 | err_task_lock: | ||
1190 | task_unlock(task); | ||
1147 | put_task_struct(task); | 1191 | put_task_struct(task); |
1148 | return count; | 1192 | out: |
1193 | return err < 0 ? err : count; | ||
1149 | } | 1194 | } |
1150 | 1195 | ||
1151 | static const struct file_operations proc_oom_score_adj_operations = { | 1196 | static const struct file_operations proc_oom_score_adj_operations = { |
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c index caa758377d66..c1f93896cb53 100644 --- a/fs/reiserfs/inode.c +++ b/fs/reiserfs/inode.c | |||
@@ -2438,7 +2438,7 @@ static int reiserfs_write_full_page(struct page *page, | |||
2438 | /* from this point on, we know the buffer is mapped to a | 2438 | /* from this point on, we know the buffer is mapped to a |
2439 | * real block and not a direct item | 2439 | * real block and not a direct item |
2440 | */ | 2440 | */ |
2441 | if (wbc->sync_mode != WB_SYNC_NONE || !wbc->nonblocking) { | 2441 | if (wbc->sync_mode != WB_SYNC_NONE) { |
2442 | lock_buffer(bh); | 2442 | lock_buffer(bh); |
2443 | } else { | 2443 | } else { |
2444 | if (!trylock_buffer(bh)) { | 2444 | if (!trylock_buffer(bh)) { |
diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c index b552f816de15..c9af48fffcd7 100644 --- a/fs/xfs/linux-2.6/xfs_aops.c +++ b/fs/xfs/linux-2.6/xfs_aops.c | |||
@@ -1139,8 +1139,7 @@ xfs_vm_writepage( | |||
1139 | type = IO_DELAY; | 1139 | type = IO_DELAY; |
1140 | flags = BMAPI_ALLOCATE; | 1140 | flags = BMAPI_ALLOCATE; |
1141 | 1141 | ||
1142 | if (wbc->sync_mode == WB_SYNC_NONE && | 1142 | if (wbc->sync_mode == WB_SYNC_NONE) |
1143 | wbc->nonblocking) | ||
1144 | flags |= BMAPI_TRYLOCK; | 1143 | flags |= BMAPI_TRYLOCK; |
1145 | } | 1144 | } |
1146 | 1145 | ||
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index f4229fb315e1..2c0fc10956ba 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h | |||
@@ -150,6 +150,7 @@ | |||
150 | #define DATA_DATA \ | 150 | #define DATA_DATA \ |
151 | *(.data) \ | 151 | *(.data) \ |
152 | *(.ref.data) \ | 152 | *(.ref.data) \ |
153 | *(.data..shared_aligned) /* percpu related */ \ | ||
153 | DEV_KEEP(init.data) \ | 154 | DEV_KEEP(init.data) \ |
154 | DEV_KEEP(exit.data) \ | 155 | DEV_KEEP(exit.data) \ |
155 | CPU_KEEP(init.data) \ | 156 | CPU_KEEP(init.data) \ |
@@ -636,7 +637,7 @@ | |||
636 | 637 | ||
637 | #ifdef CONFIG_BLK_DEV_INITRD | 638 | #ifdef CONFIG_BLK_DEV_INITRD |
638 | #define INIT_RAM_FS \ | 639 | #define INIT_RAM_FS \ |
639 | . = ALIGN(PAGE_SIZE); \ | 640 | . = ALIGN(4); \ |
640 | VMLINUX_SYMBOL(__initramfs_start) = .; \ | 641 | VMLINUX_SYMBOL(__initramfs_start) = .; \ |
641 | *(.init.ramfs) \ | 642 | *(.init.ramfs) \ |
642 | VMLINUX_SYMBOL(__initramfs_end) = .; | 643 | VMLINUX_SYMBOL(__initramfs_end) = .; |
diff --git a/include/linux/backing-dev.h b/include/linux/backing-dev.h index 35b00746c712..4ce34fa937d4 100644 --- a/include/linux/backing-dev.h +++ b/include/linux/backing-dev.h | |||
@@ -111,6 +111,7 @@ void bdi_wakeup_thread_delayed(struct backing_dev_info *bdi); | |||
111 | 111 | ||
112 | extern spinlock_t bdi_lock; | 112 | extern spinlock_t bdi_lock; |
113 | extern struct list_head bdi_list; | 113 | extern struct list_head bdi_list; |
114 | extern struct list_head bdi_pending_list; | ||
114 | 115 | ||
115 | static inline int wb_has_dirty_io(struct bdi_writeback *wb) | 116 | static inline int wb_has_dirty_io(struct bdi_writeback *wb) |
116 | { | 117 | { |
@@ -285,7 +286,7 @@ enum { | |||
285 | void clear_bdi_congested(struct backing_dev_info *bdi, int sync); | 286 | void clear_bdi_congested(struct backing_dev_info *bdi, int sync); |
286 | void set_bdi_congested(struct backing_dev_info *bdi, int sync); | 287 | void set_bdi_congested(struct backing_dev_info *bdi, int sync); |
287 | long congestion_wait(int sync, long timeout); | 288 | long congestion_wait(int sync, long timeout); |
288 | 289 | long wait_iff_congested(struct zone *zone, int sync, long timeout); | |
289 | 290 | ||
290 | static inline bool bdi_cap_writeback_dirty(struct backing_dev_info *bdi) | 291 | static inline bool bdi_cap_writeback_dirty(struct backing_dev_info *bdi) |
291 | { | 292 | { |
diff --git a/include/linux/fs.h b/include/linux/fs.h index bb20373d0b46..4658777b41cc 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
@@ -34,9 +34,9 @@ | |||
34 | 34 | ||
35 | /* And dynamically-tunable limits and defaults: */ | 35 | /* And dynamically-tunable limits and defaults: */ |
36 | struct files_stat_struct { | 36 | struct files_stat_struct { |
37 | int nr_files; /* read only */ | 37 | unsigned long nr_files; /* read only */ |
38 | int nr_free_files; /* read only */ | 38 | unsigned long nr_free_files; /* read only */ |
39 | int max_files; /* tunable */ | 39 | unsigned long max_files; /* tunable */ |
40 | }; | 40 | }; |
41 | 41 | ||
42 | struct inodes_stat_t { | 42 | struct inodes_stat_t { |
@@ -402,7 +402,7 @@ extern void __init inode_init_early(void); | |||
402 | extern void __init files_init(unsigned long); | 402 | extern void __init files_init(unsigned long); |
403 | 403 | ||
404 | extern struct files_stat_struct files_stat; | 404 | extern struct files_stat_struct files_stat; |
405 | extern int get_max_files(void); | 405 | extern unsigned long get_max_files(void); |
406 | extern int sysctl_nr_open; | 406 | extern int sysctl_nr_open; |
407 | extern struct inodes_stat_t inodes_stat; | 407 | extern struct inodes_stat_t inodes_stat; |
408 | extern int leases_enable, lease_break_time; | 408 | extern int leases_enable, lease_break_time; |
diff --git a/include/linux/gfp.h b/include/linux/gfp.h index 975609cb8548..e8713d55360a 100644 --- a/include/linux/gfp.h +++ b/include/linux/gfp.h | |||
@@ -9,6 +9,32 @@ | |||
9 | 9 | ||
10 | struct vm_area_struct; | 10 | struct vm_area_struct; |
11 | 11 | ||
12 | /* Plain integer GFP bitmasks. Do not use this directly. */ | ||
13 | #define ___GFP_DMA 0x01u | ||
14 | #define ___GFP_HIGHMEM 0x02u | ||
15 | #define ___GFP_DMA32 0x04u | ||
16 | #define ___GFP_MOVABLE 0x08u | ||
17 | #define ___GFP_WAIT 0x10u | ||
18 | #define ___GFP_HIGH 0x20u | ||
19 | #define ___GFP_IO 0x40u | ||
20 | #define ___GFP_FS 0x80u | ||
21 | #define ___GFP_COLD 0x100u | ||
22 | #define ___GFP_NOWARN 0x200u | ||
23 | #define ___GFP_REPEAT 0x400u | ||
24 | #define ___GFP_NOFAIL 0x800u | ||
25 | #define ___GFP_NORETRY 0x1000u | ||
26 | #define ___GFP_COMP 0x4000u | ||
27 | #define ___GFP_ZERO 0x8000u | ||
28 | #define ___GFP_NOMEMALLOC 0x10000u | ||
29 | #define ___GFP_HARDWALL 0x20000u | ||
30 | #define ___GFP_THISNODE 0x40000u | ||
31 | #define ___GFP_RECLAIMABLE 0x80000u | ||
32 | #ifdef CONFIG_KMEMCHECK | ||
33 | #define ___GFP_NOTRACK 0x200000u | ||
34 | #else | ||
35 | #define ___GFP_NOTRACK 0 | ||
36 | #endif | ||
37 | |||
12 | /* | 38 | /* |
13 | * GFP bitmasks.. | 39 | * GFP bitmasks.. |
14 | * | 40 | * |
@@ -18,10 +44,10 @@ struct vm_area_struct; | |||
18 | * without the underscores and use them consistently. The definitions here may | 44 | * without the underscores and use them consistently. The definitions here may |
19 | * be used in bit comparisons. | 45 | * be used in bit comparisons. |
20 | */ | 46 | */ |
21 | #define __GFP_DMA ((__force gfp_t)0x01u) | 47 | #define __GFP_DMA ((__force gfp_t)___GFP_DMA) |
22 | #define __GFP_HIGHMEM ((__force gfp_t)0x02u) | 48 | #define __GFP_HIGHMEM ((__force gfp_t)___GFP_HIGHMEM) |
23 | #define __GFP_DMA32 ((__force gfp_t)0x04u) | 49 | #define __GFP_DMA32 ((__force gfp_t)___GFP_DMA32) |
24 | #define __GFP_MOVABLE ((__force gfp_t)0x08u) /* Page is movable */ | 50 | #define __GFP_MOVABLE ((__force gfp_t)___GFP_MOVABLE) /* Page is movable */ |
25 | #define GFP_ZONEMASK (__GFP_DMA|__GFP_HIGHMEM|__GFP_DMA32|__GFP_MOVABLE) | 51 | #define GFP_ZONEMASK (__GFP_DMA|__GFP_HIGHMEM|__GFP_DMA32|__GFP_MOVABLE) |
26 | /* | 52 | /* |
27 | * Action modifiers - doesn't change the zoning | 53 | * Action modifiers - doesn't change the zoning |
@@ -38,27 +64,22 @@ struct vm_area_struct; | |||
38 | * __GFP_MOVABLE: Flag that this page will be movable by the page migration | 64 | * __GFP_MOVABLE: Flag that this page will be movable by the page migration |
39 | * mechanism or reclaimed | 65 | * mechanism or reclaimed |
40 | */ | 66 | */ |
41 | #define __GFP_WAIT ((__force gfp_t)0x10u) /* Can wait and reschedule? */ | 67 | #define __GFP_WAIT ((__force gfp_t)___GFP_WAIT) /* Can wait and reschedule? */ |
42 | #define __GFP_HIGH ((__force gfp_t)0x20u) /* Should access emergency pools? */ | 68 | #define __GFP_HIGH ((__force gfp_t)___GFP_HIGH) /* Should access emergency pools? */ |
43 | #define __GFP_IO ((__force gfp_t)0x40u) /* Can start physical IO? */ | 69 | #define __GFP_IO ((__force gfp_t)___GFP_IO) /* Can start physical IO? */ |
44 | #define __GFP_FS ((__force gfp_t)0x80u) /* Can call down to low-level FS? */ | 70 | #define __GFP_FS ((__force gfp_t)___GFP_FS) /* Can call down to low-level FS? */ |
45 | #define __GFP_COLD ((__force gfp_t)0x100u) /* Cache-cold page required */ | 71 | #define __GFP_COLD ((__force gfp_t)___GFP_COLD) /* Cache-cold page required */ |
46 | #define __GFP_NOWARN ((__force gfp_t)0x200u) /* Suppress page allocation failure warning */ | 72 | #define __GFP_NOWARN ((__force gfp_t)___GFP_NOWARN) /* Suppress page allocation failure warning */ |
47 | #define __GFP_REPEAT ((__force gfp_t)0x400u) /* See above */ | 73 | #define __GFP_REPEAT ((__force gfp_t)___GFP_REPEAT) /* See above */ |
48 | #define __GFP_NOFAIL ((__force gfp_t)0x800u) /* See above */ | 74 | #define __GFP_NOFAIL ((__force gfp_t)___GFP_NOFAIL) /* See above */ |
49 | #define __GFP_NORETRY ((__force gfp_t)0x1000u)/* See above */ | 75 | #define __GFP_NORETRY ((__force gfp_t)___GFP_NORETRY) /* See above */ |
50 | #define __GFP_COMP ((__force gfp_t)0x4000u)/* Add compound page metadata */ | 76 | #define __GFP_COMP ((__force gfp_t)___GFP_COMP) /* Add compound page metadata */ |
51 | #define __GFP_ZERO ((__force gfp_t)0x8000u)/* Return zeroed page on success */ | 77 | #define __GFP_ZERO ((__force gfp_t)___GFP_ZERO) /* Return zeroed page on success */ |
52 | #define __GFP_NOMEMALLOC ((__force gfp_t)0x10000u) /* Don't use emergency reserves */ | 78 | #define __GFP_NOMEMALLOC ((__force gfp_t)___GFP_NOMEMALLOC) /* Don't use emergency reserves */ |
53 | #define __GFP_HARDWALL ((__force gfp_t)0x20000u) /* Enforce hardwall cpuset memory allocs */ | 79 | #define __GFP_HARDWALL ((__force gfp_t)___GFP_HARDWALL) /* Enforce hardwall cpuset memory allocs */ |
54 | #define __GFP_THISNODE ((__force gfp_t)0x40000u)/* No fallback, no policies */ | 80 | #define __GFP_THISNODE ((__force gfp_t)___GFP_THISNODE)/* No fallback, no policies */ |
55 | #define __GFP_RECLAIMABLE ((__force gfp_t)0x80000u) /* Page is reclaimable */ | 81 | #define __GFP_RECLAIMABLE ((__force gfp_t)___GFP_RECLAIMABLE) /* Page is reclaimable */ |
56 | 82 | #define __GFP_NOTRACK ((__force gfp_t)___GFP_NOTRACK) /* Don't track with kmemcheck */ | |
57 | #ifdef CONFIG_KMEMCHECK | ||
58 | #define __GFP_NOTRACK ((__force gfp_t)0x200000u) /* Don't track with kmemcheck */ | ||
59 | #else | ||
60 | #define __GFP_NOTRACK ((__force gfp_t)0) | ||
61 | #endif | ||
62 | 83 | ||
63 | /* | 84 | /* |
64 | * This may seem redundant, but it's a way of annotating false positives vs. | 85 | * This may seem redundant, but it's a way of annotating false positives vs. |
@@ -186,14 +207,14 @@ static inline int allocflags_to_migratetype(gfp_t gfp_flags) | |||
186 | #endif | 207 | #endif |
187 | 208 | ||
188 | #define GFP_ZONE_TABLE ( \ | 209 | #define GFP_ZONE_TABLE ( \ |
189 | (ZONE_NORMAL << 0 * ZONES_SHIFT) \ | 210 | (ZONE_NORMAL << 0 * ZONES_SHIFT) \ |
190 | | (OPT_ZONE_DMA << __GFP_DMA * ZONES_SHIFT) \ | 211 | | (OPT_ZONE_DMA << ___GFP_DMA * ZONES_SHIFT) \ |
191 | | (OPT_ZONE_HIGHMEM << __GFP_HIGHMEM * ZONES_SHIFT) \ | 212 | | (OPT_ZONE_HIGHMEM << ___GFP_HIGHMEM * ZONES_SHIFT) \ |
192 | | (OPT_ZONE_DMA32 << __GFP_DMA32 * ZONES_SHIFT) \ | 213 | | (OPT_ZONE_DMA32 << ___GFP_DMA32 * ZONES_SHIFT) \ |
193 | | (ZONE_NORMAL << __GFP_MOVABLE * ZONES_SHIFT) \ | 214 | | (ZONE_NORMAL << ___GFP_MOVABLE * ZONES_SHIFT) \ |
194 | | (OPT_ZONE_DMA << (__GFP_MOVABLE | __GFP_DMA) * ZONES_SHIFT) \ | 215 | | (OPT_ZONE_DMA << (___GFP_MOVABLE | ___GFP_DMA) * ZONES_SHIFT) \ |
195 | | (ZONE_MOVABLE << (__GFP_MOVABLE | __GFP_HIGHMEM) * ZONES_SHIFT)\ | 216 | | (ZONE_MOVABLE << (___GFP_MOVABLE | ___GFP_HIGHMEM) * ZONES_SHIFT) \ |
196 | | (OPT_ZONE_DMA32 << (__GFP_MOVABLE | __GFP_DMA32) * ZONES_SHIFT)\ | 217 | | (OPT_ZONE_DMA32 << (___GFP_MOVABLE | ___GFP_DMA32) * ZONES_SHIFT) \ |
197 | ) | 218 | ) |
198 | 219 | ||
199 | /* | 220 | /* |
@@ -203,20 +224,20 @@ static inline int allocflags_to_migratetype(gfp_t gfp_flags) | |||
203 | * allowed. | 224 | * allowed. |
204 | */ | 225 | */ |
205 | #define GFP_ZONE_BAD ( \ | 226 | #define GFP_ZONE_BAD ( \ |
206 | 1 << (__GFP_DMA | __GFP_HIGHMEM) \ | 227 | 1 << (___GFP_DMA | ___GFP_HIGHMEM) \ |
207 | | 1 << (__GFP_DMA | __GFP_DMA32) \ | 228 | | 1 << (___GFP_DMA | ___GFP_DMA32) \ |
208 | | 1 << (__GFP_DMA32 | __GFP_HIGHMEM) \ | 229 | | 1 << (___GFP_DMA32 | ___GFP_HIGHMEM) \ |
209 | | 1 << (__GFP_DMA | __GFP_DMA32 | __GFP_HIGHMEM) \ | 230 | | 1 << (___GFP_DMA | ___GFP_DMA32 | ___GFP_HIGHMEM) \ |
210 | | 1 << (__GFP_MOVABLE | __GFP_HIGHMEM | __GFP_DMA) \ | 231 | | 1 << (___GFP_MOVABLE | ___GFP_HIGHMEM | ___GFP_DMA) \ |
211 | | 1 << (__GFP_MOVABLE | __GFP_DMA32 | __GFP_DMA) \ | 232 | | 1 << (___GFP_MOVABLE | ___GFP_DMA32 | ___GFP_DMA) \ |
212 | | 1 << (__GFP_MOVABLE | __GFP_DMA32 | __GFP_HIGHMEM) \ | 233 | | 1 << (___GFP_MOVABLE | ___GFP_DMA32 | ___GFP_HIGHMEM) \ |
213 | | 1 << (__GFP_MOVABLE | __GFP_DMA32 | __GFP_DMA | __GFP_HIGHMEM)\ | 234 | | 1 << (___GFP_MOVABLE | ___GFP_DMA32 | ___GFP_DMA | ___GFP_HIGHMEM) \ |
214 | ) | 235 | ) |
215 | 236 | ||
216 | static inline enum zone_type gfp_zone(gfp_t flags) | 237 | static inline enum zone_type gfp_zone(gfp_t flags) |
217 | { | 238 | { |
218 | enum zone_type z; | 239 | enum zone_type z; |
219 | int bit = flags & GFP_ZONEMASK; | 240 | int bit = (__force int) (flags & GFP_ZONEMASK); |
220 | 241 | ||
221 | z = (GFP_ZONE_TABLE >> (bit * ZONES_SHIFT)) & | 242 | z = (GFP_ZONE_TABLE >> (bit * ZONES_SHIFT)) & |
222 | ((1 << ZONES_SHIFT) - 1); | 243 | ((1 << ZONES_SHIFT) - 1); |
diff --git a/include/linux/highmem.h b/include/linux/highmem.h index e3060ef85b6d..8a85ec109a3a 100644 --- a/include/linux/highmem.h +++ b/include/linux/highmem.h | |||
@@ -28,18 +28,6 @@ static inline void invalidate_kernel_vmap_range(void *vaddr, int size) | |||
28 | 28 | ||
29 | #include <asm/kmap_types.h> | 29 | #include <asm/kmap_types.h> |
30 | 30 | ||
31 | #ifdef CONFIG_DEBUG_HIGHMEM | ||
32 | |||
33 | void debug_kmap_atomic(enum km_type type); | ||
34 | |||
35 | #else | ||
36 | |||
37 | static inline void debug_kmap_atomic(enum km_type type) | ||
38 | { | ||
39 | } | ||
40 | |||
41 | #endif | ||
42 | |||
43 | #ifdef CONFIG_HIGHMEM | 31 | #ifdef CONFIG_HIGHMEM |
44 | #include <asm/highmem.h> | 32 | #include <asm/highmem.h> |
45 | 33 | ||
@@ -49,6 +37,27 @@ extern unsigned long totalhigh_pages; | |||
49 | 37 | ||
50 | void kmap_flush_unused(void); | 38 | void kmap_flush_unused(void); |
51 | 39 | ||
40 | DECLARE_PER_CPU(int, __kmap_atomic_idx); | ||
41 | |||
42 | static inline int kmap_atomic_idx_push(void) | ||
43 | { | ||
44 | int idx = __get_cpu_var(__kmap_atomic_idx)++; | ||
45 | #ifdef CONFIG_DEBUG_HIGHMEM | ||
46 | WARN_ON_ONCE(in_irq() && !irqs_disabled()); | ||
47 | BUG_ON(idx > KM_TYPE_NR); | ||
48 | #endif | ||
49 | return idx; | ||
50 | } | ||
51 | |||
52 | static inline int kmap_atomic_idx_pop(void) | ||
53 | { | ||
54 | int idx = --__get_cpu_var(__kmap_atomic_idx); | ||
55 | #ifdef CONFIG_DEBUG_HIGHMEM | ||
56 | BUG_ON(idx < 0); | ||
57 | #endif | ||
58 | return idx; | ||
59 | } | ||
60 | |||
52 | #else /* CONFIG_HIGHMEM */ | 61 | #else /* CONFIG_HIGHMEM */ |
53 | 62 | ||
54 | static inline unsigned int nr_free_highpages(void) { return 0; } | 63 | static inline unsigned int nr_free_highpages(void) { return 0; } |
@@ -66,19 +75,19 @@ static inline void kunmap(struct page *page) | |||
66 | { | 75 | { |
67 | } | 76 | } |
68 | 77 | ||
69 | static inline void *kmap_atomic(struct page *page, enum km_type idx) | 78 | static inline void *__kmap_atomic(struct page *page) |
70 | { | 79 | { |
71 | pagefault_disable(); | 80 | pagefault_disable(); |
72 | return page_address(page); | 81 | return page_address(page); |
73 | } | 82 | } |
74 | #define kmap_atomic_prot(page, idx, prot) kmap_atomic(page, idx) | 83 | #define kmap_atomic_prot(page, prot) __kmap_atomic(page) |
75 | 84 | ||
76 | static inline void kunmap_atomic_notypecheck(void *addr, enum km_type idx) | 85 | static inline void __kunmap_atomic(void *addr) |
77 | { | 86 | { |
78 | pagefault_enable(); | 87 | pagefault_enable(); |
79 | } | 88 | } |
80 | 89 | ||
81 | #define kmap_atomic_pfn(pfn, idx) kmap_atomic(pfn_to_page(pfn), (idx)) | 90 | #define kmap_atomic_pfn(pfn) kmap_atomic(pfn_to_page(pfn)) |
82 | #define kmap_atomic_to_page(ptr) virt_to_page(ptr) | 91 | #define kmap_atomic_to_page(ptr) virt_to_page(ptr) |
83 | 92 | ||
84 | #define kmap_flush_unused() do {} while(0) | 93 | #define kmap_flush_unused() do {} while(0) |
@@ -86,12 +95,20 @@ static inline void kunmap_atomic_notypecheck(void *addr, enum km_type idx) | |||
86 | 95 | ||
87 | #endif /* CONFIG_HIGHMEM */ | 96 | #endif /* CONFIG_HIGHMEM */ |
88 | 97 | ||
89 | /* Prevent people trying to call kunmap_atomic() as if it were kunmap() */ | 98 | /* |
90 | /* kunmap_atomic() should get the return value of kmap_atomic, not the page. */ | 99 | * Make both: kmap_atomic(page, idx) and kmap_atomic(page) work. |
91 | #define kunmap_atomic(addr, idx) do { \ | 100 | */ |
92 | BUILD_BUG_ON(__same_type((addr), struct page *)); \ | 101 | #define kmap_atomic(page, args...) __kmap_atomic(page) |
93 | kunmap_atomic_notypecheck((addr), (idx)); \ | 102 | |
94 | } while (0) | 103 | /* |
104 | * Prevent people trying to call kunmap_atomic() as if it were kunmap() | ||
105 | * kunmap_atomic() should get the return value of kmap_atomic, not the page. | ||
106 | */ | ||
107 | #define kunmap_atomic(addr, args...) \ | ||
108 | do { \ | ||
109 | BUILD_BUG_ON(__same_type((addr), struct page *)); \ | ||
110 | __kunmap_atomic(addr); \ | ||
111 | } while (0) | ||
95 | 112 | ||
96 | /* when CONFIG_HIGHMEM is not set these will be plain clear/copy_page */ | 113 | /* when CONFIG_HIGHMEM is not set these will be plain clear/copy_page */ |
97 | #ifndef clear_user_highpage | 114 | #ifndef clear_user_highpage |
@@ -201,8 +218,8 @@ static inline void copy_user_highpage(struct page *to, struct page *from, | |||
201 | vfrom = kmap_atomic(from, KM_USER0); | 218 | vfrom = kmap_atomic(from, KM_USER0); |
202 | vto = kmap_atomic(to, KM_USER1); | 219 | vto = kmap_atomic(to, KM_USER1); |
203 | copy_user_page(vto, vfrom, vaddr, to); | 220 | copy_user_page(vto, vfrom, vaddr, to); |
204 | kunmap_atomic(vfrom, KM_USER0); | ||
205 | kunmap_atomic(vto, KM_USER1); | 221 | kunmap_atomic(vto, KM_USER1); |
222 | kunmap_atomic(vfrom, KM_USER0); | ||
206 | } | 223 | } |
207 | 224 | ||
208 | #endif | 225 | #endif |
@@ -214,8 +231,8 @@ static inline void copy_highpage(struct page *to, struct page *from) | |||
214 | vfrom = kmap_atomic(from, KM_USER0); | 231 | vfrom = kmap_atomic(from, KM_USER0); |
215 | vto = kmap_atomic(to, KM_USER1); | 232 | vto = kmap_atomic(to, KM_USER1); |
216 | copy_page(vto, vfrom); | 233 | copy_page(vto, vfrom); |
217 | kunmap_atomic(vfrom, KM_USER0); | ||
218 | kunmap_atomic(vto, KM_USER1); | 234 | kunmap_atomic(vto, KM_USER1); |
235 | kunmap_atomic(vfrom, KM_USER0); | ||
219 | } | 236 | } |
220 | 237 | ||
221 | #endif /* _LINUX_HIGHMEM_H */ | 238 | #endif /* _LINUX_HIGHMEM_H */ |
diff --git a/include/linux/i2c/apds990x.h b/include/linux/i2c/apds990x.h new file mode 100644 index 000000000000..d186fcc5d257 --- /dev/null +++ b/include/linux/i2c/apds990x.h | |||
@@ -0,0 +1,79 @@ | |||
1 | /* | ||
2 | * This file is part of the APDS990x sensor driver. | ||
3 | * Chip is combined proximity and ambient light sensor. | ||
4 | * | ||
5 | * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). | ||
6 | * | ||
7 | * Contact: Samu Onkalo <samu.p.onkalo@nokia.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or | ||
10 | * modify it under the terms of the GNU General Public License | ||
11 | * version 2 as published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
21 | * 02110-1301 USA | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | #ifndef __APDS990X_H__ | ||
26 | #define __APDS990X_H__ | ||
27 | |||
28 | |||
29 | #define APDS_IRLED_CURR_12mA 0x3 | ||
30 | #define APDS_IRLED_CURR_25mA 0x2 | ||
31 | #define APDS_IRLED_CURR_50mA 0x1 | ||
32 | #define APDS_IRLED_CURR_100mA 0x0 | ||
33 | |||
34 | /** | ||
35 | * struct apds990x_chip_factors - defines effect of the cover window | ||
36 | * @ga: Total glass attenuation | ||
37 | * @cf1: clear channel factor 1 for raw to lux conversion | ||
38 | * @irf1: IR channel factor 1 for raw to lux conversion | ||
39 | * @cf2: clear channel factor 2 for raw to lux conversion | ||
40 | * @irf2: IR channel factor 2 for raw to lux conversion | ||
41 | * @df: device factor for conversion formulas | ||
42 | * | ||
43 | * Structure for tuning ALS calculation to match with environment. | ||
44 | * Values depend on the material above the sensor and the sensor | ||
45 | * itself. If the GA is zero, driver will use uncovered sensor default values | ||
46 | * format: decimal value * APDS_PARAM_SCALE except df which is plain integer. | ||
47 | */ | ||
48 | #define APDS_PARAM_SCALE 4096 | ||
49 | struct apds990x_chip_factors { | ||
50 | int ga; | ||
51 | int cf1; | ||
52 | int irf1; | ||
53 | int cf2; | ||
54 | int irf2; | ||
55 | int df; | ||
56 | }; | ||
57 | |||
58 | /** | ||
59 | * struct apds990x_platform_data - platform data for apsd990x.c driver | ||
60 | * @cf: chip factor data | ||
61 | * @pddrive: IR-led driving current | ||
62 | * @ppcount: number of IR pulses used for proximity estimation | ||
63 | * @setup_resources: interrupt line setup call back function | ||
64 | * @release_resources: interrupt line release call back function | ||
65 | * | ||
66 | * Proximity detection result depends heavily on correct ppcount, pdrive | ||
67 | * and cover window. | ||
68 | * | ||
69 | */ | ||
70 | |||
71 | struct apds990x_platform_data { | ||
72 | struct apds990x_chip_factors cf; | ||
73 | u8 pdrive; | ||
74 | u8 ppcount; | ||
75 | int (*setup_resources)(void); | ||
76 | int (*release_resources)(void); | ||
77 | }; | ||
78 | |||
79 | #endif | ||
diff --git a/include/linux/i2c/bh1770glc.h b/include/linux/i2c/bh1770glc.h new file mode 100644 index 000000000000..8b5e2df36c72 --- /dev/null +++ b/include/linux/i2c/bh1770glc.h | |||
@@ -0,0 +1,53 @@ | |||
1 | /* | ||
2 | * This file is part of the ROHM BH1770GLC / OSRAM SFH7770 sensor driver. | ||
3 | * Chip is combined proximity and ambient light sensor. | ||
4 | * | ||
5 | * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). | ||
6 | * | ||
7 | * Contact: Samu Onkalo <samu.p.onkalo@nokia.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or | ||
10 | * modify it under the terms of the GNU General Public License | ||
11 | * version 2 as published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
21 | * 02110-1301 USA | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | #ifndef __BH1770_H__ | ||
26 | #define __BH1770_H__ | ||
27 | |||
28 | /** | ||
29 | * struct bh1770_platform_data - platform data for bh1770glc driver | ||
30 | * @led_def_curr: IR led driving current. | ||
31 | * @glass_attenuation: Attenuation factor for covering window. | ||
32 | * @setup_resources: Call back for interrupt line setup function | ||
33 | * @release_resources: Call back for interrupte line release function | ||
34 | * | ||
35 | * Example of glass attenuation: 16384 * 385 / 100 means attenuation factor | ||
36 | * of 3.85. i.e. light_above_sensor = light_above_cover_window / 3.85 | ||
37 | */ | ||
38 | |||
39 | struct bh1770_platform_data { | ||
40 | #define BH1770_LED_5mA 0 | ||
41 | #define BH1770_LED_10mA 1 | ||
42 | #define BH1770_LED_20mA 2 | ||
43 | #define BH1770_LED_50mA 3 | ||
44 | #define BH1770_LED_100mA 4 | ||
45 | #define BH1770_LED_150mA 5 | ||
46 | #define BH1770_LED_200mA 6 | ||
47 | __u8 led_def_curr; | ||
48 | #define BH1770_NEUTRAL_GA 16384 /* 16384 / 16384 = 1 */ | ||
49 | __u32 glass_attenuation; | ||
50 | int (*setup_resources)(void); | ||
51 | int (*release_resources)(void); | ||
52 | }; | ||
53 | #endif | ||
diff --git a/include/linux/io-mapping.h b/include/linux/io-mapping.h index 7fb592793738..8cdcc2a199ad 100644 --- a/include/linux/io-mapping.h +++ b/include/linux/io-mapping.h | |||
@@ -81,8 +81,7 @@ io_mapping_free(struct io_mapping *mapping) | |||
81 | /* Atomic map/unmap */ | 81 | /* Atomic map/unmap */ |
82 | static inline void __iomem * | 82 | static inline void __iomem * |
83 | io_mapping_map_atomic_wc(struct io_mapping *mapping, | 83 | io_mapping_map_atomic_wc(struct io_mapping *mapping, |
84 | unsigned long offset, | 84 | unsigned long offset) |
85 | int slot) | ||
86 | { | 85 | { |
87 | resource_size_t phys_addr; | 86 | resource_size_t phys_addr; |
88 | unsigned long pfn; | 87 | unsigned long pfn; |
@@ -90,13 +89,13 @@ io_mapping_map_atomic_wc(struct io_mapping *mapping, | |||
90 | BUG_ON(offset >= mapping->size); | 89 | BUG_ON(offset >= mapping->size); |
91 | phys_addr = mapping->base + offset; | 90 | phys_addr = mapping->base + offset; |
92 | pfn = (unsigned long) (phys_addr >> PAGE_SHIFT); | 91 | pfn = (unsigned long) (phys_addr >> PAGE_SHIFT); |
93 | return iomap_atomic_prot_pfn(pfn, slot, mapping->prot); | 92 | return iomap_atomic_prot_pfn(pfn, mapping->prot); |
94 | } | 93 | } |
95 | 94 | ||
96 | static inline void | 95 | static inline void |
97 | io_mapping_unmap_atomic(void __iomem *vaddr, int slot) | 96 | io_mapping_unmap_atomic(void __iomem *vaddr) |
98 | { | 97 | { |
99 | iounmap_atomic(vaddr, slot); | 98 | iounmap_atomic(vaddr); |
100 | } | 99 | } |
101 | 100 | ||
102 | static inline void __iomem * | 101 | static inline void __iomem * |
@@ -137,14 +136,13 @@ io_mapping_free(struct io_mapping *mapping) | |||
137 | /* Atomic map/unmap */ | 136 | /* Atomic map/unmap */ |
138 | static inline void __iomem * | 137 | static inline void __iomem * |
139 | io_mapping_map_atomic_wc(struct io_mapping *mapping, | 138 | io_mapping_map_atomic_wc(struct io_mapping *mapping, |
140 | unsigned long offset, | 139 | unsigned long offset) |
141 | int slot) | ||
142 | { | 140 | { |
143 | return ((char __force __iomem *) mapping) + offset; | 141 | return ((char __force __iomem *) mapping) + offset; |
144 | } | 142 | } |
145 | 143 | ||
146 | static inline void | 144 | static inline void |
147 | io_mapping_unmap_atomic(void __iomem *vaddr, int slot) | 145 | io_mapping_unmap_atomic(void __iomem *vaddr) |
148 | { | 146 | { |
149 | } | 147 | } |
150 | 148 | ||
diff --git a/include/linux/kernel.h b/include/linux/kernel.h index edef168a0406..450092c1e35f 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h | |||
@@ -173,6 +173,11 @@ extern int _cond_resched(void); | |||
173 | (__x < 0) ? -__x : __x; \ | 173 | (__x < 0) ? -__x : __x; \ |
174 | }) | 174 | }) |
175 | 175 | ||
176 | #define abs64(x) ({ \ | ||
177 | s64 __x = (x); \ | ||
178 | (__x < 0) ? -__x : __x; \ | ||
179 | }) | ||
180 | |||
176 | #ifdef CONFIG_PROVE_LOCKING | 181 | #ifdef CONFIG_PROVE_LOCKING |
177 | void might_fault(void); | 182 | void might_fault(void); |
178 | #else | 183 | #else |
@@ -203,10 +208,10 @@ extern unsigned long simple_strtoul(const char *,char **,unsigned int); | |||
203 | extern long simple_strtol(const char *,char **,unsigned int); | 208 | extern long simple_strtol(const char *,char **,unsigned int); |
204 | extern unsigned long long simple_strtoull(const char *,char **,unsigned int); | 209 | extern unsigned long long simple_strtoull(const char *,char **,unsigned int); |
205 | extern long long simple_strtoll(const char *,char **,unsigned int); | 210 | extern long long simple_strtoll(const char *,char **,unsigned int); |
206 | extern int strict_strtoul(const char *, unsigned int, unsigned long *); | 211 | extern int __must_check strict_strtoul(const char *, unsigned int, unsigned long *); |
207 | extern int strict_strtol(const char *, unsigned int, long *); | 212 | extern int __must_check strict_strtol(const char *, unsigned int, long *); |
208 | extern int strict_strtoull(const char *, unsigned int, unsigned long long *); | 213 | extern int __must_check strict_strtoull(const char *, unsigned int, unsigned long long *); |
209 | extern int strict_strtoll(const char *, unsigned int, long long *); | 214 | extern int __must_check strict_strtoll(const char *, unsigned int, long long *); |
210 | extern int sprintf(char * buf, const char * fmt, ...) | 215 | extern int sprintf(char * buf, const char * fmt, ...) |
211 | __attribute__ ((format (printf, 2, 3))); | 216 | __attribute__ ((format (printf, 2, 3))); |
212 | extern int vsprintf(char *buf, const char *, va_list) | 217 | extern int vsprintf(char *buf, const char *, va_list) |
@@ -277,6 +282,11 @@ asmlinkage int vprintk(const char *fmt, va_list args) | |||
277 | asmlinkage int printk(const char * fmt, ...) | 282 | asmlinkage int printk(const char * fmt, ...) |
278 | __attribute__ ((format (printf, 1, 2))) __cold; | 283 | __attribute__ ((format (printf, 1, 2))) __cold; |
279 | 284 | ||
285 | /* | ||
286 | * Please don't use printk_ratelimit(), because it shares ratelimiting state | ||
287 | * with all other unrelated printk_ratelimit() callsites. Instead use | ||
288 | * printk_ratelimited() or plain old __ratelimit(). | ||
289 | */ | ||
280 | extern int __printk_ratelimit(const char *func); | 290 | extern int __printk_ratelimit(const char *func); |
281 | #define printk_ratelimit() __printk_ratelimit(__func__) | 291 | #define printk_ratelimit() __printk_ratelimit(__func__) |
282 | extern bool printk_timed_ratelimit(unsigned long *caller_jiffies, | 292 | extern bool printk_timed_ratelimit(unsigned long *caller_jiffies, |
@@ -651,6 +661,24 @@ static inline void ftrace_dump(enum ftrace_dump_mode oops_dump_mode) { } | |||
651 | (void) (&_max1 == &_max2); \ | 661 | (void) (&_max1 == &_max2); \ |
652 | _max1 > _max2 ? _max1 : _max2; }) | 662 | _max1 > _max2 ? _max1 : _max2; }) |
653 | 663 | ||
664 | #define min3(x, y, z) ({ \ | ||
665 | typeof(x) _min1 = (x); \ | ||
666 | typeof(y) _min2 = (y); \ | ||
667 | typeof(z) _min3 = (z); \ | ||
668 | (void) (&_min1 == &_min2); \ | ||
669 | (void) (&_min1 == &_min3); \ | ||
670 | _min1 < _min2 ? (_min1 < _min3 ? _min1 : _min3) : \ | ||
671 | (_min2 < _min3 ? _min2 : _min3); }) | ||
672 | |||
673 | #define max3(x, y, z) ({ \ | ||
674 | typeof(x) _max1 = (x); \ | ||
675 | typeof(y) _max2 = (y); \ | ||
676 | typeof(z) _max3 = (z); \ | ||
677 | (void) (&_max1 == &_max2); \ | ||
678 | (void) (&_max1 == &_max3); \ | ||
679 | _max1 > _max2 ? (_max1 > _max3 ? _max1 : _max3) : \ | ||
680 | (_max2 > _max3 ? _max2 : _max3); }) | ||
681 | |||
654 | /** | 682 | /** |
655 | * min_not_zero - return the minimum that is _not_ zero, unless both are zero | 683 | * min_not_zero - return the minimum that is _not_ zero, unless both are zero |
656 | * @x: value1 | 684 | * @x: value1 |
diff --git a/include/linux/kfifo.h b/include/linux/kfifo.h index 62dbee554f60..c238ad2f82ea 100644 --- a/include/linux/kfifo.h +++ b/include/linux/kfifo.h | |||
@@ -171,11 +171,8 @@ struct kfifo_rec_ptr_2 __STRUCT_KFIFO_PTR(unsigned char, 2, void); | |||
171 | } | 171 | } |
172 | 172 | ||
173 | 173 | ||
174 | static inline unsigned int __must_check | 174 | /* __kfifo_must_check_helper() is temporarily disabled because it was faulty */ |
175 | __kfifo_must_check_helper(unsigned int val) | 175 | #define __kfifo_must_check_helper(x) (x) |
176 | { | ||
177 | return val; | ||
178 | } | ||
179 | 176 | ||
180 | /** | 177 | /** |
181 | * kfifo_initialized - Check if the fifo is initialized | 178 | * kfifo_initialized - Check if the fifo is initialized |
diff --git a/include/linux/math64.h b/include/linux/math64.h index c87f1528703a..23fcdfcba81b 100644 --- a/include/linux/math64.h +++ b/include/linux/math64.h | |||
@@ -35,6 +35,14 @@ static inline u64 div64_u64(u64 dividend, u64 divisor) | |||
35 | return dividend / divisor; | 35 | return dividend / divisor; |
36 | } | 36 | } |
37 | 37 | ||
38 | /** | ||
39 | * div64_s64 - signed 64bit divide with 64bit divisor | ||
40 | */ | ||
41 | static inline s64 div64_s64(s64 dividend, s64 divisor) | ||
42 | { | ||
43 | return dividend / divisor; | ||
44 | } | ||
45 | |||
38 | #elif BITS_PER_LONG == 32 | 46 | #elif BITS_PER_LONG == 32 |
39 | 47 | ||
40 | #ifndef div_u64_rem | 48 | #ifndef div_u64_rem |
@@ -53,6 +61,10 @@ extern s64 div_s64_rem(s64 dividend, s32 divisor, s32 *remainder); | |||
53 | extern u64 div64_u64(u64 dividend, u64 divisor); | 61 | extern u64 div64_u64(u64 dividend, u64 divisor); |
54 | #endif | 62 | #endif |
55 | 63 | ||
64 | #ifndef div64_s64 | ||
65 | extern s64 div64_s64(s64 dividend, s64 divisor); | ||
66 | #endif | ||
67 | |||
56 | #endif /* BITS_PER_LONG */ | 68 | #endif /* BITS_PER_LONG */ |
57 | 69 | ||
58 | /** | 70 | /** |
diff --git a/include/linux/memory_hotplug.h b/include/linux/memory_hotplug.h index 864035fb8f8a..4307231bd22f 100644 --- a/include/linux/memory_hotplug.h +++ b/include/linux/memory_hotplug.h | |||
@@ -70,6 +70,10 @@ extern void online_page(struct page *page); | |||
70 | extern int online_pages(unsigned long, unsigned long); | 70 | extern int online_pages(unsigned long, unsigned long); |
71 | extern void __offline_isolated_pages(unsigned long, unsigned long); | 71 | extern void __offline_isolated_pages(unsigned long, unsigned long); |
72 | 72 | ||
73 | #ifdef CONFIG_MEMORY_HOTREMOVE | ||
74 | extern bool is_pageblock_removable_nolock(struct page *page); | ||
75 | #endif /* CONFIG_MEMORY_HOTREMOVE */ | ||
76 | |||
73 | /* reasonably generic interface to expand the physical pages in a zone */ | 77 | /* reasonably generic interface to expand the physical pages in a zone */ |
74 | extern int __add_pages(int nid, struct zone *zone, unsigned long start_pfn, | 78 | extern int __add_pages(int nid, struct zone *zone, unsigned long start_pfn, |
75 | unsigned long nr_pages); | 79 | unsigned long nr_pages); |
diff --git a/include/linux/mm.h b/include/linux/mm.h index a4c66846fb8f..721f451c3029 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h | |||
@@ -144,6 +144,7 @@ extern pgprot_t protection_map[16]; | |||
144 | #define FAULT_FLAG_WRITE 0x01 /* Fault was a write access */ | 144 | #define FAULT_FLAG_WRITE 0x01 /* Fault was a write access */ |
145 | #define FAULT_FLAG_NONLINEAR 0x02 /* Fault was via a nonlinear mapping */ | 145 | #define FAULT_FLAG_NONLINEAR 0x02 /* Fault was via a nonlinear mapping */ |
146 | #define FAULT_FLAG_MKWRITE 0x04 /* Fault was mkwrite of existing pte */ | 146 | #define FAULT_FLAG_MKWRITE 0x04 /* Fault was mkwrite of existing pte */ |
147 | #define FAULT_FLAG_ALLOW_RETRY 0x08 /* Retry fault if blocking */ | ||
147 | 148 | ||
148 | /* | 149 | /* |
149 | * This interface is used by x86 PAT code to identify a pfn mapping that is | 150 | * This interface is used by x86 PAT code to identify a pfn mapping that is |
@@ -497,8 +498,8 @@ static inline void set_compound_order(struct page *page, unsigned long order) | |||
497 | #define NODES_PGSHIFT (NODES_PGOFF * (NODES_WIDTH != 0)) | 498 | #define NODES_PGSHIFT (NODES_PGOFF * (NODES_WIDTH != 0)) |
498 | #define ZONES_PGSHIFT (ZONES_PGOFF * (ZONES_WIDTH != 0)) | 499 | #define ZONES_PGSHIFT (ZONES_PGOFF * (ZONES_WIDTH != 0)) |
499 | 500 | ||
500 | /* NODE:ZONE or SECTION:ZONE is used to ID a zone for the buddy allcator */ | 501 | /* NODE:ZONE or SECTION:ZONE is used to ID a zone for the buddy allocator */ |
501 | #ifdef NODE_NOT_IN_PAGEFLAGS | 502 | #ifdef NODE_NOT_IN_PAGE_FLAGS |
502 | #define ZONEID_SHIFT (SECTIONS_SHIFT + ZONES_SHIFT) | 503 | #define ZONEID_SHIFT (SECTIONS_SHIFT + ZONES_SHIFT) |
503 | #define ZONEID_PGOFF ((SECTIONS_PGOFF < ZONES_PGOFF)? \ | 504 | #define ZONEID_PGOFF ((SECTIONS_PGOFF < ZONES_PGOFF)? \ |
504 | SECTIONS_PGOFF : ZONES_PGOFF) | 505 | SECTIONS_PGOFF : ZONES_PGOFF) |
@@ -723,6 +724,7 @@ static inline int page_mapped(struct page *page) | |||
723 | 724 | ||
724 | #define VM_FAULT_NOPAGE 0x0100 /* ->fault installed the pte, not return page */ | 725 | #define VM_FAULT_NOPAGE 0x0100 /* ->fault installed the pte, not return page */ |
725 | #define VM_FAULT_LOCKED 0x0200 /* ->fault locked the returned page */ | 726 | #define VM_FAULT_LOCKED 0x0200 /* ->fault locked the returned page */ |
727 | #define VM_FAULT_RETRY 0x0400 /* ->fault blocked, must retry */ | ||
726 | 728 | ||
727 | #define VM_FAULT_HWPOISON_LARGE_MASK 0xf000 /* encodes hpage index for large hwpoison */ | 729 | #define VM_FAULT_HWPOISON_LARGE_MASK 0xf000 /* encodes hpage index for large hwpoison */ |
728 | 730 | ||
@@ -868,6 +870,7 @@ int __set_page_dirty_no_writeback(struct page *page); | |||
868 | int redirty_page_for_writepage(struct writeback_control *wbc, | 870 | int redirty_page_for_writepage(struct writeback_control *wbc, |
869 | struct page *page); | 871 | struct page *page); |
870 | void account_page_dirtied(struct page *page, struct address_space *mapping); | 872 | void account_page_dirtied(struct page *page, struct address_space *mapping); |
873 | void account_page_writeback(struct page *page); | ||
871 | int set_page_dirty(struct page *page); | 874 | int set_page_dirty(struct page *page); |
872 | int set_page_dirty_lock(struct page *page); | 875 | int set_page_dirty_lock(struct page *page); |
873 | int clear_page_dirty_for_io(struct page *page); | 876 | int clear_page_dirty_for_io(struct page *page); |
@@ -1031,7 +1034,15 @@ extern void unregister_shrinker(struct shrinker *); | |||
1031 | 1034 | ||
1032 | int vma_wants_writenotify(struct vm_area_struct *vma); | 1035 | int vma_wants_writenotify(struct vm_area_struct *vma); |
1033 | 1036 | ||
1034 | extern pte_t *get_locked_pte(struct mm_struct *mm, unsigned long addr, spinlock_t **ptl); | 1037 | extern pte_t *__get_locked_pte(struct mm_struct *mm, unsigned long addr, |
1038 | spinlock_t **ptl); | ||
1039 | static inline pte_t *get_locked_pte(struct mm_struct *mm, unsigned long addr, | ||
1040 | spinlock_t **ptl) | ||
1041 | { | ||
1042 | pte_t *ptep; | ||
1043 | __cond_lock(*ptl, ptep = __get_locked_pte(mm, addr, ptl)); | ||
1044 | return ptep; | ||
1045 | } | ||
1035 | 1046 | ||
1036 | #ifdef __PAGETABLE_PUD_FOLDED | 1047 | #ifdef __PAGETABLE_PUD_FOLDED |
1037 | static inline int __pud_alloc(struct mm_struct *mm, pgd_t *pgd, | 1048 | static inline int __pud_alloc(struct mm_struct *mm, pgd_t *pgd, |
diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h index cb57d657ce4d..bb7288a782fd 100644 --- a/include/linux/mm_types.h +++ b/include/linux/mm_types.h | |||
@@ -310,6 +310,8 @@ struct mm_struct { | |||
310 | #ifdef CONFIG_MMU_NOTIFIER | 310 | #ifdef CONFIG_MMU_NOTIFIER |
311 | struct mmu_notifier_mm *mmu_notifier_mm; | 311 | struct mmu_notifier_mm *mmu_notifier_mm; |
312 | #endif | 312 | #endif |
313 | /* How many tasks sharing this mm are OOM_DISABLE */ | ||
314 | atomic_t oom_disable_count; | ||
313 | }; | 315 | }; |
314 | 316 | ||
315 | /* Future-safe accessor for struct mm_struct's cpu_vm_mask. */ | 317 | /* Future-safe accessor for struct mm_struct's cpu_vm_mask. */ |
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index 3984c4eb41fd..39c24ebe9cfd 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h | |||
@@ -104,6 +104,8 @@ enum zone_stat_item { | |||
104 | NR_ISOLATED_ANON, /* Temporary isolated pages from anon lru */ | 104 | NR_ISOLATED_ANON, /* Temporary isolated pages from anon lru */ |
105 | NR_ISOLATED_FILE, /* Temporary isolated pages from file lru */ | 105 | NR_ISOLATED_FILE, /* Temporary isolated pages from file lru */ |
106 | NR_SHMEM, /* shmem pages (included tmpfs/GEM pages) */ | 106 | NR_SHMEM, /* shmem pages (included tmpfs/GEM pages) */ |
107 | NR_DIRTIED, /* page dirtyings since bootup */ | ||
108 | NR_WRITTEN, /* page writings since bootup */ | ||
107 | #ifdef CONFIG_NUMA | 109 | #ifdef CONFIG_NUMA |
108 | NUMA_HIT, /* allocated in intended node */ | 110 | NUMA_HIT, /* allocated in intended node */ |
109 | NUMA_MISS, /* allocated in non intended node */ | 111 | NUMA_MISS, /* allocated in non intended node */ |
@@ -421,6 +423,9 @@ struct zone { | |||
421 | typedef enum { | 423 | typedef enum { |
422 | ZONE_RECLAIM_LOCKED, /* prevents concurrent reclaim */ | 424 | ZONE_RECLAIM_LOCKED, /* prevents concurrent reclaim */ |
423 | ZONE_OOM_LOCKED, /* zone is in OOM killer zonelist */ | 425 | ZONE_OOM_LOCKED, /* zone is in OOM killer zonelist */ |
426 | ZONE_CONGESTED, /* zone has many dirty pages backed by | ||
427 | * a congested BDI | ||
428 | */ | ||
424 | } zone_flags_t; | 429 | } zone_flags_t; |
425 | 430 | ||
426 | static inline void zone_set_flag(struct zone *zone, zone_flags_t flag) | 431 | static inline void zone_set_flag(struct zone *zone, zone_flags_t flag) |
@@ -438,6 +443,11 @@ static inline void zone_clear_flag(struct zone *zone, zone_flags_t flag) | |||
438 | clear_bit(flag, &zone->flags); | 443 | clear_bit(flag, &zone->flags); |
439 | } | 444 | } |
440 | 445 | ||
446 | static inline int zone_is_reclaim_congested(const struct zone *zone) | ||
447 | { | ||
448 | return test_bit(ZONE_CONGESTED, &zone->flags); | ||
449 | } | ||
450 | |||
441 | static inline int zone_is_reclaim_locked(const struct zone *zone) | 451 | static inline int zone_is_reclaim_locked(const struct zone *zone) |
442 | { | 452 | { |
443 | return test_bit(ZONE_RECLAIM_LOCKED, &zone->flags); | 453 | return test_bit(ZONE_RECLAIM_LOCKED, &zone->flags); |
diff --git a/include/linux/moduleparam.h b/include/linux/moduleparam.h index 9d2f1837b3d8..112adf8bd47d 100644 --- a/include/linux/moduleparam.h +++ b/include/linux/moduleparam.h | |||
@@ -21,8 +21,8 @@ | |||
21 | #define __module_cat(a,b) ___module_cat(a,b) | 21 | #define __module_cat(a,b) ___module_cat(a,b) |
22 | #define __MODULE_INFO(tag, name, info) \ | 22 | #define __MODULE_INFO(tag, name, info) \ |
23 | static const char __module_cat(name,__LINE__)[] \ | 23 | static const char __module_cat(name,__LINE__)[] \ |
24 | __used \ | 24 | __used __attribute__((section(".modinfo"), unused, aligned(1))) \ |
25 | __attribute__((section(".modinfo"),unused)) = __stringify(tag) "=" info | 25 | = __stringify(tag) "=" info |
26 | #else /* !MODULE */ | 26 | #else /* !MODULE */ |
27 | #define __MODULE_INFO(tag, name, info) | 27 | #define __MODULE_INFO(tag, name, info) |
28 | #endif | 28 | #endif |
diff --git a/include/linux/pageblock-flags.h b/include/linux/pageblock-flags.h index e8c06122be36..19ef95d293ae 100644 --- a/include/linux/pageblock-flags.h +++ b/include/linux/pageblock-flags.h | |||
@@ -67,7 +67,8 @@ void set_pageblock_flags_group(struct page *page, unsigned long flags, | |||
67 | 67 | ||
68 | #define get_pageblock_flags(page) \ | 68 | #define get_pageblock_flags(page) \ |
69 | get_pageblock_flags_group(page, 0, NR_PAGEBLOCK_BITS-1) | 69 | get_pageblock_flags_group(page, 0, NR_PAGEBLOCK_BITS-1) |
70 | #define set_pageblock_flags(page) \ | 70 | #define set_pageblock_flags(page, flags) \ |
71 | set_pageblock_flags_group(page, 0, NR_PAGEBLOCK_BITS-1) | 71 | set_pageblock_flags_group(page, flags, \ |
72 | 0, NR_PAGEBLOCK_BITS-1) | ||
72 | 73 | ||
73 | #endif /* PAGEBLOCK_FLAGS_H */ | 74 | #endif /* PAGEBLOCK_FLAGS_H */ |
diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h index e12cdc6d79ee..2d1ffe3cf1ee 100644 --- a/include/linux/pagemap.h +++ b/include/linux/pagemap.h | |||
@@ -299,6 +299,8 @@ static inline pgoff_t linear_page_index(struct vm_area_struct *vma, | |||
299 | extern void __lock_page(struct page *page); | 299 | extern void __lock_page(struct page *page); |
300 | extern int __lock_page_killable(struct page *page); | 300 | extern int __lock_page_killable(struct page *page); |
301 | extern void __lock_page_nosync(struct page *page); | 301 | extern void __lock_page_nosync(struct page *page); |
302 | extern int __lock_page_or_retry(struct page *page, struct mm_struct *mm, | ||
303 | unsigned int flags); | ||
302 | extern void unlock_page(struct page *page); | 304 | extern void unlock_page(struct page *page); |
303 | 305 | ||
304 | static inline void __set_page_locked(struct page *page) | 306 | static inline void __set_page_locked(struct page *page) |
@@ -351,6 +353,17 @@ static inline void lock_page_nosync(struct page *page) | |||
351 | } | 353 | } |
352 | 354 | ||
353 | /* | 355 | /* |
356 | * lock_page_or_retry - Lock the page, unless this would block and the | ||
357 | * caller indicated that it can handle a retry. | ||
358 | */ | ||
359 | static inline int lock_page_or_retry(struct page *page, struct mm_struct *mm, | ||
360 | unsigned int flags) | ||
361 | { | ||
362 | might_sleep(); | ||
363 | return trylock_page(page) || __lock_page_or_retry(page, mm, flags); | ||
364 | } | ||
365 | |||
366 | /* | ||
354 | * This is exported only for wait_on_page_locked/wait_on_page_writeback. | 367 | * This is exported only for wait_on_page_locked/wait_on_page_writeback. |
355 | * Never use this directly! | 368 | * Never use this directly! |
356 | */ | 369 | */ |
diff --git a/include/linux/ratelimit.h b/include/linux/ratelimit.h index 8f69d09a41a5..03ff67b0cdf5 100644 --- a/include/linux/ratelimit.h +++ b/include/linux/ratelimit.h | |||
@@ -36,6 +36,8 @@ static inline void ratelimit_state_init(struct ratelimit_state *rs, | |||
36 | rs->begin = 0; | 36 | rs->begin = 0; |
37 | } | 37 | } |
38 | 38 | ||
39 | extern struct ratelimit_state printk_ratelimit_state; | ||
40 | |||
39 | extern int ___ratelimit(struct ratelimit_state *rs, const char *func); | 41 | extern int ___ratelimit(struct ratelimit_state *rs, const char *func); |
40 | #define __ratelimit(state) ___ratelimit(state, __func__) | 42 | #define __ratelimit(state) ___ratelimit(state, __func__) |
41 | 43 | ||
diff --git a/include/linux/rmap.h b/include/linux/rmap.h index 31b2fd75dcba..bb83c0da2071 100644 --- a/include/linux/rmap.h +++ b/include/linux/rmap.h | |||
@@ -25,8 +25,8 @@ | |||
25 | * pointing to this anon_vma once its vma list is empty. | 25 | * pointing to this anon_vma once its vma list is empty. |
26 | */ | 26 | */ |
27 | struct anon_vma { | 27 | struct anon_vma { |
28 | spinlock_t lock; /* Serialize access to vma list */ | ||
29 | struct anon_vma *root; /* Root of this anon_vma tree */ | 28 | struct anon_vma *root; /* Root of this anon_vma tree */ |
29 | spinlock_t lock; /* Serialize access to vma list */ | ||
30 | #if defined(CONFIG_KSM) || defined(CONFIG_MIGRATION) | 30 | #if defined(CONFIG_KSM) || defined(CONFIG_MIGRATION) |
31 | 31 | ||
32 | /* | 32 | /* |
@@ -205,9 +205,20 @@ int try_to_unmap_one(struct page *, struct vm_area_struct *, | |||
205 | /* | 205 | /* |
206 | * Called from mm/filemap_xip.c to unmap empty zero page | 206 | * Called from mm/filemap_xip.c to unmap empty zero page |
207 | */ | 207 | */ |
208 | pte_t *page_check_address(struct page *, struct mm_struct *, | 208 | pte_t *__page_check_address(struct page *, struct mm_struct *, |
209 | unsigned long, spinlock_t **, int); | 209 | unsigned long, spinlock_t **, int); |
210 | 210 | ||
211 | static inline pte_t *page_check_address(struct page *page, struct mm_struct *mm, | ||
212 | unsigned long address, | ||
213 | spinlock_t **ptlp, int sync) | ||
214 | { | ||
215 | pte_t *ptep; | ||
216 | |||
217 | __cond_lock(*ptlp, ptep = __page_check_address(page, mm, address, | ||
218 | ptlp, sync)); | ||
219 | return ptep; | ||
220 | } | ||
221 | |||
211 | /* | 222 | /* |
212 | * Used by swapoff to help locate where page is expected in vma. | 223 | * Used by swapoff to help locate where page is expected in vma. |
213 | */ | 224 | */ |
@@ -230,7 +241,20 @@ int try_to_munlock(struct page *); | |||
230 | /* | 241 | /* |
231 | * Called by memory-failure.c to kill processes. | 242 | * Called by memory-failure.c to kill processes. |
232 | */ | 243 | */ |
233 | struct anon_vma *page_lock_anon_vma(struct page *page); | 244 | struct anon_vma *__page_lock_anon_vma(struct page *page); |
245 | |||
246 | static inline struct anon_vma *page_lock_anon_vma(struct page *page) | ||
247 | { | ||
248 | struct anon_vma *anon_vma; | ||
249 | |||
250 | __cond_lock(RCU, anon_vma = __page_lock_anon_vma(page)); | ||
251 | |||
252 | /* (void) is needed to make gcc happy */ | ||
253 | (void) __cond_lock(&anon_vma->root->lock, anon_vma); | ||
254 | |||
255 | return anon_vma; | ||
256 | } | ||
257 | |||
234 | void page_unlock_anon_vma(struct anon_vma *anon_vma); | 258 | void page_unlock_anon_vma(struct anon_vma *anon_vma); |
235 | int page_mapped_in_vma(struct page *page, struct vm_area_struct *vma); | 259 | int page_mapped_in_vma(struct page *page, struct vm_area_struct *vma); |
236 | 260 | ||
diff --git a/include/linux/sched.h b/include/linux/sched.h index 56154bbb8da9..393ce94e54b7 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h | |||
@@ -1706,7 +1706,6 @@ extern void thread_group_times(struct task_struct *p, cputime_t *ut, cputime_t * | |||
1706 | #define PF_DUMPCORE 0x00000200 /* dumped core */ | 1706 | #define PF_DUMPCORE 0x00000200 /* dumped core */ |
1707 | #define PF_SIGNALED 0x00000400 /* killed by a signal */ | 1707 | #define PF_SIGNALED 0x00000400 /* killed by a signal */ |
1708 | #define PF_MEMALLOC 0x00000800 /* Allocating memory */ | 1708 | #define PF_MEMALLOC 0x00000800 /* Allocating memory */ |
1709 | #define PF_FLUSHER 0x00001000 /* responsible for disk writeback */ | ||
1710 | #define PF_USED_MATH 0x00002000 /* if unset the fpu must be initialized before use */ | 1709 | #define PF_USED_MATH 0x00002000 /* if unset the fpu must be initialized before use */ |
1711 | #define PF_FREEZING 0x00004000 /* freeze in progress. do not account to load */ | 1710 | #define PF_FREEZING 0x00004000 /* freeze in progress. do not account to load */ |
1712 | #define PF_NOFREEZE 0x00008000 /* this thread should not be frozen */ | 1711 | #define PF_NOFREEZE 0x00008000 /* this thread should not be frozen */ |
diff --git a/include/linux/swap.h b/include/linux/swap.h index 7cdd63366f88..eba53e71d2cc 100644 --- a/include/linux/swap.h +++ b/include/linux/swap.h | |||
@@ -271,8 +271,18 @@ extern void scan_mapping_unevictable_pages(struct address_space *); | |||
271 | extern unsigned long scan_unevictable_pages; | 271 | extern unsigned long scan_unevictable_pages; |
272 | extern int scan_unevictable_handler(struct ctl_table *, int, | 272 | extern int scan_unevictable_handler(struct ctl_table *, int, |
273 | void __user *, size_t *, loff_t *); | 273 | void __user *, size_t *, loff_t *); |
274 | #ifdef CONFIG_NUMA | ||
274 | extern int scan_unevictable_register_node(struct node *node); | 275 | extern int scan_unevictable_register_node(struct node *node); |
275 | extern void scan_unevictable_unregister_node(struct node *node); | 276 | extern void scan_unevictable_unregister_node(struct node *node); |
277 | #else | ||
278 | static inline int scan_unevictable_register_node(struct node *node) | ||
279 | { | ||
280 | return 0; | ||
281 | } | ||
282 | static inline void scan_unevictable_unregister_node(struct node *node) | ||
283 | { | ||
284 | } | ||
285 | #endif | ||
276 | 286 | ||
277 | extern int kswapd_run(int nid); | 287 | extern int kswapd_run(int nid); |
278 | extern void kswapd_stop(int nid); | 288 | extern void kswapd_stop(int nid); |
diff --git a/include/linux/types.h b/include/linux/types.h index 357dbc19606f..c2a9eb44f2fa 100644 --- a/include/linux/types.h +++ b/include/linux/types.h | |||
@@ -121,15 +121,7 @@ typedef __u64 u_int64_t; | |||
121 | typedef __s64 int64_t; | 121 | typedef __s64 int64_t; |
122 | #endif | 122 | #endif |
123 | 123 | ||
124 | /* | 124 | /* this is a special 64bit data type that is 8-byte aligned */ |
125 | * aligned_u64 should be used in defining kernel<->userspace ABIs to avoid | ||
126 | * common 32/64-bit compat problems. | ||
127 | * 64-bit values align to 4-byte boundaries on x86_32 (and possibly other | ||
128 | * architectures) and to 8-byte boundaries on 64-bit architetures. The new | ||
129 | * aligned_64 type enforces 8-byte alignment so that structs containing | ||
130 | * aligned_64 values have the same alignment on 32-bit and 64-bit architectures. | ||
131 | * No conversions are necessary between 32-bit user-space and a 64-bit kernel. | ||
132 | */ | ||
133 | #define aligned_u64 __u64 __attribute__((aligned(8))) | 125 | #define aligned_u64 __u64 __attribute__((aligned(8))) |
134 | #define aligned_be64 __be64 __attribute__((aligned(8))) | 126 | #define aligned_be64 __be64 __attribute__((aligned(8))) |
135 | #define aligned_le64 __le64 __attribute__((aligned(8))) | 127 | #define aligned_le64 __le64 __attribute__((aligned(8))) |
@@ -186,7 +178,15 @@ typedef __u64 __bitwise __be64; | |||
186 | typedef __u16 __bitwise __sum16; | 178 | typedef __u16 __bitwise __sum16; |
187 | typedef __u32 __bitwise __wsum; | 179 | typedef __u32 __bitwise __wsum; |
188 | 180 | ||
189 | /* this is a special 64bit data type that is 8-byte aligned */ | 181 | /* |
182 | * aligned_u64 should be used in defining kernel<->userspace ABIs to avoid | ||
183 | * common 32/64-bit compat problems. | ||
184 | * 64-bit values align to 4-byte boundaries on x86_32 (and possibly other | ||
185 | * architectures) and to 8-byte boundaries on 64-bit architetures. The new | ||
186 | * aligned_64 type enforces 8-byte alignment so that structs containing | ||
187 | * aligned_64 values have the same alignment on 32-bit and 64-bit architectures. | ||
188 | * No conversions are necessary between 32-bit user-space and a 64-bit kernel. | ||
189 | */ | ||
190 | #define __aligned_u64 __u64 __attribute__((aligned(8))) | 190 | #define __aligned_u64 __u64 __attribute__((aligned(8))) |
191 | #define __aligned_be64 __be64 __attribute__((aligned(8))) | 191 | #define __aligned_be64 __be64 __attribute__((aligned(8))) |
192 | #define __aligned_le64 __le64 __attribute__((aligned(8))) | 192 | #define __aligned_le64 __le64 __attribute__((aligned(8))) |
diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h index 63a4fe6d51bd..a03dcf62ca9d 100644 --- a/include/linux/vmalloc.h +++ b/include/linux/vmalloc.h | |||
@@ -53,8 +53,10 @@ static inline void vmalloc_init(void) | |||
53 | #endif | 53 | #endif |
54 | 54 | ||
55 | extern void *vmalloc(unsigned long size); | 55 | extern void *vmalloc(unsigned long size); |
56 | extern void *vzalloc(unsigned long size); | ||
56 | extern void *vmalloc_user(unsigned long size); | 57 | extern void *vmalloc_user(unsigned long size); |
57 | extern void *vmalloc_node(unsigned long size, int node); | 58 | extern void *vmalloc_node(unsigned long size, int node); |
59 | extern void *vzalloc_node(unsigned long size, int node); | ||
58 | extern void *vmalloc_exec(unsigned long size); | 60 | extern void *vmalloc_exec(unsigned long size); |
59 | extern void *vmalloc_32(unsigned long size); | 61 | extern void *vmalloc_32(unsigned long size); |
60 | extern void *vmalloc_32_user(unsigned long size); | 62 | extern void *vmalloc_32_user(unsigned long size); |
diff --git a/include/linux/workqueue.h b/include/linux/workqueue.h index 070bb7a88936..0c0771f06bfa 100644 --- a/include/linux/workqueue.h +++ b/include/linux/workqueue.h | |||
@@ -190,7 +190,7 @@ static inline unsigned int work_static(struct work_struct *work) { return 0; } | |||
190 | __INIT_WORK((_work), (_func), 0); \ | 190 | __INIT_WORK((_work), (_func), 0); \ |
191 | } while (0) | 191 | } while (0) |
192 | 192 | ||
193 | #define INIT_WORK_ON_STACK(_work, _func) \ | 193 | #define INIT_WORK_ONSTACK(_work, _func) \ |
194 | do { \ | 194 | do { \ |
195 | __INIT_WORK((_work), (_func), 1); \ | 195 | __INIT_WORK((_work), (_func), 1); \ |
196 | } while (0) | 196 | } while (0) |
@@ -201,9 +201,9 @@ static inline unsigned int work_static(struct work_struct *work) { return 0; } | |||
201 | init_timer(&(_work)->timer); \ | 201 | init_timer(&(_work)->timer); \ |
202 | } while (0) | 202 | } while (0) |
203 | 203 | ||
204 | #define INIT_DELAYED_WORK_ON_STACK(_work, _func) \ | 204 | #define INIT_DELAYED_WORK_ONSTACK(_work, _func) \ |
205 | do { \ | 205 | do { \ |
206 | INIT_WORK_ON_STACK(&(_work)->work, (_func)); \ | 206 | INIT_WORK_ONSTACK(&(_work)->work, (_func)); \ |
207 | init_timer_on_stack(&(_work)->timer); \ | 207 | init_timer_on_stack(&(_work)->timer); \ |
208 | } while (0) | 208 | } while (0) |
209 | 209 | ||
diff --git a/include/linux/writeback.h b/include/linux/writeback.h index 72a5d647a5f2..c7299d2ace6b 100644 --- a/include/linux/writeback.h +++ b/include/linux/writeback.h | |||
@@ -149,6 +149,8 @@ int write_cache_pages(struct address_space *mapping, | |||
149 | int do_writepages(struct address_space *mapping, struct writeback_control *wbc); | 149 | int do_writepages(struct address_space *mapping, struct writeback_control *wbc); |
150 | void set_page_dirty_balance(struct page *page, int page_mkwrite); | 150 | void set_page_dirty_balance(struct page *page, int page_mkwrite); |
151 | void writeback_set_ratelimit(void); | 151 | void writeback_set_ratelimit(void); |
152 | void tag_pages_for_writeback(struct address_space *mapping, | ||
153 | pgoff_t start, pgoff_t end); | ||
152 | 154 | ||
153 | /* pdflush.c */ | 155 | /* pdflush.c */ |
154 | extern int nr_pdflush_threads; /* Global so it can be exported to sysctl | 156 | extern int nr_pdflush_threads; /* Global so it can be exported to sysctl |
diff --git a/include/trace/events/ext4.h b/include/trace/events/ext4.h index 01e9e0076a92..6bcb00645de4 100644 --- a/include/trace/events/ext4.h +++ b/include/trace/events/ext4.h | |||
@@ -242,18 +242,20 @@ TRACE_EVENT(ext4_da_writepages, | |||
242 | __entry->pages_skipped = wbc->pages_skipped; | 242 | __entry->pages_skipped = wbc->pages_skipped; |
243 | __entry->range_start = wbc->range_start; | 243 | __entry->range_start = wbc->range_start; |
244 | __entry->range_end = wbc->range_end; | 244 | __entry->range_end = wbc->range_end; |
245 | __entry->nonblocking = wbc->nonblocking; | ||
246 | __entry->for_kupdate = wbc->for_kupdate; | 245 | __entry->for_kupdate = wbc->for_kupdate; |
247 | __entry->for_reclaim = wbc->for_reclaim; | 246 | __entry->for_reclaim = wbc->for_reclaim; |
248 | __entry->range_cyclic = wbc->range_cyclic; | 247 | __entry->range_cyclic = wbc->range_cyclic; |
249 | __entry->writeback_index = inode->i_mapping->writeback_index; | 248 | __entry->writeback_index = inode->i_mapping->writeback_index; |
250 | ), | 249 | ), |
251 | 250 | ||
252 | TP_printk("dev %s ino %lu nr_to_write %ld pages_skipped %ld range_start %llu range_end %llu nonblocking %d for_kupdate %d for_reclaim %d range_cyclic %d writeback_index %lu", | 251 | TP_printk("dev %s ino %lu nr_to_write %ld pages_skipped %ld " |
252 | "range_start %llu range_end %llu " | ||
253 | "for_kupdate %d for_reclaim %d " | ||
254 | "range_cyclic %d writeback_index %lu", | ||
253 | jbd2_dev_to_name(__entry->dev), | 255 | jbd2_dev_to_name(__entry->dev), |
254 | (unsigned long) __entry->ino, __entry->nr_to_write, | 256 | (unsigned long) __entry->ino, __entry->nr_to_write, |
255 | __entry->pages_skipped, __entry->range_start, | 257 | __entry->pages_skipped, __entry->range_start, |
256 | __entry->range_end, __entry->nonblocking, | 258 | __entry->range_end, |
257 | __entry->for_kupdate, __entry->for_reclaim, | 259 | __entry->for_kupdate, __entry->for_reclaim, |
258 | __entry->range_cyclic, | 260 | __entry->range_cyclic, |
259 | (unsigned long) __entry->writeback_index) | 261 | (unsigned long) __entry->writeback_index) |
diff --git a/include/trace/events/vmscan.h b/include/trace/events/vmscan.h index 370aa5a87322..c255fcc587bf 100644 --- a/include/trace/events/vmscan.h +++ b/include/trace/events/vmscan.h | |||
@@ -10,6 +10,7 @@ | |||
10 | 10 | ||
11 | #define RECLAIM_WB_ANON 0x0001u | 11 | #define RECLAIM_WB_ANON 0x0001u |
12 | #define RECLAIM_WB_FILE 0x0002u | 12 | #define RECLAIM_WB_FILE 0x0002u |
13 | #define RECLAIM_WB_MIXED 0x0010u | ||
13 | #define RECLAIM_WB_SYNC 0x0004u | 14 | #define RECLAIM_WB_SYNC 0x0004u |
14 | #define RECLAIM_WB_ASYNC 0x0008u | 15 | #define RECLAIM_WB_ASYNC 0x0008u |
15 | 16 | ||
@@ -17,13 +18,20 @@ | |||
17 | (flags) ? __print_flags(flags, "|", \ | 18 | (flags) ? __print_flags(flags, "|", \ |
18 | {RECLAIM_WB_ANON, "RECLAIM_WB_ANON"}, \ | 19 | {RECLAIM_WB_ANON, "RECLAIM_WB_ANON"}, \ |
19 | {RECLAIM_WB_FILE, "RECLAIM_WB_FILE"}, \ | 20 | {RECLAIM_WB_FILE, "RECLAIM_WB_FILE"}, \ |
21 | {RECLAIM_WB_MIXED, "RECLAIM_WB_MIXED"}, \ | ||
20 | {RECLAIM_WB_SYNC, "RECLAIM_WB_SYNC"}, \ | 22 | {RECLAIM_WB_SYNC, "RECLAIM_WB_SYNC"}, \ |
21 | {RECLAIM_WB_ASYNC, "RECLAIM_WB_ASYNC"} \ | 23 | {RECLAIM_WB_ASYNC, "RECLAIM_WB_ASYNC"} \ |
22 | ) : "RECLAIM_WB_NONE" | 24 | ) : "RECLAIM_WB_NONE" |
23 | 25 | ||
24 | #define trace_reclaim_flags(page, sync) ( \ | 26 | #define trace_reclaim_flags(page, sync) ( \ |
25 | (page_is_file_cache(page) ? RECLAIM_WB_FILE : RECLAIM_WB_ANON) | \ | 27 | (page_is_file_cache(page) ? RECLAIM_WB_FILE : RECLAIM_WB_ANON) | \ |
26 | (sync == PAGEOUT_IO_SYNC ? RECLAIM_WB_SYNC : RECLAIM_WB_ASYNC) \ | 28 | (sync == LUMPY_MODE_SYNC ? RECLAIM_WB_SYNC : RECLAIM_WB_ASYNC) \ |
29 | ) | ||
30 | |||
31 | #define trace_shrink_flags(file, sync) ( \ | ||
32 | (sync == LUMPY_MODE_SYNC ? RECLAIM_WB_MIXED : \ | ||
33 | (file ? RECLAIM_WB_FILE : RECLAIM_WB_ANON)) | \ | ||
34 | (sync == LUMPY_MODE_SYNC ? RECLAIM_WB_SYNC : RECLAIM_WB_ASYNC) \ | ||
27 | ) | 35 | ) |
28 | 36 | ||
29 | TRACE_EVENT(mm_vmscan_kswapd_sleep, | 37 | TRACE_EVENT(mm_vmscan_kswapd_sleep, |
@@ -269,6 +277,40 @@ TRACE_EVENT(mm_vmscan_writepage, | |||
269 | show_reclaim_flags(__entry->reclaim_flags)) | 277 | show_reclaim_flags(__entry->reclaim_flags)) |
270 | ); | 278 | ); |
271 | 279 | ||
280 | TRACE_EVENT(mm_vmscan_lru_shrink_inactive, | ||
281 | |||
282 | TP_PROTO(int nid, int zid, | ||
283 | unsigned long nr_scanned, unsigned long nr_reclaimed, | ||
284 | int priority, int reclaim_flags), | ||
285 | |||
286 | TP_ARGS(nid, zid, nr_scanned, nr_reclaimed, priority, reclaim_flags), | ||
287 | |||
288 | TP_STRUCT__entry( | ||
289 | __field(int, nid) | ||
290 | __field(int, zid) | ||
291 | __field(unsigned long, nr_scanned) | ||
292 | __field(unsigned long, nr_reclaimed) | ||
293 | __field(int, priority) | ||
294 | __field(int, reclaim_flags) | ||
295 | ), | ||
296 | |||
297 | TP_fast_assign( | ||
298 | __entry->nid = nid; | ||
299 | __entry->zid = zid; | ||
300 | __entry->nr_scanned = nr_scanned; | ||
301 | __entry->nr_reclaimed = nr_reclaimed; | ||
302 | __entry->priority = priority; | ||
303 | __entry->reclaim_flags = reclaim_flags; | ||
304 | ), | ||
305 | |||
306 | TP_printk("nid=%d zid=%d nr_scanned=%ld nr_reclaimed=%ld priority=%d flags=%s", | ||
307 | __entry->nid, __entry->zid, | ||
308 | __entry->nr_scanned, __entry->nr_reclaimed, | ||
309 | __entry->priority, | ||
310 | show_reclaim_flags(__entry->reclaim_flags)) | ||
311 | ); | ||
312 | |||
313 | |||
272 | #endif /* _TRACE_VMSCAN_H */ | 314 | #endif /* _TRACE_VMSCAN_H */ |
273 | 315 | ||
274 | /* This part must be outside protection */ | 316 | /* This part must be outside protection */ |
diff --git a/include/trace/events/writeback.h b/include/trace/events/writeback.h index f345f66ae9d1..89a2b2db4375 100644 --- a/include/trace/events/writeback.h +++ b/include/trace/events/writeback.h | |||
@@ -96,8 +96,6 @@ DECLARE_EVENT_CLASS(wbc_class, | |||
96 | __field(long, nr_to_write) | 96 | __field(long, nr_to_write) |
97 | __field(long, pages_skipped) | 97 | __field(long, pages_skipped) |
98 | __field(int, sync_mode) | 98 | __field(int, sync_mode) |
99 | __field(int, nonblocking) | ||
100 | __field(int, encountered_congestion) | ||
101 | __field(int, for_kupdate) | 99 | __field(int, for_kupdate) |
102 | __field(int, for_background) | 100 | __field(int, for_background) |
103 | __field(int, for_reclaim) | 101 | __field(int, for_reclaim) |
@@ -153,6 +151,41 @@ DEFINE_WBC_EVENT(wbc_balance_dirty_written); | |||
153 | DEFINE_WBC_EVENT(wbc_balance_dirty_wait); | 151 | DEFINE_WBC_EVENT(wbc_balance_dirty_wait); |
154 | DEFINE_WBC_EVENT(wbc_writepage); | 152 | DEFINE_WBC_EVENT(wbc_writepage); |
155 | 153 | ||
154 | DECLARE_EVENT_CLASS(writeback_congest_waited_template, | ||
155 | |||
156 | TP_PROTO(unsigned int usec_timeout, unsigned int usec_delayed), | ||
157 | |||
158 | TP_ARGS(usec_timeout, usec_delayed), | ||
159 | |||
160 | TP_STRUCT__entry( | ||
161 | __field( unsigned int, usec_timeout ) | ||
162 | __field( unsigned int, usec_delayed ) | ||
163 | ), | ||
164 | |||
165 | TP_fast_assign( | ||
166 | __entry->usec_timeout = usec_timeout; | ||
167 | __entry->usec_delayed = usec_delayed; | ||
168 | ), | ||
169 | |||
170 | TP_printk("usec_timeout=%u usec_delayed=%u", | ||
171 | __entry->usec_timeout, | ||
172 | __entry->usec_delayed) | ||
173 | ); | ||
174 | |||
175 | DEFINE_EVENT(writeback_congest_waited_template, writeback_congestion_wait, | ||
176 | |||
177 | TP_PROTO(unsigned int usec_timeout, unsigned int usec_delayed), | ||
178 | |||
179 | TP_ARGS(usec_timeout, usec_delayed) | ||
180 | ); | ||
181 | |||
182 | DEFINE_EVENT(writeback_congest_waited_template, writeback_wait_iff_congested, | ||
183 | |||
184 | TP_PROTO(unsigned int usec_timeout, unsigned int usec_delayed), | ||
185 | |||
186 | TP_ARGS(usec_timeout, usec_delayed) | ||
187 | ); | ||
188 | |||
156 | #endif /* _TRACE_WRITEBACK_H */ | 189 | #endif /* _TRACE_WRITEBACK_H */ |
157 | 190 | ||
158 | /* This part must be outside protection */ | 191 | /* This part must be outside protection */ |
diff --git a/init/do_mounts.c b/init/do_mounts.c index 62a47eafa8e9..830aaec9c7d5 100644 --- a/init/do_mounts.c +++ b/init/do_mounts.c | |||
@@ -291,7 +291,7 @@ static int __init do_mount_root(char *name, char *fs, int flags, void *data) | |||
291 | if (err) | 291 | if (err) |
292 | return err; | 292 | return err; |
293 | 293 | ||
294 | sys_chdir("/root"); | 294 | sys_chdir((const char __user __force *)"/root"); |
295 | ROOT_DEV = current->fs->pwd.mnt->mnt_sb->s_dev; | 295 | ROOT_DEV = current->fs->pwd.mnt->mnt_sb->s_dev; |
296 | printk("VFS: Mounted root (%s filesystem)%s on device %u:%u.\n", | 296 | printk("VFS: Mounted root (%s filesystem)%s on device %u:%u.\n", |
297 | current->fs->pwd.mnt->mnt_sb->s_type->name, | 297 | current->fs->pwd.mnt->mnt_sb->s_type->name, |
@@ -488,5 +488,5 @@ void __init prepare_namespace(void) | |||
488 | out: | 488 | out: |
489 | devtmpfs_mount("dev"); | 489 | devtmpfs_mount("dev"); |
490 | sys_mount(".", "/", NULL, MS_MOVE, NULL); | 490 | sys_mount(".", "/", NULL, MS_MOVE, NULL); |
491 | sys_chroot("."); | 491 | sys_chroot((const char __user __force *)"."); |
492 | } | 492 | } |
diff --git a/init/do_mounts_md.c b/init/do_mounts_md.c index 69aebbf8fd2d..32c4799b8c91 100644 --- a/init/do_mounts_md.c +++ b/init/do_mounts_md.c | |||
@@ -283,7 +283,7 @@ static void __init autodetect_raid(void) | |||
283 | 283 | ||
284 | wait_for_device_probe(); | 284 | wait_for_device_probe(); |
285 | 285 | ||
286 | fd = sys_open("/dev/md0", 0, 0); | 286 | fd = sys_open((const char __user __force *) "/dev/md0", 0, 0); |
287 | if (fd >= 0) { | 287 | if (fd >= 0) { |
288 | sys_ioctl(fd, RAID_AUTORUN, raid_autopart); | 288 | sys_ioctl(fd, RAID_AUTORUN, raid_autopart); |
289 | sys_close(fd); | 289 | sys_close(fd); |
diff --git a/init/do_mounts_rd.c b/init/do_mounts_rd.c index bf3ef667bf36..6e1ee6987c78 100644 --- a/init/do_mounts_rd.c +++ b/init/do_mounts_rd.c | |||
@@ -168,7 +168,7 @@ int __init rd_load_image(char *from) | |||
168 | char rotator[4] = { '|' , '/' , '-' , '\\' }; | 168 | char rotator[4] = { '|' , '/' , '-' , '\\' }; |
169 | #endif | 169 | #endif |
170 | 170 | ||
171 | out_fd = sys_open("/dev/ram", O_RDWR, 0); | 171 | out_fd = sys_open((const char __user __force *) "/dev/ram", O_RDWR, 0); |
172 | if (out_fd < 0) | 172 | if (out_fd < 0) |
173 | goto out; | 173 | goto out; |
174 | 174 | ||
@@ -267,7 +267,7 @@ noclose_input: | |||
267 | sys_close(out_fd); | 267 | sys_close(out_fd); |
268 | out: | 268 | out: |
269 | kfree(buf); | 269 | kfree(buf); |
270 | sys_unlink("/dev/ram"); | 270 | sys_unlink((const char __user __force *) "/dev/ram"); |
271 | return res; | 271 | return res; |
272 | } | 272 | } |
273 | 273 | ||
diff --git a/init/initramfs.c b/init/initramfs.c index 4b9c20205092..d9c6e782ff53 100644 --- a/init/initramfs.c +++ b/init/initramfs.c | |||
@@ -528,7 +528,7 @@ static void __init clean_rootfs(void) | |||
528 | struct linux_dirent64 *dirp; | 528 | struct linux_dirent64 *dirp; |
529 | int num; | 529 | int num; |
530 | 530 | ||
531 | fd = sys_open("/", O_RDONLY, 0); | 531 | fd = sys_open((const char __user __force *) "/", O_RDONLY, 0); |
532 | WARN_ON(fd < 0); | 532 | WARN_ON(fd < 0); |
533 | if (fd < 0) | 533 | if (fd < 0) |
534 | return; | 534 | return; |
@@ -590,7 +590,8 @@ static int __init populate_rootfs(void) | |||
590 | } | 590 | } |
591 | printk(KERN_INFO "rootfs image is not initramfs (%s)" | 591 | printk(KERN_INFO "rootfs image is not initramfs (%s)" |
592 | "; looks like an initrd\n", err); | 592 | "; looks like an initrd\n", err); |
593 | fd = sys_open("/initrd.image", O_WRONLY|O_CREAT, 0700); | 593 | fd = sys_open((const char __user __force *) "/initrd.image", |
594 | O_WRONLY|O_CREAT, 0700); | ||
594 | if (fd >= 0) { | 595 | if (fd >= 0) { |
595 | sys_write(fd, (char *)initrd_start, | 596 | sys_write(fd, (char *)initrd_start, |
596 | initrd_end - initrd_start); | 597 | initrd_end - initrd_start); |
diff --git a/init/noinitramfs.c b/init/noinitramfs.c index f4c1a3a1b8c5..267739d85179 100644 --- a/init/noinitramfs.c +++ b/init/noinitramfs.c | |||
@@ -29,17 +29,17 @@ static int __init default_rootfs(void) | |||
29 | { | 29 | { |
30 | int err; | 30 | int err; |
31 | 31 | ||
32 | err = sys_mkdir("/dev", 0755); | 32 | err = sys_mkdir((const char __user __force *) "/dev", 0755); |
33 | if (err < 0) | 33 | if (err < 0) |
34 | goto out; | 34 | goto out; |
35 | 35 | ||
36 | err = sys_mknod((const char __user *) "/dev/console", | 36 | err = sys_mknod((const char __user __force *) "/dev/console", |
37 | S_IFCHR | S_IRUSR | S_IWUSR, | 37 | S_IFCHR | S_IRUSR | S_IWUSR, |
38 | new_encode_dev(MKDEV(5, 1))); | 38 | new_encode_dev(MKDEV(5, 1))); |
39 | if (err < 0) | 39 | if (err < 0) |
40 | goto out; | 40 | goto out; |
41 | 41 | ||
42 | err = sys_mkdir("/root", 0700); | 42 | err = sys_mkdir((const char __user __force *) "/root", 0700); |
43 | if (err < 0) | 43 | if (err < 0) |
44 | goto out; | 44 | goto out; |
45 | 45 | ||
diff --git a/kernel/exit.c b/kernel/exit.c index e2bdf37f9fde..894179a32ec1 100644 --- a/kernel/exit.c +++ b/kernel/exit.c | |||
@@ -50,6 +50,7 @@ | |||
50 | #include <linux/perf_event.h> | 50 | #include <linux/perf_event.h> |
51 | #include <trace/events/sched.h> | 51 | #include <trace/events/sched.h> |
52 | #include <linux/hw_breakpoint.h> | 52 | #include <linux/hw_breakpoint.h> |
53 | #include <linux/oom.h> | ||
53 | 54 | ||
54 | #include <asm/uaccess.h> | 55 | #include <asm/uaccess.h> |
55 | #include <asm/unistd.h> | 56 | #include <asm/unistd.h> |
@@ -687,6 +688,8 @@ static void exit_mm(struct task_struct * tsk) | |||
687 | enter_lazy_tlb(mm, current); | 688 | enter_lazy_tlb(mm, current); |
688 | /* We don't want this task to be frozen prematurely */ | 689 | /* We don't want this task to be frozen prematurely */ |
689 | clear_freeze_flag(tsk); | 690 | clear_freeze_flag(tsk); |
691 | if (tsk->signal->oom_score_adj == OOM_SCORE_ADJ_MIN) | ||
692 | atomic_dec(&mm->oom_disable_count); | ||
690 | task_unlock(tsk); | 693 | task_unlock(tsk); |
691 | mm_update_next_owner(mm); | 694 | mm_update_next_owner(mm); |
692 | mmput(mm); | 695 | mmput(mm); |
diff --git a/kernel/fork.c b/kernel/fork.c index c445f8cc408d..e87aaaaf5131 100644 --- a/kernel/fork.c +++ b/kernel/fork.c | |||
@@ -65,6 +65,7 @@ | |||
65 | #include <linux/perf_event.h> | 65 | #include <linux/perf_event.h> |
66 | #include <linux/posix-timers.h> | 66 | #include <linux/posix-timers.h> |
67 | #include <linux/user-return-notifier.h> | 67 | #include <linux/user-return-notifier.h> |
68 | #include <linux/oom.h> | ||
68 | 69 | ||
69 | #include <asm/pgtable.h> | 70 | #include <asm/pgtable.h> |
70 | #include <asm/pgalloc.h> | 71 | #include <asm/pgalloc.h> |
@@ -488,6 +489,7 @@ static struct mm_struct * mm_init(struct mm_struct * mm, struct task_struct *p) | |||
488 | mm->cached_hole_size = ~0UL; | 489 | mm->cached_hole_size = ~0UL; |
489 | mm_init_aio(mm); | 490 | mm_init_aio(mm); |
490 | mm_init_owner(mm, p); | 491 | mm_init_owner(mm, p); |
492 | atomic_set(&mm->oom_disable_count, 0); | ||
491 | 493 | ||
492 | if (likely(!mm_alloc_pgd(mm))) { | 494 | if (likely(!mm_alloc_pgd(mm))) { |
493 | mm->def_flags = 0; | 495 | mm->def_flags = 0; |
@@ -741,6 +743,8 @@ good_mm: | |||
741 | /* Initializing for Swap token stuff */ | 743 | /* Initializing for Swap token stuff */ |
742 | mm->token_priority = 0; | 744 | mm->token_priority = 0; |
743 | mm->last_interval = 0; | 745 | mm->last_interval = 0; |
746 | if (tsk->signal->oom_score_adj == OOM_SCORE_ADJ_MIN) | ||
747 | atomic_inc(&mm->oom_disable_count); | ||
744 | 748 | ||
745 | tsk->mm = mm; | 749 | tsk->mm = mm; |
746 | tsk->active_mm = mm; | 750 | tsk->active_mm = mm; |
@@ -1299,8 +1303,13 @@ bad_fork_cleanup_io: | |||
1299 | bad_fork_cleanup_namespaces: | 1303 | bad_fork_cleanup_namespaces: |
1300 | exit_task_namespaces(p); | 1304 | exit_task_namespaces(p); |
1301 | bad_fork_cleanup_mm: | 1305 | bad_fork_cleanup_mm: |
1302 | if (p->mm) | 1306 | if (p->mm) { |
1307 | task_lock(p); | ||
1308 | if (p->signal->oom_score_adj == OOM_SCORE_ADJ_MIN) | ||
1309 | atomic_dec(&p->mm->oom_disable_count); | ||
1310 | task_unlock(p); | ||
1303 | mmput(p->mm); | 1311 | mmput(p->mm); |
1312 | } | ||
1304 | bad_fork_cleanup_signal: | 1313 | bad_fork_cleanup_signal: |
1305 | if (!(clone_flags & CLONE_THREAD)) | 1314 | if (!(clone_flags & CLONE_THREAD)) |
1306 | free_signal_struct(p->signal); | 1315 | free_signal_struct(p->signal); |
@@ -1693,6 +1702,10 @@ SYSCALL_DEFINE1(unshare, unsigned long, unshare_flags) | |||
1693 | active_mm = current->active_mm; | 1702 | active_mm = current->active_mm; |
1694 | current->mm = new_mm; | 1703 | current->mm = new_mm; |
1695 | current->active_mm = new_mm; | 1704 | current->active_mm = new_mm; |
1705 | if (current->signal->oom_score_adj == OOM_SCORE_ADJ_MIN) { | ||
1706 | atomic_dec(&mm->oom_disable_count); | ||
1707 | atomic_inc(&new_mm->oom_disable_count); | ||
1708 | } | ||
1696 | activate_mm(active_mm, new_mm); | 1709 | activate_mm(active_mm, new_mm); |
1697 | new_mm = mm; | 1710 | new_mm = mm; |
1698 | } | 1711 | } |
diff --git a/kernel/kexec.c b/kernel/kexec.c index c0613f7d6730..b55045bc7563 100644 --- a/kernel/kexec.c +++ b/kernel/kexec.c | |||
@@ -816,7 +816,7 @@ static int kimage_load_normal_segment(struct kimage *image, | |||
816 | 816 | ||
817 | ptr = kmap(page); | 817 | ptr = kmap(page); |
818 | /* Start with a clear page */ | 818 | /* Start with a clear page */ |
819 | memset(ptr, 0, PAGE_SIZE); | 819 | clear_page(ptr); |
820 | ptr += maddr & ~PAGE_MASK; | 820 | ptr += maddr & ~PAGE_MASK; |
821 | mchunk = PAGE_SIZE - (maddr & ~PAGE_MASK); | 821 | mchunk = PAGE_SIZE - (maddr & ~PAGE_MASK); |
822 | if (mchunk > mbytes) | 822 | if (mchunk > mbytes) |
diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c index ac7eb109f196..0dac75ea4456 100644 --- a/kernel/power/snapshot.c +++ b/kernel/power/snapshot.c | |||
@@ -984,8 +984,8 @@ static void copy_data_page(unsigned long dst_pfn, unsigned long src_pfn) | |||
984 | src = kmap_atomic(s_page, KM_USER0); | 984 | src = kmap_atomic(s_page, KM_USER0); |
985 | dst = kmap_atomic(d_page, KM_USER1); | 985 | dst = kmap_atomic(d_page, KM_USER1); |
986 | do_copy_page(dst, src); | 986 | do_copy_page(dst, src); |
987 | kunmap_atomic(src, KM_USER0); | ||
988 | kunmap_atomic(dst, KM_USER1); | 987 | kunmap_atomic(dst, KM_USER1); |
988 | kunmap_atomic(src, KM_USER0); | ||
989 | } else { | 989 | } else { |
990 | if (PageHighMem(d_page)) { | 990 | if (PageHighMem(d_page)) { |
991 | /* Page pointed to by src may contain some kernel | 991 | /* Page pointed to by src may contain some kernel |
@@ -993,7 +993,7 @@ static void copy_data_page(unsigned long dst_pfn, unsigned long src_pfn) | |||
993 | */ | 993 | */ |
994 | safe_copy_page(buffer, s_page); | 994 | safe_copy_page(buffer, s_page); |
995 | dst = kmap_atomic(d_page, KM_USER0); | 995 | dst = kmap_atomic(d_page, KM_USER0); |
996 | memcpy(dst, buffer, PAGE_SIZE); | 996 | copy_page(dst, buffer); |
997 | kunmap_atomic(dst, KM_USER0); | 997 | kunmap_atomic(dst, KM_USER0); |
998 | } else { | 998 | } else { |
999 | safe_copy_page(page_address(d_page), s_page); | 999 | safe_copy_page(page_address(d_page), s_page); |
@@ -1687,7 +1687,7 @@ int snapshot_read_next(struct snapshot_handle *handle) | |||
1687 | memory_bm_position_reset(&orig_bm); | 1687 | memory_bm_position_reset(&orig_bm); |
1688 | memory_bm_position_reset(©_bm); | 1688 | memory_bm_position_reset(©_bm); |
1689 | } else if (handle->cur <= nr_meta_pages) { | 1689 | } else if (handle->cur <= nr_meta_pages) { |
1690 | memset(buffer, 0, PAGE_SIZE); | 1690 | clear_page(buffer); |
1691 | pack_pfns(buffer, &orig_bm); | 1691 | pack_pfns(buffer, &orig_bm); |
1692 | } else { | 1692 | } else { |
1693 | struct page *page; | 1693 | struct page *page; |
@@ -1701,7 +1701,7 @@ int snapshot_read_next(struct snapshot_handle *handle) | |||
1701 | void *kaddr; | 1701 | void *kaddr; |
1702 | 1702 | ||
1703 | kaddr = kmap_atomic(page, KM_USER0); | 1703 | kaddr = kmap_atomic(page, KM_USER0); |
1704 | memcpy(buffer, kaddr, PAGE_SIZE); | 1704 | copy_page(buffer, kaddr); |
1705 | kunmap_atomic(kaddr, KM_USER0); | 1705 | kunmap_atomic(kaddr, KM_USER0); |
1706 | handle->buffer = buffer; | 1706 | handle->buffer = buffer; |
1707 | } else { | 1707 | } else { |
@@ -1984,7 +1984,7 @@ static void copy_last_highmem_page(void) | |||
1984 | void *dst; | 1984 | void *dst; |
1985 | 1985 | ||
1986 | dst = kmap_atomic(last_highmem_page, KM_USER0); | 1986 | dst = kmap_atomic(last_highmem_page, KM_USER0); |
1987 | memcpy(dst, buffer, PAGE_SIZE); | 1987 | copy_page(dst, buffer); |
1988 | kunmap_atomic(dst, KM_USER0); | 1988 | kunmap_atomic(dst, KM_USER0); |
1989 | last_highmem_page = NULL; | 1989 | last_highmem_page = NULL; |
1990 | } | 1990 | } |
@@ -2270,11 +2270,11 @@ swap_two_pages_data(struct page *p1, struct page *p2, void *buf) | |||
2270 | 2270 | ||
2271 | kaddr1 = kmap_atomic(p1, KM_USER0); | 2271 | kaddr1 = kmap_atomic(p1, KM_USER0); |
2272 | kaddr2 = kmap_atomic(p2, KM_USER1); | 2272 | kaddr2 = kmap_atomic(p2, KM_USER1); |
2273 | memcpy(buf, kaddr1, PAGE_SIZE); | 2273 | copy_page(buf, kaddr1); |
2274 | memcpy(kaddr1, kaddr2, PAGE_SIZE); | 2274 | copy_page(kaddr1, kaddr2); |
2275 | memcpy(kaddr2, buf, PAGE_SIZE); | 2275 | copy_page(kaddr2, buf); |
2276 | kunmap_atomic(kaddr1, KM_USER0); | ||
2277 | kunmap_atomic(kaddr2, KM_USER1); | 2276 | kunmap_atomic(kaddr2, KM_USER1); |
2277 | kunmap_atomic(kaddr1, KM_USER0); | ||
2278 | } | 2278 | } |
2279 | 2279 | ||
2280 | /** | 2280 | /** |
diff --git a/kernel/power/swap.c b/kernel/power/swap.c index 916eaa790399..a0e4a86ccf94 100644 --- a/kernel/power/swap.c +++ b/kernel/power/swap.c | |||
@@ -251,7 +251,7 @@ static int write_page(void *buf, sector_t offset, struct bio **bio_chain) | |||
251 | if (bio_chain) { | 251 | if (bio_chain) { |
252 | src = (void *)__get_free_page(__GFP_WAIT | __GFP_HIGH); | 252 | src = (void *)__get_free_page(__GFP_WAIT | __GFP_HIGH); |
253 | if (src) { | 253 | if (src) { |
254 | memcpy(src, buf, PAGE_SIZE); | 254 | copy_page(src, buf); |
255 | } else { | 255 | } else { |
256 | WARN_ON_ONCE(1); | 256 | WARN_ON_ONCE(1); |
257 | bio_chain = NULL; /* Go synchronous */ | 257 | bio_chain = NULL; /* Go synchronous */ |
@@ -325,7 +325,7 @@ static int swap_write_page(struct swap_map_handle *handle, void *buf, | |||
325 | error = write_page(handle->cur, handle->cur_swap, NULL); | 325 | error = write_page(handle->cur, handle->cur_swap, NULL); |
326 | if (error) | 326 | if (error) |
327 | goto out; | 327 | goto out; |
328 | memset(handle->cur, 0, PAGE_SIZE); | 328 | clear_page(handle->cur); |
329 | handle->cur_swap = offset; | 329 | handle->cur_swap = offset; |
330 | handle->k = 0; | 330 | handle->k = 0; |
331 | } | 331 | } |
@@ -910,7 +910,7 @@ int swsusp_check(void) | |||
910 | hib_resume_bdev = open_by_devnum(swsusp_resume_device, FMODE_READ); | 910 | hib_resume_bdev = open_by_devnum(swsusp_resume_device, FMODE_READ); |
911 | if (!IS_ERR(hib_resume_bdev)) { | 911 | if (!IS_ERR(hib_resume_bdev)) { |
912 | set_blocksize(hib_resume_bdev, PAGE_SIZE); | 912 | set_blocksize(hib_resume_bdev, PAGE_SIZE); |
913 | memset(swsusp_header, 0, PAGE_SIZE); | 913 | clear_page(swsusp_header); |
914 | error = hib_bio_read_page(swsusp_resume_block, | 914 | error = hib_bio_read_page(swsusp_resume_block, |
915 | swsusp_header, NULL); | 915 | swsusp_header, NULL); |
916 | if (error) | 916 | if (error) |
diff --git a/kernel/printk.c b/kernel/printk.c index 2531017795f6..b2ebaee8c377 100644 --- a/kernel/printk.c +++ b/kernel/printk.c | |||
@@ -210,7 +210,7 @@ __setup("log_buf_len=", log_buf_len_setup); | |||
210 | 210 | ||
211 | #ifdef CONFIG_BOOT_PRINTK_DELAY | 211 | #ifdef CONFIG_BOOT_PRINTK_DELAY |
212 | 212 | ||
213 | static unsigned int boot_delay; /* msecs delay after each printk during bootup */ | 213 | static int boot_delay; /* msecs delay after each printk during bootup */ |
214 | static unsigned long long loops_per_msec; /* based on boot_delay */ | 214 | static unsigned long long loops_per_msec; /* based on boot_delay */ |
215 | 215 | ||
216 | static int __init boot_delay_setup(char *str) | 216 | static int __init boot_delay_setup(char *str) |
@@ -647,6 +647,7 @@ static inline int can_use_console(unsigned int cpu) | |||
647 | * released but interrupts still disabled. | 647 | * released but interrupts still disabled. |
648 | */ | 648 | */ |
649 | static int acquire_console_semaphore_for_printk(unsigned int cpu) | 649 | static int acquire_console_semaphore_for_printk(unsigned int cpu) |
650 | __releases(&logbuf_lock) | ||
650 | { | 651 | { |
651 | int retval = 0; | 652 | int retval = 0; |
652 | 653 | ||
@@ -1511,7 +1512,7 @@ int kmsg_dump_unregister(struct kmsg_dumper *dumper) | |||
1511 | } | 1512 | } |
1512 | EXPORT_SYMBOL_GPL(kmsg_dump_unregister); | 1513 | EXPORT_SYMBOL_GPL(kmsg_dump_unregister); |
1513 | 1514 | ||
1514 | static const char const *kmsg_reasons[] = { | 1515 | static const char * const kmsg_reasons[] = { |
1515 | [KMSG_DUMP_OOPS] = "oops", | 1516 | [KMSG_DUMP_OOPS] = "oops", |
1516 | [KMSG_DUMP_PANIC] = "panic", | 1517 | [KMSG_DUMP_PANIC] = "panic", |
1517 | [KMSG_DUMP_KEXEC] = "kexec", | 1518 | [KMSG_DUMP_KEXEC] = "kexec", |
diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c index 090c28812ce1..2df820b03beb 100644 --- a/kernel/stop_machine.c +++ b/kernel/stop_machine.c | |||
@@ -262,7 +262,7 @@ repeat: | |||
262 | cpu_stop_fn_t fn = work->fn; | 262 | cpu_stop_fn_t fn = work->fn; |
263 | void *arg = work->arg; | 263 | void *arg = work->arg; |
264 | struct cpu_stop_done *done = work->done; | 264 | struct cpu_stop_done *done = work->done; |
265 | char ksym_buf[KSYM_NAME_LEN]; | 265 | char ksym_buf[KSYM_NAME_LEN] __maybe_unused; |
266 | 266 | ||
267 | __set_current_state(TASK_RUNNING); | 267 | __set_current_state(TASK_RUNNING); |
268 | 268 | ||
@@ -304,7 +304,7 @@ static int __cpuinit cpu_stop_cpu_callback(struct notifier_block *nfb, | |||
304 | p = kthread_create(cpu_stopper_thread, stopper, "migration/%d", | 304 | p = kthread_create(cpu_stopper_thread, stopper, "migration/%d", |
305 | cpu); | 305 | cpu); |
306 | if (IS_ERR(p)) | 306 | if (IS_ERR(p)) |
307 | return NOTIFY_BAD; | 307 | return notifier_from_errno(PTR_ERR(p)); |
308 | get_task_struct(p); | 308 | get_task_struct(p); |
309 | kthread_bind(p, cpu); | 309 | kthread_bind(p, cpu); |
310 | sched_set_stop_task(cpu, p); | 310 | sched_set_stop_task(cpu, p); |
@@ -372,7 +372,7 @@ static int __init cpu_stop_init(void) | |||
372 | /* start one for the boot cpu */ | 372 | /* start one for the boot cpu */ |
373 | err = cpu_stop_cpu_callback(&cpu_stop_cpu_notifier, CPU_UP_PREPARE, | 373 | err = cpu_stop_cpu_callback(&cpu_stop_cpu_notifier, CPU_UP_PREPARE, |
374 | bcpu); | 374 | bcpu); |
375 | BUG_ON(err == NOTIFY_BAD); | 375 | BUG_ON(err != NOTIFY_OK); |
376 | cpu_stop_cpu_callback(&cpu_stop_cpu_notifier, CPU_ONLINE, bcpu); | 376 | cpu_stop_cpu_callback(&cpu_stop_cpu_notifier, CPU_ONLINE, bcpu); |
377 | register_cpu_notifier(&cpu_stop_cpu_notifier); | 377 | register_cpu_notifier(&cpu_stop_cpu_notifier); |
378 | 378 | ||
diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 3a45c224770f..48d9d689498f 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c | |||
@@ -161,8 +161,6 @@ extern int no_unaligned_warning; | |||
161 | extern int unaligned_dump_stack; | 161 | extern int unaligned_dump_stack; |
162 | #endif | 162 | #endif |
163 | 163 | ||
164 | extern struct ratelimit_state printk_ratelimit_state; | ||
165 | |||
166 | #ifdef CONFIG_PROC_SYSCTL | 164 | #ifdef CONFIG_PROC_SYSCTL |
167 | static int proc_do_cad_pid(struct ctl_table *table, int write, | 165 | static int proc_do_cad_pid(struct ctl_table *table, int write, |
168 | void __user *buffer, size_t *lenp, loff_t *ppos); | 166 | void __user *buffer, size_t *lenp, loff_t *ppos); |
@@ -1352,16 +1350,16 @@ static struct ctl_table fs_table[] = { | |||
1352 | { | 1350 | { |
1353 | .procname = "file-nr", | 1351 | .procname = "file-nr", |
1354 | .data = &files_stat, | 1352 | .data = &files_stat, |
1355 | .maxlen = 3*sizeof(int), | 1353 | .maxlen = sizeof(files_stat), |
1356 | .mode = 0444, | 1354 | .mode = 0444, |
1357 | .proc_handler = proc_nr_files, | 1355 | .proc_handler = proc_nr_files, |
1358 | }, | 1356 | }, |
1359 | { | 1357 | { |
1360 | .procname = "file-max", | 1358 | .procname = "file-max", |
1361 | .data = &files_stat.max_files, | 1359 | .data = &files_stat.max_files, |
1362 | .maxlen = sizeof(int), | 1360 | .maxlen = sizeof(files_stat.max_files), |
1363 | .mode = 0644, | 1361 | .mode = 0644, |
1364 | .proc_handler = proc_dointvec, | 1362 | .proc_handler = proc_doulongvec_minmax, |
1365 | }, | 1363 | }, |
1366 | { | 1364 | { |
1367 | .procname = "nr_open", | 1365 | .procname = "nr_open", |
diff --git a/kernel/user.c b/kernel/user.c index 7e72614b736d..2c7d8d5914b1 100644 --- a/kernel/user.c +++ b/kernel/user.c | |||
@@ -91,6 +91,7 @@ static struct user_struct *uid_hash_find(uid_t uid, struct hlist_head *hashent) | |||
91 | * upon function exit. | 91 | * upon function exit. |
92 | */ | 92 | */ |
93 | static void free_user(struct user_struct *up, unsigned long flags) | 93 | static void free_user(struct user_struct *up, unsigned long flags) |
94 | __releases(&uidhash_lock) | ||
94 | { | 95 | { |
95 | uid_hash_remove(up); | 96 | uid_hash_remove(up); |
96 | spin_unlock_irqrestore(&uidhash_lock, flags); | 97 | spin_unlock_irqrestore(&uidhash_lock, flags); |
diff --git a/kernel/workqueue.c b/kernel/workqueue.c index e5ff2cbaadc2..90db1bd1a978 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c | |||
@@ -2064,7 +2064,7 @@ static void insert_wq_barrier(struct cpu_workqueue_struct *cwq, | |||
2064 | * checks and call back into the fixup functions where we | 2064 | * checks and call back into the fixup functions where we |
2065 | * might deadlock. | 2065 | * might deadlock. |
2066 | */ | 2066 | */ |
2067 | INIT_WORK_ON_STACK(&barr->work, wq_barrier_func); | 2067 | INIT_WORK_ONSTACK(&barr->work, wq_barrier_func); |
2068 | __set_bit(WORK_STRUCT_PENDING_BIT, work_data_bits(&barr->work)); | 2068 | __set_bit(WORK_STRUCT_PENDING_BIT, work_data_bits(&barr->work)); |
2069 | init_completion(&barr->done); | 2069 | init_completion(&barr->done); |
2070 | 2070 | ||
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 69a32664c289..95bda87a3e84 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug | |||
@@ -317,6 +317,14 @@ config DEBUG_OBJECTS_RCU_HEAD | |||
317 | help | 317 | help |
318 | Enable this to turn on debugging of RCU list heads (call_rcu() usage). | 318 | Enable this to turn on debugging of RCU list heads (call_rcu() usage). |
319 | 319 | ||
320 | config DEBUG_OBJECTS_PERCPU_COUNTER | ||
321 | bool "Debug percpu counter objects" | ||
322 | depends on DEBUG_OBJECTS | ||
323 | help | ||
324 | If you say Y here, additional code will be inserted into the | ||
325 | percpu counter routines to track the life time of percpu counter | ||
326 | objects and validate the percpu counter operations. | ||
327 | |||
320 | config DEBUG_OBJECTS_ENABLE_DEFAULT | 328 | config DEBUG_OBJECTS_ENABLE_DEFAULT |
321 | int "debug_objects bootup default value (0-1)" | 329 | int "debug_objects bootup default value (0-1)" |
322 | range 0 1 | 330 | range 0 1 |
@@ -740,6 +748,15 @@ config DEBUG_LIST | |||
740 | 748 | ||
741 | If unsure, say N. | 749 | If unsure, say N. |
742 | 750 | ||
751 | config TEST_LIST_SORT | ||
752 | bool "Linked list sorting test" | ||
753 | depends on DEBUG_KERNEL | ||
754 | help | ||
755 | Enable this to turn on 'list_sort()' function test. This test is | ||
756 | executed only once during system boot, so affects only boot time. | ||
757 | |||
758 | If unsure, say N. | ||
759 | |||
743 | config DEBUG_SG | 760 | config DEBUG_SG |
744 | bool "Debug SG table operations" | 761 | bool "Debug SG table operations" |
745 | depends on DEBUG_KERNEL | 762 | depends on DEBUG_KERNEL |
diff --git a/lib/bitmap.c b/lib/bitmap.c index ffb78c916ccd..741fae905ae3 100644 --- a/lib/bitmap.c +++ b/lib/bitmap.c | |||
@@ -359,7 +359,6 @@ EXPORT_SYMBOL(bitmap_find_next_zero_area); | |||
359 | 359 | ||
360 | #define CHUNKSZ 32 | 360 | #define CHUNKSZ 32 |
361 | #define nbits_to_hold_value(val) fls(val) | 361 | #define nbits_to_hold_value(val) fls(val) |
362 | #define unhex(c) (isdigit(c) ? (c - '0') : (toupper(c) - 'A' + 10)) | ||
363 | #define BASEDEC 10 /* fancier cpuset lists input in decimal */ | 362 | #define BASEDEC 10 /* fancier cpuset lists input in decimal */ |
364 | 363 | ||
365 | /** | 364 | /** |
@@ -466,7 +465,7 @@ int __bitmap_parse(const char *buf, unsigned int buflen, | |||
466 | if (chunk & ~((1UL << (CHUNKSZ - 4)) - 1)) | 465 | if (chunk & ~((1UL << (CHUNKSZ - 4)) - 1)) |
467 | return -EOVERFLOW; | 466 | return -EOVERFLOW; |
468 | 467 | ||
469 | chunk = (chunk << 4) | unhex(c); | 468 | chunk = (chunk << 4) | hex_to_bin(c); |
470 | ndigits++; totaldigits++; | 469 | ndigits++; totaldigits++; |
471 | } | 470 | } |
472 | if (ndigits == 0) | 471 | if (ndigits == 0) |
diff --git a/lib/div64.c b/lib/div64.c index a111eb8de9cf..5b4919191778 100644 --- a/lib/div64.c +++ b/lib/div64.c | |||
@@ -77,26 +77,58 @@ s64 div_s64_rem(s64 dividend, s32 divisor, s32 *remainder) | |||
77 | EXPORT_SYMBOL(div_s64_rem); | 77 | EXPORT_SYMBOL(div_s64_rem); |
78 | #endif | 78 | #endif |
79 | 79 | ||
80 | /* 64bit divisor, dividend and result. dynamic precision */ | 80 | /** |
81 | * div64_u64 - unsigned 64bit divide with 64bit divisor | ||
82 | * @dividend: 64bit dividend | ||
83 | * @divisor: 64bit divisor | ||
84 | * | ||
85 | * This implementation is a modified version of the algorithm proposed | ||
86 | * by the book 'Hacker's Delight'. The original source and full proof | ||
87 | * can be found here and is available for use without restriction. | ||
88 | * | ||
89 | * 'http://www.hackersdelight.org/HDcode/newCode/divDouble.c' | ||
90 | */ | ||
81 | #ifndef div64_u64 | 91 | #ifndef div64_u64 |
82 | u64 div64_u64(u64 dividend, u64 divisor) | 92 | u64 div64_u64(u64 dividend, u64 divisor) |
83 | { | 93 | { |
84 | u32 high, d; | 94 | u32 high = divisor >> 32; |
95 | u64 quot; | ||
85 | 96 | ||
86 | high = divisor >> 32; | 97 | if (high == 0) { |
87 | if (high) { | 98 | quot = div_u64(dividend, divisor); |
88 | unsigned int shift = fls(high); | 99 | } else { |
100 | int n = 1 + fls(high); | ||
101 | quot = div_u64(dividend >> n, divisor >> n); | ||
89 | 102 | ||
90 | d = divisor >> shift; | 103 | if (quot != 0) |
91 | dividend >>= shift; | 104 | quot--; |
92 | } else | 105 | if ((dividend - quot * divisor) >= divisor) |
93 | d = divisor; | 106 | quot++; |
107 | } | ||
94 | 108 | ||
95 | return div_u64(dividend, d); | 109 | return quot; |
96 | } | 110 | } |
97 | EXPORT_SYMBOL(div64_u64); | 111 | EXPORT_SYMBOL(div64_u64); |
98 | #endif | 112 | #endif |
99 | 113 | ||
114 | /** | ||
115 | * div64_s64 - signed 64bit divide with 64bit divisor | ||
116 | * @dividend: 64bit dividend | ||
117 | * @divisor: 64bit divisor | ||
118 | */ | ||
119 | #ifndef div64_s64 | ||
120 | s64 div64_s64(s64 dividend, s64 divisor) | ||
121 | { | ||
122 | s64 quot, t; | ||
123 | |||
124 | quot = div64_u64(abs64(dividend), abs64(divisor)); | ||
125 | t = (dividend ^ divisor) >> 63; | ||
126 | |||
127 | return (quot ^ t) - t; | ||
128 | } | ||
129 | EXPORT_SYMBOL(div64_s64); | ||
130 | #endif | ||
131 | |||
100 | #endif /* BITS_PER_LONG == 32 */ | 132 | #endif /* BITS_PER_LONG == 32 */ |
101 | 133 | ||
102 | /* | 134 | /* |
@@ -110,9 +110,10 @@ static void idr_mark_full(struct idr_layer **pa, int id) | |||
110 | * @idp: idr handle | 110 | * @idp: idr handle |
111 | * @gfp_mask: memory allocation flags | 111 | * @gfp_mask: memory allocation flags |
112 | * | 112 | * |
113 | * This function should be called prior to locking and calling the | 113 | * This function should be called prior to calling the idr_get_new* functions. |
114 | * idr_get_new* functions. It preallocates enough memory to satisfy | 114 | * It preallocates enough memory to satisfy the worst possible allocation. The |
115 | * the worst possible allocation. | 115 | * caller should pass in GFP_KERNEL if possible. This of course requires that |
116 | * no spinning locks be held. | ||
116 | * | 117 | * |
117 | * If the system is REALLY out of memory this function returns 0, | 118 | * If the system is REALLY out of memory this function returns 0, |
118 | * otherwise 1. | 119 | * otherwise 1. |
@@ -290,9 +291,11 @@ static int idr_get_new_above_int(struct idr *idp, void *ptr, int starting_id) | |||
290 | * This is the allocate id function. It should be called with any | 291 | * This is the allocate id function. It should be called with any |
291 | * required locks. | 292 | * required locks. |
292 | * | 293 | * |
293 | * If memory is required, it will return -EAGAIN, you should unlock | 294 | * If allocation from IDR's private freelist fails, idr_get_new_above() will |
294 | * and go back to the idr_pre_get() call. If the idr is full, it will | 295 | * return -EAGAIN. The caller should retry the idr_pre_get() call to refill |
295 | * return -ENOSPC. | 296 | * IDR's preallocation and then retry the idr_get_new_above() call. |
297 | * | ||
298 | * If the idr is full idr_get_new_above() will return -ENOSPC. | ||
296 | * | 299 | * |
297 | * @id returns a value in the range @starting_id ... 0x7fffffff | 300 | * @id returns a value in the range @starting_id ... 0x7fffffff |
298 | */ | 301 | */ |
@@ -318,12 +321,11 @@ EXPORT_SYMBOL(idr_get_new_above); | |||
318 | * @ptr: pointer you want associated with the id | 321 | * @ptr: pointer you want associated with the id |
319 | * @id: pointer to the allocated handle | 322 | * @id: pointer to the allocated handle |
320 | * | 323 | * |
321 | * This is the allocate id function. It should be called with any | 324 | * If allocation from IDR's private freelist fails, idr_get_new_above() will |
322 | * required locks. | 325 | * return -EAGAIN. The caller should retry the idr_pre_get() call to refill |
326 | * IDR's preallocation and then retry the idr_get_new_above() call. | ||
323 | * | 327 | * |
324 | * If memory is required, it will return -EAGAIN, you should unlock | 328 | * If the idr is full idr_get_new_above() will return -ENOSPC. |
325 | * and go back to the idr_pre_get() call. If the idr is full, it will | ||
326 | * return -ENOSPC. | ||
327 | * | 329 | * |
328 | * @id returns a value in the range 0 ... 0x7fffffff | 330 | * @id returns a value in the range 0 ... 0x7fffffff |
329 | */ | 331 | */ |
diff --git a/lib/list_sort.c b/lib/list_sort.c index a7616fa3162e..d7325c6b103f 100644 --- a/lib/list_sort.c +++ b/lib/list_sort.c | |||
@@ -141,77 +141,151 @@ void list_sort(void *priv, struct list_head *head, | |||
141 | } | 141 | } |
142 | EXPORT_SYMBOL(list_sort); | 142 | EXPORT_SYMBOL(list_sort); |
143 | 143 | ||
144 | #ifdef DEBUG_LIST_SORT | 144 | #ifdef CONFIG_TEST_LIST_SORT |
145 | |||
146 | #include <linux/random.h> | ||
147 | |||
148 | /* | ||
149 | * The pattern of set bits in the list length determines which cases | ||
150 | * are hit in list_sort(). | ||
151 | */ | ||
152 | #define TEST_LIST_LEN (512+128+2) /* not including head */ | ||
153 | |||
154 | #define TEST_POISON1 0xDEADBEEF | ||
155 | #define TEST_POISON2 0xA324354C | ||
156 | |||
145 | struct debug_el { | 157 | struct debug_el { |
146 | struct list_head l_h; | 158 | unsigned int poison1; |
159 | struct list_head list; | ||
160 | unsigned int poison2; | ||
147 | int value; | 161 | int value; |
148 | unsigned serial; | 162 | unsigned serial; |
149 | }; | 163 | }; |
150 | 164 | ||
151 | static int cmp(void *priv, struct list_head *a, struct list_head *b) | 165 | /* Array, containing pointers to all elements in the test list */ |
166 | static struct debug_el **elts __initdata; | ||
167 | |||
168 | static int __init check(struct debug_el *ela, struct debug_el *elb) | ||
152 | { | 169 | { |
153 | return container_of(a, struct debug_el, l_h)->value | 170 | if (ela->serial >= TEST_LIST_LEN) { |
154 | - container_of(b, struct debug_el, l_h)->value; | 171 | printk(KERN_ERR "list_sort_test: error: incorrect serial %d\n", |
172 | ela->serial); | ||
173 | return -EINVAL; | ||
174 | } | ||
175 | if (elb->serial >= TEST_LIST_LEN) { | ||
176 | printk(KERN_ERR "list_sort_test: error: incorrect serial %d\n", | ||
177 | elb->serial); | ||
178 | return -EINVAL; | ||
179 | } | ||
180 | if (elts[ela->serial] != ela || elts[elb->serial] != elb) { | ||
181 | printk(KERN_ERR "list_sort_test: error: phantom element\n"); | ||
182 | return -EINVAL; | ||
183 | } | ||
184 | if (ela->poison1 != TEST_POISON1 || ela->poison2 != TEST_POISON2) { | ||
185 | printk(KERN_ERR "list_sort_test: error: bad poison: %#x/%#x\n", | ||
186 | ela->poison1, ela->poison2); | ||
187 | return -EINVAL; | ||
188 | } | ||
189 | if (elb->poison1 != TEST_POISON1 || elb->poison2 != TEST_POISON2) { | ||
190 | printk(KERN_ERR "list_sort_test: error: bad poison: %#x/%#x\n", | ||
191 | elb->poison1, elb->poison2); | ||
192 | return -EINVAL; | ||
193 | } | ||
194 | return 0; | ||
155 | } | 195 | } |
156 | 196 | ||
157 | /* | 197 | static int __init cmp(void *priv, struct list_head *a, struct list_head *b) |
158 | * The pattern of set bits in the list length determines which cases | 198 | { |
159 | * are hit in list_sort(). | 199 | struct debug_el *ela, *elb; |
160 | */ | 200 | |
161 | #define LIST_SORT_TEST_LENGTH (512+128+2) /* not including head */ | 201 | ela = container_of(a, struct debug_el, list); |
202 | elb = container_of(b, struct debug_el, list); | ||
203 | |||
204 | check(ela, elb); | ||
205 | return ela->value - elb->value; | ||
206 | } | ||
162 | 207 | ||
163 | static int __init list_sort_test(void) | 208 | static int __init list_sort_test(void) |
164 | { | 209 | { |
165 | int i, r = 1, count; | 210 | int i, count = 1, err = -EINVAL; |
166 | struct list_head *head = kmalloc(sizeof(*head), GFP_KERNEL); | 211 | struct debug_el *el; |
167 | struct list_head *cur; | 212 | struct list_head *cur, *tmp; |
213 | LIST_HEAD(head); | ||
214 | |||
215 | printk(KERN_DEBUG "list_sort_test: start testing list_sort()\n"); | ||
168 | 216 | ||
169 | printk(KERN_WARNING "testing list_sort()\n"); | 217 | elts = kmalloc(sizeof(void *) * TEST_LIST_LEN, GFP_KERNEL); |
218 | if (!elts) { | ||
219 | printk(KERN_ERR "list_sort_test: error: cannot allocate " | ||
220 | "memory\n"); | ||
221 | goto exit; | ||
222 | } | ||
170 | 223 | ||
171 | cur = head; | 224 | for (i = 0; i < TEST_LIST_LEN; i++) { |
172 | for (i = 0; i < LIST_SORT_TEST_LENGTH; i++) { | 225 | el = kmalloc(sizeof(*el), GFP_KERNEL); |
173 | struct debug_el *el = kmalloc(sizeof(*el), GFP_KERNEL); | 226 | if (!el) { |
174 | BUG_ON(!el); | 227 | printk(KERN_ERR "list_sort_test: error: cannot " |
228 | "allocate memory\n"); | ||
229 | goto exit; | ||
230 | } | ||
175 | /* force some equivalencies */ | 231 | /* force some equivalencies */ |
176 | el->value = (r = (r * 725861) % 6599) % (LIST_SORT_TEST_LENGTH/3); | 232 | el->value = random32() % (TEST_LIST_LEN/3); |
177 | el->serial = i; | 233 | el->serial = i; |
178 | 234 | el->poison1 = TEST_POISON1; | |
179 | el->l_h.prev = cur; | 235 | el->poison2 = TEST_POISON2; |
180 | cur->next = &el->l_h; | 236 | elts[i] = el; |
181 | cur = cur->next; | 237 | list_add_tail(&el->list, &head); |
182 | } | 238 | } |
183 | head->prev = cur; | ||
184 | 239 | ||
185 | list_sort(NULL, head, cmp); | 240 | list_sort(NULL, &head, cmp); |
241 | |||
242 | for (cur = head.next; cur->next != &head; cur = cur->next) { | ||
243 | struct debug_el *el1; | ||
244 | int cmp_result; | ||
186 | 245 | ||
187 | count = 1; | ||
188 | for (cur = head->next; cur->next != head; cur = cur->next) { | ||
189 | struct debug_el *el = container_of(cur, struct debug_el, l_h); | ||
190 | int cmp_result = cmp(NULL, cur, cur->next); | ||
191 | if (cur->next->prev != cur) { | 246 | if (cur->next->prev != cur) { |
192 | printk(KERN_EMERG "list_sort() returned " | 247 | printk(KERN_ERR "list_sort_test: error: list is " |
193 | "a corrupted list!\n"); | 248 | "corrupted\n"); |
194 | return 1; | 249 | goto exit; |
195 | } else if (cmp_result > 0) { | 250 | } |
196 | printk(KERN_EMERG "list_sort() failed to sort!\n"); | 251 | |
197 | return 1; | 252 | cmp_result = cmp(NULL, cur, cur->next); |
198 | } else if (cmp_result == 0 && | 253 | if (cmp_result > 0) { |
199 | el->serial >= container_of(cur->next, | 254 | printk(KERN_ERR "list_sort_test: error: list is not " |
200 | struct debug_el, l_h)->serial) { | 255 | "sorted\n"); |
201 | printk(KERN_EMERG "list_sort() failed to preserve order" | 256 | goto exit; |
202 | " of equivalent elements!\n"); | 257 | } |
203 | return 1; | 258 | |
259 | el = container_of(cur, struct debug_el, list); | ||
260 | el1 = container_of(cur->next, struct debug_el, list); | ||
261 | if (cmp_result == 0 && el->serial >= el1->serial) { | ||
262 | printk(KERN_ERR "list_sort_test: error: order of " | ||
263 | "equivalent elements not preserved\n"); | ||
264 | goto exit; | ||
265 | } | ||
266 | |||
267 | if (check(el, el1)) { | ||
268 | printk(KERN_ERR "list_sort_test: error: element check " | ||
269 | "failed\n"); | ||
270 | goto exit; | ||
204 | } | 271 | } |
205 | kfree(cur->prev); | ||
206 | count++; | 272 | count++; |
207 | } | 273 | } |
208 | kfree(cur); | 274 | |
209 | if (count != LIST_SORT_TEST_LENGTH) { | 275 | if (count != TEST_LIST_LEN) { |
210 | printk(KERN_EMERG "list_sort() returned list of" | 276 | printk(KERN_ERR "list_sort_test: error: bad list length %d", |
211 | "different length!\n"); | 277 | count); |
212 | return 1; | 278 | goto exit; |
213 | } | 279 | } |
214 | return 0; | 280 | |
281 | err = 0; | ||
282 | exit: | ||
283 | kfree(elts); | ||
284 | list_for_each_safe(cur, tmp, &head) { | ||
285 | list_del(cur); | ||
286 | kfree(container_of(cur, struct debug_el, list)); | ||
287 | } | ||
288 | return err; | ||
215 | } | 289 | } |
216 | module_init(list_sort_test); | 290 | module_init(list_sort_test); |
217 | #endif | 291 | #endif /* CONFIG_TEST_LIST_SORT */ |
diff --git a/lib/parser.c b/lib/parser.c index fb34977246bb..6e89eca5cca0 100644 --- a/lib/parser.c +++ b/lib/parser.c | |||
@@ -128,12 +128,13 @@ static int match_number(substring_t *s, int *result, int base) | |||
128 | char *endp; | 128 | char *endp; |
129 | char *buf; | 129 | char *buf; |
130 | int ret; | 130 | int ret; |
131 | size_t len = s->to - s->from; | ||
131 | 132 | ||
132 | buf = kmalloc(s->to - s->from + 1, GFP_KERNEL); | 133 | buf = kmalloc(len + 1, GFP_KERNEL); |
133 | if (!buf) | 134 | if (!buf) |
134 | return -ENOMEM; | 135 | return -ENOMEM; |
135 | memcpy(buf, s->from, s->to - s->from); | 136 | memcpy(buf, s->from, len); |
136 | buf[s->to - s->from] = '\0'; | 137 | buf[len] = '\0'; |
137 | *result = simple_strtol(buf, &endp, base); | 138 | *result = simple_strtol(buf, &endp, base); |
138 | ret = 0; | 139 | ret = 0; |
139 | if (endp == buf) | 140 | if (endp == buf) |
diff --git a/lib/percpu_counter.c b/lib/percpu_counter.c index ec9048e74f44..604678d7d06d 100644 --- a/lib/percpu_counter.c +++ b/lib/percpu_counter.c | |||
@@ -8,10 +8,53 @@ | |||
8 | #include <linux/init.h> | 8 | #include <linux/init.h> |
9 | #include <linux/cpu.h> | 9 | #include <linux/cpu.h> |
10 | #include <linux/module.h> | 10 | #include <linux/module.h> |
11 | #include <linux/debugobjects.h> | ||
11 | 12 | ||
12 | static LIST_HEAD(percpu_counters); | 13 | static LIST_HEAD(percpu_counters); |
13 | static DEFINE_MUTEX(percpu_counters_lock); | 14 | static DEFINE_MUTEX(percpu_counters_lock); |
14 | 15 | ||
16 | #ifdef CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER | ||
17 | |||
18 | static struct debug_obj_descr percpu_counter_debug_descr; | ||
19 | |||
20 | static int percpu_counter_fixup_free(void *addr, enum debug_obj_state state) | ||
21 | { | ||
22 | struct percpu_counter *fbc = addr; | ||
23 | |||
24 | switch (state) { | ||
25 | case ODEBUG_STATE_ACTIVE: | ||
26 | percpu_counter_destroy(fbc); | ||
27 | debug_object_free(fbc, &percpu_counter_debug_descr); | ||
28 | return 1; | ||
29 | default: | ||
30 | return 0; | ||
31 | } | ||
32 | } | ||
33 | |||
34 | static struct debug_obj_descr percpu_counter_debug_descr = { | ||
35 | .name = "percpu_counter", | ||
36 | .fixup_free = percpu_counter_fixup_free, | ||
37 | }; | ||
38 | |||
39 | static inline void debug_percpu_counter_activate(struct percpu_counter *fbc) | ||
40 | { | ||
41 | debug_object_init(fbc, &percpu_counter_debug_descr); | ||
42 | debug_object_activate(fbc, &percpu_counter_debug_descr); | ||
43 | } | ||
44 | |||
45 | static inline void debug_percpu_counter_deactivate(struct percpu_counter *fbc) | ||
46 | { | ||
47 | debug_object_deactivate(fbc, &percpu_counter_debug_descr); | ||
48 | debug_object_free(fbc, &percpu_counter_debug_descr); | ||
49 | } | ||
50 | |||
51 | #else /* CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER */ | ||
52 | static inline void debug_percpu_counter_activate(struct percpu_counter *fbc) | ||
53 | { } | ||
54 | static inline void debug_percpu_counter_deactivate(struct percpu_counter *fbc) | ||
55 | { } | ||
56 | #endif /* CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER */ | ||
57 | |||
15 | void percpu_counter_set(struct percpu_counter *fbc, s64 amount) | 58 | void percpu_counter_set(struct percpu_counter *fbc, s64 amount) |
16 | { | 59 | { |
17 | int cpu; | 60 | int cpu; |
@@ -30,9 +73,9 @@ void __percpu_counter_add(struct percpu_counter *fbc, s64 amount, s32 batch) | |||
30 | { | 73 | { |
31 | s64 count; | 74 | s64 count; |
32 | s32 *pcount; | 75 | s32 *pcount; |
33 | int cpu = get_cpu(); | ||
34 | 76 | ||
35 | pcount = per_cpu_ptr(fbc->counters, cpu); | 77 | preempt_disable(); |
78 | pcount = this_cpu_ptr(fbc->counters); | ||
36 | count = *pcount + amount; | 79 | count = *pcount + amount; |
37 | if (count >= batch || count <= -batch) { | 80 | if (count >= batch || count <= -batch) { |
38 | spin_lock(&fbc->lock); | 81 | spin_lock(&fbc->lock); |
@@ -42,7 +85,7 @@ void __percpu_counter_add(struct percpu_counter *fbc, s64 amount, s32 batch) | |||
42 | } else { | 85 | } else { |
43 | *pcount = count; | 86 | *pcount = count; |
44 | } | 87 | } |
45 | put_cpu(); | 88 | preempt_enable(); |
46 | } | 89 | } |
47 | EXPORT_SYMBOL(__percpu_counter_add); | 90 | EXPORT_SYMBOL(__percpu_counter_add); |
48 | 91 | ||
@@ -75,7 +118,11 @@ int __percpu_counter_init(struct percpu_counter *fbc, s64 amount, | |||
75 | fbc->counters = alloc_percpu(s32); | 118 | fbc->counters = alloc_percpu(s32); |
76 | if (!fbc->counters) | 119 | if (!fbc->counters) |
77 | return -ENOMEM; | 120 | return -ENOMEM; |
121 | |||
122 | debug_percpu_counter_activate(fbc); | ||
123 | |||
78 | #ifdef CONFIG_HOTPLUG_CPU | 124 | #ifdef CONFIG_HOTPLUG_CPU |
125 | INIT_LIST_HEAD(&fbc->list); | ||
79 | mutex_lock(&percpu_counters_lock); | 126 | mutex_lock(&percpu_counters_lock); |
80 | list_add(&fbc->list, &percpu_counters); | 127 | list_add(&fbc->list, &percpu_counters); |
81 | mutex_unlock(&percpu_counters_lock); | 128 | mutex_unlock(&percpu_counters_lock); |
@@ -89,6 +136,8 @@ void percpu_counter_destroy(struct percpu_counter *fbc) | |||
89 | if (!fbc->counters) | 136 | if (!fbc->counters) |
90 | return; | 137 | return; |
91 | 138 | ||
139 | debug_percpu_counter_deactivate(fbc); | ||
140 | |||
92 | #ifdef CONFIG_HOTPLUG_CPU | 141 | #ifdef CONFIG_HOTPLUG_CPU |
93 | mutex_lock(&percpu_counters_lock); | 142 | mutex_lock(&percpu_counters_lock); |
94 | list_del(&fbc->list); | 143 | list_del(&fbc->list); |
diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 7af9d841c43b..c150d3dafff4 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c | |||
@@ -988,8 +988,15 @@ static noinline_for_stack | |||
988 | char *pointer(const char *fmt, char *buf, char *end, void *ptr, | 988 | char *pointer(const char *fmt, char *buf, char *end, void *ptr, |
989 | struct printf_spec spec) | 989 | struct printf_spec spec) |
990 | { | 990 | { |
991 | if (!ptr) | 991 | if (!ptr) { |
992 | /* | ||
993 | * Print (null) with the same width as a pointer so it makes | ||
994 | * tabular output look nice. | ||
995 | */ | ||
996 | if (spec.field_width == -1) | ||
997 | spec.field_width = 2 * sizeof(void *); | ||
992 | return string(buf, end, "(null)", spec); | 998 | return string(buf, end, "(null)", spec); |
999 | } | ||
993 | 1000 | ||
994 | switch (*fmt) { | 1001 | switch (*fmt) { |
995 | case 'F': | 1002 | case 'F': |
@@ -1031,7 +1038,7 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr, | |||
1031 | } | 1038 | } |
1032 | spec.flags |= SMALL; | 1039 | spec.flags |= SMALL; |
1033 | if (spec.field_width == -1) { | 1040 | if (spec.field_width == -1) { |
1034 | spec.field_width = 2*sizeof(void *); | 1041 | spec.field_width = 2 * sizeof(void *); |
1035 | spec.flags |= ZEROPAD; | 1042 | spec.flags |= ZEROPAD; |
1036 | } | 1043 | } |
1037 | spec.base = 16; | 1044 | spec.base = 16; |
@@ -1497,7 +1504,7 @@ EXPORT_SYMBOL(snprintf); | |||
1497 | * @...: Arguments for the format string | 1504 | * @...: Arguments for the format string |
1498 | * | 1505 | * |
1499 | * The return value is the number of characters written into @buf not including | 1506 | * The return value is the number of characters written into @buf not including |
1500 | * the trailing '\0'. If @size is <= 0 the function returns 0. | 1507 | * the trailing '\0'. If @size is == 0 the function returns 0. |
1501 | */ | 1508 | */ |
1502 | 1509 | ||
1503 | int scnprintf(char *buf, size_t size, const char *fmt, ...) | 1510 | int scnprintf(char *buf, size_t size, const char *fmt, ...) |
@@ -1509,7 +1516,11 @@ int scnprintf(char *buf, size_t size, const char *fmt, ...) | |||
1509 | i = vsnprintf(buf, size, fmt, args); | 1516 | i = vsnprintf(buf, size, fmt, args); |
1510 | va_end(args); | 1517 | va_end(args); |
1511 | 1518 | ||
1512 | return (i >= size) ? (size - 1) : i; | 1519 | if (likely(i < size)) |
1520 | return i; | ||
1521 | if (size != 0) | ||
1522 | return size - 1; | ||
1523 | return 0; | ||
1513 | } | 1524 | } |
1514 | EXPORT_SYMBOL(scnprintf); | 1525 | EXPORT_SYMBOL(scnprintf); |
1515 | 1526 | ||
diff --git a/mm/backing-dev.c b/mm/backing-dev.c index 65d420499a61..f2eb27884ffa 100644 --- a/mm/backing-dev.c +++ b/mm/backing-dev.c | |||
@@ -362,7 +362,7 @@ static int bdi_forker_thread(void *ptr) | |||
362 | { | 362 | { |
363 | struct bdi_writeback *me = ptr; | 363 | struct bdi_writeback *me = ptr; |
364 | 364 | ||
365 | current->flags |= PF_FLUSHER | PF_SWAPWRITE; | 365 | current->flags |= PF_SWAPWRITE; |
366 | set_freezable(); | 366 | set_freezable(); |
367 | 367 | ||
368 | /* | 368 | /* |
@@ -729,6 +729,7 @@ static wait_queue_head_t congestion_wqh[2] = { | |||
729 | __WAIT_QUEUE_HEAD_INITIALIZER(congestion_wqh[0]), | 729 | __WAIT_QUEUE_HEAD_INITIALIZER(congestion_wqh[0]), |
730 | __WAIT_QUEUE_HEAD_INITIALIZER(congestion_wqh[1]) | 730 | __WAIT_QUEUE_HEAD_INITIALIZER(congestion_wqh[1]) |
731 | }; | 731 | }; |
732 | static atomic_t nr_bdi_congested[2]; | ||
732 | 733 | ||
733 | void clear_bdi_congested(struct backing_dev_info *bdi, int sync) | 734 | void clear_bdi_congested(struct backing_dev_info *bdi, int sync) |
734 | { | 735 | { |
@@ -736,7 +737,8 @@ void clear_bdi_congested(struct backing_dev_info *bdi, int sync) | |||
736 | wait_queue_head_t *wqh = &congestion_wqh[sync]; | 737 | wait_queue_head_t *wqh = &congestion_wqh[sync]; |
737 | 738 | ||
738 | bit = sync ? BDI_sync_congested : BDI_async_congested; | 739 | bit = sync ? BDI_sync_congested : BDI_async_congested; |
739 | clear_bit(bit, &bdi->state); | 740 | if (test_and_clear_bit(bit, &bdi->state)) |
741 | atomic_dec(&nr_bdi_congested[sync]); | ||
740 | smp_mb__after_clear_bit(); | 742 | smp_mb__after_clear_bit(); |
741 | if (waitqueue_active(wqh)) | 743 | if (waitqueue_active(wqh)) |
742 | wake_up(wqh); | 744 | wake_up(wqh); |
@@ -748,7 +750,8 @@ void set_bdi_congested(struct backing_dev_info *bdi, int sync) | |||
748 | enum bdi_state bit; | 750 | enum bdi_state bit; |
749 | 751 | ||
750 | bit = sync ? BDI_sync_congested : BDI_async_congested; | 752 | bit = sync ? BDI_sync_congested : BDI_async_congested; |
751 | set_bit(bit, &bdi->state); | 753 | if (!test_and_set_bit(bit, &bdi->state)) |
754 | atomic_inc(&nr_bdi_congested[sync]); | ||
752 | } | 755 | } |
753 | EXPORT_SYMBOL(set_bdi_congested); | 756 | EXPORT_SYMBOL(set_bdi_congested); |
754 | 757 | ||
@@ -764,13 +767,72 @@ EXPORT_SYMBOL(set_bdi_congested); | |||
764 | long congestion_wait(int sync, long timeout) | 767 | long congestion_wait(int sync, long timeout) |
765 | { | 768 | { |
766 | long ret; | 769 | long ret; |
770 | unsigned long start = jiffies; | ||
767 | DEFINE_WAIT(wait); | 771 | DEFINE_WAIT(wait); |
768 | wait_queue_head_t *wqh = &congestion_wqh[sync]; | 772 | wait_queue_head_t *wqh = &congestion_wqh[sync]; |
769 | 773 | ||
770 | prepare_to_wait(wqh, &wait, TASK_UNINTERRUPTIBLE); | 774 | prepare_to_wait(wqh, &wait, TASK_UNINTERRUPTIBLE); |
771 | ret = io_schedule_timeout(timeout); | 775 | ret = io_schedule_timeout(timeout); |
772 | finish_wait(wqh, &wait); | 776 | finish_wait(wqh, &wait); |
777 | |||
778 | trace_writeback_congestion_wait(jiffies_to_usecs(timeout), | ||
779 | jiffies_to_usecs(jiffies - start)); | ||
780 | |||
773 | return ret; | 781 | return ret; |
774 | } | 782 | } |
775 | EXPORT_SYMBOL(congestion_wait); | 783 | EXPORT_SYMBOL(congestion_wait); |
776 | 784 | ||
785 | /** | ||
786 | * wait_iff_congested - Conditionally wait for a backing_dev to become uncongested or a zone to complete writes | ||
787 | * @zone: A zone to check if it is heavily congested | ||
788 | * @sync: SYNC or ASYNC IO | ||
789 | * @timeout: timeout in jiffies | ||
790 | * | ||
791 | * In the event of a congested backing_dev (any backing_dev) and the given | ||
792 | * @zone has experienced recent congestion, this waits for up to @timeout | ||
793 | * jiffies for either a BDI to exit congestion of the given @sync queue | ||
794 | * or a write to complete. | ||
795 | * | ||
796 | * In the absense of zone congestion, cond_resched() is called to yield | ||
797 | * the processor if necessary but otherwise does not sleep. | ||
798 | * | ||
799 | * The return value is 0 if the sleep is for the full timeout. Otherwise, | ||
800 | * it is the number of jiffies that were still remaining when the function | ||
801 | * returned. return_value == timeout implies the function did not sleep. | ||
802 | */ | ||
803 | long wait_iff_congested(struct zone *zone, int sync, long timeout) | ||
804 | { | ||
805 | long ret; | ||
806 | unsigned long start = jiffies; | ||
807 | DEFINE_WAIT(wait); | ||
808 | wait_queue_head_t *wqh = &congestion_wqh[sync]; | ||
809 | |||
810 | /* | ||
811 | * If there is no congestion, or heavy congestion is not being | ||
812 | * encountered in the current zone, yield if necessary instead | ||
813 | * of sleeping on the congestion queue | ||
814 | */ | ||
815 | if (atomic_read(&nr_bdi_congested[sync]) == 0 || | ||
816 | !zone_is_reclaim_congested(zone)) { | ||
817 | cond_resched(); | ||
818 | |||
819 | /* In case we scheduled, work out time remaining */ | ||
820 | ret = timeout - (jiffies - start); | ||
821 | if (ret < 0) | ||
822 | ret = 0; | ||
823 | |||
824 | goto out; | ||
825 | } | ||
826 | |||
827 | /* Sleep until uncongested or a write happens */ | ||
828 | prepare_to_wait(wqh, &wait, TASK_UNINTERRUPTIBLE); | ||
829 | ret = io_schedule_timeout(timeout); | ||
830 | finish_wait(wqh, &wait); | ||
831 | |||
832 | out: | ||
833 | trace_writeback_wait_iff_congested(jiffies_to_usecs(timeout), | ||
834 | jiffies_to_usecs(jiffies - start)); | ||
835 | |||
836 | return ret; | ||
837 | } | ||
838 | EXPORT_SYMBOL(wait_iff_congested); | ||
diff --git a/mm/dmapool.c b/mm/dmapool.c index 3df063706f53..4df2de77e069 100644 --- a/mm/dmapool.c +++ b/mm/dmapool.c | |||
@@ -311,6 +311,8 @@ void *dma_pool_alloc(struct dma_pool *pool, gfp_t mem_flags, | |||
311 | size_t offset; | 311 | size_t offset; |
312 | void *retval; | 312 | void *retval; |
313 | 313 | ||
314 | might_sleep_if(mem_flags & __GFP_WAIT); | ||
315 | |||
314 | spin_lock_irqsave(&pool->lock, flags); | 316 | spin_lock_irqsave(&pool->lock, flags); |
315 | restart: | 317 | restart: |
316 | list_for_each_entry(page, &pool->page_list, page_list) { | 318 | list_for_each_entry(page, &pool->page_list, page_list) { |
diff --git a/mm/filemap.c b/mm/filemap.c index 3d4df44e4221..75572b5f2374 100644 --- a/mm/filemap.c +++ b/mm/filemap.c | |||
@@ -612,6 +612,19 @@ void __lock_page_nosync(struct page *page) | |||
612 | TASK_UNINTERRUPTIBLE); | 612 | TASK_UNINTERRUPTIBLE); |
613 | } | 613 | } |
614 | 614 | ||
615 | int __lock_page_or_retry(struct page *page, struct mm_struct *mm, | ||
616 | unsigned int flags) | ||
617 | { | ||
618 | if (!(flags & FAULT_FLAG_ALLOW_RETRY)) { | ||
619 | __lock_page(page); | ||
620 | return 1; | ||
621 | } else { | ||
622 | up_read(&mm->mmap_sem); | ||
623 | wait_on_page_locked(page); | ||
624 | return 0; | ||
625 | } | ||
626 | } | ||
627 | |||
615 | /** | 628 | /** |
616 | * find_get_page - find and get a page reference | 629 | * find_get_page - find and get a page reference |
617 | * @mapping: the address_space to search | 630 | * @mapping: the address_space to search |
@@ -1539,25 +1552,28 @@ int filemap_fault(struct vm_area_struct *vma, struct vm_fault *vmf) | |||
1539 | * waiting for the lock. | 1552 | * waiting for the lock. |
1540 | */ | 1553 | */ |
1541 | do_async_mmap_readahead(vma, ra, file, page, offset); | 1554 | do_async_mmap_readahead(vma, ra, file, page, offset); |
1542 | lock_page(page); | ||
1543 | |||
1544 | /* Did it get truncated? */ | ||
1545 | if (unlikely(page->mapping != mapping)) { | ||
1546 | unlock_page(page); | ||
1547 | put_page(page); | ||
1548 | goto no_cached_page; | ||
1549 | } | ||
1550 | } else { | 1555 | } else { |
1551 | /* No page in the page cache at all */ | 1556 | /* No page in the page cache at all */ |
1552 | do_sync_mmap_readahead(vma, ra, file, offset); | 1557 | do_sync_mmap_readahead(vma, ra, file, offset); |
1553 | count_vm_event(PGMAJFAULT); | 1558 | count_vm_event(PGMAJFAULT); |
1554 | ret = VM_FAULT_MAJOR; | 1559 | ret = VM_FAULT_MAJOR; |
1555 | retry_find: | 1560 | retry_find: |
1556 | page = find_lock_page(mapping, offset); | 1561 | page = find_get_page(mapping, offset); |
1557 | if (!page) | 1562 | if (!page) |
1558 | goto no_cached_page; | 1563 | goto no_cached_page; |
1559 | } | 1564 | } |
1560 | 1565 | ||
1566 | if (!lock_page_or_retry(page, vma->vm_mm, vmf->flags)) | ||
1567 | return ret | VM_FAULT_RETRY; | ||
1568 | |||
1569 | /* Did it get truncated? */ | ||
1570 | if (unlikely(page->mapping != mapping)) { | ||
1571 | unlock_page(page); | ||
1572 | put_page(page); | ||
1573 | goto retry_find; | ||
1574 | } | ||
1575 | VM_BUG_ON(page->index != offset); | ||
1576 | |||
1561 | /* | 1577 | /* |
1562 | * We have a locked page in the page cache, now we need to check | 1578 | * We have a locked page in the page cache, now we need to check |
1563 | * that it's up-to-date. If not, it is going to be due to an error. | 1579 | * that it's up-to-date. If not, it is going to be due to an error. |
@@ -2177,12 +2193,12 @@ generic_file_direct_write(struct kiocb *iocb, const struct iovec *iov, | |||
2177 | } | 2193 | } |
2178 | 2194 | ||
2179 | if (written > 0) { | 2195 | if (written > 0) { |
2180 | loff_t end = pos + written; | 2196 | pos += written; |
2181 | if (end > i_size_read(inode) && !S_ISBLK(inode->i_mode)) { | 2197 | if (pos > i_size_read(inode) && !S_ISBLK(inode->i_mode)) { |
2182 | i_size_write(inode, end); | 2198 | i_size_write(inode, pos); |
2183 | mark_inode_dirty(inode); | 2199 | mark_inode_dirty(inode); |
2184 | } | 2200 | } |
2185 | *ppos = end; | 2201 | *ppos = pos; |
2186 | } | 2202 | } |
2187 | out: | 2203 | out: |
2188 | return written; | 2204 | return written; |
diff --git a/mm/highmem.c b/mm/highmem.c index 7a0aa1be4993..781e754a75ac 100644 --- a/mm/highmem.c +++ b/mm/highmem.c | |||
@@ -42,6 +42,10 @@ | |||
42 | unsigned long totalhigh_pages __read_mostly; | 42 | unsigned long totalhigh_pages __read_mostly; |
43 | EXPORT_SYMBOL(totalhigh_pages); | 43 | EXPORT_SYMBOL(totalhigh_pages); |
44 | 44 | ||
45 | |||
46 | DEFINE_PER_CPU(int, __kmap_atomic_idx); | ||
47 | EXPORT_PER_CPU_SYMBOL(__kmap_atomic_idx); | ||
48 | |||
45 | unsigned int nr_free_highpages (void) | 49 | unsigned int nr_free_highpages (void) |
46 | { | 50 | { |
47 | pg_data_t *pgdat; | 51 | pg_data_t *pgdat; |
@@ -422,61 +426,3 @@ void __init page_address_init(void) | |||
422 | } | 426 | } |
423 | 427 | ||
424 | #endif /* defined(CONFIG_HIGHMEM) && !defined(WANT_PAGE_VIRTUAL) */ | 428 | #endif /* defined(CONFIG_HIGHMEM) && !defined(WANT_PAGE_VIRTUAL) */ |
425 | |||
426 | #ifdef CONFIG_DEBUG_HIGHMEM | ||
427 | |||
428 | void debug_kmap_atomic(enum km_type type) | ||
429 | { | ||
430 | static int warn_count = 10; | ||
431 | |||
432 | if (unlikely(warn_count < 0)) | ||
433 | return; | ||
434 | |||
435 | if (unlikely(in_interrupt())) { | ||
436 | if (in_nmi()) { | ||
437 | if (type != KM_NMI && type != KM_NMI_PTE) { | ||
438 | WARN_ON(1); | ||
439 | warn_count--; | ||
440 | } | ||
441 | } else if (in_irq()) { | ||
442 | if (type != KM_IRQ0 && type != KM_IRQ1 && | ||
443 | type != KM_BIO_SRC_IRQ && type != KM_BIO_DST_IRQ && | ||
444 | type != KM_BOUNCE_READ && type != KM_IRQ_PTE) { | ||
445 | WARN_ON(1); | ||
446 | warn_count--; | ||
447 | } | ||
448 | } else if (!irqs_disabled()) { /* softirq */ | ||
449 | if (type != KM_IRQ0 && type != KM_IRQ1 && | ||
450 | type != KM_SOFTIRQ0 && type != KM_SOFTIRQ1 && | ||
451 | type != KM_SKB_SUNRPC_DATA && | ||
452 | type != KM_SKB_DATA_SOFTIRQ && | ||
453 | type != KM_BOUNCE_READ) { | ||
454 | WARN_ON(1); | ||
455 | warn_count--; | ||
456 | } | ||
457 | } | ||
458 | } | ||
459 | |||
460 | if (type == KM_IRQ0 || type == KM_IRQ1 || type == KM_BOUNCE_READ || | ||
461 | type == KM_BIO_SRC_IRQ || type == KM_BIO_DST_IRQ || | ||
462 | type == KM_IRQ_PTE || type == KM_NMI || | ||
463 | type == KM_NMI_PTE ) { | ||
464 | if (!irqs_disabled()) { | ||
465 | WARN_ON(1); | ||
466 | warn_count--; | ||
467 | } | ||
468 | } else if (type == KM_SOFTIRQ0 || type == KM_SOFTIRQ1) { | ||
469 | if (irq_count() == 0 && !irqs_disabled()) { | ||
470 | WARN_ON(1); | ||
471 | warn_count--; | ||
472 | } | ||
473 | } | ||
474 | #ifdef CONFIG_KGDB_KDB | ||
475 | if (unlikely(type == KM_KDB && atomic_read(&kgdb_active) == -1)) { | ||
476 | WARN_ON(1); | ||
477 | warn_count--; | ||
478 | } | ||
479 | #endif /* CONFIG_KGDB_KDB */ | ||
480 | } | ||
481 | |||
482 | #endif | ||
diff --git a/mm/hugetlb.c b/mm/hugetlb.c index 96991ded82fe..c4a3558589ab 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c | |||
@@ -2448,8 +2448,11 @@ retry_avoidcopy: | |||
2448 | * When the original hugepage is shared one, it does not have | 2448 | * When the original hugepage is shared one, it does not have |
2449 | * anon_vma prepared. | 2449 | * anon_vma prepared. |
2450 | */ | 2450 | */ |
2451 | if (unlikely(anon_vma_prepare(vma))) | 2451 | if (unlikely(anon_vma_prepare(vma))) { |
2452 | /* Caller expects lock to be held */ | ||
2453 | spin_lock(&mm->page_table_lock); | ||
2452 | return VM_FAULT_OOM; | 2454 | return VM_FAULT_OOM; |
2455 | } | ||
2453 | 2456 | ||
2454 | copy_user_huge_page(new_page, old_page, address, vma); | 2457 | copy_user_huge_page(new_page, old_page, address, vma); |
2455 | __SetPageUptodate(new_page); | 2458 | __SetPageUptodate(new_page); |
diff --git a/mm/internal.h b/mm/internal.h index 6a697bb97fc5..dedb0aff673f 100644 --- a/mm/internal.h +++ b/mm/internal.h | |||
@@ -62,7 +62,7 @@ extern bool is_free_buddy_page(struct page *page); | |||
62 | */ | 62 | */ |
63 | static inline unsigned long page_order(struct page *page) | 63 | static inline unsigned long page_order(struct page *page) |
64 | { | 64 | { |
65 | VM_BUG_ON(!PageBuddy(page)); | 65 | /* PageBuddy() must be checked by the caller */ |
66 | return page_private(page); | 66 | return page_private(page); |
67 | } | 67 | } |
68 | 68 | ||
diff --git a/mm/memory-failure.c b/mm/memory-failure.c index 44a8cefeae6e..124324134ff6 100644 --- a/mm/memory-failure.c +++ b/mm/memory-failure.c | |||
@@ -1292,6 +1292,7 @@ static int soft_offline_huge_page(struct page *page, int flags) | |||
1292 | list_add(&hpage->lru, &pagelist); | 1292 | list_add(&hpage->lru, &pagelist); |
1293 | ret = migrate_huge_pages(&pagelist, new_page, MPOL_MF_MOVE_ALL, 0); | 1293 | ret = migrate_huge_pages(&pagelist, new_page, MPOL_MF_MOVE_ALL, 0); |
1294 | if (ret) { | 1294 | if (ret) { |
1295 | putback_lru_pages(&pagelist); | ||
1295 | pr_debug("soft offline: %#lx: migration failed %d, type %lx\n", | 1296 | pr_debug("soft offline: %#lx: migration failed %d, type %lx\n", |
1296 | pfn, ret, page->flags); | 1297 | pfn, ret, page->flags); |
1297 | if (ret > 0) | 1298 | if (ret > 0) |
diff --git a/mm/memory.c b/mm/memory.c index af82741caaa4..02e48aa0ed13 100644 --- a/mm/memory.c +++ b/mm/memory.c | |||
@@ -736,7 +736,7 @@ again: | |||
736 | dst_pte = pte_alloc_map_lock(dst_mm, dst_pmd, addr, &dst_ptl); | 736 | dst_pte = pte_alloc_map_lock(dst_mm, dst_pmd, addr, &dst_ptl); |
737 | if (!dst_pte) | 737 | if (!dst_pte) |
738 | return -ENOMEM; | 738 | return -ENOMEM; |
739 | src_pte = pte_offset_map_nested(src_pmd, addr); | 739 | src_pte = pte_offset_map(src_pmd, addr); |
740 | src_ptl = pte_lockptr(src_mm, src_pmd); | 740 | src_ptl = pte_lockptr(src_mm, src_pmd); |
741 | spin_lock_nested(src_ptl, SINGLE_DEPTH_NESTING); | 741 | spin_lock_nested(src_ptl, SINGLE_DEPTH_NESTING); |
742 | orig_src_pte = src_pte; | 742 | orig_src_pte = src_pte; |
@@ -767,7 +767,7 @@ again: | |||
767 | 767 | ||
768 | arch_leave_lazy_mmu_mode(); | 768 | arch_leave_lazy_mmu_mode(); |
769 | spin_unlock(src_ptl); | 769 | spin_unlock(src_ptl); |
770 | pte_unmap_nested(orig_src_pte); | 770 | pte_unmap(orig_src_pte); |
771 | add_mm_rss_vec(dst_mm, rss); | 771 | add_mm_rss_vec(dst_mm, rss); |
772 | pte_unmap_unlock(orig_dst_pte, dst_ptl); | 772 | pte_unmap_unlock(orig_dst_pte, dst_ptl); |
773 | cond_resched(); | 773 | cond_resched(); |
@@ -1591,7 +1591,7 @@ struct page *get_dump_page(unsigned long addr) | |||
1591 | } | 1591 | } |
1592 | #endif /* CONFIG_ELF_CORE */ | 1592 | #endif /* CONFIG_ELF_CORE */ |
1593 | 1593 | ||
1594 | pte_t *get_locked_pte(struct mm_struct *mm, unsigned long addr, | 1594 | pte_t *__get_locked_pte(struct mm_struct *mm, unsigned long addr, |
1595 | spinlock_t **ptl) | 1595 | spinlock_t **ptl) |
1596 | { | 1596 | { |
1597 | pgd_t * pgd = pgd_offset(mm, addr); | 1597 | pgd_t * pgd = pgd_offset(mm, addr); |
@@ -2080,7 +2080,7 @@ static inline void cow_user_page(struct page *dst, struct page *src, unsigned lo | |||
2080 | * zeroes. | 2080 | * zeroes. |
2081 | */ | 2081 | */ |
2082 | if (__copy_from_user_inatomic(kaddr, uaddr, PAGE_SIZE)) | 2082 | if (__copy_from_user_inatomic(kaddr, uaddr, PAGE_SIZE)) |
2083 | memset(kaddr, 0, PAGE_SIZE); | 2083 | clear_page(kaddr); |
2084 | kunmap_atomic(kaddr, KM_USER0); | 2084 | kunmap_atomic(kaddr, KM_USER0); |
2085 | flush_dcache_page(dst); | 2085 | flush_dcache_page(dst); |
2086 | } else | 2086 | } else |
@@ -2108,6 +2108,7 @@ static inline void cow_user_page(struct page *dst, struct page *src, unsigned lo | |||
2108 | static int do_wp_page(struct mm_struct *mm, struct vm_area_struct *vma, | 2108 | static int do_wp_page(struct mm_struct *mm, struct vm_area_struct *vma, |
2109 | unsigned long address, pte_t *page_table, pmd_t *pmd, | 2109 | unsigned long address, pte_t *page_table, pmd_t *pmd, |
2110 | spinlock_t *ptl, pte_t orig_pte) | 2110 | spinlock_t *ptl, pte_t orig_pte) |
2111 | __releases(ptl) | ||
2111 | { | 2112 | { |
2112 | struct page *old_page, *new_page; | 2113 | struct page *old_page, *new_page; |
2113 | pte_t entry; | 2114 | pte_t entry; |
@@ -2627,6 +2628,7 @@ static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma, | |||
2627 | struct page *page, *swapcache = NULL; | 2628 | struct page *page, *swapcache = NULL; |
2628 | swp_entry_t entry; | 2629 | swp_entry_t entry; |
2629 | pte_t pte; | 2630 | pte_t pte; |
2631 | int locked; | ||
2630 | struct mem_cgroup *ptr = NULL; | 2632 | struct mem_cgroup *ptr = NULL; |
2631 | int exclusive = 0; | 2633 | int exclusive = 0; |
2632 | int ret = 0; | 2634 | int ret = 0; |
@@ -2677,8 +2679,12 @@ static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma, | |||
2677 | goto out_release; | 2679 | goto out_release; |
2678 | } | 2680 | } |
2679 | 2681 | ||
2680 | lock_page(page); | 2682 | locked = lock_page_or_retry(page, mm, flags); |
2681 | delayacct_clear_flag(DELAYACCT_PF_SWAPIN); | 2683 | delayacct_clear_flag(DELAYACCT_PF_SWAPIN); |
2684 | if (!locked) { | ||
2685 | ret |= VM_FAULT_RETRY; | ||
2686 | goto out_release; | ||
2687 | } | ||
2682 | 2688 | ||
2683 | /* | 2689 | /* |
2684 | * Make sure try_to_free_swap or reuse_swap_page or swapoff did not | 2690 | * Make sure try_to_free_swap or reuse_swap_page or swapoff did not |
@@ -2927,7 +2933,8 @@ static int __do_fault(struct mm_struct *mm, struct vm_area_struct *vma, | |||
2927 | vmf.page = NULL; | 2933 | vmf.page = NULL; |
2928 | 2934 | ||
2929 | ret = vma->vm_ops->fault(vma, &vmf); | 2935 | ret = vma->vm_ops->fault(vma, &vmf); |
2930 | if (unlikely(ret & (VM_FAULT_ERROR | VM_FAULT_NOPAGE))) | 2936 | if (unlikely(ret & (VM_FAULT_ERROR | VM_FAULT_NOPAGE | |
2937 | VM_FAULT_RETRY))) | ||
2931 | return ret; | 2938 | return ret; |
2932 | 2939 | ||
2933 | if (unlikely(PageHWPoison(vmf.page))) { | 2940 | if (unlikely(PageHWPoison(vmf.page))) { |
@@ -3344,7 +3351,7 @@ int in_gate_area_no_task(unsigned long addr) | |||
3344 | 3351 | ||
3345 | #endif /* __HAVE_ARCH_GATE_AREA */ | 3352 | #endif /* __HAVE_ARCH_GATE_AREA */ |
3346 | 3353 | ||
3347 | static int follow_pte(struct mm_struct *mm, unsigned long address, | 3354 | static int __follow_pte(struct mm_struct *mm, unsigned long address, |
3348 | pte_t **ptepp, spinlock_t **ptlp) | 3355 | pte_t **ptepp, spinlock_t **ptlp) |
3349 | { | 3356 | { |
3350 | pgd_t *pgd; | 3357 | pgd_t *pgd; |
@@ -3381,6 +3388,17 @@ out: | |||
3381 | return -EINVAL; | 3388 | return -EINVAL; |
3382 | } | 3389 | } |
3383 | 3390 | ||
3391 | static inline int follow_pte(struct mm_struct *mm, unsigned long address, | ||
3392 | pte_t **ptepp, spinlock_t **ptlp) | ||
3393 | { | ||
3394 | int res; | ||
3395 | |||
3396 | /* (void) is needed to make gcc happy */ | ||
3397 | (void) __cond_lock(*ptlp, | ||
3398 | !(res = __follow_pte(mm, address, ptepp, ptlp))); | ||
3399 | return res; | ||
3400 | } | ||
3401 | |||
3384 | /** | 3402 | /** |
3385 | * follow_pfn - look up PFN at a user virtual address | 3403 | * follow_pfn - look up PFN at a user virtual address |
3386 | * @vma: memory mapping | 3404 | * @vma: memory mapping |
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c index d4e940a26945..9260314a221e 100644 --- a/mm/memory_hotplug.c +++ b/mm/memory_hotplug.c | |||
@@ -602,27 +602,14 @@ static struct page *next_active_pageblock(struct page *page) | |||
602 | /* Checks if this range of memory is likely to be hot-removable. */ | 602 | /* Checks if this range of memory is likely to be hot-removable. */ |
603 | int is_mem_section_removable(unsigned long start_pfn, unsigned long nr_pages) | 603 | int is_mem_section_removable(unsigned long start_pfn, unsigned long nr_pages) |
604 | { | 604 | { |
605 | int type; | ||
606 | struct page *page = pfn_to_page(start_pfn); | 605 | struct page *page = pfn_to_page(start_pfn); |
607 | struct page *end_page = page + nr_pages; | 606 | struct page *end_page = page + nr_pages; |
608 | 607 | ||
609 | /* Check the starting page of each pageblock within the range */ | 608 | /* Check the starting page of each pageblock within the range */ |
610 | for (; page < end_page; page = next_active_pageblock(page)) { | 609 | for (; page < end_page; page = next_active_pageblock(page)) { |
611 | type = get_pageblock_migratetype(page); | 610 | if (!is_pageblock_removable_nolock(page)) |
612 | |||
613 | /* | ||
614 | * A pageblock containing MOVABLE or free pages is considered | ||
615 | * removable | ||
616 | */ | ||
617 | if (type != MIGRATE_MOVABLE && !pageblock_free(page)) | ||
618 | return 0; | ||
619 | |||
620 | /* | ||
621 | * A pageblock starting with a PageReserved page is not | ||
622 | * considered removable. | ||
623 | */ | ||
624 | if (PageReserved(page)) | ||
625 | return 0; | 611 | return 0; |
612 | cond_resched(); | ||
626 | } | 613 | } |
627 | 614 | ||
628 | /* All pageblocks in the memory block are likely to be hot-removable */ | 615 | /* All pageblocks in the memory block are likely to be hot-removable */ |
@@ -659,7 +646,7 @@ static int test_pages_in_a_zone(unsigned long start_pfn, unsigned long end_pfn) | |||
659 | * Scanning pfn is much easier than scanning lru list. | 646 | * Scanning pfn is much easier than scanning lru list. |
660 | * Scan pfn from start to end and Find LRU page. | 647 | * Scan pfn from start to end and Find LRU page. |
661 | */ | 648 | */ |
662 | int scan_lru_pages(unsigned long start, unsigned long end) | 649 | static unsigned long scan_lru_pages(unsigned long start, unsigned long end) |
663 | { | 650 | { |
664 | unsigned long pfn; | 651 | unsigned long pfn; |
665 | struct page *page; | 652 | struct page *page; |
@@ -709,29 +696,30 @@ do_migrate_range(unsigned long start_pfn, unsigned long end_pfn) | |||
709 | page_is_file_cache(page)); | 696 | page_is_file_cache(page)); |
710 | 697 | ||
711 | } else { | 698 | } else { |
712 | /* Becasue we don't have big zone->lock. we should | ||
713 | check this again here. */ | ||
714 | if (page_count(page)) | ||
715 | not_managed++; | ||
716 | #ifdef CONFIG_DEBUG_VM | 699 | #ifdef CONFIG_DEBUG_VM |
717 | printk(KERN_ALERT "removing pfn %lx from LRU failed\n", | 700 | printk(KERN_ALERT "removing pfn %lx from LRU failed\n", |
718 | pfn); | 701 | pfn); |
719 | dump_page(page); | 702 | dump_page(page); |
720 | #endif | 703 | #endif |
704 | /* Becasue we don't have big zone->lock. we should | ||
705 | check this again here. */ | ||
706 | if (page_count(page)) { | ||
707 | not_managed++; | ||
708 | ret = -EBUSY; | ||
709 | break; | ||
710 | } | ||
721 | } | 711 | } |
722 | } | 712 | } |
723 | ret = -EBUSY; | 713 | if (!list_empty(&source)) { |
724 | if (not_managed) { | 714 | if (not_managed) { |
725 | if (!list_empty(&source)) | 715 | putback_lru_pages(&source); |
716 | goto out; | ||
717 | } | ||
718 | /* this function returns # of failed pages */ | ||
719 | ret = migrate_pages(&source, hotremove_migrate_alloc, 0, 1); | ||
720 | if (ret) | ||
726 | putback_lru_pages(&source); | 721 | putback_lru_pages(&source); |
727 | goto out; | ||
728 | } | 722 | } |
729 | ret = 0; | ||
730 | if (list_empty(&source)) | ||
731 | goto out; | ||
732 | /* this function returns # of failed pages */ | ||
733 | ret = migrate_pages(&source, hotremove_migrate_alloc, 0, 1); | ||
734 | |||
735 | out: | 723 | out: |
736 | return ret; | 724 | return ret; |
737 | } | 725 | } |
diff --git a/mm/mempolicy.c b/mm/mempolicy.c index f969da5dd8a2..81a127643aea 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c | |||
@@ -924,15 +924,21 @@ static int migrate_to_node(struct mm_struct *mm, int source, int dest, | |||
924 | nodemask_t nmask; | 924 | nodemask_t nmask; |
925 | LIST_HEAD(pagelist); | 925 | LIST_HEAD(pagelist); |
926 | int err = 0; | 926 | int err = 0; |
927 | struct vm_area_struct *vma; | ||
927 | 928 | ||
928 | nodes_clear(nmask); | 929 | nodes_clear(nmask); |
929 | node_set(source, nmask); | 930 | node_set(source, nmask); |
930 | 931 | ||
931 | check_range(mm, mm->mmap->vm_start, mm->task_size, &nmask, | 932 | vma = check_range(mm, mm->mmap->vm_start, mm->task_size, &nmask, |
932 | flags | MPOL_MF_DISCONTIG_OK, &pagelist); | 933 | flags | MPOL_MF_DISCONTIG_OK, &pagelist); |
934 | if (IS_ERR(vma)) | ||
935 | return PTR_ERR(vma); | ||
933 | 936 | ||
934 | if (!list_empty(&pagelist)) | 937 | if (!list_empty(&pagelist)) { |
935 | err = migrate_pages(&pagelist, new_node_page, dest, 0); | 938 | err = migrate_pages(&pagelist, new_node_page, dest, 0); |
939 | if (err) | ||
940 | putback_lru_pages(&pagelist); | ||
941 | } | ||
936 | 942 | ||
937 | return err; | 943 | return err; |
938 | } | 944 | } |
@@ -1147,9 +1153,12 @@ static long do_mbind(unsigned long start, unsigned long len, | |||
1147 | 1153 | ||
1148 | err = mbind_range(mm, start, end, new); | 1154 | err = mbind_range(mm, start, end, new); |
1149 | 1155 | ||
1150 | if (!list_empty(&pagelist)) | 1156 | if (!list_empty(&pagelist)) { |
1151 | nr_failed = migrate_pages(&pagelist, new_vma_page, | 1157 | nr_failed = migrate_pages(&pagelist, new_vma_page, |
1152 | (unsigned long)vma, 0); | 1158 | (unsigned long)vma, 0); |
1159 | if (nr_failed) | ||
1160 | putback_lru_pages(&pagelist); | ||
1161 | } | ||
1153 | 1162 | ||
1154 | if (!err && nr_failed && (flags & MPOL_MF_STRICT)) | 1163 | if (!err && nr_failed && (flags & MPOL_MF_STRICT)) |
1155 | err = -EIO; | 1164 | err = -EIO; |
diff --git a/mm/migrate.c b/mm/migrate.c index f8c9bccf2520..fe5a3c6a5426 100644 --- a/mm/migrate.c +++ b/mm/migrate.c | |||
@@ -497,7 +497,6 @@ static int writeout(struct address_space *mapping, struct page *page) | |||
497 | .nr_to_write = 1, | 497 | .nr_to_write = 1, |
498 | .range_start = 0, | 498 | .range_start = 0, |
499 | .range_end = LLONG_MAX, | 499 | .range_end = LLONG_MAX, |
500 | .nonblocking = 1, | ||
501 | .for_reclaim = 1 | 500 | .for_reclaim = 1 |
502 | }; | 501 | }; |
503 | int rc; | 502 | int rc; |
@@ -884,8 +883,9 @@ out: | |||
884 | * | 883 | * |
885 | * The function returns after 10 attempts or if no pages | 884 | * The function returns after 10 attempts or if no pages |
886 | * are movable anymore because to has become empty | 885 | * are movable anymore because to has become empty |
887 | * or no retryable pages exist anymore. All pages will be | 886 | * or no retryable pages exist anymore. |
888 | * returned to the LRU or freed. | 887 | * Caller should call putback_lru_pages to return pages to the LRU |
888 | * or free list. | ||
889 | * | 889 | * |
890 | * Return: Number of pages not migrated or error code. | 890 | * Return: Number of pages not migrated or error code. |
891 | */ | 891 | */ |
@@ -932,8 +932,6 @@ out: | |||
932 | if (!swapwrite) | 932 | if (!swapwrite) |
933 | current->flags &= ~PF_SWAPWRITE; | 933 | current->flags &= ~PF_SWAPWRITE; |
934 | 934 | ||
935 | putback_lru_pages(from); | ||
936 | |||
937 | if (rc) | 935 | if (rc) |
938 | return rc; | 936 | return rc; |
939 | 937 | ||
@@ -1039,7 +1037,7 @@ static int do_move_page_to_node_array(struct mm_struct *mm, | |||
1039 | 1037 | ||
1040 | err = -EFAULT; | 1038 | err = -EFAULT; |
1041 | vma = find_vma(mm, pp->addr); | 1039 | vma = find_vma(mm, pp->addr); |
1042 | if (!vma || !vma_migratable(vma)) | 1040 | if (!vma || pp->addr < vma->vm_start || !vma_migratable(vma)) |
1043 | goto set_status; | 1041 | goto set_status; |
1044 | 1042 | ||
1045 | page = follow_page(vma, pp->addr, FOLL_GET); | 1043 | page = follow_page(vma, pp->addr, FOLL_GET); |
@@ -1088,9 +1086,12 @@ set_status: | |||
1088 | } | 1086 | } |
1089 | 1087 | ||
1090 | err = 0; | 1088 | err = 0; |
1091 | if (!list_empty(&pagelist)) | 1089 | if (!list_empty(&pagelist)) { |
1092 | err = migrate_pages(&pagelist, new_page_node, | 1090 | err = migrate_pages(&pagelist, new_page_node, |
1093 | (unsigned long)pm, 0); | 1091 | (unsigned long)pm, 0); |
1092 | if (err) | ||
1093 | putback_lru_pages(&pagelist); | ||
1094 | } | ||
1094 | 1095 | ||
1095 | up_read(&mm->mmap_sem); | 1096 | up_read(&mm->mmap_sem); |
1096 | return err; | 1097 | return err; |
@@ -1203,7 +1204,7 @@ static void do_pages_stat_array(struct mm_struct *mm, unsigned long nr_pages, | |||
1203 | int err = -EFAULT; | 1204 | int err = -EFAULT; |
1204 | 1205 | ||
1205 | vma = find_vma(mm, addr); | 1206 | vma = find_vma(mm, addr); |
1206 | if (!vma) | 1207 | if (!vma || addr < vma->vm_start) |
1207 | goto set_status; | 1208 | goto set_status; |
1208 | 1209 | ||
1209 | page = follow_page(vma, addr, 0); | 1210 | page = follow_page(vma, addr, 0); |
diff --git a/mm/mremap.c b/mm/mremap.c index cde56ee51ef7..563fbdd6293a 100644 --- a/mm/mremap.c +++ b/mm/mremap.c | |||
@@ -101,7 +101,7 @@ static void move_ptes(struct vm_area_struct *vma, pmd_t *old_pmd, | |||
101 | * pte locks because exclusive mmap_sem prevents deadlock. | 101 | * pte locks because exclusive mmap_sem prevents deadlock. |
102 | */ | 102 | */ |
103 | old_pte = pte_offset_map_lock(mm, old_pmd, old_addr, &old_ptl); | 103 | old_pte = pte_offset_map_lock(mm, old_pmd, old_addr, &old_ptl); |
104 | new_pte = pte_offset_map_nested(new_pmd, new_addr); | 104 | new_pte = pte_offset_map(new_pmd, new_addr); |
105 | new_ptl = pte_lockptr(mm, new_pmd); | 105 | new_ptl = pte_lockptr(mm, new_pmd); |
106 | if (new_ptl != old_ptl) | 106 | if (new_ptl != old_ptl) |
107 | spin_lock_nested(new_ptl, SINGLE_DEPTH_NESTING); | 107 | spin_lock_nested(new_ptl, SINGLE_DEPTH_NESTING); |
@@ -119,7 +119,7 @@ static void move_ptes(struct vm_area_struct *vma, pmd_t *old_pmd, | |||
119 | arch_leave_lazy_mmu_mode(); | 119 | arch_leave_lazy_mmu_mode(); |
120 | if (new_ptl != old_ptl) | 120 | if (new_ptl != old_ptl) |
121 | spin_unlock(new_ptl); | 121 | spin_unlock(new_ptl); |
122 | pte_unmap_nested(new_pte - 1); | 122 | pte_unmap(new_pte - 1); |
123 | pte_unmap_unlock(old_pte - 1, old_ptl); | 123 | pte_unmap_unlock(old_pte - 1, old_ptl); |
124 | if (mapping) | 124 | if (mapping) |
125 | spin_unlock(&mapping->i_mmap_lock); | 125 | spin_unlock(&mapping->i_mmap_lock); |
diff --git a/mm/nommu.c b/mm/nommu.c index 88ff091eb07a..30b5c20eec15 100644 --- a/mm/nommu.c +++ b/mm/nommu.c | |||
@@ -293,11 +293,58 @@ void *vmalloc(unsigned long size) | |||
293 | } | 293 | } |
294 | EXPORT_SYMBOL(vmalloc); | 294 | EXPORT_SYMBOL(vmalloc); |
295 | 295 | ||
296 | /* | ||
297 | * vzalloc - allocate virtually continguos memory with zero fill | ||
298 | * | ||
299 | * @size: allocation size | ||
300 | * | ||
301 | * Allocate enough pages to cover @size from the page level | ||
302 | * allocator and map them into continguos kernel virtual space. | ||
303 | * The memory allocated is set to zero. | ||
304 | * | ||
305 | * For tight control over page level allocator and protection flags | ||
306 | * use __vmalloc() instead. | ||
307 | */ | ||
308 | void *vzalloc(unsigned long size) | ||
309 | { | ||
310 | return __vmalloc(size, GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO, | ||
311 | PAGE_KERNEL); | ||
312 | } | ||
313 | EXPORT_SYMBOL(vzalloc); | ||
314 | |||
315 | /** | ||
316 | * vmalloc_node - allocate memory on a specific node | ||
317 | * @size: allocation size | ||
318 | * @node: numa node | ||
319 | * | ||
320 | * Allocate enough pages to cover @size from the page level | ||
321 | * allocator and map them into contiguous kernel virtual space. | ||
322 | * | ||
323 | * For tight control over page level allocator and protection flags | ||
324 | * use __vmalloc() instead. | ||
325 | */ | ||
296 | void *vmalloc_node(unsigned long size, int node) | 326 | void *vmalloc_node(unsigned long size, int node) |
297 | { | 327 | { |
298 | return vmalloc(size); | 328 | return vmalloc(size); |
299 | } | 329 | } |
300 | EXPORT_SYMBOL(vmalloc_node); | 330 | |
331 | /** | ||
332 | * vzalloc_node - allocate memory on a specific node with zero fill | ||
333 | * @size: allocation size | ||
334 | * @node: numa node | ||
335 | * | ||
336 | * Allocate enough pages to cover @size from the page level | ||
337 | * allocator and map them into contiguous kernel virtual space. | ||
338 | * The memory allocated is set to zero. | ||
339 | * | ||
340 | * For tight control over page level allocator and protection flags | ||
341 | * use __vmalloc() instead. | ||
342 | */ | ||
343 | void *vzalloc_node(unsigned long size, int node) | ||
344 | { | ||
345 | return vzalloc(size); | ||
346 | } | ||
347 | EXPORT_SYMBOL(vzalloc_node); | ||
301 | 348 | ||
302 | #ifndef PAGE_KERNEL_EXEC | 349 | #ifndef PAGE_KERNEL_EXEC |
303 | # define PAGE_KERNEL_EXEC PAGE_KERNEL | 350 | # define PAGE_KERNEL_EXEC PAGE_KERNEL |
diff --git a/mm/oom_kill.c b/mm/oom_kill.c index 4029583a1024..7dcca55ede7c 100644 --- a/mm/oom_kill.c +++ b/mm/oom_kill.c | |||
@@ -162,10 +162,11 @@ unsigned int oom_badness(struct task_struct *p, struct mem_cgroup *mem, | |||
162 | return 0; | 162 | return 0; |
163 | 163 | ||
164 | /* | 164 | /* |
165 | * Shortcut check for OOM_SCORE_ADJ_MIN so the entire heuristic doesn't | 165 | * Shortcut check for a thread sharing p->mm that is OOM_SCORE_ADJ_MIN |
166 | * need to be executed for something that cannot be killed. | 166 | * so the entire heuristic doesn't need to be executed for something |
167 | * that cannot be killed. | ||
167 | */ | 168 | */ |
168 | if (p->signal->oom_score_adj == OOM_SCORE_ADJ_MIN) { | 169 | if (atomic_read(&p->mm->oom_disable_count)) { |
169 | task_unlock(p); | 170 | task_unlock(p); |
170 | return 0; | 171 | return 0; |
171 | } | 172 | } |
@@ -403,16 +404,40 @@ static void dump_header(struct task_struct *p, gfp_t gfp_mask, int order, | |||
403 | #define K(x) ((x) << (PAGE_SHIFT-10)) | 404 | #define K(x) ((x) << (PAGE_SHIFT-10)) |
404 | static int oom_kill_task(struct task_struct *p, struct mem_cgroup *mem) | 405 | static int oom_kill_task(struct task_struct *p, struct mem_cgroup *mem) |
405 | { | 406 | { |
407 | struct task_struct *q; | ||
408 | struct mm_struct *mm; | ||
409 | |||
406 | p = find_lock_task_mm(p); | 410 | p = find_lock_task_mm(p); |
407 | if (!p) | 411 | if (!p) |
408 | return 1; | 412 | return 1; |
409 | 413 | ||
414 | /* mm cannot be safely dereferenced after task_unlock(p) */ | ||
415 | mm = p->mm; | ||
416 | |||
410 | pr_err("Killed process %d (%s) total-vm:%lukB, anon-rss:%lukB, file-rss:%lukB\n", | 417 | pr_err("Killed process %d (%s) total-vm:%lukB, anon-rss:%lukB, file-rss:%lukB\n", |
411 | task_pid_nr(p), p->comm, K(p->mm->total_vm), | 418 | task_pid_nr(p), p->comm, K(p->mm->total_vm), |
412 | K(get_mm_counter(p->mm, MM_ANONPAGES)), | 419 | K(get_mm_counter(p->mm, MM_ANONPAGES)), |
413 | K(get_mm_counter(p->mm, MM_FILEPAGES))); | 420 | K(get_mm_counter(p->mm, MM_FILEPAGES))); |
414 | task_unlock(p); | 421 | task_unlock(p); |
415 | 422 | ||
423 | /* | ||
424 | * Kill all processes sharing p->mm in other thread groups, if any. | ||
425 | * They don't get access to memory reserves or a higher scheduler | ||
426 | * priority, though, to avoid depletion of all memory or task | ||
427 | * starvation. This prevents mm->mmap_sem livelock when an oom killed | ||
428 | * task cannot exit because it requires the semaphore and its contended | ||
429 | * by another thread trying to allocate memory itself. That thread will | ||
430 | * now get access to memory reserves since it has a pending fatal | ||
431 | * signal. | ||
432 | */ | ||
433 | for_each_process(q) | ||
434 | if (q->mm == mm && !same_thread_group(q, p)) { | ||
435 | task_lock(q); /* Protect ->comm from prctl() */ | ||
436 | pr_err("Kill process %d (%s) sharing same memory\n", | ||
437 | task_pid_nr(q), q->comm); | ||
438 | task_unlock(q); | ||
439 | force_sig(SIGKILL, q); | ||
440 | } | ||
416 | 441 | ||
417 | set_tsk_thread_flag(p, TIF_MEMDIE); | 442 | set_tsk_thread_flag(p, TIF_MEMDIE); |
418 | force_sig(SIGKILL, p); | 443 | force_sig(SIGKILL, p); |
@@ -680,7 +705,7 @@ void out_of_memory(struct zonelist *zonelist, gfp_t gfp_mask, | |||
680 | read_lock(&tasklist_lock); | 705 | read_lock(&tasklist_lock); |
681 | if (sysctl_oom_kill_allocating_task && | 706 | if (sysctl_oom_kill_allocating_task && |
682 | !oom_unkillable_task(current, NULL, nodemask) && | 707 | !oom_unkillable_task(current, NULL, nodemask) && |
683 | (current->signal->oom_adj != OOM_DISABLE)) { | 708 | current->mm && !atomic_read(¤t->mm->oom_disable_count)) { |
684 | /* | 709 | /* |
685 | * oom_kill_process() needs tasklist_lock held. If it returns | 710 | * oom_kill_process() needs tasklist_lock held. If it returns |
686 | * non-zero, current could not be killed so we must fallback to | 711 | * non-zero, current could not be killed so we must fallback to |
diff --git a/mm/page-writeback.c b/mm/page-writeback.c index e3bccac1f025..b840afa89761 100644 --- a/mm/page-writeback.c +++ b/mm/page-writeback.c | |||
@@ -415,14 +415,8 @@ void global_dirty_limits(unsigned long *pbackground, unsigned long *pdirty) | |||
415 | 415 | ||
416 | if (vm_dirty_bytes) | 416 | if (vm_dirty_bytes) |
417 | dirty = DIV_ROUND_UP(vm_dirty_bytes, PAGE_SIZE); | 417 | dirty = DIV_ROUND_UP(vm_dirty_bytes, PAGE_SIZE); |
418 | else { | 418 | else |
419 | int dirty_ratio; | 419 | dirty = (vm_dirty_ratio * available_memory) / 100; |
420 | |||
421 | dirty_ratio = vm_dirty_ratio; | ||
422 | if (dirty_ratio < 5) | ||
423 | dirty_ratio = 5; | ||
424 | dirty = (dirty_ratio * available_memory) / 100; | ||
425 | } | ||
426 | 420 | ||
427 | if (dirty_background_bytes) | 421 | if (dirty_background_bytes) |
428 | background = DIV_ROUND_UP(dirty_background_bytes, PAGE_SIZE); | 422 | background = DIV_ROUND_UP(dirty_background_bytes, PAGE_SIZE); |
@@ -510,7 +504,7 @@ static void balance_dirty_pages(struct address_space *mapping, | |||
510 | * catch-up. This avoids (excessively) small writeouts | 504 | * catch-up. This avoids (excessively) small writeouts |
511 | * when the bdi limits are ramping up. | 505 | * when the bdi limits are ramping up. |
512 | */ | 506 | */ |
513 | if (nr_reclaimable + nr_writeback < | 507 | if (nr_reclaimable + nr_writeback <= |
514 | (background_thresh + dirty_thresh) / 2) | 508 | (background_thresh + dirty_thresh) / 2) |
515 | break; | 509 | break; |
516 | 510 | ||
@@ -542,8 +536,8 @@ static void balance_dirty_pages(struct address_space *mapping, | |||
542 | * the last resort safeguard. | 536 | * the last resort safeguard. |
543 | */ | 537 | */ |
544 | dirty_exceeded = | 538 | dirty_exceeded = |
545 | (bdi_nr_reclaimable + bdi_nr_writeback >= bdi_thresh) | 539 | (bdi_nr_reclaimable + bdi_nr_writeback > bdi_thresh) |
546 | || (nr_reclaimable + nr_writeback >= dirty_thresh); | 540 | || (nr_reclaimable + nr_writeback > dirty_thresh); |
547 | 541 | ||
548 | if (!dirty_exceeded) | 542 | if (!dirty_exceeded) |
549 | break; | 543 | break; |
@@ -1121,6 +1115,7 @@ void account_page_dirtied(struct page *page, struct address_space *mapping) | |||
1121 | { | 1115 | { |
1122 | if (mapping_cap_account_dirty(mapping)) { | 1116 | if (mapping_cap_account_dirty(mapping)) { |
1123 | __inc_zone_page_state(page, NR_FILE_DIRTY); | 1117 | __inc_zone_page_state(page, NR_FILE_DIRTY); |
1118 | __inc_zone_page_state(page, NR_DIRTIED); | ||
1124 | __inc_bdi_stat(mapping->backing_dev_info, BDI_RECLAIMABLE); | 1119 | __inc_bdi_stat(mapping->backing_dev_info, BDI_RECLAIMABLE); |
1125 | task_dirty_inc(current); | 1120 | task_dirty_inc(current); |
1126 | task_io_account_write(PAGE_CACHE_SIZE); | 1121 | task_io_account_write(PAGE_CACHE_SIZE); |
@@ -1129,6 +1124,18 @@ void account_page_dirtied(struct page *page, struct address_space *mapping) | |||
1129 | EXPORT_SYMBOL(account_page_dirtied); | 1124 | EXPORT_SYMBOL(account_page_dirtied); |
1130 | 1125 | ||
1131 | /* | 1126 | /* |
1127 | * Helper function for set_page_writeback family. | ||
1128 | * NOTE: Unlike account_page_dirtied this does not rely on being atomic | ||
1129 | * wrt interrupts. | ||
1130 | */ | ||
1131 | void account_page_writeback(struct page *page) | ||
1132 | { | ||
1133 | inc_zone_page_state(page, NR_WRITEBACK); | ||
1134 | inc_zone_page_state(page, NR_WRITTEN); | ||
1135 | } | ||
1136 | EXPORT_SYMBOL(account_page_writeback); | ||
1137 | |||
1138 | /* | ||
1132 | * For address_spaces which do not use buffers. Just tag the page as dirty in | 1139 | * For address_spaces which do not use buffers. Just tag the page as dirty in |
1133 | * its radix tree. | 1140 | * its radix tree. |
1134 | * | 1141 | * |
@@ -1366,7 +1373,7 @@ int test_set_page_writeback(struct page *page) | |||
1366 | ret = TestSetPageWriteback(page); | 1373 | ret = TestSetPageWriteback(page); |
1367 | } | 1374 | } |
1368 | if (!ret) | 1375 | if (!ret) |
1369 | inc_zone_page_state(page, NR_WRITEBACK); | 1376 | account_page_writeback(page); |
1370 | return ret; | 1377 | return ret; |
1371 | 1378 | ||
1372 | } | 1379 | } |
diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 2a362c52fdf4..07a654486f75 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c | |||
@@ -531,7 +531,7 @@ static inline void __free_one_page(struct page *page, | |||
531 | * so it's less likely to be used soon and more likely to be merged | 531 | * so it's less likely to be used soon and more likely to be merged |
532 | * as a higher order page | 532 | * as a higher order page |
533 | */ | 533 | */ |
534 | if ((order < MAX_ORDER-1) && pfn_valid_within(page_to_pfn(buddy))) { | 534 | if ((order < MAX_ORDER-2) && pfn_valid_within(page_to_pfn(buddy))) { |
535 | struct page *higher_page, *higher_buddy; | 535 | struct page *higher_page, *higher_buddy; |
536 | combined_idx = __find_combined_index(page_idx, order); | 536 | combined_idx = __find_combined_index(page_idx, order); |
537 | higher_page = page + combined_idx - page_idx; | 537 | higher_page = page + combined_idx - page_idx; |
@@ -1907,7 +1907,7 @@ __alloc_pages_high_priority(gfp_t gfp_mask, unsigned int order, | |||
1907 | preferred_zone, migratetype); | 1907 | preferred_zone, migratetype); |
1908 | 1908 | ||
1909 | if (!page && gfp_mask & __GFP_NOFAIL) | 1909 | if (!page && gfp_mask & __GFP_NOFAIL) |
1910 | congestion_wait(BLK_RW_ASYNC, HZ/50); | 1910 | wait_iff_congested(preferred_zone, BLK_RW_ASYNC, HZ/50); |
1911 | } while (!page && (gfp_mask & __GFP_NOFAIL)); | 1911 | } while (!page && (gfp_mask & __GFP_NOFAIL)); |
1912 | 1912 | ||
1913 | return page; | 1913 | return page; |
@@ -1932,7 +1932,7 @@ gfp_to_alloc_flags(gfp_t gfp_mask) | |||
1932 | const gfp_t wait = gfp_mask & __GFP_WAIT; | 1932 | const gfp_t wait = gfp_mask & __GFP_WAIT; |
1933 | 1933 | ||
1934 | /* __GFP_HIGH is assumed to be the same as ALLOC_HIGH to save a branch. */ | 1934 | /* __GFP_HIGH is assumed to be the same as ALLOC_HIGH to save a branch. */ |
1935 | BUILD_BUG_ON(__GFP_HIGH != ALLOC_HIGH); | 1935 | BUILD_BUG_ON(__GFP_HIGH != (__force gfp_t) ALLOC_HIGH); |
1936 | 1936 | ||
1937 | /* | 1937 | /* |
1938 | * The caller may dip into page reserves a bit more if the caller | 1938 | * The caller may dip into page reserves a bit more if the caller |
@@ -1940,7 +1940,7 @@ gfp_to_alloc_flags(gfp_t gfp_mask) | |||
1940 | * policy or is asking for __GFP_HIGH memory. GFP_ATOMIC requests will | 1940 | * policy or is asking for __GFP_HIGH memory. GFP_ATOMIC requests will |
1941 | * set both ALLOC_HARDER (!wait) and ALLOC_HIGH (__GFP_HIGH). | 1941 | * set both ALLOC_HARDER (!wait) and ALLOC_HIGH (__GFP_HIGH). |
1942 | */ | 1942 | */ |
1943 | alloc_flags |= (gfp_mask & __GFP_HIGH); | 1943 | alloc_flags |= (__force int) (gfp_mask & __GFP_HIGH); |
1944 | 1944 | ||
1945 | if (!wait) { | 1945 | if (!wait) { |
1946 | alloc_flags |= ALLOC_HARDER; | 1946 | alloc_flags |= ALLOC_HARDER; |
@@ -2095,7 +2095,7 @@ rebalance: | |||
2095 | pages_reclaimed += did_some_progress; | 2095 | pages_reclaimed += did_some_progress; |
2096 | if (should_alloc_retry(gfp_mask, order, pages_reclaimed)) { | 2096 | if (should_alloc_retry(gfp_mask, order, pages_reclaimed)) { |
2097 | /* Wait for some write requests to complete then retry */ | 2097 | /* Wait for some write requests to complete then retry */ |
2098 | congestion_wait(BLK_RW_ASYNC, HZ/50); | 2098 | wait_iff_congested(preferred_zone, BLK_RW_ASYNC, HZ/50); |
2099 | goto rebalance; | 2099 | goto rebalance; |
2100 | } | 2100 | } |
2101 | 2101 | ||
@@ -5297,12 +5297,65 @@ void set_pageblock_flags_group(struct page *page, unsigned long flags, | |||
5297 | * page allocater never alloc memory from ISOLATE block. | 5297 | * page allocater never alloc memory from ISOLATE block. |
5298 | */ | 5298 | */ |
5299 | 5299 | ||
5300 | static int | ||
5301 | __count_immobile_pages(struct zone *zone, struct page *page, int count) | ||
5302 | { | ||
5303 | unsigned long pfn, iter, found; | ||
5304 | /* | ||
5305 | * For avoiding noise data, lru_add_drain_all() should be called | ||
5306 | * If ZONE_MOVABLE, the zone never contains immobile pages | ||
5307 | */ | ||
5308 | if (zone_idx(zone) == ZONE_MOVABLE) | ||
5309 | return true; | ||
5310 | |||
5311 | if (get_pageblock_migratetype(page) == MIGRATE_MOVABLE) | ||
5312 | return true; | ||
5313 | |||
5314 | pfn = page_to_pfn(page); | ||
5315 | for (found = 0, iter = 0; iter < pageblock_nr_pages; iter++) { | ||
5316 | unsigned long check = pfn + iter; | ||
5317 | |||
5318 | if (!pfn_valid_within(check)) { | ||
5319 | iter++; | ||
5320 | continue; | ||
5321 | } | ||
5322 | page = pfn_to_page(check); | ||
5323 | if (!page_count(page)) { | ||
5324 | if (PageBuddy(page)) | ||
5325 | iter += (1 << page_order(page)) - 1; | ||
5326 | continue; | ||
5327 | } | ||
5328 | if (!PageLRU(page)) | ||
5329 | found++; | ||
5330 | /* | ||
5331 | * If there are RECLAIMABLE pages, we need to check it. | ||
5332 | * But now, memory offline itself doesn't call shrink_slab() | ||
5333 | * and it still to be fixed. | ||
5334 | */ | ||
5335 | /* | ||
5336 | * If the page is not RAM, page_count()should be 0. | ||
5337 | * we don't need more check. This is an _used_ not-movable page. | ||
5338 | * | ||
5339 | * The problematic thing here is PG_reserved pages. PG_reserved | ||
5340 | * is set to both of a memory hole page and a _used_ kernel | ||
5341 | * page at boot. | ||
5342 | */ | ||
5343 | if (found > count) | ||
5344 | return false; | ||
5345 | } | ||
5346 | return true; | ||
5347 | } | ||
5348 | |||
5349 | bool is_pageblock_removable_nolock(struct page *page) | ||
5350 | { | ||
5351 | struct zone *zone = page_zone(page); | ||
5352 | return __count_immobile_pages(zone, page, 0); | ||
5353 | } | ||
5354 | |||
5300 | int set_migratetype_isolate(struct page *page) | 5355 | int set_migratetype_isolate(struct page *page) |
5301 | { | 5356 | { |
5302 | struct zone *zone; | 5357 | struct zone *zone; |
5303 | struct page *curr_page; | 5358 | unsigned long flags, pfn; |
5304 | unsigned long flags, pfn, iter; | ||
5305 | unsigned long immobile = 0; | ||
5306 | struct memory_isolate_notify arg; | 5359 | struct memory_isolate_notify arg; |
5307 | int notifier_ret; | 5360 | int notifier_ret; |
5308 | int ret = -EBUSY; | 5361 | int ret = -EBUSY; |
@@ -5312,11 +5365,6 @@ int set_migratetype_isolate(struct page *page) | |||
5312 | zone_idx = zone_idx(zone); | 5365 | zone_idx = zone_idx(zone); |
5313 | 5366 | ||
5314 | spin_lock_irqsave(&zone->lock, flags); | 5367 | spin_lock_irqsave(&zone->lock, flags); |
5315 | if (get_pageblock_migratetype(page) == MIGRATE_MOVABLE || | ||
5316 | zone_idx == ZONE_MOVABLE) { | ||
5317 | ret = 0; | ||
5318 | goto out; | ||
5319 | } | ||
5320 | 5368 | ||
5321 | pfn = page_to_pfn(page); | 5369 | pfn = page_to_pfn(page); |
5322 | arg.start_pfn = pfn; | 5370 | arg.start_pfn = pfn; |
@@ -5336,23 +5384,20 @@ int set_migratetype_isolate(struct page *page) | |||
5336 | */ | 5384 | */ |
5337 | notifier_ret = memory_isolate_notify(MEM_ISOLATE_COUNT, &arg); | 5385 | notifier_ret = memory_isolate_notify(MEM_ISOLATE_COUNT, &arg); |
5338 | notifier_ret = notifier_to_errno(notifier_ret); | 5386 | notifier_ret = notifier_to_errno(notifier_ret); |
5339 | if (notifier_ret || !arg.pages_found) | 5387 | if (notifier_ret) |
5340 | goto out; | 5388 | goto out; |
5341 | 5389 | /* | |
5342 | for (iter = pfn; iter < (pfn + pageblock_nr_pages); iter++) { | 5390 | * FIXME: Now, memory hotplug doesn't call shrink_slab() by itself. |
5343 | if (!pfn_valid_within(pfn)) | 5391 | * We just check MOVABLE pages. |
5344 | continue; | 5392 | */ |
5345 | 5393 | if (__count_immobile_pages(zone, page, arg.pages_found)) | |
5346 | curr_page = pfn_to_page(iter); | ||
5347 | if (!page_count(curr_page) || PageLRU(curr_page)) | ||
5348 | continue; | ||
5349 | |||
5350 | immobile++; | ||
5351 | } | ||
5352 | |||
5353 | if (arg.pages_found == immobile) | ||
5354 | ret = 0; | 5394 | ret = 0; |
5355 | 5395 | ||
5396 | /* | ||
5397 | * immobile means "not-on-lru" paes. If immobile is larger than | ||
5398 | * removable-by-driver pages reported by notifier, we'll fail. | ||
5399 | */ | ||
5400 | |||
5356 | out: | 5401 | out: |
5357 | if (!ret) { | 5402 | if (!ret) { |
5358 | set_pageblock_migratetype(page, MIGRATE_ISOLATE); | 5403 | set_pageblock_migratetype(page, MIGRATE_ISOLATE); |
diff --git a/mm/page_isolation.c b/mm/page_isolation.c index 5e0ffd967452..4ae42bb40892 100644 --- a/mm/page_isolation.c +++ b/mm/page_isolation.c | |||
@@ -86,7 +86,7 @@ undo_isolate_page_range(unsigned long start_pfn, unsigned long end_pfn) | |||
86 | * all pages in [start_pfn...end_pfn) must be in the same zone. | 86 | * all pages in [start_pfn...end_pfn) must be in the same zone. |
87 | * zone->lock must be held before call this. | 87 | * zone->lock must be held before call this. |
88 | * | 88 | * |
89 | * Returns 0 if all pages in the range is isolated. | 89 | * Returns 1 if all pages in the range is isolated. |
90 | */ | 90 | */ |
91 | static int | 91 | static int |
92 | __test_page_isolated_in_pageblock(unsigned long pfn, unsigned long end_pfn) | 92 | __test_page_isolated_in_pageblock(unsigned long pfn, unsigned long end_pfn) |
@@ -119,7 +119,6 @@ int test_pages_isolated(unsigned long start_pfn, unsigned long end_pfn) | |||
119 | struct zone *zone; | 119 | struct zone *zone; |
120 | int ret; | 120 | int ret; |
121 | 121 | ||
122 | pfn = start_pfn; | ||
123 | /* | 122 | /* |
124 | * Note: pageblock_nr_page != MAX_ORDER. Then, chunks of free page | 123 | * Note: pageblock_nr_page != MAX_ORDER. Then, chunks of free page |
125 | * is not aligned to pageblock_nr_pages. | 124 | * is not aligned to pageblock_nr_pages. |
@@ -80,7 +80,7 @@ static inline struct anon_vma_chain *anon_vma_chain_alloc(void) | |||
80 | return kmem_cache_alloc(anon_vma_chain_cachep, GFP_KERNEL); | 80 | return kmem_cache_alloc(anon_vma_chain_cachep, GFP_KERNEL); |
81 | } | 81 | } |
82 | 82 | ||
83 | void anon_vma_chain_free(struct anon_vma_chain *anon_vma_chain) | 83 | static void anon_vma_chain_free(struct anon_vma_chain *anon_vma_chain) |
84 | { | 84 | { |
85 | kmem_cache_free(anon_vma_chain_cachep, anon_vma_chain); | 85 | kmem_cache_free(anon_vma_chain_cachep, anon_vma_chain); |
86 | } | 86 | } |
@@ -314,7 +314,7 @@ void __init anon_vma_init(void) | |||
314 | * Getting a lock on a stable anon_vma from a page off the LRU is | 314 | * Getting a lock on a stable anon_vma from a page off the LRU is |
315 | * tricky: page_lock_anon_vma rely on RCU to guard against the races. | 315 | * tricky: page_lock_anon_vma rely on RCU to guard against the races. |
316 | */ | 316 | */ |
317 | struct anon_vma *page_lock_anon_vma(struct page *page) | 317 | struct anon_vma *__page_lock_anon_vma(struct page *page) |
318 | { | 318 | { |
319 | struct anon_vma *anon_vma, *root_anon_vma; | 319 | struct anon_vma *anon_vma, *root_anon_vma; |
320 | unsigned long anon_mapping; | 320 | unsigned long anon_mapping; |
@@ -348,6 +348,8 @@ out: | |||
348 | } | 348 | } |
349 | 349 | ||
350 | void page_unlock_anon_vma(struct anon_vma *anon_vma) | 350 | void page_unlock_anon_vma(struct anon_vma *anon_vma) |
351 | __releases(&anon_vma->root->lock) | ||
352 | __releases(RCU) | ||
351 | { | 353 | { |
352 | anon_vma_unlock(anon_vma); | 354 | anon_vma_unlock(anon_vma); |
353 | rcu_read_unlock(); | 355 | rcu_read_unlock(); |
@@ -407,7 +409,7 @@ unsigned long page_address_in_vma(struct page *page, struct vm_area_struct *vma) | |||
407 | * | 409 | * |
408 | * On success returns with pte mapped and locked. | 410 | * On success returns with pte mapped and locked. |
409 | */ | 411 | */ |
410 | pte_t *page_check_address(struct page *page, struct mm_struct *mm, | 412 | pte_t *__page_check_address(struct page *page, struct mm_struct *mm, |
411 | unsigned long address, spinlock_t **ptlp, int sync) | 413 | unsigned long address, spinlock_t **ptlp, int sync) |
412 | { | 414 | { |
413 | pgd_t *pgd; | 415 | pgd_t *pgd; |
@@ -901,7 +901,7 @@ static int transfer_objects(struct array_cache *to, | |||
901 | struct array_cache *from, unsigned int max) | 901 | struct array_cache *from, unsigned int max) |
902 | { | 902 | { |
903 | /* Figure out how many entries to transfer */ | 903 | /* Figure out how many entries to transfer */ |
904 | int nr = min(min(from->avail, max), to->limit - to->avail); | 904 | int nr = min3(from->avail, max, to->limit - to->avail); |
905 | 905 | ||
906 | if (!nr) | 906 | if (!nr) |
907 | return 0; | 907 | return 0; |
diff --git a/mm/swapfile.c b/mm/swapfile.c index 9fc7bac7db0c..67ddaaf98c74 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/capability.h> | 30 | #include <linux/capability.h> |
31 | #include <linux/syscalls.h> | 31 | #include <linux/syscalls.h> |
32 | #include <linux/memcontrol.h> | 32 | #include <linux/memcontrol.h> |
33 | #include <linux/poll.h> | ||
33 | 34 | ||
34 | #include <asm/pgtable.h> | 35 | #include <asm/pgtable.h> |
35 | #include <asm/tlbflush.h> | 36 | #include <asm/tlbflush.h> |
@@ -58,6 +59,10 @@ static struct swap_info_struct *swap_info[MAX_SWAPFILES]; | |||
58 | 59 | ||
59 | static DEFINE_MUTEX(swapon_mutex); | 60 | static DEFINE_MUTEX(swapon_mutex); |
60 | 61 | ||
62 | static DECLARE_WAIT_QUEUE_HEAD(proc_poll_wait); | ||
63 | /* Activity counter to indicate that a swapon or swapoff has occurred */ | ||
64 | static atomic_t proc_poll_event = ATOMIC_INIT(0); | ||
65 | |||
61 | static inline unsigned char swap_count(unsigned char ent) | 66 | static inline unsigned char swap_count(unsigned char ent) |
62 | { | 67 | { |
63 | return ent & ~SWAP_HAS_CACHE; /* may include SWAP_HAS_CONT flag */ | 68 | return ent & ~SWAP_HAS_CACHE; /* may include SWAP_HAS_CONT flag */ |
@@ -1680,6 +1685,8 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile) | |||
1680 | } | 1685 | } |
1681 | filp_close(swap_file, NULL); | 1686 | filp_close(swap_file, NULL); |
1682 | err = 0; | 1687 | err = 0; |
1688 | atomic_inc(&proc_poll_event); | ||
1689 | wake_up_interruptible(&proc_poll_wait); | ||
1683 | 1690 | ||
1684 | out_dput: | 1691 | out_dput: |
1685 | filp_close(victim, NULL); | 1692 | filp_close(victim, NULL); |
@@ -1688,6 +1695,25 @@ out: | |||
1688 | } | 1695 | } |
1689 | 1696 | ||
1690 | #ifdef CONFIG_PROC_FS | 1697 | #ifdef CONFIG_PROC_FS |
1698 | struct proc_swaps { | ||
1699 | struct seq_file seq; | ||
1700 | int event; | ||
1701 | }; | ||
1702 | |||
1703 | static unsigned swaps_poll(struct file *file, poll_table *wait) | ||
1704 | { | ||
1705 | struct proc_swaps *s = file->private_data; | ||
1706 | |||
1707 | poll_wait(file, &proc_poll_wait, wait); | ||
1708 | |||
1709 | if (s->event != atomic_read(&proc_poll_event)) { | ||
1710 | s->event = atomic_read(&proc_poll_event); | ||
1711 | return POLLIN | POLLRDNORM | POLLERR | POLLPRI; | ||
1712 | } | ||
1713 | |||
1714 | return POLLIN | POLLRDNORM; | ||
1715 | } | ||
1716 | |||
1691 | /* iterator */ | 1717 | /* iterator */ |
1692 | static void *swap_start(struct seq_file *swap, loff_t *pos) | 1718 | static void *swap_start(struct seq_file *swap, loff_t *pos) |
1693 | { | 1719 | { |
@@ -1771,7 +1797,24 @@ static const struct seq_operations swaps_op = { | |||
1771 | 1797 | ||
1772 | static int swaps_open(struct inode *inode, struct file *file) | 1798 | static int swaps_open(struct inode *inode, struct file *file) |
1773 | { | 1799 | { |
1774 | return seq_open(file, &swaps_op); | 1800 | struct proc_swaps *s; |
1801 | int ret; | ||
1802 | |||
1803 | s = kmalloc(sizeof(struct proc_swaps), GFP_KERNEL); | ||
1804 | if (!s) | ||
1805 | return -ENOMEM; | ||
1806 | |||
1807 | file->private_data = s; | ||
1808 | |||
1809 | ret = seq_open(file, &swaps_op); | ||
1810 | if (ret) { | ||
1811 | kfree(s); | ||
1812 | return ret; | ||
1813 | } | ||
1814 | |||
1815 | s->seq.private = s; | ||
1816 | s->event = atomic_read(&proc_poll_event); | ||
1817 | return ret; | ||
1775 | } | 1818 | } |
1776 | 1819 | ||
1777 | static const struct file_operations proc_swaps_operations = { | 1820 | static const struct file_operations proc_swaps_operations = { |
@@ -1779,6 +1822,7 @@ static const struct file_operations proc_swaps_operations = { | |||
1779 | .read = seq_read, | 1822 | .read = seq_read, |
1780 | .llseek = seq_lseek, | 1823 | .llseek = seq_lseek, |
1781 | .release = seq_release, | 1824 | .release = seq_release, |
1825 | .poll = swaps_poll, | ||
1782 | }; | 1826 | }; |
1783 | 1827 | ||
1784 | static int __init procswaps_init(void) | 1828 | static int __init procswaps_init(void) |
@@ -2084,6 +2128,9 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags) | |||
2084 | swap_info[prev]->next = type; | 2128 | swap_info[prev]->next = type; |
2085 | spin_unlock(&swap_lock); | 2129 | spin_unlock(&swap_lock); |
2086 | mutex_unlock(&swapon_mutex); | 2130 | mutex_unlock(&swapon_mutex); |
2131 | atomic_inc(&proc_poll_event); | ||
2132 | wake_up_interruptible(&proc_poll_wait); | ||
2133 | |||
2087 | error = 0; | 2134 | error = 0; |
2088 | goto out; | 2135 | goto out; |
2089 | bad_swap: | 2136 | bad_swap: |
diff --git a/mm/vmalloc.c b/mm/vmalloc.c index 9f909622a25e..a3d66b3dc5cb 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c | |||
@@ -293,13 +293,13 @@ static void __insert_vmap_area(struct vmap_area *va) | |||
293 | struct rb_node *tmp; | 293 | struct rb_node *tmp; |
294 | 294 | ||
295 | while (*p) { | 295 | while (*p) { |
296 | struct vmap_area *tmp; | 296 | struct vmap_area *tmp_va; |
297 | 297 | ||
298 | parent = *p; | 298 | parent = *p; |
299 | tmp = rb_entry(parent, struct vmap_area, rb_node); | 299 | tmp_va = rb_entry(parent, struct vmap_area, rb_node); |
300 | if (va->va_start < tmp->va_end) | 300 | if (va->va_start < tmp_va->va_end) |
301 | p = &(*p)->rb_left; | 301 | p = &(*p)->rb_left; |
302 | else if (va->va_end > tmp->va_start) | 302 | else if (va->va_end > tmp_va->va_start) |
303 | p = &(*p)->rb_right; | 303 | p = &(*p)->rb_right; |
304 | else | 304 | else |
305 | BUG(); | 305 | BUG(); |
@@ -1596,6 +1596,13 @@ void *__vmalloc(unsigned long size, gfp_t gfp_mask, pgprot_t prot) | |||
1596 | } | 1596 | } |
1597 | EXPORT_SYMBOL(__vmalloc); | 1597 | EXPORT_SYMBOL(__vmalloc); |
1598 | 1598 | ||
1599 | static inline void *__vmalloc_node_flags(unsigned long size, | ||
1600 | int node, gfp_t flags) | ||
1601 | { | ||
1602 | return __vmalloc_node(size, 1, flags, PAGE_KERNEL, | ||
1603 | node, __builtin_return_address(0)); | ||
1604 | } | ||
1605 | |||
1599 | /** | 1606 | /** |
1600 | * vmalloc - allocate virtually contiguous memory | 1607 | * vmalloc - allocate virtually contiguous memory |
1601 | * @size: allocation size | 1608 | * @size: allocation size |
@@ -1607,12 +1614,28 @@ EXPORT_SYMBOL(__vmalloc); | |||
1607 | */ | 1614 | */ |
1608 | void *vmalloc(unsigned long size) | 1615 | void *vmalloc(unsigned long size) |
1609 | { | 1616 | { |
1610 | return __vmalloc_node(size, 1, GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL, | 1617 | return __vmalloc_node_flags(size, -1, GFP_KERNEL | __GFP_HIGHMEM); |
1611 | -1, __builtin_return_address(0)); | ||
1612 | } | 1618 | } |
1613 | EXPORT_SYMBOL(vmalloc); | 1619 | EXPORT_SYMBOL(vmalloc); |
1614 | 1620 | ||
1615 | /** | 1621 | /** |
1622 | * vzalloc - allocate virtually contiguous memory with zero fill | ||
1623 | * @size: allocation size | ||
1624 | * Allocate enough pages to cover @size from the page level | ||
1625 | * allocator and map them into contiguous kernel virtual space. | ||
1626 | * The memory allocated is set to zero. | ||
1627 | * | ||
1628 | * For tight control over page level allocator and protection flags | ||
1629 | * use __vmalloc() instead. | ||
1630 | */ | ||
1631 | void *vzalloc(unsigned long size) | ||
1632 | { | ||
1633 | return __vmalloc_node_flags(size, -1, | ||
1634 | GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO); | ||
1635 | } | ||
1636 | EXPORT_SYMBOL(vzalloc); | ||
1637 | |||
1638 | /** | ||
1616 | * vmalloc_user - allocate zeroed virtually contiguous memory for userspace | 1639 | * vmalloc_user - allocate zeroed virtually contiguous memory for userspace |
1617 | * @size: allocation size | 1640 | * @size: allocation size |
1618 | * | 1641 | * |
@@ -1653,6 +1676,25 @@ void *vmalloc_node(unsigned long size, int node) | |||
1653 | } | 1676 | } |
1654 | EXPORT_SYMBOL(vmalloc_node); | 1677 | EXPORT_SYMBOL(vmalloc_node); |
1655 | 1678 | ||
1679 | /** | ||
1680 | * vzalloc_node - allocate memory on a specific node with zero fill | ||
1681 | * @size: allocation size | ||
1682 | * @node: numa node | ||
1683 | * | ||
1684 | * Allocate enough pages to cover @size from the page level | ||
1685 | * allocator and map them into contiguous kernel virtual space. | ||
1686 | * The memory allocated is set to zero. | ||
1687 | * | ||
1688 | * For tight control over page level allocator and protection flags | ||
1689 | * use __vmalloc_node() instead. | ||
1690 | */ | ||
1691 | void *vzalloc_node(unsigned long size, int node) | ||
1692 | { | ||
1693 | return __vmalloc_node_flags(size, node, | ||
1694 | GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO); | ||
1695 | } | ||
1696 | EXPORT_SYMBOL(vzalloc_node); | ||
1697 | |||
1656 | #ifndef PAGE_KERNEL_EXEC | 1698 | #ifndef PAGE_KERNEL_EXEC |
1657 | # define PAGE_KERNEL_EXEC PAGE_KERNEL | 1699 | # define PAGE_KERNEL_EXEC PAGE_KERNEL |
1658 | #endif | 1700 | #endif |
@@ -2350,6 +2392,7 @@ void pcpu_free_vm_areas(struct vm_struct **vms, int nr_vms) | |||
2350 | 2392 | ||
2351 | #ifdef CONFIG_PROC_FS | 2393 | #ifdef CONFIG_PROC_FS |
2352 | static void *s_start(struct seq_file *m, loff_t *pos) | 2394 | static void *s_start(struct seq_file *m, loff_t *pos) |
2395 | __acquires(&vmlist_lock) | ||
2353 | { | 2396 | { |
2354 | loff_t n = *pos; | 2397 | loff_t n = *pos; |
2355 | struct vm_struct *v; | 2398 | struct vm_struct *v; |
@@ -2376,6 +2419,7 @@ static void *s_next(struct seq_file *m, void *p, loff_t *pos) | |||
2376 | } | 2419 | } |
2377 | 2420 | ||
2378 | static void s_stop(struct seq_file *m, void *p) | 2421 | static void s_stop(struct seq_file *m, void *p) |
2422 | __releases(&vmlist_lock) | ||
2379 | { | 2423 | { |
2380 | read_unlock(&vmlist_lock); | 2424 | read_unlock(&vmlist_lock); |
2381 | } | 2425 | } |
diff --git a/mm/vmscan.c b/mm/vmscan.c index b94c9464f262..b8a6fdc21312 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c | |||
@@ -51,6 +51,12 @@ | |||
51 | #define CREATE_TRACE_POINTS | 51 | #define CREATE_TRACE_POINTS |
52 | #include <trace/events/vmscan.h> | 52 | #include <trace/events/vmscan.h> |
53 | 53 | ||
54 | enum lumpy_mode { | ||
55 | LUMPY_MODE_NONE, | ||
56 | LUMPY_MODE_ASYNC, | ||
57 | LUMPY_MODE_SYNC, | ||
58 | }; | ||
59 | |||
54 | struct scan_control { | 60 | struct scan_control { |
55 | /* Incremented by the number of inactive pages that were scanned */ | 61 | /* Incremented by the number of inactive pages that were scanned */ |
56 | unsigned long nr_scanned; | 62 | unsigned long nr_scanned; |
@@ -82,7 +88,7 @@ struct scan_control { | |||
82 | * Intend to reclaim enough continuous memory rather than reclaim | 88 | * Intend to reclaim enough continuous memory rather than reclaim |
83 | * enough amount of memory. i.e, mode for high order allocation. | 89 | * enough amount of memory. i.e, mode for high order allocation. |
84 | */ | 90 | */ |
85 | bool lumpy_reclaim_mode; | 91 | enum lumpy_mode lumpy_reclaim_mode; |
86 | 92 | ||
87 | /* Which cgroup do we reclaim from */ | 93 | /* Which cgroup do we reclaim from */ |
88 | struct mem_cgroup *mem_cgroup; | 94 | struct mem_cgroup *mem_cgroup; |
@@ -265,6 +271,36 @@ unsigned long shrink_slab(unsigned long scanned, gfp_t gfp_mask, | |||
265 | return ret; | 271 | return ret; |
266 | } | 272 | } |
267 | 273 | ||
274 | static void set_lumpy_reclaim_mode(int priority, struct scan_control *sc, | ||
275 | bool sync) | ||
276 | { | ||
277 | enum lumpy_mode mode = sync ? LUMPY_MODE_SYNC : LUMPY_MODE_ASYNC; | ||
278 | |||
279 | /* | ||
280 | * Some reclaim have alredy been failed. No worth to try synchronous | ||
281 | * lumpy reclaim. | ||
282 | */ | ||
283 | if (sync && sc->lumpy_reclaim_mode == LUMPY_MODE_NONE) | ||
284 | return; | ||
285 | |||
286 | /* | ||
287 | * If we need a large contiguous chunk of memory, or have | ||
288 | * trouble getting a small set of contiguous pages, we | ||
289 | * will reclaim both active and inactive pages. | ||
290 | */ | ||
291 | if (sc->order > PAGE_ALLOC_COSTLY_ORDER) | ||
292 | sc->lumpy_reclaim_mode = mode; | ||
293 | else if (sc->order && priority < DEF_PRIORITY - 2) | ||
294 | sc->lumpy_reclaim_mode = mode; | ||
295 | else | ||
296 | sc->lumpy_reclaim_mode = LUMPY_MODE_NONE; | ||
297 | } | ||
298 | |||
299 | static void disable_lumpy_reclaim_mode(struct scan_control *sc) | ||
300 | { | ||
301 | sc->lumpy_reclaim_mode = LUMPY_MODE_NONE; | ||
302 | } | ||
303 | |||
268 | static inline int is_page_cache_freeable(struct page *page) | 304 | static inline int is_page_cache_freeable(struct page *page) |
269 | { | 305 | { |
270 | /* | 306 | /* |
@@ -275,7 +311,8 @@ static inline int is_page_cache_freeable(struct page *page) | |||
275 | return page_count(page) - page_has_private(page) == 2; | 311 | return page_count(page) - page_has_private(page) == 2; |
276 | } | 312 | } |
277 | 313 | ||
278 | static int may_write_to_queue(struct backing_dev_info *bdi) | 314 | static int may_write_to_queue(struct backing_dev_info *bdi, |
315 | struct scan_control *sc) | ||
279 | { | 316 | { |
280 | if (current->flags & PF_SWAPWRITE) | 317 | if (current->flags & PF_SWAPWRITE) |
281 | return 1; | 318 | return 1; |
@@ -283,6 +320,10 @@ static int may_write_to_queue(struct backing_dev_info *bdi) | |||
283 | return 1; | 320 | return 1; |
284 | if (bdi == current->backing_dev_info) | 321 | if (bdi == current->backing_dev_info) |
285 | return 1; | 322 | return 1; |
323 | |||
324 | /* lumpy reclaim for hugepage often need a lot of write */ | ||
325 | if (sc->order > PAGE_ALLOC_COSTLY_ORDER) | ||
326 | return 1; | ||
286 | return 0; | 327 | return 0; |
287 | } | 328 | } |
288 | 329 | ||
@@ -307,12 +348,6 @@ static void handle_write_error(struct address_space *mapping, | |||
307 | unlock_page(page); | 348 | unlock_page(page); |
308 | } | 349 | } |
309 | 350 | ||
310 | /* Request for sync pageout. */ | ||
311 | enum pageout_io { | ||
312 | PAGEOUT_IO_ASYNC, | ||
313 | PAGEOUT_IO_SYNC, | ||
314 | }; | ||
315 | |||
316 | /* possible outcome of pageout() */ | 351 | /* possible outcome of pageout() */ |
317 | typedef enum { | 352 | typedef enum { |
318 | /* failed to write page out, page is locked */ | 353 | /* failed to write page out, page is locked */ |
@@ -330,7 +365,7 @@ typedef enum { | |||
330 | * Calls ->writepage(). | 365 | * Calls ->writepage(). |
331 | */ | 366 | */ |
332 | static pageout_t pageout(struct page *page, struct address_space *mapping, | 367 | static pageout_t pageout(struct page *page, struct address_space *mapping, |
333 | enum pageout_io sync_writeback) | 368 | struct scan_control *sc) |
334 | { | 369 | { |
335 | /* | 370 | /* |
336 | * If the page is dirty, only perform writeback if that write | 371 | * If the page is dirty, only perform writeback if that write |
@@ -366,7 +401,7 @@ static pageout_t pageout(struct page *page, struct address_space *mapping, | |||
366 | } | 401 | } |
367 | if (mapping->a_ops->writepage == NULL) | 402 | if (mapping->a_ops->writepage == NULL) |
368 | return PAGE_ACTIVATE; | 403 | return PAGE_ACTIVATE; |
369 | if (!may_write_to_queue(mapping->backing_dev_info)) | 404 | if (!may_write_to_queue(mapping->backing_dev_info, sc)) |
370 | return PAGE_KEEP; | 405 | return PAGE_KEEP; |
371 | 406 | ||
372 | if (clear_page_dirty_for_io(page)) { | 407 | if (clear_page_dirty_for_io(page)) { |
@@ -376,7 +411,6 @@ static pageout_t pageout(struct page *page, struct address_space *mapping, | |||
376 | .nr_to_write = SWAP_CLUSTER_MAX, | 411 | .nr_to_write = SWAP_CLUSTER_MAX, |
377 | .range_start = 0, | 412 | .range_start = 0, |
378 | .range_end = LLONG_MAX, | 413 | .range_end = LLONG_MAX, |
379 | .nonblocking = 1, | ||
380 | .for_reclaim = 1, | 414 | .for_reclaim = 1, |
381 | }; | 415 | }; |
382 | 416 | ||
@@ -394,7 +428,8 @@ static pageout_t pageout(struct page *page, struct address_space *mapping, | |||
394 | * direct reclaiming a large contiguous area and the | 428 | * direct reclaiming a large contiguous area and the |
395 | * first attempt to free a range of pages fails. | 429 | * first attempt to free a range of pages fails. |
396 | */ | 430 | */ |
397 | if (PageWriteback(page) && sync_writeback == PAGEOUT_IO_SYNC) | 431 | if (PageWriteback(page) && |
432 | sc->lumpy_reclaim_mode == LUMPY_MODE_SYNC) | ||
398 | wait_on_page_writeback(page); | 433 | wait_on_page_writeback(page); |
399 | 434 | ||
400 | if (!PageWriteback(page)) { | 435 | if (!PageWriteback(page)) { |
@@ -402,7 +437,7 @@ static pageout_t pageout(struct page *page, struct address_space *mapping, | |||
402 | ClearPageReclaim(page); | 437 | ClearPageReclaim(page); |
403 | } | 438 | } |
404 | trace_mm_vmscan_writepage(page, | 439 | trace_mm_vmscan_writepage(page, |
405 | trace_reclaim_flags(page, sync_writeback)); | 440 | trace_reclaim_flags(page, sc->lumpy_reclaim_mode)); |
406 | inc_zone_page_state(page, NR_VMSCAN_WRITE); | 441 | inc_zone_page_state(page, NR_VMSCAN_WRITE); |
407 | return PAGE_SUCCESS; | 442 | return PAGE_SUCCESS; |
408 | } | 443 | } |
@@ -580,7 +615,7 @@ static enum page_references page_check_references(struct page *page, | |||
580 | referenced_page = TestClearPageReferenced(page); | 615 | referenced_page = TestClearPageReferenced(page); |
581 | 616 | ||
582 | /* Lumpy reclaim - ignore references */ | 617 | /* Lumpy reclaim - ignore references */ |
583 | if (sc->lumpy_reclaim_mode) | 618 | if (sc->lumpy_reclaim_mode != LUMPY_MODE_NONE) |
584 | return PAGEREF_RECLAIM; | 619 | return PAGEREF_RECLAIM; |
585 | 620 | ||
586 | /* | 621 | /* |
@@ -616,7 +651,7 @@ static enum page_references page_check_references(struct page *page, | |||
616 | } | 651 | } |
617 | 652 | ||
618 | /* Reclaim if clean, defer dirty pages to writeback */ | 653 | /* Reclaim if clean, defer dirty pages to writeback */ |
619 | if (referenced_page) | 654 | if (referenced_page && !PageSwapBacked(page)) |
620 | return PAGEREF_RECLAIM_CLEAN; | 655 | return PAGEREF_RECLAIM_CLEAN; |
621 | 656 | ||
622 | return PAGEREF_RECLAIM; | 657 | return PAGEREF_RECLAIM; |
@@ -644,12 +679,14 @@ static noinline_for_stack void free_page_list(struct list_head *free_pages) | |||
644 | * shrink_page_list() returns the number of reclaimed pages | 679 | * shrink_page_list() returns the number of reclaimed pages |
645 | */ | 680 | */ |
646 | static unsigned long shrink_page_list(struct list_head *page_list, | 681 | static unsigned long shrink_page_list(struct list_head *page_list, |
647 | struct scan_control *sc, | 682 | struct zone *zone, |
648 | enum pageout_io sync_writeback) | 683 | struct scan_control *sc) |
649 | { | 684 | { |
650 | LIST_HEAD(ret_pages); | 685 | LIST_HEAD(ret_pages); |
651 | LIST_HEAD(free_pages); | 686 | LIST_HEAD(free_pages); |
652 | int pgactivate = 0; | 687 | int pgactivate = 0; |
688 | unsigned long nr_dirty = 0; | ||
689 | unsigned long nr_congested = 0; | ||
653 | unsigned long nr_reclaimed = 0; | 690 | unsigned long nr_reclaimed = 0; |
654 | 691 | ||
655 | cond_resched(); | 692 | cond_resched(); |
@@ -669,6 +706,7 @@ static unsigned long shrink_page_list(struct list_head *page_list, | |||
669 | goto keep; | 706 | goto keep; |
670 | 707 | ||
671 | VM_BUG_ON(PageActive(page)); | 708 | VM_BUG_ON(PageActive(page)); |
709 | VM_BUG_ON(page_zone(page) != zone); | ||
672 | 710 | ||
673 | sc->nr_scanned++; | 711 | sc->nr_scanned++; |
674 | 712 | ||
@@ -694,10 +732,13 @@ static unsigned long shrink_page_list(struct list_head *page_list, | |||
694 | * for any page for which writeback has already | 732 | * for any page for which writeback has already |
695 | * started. | 733 | * started. |
696 | */ | 734 | */ |
697 | if (sync_writeback == PAGEOUT_IO_SYNC && may_enter_fs) | 735 | if (sc->lumpy_reclaim_mode == LUMPY_MODE_SYNC && |
736 | may_enter_fs) | ||
698 | wait_on_page_writeback(page); | 737 | wait_on_page_writeback(page); |
699 | else | 738 | else { |
700 | goto keep_locked; | 739 | unlock_page(page); |
740 | goto keep_lumpy; | ||
741 | } | ||
701 | } | 742 | } |
702 | 743 | ||
703 | references = page_check_references(page, sc); | 744 | references = page_check_references(page, sc); |
@@ -743,6 +784,8 @@ static unsigned long shrink_page_list(struct list_head *page_list, | |||
743 | } | 784 | } |
744 | 785 | ||
745 | if (PageDirty(page)) { | 786 | if (PageDirty(page)) { |
787 | nr_dirty++; | ||
788 | |||
746 | if (references == PAGEREF_RECLAIM_CLEAN) | 789 | if (references == PAGEREF_RECLAIM_CLEAN) |
747 | goto keep_locked; | 790 | goto keep_locked; |
748 | if (!may_enter_fs) | 791 | if (!may_enter_fs) |
@@ -751,14 +794,18 @@ static unsigned long shrink_page_list(struct list_head *page_list, | |||
751 | goto keep_locked; | 794 | goto keep_locked; |
752 | 795 | ||
753 | /* Page is dirty, try to write it out here */ | 796 | /* Page is dirty, try to write it out here */ |
754 | switch (pageout(page, mapping, sync_writeback)) { | 797 | switch (pageout(page, mapping, sc)) { |
755 | case PAGE_KEEP: | 798 | case PAGE_KEEP: |
799 | nr_congested++; | ||
756 | goto keep_locked; | 800 | goto keep_locked; |
757 | case PAGE_ACTIVATE: | 801 | case PAGE_ACTIVATE: |
758 | goto activate_locked; | 802 | goto activate_locked; |
759 | case PAGE_SUCCESS: | 803 | case PAGE_SUCCESS: |
760 | if (PageWriteback(page) || PageDirty(page)) | 804 | if (PageWriteback(page)) |
805 | goto keep_lumpy; | ||
806 | if (PageDirty(page)) | ||
761 | goto keep; | 807 | goto keep; |
808 | |||
762 | /* | 809 | /* |
763 | * A synchronous write - probably a ramdisk. Go | 810 | * A synchronous write - probably a ramdisk. Go |
764 | * ahead and try to reclaim the page. | 811 | * ahead and try to reclaim the page. |
@@ -841,6 +888,7 @@ cull_mlocked: | |||
841 | try_to_free_swap(page); | 888 | try_to_free_swap(page); |
842 | unlock_page(page); | 889 | unlock_page(page); |
843 | putback_lru_page(page); | 890 | putback_lru_page(page); |
891 | disable_lumpy_reclaim_mode(sc); | ||
844 | continue; | 892 | continue; |
845 | 893 | ||
846 | activate_locked: | 894 | activate_locked: |
@@ -853,10 +901,21 @@ activate_locked: | |||
853 | keep_locked: | 901 | keep_locked: |
854 | unlock_page(page); | 902 | unlock_page(page); |
855 | keep: | 903 | keep: |
904 | disable_lumpy_reclaim_mode(sc); | ||
905 | keep_lumpy: | ||
856 | list_add(&page->lru, &ret_pages); | 906 | list_add(&page->lru, &ret_pages); |
857 | VM_BUG_ON(PageLRU(page) || PageUnevictable(page)); | 907 | VM_BUG_ON(PageLRU(page) || PageUnevictable(page)); |
858 | } | 908 | } |
859 | 909 | ||
910 | /* | ||
911 | * Tag a zone as congested if all the dirty pages encountered were | ||
912 | * backed by a congested BDI. In this case, reclaimers should just | ||
913 | * back off and wait for congestion to clear because further reclaim | ||
914 | * will encounter the same problem | ||
915 | */ | ||
916 | if (nr_dirty == nr_congested) | ||
917 | zone_set_flag(zone, ZONE_CONGESTED); | ||
918 | |||
860 | free_page_list(&free_pages); | 919 | free_page_list(&free_pages); |
861 | 920 | ||
862 | list_splice(&ret_pages, page_list); | 921 | list_splice(&ret_pages, page_list); |
@@ -1006,7 +1065,7 @@ static unsigned long isolate_lru_pages(unsigned long nr_to_scan, | |||
1006 | 1065 | ||
1007 | /* Check that we have not crossed a zone boundary. */ | 1066 | /* Check that we have not crossed a zone boundary. */ |
1008 | if (unlikely(page_zone_id(cursor_page) != zone_id)) | 1067 | if (unlikely(page_zone_id(cursor_page) != zone_id)) |
1009 | continue; | 1068 | break; |
1010 | 1069 | ||
1011 | /* | 1070 | /* |
1012 | * If we don't have enough swap space, reclaiming of | 1071 | * If we don't have enough swap space, reclaiming of |
@@ -1014,8 +1073,8 @@ static unsigned long isolate_lru_pages(unsigned long nr_to_scan, | |||
1014 | * pointless. | 1073 | * pointless. |
1015 | */ | 1074 | */ |
1016 | if (nr_swap_pages <= 0 && PageAnon(cursor_page) && | 1075 | if (nr_swap_pages <= 0 && PageAnon(cursor_page) && |
1017 | !PageSwapCache(cursor_page)) | 1076 | !PageSwapCache(cursor_page)) |
1018 | continue; | 1077 | break; |
1019 | 1078 | ||
1020 | if (__isolate_lru_page(cursor_page, mode, file) == 0) { | 1079 | if (__isolate_lru_page(cursor_page, mode, file) == 0) { |
1021 | list_move(&cursor_page->lru, dst); | 1080 | list_move(&cursor_page->lru, dst); |
@@ -1026,11 +1085,16 @@ static unsigned long isolate_lru_pages(unsigned long nr_to_scan, | |||
1026 | nr_lumpy_dirty++; | 1085 | nr_lumpy_dirty++; |
1027 | scan++; | 1086 | scan++; |
1028 | } else { | 1087 | } else { |
1029 | if (mode == ISOLATE_BOTH && | 1088 | /* the page is freed already. */ |
1030 | page_count(cursor_page)) | 1089 | if (!page_count(cursor_page)) |
1031 | nr_lumpy_failed++; | 1090 | continue; |
1091 | break; | ||
1032 | } | 1092 | } |
1033 | } | 1093 | } |
1094 | |||
1095 | /* If we break out of the loop above, lumpy reclaim failed */ | ||
1096 | if (pfn < end_pfn) | ||
1097 | nr_lumpy_failed++; | ||
1034 | } | 1098 | } |
1035 | 1099 | ||
1036 | *scanned = scan; | 1100 | *scanned = scan; |
@@ -1253,7 +1317,7 @@ static inline bool should_reclaim_stall(unsigned long nr_taken, | |||
1253 | return false; | 1317 | return false; |
1254 | 1318 | ||
1255 | /* Only stall on lumpy reclaim */ | 1319 | /* Only stall on lumpy reclaim */ |
1256 | if (!sc->lumpy_reclaim_mode) | 1320 | if (sc->lumpy_reclaim_mode == LUMPY_MODE_NONE) |
1257 | return false; | 1321 | return false; |
1258 | 1322 | ||
1259 | /* If we have relaimed everything on the isolated list, no stall */ | 1323 | /* If we have relaimed everything on the isolated list, no stall */ |
@@ -1286,7 +1350,6 @@ shrink_inactive_list(unsigned long nr_to_scan, struct zone *zone, | |||
1286 | unsigned long nr_scanned; | 1350 | unsigned long nr_scanned; |
1287 | unsigned long nr_reclaimed = 0; | 1351 | unsigned long nr_reclaimed = 0; |
1288 | unsigned long nr_taken; | 1352 | unsigned long nr_taken; |
1289 | unsigned long nr_active; | ||
1290 | unsigned long nr_anon; | 1353 | unsigned long nr_anon; |
1291 | unsigned long nr_file; | 1354 | unsigned long nr_file; |
1292 | 1355 | ||
@@ -1298,15 +1361,15 @@ shrink_inactive_list(unsigned long nr_to_scan, struct zone *zone, | |||
1298 | return SWAP_CLUSTER_MAX; | 1361 | return SWAP_CLUSTER_MAX; |
1299 | } | 1362 | } |
1300 | 1363 | ||
1301 | 1364 | set_lumpy_reclaim_mode(priority, sc, false); | |
1302 | lru_add_drain(); | 1365 | lru_add_drain(); |
1303 | spin_lock_irq(&zone->lru_lock); | 1366 | spin_lock_irq(&zone->lru_lock); |
1304 | 1367 | ||
1305 | if (scanning_global_lru(sc)) { | 1368 | if (scanning_global_lru(sc)) { |
1306 | nr_taken = isolate_pages_global(nr_to_scan, | 1369 | nr_taken = isolate_pages_global(nr_to_scan, |
1307 | &page_list, &nr_scanned, sc->order, | 1370 | &page_list, &nr_scanned, sc->order, |
1308 | sc->lumpy_reclaim_mode ? | 1371 | sc->lumpy_reclaim_mode == LUMPY_MODE_NONE ? |
1309 | ISOLATE_BOTH : ISOLATE_INACTIVE, | 1372 | ISOLATE_INACTIVE : ISOLATE_BOTH, |
1310 | zone, 0, file); | 1373 | zone, 0, file); |
1311 | zone->pages_scanned += nr_scanned; | 1374 | zone->pages_scanned += nr_scanned; |
1312 | if (current_is_kswapd()) | 1375 | if (current_is_kswapd()) |
@@ -1318,8 +1381,8 @@ shrink_inactive_list(unsigned long nr_to_scan, struct zone *zone, | |||
1318 | } else { | 1381 | } else { |
1319 | nr_taken = mem_cgroup_isolate_pages(nr_to_scan, | 1382 | nr_taken = mem_cgroup_isolate_pages(nr_to_scan, |
1320 | &page_list, &nr_scanned, sc->order, | 1383 | &page_list, &nr_scanned, sc->order, |
1321 | sc->lumpy_reclaim_mode ? | 1384 | sc->lumpy_reclaim_mode == LUMPY_MODE_NONE ? |
1322 | ISOLATE_BOTH : ISOLATE_INACTIVE, | 1385 | ISOLATE_INACTIVE : ISOLATE_BOTH, |
1323 | zone, sc->mem_cgroup, | 1386 | zone, sc->mem_cgroup, |
1324 | 0, file); | 1387 | 0, file); |
1325 | /* | 1388 | /* |
@@ -1337,20 +1400,12 @@ shrink_inactive_list(unsigned long nr_to_scan, struct zone *zone, | |||
1337 | 1400 | ||
1338 | spin_unlock_irq(&zone->lru_lock); | 1401 | spin_unlock_irq(&zone->lru_lock); |
1339 | 1402 | ||
1340 | nr_reclaimed = shrink_page_list(&page_list, sc, PAGEOUT_IO_ASYNC); | 1403 | nr_reclaimed = shrink_page_list(&page_list, zone, sc); |
1341 | 1404 | ||
1342 | /* Check if we should syncronously wait for writeback */ | 1405 | /* Check if we should syncronously wait for writeback */ |
1343 | if (should_reclaim_stall(nr_taken, nr_reclaimed, priority, sc)) { | 1406 | if (should_reclaim_stall(nr_taken, nr_reclaimed, priority, sc)) { |
1344 | congestion_wait(BLK_RW_ASYNC, HZ/10); | 1407 | set_lumpy_reclaim_mode(priority, sc, true); |
1345 | 1408 | nr_reclaimed += shrink_page_list(&page_list, zone, sc); | |
1346 | /* | ||
1347 | * The attempt at page out may have made some | ||
1348 | * of the pages active, mark them inactive again. | ||
1349 | */ | ||
1350 | nr_active = clear_active_flags(&page_list, NULL); | ||
1351 | count_vm_events(PGDEACTIVATE, nr_active); | ||
1352 | |||
1353 | nr_reclaimed += shrink_page_list(&page_list, sc, PAGEOUT_IO_SYNC); | ||
1354 | } | 1409 | } |
1355 | 1410 | ||
1356 | local_irq_disable(); | 1411 | local_irq_disable(); |
@@ -1359,6 +1414,12 @@ shrink_inactive_list(unsigned long nr_to_scan, struct zone *zone, | |||
1359 | __count_zone_vm_events(PGSTEAL, zone, nr_reclaimed); | 1414 | __count_zone_vm_events(PGSTEAL, zone, nr_reclaimed); |
1360 | 1415 | ||
1361 | putback_lru_pages(zone, sc, nr_anon, nr_file, &page_list); | 1416 | putback_lru_pages(zone, sc, nr_anon, nr_file, &page_list); |
1417 | |||
1418 | trace_mm_vmscan_lru_shrink_inactive(zone->zone_pgdat->node_id, | ||
1419 | zone_idx(zone), | ||
1420 | nr_scanned, nr_reclaimed, | ||
1421 | priority, | ||
1422 | trace_shrink_flags(file, sc->lumpy_reclaim_mode)); | ||
1362 | return nr_reclaimed; | 1423 | return nr_reclaimed; |
1363 | } | 1424 | } |
1364 | 1425 | ||
@@ -1506,6 +1567,7 @@ static void shrink_active_list(unsigned long nr_pages, struct zone *zone, | |||
1506 | spin_unlock_irq(&zone->lru_lock); | 1567 | spin_unlock_irq(&zone->lru_lock); |
1507 | } | 1568 | } |
1508 | 1569 | ||
1570 | #ifdef CONFIG_SWAP | ||
1509 | static int inactive_anon_is_low_global(struct zone *zone) | 1571 | static int inactive_anon_is_low_global(struct zone *zone) |
1510 | { | 1572 | { |
1511 | unsigned long active, inactive; | 1573 | unsigned long active, inactive; |
@@ -1531,12 +1593,26 @@ static int inactive_anon_is_low(struct zone *zone, struct scan_control *sc) | |||
1531 | { | 1593 | { |
1532 | int low; | 1594 | int low; |
1533 | 1595 | ||
1596 | /* | ||
1597 | * If we don't have swap space, anonymous page deactivation | ||
1598 | * is pointless. | ||
1599 | */ | ||
1600 | if (!total_swap_pages) | ||
1601 | return 0; | ||
1602 | |||
1534 | if (scanning_global_lru(sc)) | 1603 | if (scanning_global_lru(sc)) |
1535 | low = inactive_anon_is_low_global(zone); | 1604 | low = inactive_anon_is_low_global(zone); |
1536 | else | 1605 | else |
1537 | low = mem_cgroup_inactive_anon_is_low(sc->mem_cgroup); | 1606 | low = mem_cgroup_inactive_anon_is_low(sc->mem_cgroup); |
1538 | return low; | 1607 | return low; |
1539 | } | 1608 | } |
1609 | #else | ||
1610 | static inline int inactive_anon_is_low(struct zone *zone, | ||
1611 | struct scan_control *sc) | ||
1612 | { | ||
1613 | return 0; | ||
1614 | } | ||
1615 | #endif | ||
1540 | 1616 | ||
1541 | static int inactive_file_is_low_global(struct zone *zone) | 1617 | static int inactive_file_is_low_global(struct zone *zone) |
1542 | { | 1618 | { |
@@ -1721,21 +1797,6 @@ out: | |||
1721 | } | 1797 | } |
1722 | } | 1798 | } |
1723 | 1799 | ||
1724 | static void set_lumpy_reclaim_mode(int priority, struct scan_control *sc) | ||
1725 | { | ||
1726 | /* | ||
1727 | * If we need a large contiguous chunk of memory, or have | ||
1728 | * trouble getting a small set of contiguous pages, we | ||
1729 | * will reclaim both active and inactive pages. | ||
1730 | */ | ||
1731 | if (sc->order > PAGE_ALLOC_COSTLY_ORDER) | ||
1732 | sc->lumpy_reclaim_mode = 1; | ||
1733 | else if (sc->order && priority < DEF_PRIORITY - 2) | ||
1734 | sc->lumpy_reclaim_mode = 1; | ||
1735 | else | ||
1736 | sc->lumpy_reclaim_mode = 0; | ||
1737 | } | ||
1738 | |||
1739 | /* | 1800 | /* |
1740 | * This is a basic per-zone page freer. Used by both kswapd and direct reclaim. | 1801 | * This is a basic per-zone page freer. Used by both kswapd and direct reclaim. |
1741 | */ | 1802 | */ |
@@ -1750,8 +1811,6 @@ static void shrink_zone(int priority, struct zone *zone, | |||
1750 | 1811 | ||
1751 | get_scan_count(zone, sc, nr, priority); | 1812 | get_scan_count(zone, sc, nr, priority); |
1752 | 1813 | ||
1753 | set_lumpy_reclaim_mode(priority, sc); | ||
1754 | |||
1755 | while (nr[LRU_INACTIVE_ANON] || nr[LRU_ACTIVE_FILE] || | 1814 | while (nr[LRU_INACTIVE_ANON] || nr[LRU_ACTIVE_FILE] || |
1756 | nr[LRU_INACTIVE_FILE]) { | 1815 | nr[LRU_INACTIVE_FILE]) { |
1757 | for_each_evictable_lru(l) { | 1816 | for_each_evictable_lru(l) { |
@@ -1782,7 +1841,7 @@ static void shrink_zone(int priority, struct zone *zone, | |||
1782 | * Even if we did not try to evict anon pages at all, we want to | 1841 | * Even if we did not try to evict anon pages at all, we want to |
1783 | * rebalance the anon lru active/inactive ratio. | 1842 | * rebalance the anon lru active/inactive ratio. |
1784 | */ | 1843 | */ |
1785 | if (inactive_anon_is_low(zone, sc) && nr_swap_pages > 0) | 1844 | if (inactive_anon_is_low(zone, sc)) |
1786 | shrink_active_list(SWAP_CLUSTER_MAX, zone, sc, priority, 0); | 1845 | shrink_active_list(SWAP_CLUSTER_MAX, zone, sc, priority, 0); |
1787 | 1846 | ||
1788 | throttle_vm_writeout(sc->gfp_mask); | 1847 | throttle_vm_writeout(sc->gfp_mask); |
@@ -1937,21 +1996,16 @@ static unsigned long do_try_to_free_pages(struct zonelist *zonelist, | |||
1937 | 1996 | ||
1938 | /* Take a nap, wait for some writeback to complete */ | 1997 | /* Take a nap, wait for some writeback to complete */ |
1939 | if (!sc->hibernation_mode && sc->nr_scanned && | 1998 | if (!sc->hibernation_mode && sc->nr_scanned && |
1940 | priority < DEF_PRIORITY - 2) | 1999 | priority < DEF_PRIORITY - 2) { |
1941 | congestion_wait(BLK_RW_ASYNC, HZ/10); | 2000 | struct zone *preferred_zone; |
2001 | |||
2002 | first_zones_zonelist(zonelist, gfp_zone(sc->gfp_mask), | ||
2003 | NULL, &preferred_zone); | ||
2004 | wait_iff_congested(preferred_zone, BLK_RW_ASYNC, HZ/10); | ||
2005 | } | ||
1942 | } | 2006 | } |
1943 | 2007 | ||
1944 | out: | 2008 | out: |
1945 | /* | ||
1946 | * Now that we've scanned all the zones at this priority level, note | ||
1947 | * that level within the zone so that the next thread which performs | ||
1948 | * scanning of this zone will immediately start out at this priority | ||
1949 | * level. This affects only the decision whether or not to bring | ||
1950 | * mapped pages onto the inactive list. | ||
1951 | */ | ||
1952 | if (priority < 0) | ||
1953 | priority = 0; | ||
1954 | |||
1955 | delayacct_freepages_end(); | 2009 | delayacct_freepages_end(); |
1956 | put_mems_allowed(); | 2010 | put_mems_allowed(); |
1957 | 2011 | ||
@@ -2247,6 +2301,15 @@ loop_again: | |||
2247 | if (!zone_watermark_ok(zone, order, | 2301 | if (!zone_watermark_ok(zone, order, |
2248 | min_wmark_pages(zone), end_zone, 0)) | 2302 | min_wmark_pages(zone), end_zone, 0)) |
2249 | has_under_min_watermark_zone = 1; | 2303 | has_under_min_watermark_zone = 1; |
2304 | } else { | ||
2305 | /* | ||
2306 | * If a zone reaches its high watermark, | ||
2307 | * consider it to be no longer congested. It's | ||
2308 | * possible there are dirty pages backed by | ||
2309 | * congested BDIs but as pressure is relieved, | ||
2310 | * spectulatively avoid congestion waits | ||
2311 | */ | ||
2312 | zone_clear_flag(zone, ZONE_CONGESTED); | ||
2250 | } | 2313 | } |
2251 | 2314 | ||
2252 | } | 2315 | } |
@@ -2987,6 +3050,7 @@ int scan_unevictable_handler(struct ctl_table *table, int write, | |||
2987 | return 0; | 3050 | return 0; |
2988 | } | 3051 | } |
2989 | 3052 | ||
3053 | #ifdef CONFIG_NUMA | ||
2990 | /* | 3054 | /* |
2991 | * per node 'scan_unevictable_pages' attribute. On demand re-scan of | 3055 | * per node 'scan_unevictable_pages' attribute. On demand re-scan of |
2992 | * a specified node's per zone unevictable lists for evictable pages. | 3056 | * a specified node's per zone unevictable lists for evictable pages. |
@@ -3033,4 +3097,4 @@ void scan_unevictable_unregister_node(struct node *node) | |||
3033 | { | 3097 | { |
3034 | sysdev_remove_file(&node->sysdev, &attr_scan_unevictable_pages); | 3098 | sysdev_remove_file(&node->sysdev, &attr_scan_unevictable_pages); |
3035 | } | 3099 | } |
3036 | 3100 | #endif | |
diff --git a/mm/vmstat.c b/mm/vmstat.c index 355a9e669aaa..cd2e42be7b68 100644 --- a/mm/vmstat.c +++ b/mm/vmstat.c | |||
@@ -17,6 +17,8 @@ | |||
17 | #include <linux/vmstat.h> | 17 | #include <linux/vmstat.h> |
18 | #include <linux/sched.h> | 18 | #include <linux/sched.h> |
19 | #include <linux/math64.h> | 19 | #include <linux/math64.h> |
20 | #include <linux/writeback.h> | ||
21 | #include <linux/compaction.h> | ||
20 | 22 | ||
21 | #ifdef CONFIG_VM_EVENT_COUNTERS | 23 | #ifdef CONFIG_VM_EVENT_COUNTERS |
22 | DEFINE_PER_CPU(struct vm_event_state, vm_event_states) = {{0}}; | 24 | DEFINE_PER_CPU(struct vm_event_state, vm_event_states) = {{0}}; |
@@ -394,6 +396,7 @@ void zone_statistics(struct zone *preferred_zone, struct zone *z) | |||
394 | #endif | 396 | #endif |
395 | 397 | ||
396 | #ifdef CONFIG_COMPACTION | 398 | #ifdef CONFIG_COMPACTION |
399 | |||
397 | struct contig_page_info { | 400 | struct contig_page_info { |
398 | unsigned long free_pages; | 401 | unsigned long free_pages; |
399 | unsigned long free_blocks_total; | 402 | unsigned long free_blocks_total; |
@@ -745,6 +748,11 @@ static const char * const vmstat_text[] = { | |||
745 | "nr_isolated_anon", | 748 | "nr_isolated_anon", |
746 | "nr_isolated_file", | 749 | "nr_isolated_file", |
747 | "nr_shmem", | 750 | "nr_shmem", |
751 | "nr_dirtied", | ||
752 | "nr_written", | ||
753 | "nr_dirty_threshold", | ||
754 | "nr_dirty_background_threshold", | ||
755 | |||
748 | #ifdef CONFIG_NUMA | 756 | #ifdef CONFIG_NUMA |
749 | "numa_hit", | 757 | "numa_hit", |
750 | "numa_miss", | 758 | "numa_miss", |
@@ -904,36 +912,44 @@ static const struct file_operations proc_zoneinfo_file_operations = { | |||
904 | .release = seq_release, | 912 | .release = seq_release, |
905 | }; | 913 | }; |
906 | 914 | ||
915 | enum writeback_stat_item { | ||
916 | NR_DIRTY_THRESHOLD, | ||
917 | NR_DIRTY_BG_THRESHOLD, | ||
918 | NR_VM_WRITEBACK_STAT_ITEMS, | ||
919 | }; | ||
920 | |||
907 | static void *vmstat_start(struct seq_file *m, loff_t *pos) | 921 | static void *vmstat_start(struct seq_file *m, loff_t *pos) |
908 | { | 922 | { |
909 | unsigned long *v; | 923 | unsigned long *v; |
910 | #ifdef CONFIG_VM_EVENT_COUNTERS | 924 | int i, stat_items_size; |
911 | unsigned long *e; | ||
912 | #endif | ||
913 | int i; | ||
914 | 925 | ||
915 | if (*pos >= ARRAY_SIZE(vmstat_text)) | 926 | if (*pos >= ARRAY_SIZE(vmstat_text)) |
916 | return NULL; | 927 | return NULL; |
928 | stat_items_size = NR_VM_ZONE_STAT_ITEMS * sizeof(unsigned long) + | ||
929 | NR_VM_WRITEBACK_STAT_ITEMS * sizeof(unsigned long); | ||
917 | 930 | ||
918 | #ifdef CONFIG_VM_EVENT_COUNTERS | 931 | #ifdef CONFIG_VM_EVENT_COUNTERS |
919 | v = kmalloc(NR_VM_ZONE_STAT_ITEMS * sizeof(unsigned long) | 932 | stat_items_size += sizeof(struct vm_event_state); |
920 | + sizeof(struct vm_event_state), GFP_KERNEL); | ||
921 | #else | ||
922 | v = kmalloc(NR_VM_ZONE_STAT_ITEMS * sizeof(unsigned long), | ||
923 | GFP_KERNEL); | ||
924 | #endif | 933 | #endif |
934 | |||
935 | v = kmalloc(stat_items_size, GFP_KERNEL); | ||
925 | m->private = v; | 936 | m->private = v; |
926 | if (!v) | 937 | if (!v) |
927 | return ERR_PTR(-ENOMEM); | 938 | return ERR_PTR(-ENOMEM); |
928 | for (i = 0; i < NR_VM_ZONE_STAT_ITEMS; i++) | 939 | for (i = 0; i < NR_VM_ZONE_STAT_ITEMS; i++) |
929 | v[i] = global_page_state(i); | 940 | v[i] = global_page_state(i); |
941 | v += NR_VM_ZONE_STAT_ITEMS; | ||
942 | |||
943 | global_dirty_limits(v + NR_DIRTY_BG_THRESHOLD, | ||
944 | v + NR_DIRTY_THRESHOLD); | ||
945 | v += NR_VM_WRITEBACK_STAT_ITEMS; | ||
946 | |||
930 | #ifdef CONFIG_VM_EVENT_COUNTERS | 947 | #ifdef CONFIG_VM_EVENT_COUNTERS |
931 | e = v + NR_VM_ZONE_STAT_ITEMS; | 948 | all_vm_events(v); |
932 | all_vm_events(e); | 949 | v[PGPGIN] /= 2; /* sectors -> kbytes */ |
933 | e[PGPGIN] /= 2; /* sectors -> kbytes */ | 950 | v[PGPGOUT] /= 2; |
934 | e[PGPGOUT] /= 2; | ||
935 | #endif | 951 | #endif |
936 | return v + *pos; | 952 | return m->private + *pos; |
937 | } | 953 | } |
938 | 954 | ||
939 | static void *vmstat_next(struct seq_file *m, void *arg, loff_t *pos) | 955 | static void *vmstat_next(struct seq_file *m, void *arg, loff_t *pos) |
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 0ebc777a6660..3c95304a0817 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c | |||
@@ -117,7 +117,7 @@ | |||
117 | 117 | ||
118 | static struct hlist_head unix_socket_table[UNIX_HASH_SIZE + 1]; | 118 | static struct hlist_head unix_socket_table[UNIX_HASH_SIZE + 1]; |
119 | static DEFINE_SPINLOCK(unix_table_lock); | 119 | static DEFINE_SPINLOCK(unix_table_lock); |
120 | static atomic_t unix_nr_socks = ATOMIC_INIT(0); | 120 | static atomic_long_t unix_nr_socks; |
121 | 121 | ||
122 | #define unix_sockets_unbound (&unix_socket_table[UNIX_HASH_SIZE]) | 122 | #define unix_sockets_unbound (&unix_socket_table[UNIX_HASH_SIZE]) |
123 | 123 | ||
@@ -360,13 +360,13 @@ static void unix_sock_destructor(struct sock *sk) | |||
360 | if (u->addr) | 360 | if (u->addr) |
361 | unix_release_addr(u->addr); | 361 | unix_release_addr(u->addr); |
362 | 362 | ||
363 | atomic_dec(&unix_nr_socks); | 363 | atomic_long_dec(&unix_nr_socks); |
364 | local_bh_disable(); | 364 | local_bh_disable(); |
365 | sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1); | 365 | sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1); |
366 | local_bh_enable(); | 366 | local_bh_enable(); |
367 | #ifdef UNIX_REFCNT_DEBUG | 367 | #ifdef UNIX_REFCNT_DEBUG |
368 | printk(KERN_DEBUG "UNIX %p is destroyed, %d are still alive.\n", sk, | 368 | printk(KERN_DEBUG "UNIX %p is destroyed, %ld are still alive.\n", sk, |
369 | atomic_read(&unix_nr_socks)); | 369 | atomic_long_read(&unix_nr_socks)); |
370 | #endif | 370 | #endif |
371 | } | 371 | } |
372 | 372 | ||
@@ -606,8 +606,8 @@ static struct sock *unix_create1(struct net *net, struct socket *sock) | |||
606 | struct sock *sk = NULL; | 606 | struct sock *sk = NULL; |
607 | struct unix_sock *u; | 607 | struct unix_sock *u; |
608 | 608 | ||
609 | atomic_inc(&unix_nr_socks); | 609 | atomic_long_inc(&unix_nr_socks); |
610 | if (atomic_read(&unix_nr_socks) > 2 * get_max_files()) | 610 | if (atomic_long_read(&unix_nr_socks) > 2 * get_max_files()) |
611 | goto out; | 611 | goto out; |
612 | 612 | ||
613 | sk = sk_alloc(net, PF_UNIX, GFP_KERNEL, &unix_proto); | 613 | sk = sk_alloc(net, PF_UNIX, GFP_KERNEL, &unix_proto); |
@@ -632,7 +632,7 @@ static struct sock *unix_create1(struct net *net, struct socket *sock) | |||
632 | unix_insert_socket(unix_sockets_unbound, sk); | 632 | unix_insert_socket(unix_sockets_unbound, sk); |
633 | out: | 633 | out: |
634 | if (sk == NULL) | 634 | if (sk == NULL) |
635 | atomic_dec(&unix_nr_socks); | 635 | atomic_long_dec(&unix_nr_socks); |
636 | else { | 636 | else { |
637 | local_bh_disable(); | 637 | local_bh_disable(); |
638 | sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1); | 638 | sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1); |
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 2039acdf5122..90b54d4697fd 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl | |||
@@ -2,7 +2,7 @@ | |||
2 | # (c) 2001, Dave Jones. (the file handling bit) | 2 | # (c) 2001, Dave Jones. (the file handling bit) |
3 | # (c) 2005, Joel Schopp <jschopp@austin.ibm.com> (the ugly bit) | 3 | # (c) 2005, Joel Schopp <jschopp@austin.ibm.com> (the ugly bit) |
4 | # (c) 2007,2008, Andy Whitcroft <apw@uk.ibm.com> (new conditions, test suite) | 4 | # (c) 2007,2008, Andy Whitcroft <apw@uk.ibm.com> (new conditions, test suite) |
5 | # (c) 2008,2009, Andy Whitcroft <apw@canonical.com> | 5 | # (c) 2008-2010 Andy Whitcroft <apw@canonical.com> |
6 | # Licensed under the terms of the GNU GPL License version 2 | 6 | # Licensed under the terms of the GNU GPL License version 2 |
7 | 7 | ||
8 | use strict; | 8 | use strict; |
@@ -10,7 +10,7 @@ use strict; | |||
10 | my $P = $0; | 10 | my $P = $0; |
11 | $P =~ s@.*/@@g; | 11 | $P =~ s@.*/@@g; |
12 | 12 | ||
13 | my $V = '0.30'; | 13 | my $V = '0.31'; |
14 | 14 | ||
15 | use Getopt::Long qw(:config no_auto_abbrev); | 15 | use Getopt::Long qw(:config no_auto_abbrev); |
16 | 16 | ||
@@ -103,6 +103,8 @@ for my $key (keys %debug) { | |||
103 | die "$@" if ($@); | 103 | die "$@" if ($@); |
104 | } | 104 | } |
105 | 105 | ||
106 | my $rpt_cleaners = 0; | ||
107 | |||
106 | if ($terse) { | 108 | if ($terse) { |
107 | $emacs = 1; | 109 | $emacs = 1; |
108 | $quiet++; | 110 | $quiet++; |
@@ -150,6 +152,20 @@ our $Sparse = qr{ | |||
150 | # We need \b after 'init' otherwise 'initconst' will cause a false positive in a check | 152 | # We need \b after 'init' otherwise 'initconst' will cause a false positive in a check |
151 | our $Attribute = qr{ | 153 | our $Attribute = qr{ |
152 | const| | 154 | const| |
155 | __percpu| | ||
156 | __nocast| | ||
157 | __safe| | ||
158 | __bitwise__| | ||
159 | __packed__| | ||
160 | __packed2__| | ||
161 | __naked| | ||
162 | __maybe_unused| | ||
163 | __always_unused| | ||
164 | __noreturn| | ||
165 | __used| | ||
166 | __cold| | ||
167 | __noclone| | ||
168 | __deprecated| | ||
153 | __read_mostly| | 169 | __read_mostly| |
154 | __kprobes| | 170 | __kprobes| |
155 | __(?:mem|cpu|dev|)(?:initdata|initconst|init\b)| | 171 | __(?:mem|cpu|dev|)(?:initdata|initconst|init\b)| |
@@ -675,15 +691,15 @@ sub ctx_block_get { | |||
675 | $blk .= $rawlines[$line]; | 691 | $blk .= $rawlines[$line]; |
676 | 692 | ||
677 | # Handle nested #if/#else. | 693 | # Handle nested #if/#else. |
678 | if ($rawlines[$line] =~ /^.\s*#\s*(?:ifndef|ifdef|if)\s/) { | 694 | if ($lines[$line] =~ /^.\s*#\s*(?:ifndef|ifdef|if)\s/) { |
679 | push(@stack, $level); | 695 | push(@stack, $level); |
680 | } elsif ($rawlines[$line] =~ /^.\s*#\s*(?:else|elif)\b/) { | 696 | } elsif ($lines[$line] =~ /^.\s*#\s*(?:else|elif)\b/) { |
681 | $level = $stack[$#stack - 1]; | 697 | $level = $stack[$#stack - 1]; |
682 | } elsif ($rawlines[$line] =~ /^.\s*#\s*endif\b/) { | 698 | } elsif ($lines[$line] =~ /^.\s*#\s*endif\b/) { |
683 | $level = pop(@stack); | 699 | $level = pop(@stack); |
684 | } | 700 | } |
685 | 701 | ||
686 | foreach my $c (split(//, $rawlines[$line])) { | 702 | foreach my $c (split(//, $lines[$line])) { |
687 | ##print "C<$c>L<$level><$open$close>O<$off>\n"; | 703 | ##print "C<$c>L<$level><$open$close>O<$off>\n"; |
688 | if ($off > 0) { | 704 | if ($off > 0) { |
689 | $off--; | 705 | $off--; |
@@ -843,7 +859,12 @@ sub annotate_values { | |||
843 | $av_preprocessor = 0; | 859 | $av_preprocessor = 0; |
844 | } | 860 | } |
845 | 861 | ||
846 | } elsif ($cur =~ /^($Type)\s*(?:$Ident|,|\)|\()/) { | 862 | } elsif ($cur =~ /^(\(\s*$Type\s*)\)/) { |
863 | print "CAST($1)\n" if ($dbg_values > 1); | ||
864 | push(@av_paren_type, $type); | ||
865 | $type = 'C'; | ||
866 | |||
867 | } elsif ($cur =~ /^($Type)\s*(?:$Ident|,|\)|\(|\s*$)/) { | ||
847 | print "DECLARE($1)\n" if ($dbg_values > 1); | 868 | print "DECLARE($1)\n" if ($dbg_values > 1); |
848 | $type = 'T'; | 869 | $type = 'T'; |
849 | 870 | ||
@@ -1308,7 +1329,11 @@ sub process { | |||
1308 | $here = "#$realline: " if ($file); | 1329 | $here = "#$realline: " if ($file); |
1309 | 1330 | ||
1310 | # extract the filename as it passes | 1331 | # extract the filename as it passes |
1311 | if ($line=~/^\+\+\+\s+(\S+)/) { | 1332 | if ($line =~ /^diff --git.*?(\S+)$/) { |
1333 | $realfile = $1; | ||
1334 | $realfile =~ s@^([^/]*)/@@; | ||
1335 | |||
1336 | } elsif ($line =~ /^\+\+\+\s+(\S+)/) { | ||
1312 | $realfile = $1; | 1337 | $realfile = $1; |
1313 | $realfile =~ s@^([^/]*)/@@; | 1338 | $realfile =~ s@^([^/]*)/@@; |
1314 | 1339 | ||
@@ -1332,6 +1357,14 @@ sub process { | |||
1332 | 1357 | ||
1333 | $cnt_lines++ if ($realcnt != 0); | 1358 | $cnt_lines++ if ($realcnt != 0); |
1334 | 1359 | ||
1360 | # Check for incorrect file permissions | ||
1361 | if ($line =~ /^new (file )?mode.*[7531]\d{0,2}$/) { | ||
1362 | my $permhere = $here . "FILE: $realfile\n"; | ||
1363 | if ($realfile =~ /(Makefile|Kconfig|\.c|\.h|\.S|\.tmpl)$/) { | ||
1364 | ERROR("do not set execute permissions for source files\n" . $permhere); | ||
1365 | } | ||
1366 | } | ||
1367 | |||
1335 | #check the patch for a signoff: | 1368 | #check the patch for a signoff: |
1336 | if ($line =~ /^\s*signed-off-by:/i) { | 1369 | if ($line =~ /^\s*signed-off-by:/i) { |
1337 | # This is a signoff, if ugly, so do not double report. | 1370 | # This is a signoff, if ugly, so do not double report. |
@@ -1389,21 +1422,38 @@ sub process { | |||
1389 | } elsif ($rawline =~ /^\+.*\S\s+$/ || $rawline =~ /^\+\s+$/) { | 1422 | } elsif ($rawline =~ /^\+.*\S\s+$/ || $rawline =~ /^\+\s+$/) { |
1390 | my $herevet = "$here\n" . cat_vet($rawline) . "\n"; | 1423 | my $herevet = "$here\n" . cat_vet($rawline) . "\n"; |
1391 | ERROR("trailing whitespace\n" . $herevet); | 1424 | ERROR("trailing whitespace\n" . $herevet); |
1425 | $rpt_cleaners = 1; | ||
1392 | } | 1426 | } |
1393 | 1427 | ||
1394 | # check for Kconfig help text having a real description | 1428 | # check for Kconfig help text having a real description |
1429 | # Only applies when adding the entry originally, after that we do not have | ||
1430 | # sufficient context to determine whether it is indeed long enough. | ||
1395 | if ($realfile =~ /Kconfig/ && | 1431 | if ($realfile =~ /Kconfig/ && |
1396 | $line =~ /\+?\s*(---)?help(---)?$/) { | 1432 | $line =~ /\+\s*(?:---)?help(?:---)?$/) { |
1397 | my $length = 0; | 1433 | my $length = 0; |
1398 | for (my $l = $linenr; defined($lines[$l]); $l++) { | 1434 | my $cnt = $realcnt; |
1399 | my $f = $lines[$l]; | 1435 | my $ln = $linenr + 1; |
1436 | my $f; | ||
1437 | my $is_end = 0; | ||
1438 | while ($cnt > 0 && defined $lines[$ln - 1]) { | ||
1439 | $f = $lines[$ln - 1]; | ||
1440 | $cnt-- if ($lines[$ln - 1] !~ /^-/); | ||
1441 | $is_end = $lines[$ln - 1] =~ /^\+/; | ||
1442 | $ln++; | ||
1443 | |||
1444 | next if ($f =~ /^-/); | ||
1445 | $f =~ s/^.//; | ||
1400 | $f =~ s/#.*//; | 1446 | $f =~ s/#.*//; |
1401 | $f =~ s/^\s+//; | 1447 | $f =~ s/^\s+//; |
1402 | next if ($f =~ /^$/); | 1448 | next if ($f =~ /^$/); |
1403 | last if ($f =~ /^\s*config\s/); | 1449 | if ($f =~ /^\s*config\s/) { |
1450 | $is_end = 1; | ||
1451 | last; | ||
1452 | } | ||
1404 | $length++; | 1453 | $length++; |
1405 | } | 1454 | } |
1406 | WARN("please write a paragraph that describes the config symbol fully\n" . $herecurr) if ($length < 4); | 1455 | WARN("please write a paragraph that describes the config symbol fully\n" . $herecurr) if ($is_end && $length < 4); |
1456 | #print "is_end<$is_end> length<$length>\n"; | ||
1407 | } | 1457 | } |
1408 | 1458 | ||
1409 | # check we are in a valid source file if not then ignore this hunk | 1459 | # check we are in a valid source file if not then ignore this hunk |
@@ -1450,6 +1500,7 @@ sub process { | |||
1450 | $rawline =~ /^\+\s* \s*/) { | 1500 | $rawline =~ /^\+\s* \s*/) { |
1451 | my $herevet = "$here\n" . cat_vet($rawline) . "\n"; | 1501 | my $herevet = "$here\n" . cat_vet($rawline) . "\n"; |
1452 | ERROR("code indent should use tabs where possible\n" . $herevet); | 1502 | ERROR("code indent should use tabs where possible\n" . $herevet); |
1503 | $rpt_cleaners = 1; | ||
1453 | } | 1504 | } |
1454 | 1505 | ||
1455 | # check for space before tabs. | 1506 | # check for space before tabs. |
@@ -1459,10 +1510,13 @@ sub process { | |||
1459 | } | 1510 | } |
1460 | 1511 | ||
1461 | # check for spaces at the beginning of a line. | 1512 | # check for spaces at the beginning of a line. |
1462 | if ($rawline =~ /^\+ / && $rawline !~ /\+ +\*/) { | 1513 | # Exceptions: |
1514 | # 1) within comments | ||
1515 | # 2) indented preprocessor commands | ||
1516 | # 3) hanging labels | ||
1517 | if ($rawline =~ /^\+ / && $line !~ /\+ *(?:$;|#|$Ident:)/) { | ||
1463 | my $herevet = "$here\n" . cat_vet($rawline) . "\n"; | 1518 | my $herevet = "$here\n" . cat_vet($rawline) . "\n"; |
1464 | WARN("please, no space for starting a line, \ | 1519 | WARN("please, no spaces at the start of a line\n" . $herevet); |
1465 | excluding comments\n" . $herevet); | ||
1466 | } | 1520 | } |
1467 | 1521 | ||
1468 | # check we are in a valid C source file if not then ignore this hunk | 1522 | # check we are in a valid C source file if not then ignore this hunk |
@@ -1598,7 +1652,7 @@ sub process { | |||
1598 | 1652 | ||
1599 | if ($ctx !~ /{\s*/ && defined($lines[$ctx_ln -1]) && $lines[$ctx_ln - 1] =~ /^\+\s*{/) { | 1653 | if ($ctx !~ /{\s*/ && defined($lines[$ctx_ln -1]) && $lines[$ctx_ln - 1] =~ /^\+\s*{/) { |
1600 | ERROR("that open brace { should be on the previous line\n" . | 1654 | ERROR("that open brace { should be on the previous line\n" . |
1601 | "$here\n$ctx\n$lines[$ctx_ln - 1]\n"); | 1655 | "$here\n$ctx\n$rawlines[$ctx_ln - 1]\n"); |
1602 | } | 1656 | } |
1603 | if ($level == 0 && $pre_ctx !~ /}\s*while\s*\($/ && | 1657 | if ($level == 0 && $pre_ctx !~ /}\s*while\s*\($/ && |
1604 | $ctx =~ /\)\s*\;\s*$/ && | 1658 | $ctx =~ /\)\s*\;\s*$/ && |
@@ -1607,7 +1661,7 @@ sub process { | |||
1607 | my ($nlength, $nindent) = line_stats($lines[$ctx_ln - 1]); | 1661 | my ($nlength, $nindent) = line_stats($lines[$ctx_ln - 1]); |
1608 | if ($nindent > $indent) { | 1662 | if ($nindent > $indent) { |
1609 | WARN("trailing semicolon indicates no statements, indent implies otherwise\n" . | 1663 | WARN("trailing semicolon indicates no statements, indent implies otherwise\n" . |
1610 | "$here\n$ctx\n$lines[$ctx_ln - 1]\n"); | 1664 | "$here\n$ctx\n$rawlines[$ctx_ln - 1]\n"); |
1611 | } | 1665 | } |
1612 | } | 1666 | } |
1613 | } | 1667 | } |
@@ -1768,8 +1822,17 @@ sub process { | |||
1768 | !defined $suppress_export{$realline_next} && | 1822 | !defined $suppress_export{$realline_next} && |
1769 | ($lines[$realline_next - 1] =~ /EXPORT_SYMBOL.*\((.*)\)/ || | 1823 | ($lines[$realline_next - 1] =~ /EXPORT_SYMBOL.*\((.*)\)/ || |
1770 | $lines[$realline_next - 1] =~ /EXPORT_UNUSED_SYMBOL.*\((.*)\)/)) { | 1824 | $lines[$realline_next - 1] =~ /EXPORT_UNUSED_SYMBOL.*\((.*)\)/)) { |
1825 | # Handle definitions which produce identifiers with | ||
1826 | # a prefix: | ||
1827 | # XXX(foo); | ||
1828 | # EXPORT_SYMBOL(something_foo); | ||
1771 | my $name = $1; | 1829 | my $name = $1; |
1772 | if ($stat !~ /(?: | 1830 | if ($stat =~ /^.([A-Z_]+)\s*\(\s*($Ident)/ && |
1831 | $name =~ /^${Ident}_$2/) { | ||
1832 | #print "FOO C name<$name>\n"; | ||
1833 | $suppress_export{$realline_next} = 1; | ||
1834 | |||
1835 | } elsif ($stat !~ /(?: | ||
1773 | \n.}\s*$| | 1836 | \n.}\s*$| |
1774 | ^.DEFINE_$Ident\(\Q$name\E\)| | 1837 | ^.DEFINE_$Ident\(\Q$name\E\)| |
1775 | ^.DECLARE_$Ident\(\Q$name\E\)| | 1838 | ^.DECLARE_$Ident\(\Q$name\E\)| |
@@ -1806,6 +1869,23 @@ sub process { | |||
1806 | $herecurr); | 1869 | $herecurr); |
1807 | } | 1870 | } |
1808 | 1871 | ||
1872 | # check for static const char * arrays. | ||
1873 | if ($line =~ /\bstatic\s+const\s+char\s*\*\s*(\w+)\s*\[\s*\]\s*=\s*/) { | ||
1874 | WARN("static const char * array should probably be static const char * const\n" . | ||
1875 | $herecurr); | ||
1876 | } | ||
1877 | |||
1878 | # check for static char foo[] = "bar" declarations. | ||
1879 | if ($line =~ /\bstatic\s+char\s+(\w+)\s*\[\s*\]\s*=\s*"/) { | ||
1880 | WARN("static char array declaration should probably be static const char\n" . | ||
1881 | $herecurr); | ||
1882 | } | ||
1883 | |||
1884 | # check for declarations of struct pci_device_id | ||
1885 | if ($line =~ /\bstruct\s+pci_device_id\s+\w+\s*\[\s*\]\s*\=\s*\{/) { | ||
1886 | WARN("Use DEFINE_PCI_DEVICE_TABLE for struct pci_device_id\n" . $herecurr); | ||
1887 | } | ||
1888 | |||
1809 | # check for new typedefs, only function parameters and sparse annotations | 1889 | # check for new typedefs, only function parameters and sparse annotations |
1810 | # make sense. | 1890 | # make sense. |
1811 | if ($line =~ /\btypedef\s/ && | 1891 | if ($line =~ /\btypedef\s/ && |
@@ -1899,6 +1979,11 @@ sub process { | |||
1899 | ERROR("open brace '{' following $1 go on the same line\n" . $hereprev); | 1979 | ERROR("open brace '{' following $1 go on the same line\n" . $hereprev); |
1900 | } | 1980 | } |
1901 | 1981 | ||
1982 | # missing space after union, struct or enum definition | ||
1983 | if ($line =~ /^.\s*(?:typedef\s+)?(enum|union|struct)(?:\s+$Ident)?(?:\s+$Ident)?[=\{]/) { | ||
1984 | WARN("missing space after $1 definition\n" . $herecurr); | ||
1985 | } | ||
1986 | |||
1902 | # check for spacing round square brackets; allowed: | 1987 | # check for spacing round square brackets; allowed: |
1903 | # 1. with a type on the left -- int [] a; | 1988 | # 1. with a type on the left -- int [] a; |
1904 | # 2. at the beginning of a line for slice initialisers -- [0...10] = 5, | 1989 | # 2. at the beginning of a line for slice initialisers -- [0...10] = 5, |
@@ -2176,21 +2261,29 @@ sub process { | |||
2176 | my $value = $2; | 2261 | my $value = $2; |
2177 | 2262 | ||
2178 | # Flatten any parentheses | 2263 | # Flatten any parentheses |
2179 | $value =~ s/\)\(/\) \(/g; | 2264 | $value =~ s/\(/ \(/g; |
2265 | $value =~ s/\)/\) /g; | ||
2180 | while ($value =~ s/\[[^\{\}]*\]/1/ || | 2266 | while ($value =~ s/\[[^\{\}]*\]/1/ || |
2181 | $value !~ /(?:$Ident|-?$Constant)\s* | 2267 | $value !~ /(?:$Ident|-?$Constant)\s* |
2182 | $Compare\s* | 2268 | $Compare\s* |
2183 | (?:$Ident|-?$Constant)/x && | 2269 | (?:$Ident|-?$Constant)/x && |
2184 | $value =~ s/\([^\(\)]*\)/1/) { | 2270 | $value =~ s/\([^\(\)]*\)/1/) { |
2185 | } | 2271 | } |
2186 | 2272 | #print "value<$value>\n"; | |
2187 | if ($value =~ /^(?:$Ident|-?$Constant)$/) { | 2273 | if ($value =~ /^\s*(?:$Ident|-?$Constant)\s*$/) { |
2188 | ERROR("return is not a function, parentheses are not required\n" . $herecurr); | 2274 | ERROR("return is not a function, parentheses are not required\n" . $herecurr); |
2189 | 2275 | ||
2190 | } elsif ($spacing !~ /\s+/) { | 2276 | } elsif ($spacing !~ /\s+/) { |
2191 | ERROR("space required before the open parenthesis '('\n" . $herecurr); | 2277 | ERROR("space required before the open parenthesis '('\n" . $herecurr); |
2192 | } | 2278 | } |
2193 | } | 2279 | } |
2280 | # Return of what appears to be an errno should normally be -'ve | ||
2281 | if ($line =~ /^.\s*return\s*(E[A-Z]*)\s*;/) { | ||
2282 | my $name = $1; | ||
2283 | if ($name ne 'EOF' && $name ne 'ERROR') { | ||
2284 | WARN("return of an errno should typically be -ve (return -$1)\n" . $herecurr); | ||
2285 | } | ||
2286 | } | ||
2194 | 2287 | ||
2195 | # Need a space before open parenthesis after if, while etc | 2288 | # Need a space before open parenthesis after if, while etc |
2196 | if ($line=~/\b(if|while|for|switch)\(/) { | 2289 | if ($line=~/\b(if|while|for|switch)\(/) { |
@@ -2409,8 +2502,8 @@ sub process { | |||
2409 | \.$Ident\s*=\s*| | 2502 | \.$Ident\s*=\s*| |
2410 | ^\"|\"$ | 2503 | ^\"|\"$ |
2411 | }x; | 2504 | }x; |
2412 | #print "REST<$rest> dstat<$dstat>\n"; | 2505 | #print "REST<$rest> dstat<$dstat> ctx<$ctx>\n"; |
2413 | if ($rest ne '') { | 2506 | if ($rest ne '' && $rest ne ',') { |
2414 | if ($rest !~ /while\s*\(/ && | 2507 | if ($rest !~ /while\s*\(/ && |
2415 | $dstat !~ /$exceptions/) | 2508 | $dstat !~ /$exceptions/) |
2416 | { | 2509 | { |
@@ -2839,6 +2932,15 @@ sub process { | |||
2839 | print "\n" if ($quiet == 0); | 2932 | print "\n" if ($quiet == 0); |
2840 | } | 2933 | } |
2841 | 2934 | ||
2935 | if ($quiet == 0) { | ||
2936 | # If there were whitespace errors which cleanpatch can fix | ||
2937 | # then suggest that. | ||
2938 | if ($rpt_cleaners) { | ||
2939 | print "NOTE: whitespace errors detected, you may wish to use scripts/cleanpatch or\n"; | ||
2940 | print " scripts/cleanfile\n\n"; | ||
2941 | } | ||
2942 | } | ||
2943 | |||
2842 | if ($clean == 1 && $quiet == 0) { | 2944 | if ($clean == 1 && $quiet == 0) { |
2843 | print "$vname has no obvious style problems and is ready for submission.\n" | 2945 | print "$vname has no obvious style problems and is ready for submission.\n" |
2844 | } | 2946 | } |
diff --git a/scripts/get_maintainer.pl b/scripts/get_maintainer.pl index b2281982f52f..d21ec3a89603 100755 --- a/scripts/get_maintainer.pl +++ b/scripts/get_maintainer.pl | |||
@@ -13,7 +13,7 @@ | |||
13 | use strict; | 13 | use strict; |
14 | 14 | ||
15 | my $P = $0; | 15 | my $P = $0; |
16 | my $V = '0.24'; | 16 | my $V = '0.26-beta6'; |
17 | 17 | ||
18 | use Getopt::Long qw(:config no_auto_abbrev); | 18 | use Getopt::Long qw(:config no_auto_abbrev); |
19 | 19 | ||
@@ -24,15 +24,19 @@ my $email_maintainer = 1; | |||
24 | my $email_list = 1; | 24 | my $email_list = 1; |
25 | my $email_subscriber_list = 0; | 25 | my $email_subscriber_list = 0; |
26 | my $email_git_penguin_chiefs = 0; | 26 | my $email_git_penguin_chiefs = 0; |
27 | my $email_git = 1; | 27 | my $email_git = 0; |
28 | my $email_git_all_signature_types = 0; | 28 | my $email_git_all_signature_types = 0; |
29 | my $email_git_blame = 0; | 29 | my $email_git_blame = 0; |
30 | my $email_git_blame_signatures = 1; | ||
31 | my $email_git_fallback = 1; | ||
30 | my $email_git_min_signatures = 1; | 32 | my $email_git_min_signatures = 1; |
31 | my $email_git_max_maintainers = 5; | 33 | my $email_git_max_maintainers = 5; |
32 | my $email_git_min_percent = 5; | 34 | my $email_git_min_percent = 5; |
33 | my $email_git_since = "1-year-ago"; | 35 | my $email_git_since = "1-year-ago"; |
34 | my $email_hg_since = "-365"; | 36 | my $email_hg_since = "-365"; |
37 | my $interactive = 0; | ||
35 | my $email_remove_duplicates = 1; | 38 | my $email_remove_duplicates = 1; |
39 | my $email_use_mailmap = 1; | ||
36 | my $output_multiline = 1; | 40 | my $output_multiline = 1; |
37 | my $output_separator = ", "; | 41 | my $output_separator = ", "; |
38 | my $output_roles = 0; | 42 | my $output_roles = 0; |
@@ -49,8 +53,13 @@ my $pattern_depth = 0; | |||
49 | my $version = 0; | 53 | my $version = 0; |
50 | my $help = 0; | 54 | my $help = 0; |
51 | 55 | ||
56 | my $vcs_used = 0; | ||
57 | |||
52 | my $exit = 0; | 58 | my $exit = 0; |
53 | 59 | ||
60 | my %commit_author_hash; | ||
61 | my %commit_signer_hash; | ||
62 | |||
54 | my @penguin_chief = (); | 63 | my @penguin_chief = (); |
55 | push(@penguin_chief, "Linus Torvalds:torvalds\@linux-foundation.org"); | 64 | push(@penguin_chief, "Linus Torvalds:torvalds\@linux-foundation.org"); |
56 | #Andrew wants in on most everything - 2009/01/14 | 65 | #Andrew wants in on most everything - 2009/01/14 |
@@ -73,7 +82,6 @@ my @signature_tags = (); | |||
73 | push(@signature_tags, "Signed-off-by:"); | 82 | push(@signature_tags, "Signed-off-by:"); |
74 | push(@signature_tags, "Reviewed-by:"); | 83 | push(@signature_tags, "Reviewed-by:"); |
75 | push(@signature_tags, "Acked-by:"); | 84 | push(@signature_tags, "Acked-by:"); |
76 | my $signaturePattern = "\(" . join("|", @signature_tags) . "\)"; | ||
77 | 85 | ||
78 | # rfc822 email address - preloaded methods go here. | 86 | # rfc822 email address - preloaded methods go here. |
79 | my $rfc822_lwsp = "(?:(?:\\r\\n)?[ \\t])"; | 87 | my $rfc822_lwsp = "(?:(?:\\r\\n)?[ \\t])"; |
@@ -86,31 +94,70 @@ my %VCS_cmds; | |||
86 | my %VCS_cmds_git = ( | 94 | my %VCS_cmds_git = ( |
87 | "execute_cmd" => \&git_execute_cmd, | 95 | "execute_cmd" => \&git_execute_cmd, |
88 | "available" => '(which("git") ne "") && (-d ".git")', | 96 | "available" => '(which("git") ne "") && (-d ".git")', |
89 | "find_signers_cmd" => "git log --no-color --since=\$email_git_since -- \$file", | 97 | "find_signers_cmd" => |
90 | "find_commit_signers_cmd" => "git log --no-color -1 \$commit", | 98 | "git log --no-color --since=\$email_git_since " . |
99 | '--format="GitCommit: %H%n' . | ||
100 | 'GitAuthor: %an <%ae>%n' . | ||
101 | 'GitDate: %aD%n' . | ||
102 | 'GitSubject: %s%n' . | ||
103 | '%b%n"' . | ||
104 | " -- \$file", | ||
105 | "find_commit_signers_cmd" => | ||
106 | "git log --no-color " . | ||
107 | '--format="GitCommit: %H%n' . | ||
108 | 'GitAuthor: %an <%ae>%n' . | ||
109 | 'GitDate: %aD%n' . | ||
110 | 'GitSubject: %s%n' . | ||
111 | '%b%n"' . | ||
112 | " -1 \$commit", | ||
113 | "find_commit_author_cmd" => | ||
114 | "git log --no-color " . | ||
115 | '--format="GitCommit: %H%n' . | ||
116 | 'GitAuthor: %an <%ae>%n' . | ||
117 | 'GitDate: %aD%n' . | ||
118 | 'GitSubject: %s%n"' . | ||
119 | " -1 \$commit", | ||
91 | "blame_range_cmd" => "git blame -l -L \$diff_start,+\$diff_length \$file", | 120 | "blame_range_cmd" => "git blame -l -L \$diff_start,+\$diff_length \$file", |
92 | "blame_file_cmd" => "git blame -l \$file", | 121 | "blame_file_cmd" => "git blame -l \$file", |
93 | "commit_pattern" => "^commit [0-9a-f]{40,40}", | 122 | "commit_pattern" => "^GitCommit: ([0-9a-f]{40,40})", |
94 | "blame_commit_pattern" => "^([0-9a-f]+) " | 123 | "blame_commit_pattern" => "^([0-9a-f]+) ", |
124 | "author_pattern" => "^GitAuthor: (.*)", | ||
125 | "subject_pattern" => "^GitSubject: (.*)", | ||
95 | ); | 126 | ); |
96 | 127 | ||
97 | my %VCS_cmds_hg = ( | 128 | my %VCS_cmds_hg = ( |
98 | "execute_cmd" => \&hg_execute_cmd, | 129 | "execute_cmd" => \&hg_execute_cmd, |
99 | "available" => '(which("hg") ne "") && (-d ".hg")', | 130 | "available" => '(which("hg") ne "") && (-d ".hg")', |
100 | "find_signers_cmd" => | 131 | "find_signers_cmd" => |
101 | "hg log --date=\$email_hg_since" . | 132 | "hg log --date=\$email_hg_since " . |
102 | " --template='commit {node}\\n{desc}\\n' -- \$file", | 133 | "--template='HgCommit: {node}\\n" . |
103 | "find_commit_signers_cmd" => "hg log --template='{desc}\\n' -r \$commit", | 134 | "HgAuthor: {author}\\n" . |
135 | "HgSubject: {desc}\\n'" . | ||
136 | " -- \$file", | ||
137 | "find_commit_signers_cmd" => | ||
138 | "hg log " . | ||
139 | "--template='HgSubject: {desc}\\n'" . | ||
140 | " -r \$commit", | ||
141 | "find_commit_author_cmd" => | ||
142 | "hg log " . | ||
143 | "--template='HgCommit: {node}\\n" . | ||
144 | "HgAuthor: {author}\\n" . | ||
145 | "HgSubject: {desc|firstline}\\n'" . | ||
146 | " -r \$commit", | ||
104 | "blame_range_cmd" => "", # not supported | 147 | "blame_range_cmd" => "", # not supported |
105 | "blame_file_cmd" => "hg blame -c \$file", | 148 | "blame_file_cmd" => "hg blame -n \$file", |
106 | "commit_pattern" => "^commit [0-9a-f]{40,40}", | 149 | "commit_pattern" => "^HgCommit: ([0-9a-f]{40,40})", |
107 | "blame_commit_pattern" => "^([0-9a-f]+):" | 150 | "blame_commit_pattern" => "^([ 0-9a-f]+):", |
151 | "author_pattern" => "^HgAuthor: (.*)", | ||
152 | "subject_pattern" => "^HgSubject: (.*)", | ||
108 | ); | 153 | ); |
109 | 154 | ||
110 | if (-f "${lk_path}.get_maintainer.conf") { | 155 | my $conf = which_conf(".get_maintainer.conf"); |
156 | if (-f $conf) { | ||
111 | my @conf_args; | 157 | my @conf_args; |
112 | open(my $conffile, '<', "${lk_path}.get_maintainer.conf") | 158 | open(my $conffile, '<', "$conf") |
113 | or warn "$P: Can't open .get_maintainer.conf: $!\n"; | 159 | or warn "$P: Can't find a readable .get_maintainer.conf file $!\n"; |
160 | |||
114 | while (<$conffile>) { | 161 | while (<$conffile>) { |
115 | my $line = $_; | 162 | my $line = $_; |
116 | 163 | ||
@@ -136,13 +183,17 @@ if (!GetOptions( | |||
136 | 'git!' => \$email_git, | 183 | 'git!' => \$email_git, |
137 | 'git-all-signature-types!' => \$email_git_all_signature_types, | 184 | 'git-all-signature-types!' => \$email_git_all_signature_types, |
138 | 'git-blame!' => \$email_git_blame, | 185 | 'git-blame!' => \$email_git_blame, |
186 | 'git-blame-signatures!' => \$email_git_blame_signatures, | ||
187 | 'git-fallback!' => \$email_git_fallback, | ||
139 | 'git-chief-penguins!' => \$email_git_penguin_chiefs, | 188 | 'git-chief-penguins!' => \$email_git_penguin_chiefs, |
140 | 'git-min-signatures=i' => \$email_git_min_signatures, | 189 | 'git-min-signatures=i' => \$email_git_min_signatures, |
141 | 'git-max-maintainers=i' => \$email_git_max_maintainers, | 190 | 'git-max-maintainers=i' => \$email_git_max_maintainers, |
142 | 'git-min-percent=i' => \$email_git_min_percent, | 191 | 'git-min-percent=i' => \$email_git_min_percent, |
143 | 'git-since=s' => \$email_git_since, | 192 | 'git-since=s' => \$email_git_since, |
144 | 'hg-since=s' => \$email_hg_since, | 193 | 'hg-since=s' => \$email_hg_since, |
194 | 'i|interactive!' => \$interactive, | ||
145 | 'remove-duplicates!' => \$email_remove_duplicates, | 195 | 'remove-duplicates!' => \$email_remove_duplicates, |
196 | 'mailmap!' => \$email_use_mailmap, | ||
146 | 'm!' => \$email_maintainer, | 197 | 'm!' => \$email_maintainer, |
147 | 'n!' => \$email_usename, | 198 | 'n!' => \$email_usename, |
148 | 'l!' => \$email_list, | 199 | 'l!' => \$email_list, |
@@ -181,13 +232,9 @@ if (-t STDIN && !@ARGV) { | |||
181 | die "$P: missing patchfile or -f file - use --help if necessary\n"; | 232 | die "$P: missing patchfile or -f file - use --help if necessary\n"; |
182 | } | 233 | } |
183 | 234 | ||
184 | if ($output_separator ne ", ") { | 235 | $output_multiline = 0 if ($output_separator ne ", "); |
185 | $output_multiline = 0; | 236 | $output_rolestats = 1 if ($interactive); |
186 | } | 237 | $output_roles = 1 if ($output_rolestats); |
187 | |||
188 | if ($output_rolestats) { | ||
189 | $output_roles = 1; | ||
190 | } | ||
191 | 238 | ||
192 | if ($sections) { | 239 | if ($sections) { |
193 | $email = 0; | 240 | $email = 0; |
@@ -197,6 +244,7 @@ if ($sections) { | |||
197 | $subsystem = 0; | 244 | $subsystem = 0; |
198 | $web = 0; | 245 | $web = 0; |
199 | $keywords = 0; | 246 | $keywords = 0; |
247 | $interactive = 0; | ||
200 | } else { | 248 | } else { |
201 | my $selections = $email + $scm + $status + $subsystem + $web; | 249 | my $selections = $email + $scm + $status + $subsystem + $web; |
202 | if ($selections == 0) { | 250 | if ($selections == 0) { |
@@ -215,10 +263,6 @@ if (!top_of_kernel_tree($lk_path)) { | |||
215 | . "a linux kernel source tree.\n"; | 263 | . "a linux kernel source tree.\n"; |
216 | } | 264 | } |
217 | 265 | ||
218 | if ($email_git_all_signature_types) { | ||
219 | $signaturePattern = "(.+?)[Bb][Yy]:"; | ||
220 | } | ||
221 | |||
222 | ## Read MAINTAINERS for type/value pairs | 266 | ## Read MAINTAINERS for type/value pairs |
223 | 267 | ||
224 | my @typevalue = (); | 268 | my @typevalue = (); |
@@ -253,31 +297,82 @@ while (<$maint>) { | |||
253 | } | 297 | } |
254 | close($maint); | 298 | close($maint); |
255 | 299 | ||
256 | my %mailmap; | ||
257 | 300 | ||
258 | if ($email_remove_duplicates) { | 301 | # |
259 | open(my $mailmap, '<', "${lk_path}.mailmap") | 302 | # Read mail address map |
260 | or warn "$P: Can't open .mailmap: $!\n"; | 303 | # |
261 | while (<$mailmap>) { | ||
262 | my $line = $_; | ||
263 | 304 | ||
264 | next if ($line =~ m/^\s*#/); | 305 | my $mailmap; |
265 | next if ($line =~ m/^\s*$/); | ||
266 | 306 | ||
267 | my ($name, $address) = parse_email($line); | 307 | read_mailmap(); |
268 | $line = format_email($name, $address, $email_usename); | ||
269 | 308 | ||
270 | next if ($line =~ m/^\s*$/); | 309 | sub read_mailmap { |
310 | $mailmap = { | ||
311 | names => {}, | ||
312 | addresses => {} | ||
313 | }; | ||
271 | 314 | ||
272 | if (exists($mailmap{$name})) { | 315 | return if (!$email_use_mailmap || !(-f "${lk_path}.mailmap")); |
273 | my $obj = $mailmap{$name}; | 316 | |
274 | push(@$obj, $address); | 317 | open(my $mailmap_file, '<', "${lk_path}.mailmap") |
275 | } else { | 318 | or warn "$P: Can't open .mailmap: $!\n"; |
276 | my @arr = ($address); | 319 | |
277 | $mailmap{$name} = \@arr; | 320 | while (<$mailmap_file>) { |
321 | s/#.*$//; #strip comments | ||
322 | s/^\s+|\s+$//g; #trim | ||
323 | |||
324 | next if (/^\s*$/); #skip empty lines | ||
325 | #entries have one of the following formats: | ||
326 | # name1 <mail1> | ||
327 | # <mail1> <mail2> | ||
328 | # name1 <mail1> <mail2> | ||
329 | # name1 <mail1> name2 <mail2> | ||
330 | # (see man git-shortlog) | ||
331 | if (/^(.+)<(.+)>$/) { | ||
332 | my $real_name = $1; | ||
333 | my $address = $2; | ||
334 | |||
335 | $real_name =~ s/\s+$//; | ||
336 | ($real_name, $address) = parse_email("$real_name <$address>"); | ||
337 | $mailmap->{names}->{$address} = $real_name; | ||
338 | |||
339 | } elsif (/^<([^\s]+)>\s*<([^\s]+)>$/) { | ||
340 | my $real_address = $1; | ||
341 | my $wrong_address = $2; | ||
342 | |||
343 | $mailmap->{addresses}->{$wrong_address} = $real_address; | ||
344 | |||
345 | } elsif (/^(.+)<([^\s]+)>\s*<([^\s]+)>$/) { | ||
346 | my $real_name = $1; | ||
347 | my $real_address = $2; | ||
348 | my $wrong_address = $3; | ||
349 | |||
350 | $real_name =~ s/\s+$//; | ||
351 | ($real_name, $real_address) = | ||
352 | parse_email("$real_name <$real_address>"); | ||
353 | $mailmap->{names}->{$wrong_address} = $real_name; | ||
354 | $mailmap->{addresses}->{$wrong_address} = $real_address; | ||
355 | |||
356 | } elsif (/^(.+)<([^\s]+)>\s*([^\s].*)<([^\s]+)>$/) { | ||
357 | my $real_name = $1; | ||
358 | my $real_address = $2; | ||
359 | my $wrong_name = $3; | ||
360 | my $wrong_address = $4; | ||
361 | |||
362 | $real_name =~ s/\s+$//; | ||
363 | ($real_name, $real_address) = | ||
364 | parse_email("$real_name <$real_address>"); | ||
365 | |||
366 | $wrong_name =~ s/\s+$//; | ||
367 | ($wrong_name, $wrong_address) = | ||
368 | parse_email("$wrong_name <$wrong_address>"); | ||
369 | |||
370 | my $wrong_email = format_email($wrong_name, $wrong_address, 1); | ||
371 | $mailmap->{names}->{$wrong_email} = $real_name; | ||
372 | $mailmap->{addresses}->{$wrong_email} = $real_address; | ||
278 | } | 373 | } |
279 | } | 374 | } |
280 | close($mailmap); | 375 | close($mailmap_file); |
281 | } | 376 | } |
282 | 377 | ||
283 | ## use the filenames on the command line or find the filenames in the patchfiles | 378 | ## use the filenames on the command line or find the filenames in the patchfiles |
@@ -302,7 +397,7 @@ foreach my $file (@ARGV) { | |||
302 | } | 397 | } |
303 | if ($from_filename) { | 398 | if ($from_filename) { |
304 | push(@files, $file); | 399 | push(@files, $file); |
305 | if (-f $file && ($keywords || $file_emails)) { | 400 | if ($file ne "MAINTAINERS" && -f $file && ($keywords || $file_emails)) { |
306 | open(my $f, '<', $file) | 401 | open(my $f, '<', $file) |
307 | or die "$P: Can't open $file: $!\n"; | 402 | or die "$P: Can't open $file: $!\n"; |
308 | my $text = do { local($/) ; <$f> }; | 403 | my $text = do { local($/) ; <$f> }; |
@@ -357,67 +452,127 @@ foreach my $file (@ARGV) { | |||
357 | 452 | ||
358 | @file_emails = uniq(@file_emails); | 453 | @file_emails = uniq(@file_emails); |
359 | 454 | ||
455 | my %email_hash_name; | ||
456 | my %email_hash_address; | ||
360 | my @email_to = (); | 457 | my @email_to = (); |
458 | my %hash_list_to; | ||
361 | my @list_to = (); | 459 | my @list_to = (); |
362 | my @scm = (); | 460 | my @scm = (); |
363 | my @web = (); | 461 | my @web = (); |
364 | my @subsystem = (); | 462 | my @subsystem = (); |
365 | my @status = (); | 463 | my @status = (); |
464 | my %deduplicate_name_hash = (); | ||
465 | my %deduplicate_address_hash = (); | ||
466 | my $signature_pattern; | ||
366 | 467 | ||
367 | # Find responsible parties | 468 | my @maintainers = get_maintainers(); |
368 | 469 | ||
369 | foreach my $file (@files) { | 470 | if (@maintainers) { |
471 | @maintainers = merge_email(@maintainers); | ||
472 | output(@maintainers); | ||
473 | } | ||
370 | 474 | ||
371 | my %hash; | 475 | if ($scm) { |
372 | my $tvi = find_first_section(); | 476 | @scm = uniq(@scm); |
373 | while ($tvi < @typevalue) { | 477 | output(@scm); |
374 | my $start = find_starting_index($tvi); | 478 | } |
375 | my $end = find_ending_index($tvi); | 479 | |
376 | my $exclude = 0; | 480 | if ($status) { |
377 | my $i; | 481 | @status = uniq(@status); |
378 | 482 | output(@status); | |
379 | #Do not match excluded file patterns | 483 | } |
380 | 484 | ||
381 | for ($i = $start; $i < $end; $i++) { | 485 | if ($subsystem) { |
382 | my $line = $typevalue[$i]; | 486 | @subsystem = uniq(@subsystem); |
383 | if ($line =~ m/^(\C):\s*(.*)/) { | 487 | output(@subsystem); |
384 | my $type = $1; | 488 | } |
385 | my $value = $2; | 489 | |
386 | if ($type eq 'X') { | 490 | if ($web) { |
387 | if (file_match_pattern($file, $value)) { | 491 | @web = uniq(@web); |
388 | $exclude = 1; | 492 | output(@web); |
389 | last; | 493 | } |
390 | } | 494 | |
391 | } | 495 | exit($exit); |
392 | } | 496 | |
393 | } | 497 | sub get_maintainers { |
498 | %email_hash_name = (); | ||
499 | %email_hash_address = (); | ||
500 | %commit_author_hash = (); | ||
501 | %commit_signer_hash = (); | ||
502 | @email_to = (); | ||
503 | %hash_list_to = (); | ||
504 | @list_to = (); | ||
505 | @scm = (); | ||
506 | @web = (); | ||
507 | @subsystem = (); | ||
508 | @status = (); | ||
509 | %deduplicate_name_hash = (); | ||
510 | %deduplicate_address_hash = (); | ||
511 | if ($email_git_all_signature_types) { | ||
512 | $signature_pattern = "(.+?)[Bb][Yy]:"; | ||
513 | } else { | ||
514 | $signature_pattern = "\(" . join("|", @signature_tags) . "\)"; | ||
515 | } | ||
516 | |||
517 | # Find responsible parties | ||
518 | |||
519 | my %exact_pattern_match_hash = (); | ||
520 | |||
521 | foreach my $file (@files) { | ||
522 | |||
523 | my %hash; | ||
524 | my $tvi = find_first_section(); | ||
525 | while ($tvi < @typevalue) { | ||
526 | my $start = find_starting_index($tvi); | ||
527 | my $end = find_ending_index($tvi); | ||
528 | my $exclude = 0; | ||
529 | my $i; | ||
530 | |||
531 | #Do not match excluded file patterns | ||
394 | 532 | ||
395 | if (!$exclude) { | ||
396 | for ($i = $start; $i < $end; $i++) { | 533 | for ($i = $start; $i < $end; $i++) { |
397 | my $line = $typevalue[$i]; | 534 | my $line = $typevalue[$i]; |
398 | if ($line =~ m/^(\C):\s*(.*)/) { | 535 | if ($line =~ m/^(\C):\s*(.*)/) { |
399 | my $type = $1; | 536 | my $type = $1; |
400 | my $value = $2; | 537 | my $value = $2; |
401 | if ($type eq 'F') { | 538 | if ($type eq 'X') { |
402 | if (file_match_pattern($file, $value)) { | 539 | if (file_match_pattern($file, $value)) { |
403 | my $value_pd = ($value =~ tr@/@@); | 540 | $exclude = 1; |
404 | my $file_pd = ($file =~ tr@/@@); | 541 | last; |
405 | $value_pd++ if (substr($value,-1,1) ne "/"); | 542 | } |
406 | if ($pattern_depth == 0 || | 543 | } |
407 | (($file_pd - $value_pd) < $pattern_depth)) { | 544 | } |
408 | $hash{$tvi} = $value_pd; | 545 | } |
546 | |||
547 | if (!$exclude) { | ||
548 | for ($i = $start; $i < $end; $i++) { | ||
549 | my $line = $typevalue[$i]; | ||
550 | if ($line =~ m/^(\C):\s*(.*)/) { | ||
551 | my $type = $1; | ||
552 | my $value = $2; | ||
553 | if ($type eq 'F') { | ||
554 | if (file_match_pattern($file, $value)) { | ||
555 | my $value_pd = ($value =~ tr@/@@); | ||
556 | my $file_pd = ($file =~ tr@/@@); | ||
557 | $value_pd++ if (substr($value,-1,1) ne "/"); | ||
558 | $value_pd = -1 if ($value =~ /^\.\*/); | ||
559 | if ($value_pd >= $file_pd) { | ||
560 | $exact_pattern_match_hash{$file} = 1; | ||
561 | } | ||
562 | if ($pattern_depth == 0 || | ||
563 | (($file_pd - $value_pd) < $pattern_depth)) { | ||
564 | $hash{$tvi} = $value_pd; | ||
565 | } | ||
409 | } | 566 | } |
410 | } | 567 | } |
411 | } | 568 | } |
412 | } | 569 | } |
413 | } | 570 | } |
571 | $tvi = $end + 1; | ||
414 | } | 572 | } |
415 | 573 | ||
416 | $tvi = $end + 1; | 574 | foreach my $line (sort {$hash{$b} <=> $hash{$a}} keys %hash) { |
417 | } | 575 | add_categories($line); |
418 | |||
419 | foreach my $line (sort {$hash{$b} <=> $hash{$a}} keys %hash) { | ||
420 | add_categories($line); | ||
421 | if ($sections) { | 576 | if ($sections) { |
422 | my $i; | 577 | my $i; |
423 | my $start = find_starting_index($line); | 578 | my $start = find_starting_index($line); |
@@ -435,80 +590,71 @@ foreach my $file (@files) { | |||
435 | } | 590 | } |
436 | print("\n"); | 591 | print("\n"); |
437 | } | 592 | } |
593 | } | ||
438 | } | 594 | } |
439 | 595 | ||
440 | if ($email && $email_git) { | 596 | if ($keywords) { |
441 | vcs_file_signoffs($file); | 597 | @keyword_tvi = sort_and_uniq(@keyword_tvi); |
598 | foreach my $line (@keyword_tvi) { | ||
599 | add_categories($line); | ||
600 | } | ||
442 | } | 601 | } |
443 | 602 | ||
444 | if ($email && $email_git_blame) { | 603 | foreach my $email (@email_to, @list_to) { |
445 | vcs_file_blame($file); | 604 | $email->[0] = deduplicate_email($email->[0]); |
446 | } | 605 | } |
447 | } | ||
448 | 606 | ||
449 | if ($keywords) { | 607 | foreach my $file (@files) { |
450 | @keyword_tvi = sort_and_uniq(@keyword_tvi); | 608 | if ($email && |
451 | foreach my $line (@keyword_tvi) { | 609 | ($email_git || ($email_git_fallback && |
452 | add_categories($line); | 610 | !$exact_pattern_match_hash{$file}))) { |
611 | vcs_file_signoffs($file); | ||
612 | } | ||
613 | if ($email && $email_git_blame) { | ||
614 | vcs_file_blame($file); | ||
615 | } | ||
453 | } | 616 | } |
454 | } | ||
455 | 617 | ||
456 | if ($email) { | 618 | if ($email) { |
457 | foreach my $chief (@penguin_chief) { | 619 | foreach my $chief (@penguin_chief) { |
458 | if ($chief =~ m/^(.*):(.*)/) { | 620 | if ($chief =~ m/^(.*):(.*)/) { |
459 | my $email_address; | 621 | my $email_address; |
460 | 622 | ||
461 | $email_address = format_email($1, $2, $email_usename); | 623 | $email_address = format_email($1, $2, $email_usename); |
462 | if ($email_git_penguin_chiefs) { | 624 | if ($email_git_penguin_chiefs) { |
463 | push(@email_to, [$email_address, 'chief penguin']); | 625 | push(@email_to, [$email_address, 'chief penguin']); |
464 | } else { | 626 | } else { |
465 | @email_to = grep($_->[0] !~ /${email_address}/, @email_to); | 627 | @email_to = grep($_->[0] !~ /${email_address}/, @email_to); |
628 | } | ||
466 | } | 629 | } |
467 | } | 630 | } |
468 | } | ||
469 | 631 | ||
470 | foreach my $email (@file_emails) { | 632 | foreach my $email (@file_emails) { |
471 | my ($name, $address) = parse_email($email); | 633 | my ($name, $address) = parse_email($email); |
472 | 634 | ||
473 | my $tmp_email = format_email($name, $address, $email_usename); | 635 | my $tmp_email = format_email($name, $address, $email_usename); |
474 | push_email_address($tmp_email, ''); | 636 | push_email_address($tmp_email, ''); |
475 | add_role($tmp_email, 'in file'); | 637 | add_role($tmp_email, 'in file'); |
638 | } | ||
476 | } | 639 | } |
477 | } | ||
478 | 640 | ||
479 | if ($email || $email_list) { | ||
480 | my @to = (); | 641 | my @to = (); |
481 | if ($email) { | 642 | if ($email || $email_list) { |
482 | @to = (@to, @email_to); | 643 | if ($email) { |
483 | } | 644 | @to = (@to, @email_to); |
484 | if ($email_list) { | 645 | } |
485 | @to = (@to, @list_to); | 646 | if ($email_list) { |
647 | @to = (@to, @list_to); | ||
648 | } | ||
486 | } | 649 | } |
487 | output(merge_email(@to)); | ||
488 | } | ||
489 | |||
490 | if ($scm) { | ||
491 | @scm = uniq(@scm); | ||
492 | output(@scm); | ||
493 | } | ||
494 | |||
495 | if ($status) { | ||
496 | @status = uniq(@status); | ||
497 | output(@status); | ||
498 | } | ||
499 | 650 | ||
500 | if ($subsystem) { | 651 | if ($interactive) { |
501 | @subsystem = uniq(@subsystem); | 652 | @to = interactive_get_maintainers(\@to); |
502 | output(@subsystem); | 653 | } |
503 | } | ||
504 | 654 | ||
505 | if ($web) { | 655 | return @to; |
506 | @web = uniq(@web); | ||
507 | output(@web); | ||
508 | } | 656 | } |
509 | 657 | ||
510 | exit($exit); | ||
511 | |||
512 | sub file_match_pattern { | 658 | sub file_match_pattern { |
513 | my ($file, $pattern) = @_; | 659 | my ($file, $pattern) = @_; |
514 | if (substr($pattern, -1) eq "/") { | 660 | if (substr($pattern, -1) eq "/") { |
@@ -537,7 +683,8 @@ MAINTAINER field selection options: | |||
537 | --email => print email address(es) if any | 683 | --email => print email address(es) if any |
538 | --git => include recent git \*-by: signers | 684 | --git => include recent git \*-by: signers |
539 | --git-all-signature-types => include signers regardless of signature type | 685 | --git-all-signature-types => include signers regardless of signature type |
540 | or use only ${signaturePattern} signers (default: $email_git_all_signature_types) | 686 | or use only ${signature_pattern} signers (default: $email_git_all_signature_types) |
687 | --git-fallback => use git when no exact MAINTAINERS pattern (default: $email_git_fallback) | ||
541 | --git-chief-penguins => include ${penguin_chiefs} | 688 | --git-chief-penguins => include ${penguin_chiefs} |
542 | --git-min-signatures => number of signatures required (default: $email_git_min_signatures) | 689 | --git-min-signatures => number of signatures required (default: $email_git_min_signatures) |
543 | --git-max-maintainers => maximum maintainers to add (default: $email_git_max_maintainers) | 690 | --git-max-maintainers => maximum maintainers to add (default: $email_git_max_maintainers) |
@@ -545,6 +692,7 @@ MAINTAINER field selection options: | |||
545 | --git-blame => use git blame to find modified commits for patch or file | 692 | --git-blame => use git blame to find modified commits for patch or file |
546 | --git-since => git history to use (default: $email_git_since) | 693 | --git-since => git history to use (default: $email_git_since) |
547 | --hg-since => hg history to use (default: $email_hg_since) | 694 | --hg-since => hg history to use (default: $email_hg_since) |
695 | --interactive => display a menu (mostly useful if used with the --git option) | ||
548 | --m => include maintainer(s) if any | 696 | --m => include maintainer(s) if any |
549 | --n => include name 'Full Name <addr\@domain.tld>' | 697 | --n => include name 'Full Name <addr\@domain.tld>' |
550 | --l => include list(s) if any | 698 | --l => include list(s) if any |
@@ -565,8 +713,9 @@ Output type options: | |||
565 | 713 | ||
566 | Other options: | 714 | Other options: |
567 | --pattern-depth => Number of pattern directory traversals (default: 0 (all)) | 715 | --pattern-depth => Number of pattern directory traversals (default: 0 (all)) |
568 | --keywords => scan patch for keywords (default: 1 (on)) | 716 | --keywords => scan patch for keywords (default: $keywords) |
569 | --sections => print the entire subsystem sections with pattern matches | 717 | --sections => print all of the subsystem sections with pattern matches |
718 | --mailmap => use .mailmap file (default: $email_use_mailmap) | ||
570 | --version => show version | 719 | --version => show version |
571 | --help => show this help information | 720 | --help => show this help information |
572 | 721 | ||
@@ -606,30 +755,30 @@ EOT | |||
606 | } | 755 | } |
607 | 756 | ||
608 | sub top_of_kernel_tree { | 757 | sub top_of_kernel_tree { |
609 | my ($lk_path) = @_; | 758 | my ($lk_path) = @_; |
610 | 759 | ||
611 | if ($lk_path ne "" && substr($lk_path,length($lk_path)-1,1) ne "/") { | 760 | if ($lk_path ne "" && substr($lk_path,length($lk_path)-1,1) ne "/") { |
612 | $lk_path .= "/"; | 761 | $lk_path .= "/"; |
613 | } | 762 | } |
614 | if ( (-f "${lk_path}COPYING") | 763 | if ( (-f "${lk_path}COPYING") |
615 | && (-f "${lk_path}CREDITS") | 764 | && (-f "${lk_path}CREDITS") |
616 | && (-f "${lk_path}Kbuild") | 765 | && (-f "${lk_path}Kbuild") |
617 | && (-f "${lk_path}MAINTAINERS") | 766 | && (-f "${lk_path}MAINTAINERS") |
618 | && (-f "${lk_path}Makefile") | 767 | && (-f "${lk_path}Makefile") |
619 | && (-f "${lk_path}README") | 768 | && (-f "${lk_path}README") |
620 | && (-d "${lk_path}Documentation") | 769 | && (-d "${lk_path}Documentation") |
621 | && (-d "${lk_path}arch") | 770 | && (-d "${lk_path}arch") |
622 | && (-d "${lk_path}include") | 771 | && (-d "${lk_path}include") |
623 | && (-d "${lk_path}drivers") | 772 | && (-d "${lk_path}drivers") |
624 | && (-d "${lk_path}fs") | 773 | && (-d "${lk_path}fs") |
625 | && (-d "${lk_path}init") | 774 | && (-d "${lk_path}init") |
626 | && (-d "${lk_path}ipc") | 775 | && (-d "${lk_path}ipc") |
627 | && (-d "${lk_path}kernel") | 776 | && (-d "${lk_path}kernel") |
628 | && (-d "${lk_path}lib") | 777 | && (-d "${lk_path}lib") |
629 | && (-d "${lk_path}scripts")) { | 778 | && (-d "${lk_path}scripts")) { |
630 | return 1; | 779 | return 1; |
631 | } | 780 | } |
632 | return 0; | 781 | return 0; |
633 | } | 782 | } |
634 | 783 | ||
635 | sub parse_email { | 784 | sub parse_email { |
@@ -821,11 +970,19 @@ sub add_categories { | |||
821 | } | 970 | } |
822 | if ($list_additional =~ m/subscribers-only/) { | 971 | if ($list_additional =~ m/subscribers-only/) { |
823 | if ($email_subscriber_list) { | 972 | if ($email_subscriber_list) { |
824 | push(@list_to, [$list_address, "subscriber list${list_role}"]); | 973 | if (!$hash_list_to{lc($list_address)}) { |
974 | $hash_list_to{lc($list_address)} = 1; | ||
975 | push(@list_to, [$list_address, | ||
976 | "subscriber list${list_role}"]); | ||
977 | } | ||
825 | } | 978 | } |
826 | } else { | 979 | } else { |
827 | if ($email_list) { | 980 | if ($email_list) { |
828 | push(@list_to, [$list_address, "open list${list_role}"]); | 981 | if (!$hash_list_to{lc($list_address)}) { |
982 | $hash_list_to{lc($list_address)} = 1; | ||
983 | push(@list_to, [$list_address, | ||
984 | "open list${list_role}"]); | ||
985 | } | ||
829 | } | 986 | } |
830 | } | 987 | } |
831 | } elsif ($ptype eq "M") { | 988 | } elsif ($ptype eq "M") { |
@@ -856,15 +1013,12 @@ sub add_categories { | |||
856 | } | 1013 | } |
857 | } | 1014 | } |
858 | 1015 | ||
859 | my %email_hash_name; | ||
860 | my %email_hash_address; | ||
861 | |||
862 | sub email_inuse { | 1016 | sub email_inuse { |
863 | my ($name, $address) = @_; | 1017 | my ($name, $address) = @_; |
864 | 1018 | ||
865 | return 1 if (($name eq "") && ($address eq "")); | 1019 | return 1 if (($name eq "") && ($address eq "")); |
866 | return 1 if (($name ne "") && exists($email_hash_name{$name})); | 1020 | return 1 if (($name ne "") && exists($email_hash_name{lc($name)})); |
867 | return 1 if (($address ne "") && exists($email_hash_address{$address})); | 1021 | return 1 if (($address ne "") && exists($email_hash_address{lc($address)})); |
868 | 1022 | ||
869 | return 0; | 1023 | return 0; |
870 | } | 1024 | } |
@@ -882,8 +1036,8 @@ sub push_email_address { | |||
882 | push(@email_to, [format_email($name, $address, $email_usename), $role]); | 1036 | push(@email_to, [format_email($name, $address, $email_usename), $role]); |
883 | } elsif (!email_inuse($name, $address)) { | 1037 | } elsif (!email_inuse($name, $address)) { |
884 | push(@email_to, [format_email($name, $address, $email_usename), $role]); | 1038 | push(@email_to, [format_email($name, $address, $email_usename), $role]); |
885 | $email_hash_name{$name}++; | 1039 | $email_hash_name{lc($name)}++ if ($name ne ""); |
886 | $email_hash_address{$address}++; | 1040 | $email_hash_address{lc($address)}++; |
887 | } | 1041 | } |
888 | 1042 | ||
889 | return 1; | 1043 | return 1; |
@@ -952,30 +1106,69 @@ sub which { | |||
952 | return ""; | 1106 | return ""; |
953 | } | 1107 | } |
954 | 1108 | ||
955 | sub mailmap { | 1109 | sub which_conf { |
956 | my (@lines) = @_; | 1110 | my ($conf) = @_; |
957 | my %hash; | ||
958 | 1111 | ||
959 | foreach my $line (@lines) { | 1112 | foreach my $path (split(/:/, ".:$ENV{HOME}:.scripts")) { |
960 | my ($name, $address) = parse_email($line); | 1113 | if (-e "$path/$conf") { |
961 | if (!exists($hash{$name})) { | 1114 | return "$path/$conf"; |
962 | $hash{$name} = $address; | ||
963 | } elsif ($address ne $hash{$name}) { | ||
964 | $address = $hash{$name}; | ||
965 | $line = format_email($name, $address, $email_usename); | ||
966 | } | 1115 | } |
967 | if (exists($mailmap{$name})) { | 1116 | } |
968 | my $obj = $mailmap{$name}; | 1117 | |
969 | foreach my $map_address (@$obj) { | 1118 | return ""; |
970 | if (($map_address eq $address) && | 1119 | } |
971 | ($map_address ne $hash{$name})) { | 1120 | |
972 | $line = format_email($name, $hash{$name}, $email_usename); | 1121 | sub mailmap_email { |
973 | } | 1122 | my ($line) = @_; |
974 | } | 1123 | |
1124 | my ($name, $address) = parse_email($line); | ||
1125 | my $email = format_email($name, $address, 1); | ||
1126 | my $real_name = $name; | ||
1127 | my $real_address = $address; | ||
1128 | |||
1129 | if (exists $mailmap->{names}->{$email} || | ||
1130 | exists $mailmap->{addresses}->{$email}) { | ||
1131 | if (exists $mailmap->{names}->{$email}) { | ||
1132 | $real_name = $mailmap->{names}->{$email}; | ||
1133 | } | ||
1134 | if (exists $mailmap->{addresses}->{$email}) { | ||
1135 | $real_address = $mailmap->{addresses}->{$email}; | ||
1136 | } | ||
1137 | } else { | ||
1138 | if (exists $mailmap->{names}->{$address}) { | ||
1139 | $real_name = $mailmap->{names}->{$address}; | ||
1140 | } | ||
1141 | if (exists $mailmap->{addresses}->{$address}) { | ||
1142 | $real_address = $mailmap->{addresses}->{$address}; | ||
975 | } | 1143 | } |
976 | } | 1144 | } |
1145 | return format_email($real_name, $real_address, 1); | ||
1146 | } | ||
977 | 1147 | ||
978 | return @lines; | 1148 | sub mailmap { |
1149 | my (@addresses) = @_; | ||
1150 | |||
1151 | my @mapped_emails = (); | ||
1152 | foreach my $line (@addresses) { | ||
1153 | push(@mapped_emails, mailmap_email($line)); | ||
1154 | } | ||
1155 | merge_by_realname(@mapped_emails) if ($email_use_mailmap); | ||
1156 | return @mapped_emails; | ||
1157 | } | ||
1158 | |||
1159 | sub merge_by_realname { | ||
1160 | my %address_map; | ||
1161 | my (@emails) = @_; | ||
1162 | |||
1163 | foreach my $email (@emails) { | ||
1164 | my ($name, $address) = parse_email($email); | ||
1165 | if (exists $address_map{$name}) { | ||
1166 | $address = $address_map{$name}; | ||
1167 | $email = format_email($name, $address, 1); | ||
1168 | } else { | ||
1169 | $address_map{$name} = $address; | ||
1170 | } | ||
1171 | } | ||
979 | } | 1172 | } |
980 | 1173 | ||
981 | sub git_execute_cmd { | 1174 | sub git_execute_cmd { |
@@ -999,10 +1192,30 @@ sub hg_execute_cmd { | |||
999 | return @lines; | 1192 | return @lines; |
1000 | } | 1193 | } |
1001 | 1194 | ||
1195 | sub extract_formatted_signatures { | ||
1196 | my (@signature_lines) = @_; | ||
1197 | |||
1198 | my @type = @signature_lines; | ||
1199 | |||
1200 | s/\s*(.*):.*/$1/ for (@type); | ||
1201 | |||
1202 | # cut -f2- -d":" | ||
1203 | s/\s*.*:\s*(.+)\s*/$1/ for (@signature_lines); | ||
1204 | |||
1205 | ## Reformat email addresses (with names) to avoid badly written signatures | ||
1206 | |||
1207 | foreach my $signer (@signature_lines) { | ||
1208 | $signer = deduplicate_email($signer); | ||
1209 | } | ||
1210 | |||
1211 | return (\@type, \@signature_lines); | ||
1212 | } | ||
1213 | |||
1002 | sub vcs_find_signers { | 1214 | sub vcs_find_signers { |
1003 | my ($cmd) = @_; | 1215 | my ($cmd) = @_; |
1004 | my @lines = (); | ||
1005 | my $commits; | 1216 | my $commits; |
1217 | my @lines = (); | ||
1218 | my @signatures = (); | ||
1006 | 1219 | ||
1007 | @lines = &{$VCS_cmds{"execute_cmd"}}($cmd); | 1220 | @lines = &{$VCS_cmds{"execute_cmd"}}($cmd); |
1008 | 1221 | ||
@@ -1010,21 +1223,48 @@ sub vcs_find_signers { | |||
1010 | 1223 | ||
1011 | $commits = grep(/$pattern/, @lines); # of commits | 1224 | $commits = grep(/$pattern/, @lines); # of commits |
1012 | 1225 | ||
1013 | @lines = grep(/^[ \t]*${signaturePattern}.*\@.*$/, @lines); | 1226 | @signatures = grep(/^[ \t]*${signature_pattern}.*\@.*$/, @lines); |
1227 | |||
1228 | return (0, @signatures) if !@signatures; | ||
1229 | |||
1230 | save_commits_by_author(@lines) if ($interactive); | ||
1231 | save_commits_by_signer(@lines) if ($interactive); | ||
1232 | |||
1233 | if (!$email_git_penguin_chiefs) { | ||
1234 | @signatures = grep(!/${penguin_chiefs}/i, @signatures); | ||
1235 | } | ||
1236 | |||
1237 | my ($types_ref, $signers_ref) = extract_formatted_signatures(@signatures); | ||
1238 | |||
1239 | return ($commits, @$signers_ref); | ||
1240 | } | ||
1241 | |||
1242 | sub vcs_find_author { | ||
1243 | my ($cmd) = @_; | ||
1244 | my @lines = (); | ||
1245 | |||
1246 | @lines = &{$VCS_cmds{"execute_cmd"}}($cmd); | ||
1247 | |||
1014 | if (!$email_git_penguin_chiefs) { | 1248 | if (!$email_git_penguin_chiefs) { |
1015 | @lines = grep(!/${penguin_chiefs}/i, @lines); | 1249 | @lines = grep(!/${penguin_chiefs}/i, @lines); |
1016 | } | 1250 | } |
1017 | # cut -f2- -d":" | ||
1018 | s/.*:\s*(.+)\s*/$1/ for (@lines); | ||
1019 | 1251 | ||
1020 | ## Reformat email addresses (with names) to avoid badly written signatures | 1252 | return @lines if !@lines; |
1021 | 1253 | ||
1254 | my @authors = (); | ||
1022 | foreach my $line (@lines) { | 1255 | foreach my $line (@lines) { |
1023 | my ($name, $address) = parse_email($line); | 1256 | if ($line =~ m/$VCS_cmds{"author_pattern"}/) { |
1024 | $line = format_email($name, $address, 1); | 1257 | my $author = $1; |
1258 | my ($name, $address) = parse_email($author); | ||
1259 | $author = format_email($name, $address, 1); | ||
1260 | push(@authors, $author); | ||
1261 | } | ||
1025 | } | 1262 | } |
1026 | 1263 | ||
1027 | return ($commits, @lines); | 1264 | save_commits_by_author(@lines) if ($interactive); |
1265 | save_commits_by_signer(@lines) if ($interactive); | ||
1266 | |||
1267 | return @authors; | ||
1028 | } | 1268 | } |
1029 | 1269 | ||
1030 | sub vcs_save_commits { | 1270 | sub vcs_save_commits { |
@@ -1084,6 +1324,10 @@ sub vcs_blame { | |||
1084 | @commits = vcs_save_commits($cmd); | 1324 | @commits = vcs_save_commits($cmd); |
1085 | } | 1325 | } |
1086 | 1326 | ||
1327 | foreach my $commit (@commits) { | ||
1328 | $commit =~ s/^\^//g; | ||
1329 | } | ||
1330 | |||
1087 | return @commits; | 1331 | return @commits; |
1088 | } | 1332 | } |
1089 | 1333 | ||
@@ -1092,7 +1336,7 @@ sub vcs_exists { | |||
1092 | %VCS_cmds = %VCS_cmds_git; | 1336 | %VCS_cmds = %VCS_cmds_git; |
1093 | return 1 if eval $VCS_cmds{"available"}; | 1337 | return 1 if eval $VCS_cmds{"available"}; |
1094 | %VCS_cmds = %VCS_cmds_hg; | 1338 | %VCS_cmds = %VCS_cmds_hg; |
1095 | return 1 if eval $VCS_cmds{"available"}; | 1339 | return 2 if eval $VCS_cmds{"available"}; |
1096 | %VCS_cmds = (); | 1340 | %VCS_cmds = (); |
1097 | if (!$printed_novcs) { | 1341 | if (!$printed_novcs) { |
1098 | warn("$P: No supported VCS found. Add --nogit to options?\n"); | 1342 | warn("$P: No supported VCS found. Add --nogit to options?\n"); |
@@ -1104,6 +1348,405 @@ sub vcs_exists { | |||
1104 | return 0; | 1348 | return 0; |
1105 | } | 1349 | } |
1106 | 1350 | ||
1351 | sub vcs_is_git { | ||
1352 | vcs_exists(); | ||
1353 | return $vcs_used == 1; | ||
1354 | } | ||
1355 | |||
1356 | sub vcs_is_hg { | ||
1357 | return $vcs_used == 2; | ||
1358 | } | ||
1359 | |||
1360 | sub interactive_get_maintainers { | ||
1361 | my ($list_ref) = @_; | ||
1362 | my @list = @$list_ref; | ||
1363 | |||
1364 | vcs_exists(); | ||
1365 | |||
1366 | my %selected; | ||
1367 | my %authored; | ||
1368 | my %signed; | ||
1369 | my $count = 0; | ||
1370 | my $maintained = 0; | ||
1371 | foreach my $entry (@list) { | ||
1372 | $maintained = 1 if ($entry->[1] =~ /^(maintainer|supporter)/i); | ||
1373 | $selected{$count} = 1; | ||
1374 | $authored{$count} = 0; | ||
1375 | $signed{$count} = 0; | ||
1376 | $count++; | ||
1377 | } | ||
1378 | |||
1379 | #menu loop | ||
1380 | my $done = 0; | ||
1381 | my $print_options = 0; | ||
1382 | my $redraw = 1; | ||
1383 | while (!$done) { | ||
1384 | $count = 0; | ||
1385 | if ($redraw) { | ||
1386 | printf STDERR "\n%1s %2s %-65s", | ||
1387 | "*", "#", "email/list and role:stats"; | ||
1388 | if ($email_git || | ||
1389 | ($email_git_fallback && !$maintained) || | ||
1390 | $email_git_blame) { | ||
1391 | print STDERR "auth sign"; | ||
1392 | } | ||
1393 | print STDERR "\n"; | ||
1394 | foreach my $entry (@list) { | ||
1395 | my $email = $entry->[0]; | ||
1396 | my $role = $entry->[1]; | ||
1397 | my $sel = ""; | ||
1398 | $sel = "*" if ($selected{$count}); | ||
1399 | my $commit_author = $commit_author_hash{$email}; | ||
1400 | my $commit_signer = $commit_signer_hash{$email}; | ||
1401 | my $authored = 0; | ||
1402 | my $signed = 0; | ||
1403 | $authored++ for (@{$commit_author}); | ||
1404 | $signed++ for (@{$commit_signer}); | ||
1405 | printf STDERR "%1s %2d %-65s", $sel, $count + 1, $email; | ||
1406 | printf STDERR "%4d %4d", $authored, $signed | ||
1407 | if ($authored > 0 || $signed > 0); | ||
1408 | printf STDERR "\n %s\n", $role; | ||
1409 | if ($authored{$count}) { | ||
1410 | my $commit_author = $commit_author_hash{$email}; | ||
1411 | foreach my $ref (@{$commit_author}) { | ||
1412 | print STDERR " Author: @{$ref}[1]\n"; | ||
1413 | } | ||
1414 | } | ||
1415 | if ($signed{$count}) { | ||
1416 | my $commit_signer = $commit_signer_hash{$email}; | ||
1417 | foreach my $ref (@{$commit_signer}) { | ||
1418 | print STDERR " @{$ref}[2]: @{$ref}[1]\n"; | ||
1419 | } | ||
1420 | } | ||
1421 | |||
1422 | $count++; | ||
1423 | } | ||
1424 | } | ||
1425 | my $date_ref = \$email_git_since; | ||
1426 | $date_ref = \$email_hg_since if (vcs_is_hg()); | ||
1427 | if ($print_options) { | ||
1428 | $print_options = 0; | ||
1429 | if (vcs_exists()) { | ||
1430 | print STDERR <<EOT | ||
1431 | |||
1432 | Version Control options: | ||
1433 | g use git history [$email_git] | ||
1434 | gf use git-fallback [$email_git_fallback] | ||
1435 | b use git blame [$email_git_blame] | ||
1436 | bs use blame signatures [$email_git_blame_signatures] | ||
1437 | c# minimum commits [$email_git_min_signatures] | ||
1438 | %# min percent [$email_git_min_percent] | ||
1439 | d# history to use [$$date_ref] | ||
1440 | x# max maintainers [$email_git_max_maintainers] | ||
1441 | t all signature types [$email_git_all_signature_types] | ||
1442 | m use .mailmap [$email_use_mailmap] | ||
1443 | EOT | ||
1444 | } | ||
1445 | print STDERR <<EOT | ||
1446 | |||
1447 | Additional options: | ||
1448 | 0 toggle all | ||
1449 | tm toggle maintainers | ||
1450 | tg toggle git entries | ||
1451 | tl toggle open list entries | ||
1452 | ts toggle subscriber list entries | ||
1453 | f emails in file [$file_emails] | ||
1454 | k keywords in file [$keywords] | ||
1455 | r remove duplicates [$email_remove_duplicates] | ||
1456 | p# pattern match depth [$pattern_depth] | ||
1457 | EOT | ||
1458 | } | ||
1459 | print STDERR | ||
1460 | "\n#(toggle), A#(author), S#(signed) *(all), ^(none), O(options), Y(approve): "; | ||
1461 | |||
1462 | my $input = <STDIN>; | ||
1463 | chomp($input); | ||
1464 | |||
1465 | $redraw = 1; | ||
1466 | my $rerun = 0; | ||
1467 | my @wish = split(/[, ]+/, $input); | ||
1468 | foreach my $nr (@wish) { | ||
1469 | $nr = lc($nr); | ||
1470 | my $sel = substr($nr, 0, 1); | ||
1471 | my $str = substr($nr, 1); | ||
1472 | my $val = 0; | ||
1473 | $val = $1 if $str =~ /^(\d+)$/; | ||
1474 | |||
1475 | if ($sel eq "y") { | ||
1476 | $interactive = 0; | ||
1477 | $done = 1; | ||
1478 | $output_rolestats = 0; | ||
1479 | $output_roles = 0; | ||
1480 | last; | ||
1481 | } elsif ($nr =~ /^\d+$/ && $nr > 0 && $nr <= $count) { | ||
1482 | $selected{$nr - 1} = !$selected{$nr - 1}; | ||
1483 | } elsif ($sel eq "*" || $sel eq '^') { | ||
1484 | my $toggle = 0; | ||
1485 | $toggle = 1 if ($sel eq '*'); | ||
1486 | for (my $i = 0; $i < $count; $i++) { | ||
1487 | $selected{$i} = $toggle; | ||
1488 | } | ||
1489 | } elsif ($sel eq "0") { | ||
1490 | for (my $i = 0; $i < $count; $i++) { | ||
1491 | $selected{$i} = !$selected{$i}; | ||
1492 | } | ||
1493 | } elsif ($sel eq "t") { | ||
1494 | if (lc($str) eq "m") { | ||
1495 | for (my $i = 0; $i < $count; $i++) { | ||
1496 | $selected{$i} = !$selected{$i} | ||
1497 | if ($list[$i]->[1] =~ /^(maintainer|supporter)/i); | ||
1498 | } | ||
1499 | } elsif (lc($str) eq "g") { | ||
1500 | for (my $i = 0; $i < $count; $i++) { | ||
1501 | $selected{$i} = !$selected{$i} | ||
1502 | if ($list[$i]->[1] =~ /^(author|commit|signer)/i); | ||
1503 | } | ||
1504 | } elsif (lc($str) eq "l") { | ||
1505 | for (my $i = 0; $i < $count; $i++) { | ||
1506 | $selected{$i} = !$selected{$i} | ||
1507 | if ($list[$i]->[1] =~ /^(open list)/i); | ||
1508 | } | ||
1509 | } elsif (lc($str) eq "s") { | ||
1510 | for (my $i = 0; $i < $count; $i++) { | ||
1511 | $selected{$i} = !$selected{$i} | ||
1512 | if ($list[$i]->[1] =~ /^(subscriber list)/i); | ||
1513 | } | ||
1514 | } | ||
1515 | } elsif ($sel eq "a") { | ||
1516 | if ($val > 0 && $val <= $count) { | ||
1517 | $authored{$val - 1} = !$authored{$val - 1}; | ||
1518 | } elsif ($str eq '*' || $str eq '^') { | ||
1519 | my $toggle = 0; | ||
1520 | $toggle = 1 if ($str eq '*'); | ||
1521 | for (my $i = 0; $i < $count; $i++) { | ||
1522 | $authored{$i} = $toggle; | ||
1523 | } | ||
1524 | } | ||
1525 | } elsif ($sel eq "s") { | ||
1526 | if ($val > 0 && $val <= $count) { | ||
1527 | $signed{$val - 1} = !$signed{$val - 1}; | ||
1528 | } elsif ($str eq '*' || $str eq '^') { | ||
1529 | my $toggle = 0; | ||
1530 | $toggle = 1 if ($str eq '*'); | ||
1531 | for (my $i = 0; $i < $count; $i++) { | ||
1532 | $signed{$i} = $toggle; | ||
1533 | } | ||
1534 | } | ||
1535 | } elsif ($sel eq "o") { | ||
1536 | $print_options = 1; | ||
1537 | $redraw = 1; | ||
1538 | } elsif ($sel eq "g") { | ||
1539 | if ($str eq "f") { | ||
1540 | bool_invert(\$email_git_fallback); | ||
1541 | } else { | ||
1542 | bool_invert(\$email_git); | ||
1543 | } | ||
1544 | $rerun = 1; | ||
1545 | } elsif ($sel eq "b") { | ||
1546 | if ($str eq "s") { | ||
1547 | bool_invert(\$email_git_blame_signatures); | ||
1548 | } else { | ||
1549 | bool_invert(\$email_git_blame); | ||
1550 | } | ||
1551 | $rerun = 1; | ||
1552 | } elsif ($sel eq "c") { | ||
1553 | if ($val > 0) { | ||
1554 | $email_git_min_signatures = $val; | ||
1555 | $rerun = 1; | ||
1556 | } | ||
1557 | } elsif ($sel eq "x") { | ||
1558 | if ($val > 0) { | ||
1559 | $email_git_max_maintainers = $val; | ||
1560 | $rerun = 1; | ||
1561 | } | ||
1562 | } elsif ($sel eq "%") { | ||
1563 | if ($str ne "" && $val >= 0) { | ||
1564 | $email_git_min_percent = $val; | ||
1565 | $rerun = 1; | ||
1566 | } | ||
1567 | } elsif ($sel eq "d") { | ||
1568 | if (vcs_is_git()) { | ||
1569 | $email_git_since = $str; | ||
1570 | } elsif (vcs_is_hg()) { | ||
1571 | $email_hg_since = $str; | ||
1572 | } | ||
1573 | $rerun = 1; | ||
1574 | } elsif ($sel eq "t") { | ||
1575 | bool_invert(\$email_git_all_signature_types); | ||
1576 | $rerun = 1; | ||
1577 | } elsif ($sel eq "f") { | ||
1578 | bool_invert(\$file_emails); | ||
1579 | $rerun = 1; | ||
1580 | } elsif ($sel eq "r") { | ||
1581 | bool_invert(\$email_remove_duplicates); | ||
1582 | $rerun = 1; | ||
1583 | } elsif ($sel eq "m") { | ||
1584 | bool_invert(\$email_use_mailmap); | ||
1585 | read_mailmap(); | ||
1586 | $rerun = 1; | ||
1587 | } elsif ($sel eq "k") { | ||
1588 | bool_invert(\$keywords); | ||
1589 | $rerun = 1; | ||
1590 | } elsif ($sel eq "p") { | ||
1591 | if ($str ne "" && $val >= 0) { | ||
1592 | $pattern_depth = $val; | ||
1593 | $rerun = 1; | ||
1594 | } | ||
1595 | } elsif ($sel eq "h" || $sel eq "?") { | ||
1596 | print STDERR <<EOT | ||
1597 | |||
1598 | Interactive mode allows you to select the various maintainers, submitters, | ||
1599 | commit signers and mailing lists that could be CC'd on a patch. | ||
1600 | |||
1601 | Any *'d entry is selected. | ||
1602 | |||
1603 | If you have git or hg installed, you can choose to summarize the commit | ||
1604 | history of files in the patch. Also, each line of the current file can | ||
1605 | be matched to its commit author and that commits signers with blame. | ||
1606 | |||
1607 | Various knobs exist to control the length of time for active commit | ||
1608 | tracking, the maximum number of commit authors and signers to add, | ||
1609 | and such. | ||
1610 | |||
1611 | Enter selections at the prompt until you are satisfied that the selected | ||
1612 | maintainers are appropriate. You may enter multiple selections separated | ||
1613 | by either commas or spaces. | ||
1614 | |||
1615 | EOT | ||
1616 | } else { | ||
1617 | print STDERR "invalid option: '$nr'\n"; | ||
1618 | $redraw = 0; | ||
1619 | } | ||
1620 | } | ||
1621 | if ($rerun) { | ||
1622 | print STDERR "git-blame can be very slow, please have patience..." | ||
1623 | if ($email_git_blame); | ||
1624 | goto &get_maintainers; | ||
1625 | } | ||
1626 | } | ||
1627 | |||
1628 | #drop not selected entries | ||
1629 | $count = 0; | ||
1630 | my @new_emailto = (); | ||
1631 | foreach my $entry (@list) { | ||
1632 | if ($selected{$count}) { | ||
1633 | push(@new_emailto, $list[$count]); | ||
1634 | } | ||
1635 | $count++; | ||
1636 | } | ||
1637 | return @new_emailto; | ||
1638 | } | ||
1639 | |||
1640 | sub bool_invert { | ||
1641 | my ($bool_ref) = @_; | ||
1642 | |||
1643 | if ($$bool_ref) { | ||
1644 | $$bool_ref = 0; | ||
1645 | } else { | ||
1646 | $$bool_ref = 1; | ||
1647 | } | ||
1648 | } | ||
1649 | |||
1650 | sub deduplicate_email { | ||
1651 | my ($email) = @_; | ||
1652 | |||
1653 | my $matched = 0; | ||
1654 | my ($name, $address) = parse_email($email); | ||
1655 | $email = format_email($name, $address, 1); | ||
1656 | $email = mailmap_email($email); | ||
1657 | |||
1658 | return $email if (!$email_remove_duplicates); | ||
1659 | |||
1660 | ($name, $address) = parse_email($email); | ||
1661 | |||
1662 | if ($name ne "" && $deduplicate_name_hash{lc($name)}) { | ||
1663 | $name = $deduplicate_name_hash{lc($name)}->[0]; | ||
1664 | $address = $deduplicate_name_hash{lc($name)}->[1]; | ||
1665 | $matched = 1; | ||
1666 | } elsif ($deduplicate_address_hash{lc($address)}) { | ||
1667 | $name = $deduplicate_address_hash{lc($address)}->[0]; | ||
1668 | $address = $deduplicate_address_hash{lc($address)}->[1]; | ||
1669 | $matched = 1; | ||
1670 | } | ||
1671 | if (!$matched) { | ||
1672 | $deduplicate_name_hash{lc($name)} = [ $name, $address ]; | ||
1673 | $deduplicate_address_hash{lc($address)} = [ $name, $address ]; | ||
1674 | } | ||
1675 | $email = format_email($name, $address, 1); | ||
1676 | $email = mailmap_email($email); | ||
1677 | return $email; | ||
1678 | } | ||
1679 | |||
1680 | sub save_commits_by_author { | ||
1681 | my (@lines) = @_; | ||
1682 | |||
1683 | my @authors = (); | ||
1684 | my @commits = (); | ||
1685 | my @subjects = (); | ||
1686 | |||
1687 | foreach my $line (@lines) { | ||
1688 | if ($line =~ m/$VCS_cmds{"author_pattern"}/) { | ||
1689 | my $author = $1; | ||
1690 | $author = deduplicate_email($author); | ||
1691 | push(@authors, $author); | ||
1692 | } | ||
1693 | push(@commits, $1) if ($line =~ m/$VCS_cmds{"commit_pattern"}/); | ||
1694 | push(@subjects, $1) if ($line =~ m/$VCS_cmds{"subject_pattern"}/); | ||
1695 | } | ||
1696 | |||
1697 | for (my $i = 0; $i < @authors; $i++) { | ||
1698 | my $exists = 0; | ||
1699 | foreach my $ref(@{$commit_author_hash{$authors[$i]}}) { | ||
1700 | if (@{$ref}[0] eq $commits[$i] && | ||
1701 | @{$ref}[1] eq $subjects[$i]) { | ||
1702 | $exists = 1; | ||
1703 | last; | ||
1704 | } | ||
1705 | } | ||
1706 | if (!$exists) { | ||
1707 | push(@{$commit_author_hash{$authors[$i]}}, | ||
1708 | [ ($commits[$i], $subjects[$i]) ]); | ||
1709 | } | ||
1710 | } | ||
1711 | } | ||
1712 | |||
1713 | sub save_commits_by_signer { | ||
1714 | my (@lines) = @_; | ||
1715 | |||
1716 | my $commit = ""; | ||
1717 | my $subject = ""; | ||
1718 | |||
1719 | foreach my $line (@lines) { | ||
1720 | $commit = $1 if ($line =~ m/$VCS_cmds{"commit_pattern"}/); | ||
1721 | $subject = $1 if ($line =~ m/$VCS_cmds{"subject_pattern"}/); | ||
1722 | if ($line =~ /^[ \t]*${signature_pattern}.*\@.*$/) { | ||
1723 | my @signatures = ($line); | ||
1724 | my ($types_ref, $signers_ref) = extract_formatted_signatures(@signatures); | ||
1725 | my @types = @$types_ref; | ||
1726 | my @signers = @$signers_ref; | ||
1727 | |||
1728 | my $type = $types[0]; | ||
1729 | my $signer = $signers[0]; | ||
1730 | |||
1731 | $signer = deduplicate_email($signer); | ||
1732 | |||
1733 | my $exists = 0; | ||
1734 | foreach my $ref(@{$commit_signer_hash{$signer}}) { | ||
1735 | if (@{$ref}[0] eq $commit && | ||
1736 | @{$ref}[1] eq $subject && | ||
1737 | @{$ref}[2] eq $type) { | ||
1738 | $exists = 1; | ||
1739 | last; | ||
1740 | } | ||
1741 | } | ||
1742 | if (!$exists) { | ||
1743 | push(@{$commit_signer_hash{$signer}}, | ||
1744 | [ ($commit, $subject, $type) ]); | ||
1745 | } | ||
1746 | } | ||
1747 | } | ||
1748 | } | ||
1749 | |||
1107 | sub vcs_assign { | 1750 | sub vcs_assign { |
1108 | my ($role, $divisor, @lines) = @_; | 1751 | my ($role, $divisor, @lines) = @_; |
1109 | 1752 | ||
@@ -1117,9 +1760,9 @@ sub vcs_assign { | |||
1117 | $divisor = 1; | 1760 | $divisor = 1; |
1118 | } | 1761 | } |
1119 | 1762 | ||
1120 | if ($email_remove_duplicates) { | 1763 | @lines = mailmap(@lines); |
1121 | @lines = mailmap(@lines); | 1764 | |
1122 | } | 1765 | return if (@lines <= 0); |
1123 | 1766 | ||
1124 | @lines = sort(@lines); | 1767 | @lines = sort(@lines); |
1125 | 1768 | ||
@@ -1152,12 +1795,18 @@ sub vcs_file_signoffs { | |||
1152 | my @signers = (); | 1795 | my @signers = (); |
1153 | my $commits; | 1796 | my $commits; |
1154 | 1797 | ||
1155 | return if (!vcs_exists()); | 1798 | $vcs_used = vcs_exists(); |
1799 | return if (!$vcs_used); | ||
1156 | 1800 | ||
1157 | my $cmd = $VCS_cmds{"find_signers_cmd"}; | 1801 | my $cmd = $VCS_cmds{"find_signers_cmd"}; |
1158 | $cmd =~ s/(\$\w+)/$1/eeg; # interpolate $cmd | 1802 | $cmd =~ s/(\$\w+)/$1/eeg; # interpolate $cmd |
1159 | 1803 | ||
1160 | ($commits, @signers) = vcs_find_signers($cmd); | 1804 | ($commits, @signers) = vcs_find_signers($cmd); |
1805 | |||
1806 | foreach my $signer (@signers) { | ||
1807 | $signer = deduplicate_email($signer); | ||
1808 | } | ||
1809 | |||
1161 | vcs_assign("commit_signer", $commits, @signers); | 1810 | vcs_assign("commit_signer", $commits, @signers); |
1162 | } | 1811 | } |
1163 | 1812 | ||
@@ -1165,29 +1814,114 @@ sub vcs_file_blame { | |||
1165 | my ($file) = @_; | 1814 | my ($file) = @_; |
1166 | 1815 | ||
1167 | my @signers = (); | 1816 | my @signers = (); |
1817 | my @all_commits = (); | ||
1168 | my @commits = (); | 1818 | my @commits = (); |
1169 | my $total_commits; | 1819 | my $total_commits; |
1820 | my $total_lines; | ||
1170 | 1821 | ||
1171 | return if (!vcs_exists()); | 1822 | $vcs_used = vcs_exists(); |
1823 | return if (!$vcs_used); | ||
1172 | 1824 | ||
1173 | @commits = vcs_blame($file); | 1825 | @all_commits = vcs_blame($file); |
1174 | @commits = uniq(@commits); | 1826 | @commits = uniq(@all_commits); |
1175 | $total_commits = @commits; | 1827 | $total_commits = @commits; |
1828 | $total_lines = @all_commits; | ||
1176 | 1829 | ||
1177 | foreach my $commit (@commits) { | 1830 | if ($email_git_blame_signatures) { |
1178 | my $commit_count; | 1831 | if (vcs_is_hg()) { |
1179 | my @commit_signers = (); | 1832 | my $commit_count; |
1833 | my @commit_signers = (); | ||
1834 | my $commit = join(" -r ", @commits); | ||
1835 | my $cmd; | ||
1836 | |||
1837 | $cmd = $VCS_cmds{"find_commit_signers_cmd"}; | ||
1838 | $cmd =~ s/(\$\w+)/$1/eeg; #substitute variables in $cmd | ||
1839 | |||
1840 | ($commit_count, @commit_signers) = vcs_find_signers($cmd); | ||
1841 | |||
1842 | push(@signers, @commit_signers); | ||
1843 | } else { | ||
1844 | foreach my $commit (@commits) { | ||
1845 | my $commit_count; | ||
1846 | my @commit_signers = (); | ||
1847 | my $cmd; | ||
1180 | 1848 | ||
1181 | my $cmd = $VCS_cmds{"find_commit_signers_cmd"}; | 1849 | $cmd = $VCS_cmds{"find_commit_signers_cmd"}; |
1182 | $cmd =~ s/(\$\w+)/$1/eeg; #interpolate $cmd | 1850 | $cmd =~ s/(\$\w+)/$1/eeg; #substitute variables in $cmd |
1183 | 1851 | ||
1184 | ($commit_count, @commit_signers) = vcs_find_signers($cmd); | 1852 | ($commit_count, @commit_signers) = vcs_find_signers($cmd); |
1185 | push(@signers, @commit_signers); | 1853 | |
1854 | push(@signers, @commit_signers); | ||
1855 | } | ||
1856 | } | ||
1186 | } | 1857 | } |
1187 | 1858 | ||
1188 | if ($from_filename) { | 1859 | if ($from_filename) { |
1860 | if ($output_rolestats) { | ||
1861 | my @blame_signers; | ||
1862 | if (vcs_is_hg()) {{ # Double brace for last exit | ||
1863 | my $commit_count; | ||
1864 | my @commit_signers = (); | ||
1865 | @commits = uniq(@commits); | ||
1866 | @commits = sort(@commits); | ||
1867 | my $commit = join(" -r ", @commits); | ||
1868 | my $cmd; | ||
1869 | |||
1870 | $cmd = $VCS_cmds{"find_commit_author_cmd"}; | ||
1871 | $cmd =~ s/(\$\w+)/$1/eeg; #substitute variables in $cmd | ||
1872 | |||
1873 | my @lines = (); | ||
1874 | |||
1875 | @lines = &{$VCS_cmds{"execute_cmd"}}($cmd); | ||
1876 | |||
1877 | if (!$email_git_penguin_chiefs) { | ||
1878 | @lines = grep(!/${penguin_chiefs}/i, @lines); | ||
1879 | } | ||
1880 | |||
1881 | last if !@lines; | ||
1882 | |||
1883 | my @authors = (); | ||
1884 | foreach my $line (@lines) { | ||
1885 | if ($line =~ m/$VCS_cmds{"author_pattern"}/) { | ||
1886 | my $author = $1; | ||
1887 | $author = deduplicate_email($author); | ||
1888 | push(@authors, $author); | ||
1889 | } | ||
1890 | } | ||
1891 | |||
1892 | save_commits_by_author(@lines) if ($interactive); | ||
1893 | save_commits_by_signer(@lines) if ($interactive); | ||
1894 | |||
1895 | push(@signers, @authors); | ||
1896 | }} | ||
1897 | else { | ||
1898 | foreach my $commit (@commits) { | ||
1899 | my $i; | ||
1900 | my $cmd = $VCS_cmds{"find_commit_author_cmd"}; | ||
1901 | $cmd =~ s/(\$\w+)/$1/eeg; #interpolate $cmd | ||
1902 | my @author = vcs_find_author($cmd); | ||
1903 | next if !@author; | ||
1904 | |||
1905 | my $formatted_author = deduplicate_email($author[0]); | ||
1906 | |||
1907 | my $count = grep(/$commit/, @all_commits); | ||
1908 | for ($i = 0; $i < $count ; $i++) { | ||
1909 | push(@blame_signers, $formatted_author); | ||
1910 | } | ||
1911 | } | ||
1912 | } | ||
1913 | if (@blame_signers) { | ||
1914 | vcs_assign("authored lines", $total_lines, @blame_signers); | ||
1915 | } | ||
1916 | } | ||
1917 | foreach my $signer (@signers) { | ||
1918 | $signer = deduplicate_email($signer); | ||
1919 | } | ||
1189 | vcs_assign("commits", $total_commits, @signers); | 1920 | vcs_assign("commits", $total_commits, @signers); |
1190 | } else { | 1921 | } else { |
1922 | foreach my $signer (@signers) { | ||
1923 | $signer = deduplicate_email($signer); | ||
1924 | } | ||
1191 | vcs_assign("modified commits", $total_commits, @signers); | 1925 | vcs_assign("modified commits", $total_commits, @signers); |
1192 | } | 1926 | } |
1193 | } | 1927 | } |